11#include <PhosphorWindowRules/RuleEvaluator.h>
12#include <PhosphorWindowRules/WindowRuleStore.h>
81 Q_PROPERTY(
int layoutCount READ layoutCount NOTIFY layoutsChanged)
84 Q_PROPERTY(QString layoutDirectory READ layoutDirectory WRITE setLayoutDirectory NOTIFY layoutDirectoryChanged)
126 LayoutRegistry(PhosphorWindowRules::WindowRuleStore* ruleStore, QString layoutSubdirectory,
127 QObject* parent =
nullptr);
134 return m_layouts.size();
151 return m_activeLayout;
160 return m_layoutDirectory;
304 return m_previousLayout;
307 Q_INVOKABLE
void assignLayout(
const QString& screenId,
int virtualDesktop,
const QString& activity,
Layout* layout);
308 Q_INVOKABLE
void assignLayoutById(
const QString& screenId,
int virtualDesktop,
const QString& activity,
309 const QString& layoutId);
318 const QString& activity = QString())
const override;
330 return layoutForScreen(screenId, currentVirtualDesktopForScreen(screenId), m_currentActivity);
343 const QString& activity)
const override;
351 bool resolveContextLocked(
const QString& screenId,
int virtualDesktop,
const QString& activity)
const override;
363 const QString& activity)
const;
373 const QString& activity)
const override;
376 const QString& activity = QString());
386 const QString& activity = QString())
const;
399 const QString& activity = QString())
const override;
419 const QString& activity = QString())
const;
422 const QString& activity = QString())
const;
437 const QString& activity = QString())
const override;
451 const QString& activity = QString())
const;
464 const QString& activity = QString())
const;
466 const QString& activity = QString())
const override;
504 static constexpr QLatin1String QuickSlotsSnappingKey{
"snapping"};
505 static constexpr QLatin1String QuickSlotsAutotileKey{
"autotile"};
513 return m_quickLayoutSlots[modeIndex(mode)];
530 return m_currentVirtualDesktop;
534 return m_currentActivity;
538 m_currentVirtualDesktop = desktop;
544 const auto it = m_screenVirtualDesktop.constFind(screenId);
545 return it != m_screenVirtualDesktop.constEnd() ? it.value() : m_currentVirtualDesktop;
551 if (!screenId.isEmpty() && desktop >= 1) {
552 m_screenVirtualDesktop.insert(screenId, desktop);
558 m_screenVirtualDesktop.remove(screenId);
562 m_currentActivity = activity;
587 return static_cast<int>(m_contextResolveCache.size());
606 void ensureLayoutDirectory();
607 void loadLayoutsFromDirectory(
const QString& directory);
608 Layout* restoreSystemLayout(
const QUuid&
id,
const QString& systemPath);
609 QString layoutFilePath(
const QUuid&
id)
const;
610 QString quickLayoutsFilePath()
const;
611 QString layoutSettingsFilePath()
const;
612 void readQuickLayouts();
613 void writeQuickLayouts();
619 return mode == AssignmentEntry::Autotile ? 1 : 0;
621 Layout* cycleLayoutImpl(
const QString& screenId,
int direction);
622 bool shouldSkipLayoutAssignment(
const QString& layoutId,
const QString& context)
const;
623 void emitLayoutAssigned(
const QString& screenId,
int virtualDesktop,
const QString& layoutId);
638 void applyLayoutToScreen(
const QString& screenId,
Layout* layout);
641 void migrateLegacyAutotileOverrides();
642 Layout* resolveConfiguredDefault()
const;
677 std::optional<AssignmentEntry> resolveAssignmentEntry(
const QString& screenId,
int virtualDesktop,
678 const QString& activity)
const;
684 bool hasExactContextRule(
const QString& screenId,
int virtualDesktop,
const QString& activity)
const;
697 const PhosphorWindowRules::WindowRule* findExactContextRule(
const QString& screenId,
int virtualDesktop,
698 const QString& activity)
const;
702 QUuid exactContextRuleId(
const QString& screenId,
int virtualDesktop,
const QString& activity)
const;
706 void upsertAssignmentRule(
const QString& screenId,
int virtualDesktop,
const QString& activity,
711 bool removeAssignmentRule(
const QString& screenId,
int virtualDesktop,
const QString& activity);
723 template<
typename KeyT,
typename DecodeFn,
typename Val
idFn,
typename FamilyFn>
724 void applyBatchAssignments(
const QHash<KeyT, QString>& assignments, DecodeFn decode, ValidFn valid,
725 FamilyFn familyMatches,
int emitDesktop,
const QString& emitActivity,
const char* label);
734 bool purgeSnappingLayoutFromAssignments(
const QString& layoutId);
766 AssignmentEntry resolveDefaultAssignmentEntryForContext(
const QString& screenId,
int virtualDesktop,
767 const QString& activity)
const;
776 bool hasMatchingAssignmentRule(
const QString& screenId,
int virtualDesktop,
const QString& activity)
const;
783 struct ContextResolveKey
786 int virtualDesktop = 0;
788 bool operator==(
const ContextResolveKey& other)
const noexcept
790 return virtualDesktop == other.virtualDesktop && screenId == other.screenId && activity == other.activity;
793 friend size_t qHash(
const LayoutRegistry::ContextResolveKey& key,
size_t seed)
noexcept
800 h = ::qHash(key.screenId, h);
801 h = ::qHash(key.virtualDesktop, h);
802 h = ::qHash(key.activity, h);
817 template<
typename V,
typename ComputeFn>
818 V resolveCachedContext(QHash<ContextResolveKey, V>& cache, quint64& cacheRevision,
const QString& screenId,
819 int virtualDesktop,
const QString& activity, ComputeFn&& compute)
const
821 const quint64 revision = m_ruleStore->ruleSet().revision();
822 if (revision != cacheRevision) {
824 cacheRevision = revision;
826 const ContextResolveKey key{screenId, virtualDesktop, activity};
827 const auto cached = cache.constFind(key);
828 if (cached != cache.constEnd()) {
829 return cached.value();
832 constexpr qsizetype kMaxEntries = 256;
833 if (cache.size() >= kMaxEntries) {
836 cache.insert(key, value);
852 struct RuleSlotResolution
854 std::optional<AssignmentEntry> modeEntry;
855 std::optional<QString> snappingLayout;
856 std::optional<QString> tilingAlgorithm;
865 mutable QHash<ContextResolveKey, std::optional<RuleSlotResolution>> m_contextResolveCache;
869 mutable quint64 m_contextResolveCacheRevision = 0;
877 mutable QHash<ContextResolveKey, ContextGapOverride> m_contextGapCache;
878 mutable quint64 m_contextGapCacheRevision = 0;
885 mutable QHash<ContextResolveKey, bool> m_contextLockCache;
886 mutable quint64 m_contextLockCacheRevision = 0;
894 mutable QHash<ContextResolveKey, std::optional<bool>> m_contextDefaultAssignmentCache;
895 mutable quint64 m_contextDefaultAssignmentCacheRevision = 0;
902 mutable QHash<ContextResolveKey, ContextOverlayOverride> m_contextOverlayCache;
903 mutable quint64 m_contextOverlayCacheRevision = 0;
905 std::function<QString()> m_defaultLayoutIdProvider;
911 std::function<QString()> m_defaultAutotileAlgorithmProvider;
916 std::function<bool()> m_snappingPreferredProvider;
921 std::function<bool()> m_defaultAssignmentSuppressedProvider;
925 PhosphorWindowRules::WindowRuleStore* m_ruleStore =
nullptr;
927 std::unique_ptr<PhosphorWindowRules::RuleEvaluator> m_evaluator;
928 QString m_layoutSubdirectory;
929 QString m_layoutDirectory;
930 QVector<Layout*> m_layouts;
931 Layout* m_activeLayout =
nullptr;
932 Layout* m_previousLayout =
nullptr;
936 QHash<int, QString> m_quickLayoutSlots[2];
940 LayoutSettingsStore m_layoutSettings;
941 int m_currentVirtualDesktop = 1;
945 QHash<QString, int> m_screenVirtualDesktop;
946 QString m_currentActivity;
Enumeration + mutation surface for the in-memory zone-layout catalog.
Definition IZoneLayoutRegistry.h:45
Manual zone-layout registry + per-context assignment store.
Definition LayoutRegistry.h:78
friend size_t qHash(const LayoutRegistry::ContextResolveKey &key, size_t seed) noexcept
Definition LayoutRegistry.h:793
AssignmentEntry::Mode modeForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
QString layoutDirectory() const
Definition LayoutRegistry.h:158
void applyQuickLayout(AssignmentEntry::Mode mode, int number, const QString &screenId)
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...
LayoutRegistry(PhosphorWindowRules::WindowRuleStore *ruleStore, QString layoutSubdirectory, QObject *parent=nullptr)
int currentVirtualDesktop() const override
Definition LayoutRegistry.h:528
QHash< int, QString > quickLayoutSlots(AssignmentEntry::Mode mode) const
Definition LayoutRegistry.h:511
void exportLayout(Layout *layout, const QString &filePath)
Layout * duplicateLayout(Layout *source) override
int layoutCount() const override
Definition LayoutRegistry.h:132
void setActiveLayoutById(const QUuid &id) override
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:324
Layout * activeLayout() const override
Definition LayoutRegistry.h:149
bool hasExplicitAssignment(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
True iff a context-assignment rule whose match is exactly this (screen, desktop, activity) tuple's sh...
void cycleToPreviousLayout(const QString &screenId)
void addLayout(Layout *layout) override
QHash< QPair< QString, int >, QString > desktopAssignments() const
Layout * layout(int index) const override
ContextOverlayOverride resolveContextOverlay(const QString &screenId, int virtualDesktop, const QString &activity) const override
Resolve the per-context overlay-property override (shader / style) for (screen, desktop,...
void setLayoutDirectory(const QString &directory)
void saveAutotileOverrides(const QString &algorithmId, const QJsonObject &overrides)
void setQuickLayoutSlot(AssignmentEntry::Mode mode, int number, const QString &layoutId)
~LayoutRegistry() override
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:302
void setSnappingPreferredProvider(std::function< bool()> provider)
Inject a callback that returns true when Snapping is the user's preferred default mode (regardless of...
int currentVirtualDesktopForScreen(const QString &screenId) const override
This screen's current virtual desktop, falling back to the global m_currentVirtualDesktop when no per...
Definition LayoutRegistry.h:542
void setCurrentActivity(const QString &activity)
Definition LayoutRegistry.h:560
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())
int contextResolveCacheSize() const
Current entry count in the resolveAssignmentEntry hot-path cache.
Definition LayoutRegistry.h:585
bool isContextActiveLayoutSuppressed(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const override
True iff the context has NO active layout specifically because the default assignment is suppressed —...
void setCurrentVirtualDesktopForScreen(const QString &screenId, int desktop)
Record a single screen's current virtual desktop (per-output virtual desktops).
Definition LayoutRegistry.h:549
void clearAutotileAssignments()
Flip mode to Snapping for every entry currently in Autotile (preserves snappingLayout + tilingAlgorit...
void setCurrentVirtualDesktop(int desktop)
Definition LayoutRegistry.h:536
bool snappingPreferred() const
True when the snapping-preferred provider is wired AND reports true — i.e.
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
Layout * layoutById(const QUuid &id) const override
Resolve a layout by its stable UUID.
void setAllQuickLayoutSlots(AssignmentEntry::Mode mode, const QHash< int, QString > &slots)
bool resolveContextLocked(const QString &screenId, int virtualDesktop, const QString &activity) const override
Resolve whether a context rule locks the active layout for the (screen, desktop, activity) context by...
void importLayout(const QString &filePath)
void removeLayout(Layout *layout) override
std::optional< bool > resolveContextDefaultAssignment(const QString &screenId, int virtualDesktop, const QString &activity) const
Resolve a per-context override of the global default-layout-assignment baseline for the (screen,...
QString currentActivity() const override
Definition LayoutRegistry.h:532
void seedDefaultLayoutSettingsIfFresh(const QJsonObject &defaults)
Seed curated default picker visibility into the sidecar, but ONLY on a fresh install — when neither l...
Layout * layoutForShortcut(AssignmentEntry::Mode mode, int number) const
void clearCurrentVirtualDesktopForScreen(const QString &screenId)
Drop a screen's per-output desktop, reverting it to the global value.
Definition LayoutRegistry.h:556
void setDefaultLayoutIdProvider(std::function< QString()> provider)
Inject a callback that returns the user-configured default layout id (or empty if unset).
void setDefaultAssignmentSuppressedProvider(std::function< bool()> provider)
Inject a callback that returns true when the user has opted to suppress the synthesized level-1 defau...
QHash< QPair< QString, QString >, QString > activityAssignments() const
void layoutDirectoryChanged()
void setDefaultAutotileAlgorithmProvider(std::function< QString()> provider)
Inject a callback that returns the user-configured default autotile algorithm id (or empty if autotil...
QJsonObject loadAutotileOverrides(const QString &algorithmId) const override
Per-algorithm autotile settings (gaps, shader, hiddenFromSelector, …) stored in the unified layout-se...
ContextGapOverride resolveContextGaps(const QString &screenId, int virtualDesktop, const QString &activity) const override
Resolve the per-context gap override for (screen, desktop, activity) by evaluating a windowless Windo...
QString tilingAlgorithmForScreen(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const override
Raw id of the tiling algorithm active for the (screenId, virtualDesktop, activity) context,...
void saveLayout(Layout *layout)
QHash< CombinedAssignmentKey, QString > combinedAssignments() const
Strict Combined-context reader.
QVector< Layout * > builtInLayouts() const
void setActiveLayout(Layout *layout) override
void assignLayout(const QString &screenId, int virtualDesktop, const QString &activity, Layout *layout)
void createBuiltInLayouts()
bool isDefaultAssignmentSuppressedForContext(const QString &screenId, int virtualDesktop=0, const QString &activity=QString()) const
True iff the SYNTHESIZED default (the level-1 provider layout / autotile algorithm) is suppressed for...
void setAllCombinedAssignments(const QHash< CombinedAssignmentKey, QString > &assignments)
Combined-context (screen + desktop + activity) batch setter — the triple-axis sibling of the Activity...
QVector< Layout * > layouts() const override
Enumerate every known layout.
Definition LayoutRegistry.h:136
Represents a collection of zones that form a layout.
Definition Layout.h:40
Definition IWindowTrackingService.h:23
size_t qHash(const LayoutAssignmentKey &key, size_t seed=0)
Definition AssignmentEntry.h:75
Explicit per-context assignment entry storing both mode fields.
Definition AssignmentEntry.h:91
Mode
Per-context engine selection.
Definition AssignmentEntry.h:100
Triple-axis key for the Combined-context batch API.
Definition LayoutRegistry.h:36
int virtualDesktop
Definition LayoutRegistry.h:38
QString activity
Definition LayoutRegistry.h:39
QString screenId
Definition LayoutRegistry.h:37
bool operator==(const CombinedAssignmentKey &other) const
Definition LayoutRegistry.h:41
Per-context gap override resolved from window rules.
Definition AssignmentEntry.h:188
Per-context overlay-property overrides resolved from window-rule actions.
Definition AssignmentEntry.h:220