Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
LayoutRegistry.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
9
11
12#include <QHash>
13#include <QPair>
14#include <QString>
15#include <QUuid>
16#include <functional>
17#include <memory>
18
19namespace PhosphorZones {
20
47class PHOSPHORZONES_EXPORT LayoutRegistry : public IZoneLayoutRegistry
48{
49 Q_OBJECT
50
51 Q_PROPERTY(int layoutCount READ layoutCount NOTIFY layoutsChanged)
52 // `activeLayout` Q_PROPERTY moved to IZoneLayoutRegistry alongside its
53 // NOTIFY signal so the contract is visible to interface consumers.
54 Q_PROPERTY(QString layoutDirectory READ layoutDirectory WRITE setLayoutDirectory NOTIFY layoutDirectoryChanged)
55
56public:
72 LayoutRegistry(std::unique_ptr<PhosphorConfig::IBackend> backend, QString layoutSubdirectory,
73 QObject* parent = nullptr);
74 ~LayoutRegistry() override;
75
76 // ─── IZoneLayoutRegistry ──────────────────────────────────────────────
77
78 int layoutCount() const override
79 {
80 return m_layouts.size();
81 }
82 QVector<Layout*> layouts() const override
83 {
84 return m_layouts;
85 }
86 Layout* layout(int index) const override;
87 Layout* layoutById(const QUuid& id) const override;
88 Layout* layoutByName(const QString& name) const override;
89
90 Q_INVOKABLE void addLayout(Layout* layout) override;
91 Q_INVOKABLE void removeLayout(Layout* layout) override;
92 Q_INVOKABLE void removeLayoutById(const QUuid& id) override;
93 Q_INVOKABLE Layout* duplicateLayout(Layout* source) override;
94
95 Layout* activeLayout() const override
96 {
97 return m_activeLayout;
98 }
99 Q_INVOKABLE void setActiveLayout(Layout* layout) override;
100 Q_INVOKABLE void setActiveLayoutById(const QUuid& id) override;
101
102 // ─── Layout persistence (disk JSON) ───────────────────────────────────
103
104 QString layoutDirectory() const
105 {
106 return m_layoutDirectory;
107 }
108 void setLayoutDirectory(const QString& directory);
109
110 Q_INVOKABLE void loadLayouts();
111 Q_INVOKABLE void saveLayouts();
112 void saveLayout(Layout* layout);
113
114 Q_INVOKABLE void importLayout(const QString& filePath);
115 Q_INVOKABLE void exportLayout(Layout* layout, const QString& filePath);
116
117 // ─── Assignment persistence (via config backend) ──────────────────────
118
119 Q_INVOKABLE void loadAssignments();
120 Q_INVOKABLE void saveAssignments();
121
122 // ─── Default-layout resolution ────────────────────────────────────────
123
137 Q_INVOKABLE Layout* defaultLayout() const override;
138
148 void setDefaultLayoutIdProvider(std::function<QString()> provider);
149
183 void setDefaultAutotileAlgorithmProvider(std::function<QString()> provider);
184
211 void setSnappingPreferredProvider(std::function<bool()> provider);
212
213 // ─── Assignments (per-context routing) ────────────────────────────────
214
219 {
220 return m_previousLayout;
221 }
222
223 Q_INVOKABLE void assignLayout(const QString& screenId, int virtualDesktop, const QString& activity, Layout* layout);
224 Q_INVOKABLE void assignLayoutById(const QString& screenId, int virtualDesktop, const QString& activity,
225 const QString& layoutId);
226
230 void setAssignmentEntryDirect(const QString& screenId, int virtualDesktop, const QString& activity,
231 const AssignmentEntry& entry);
232
243 void setSnappingLayoutPreservingMode(const QString& screenId, int virtualDesktop, const QString& activity,
244 const QString& layoutId);
245
248 void setTilingAlgorithmPreservingMode(const QString& screenId, int virtualDesktop, const QString& activity,
249 const QString& algorithmId);
250
281 void setSnappingLayoutPromoting(const QString& screenId, int virtualDesktop, const QString& activity,
282 const QString& layoutId);
283
286 void setTilingAlgorithmPromoting(const QString& screenId, int virtualDesktop, const QString& activity,
287 const QString& algorithmId);
288
289 Q_INVOKABLE Layout* layoutForScreen(const QString& screenId, int virtualDesktop = 0,
290 const QString& activity = QString()) const override;
291
296 Q_INVOKABLE Layout* resolveLayoutForScreen(const QString& screenId) const override
297 {
298 return layoutForScreen(screenId, m_currentVirtualDesktop, m_currentActivity);
299 }
300
301 Q_INVOKABLE void clearAssignment(const QString& screenId, int virtualDesktop = 0,
302 const QString& activity = QString());
303 Q_INVOKABLE bool hasExplicitAssignment(const QString& screenId, int virtualDesktop = 0,
304 const QString& activity = QString()) const;
305
316 Q_INVOKABLE QString assignmentIdForScreen(const QString& screenId, int virtualDesktop = 0,
317 const QString& activity = QString()) const override;
318
336 AssignmentEntry assignmentEntryForScreen(const QString& screenId, int virtualDesktop = 0,
337 const QString& activity = QString()) const;
338
339 AssignmentEntry::Mode modeForScreen(const QString& screenId, int virtualDesktop = 0,
340 const QString& activity = QString()) const;
341
352 QString snappingLayoutForScreen(const QString& screenId, int virtualDesktop = 0,
353 const QString& activity = QString()) const;
354 QString tilingAlgorithmForScreen(const QString& screenId, int virtualDesktop = 0,
355 const QString& activity = QString()) const;
356
361
363 void setAllScreenAssignments(const QHash<QString, QString>& assignments);
364 void setAllDesktopAssignments(const QHash<QPair<QString, int>, QString>& assignments);
365 void setAllActivityAssignments(const QHash<QPair<QString, QString>, QString>& assignments);
366
367 QHash<QPair<QString, int>, QString> desktopAssignments() const;
368 QHash<QPair<QString, QString>, QString> activityAssignments() const;
369
370 // ─── Quick-layout slots (1..9) ────────────────────────────────────────
371
372 Q_INVOKABLE Layout* layoutForShortcut(int number) const;
373 Q_INVOKABLE void applyQuickLayout(int number, const QString& screenId);
374 void setQuickLayoutSlot(int number, const QString& layoutId);
375 void setAllQuickLayoutSlots(const QHash<int, QString>& slots);
376 QHash<int, QString> quickLayoutSlots() const
377 {
378 return m_quickLayoutShortcuts;
379 }
380
381 // ─── Layout cycling ───────────────────────────────────────────────────
382
383 Q_INVOKABLE void cycleToPreviousLayout(const QString& screenId);
384 Q_INVOKABLE void cycleToNextLayout(const QString& screenId);
385
386 // ─── Built-in layouts ─────────────────────────────────────────────────
387
388 Q_INVOKABLE void createBuiltInLayouts();
389 QVector<Layout*> builtInLayouts() const;
390
391 // ─── Context (desktop / activity) ─────────────────────────────────────
392
393 Q_INVOKABLE int currentVirtualDesktop() const override
394 {
395 return m_currentVirtualDesktop;
396 }
397 Q_INVOKABLE QString currentActivity() const override
398 {
399 return m_currentActivity;
400 }
401 void setCurrentVirtualDesktop(int desktop)
402 {
403 m_currentVirtualDesktop = desktop;
404 }
405 void setCurrentActivity(const QString& activity)
406 {
407 m_currentActivity = activity;
408 }
409
410 // ─── Autotile layout overrides (per-algorithm user overrides) ─────────
411
412 void saveAutotileOverrides(const QString& algorithmId, const QJsonObject& overrides);
413 QJsonObject loadAutotileOverrides(const QString& algorithmId) const;
414
415Q_SIGNALS:
416 // layoutAdded / layoutRemoved / activeLayoutChanged / layoutAssigned are
417 // inherited from IZoneLayoutRegistry - declared on the interface so
418 // consumers that target the contract can connect without depending on
419 // the concrete class. Emit sites still live in this TU and reach the
420 // inherited signal via Q_OBJECT's metaobject chain.
425
426private:
432 void clearShadowsForSlot(const QString& screenId, int virtualDesktop, const QString& activity);
433
434 void ensureLayoutDirectory();
435 void loadLayoutsFromDirectory(const QString& directory);
436 Layout* restoreSystemLayout(const QUuid& id, const QString& systemPath);
437 QString layoutFilePath(const QUuid& id) const;
438 void readAssignmentGroups(PhosphorConfig::IBackend* backend);
439 void readQuickLayouts(PhosphorConfig::IBackend* backend);
440 Layout* cycleLayoutImpl(const QString& screenId, int direction);
441 bool shouldSkipLayoutAssignment(const QString& layoutId, const QString& context) const;
442 void emitLayoutAssigned(const QString& screenId, int virtualDesktop, const QString& layoutId);
457 void applyLayoutToScreen(const QString& screenId, Layout* layout);
458 QJsonObject loadAllAutotileOverrides() const;
459 void saveAllAutotileOverrides(const QJsonObject& all);
460 Layout* resolveConfiguredDefault() const;
461
472 AssignmentEntry resolveDefaultAssignmentEntry() const;
473
474 std::function<QString()> m_defaultLayoutIdProvider;
480 std::function<QString()> m_defaultAutotileAlgorithmProvider;
485 std::function<bool()> m_snappingPreferredProvider;
486 std::unique_ptr<PhosphorConfig::IBackend> m_ownedBackend;
487 PhosphorConfig::IBackend* m_configBackend = nullptr;
488 QString m_layoutSubdirectory;
489 QString m_layoutDirectory;
490 QVector<Layout*> m_layouts;
491 Layout* m_activeLayout = nullptr;
492 Layout* m_previousLayout = nullptr;
493 QHash<LayoutAssignmentKey, AssignmentEntry> m_assignments;
494 QHash<int, QString> m_quickLayoutShortcuts;
495 int m_currentVirtualDesktop = 1;
496 QString m_currentActivity;
497};
498
499} // namespace PhosphorZones
Pluggable configuration backend.
Definition IBackend.h:150
Enumeration + mutation surface for the in-memory zone-layout catalog.
Definition IZoneLayoutRegistry.h:43
Manual zone-layout registry + per-context assignment store.
Definition LayoutRegistry.h:48
AssignmentEntry::Mode modeForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
QString layoutDirectory() const
Definition LayoutRegistry.h:104
LayoutRegistry(std::unique_ptr< PhosphorConfig::IBackend > backend, QString layoutSubdirectory, QObject *parent=nullptr)
void setAllDesktopAssignments(const QHash< QPair< QString, int >, QString > &assignments)
QString assignmentIdForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const override
Raw assignment id for a (screen, desktop, activity) context.
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 no...
void setSnappingLayoutPreservingMode(const QString &screenId, int virtualDesktop, const QString &activity, const QString &layoutId)
Update only the snappingLayout field for the (screenId, virtualDesktop, activity) entry,...
void setQuickLayoutSlot(int number, const QString &layoutId)
int currentVirtualDesktop() const override
Definition LayoutRegistry.h:393
void exportLayout(Layout *layout, const QString &filePath)
Layout * duplicateLayout(Layout *source) override
int layoutCount() const override
Definition LayoutRegistry.h:78
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 setActiveLayoutById(const QUuid &id) override
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.
void setAssignmentEntryDirect(const QString &screenId, int virtualDesktop, const QString &activity, const AssignmentEntry &entry)
Store a full entry directly (from KCM via D-Bus).
void cycleToNextLayout(const QString &screenId)
void setAllActivityAssignments(const QHash< QPair< QString, QString >, QString > &assignments)
void setAllScreenAssignments(const QHash< QString, QString > &assignments)
Batch setters - clear existing, set new, save once at end.
Layout * resolveLayoutForScreen(const QString &screenId) const override
Resolve layout for screenId using the current desktop/activity context.
Definition LayoutRegistry.h:296
Layout * activeLayout() const override
Definition LayoutRegistry.h:95
bool hasExplicitAssignment(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
void cycleToPreviousLayout(const QString &screenId)
void addLayout(Layout *layout) override
QHash< QPair< QString, int >, QString > desktopAssignments() const
Layout * layout(int index) const override
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...
void setAllQuickLayoutSlots(const QHash< int, QString > &slots)
void setLayoutDirectory(const QString &directory)
void applyQuickLayout(int number, const QString &screenId)
void saveAutotileOverrides(const QString &algorithmId, const QJsonObject &overrides)
void assignLayoutById(const QString &screenId, int virtualDesktop, const QString &activity, const QString &layoutId)
Layout * previousLayout() const
Get the previous active layout (before the most recent setActiveLayout).
Definition LayoutRegistry.h:218
void setSnappingPreferredProvider(std::function< bool()> provider)
Inject a callback that returns true when Snapping is the user's preferred default mode (regardless of...
void setCurrentActivity(const QString &activity)
Definition LayoutRegistry.h:405
Layout * defaultLayout() const override
Resolve the effective default layout.
void removeLayoutById(const QUuid &id) override
void clearAssignment(const QString &screenId, int virtualDesktop=0, const QString &activity=QString())
void clearAutotileAssignments()
Flip mode to Snapping for every entry currently in Autotile (preserves snappingLayout + tilingAlgorit...
QString tilingAlgorithmForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
void setCurrentVirtualDesktop(int desktop)
Definition LayoutRegistry.h:401
AssignmentEntry assignmentEntryForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
Full entry for a (screen, desktop, activity) context.
Layout * layoutByName(const QString &name) const override
QJsonObject loadAutotileOverrides(const QString &algorithmId) const
Layout * layoutById(const QUuid &id) const override
Resolve a layout by its stable UUID.
void importLayout(const QString &filePath)
void removeLayout(Layout *layout) override
QHash< int, QString > quickLayoutSlots() const
Definition LayoutRegistry.h:376
QString currentActivity() const override
Definition LayoutRegistry.h:397
void setDefaultLayoutIdProvider(std::function< QString()> provider)
Inject a callback that returns the user-configured default layout id (or empty if unset).
QHash< QPair< QString, QString >, QString > activityAssignments() const
void setDefaultAutotileAlgorithmProvider(std::function< QString()> provider)
Inject a callback that returns the user-configured default autotile algorithm id (or empty if autotil...
void saveLayout(Layout *layout)
QVector< Layout * > builtInLayouts() const
Layout * layoutForShortcut(int number) const
void setActiveLayout(Layout *layout) override
void assignLayout(const QString &screenId, int virtualDesktop, const QString &activity, Layout *layout)
QVector< Layout * > layouts() const override
Enumerate every known layout.
Definition LayoutRegistry.h:82
Represents a collection of zones that form a layout.
Definition Layout.h:74
Definition IWindowTrackingService.h:22
Explicit per-context assignment entry storing both mode fields.
Definition AssignmentEntry.h:86
Mode
Definition AssignmentEntry.h:87