Manual zone-layout registry + per-context assignment store. More...
#include <phosphor-zones/include/PhosphorZones/LayoutRegistry.h>
Signals | |
| void | layoutsChanged () |
| void | layoutDirectoryChanged () |
| void | layoutsLoaded () |
| void | layoutsSaved () |
Signals inherited from PhosphorZones::IZoneLayoutRegistry | |
| void | layoutAdded (Layout *layout) |
| void | layoutRemoved (Layout *layout) |
| void | activeLayoutChanged (Layout *layout) |
| void | layoutAssigned (const QString &screenId, int virtualDesktop, Layout *layout) |
Signals inherited from PhosphorLayout::ILayoutSourceRegistry | |
| void | contentsChanged () |
| Emitted when the set of layouts this registry produces changes in any way that invalidates cached previews — entries added, removed, renamed, or re-parameterised. | |
Public Member Functions | |
| LayoutRegistry (std::unique_ptr< PhosphorConfig::IBackend > backend, QString layoutSubdirectory, QObject *parent=nullptr) | |
| ~LayoutRegistry () override | |
| int | layoutCount () const override |
| QVector< Layout * > | layouts () const override |
| Enumerate every known layout. | |
| Layout * | layout (int index) const override |
| Layout * | layoutById (const QUuid &id) const override |
| Resolve a layout by its stable UUID. | |
| Layout * | layoutByName (const QString &name) const override |
| void | addLayout (Layout *layout) override |
| void | removeLayout (Layout *layout) override |
| void | removeLayoutById (const QUuid &id) override |
| Layout * | duplicateLayout (Layout *source) override |
| Layout * | activeLayout () const override |
| void | setActiveLayout (Layout *layout) override |
| void | setActiveLayoutById (const QUuid &id) override |
| QString | layoutDirectory () const |
| void | setLayoutDirectory (const QString &directory) |
| void | loadLayouts () |
| void | saveLayouts () |
| void | saveLayout (Layout *layout) |
| void | importLayout (const QString &filePath) |
| void | exportLayout (Layout *layout, const QString &filePath) |
| void | loadAssignments () |
| void | saveAssignments () |
| Layout * | defaultLayout () const override |
| Resolve the effective default layout. | |
| void | setDefaultLayoutIdProvider (std::function< QString()> provider) |
| Inject a callback that returns the user-configured default layout id (or empty if unset). | |
| void | setDefaultAutotileAlgorithmProvider (std::function< QString()> provider) |
| Inject a callback that returns the user-configured default autotile algorithm id (or empty if autotile is not the user's active default). | |
| void | setSnappingPreferredProvider (std::function< bool()> provider) |
| Inject a callback that returns true when Snapping is the user's preferred default mode (regardless of whether a default snapping layout id is configured). | |
| Layout * | previousLayout () const |
| Get the previous active layout (before the most recent setActiveLayout). | |
| void | assignLayout (const QString &screenId, int virtualDesktop, const QString &activity, Layout *layout) |
| void | assignLayoutById (const QString &screenId, int virtualDesktop, const QString &activity, const QString &layoutId) |
| void | setAssignmentEntryDirect (const QString &screenId, int virtualDesktop, const QString &activity, const AssignmentEntry &entry) |
| Store a full entry directly (from KCM via D-Bus). | |
| void | setSnappingLayoutPreservingMode (const QString &screenId, int virtualDesktop, const QString &activity, const QString &layoutId) |
Update only the snappingLayout field for the (screenId, virtualDesktop, activity) entry, preserving mode and tilingAlgorithm. | |
| void | setTilingAlgorithmPreservingMode (const QString &screenId, int virtualDesktop, const QString &activity, const QString &algorithmId) |
Update only the tilingAlgorithm field, mirroring setSnappingLayoutPreservingMode for the tiling slot. | |
| void | setSnappingLayoutPromoting (const QString &screenId, int virtualDesktop, const QString &activity, const QString &layoutId) |
| "Promote" variant of setSnappingLayoutPreservingMode used when the user's current rendered context is already in Snapping mode — i.e. | |
| void | setTilingAlgorithmPromoting (const QString &screenId, int virtualDesktop, const QString &activity, const QString &algorithmId) |
Symmetric promoting variant for the tile field; forces mode=Autotile after wiping shadows. | |
| Layout * | layoutForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const override |
Cascade-resolve the manual layout for screenId. | |
| Layout * | resolveLayoutForScreen (const QString &screenId) const override |
Resolve layout for screenId using the current desktop/activity context. | |
| void | clearAssignment (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) |
| bool | hasExplicitAssignment (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const |
| QString | assignmentIdForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const override |
| Raw assignment id for a (screen, desktop, activity) context. | |
| AssignmentEntry | assignmentEntryForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const |
| Full entry for a (screen, desktop, activity) context. | |
| AssignmentEntry::Mode | modeForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const |
| QString | snappingLayoutForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const |
| Per-field cascade readers — return the named field from the first entry in the cascade where it is non-empty. | |
| QString | tilingAlgorithmForScreen (const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const |
| void | clearAutotileAssignments () |
Flip mode to Snapping for every entry currently in Autotile (preserves snappingLayout + tilingAlgorithm). | |
| void | setAllScreenAssignments (const QHash< QString, QString > &assignments) |
| Batch setters - clear existing, set new, save once at end. | |
| void | setAllDesktopAssignments (const QHash< QPair< QString, int >, QString > &assignments) |
| void | setAllActivityAssignments (const QHash< QPair< QString, QString >, QString > &assignments) |
| QHash< QPair< QString, int >, QString > | desktopAssignments () const |
| QHash< QPair< QString, QString >, QString > | activityAssignments () const |
| Layout * | layoutForShortcut (int number) const |
| void | applyQuickLayout (int number, const QString &screenId) |
| void | setQuickLayoutSlot (int number, const QString &layoutId) |
| void | setAllQuickLayoutSlots (const QHash< int, QString > &slots) |
| QHash< int, QString > | quickLayoutSlots () const |
| void | cycleToPreviousLayout (const QString &screenId) |
| void | cycleToNextLayout (const QString &screenId) |
| void | createBuiltInLayouts () |
| QVector< Layout * > | builtInLayouts () const |
| int | currentVirtualDesktop () const override |
| QString | currentActivity () const override |
| void | setCurrentVirtualDesktop (int desktop) |
| void | setCurrentActivity (const QString &activity) |
| void | saveAutotileOverrides (const QString &algorithmId, const QJsonObject &overrides) |
| QJsonObject | loadAutotileOverrides (const QString &algorithmId) const |
Public Member Functions inherited from PhosphorZones::IZoneLayoutRegistry | |
| IZoneLayoutRegistry (QObject *parent=nullptr) | |
| ~IZoneLayoutRegistry () override | |
Public Member Functions inherited from PhosphorLayout::ILayoutSourceRegistry | |
| ILayoutSourceRegistry (QObject *parent=nullptr) | |
| ~ILayoutSourceRegistry () override | |
Manual zone-layout registry + per-context assignment store.
Concrete counterpart to IZoneLayoutRegistry - mirrors the PhosphorTiles AlgorithmRegistry shape (interface for the provider contract, one concrete class for everything else). Composition roots construct one instance per process and inject it into every consumer; there is no process-global singleton.
Responsibilities:
Schema strings ("Assignment:", "QuickLayouts", "ModeTracking") are hardcoded lib-level constants inside layoutregistry_persistence.cpp. They ARE the wire format - third-party compositors that reuse this lib share them for free.
| PhosphorZones::LayoutRegistry::LayoutRegistry | ( | std::unique_ptr< PhosphorConfig::IBackend > | backend, |
| QString | layoutSubdirectory, | ||
| QObject * | parent = nullptr |
||
| ) |
| backend | Owned config-store backend (typically createAssignmentsBackend()). Required - asserted non-null; every persistence method dereferences it. |
| layoutSubdirectory | XDG-relative path used for layout JSON discovery (e.g. "plasmazones/layouts"). The registry writes to QStandardPaths::writableLocation(GenericDataLocation)/<subdir> and reads the union of every GenericDataLocation entry containing that subdirectory, so system copies (in /usr/share/ <subdir>) provide built-ins while the user-writable copy overrides them. Required - asserted non-empty. |
| parent | Qt parent. |
|
override |
|
inlineoverridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
| QHash< QPair< QString, QString >, QString > PhosphorZones::LayoutRegistry::activityAssignments | ( | ) | const |
|
overridevirtual |
| layout | Ownership transferred - the registry adopts layout and is responsible for its lifetime from this call on. |
Implements PhosphorZones::IZoneLayoutRegistry.
| void PhosphorZones::LayoutRegistry::applyQuickLayout | ( | int | number, |
| const QString & | screenId | ||
| ) |
| void PhosphorZones::LayoutRegistry::assignLayout | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| Layout * | layout | ||
| ) |
| void PhosphorZones::LayoutRegistry::assignLayoutById | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const QString & | layoutId | ||
| ) |
| AssignmentEntry PhosphorZones::LayoutRegistry::assignmentEntryForScreen | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) | const |
Full entry for a (screen, desktop, activity) context.
Shares the per-context cascade with layoutForScreen up through level-2 (per-screen base entry), but the two diverge at level-1 (global defaults): on cascade-miss this method synthesizes from BOTH providers - snap provider first, then autotile provider - using the same precedence as assignmentIdForScreen, while layoutForScreen consults only the snap provider via defaultLayout. This means a caller mixing both APIs may see entry.mode == Autotile with layoutForScreen returning a snap Layout* (the historical pre-368 fallback shape, preserved so the autotile engine's assignmentIdForScreen-driven activation path remains mode-aware while the snap engine's layoutForScreen-driven path stays Layout*-typed). Returns a default-constructed entry when neither provider returns a value. Callers that need raw stored state without the synth fallback must gate with hasExplicitAssignment.
|
overridevirtual |
Raw assignment id for a (screen, desktop, activity) context.
Returns the stored string (manual-layout UUID or "autotile:<algorithmId>") without resolving to a Layout*. On cascade-miss, falls through to the level-1 global defaults (snap provider first, then autotile provider; see setDefaultLayoutIdProvider / setDefaultAutotileAlgorithmProvider). Empty when every cascade level misses AND both providers return empty. Callers that need to distinguish "stored" from "synthesized fallback" must pair this with hasExplicitAssignment.
Implements PhosphorZones::IZoneLayoutRegistry.
| QVector< Layout * > PhosphorZones::LayoutRegistry::builtInLayouts | ( | ) | const |
| void PhosphorZones::LayoutRegistry::clearAssignment | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) |
| void PhosphorZones::LayoutRegistry::clearAutotileAssignments | ( | ) |
Flip mode to Snapping for every entry currently in Autotile (preserves snappingLayout + tilingAlgorithm).
Emits layoutAssigned per affected screen; one save at end.
| void PhosphorZones::LayoutRegistry::createBuiltInLayouts | ( | ) |
|
inlineoverridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
inlineoverridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
| void PhosphorZones::LayoutRegistry::cycleToNextLayout | ( | const QString & | screenId | ) |
| void PhosphorZones::LayoutRegistry::cycleToPreviousLayout | ( | const QString & | screenId | ) |
|
overridevirtual |
Resolve the effective default layout.
Returns, in order:
defaultOrder)."autotile:<algo>" id from the level-1 cascade. Implements PhosphorZones::IZoneLayoutRegistry.
| QHash< QPair< QString, int >, QString > PhosphorZones::LayoutRegistry::desktopAssignments | ( | ) | const |
| source | Borrowed - caller retains ownership. |
addLayout semantics). Returns nullptr if source is unknown. Implements PhosphorZones::IZoneLayoutRegistry.
| void PhosphorZones::LayoutRegistry::exportLayout | ( | Layout * | layout, |
| const QString & | filePath | ||
| ) |
| bool PhosphorZones::LayoutRegistry::hasExplicitAssignment | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) | const |
| void PhosphorZones::LayoutRegistry::importLayout | ( | const QString & | filePath | ) |
|
overridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
overridevirtual |
Resolve a layout by its stable UUID.
Returns nullptr when no layout with that id is known to the registry.
Implements PhosphorZones::IZoneLayoutRegistry.
|
overridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
inlineoverridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
inline |
|
signal |
|
overridevirtual |
Cascade-resolve the manual layout for screenId.
Returns defaultLayout() when no explicit assignment matches.
Implements PhosphorZones::IZoneLayoutRegistry.
| Layout * PhosphorZones::LayoutRegistry::layoutForShortcut | ( | int | number | ) | const |
|
inlineoverridevirtual |
Enumerate every known layout.
Borrowed pointers - owned by the concrete registry (typically LayoutManager). Order is the registry's natural iteration order.
Implements PhosphorZones::IZoneLayoutRegistry.
|
signal |
|
signal |
|
signal |
| void PhosphorZones::LayoutRegistry::loadAssignments | ( | ) |
| QJsonObject PhosphorZones::LayoutRegistry::loadAutotileOverrides | ( | const QString & | algorithmId | ) | const |
| void PhosphorZones::LayoutRegistry::loadLayouts | ( | ) |
| AssignmentEntry::Mode PhosphorZones::LayoutRegistry::modeForScreen | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) | const |
|
inline |
Get the previous active layout (before the most recent setActiveLayout).
On first call, equals activeLayout. Used by resnap-to-new-layout.
|
inline |
|
overridevirtual |
| layout | Borrowed - caller hands the pointer in; the registry un-registers it and schedules deletion via deleteLater (matching how the registry adopted it in addLayout). Callers must drop any other references before this call returns. |
Implements PhosphorZones::IZoneLayoutRegistry.
|
overridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
inlineoverridevirtual |
Resolve layout for screenId using the current desktop/activity context.
layoutForScreen already falls back to defaultLayout internally when no explicit assignment matches, so this helper is a thin context-filling forwarder.
Implements PhosphorZones::IZoneLayoutRegistry.
| void PhosphorZones::LayoutRegistry::saveAssignments | ( | ) |
| void PhosphorZones::LayoutRegistry::saveAutotileOverrides | ( | const QString & | algorithmId, |
| const QJsonObject & | overrides | ||
| ) |
| void PhosphorZones::LayoutRegistry::saveLayout | ( | Layout * | layout | ) |
| void PhosphorZones::LayoutRegistry::saveLayouts | ( | ) |
|
overridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
|
overridevirtual |
Implements PhosphorZones::IZoneLayoutRegistry.
| void PhosphorZones::LayoutRegistry::setAllActivityAssignments | ( | const QHash< QPair< QString, QString >, QString > & | assignments | ) |
| void PhosphorZones::LayoutRegistry::setAllDesktopAssignments | ( | const QHash< QPair< QString, int >, QString > & | assignments | ) |
| void PhosphorZones::LayoutRegistry::setAllQuickLayoutSlots | ( | const QHash< int, QString > & | slots | ) |
| void PhosphorZones::LayoutRegistry::setAllScreenAssignments | ( | const QHash< QString, QString > & | assignments | ) |
Batch setters - clear existing, set new, save once at end.
| void PhosphorZones::LayoutRegistry::setAssignmentEntryDirect | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const AssignmentEntry & | entry | ||
| ) |
Store a full entry directly (from KCM via D-Bus).
Stores regardless of isValid() - mode-only entries are valid when explicitly set.
|
inline |
|
inline |
| void PhosphorZones::LayoutRegistry::setDefaultAutotileAlgorithmProvider | ( | std::function< QString()> | provider | ) |
Inject a callback that returns the user-configured default autotile algorithm id (or empty if autotile is not the user's active default).
Symmetric to setDefaultLayoutIdProvider, completing the level-1 (global) tier of the assignment hierarchy:
On cascade-miss, assignmentIdForScreen and assignmentEntryForScreen consult the snap provider first, then the autotile provider; the first non-empty return wins. Providers are pass-throughs from the composition root's settings layer - each is expected to return empty when its mode is disabled in settings, which means "autotile-only" users see autotile as the natural cascade fallback (snap provider returns empty → autotile wins) without any mode-priority logic in the composition root. layoutForScreen ignores the autotile provider (it returns a snap Layout*, which has no autotile counterpart) and falls back to defaultLayout as before.
Invoked on every cascade-miss with no caching, so providers can re-read settings cheaply per call. Pass an empty function to disable.
Thread-safety: the provider is read on every cascade query and swapped via this setter without synchronization; both must run on the same thread (the LayoutRegistry's owner thread, typically the main Qt thread). The same applies to setDefaultLayoutIdProvider.
| void PhosphorZones::LayoutRegistry::setDefaultLayoutIdProvider | ( | std::function< QString()> | provider | ) |
Inject a callback that returns the user-configured default layout id (or empty if unset).
Used by composition roots that own a settings object the lib doesn't know about. The registry invokes the callback on every defaultLayout call (no caching) so the callback can re-read settings on each call. Pass an empty function to disable.
| void PhosphorZones::LayoutRegistry::setLayoutDirectory | ( | const QString & | directory | ) |
| void PhosphorZones::LayoutRegistry::setQuickLayoutSlot | ( | int | number, |
| const QString & | layoutId | ||
| ) |
| void PhosphorZones::LayoutRegistry::setSnappingLayoutPreservingMode | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const QString & | layoutId | ||
| ) |
Update only the snappingLayout field for the (screenId, virtualDesktop, activity) entry, preserving mode and tilingAlgorithm.
When no entry exists at that key, seeds a new entry from the cascade-resolved ambient state at that context so the recorded preference lands in the right mode. A pre-existing local entry — including one whose activeLayoutId() happens to be empty (e.g. a stored tile-only preference) — is used as-is as the seed so its opposite-field value is preserved. Empty layoutId clears the snap field; if both fields end up empty the entry is removed entirely.
| void PhosphorZones::LayoutRegistry::setSnappingLayoutPromoting | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const QString & | layoutId | ||
| ) |
"Promote" variant of setSnappingLayoutPreservingMode used when the user's current rendered context is already in Snapping mode — i.e.
the edit matches what's actively rendering. Wipes every other assignment entry on the same physical screen (and its VS variants) that would shadow this slot in the cascade, forces the slot to mode=Snapping with the new layoutId, and emits layoutAssigned. After this the slot is the cascade winner for every context on the screen, so setActiveLayout + onLayoutChanged see a real layout change and the resnap path actually moves windows. Snap and tile are independent fields (the slot's tile is left intact / inherited from the existing entry).
Shadow scope by slot shape (see clearShadowsForSlot):
| void PhosphorZones::LayoutRegistry::setSnappingPreferredProvider | ( | std::function< bool()> | provider | ) |
Inject a callback that returns true when Snapping is the user's preferred default mode (regardless of whether a default snapping layout id is configured).
Without this provider, resolveDefaultAssignmentEntry can only tell whether snap has a non-empty default layout id. When a user has snapping enabled but never configured a global default layout (a common, valid state - the user expects per-screen assignments to drive everything), the m_defaultLayoutIdProvider returns empty and the cascade silently falls through to the autotile branch - surfacing autotile content (e.g. "Tiling: Binary Split") to a user who never wanted autotile.
This provider lets the composition root express "snap mode is
preferred" independently of "snap has a default layout". When it returns true, the resolver returns a Snapping entry with the (possibly empty) snappingLayout from m_defaultLayoutIdProvider - activeLayoutId() then yields empty, callers see "no assignment", and the OSD path correctly suppresses rather than falling back to autotile.
Optional. When unset, the resolver behaves as before (snap-id-non-empty → snap; else autotile if available; else empty). Same threading rules as the other two providers.
| void PhosphorZones::LayoutRegistry::setTilingAlgorithmPreservingMode | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const QString & | algorithmId | ||
| ) |
Update only the tilingAlgorithm field, mirroring setSnappingLayoutPreservingMode for the tiling slot.
| void PhosphorZones::LayoutRegistry::setTilingAlgorithmPromoting | ( | const QString & | screenId, |
| int | virtualDesktop, | ||
| const QString & | activity, | ||
| const QString & | algorithmId | ||
| ) |
Symmetric promoting variant for the tile field; forces mode=Autotile after wiping shadows.
| QString PhosphorZones::LayoutRegistry::snappingLayoutForScreen | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) | const |
Per-field cascade readers — return the named field from the first entry in the cascade where it is non-empty.
Crucially, these do NOT route through the activeLayoutId-based reject filter that assignmentEntryForScreen uses, so a "stored-but-inactive" preference (e.g. an entry shaped like {mode=Snapping, snap="", tile="cluster"} that the partial-update path can produce) IS visible to the field-getter that targets the populated field. On total cascade miss they synthesize from the global default (snap provider for snap, autotile provider for tile) and may still return empty if no provider has a value.
| QString PhosphorZones::LayoutRegistry::tilingAlgorithmForScreen | ( | const QString & | screenId, |
| int | virtualDesktop = 0, |
||
| const QString & | activity = QString() |
||
| ) | const |