Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
IZoneLayoutRegistry.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6// IZoneLayoutRegistry - enumeration + mutation of the catalog of
7// manual zone layouts.
8//
9// Split out of ILayoutManager so callers that need the layout set
10// (editor save path, layout-import flow, settings create-layout
11// button, read-only preview renderers) can depend on one contract
12// instead of the full manager. "Active layout" selection lives here
13// because it mutates the manager's active-layout slot.
14//
15// Inherits PhosphorLayout::ILayoutSourceRegistry so concrete registries
16// (LayoutManager) carry the unified `contentsChanged` signal that
17// ZonesLayoutSource subscribes to - matching the pattern every other
18// provider library (phosphor-tiles, phosphor-scroll-engine, …)
19// follows. Inheriting QObject via the unified base rather than
20// directly keeps ILayoutManager's non-virtual multi-inheritance safe:
21// every path through ILayoutManager reaches QObject exactly once, so
22// LayoutManager has a single QObject subobject.
23
24#include <phosphorzones_export.h>
25
31
32#include <QJsonObject>
33#include <QString>
34#include <QUuid>
35#include <QVector>
36
37#include <optional>
38
39namespace PhosphorZones {
40
41class ScrollingTemplateStore;
42
51{
52 Q_OBJECT
53
54 // Live in the interface so QML-bound consumers can target the contract
55 // without depending on the concrete @ref LayoutRegistry. moc's NOTIFY
56 // check resolves the signal in the same class scope it sees the READ
57 // method, so the property + the signal must travel together.
58 Q_PROPERTY(Layout* activeLayout READ activeLayout NOTIFY activeLayoutChanged)
59
60public:
61 explicit IZoneLayoutRegistry(QObject* parent = nullptr);
63
67 virtual QVector<Layout*> layouts() const = 0;
68
69 virtual int layoutCount() const = 0;
70 virtual Layout* layout(int index) const = 0;
71 virtual Layout* layoutByName(const QString& name) const = 0;
72
75 virtual Layout* layoutById(const QUuid& id) const = 0;
76
79 virtual void addLayout(Layout* layout) = 0;
92 virtual bool removeLayout(Layout* layout) = 0;
95 virtual bool removeLayoutById(const QUuid& id) = 0;
100 virtual Layout* duplicateLayout(Layout* source) = 0;
101
102 // Active layout (internal - used for resnap / geometry / overlay
103 // machinery). Borrowed pointer owned by the registry.
104 virtual Layout* activeLayout() const = 0;
105 virtual void setActiveLayout(Layout* layout) = 0;
106 virtual void setActiveLayoutById(const QUuid& id) = 0;
107
108 // ─── Per-screen layout resolution (cascade-aware) ─────────────────────
109 //
110 // These queries resolve a layout for a (screen, desktop, activity)
111 // context by walking the assignment cascade and falling back to the
112 // global default. Overlay/geometry/animation consumers depend on this
113 // shape, so it lives on the interface - callers can target the
114 // contract without depending on the concrete @c LayoutRegistry.
115
118 virtual Layout* layoutForScreen(const QString& screenId, int virtualDesktop = 0,
119 const QString& activity = QString()) const = 0;
120
123 virtual Layout* resolveLayoutForScreen(const QString& screenId) const = 0;
124
130 virtual QString assignmentIdForScreen(const QString& screenId, int virtualDesktop = 0,
131 const QString& activity = QString()) const = 0;
132
138 {
139 return nullptr;
140 }
141
148 virtual ScrollingTemplate scrollingTemplateForContext(const QString& screenId, int virtualDesktop,
149 const QString& activity) const
150 {
151 Q_UNUSED(screenId)
152 Q_UNUSED(virtualDesktop)
153 Q_UNUSED(activity)
154 return {};
155 }
156
157 // scrollingTemplateExplicitlyNone, the other half of the pair the next
158 // function reads, is declared at the END of the virtuals (see its own doc
159 // there for both what it answers and why it sits last).
160
171 QString scrollingDisplayIdForContext(const QString& screenId, int virtualDesktop, const QString& activity) const
172 {
173 const ScrollingTemplate templ = scrollingTemplateForContext(screenId, virtualDesktop, activity);
174 if (templ.isValid()) {
175 return templ.id.toString();
176 }
177 // Tested only once the resolver has come back empty: a context cannot
178 // both name a template and be opted out. That ordering costs a second
179 // resolve on a screen with no template and no configured default,
180 // which is not rare — the memoized context cache makes it a lookup
181 // rather than a second priority walk.
182 if (scrollingTemplateExplicitlyNone(screenId, virtualDesktop, activity)) {
183 return QString(NoScrollingTemplate);
184 }
186 }
187
189 virtual Layout* defaultLayout() const = 0;
190
191 // ─── Session context (current desktop / activity) ─────────────────────
192 //
193 // The registry holds session-context state because per-context
194 // assignment resolution needs it. Consumers that drive context-aware
195 // queries (overlay re-layout on desktop switch, autotile re-run on
196 // activity change) read it through the interface.
197
198 virtual int currentVirtualDesktop() const = 0;
202 virtual int currentVirtualDesktopForScreen(const QString& screenId) const
203 {
204 Q_UNUSED(screenId)
205 return currentVirtualDesktop();
206 }
207 virtual QString currentActivity() const = 0;
208
214 virtual QJsonObject loadAutotileOverrides(const QString& algorithmId) const
215 {
216 Q_UNUSED(algorithmId)
217 return {};
218 }
219
226 virtual QString tilingAlgorithmForScreen(const QString& screenId, int virtualDesktop = 0,
227 const QString& activity = QString()) const
228 {
229 Q_UNUSED(screenId)
230 Q_UNUSED(virtualDesktop)
231 Q_UNUSED(activity)
232 return {};
233 }
234
253 virtual ContextGapOverride resolveContextGaps(const QString& screenId, int virtualDesktop, const QString& activity,
254 const QString& mode = QString()) const
255 {
256 Q_UNUSED(screenId);
257 Q_UNUSED(virtualDesktop);
258 Q_UNUSED(activity);
259 Q_UNUSED(mode);
260 return {};
261 }
262
272 virtual bool resolveContextLocked(const QString& screenId, int virtualDesktop, const QString& activity) const
273 {
274 Q_UNUSED(screenId);
275 Q_UNUSED(virtualDesktop);
276 Q_UNUSED(activity);
277 return false;
278 }
279
288 virtual std::optional<bool> resolveContextDragSelectorEnabled(const QString& screenId, int virtualDesktop,
289 const QString& activity) const
290 {
291 Q_UNUSED(screenId);
292 Q_UNUSED(virtualDesktop);
293 Q_UNUSED(activity);
294 return std::nullopt;
295 }
296
304 virtual bool isContextActiveLayoutSuppressed(const QString& screenId, int virtualDesktop,
305 const QString& activity) const
306 {
307 Q_UNUSED(screenId);
308 Q_UNUSED(virtualDesktop);
309 Q_UNUSED(activity);
310 return false;
311 }
312
321 virtual ContextOverlayOverride resolveContextOverlay(const QString& screenId, int virtualDesktop,
322 const QString& activity) const
323 {
324 Q_UNUSED(screenId);
325 Q_UNUSED(virtualDesktop);
326 Q_UNUSED(activity);
327 return {};
328 }
329
350 virtual bool scrollingTemplateExplicitlyNone(const QString& screenId, int virtualDesktop,
351 const QString& activity) const
352 {
353 Q_UNUSED(screenId)
354 Q_UNUSED(virtualDesktop)
355 Q_UNUSED(activity)
356 return false;
357 }
358
359Q_SIGNALS:
360 // Catalog mutation. @c addLayout / @c duplicateLayout fire `layoutAdded`;
361 // @c removeLayout / @c removeLayoutById fire `layoutRemoved` on success;
362 // a refused removal (see their @return) fires nothing.
363 void layoutAdded(Layout* layout);
364 void layoutRemoved(Layout* layout);
365
366 // Active-layout selection. Fires from @c setActiveLayout /
367 // @c setActiveLayoutById only when the active-layout pointer actually
368 // changes (concrete implementer guards with an equality check -
369 // matches the project rule "only emit signals when value actually
370 // changes").
372
373 // Assignment churn. Fires when a (screenId, virtualDesktop) assignment
374 // is WRITTEN; activity context is intentionally omitted from the signal -
375 // consumers that care about activity-keyed assignments re-query via
376 // @c layoutForScreen with their current activity. Deliberately NOT an
377 // emit-on-change signal: the emitters fire unconditionally on every
378 // assignment write, because consumers use it as a re-derive trigger
379 // (engine screen sets, layout filters, template vocabulary pushes) whose
380 // inputs go beyond the (screen, desktop, layout) payload - an identical
381 // payload can still mean a changed template or activity-keyed entry.
382 void layoutAssigned(const QString& screenId, int virtualDesktop, Layout* layout);
383};
384
385} // namespace PhosphorZones
Abstract notifier surface for every registry that feeds an ILayoutSource.
Definition ILayoutSourceRegistry.h:37
Enumeration + mutation surface for the in-memory zone-layout catalog.
Definition IZoneLayoutRegistry.h:51
virtual Layout * layout(int index) const =0
virtual Layout * layoutById(const QUuid &id) const =0
Resolve a layout by its stable UUID.
void layoutRemoved(Layout *layout)
virtual Layout * layoutForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const =0
Cascade-resolve the manual layout for screenId.
virtual QString assignmentIdForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const =0
Raw assignment id (manual-layout UUID, "autotile:<algorithmId>", or the bare "scrolling:" sentinel) f...
virtual bool isContextActiveLayoutSuppressed(const QString &screenId, int virtualDesktop, const QString &activity) const
True iff the (screenId, virtualDesktop, activity) context has no active layout specifically because t...
Definition IZoneLayoutRegistry.h:304
virtual int currentVirtualDesktopForScreen(const QString &screenId) const
This screen's current virtual desktop (Plasma 6.7 per-output virtual desktops, #648).
Definition IZoneLayoutRegistry.h:202
void layoutAdded(Layout *layout)
virtual bool removeLayout(Layout *layout)=0
virtual std::optional< bool > resolveContextDragSelectorEnabled(const QString &screenId, int virtualDesktop, const QString &activity) const
Resolve a per-context override of the drag selector popup — the edge-triggered zone / strip picker of...
Definition IZoneLayoutRegistry.h:288
virtual Layout * activeLayout() const =0
virtual bool removeLayoutById(const QUuid &id)=0
virtual QVector< Layout * > layouts() const =0
Enumerate every known layout.
IZoneLayoutRegistry(QObject *parent=nullptr)
virtual bool resolveContextLocked(const QString &screenId, int virtualDesktop, const QString &activity) const
Resolve whether rules lock the active layout for the (screenId, virtualDesktop, activity) context — t...
Definition IZoneLayoutRegistry.h:272
virtual Layout * layoutByName(const QString &name) const =0
virtual Layout * defaultLayout() const =0
Effective global default layout (snap-only fallback).
virtual QString currentActivity() const =0
virtual void addLayout(Layout *layout)=0
virtual void setActiveLayoutById(const QUuid &id)=0
void activeLayoutChanged(Layout *layout)
virtual ScrollingTemplate scrollingTemplateForContext(const QString &screenId, int virtualDesktop, const QString &activity) const
The resolved scrolling TEMPLATE for a context (the native ScrollingTemplate whose vocabularies and bl...
Definition IZoneLayoutRegistry.h:148
QString scrollingDisplayIdForContext(const QString &screenId, int virtualDesktop, const QString &activity) const
The id the layout PICKER highlights for a scrolling context: the resolved template's bare UUID,...
Definition IZoneLayoutRegistry.h:171
virtual void setActiveLayout(Layout *layout)=0
virtual ScrollingTemplateStore * scrollingTemplateStore() const
The native scrolling-template store wired into this registry, or null when none is (lightweight stubs...
Definition IZoneLayoutRegistry.h:137
void layoutAssigned(const QString &screenId, int virtualDesktop, Layout *layout)
virtual Layout * resolveLayoutForScreen(const QString &screenId) const =0
Convenience: resolve a layout using the registry's current (desktop, activity) context.
virtual bool scrollingTemplateExplicitlyNone(const QString &screenId, int virtualDesktop, const QString &activity) const
Whether the context opted out of templates EXPLICITLY, as opposed to merely naming none (an unset slo...
Definition IZoneLayoutRegistry.h:350
virtual ContextOverlayOverride resolveContextOverlay(const QString &screenId, int virtualDesktop, const QString &activity) const
Resolve the per-context overlay-property override for the (screenId, virtualDesktop,...
Definition IZoneLayoutRegistry.h:321
virtual ContextGapOverride resolveContextGaps(const QString &screenId, int virtualDesktop, const QString &activity, const QString &mode=QString()) const
Resolve the per-context gap override (zone padding + outer gaps) that rules pin for the (screenId,...
Definition IZoneLayoutRegistry.h:253
virtual int currentVirtualDesktop() const =0
virtual Layout * duplicateLayout(Layout *source)=0
virtual QJsonObject loadAutotileOverrides(const QString &algorithmId) const
Per-algorithm autotile settings (gaps, shader, hiddenFromSelector, …) stored in the unified layout-se...
Definition IZoneLayoutRegistry.h:214
virtual QString tilingAlgorithmForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
Raw id of the tiling algorithm active for the (screenId, virtualDesktop, activity) context,...
Definition IZoneLayoutRegistry.h:226
virtual int layoutCount() const =0
Represents a collection of zones that form a layout.
Definition Layout.h:42
Load/save store for scrolling templates.
Definition ScrollingTemplateStore.h:37
A scrolling screen's first-class sizing template.
Definition ScrollingTemplate.h:128
QUuid id
Definition ScrollingTemplate.h:130
bool isValid() const
Definition ScrollingTemplate.h:167
constexpr QLatin1String ScrollingId
Scrolling has no layout entity, so its whole id is the bare sentinel — it exists so a mode-only Scrol...
Definition LayoutId.h:37
Definition IWindowTrackingService.h:23
constexpr QLatin1String NoScrollingTemplate
Reserved value of AssignmentEntry::scrollingTemplateLayout meaning "this context explicitly uses NO s...
Definition AssignmentEntry.h:132
Per-context gap override resolved from rules.
Definition AssignmentEntry.h:362
Per-context overlay-property overrides resolved from window-rule actions.
Definition AssignmentEntry.h:400