Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
WindowTrackingService.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#include <phosphorplacement_export.h>
7
18
19#include <QHash>
20#include <QObject>
21#include <QPointer>
22#include <QRect>
23#include <QSet>
24#include <QString>
25#include <QStringList>
26
27#include <functional>
28#include <optional>
29#include <utility>
30
31namespace PhosphorZones {
32class IZoneDetector;
33class Layout;
34class LayoutRegistry;
35class Zone;
36}
37
39class SnapState;
40}
41
42namespace PhosphorEngine {
43class WindowRegistry;
44}
45
49
50namespace PhosphorScreens {
51class ScreenManager;
52}
53
54namespace PhosphorPlacement {
55
79class PHOSPHORPLACEMENT_EXPORT WindowTrackingService : public QObject, public PhosphorEngine::IWindowTrackingService
80{
81 Q_OBJECT
82
83public:
85 PhosphorZones::IZoneDetector* zoneDetector,
86 PhosphorScreens::ScreenManager* screenManager,
88 IGeometryResolver* geometryResolver = nullptr, PlacementConfig config = {},
89 QObject* parent = nullptr);
90
96 const PlacementConfig& config() const
97 {
98 return m_config;
99 }
100
101 QObject* asQObject() override
102 {
103 return this;
104 }
106
117 {
118 m_windowRegistry = registry;
119 }
120
122 {
123 m_snapState = state;
124 }
125
129 {
130 return m_placementStore;
131 }
133 {
134 return m_placementStore;
135 }
136
155 using ShouldTrackPredicate = std::function<bool(const QString& screenId, int virtualDesktop)>;
156
176 {
177 m_shouldTrackPredicate = std::move(predicate);
178 }
179
192 {
193 m_snapEngine = engine;
194 }
195
197 {
198 return m_snapEngine.data();
199 }
200
209 using AutotileModePredicate = std::function<bool(const QString& windowId)>;
211 {
212 m_autotileModePredicate = std::move(predicate);
213 }
214
224 bool isWindowInAutotileMode(const QString& windowId) const
225 {
226 return m_autotileModePredicate && m_autotileModePredicate(windowId);
227 }
228
243 using AutotileTiledPredicate = std::function<bool(const QString& windowId)>;
245 {
246 m_autotileTiledPredicate = std::move(predicate);
247 }
248
251 bool isWindowAutotileTiled(const QString& windowId) const
252 {
253 return m_autotileTiledPredicate && m_autotileTiledPredicate(windowId);
254 }
255
260 {
261 return m_windowRegistry;
262 }
263
265 {
266 return m_screenManager;
267 }
268
269 // ═══════════════════════════════════════════════════════════════════════════
270 // PhosphorZones::Zone Assignment Management
271 // ═══════════════════════════════════════════════════════════════════════════
272
280 void assignWindowToZone(const QString& windowId, const QString& zoneId, const QString& screenId,
281 int virtualDesktop) override;
282
290 void assignWindowToZones(const QString& windowId, const QStringList& zoneIds, const QString& screenId,
291 int virtualDesktop) override;
292
297 void unassignWindow(const QString& windowId) override;
298
304 QString zoneForWindow(const QString& windowId) const override;
305
311 QStringList zonesForWindow(const QString& windowId) const override;
312
318 QString screenForWindow(const QString& windowId) const override;
319
323 QString screenForWindow(const QString& windowId, const QString& defaultScreen) const override;
324
330 QStringList windowsInZone(const QString& zoneId) const override;
331
336 QStringList snappedWindows() const;
337
340 int pruneStaleAssignments(const QSet<QString>& aliveWindowIds);
341
345 bool isWindowSnapped(const QString& windowId) const override;
346
347 // ═══════════════════════════════════════════════════════════════════════════
348 // Geometry Validation Utility
349 // ═══════════════════════════════════════════════════════════════════════════
350
365 std::optional<QRect> validateGeometryForScreen(const QRect& geo, const QString& savedScreen,
366 const QString& currentScreenName) const;
367
379 std::optional<QRect> validatedUnmanagedGeometry(const QString& windowId, const QString& screenId,
380 bool exactOnly = false) const override;
381
384 void recordFreeGeometry(const QString& windowId, const QString& screenId, const QRect& geometry,
385 bool overwrite) override;
386
396 void recordFloatingClose(const QString& windowId, const QString& screenId, const QRect& geometry);
397
400 void clearFreeGeometry(const QString& windowId) override;
401
402 // ═══════════════════════════════════════════════════════════════════════════
403 // Floating Window State
404 // ═══════════════════════════════════════════════════════════════════════════
405
421 using EngineFloatResolver = std::function<bool(const QString& windowId)>;
422 using EngineFloatWriter = std::function<void(const QString& windowId, bool floating)>;
423 using EngineFloatLister = std::function<QStringList()>;
424
426 {
427 m_engineFloatResolver = std::move(resolver);
428 }
430 {
431 m_engineFloatWriter = std::move(writer);
432 }
436 {
437 m_engineFloatLister = std::move(lister);
438 }
439
446 bool isWindowFloating(const QString& windowId) const override;
447
458 void setWindowFloating(const QString& windowId, bool floating) override;
459
463 QStringList floatingWindows() const;
464
469 void unsnapForFloat(const QString& windowId) override;
470
476 QString preFloatZone(const QString& windowId) const;
477
483 QStringList preFloatZones(const QString& windowId) const override;
484
490 QString preFloatScreen(const QString& windowId) const override;
491
495 void clearPreFloatZone(const QString& windowId);
496
502 void clearPreFloatZoneForWindow(const QString& windowId);
503
514 bool clearFloatingForSnap(const QString& windowId) override;
515
516 // ═══════════════════════════════════════════════════════════════════════════
517 // Sticky Window Handling
518 // ═══════════════════════════════════════════════════════════════════════════
519
523 void setWindowSticky(const QString& windowId, bool sticky);
524
528 bool isWindowSticky(const QString& windowId) const override;
529
530 // ═══════════════════════════════════════════════════════════════════════════
531 // Auto-Snap Logic
532 // ═══════════════════════════════════════════════════════════════════════════
533
539 void recordSnapIntent(const QString& windowId, bool wasUserInitiated) override;
540
544 QString lastUsedZoneId() const;
545
552 QString lastUsedZoneClass() const;
553
560 QString lastUsedScreenName() const;
561
565 int lastUsedDesktop() const;
566
575 void retagLastUsedZoneClass(const QString& newClass);
576
580 void updateLastUsedZone(const QString& zoneId, const QString& screenId, const QString& windowClass,
581 int virtualDesktop) override;
582
592 void markAsAutoSnapped(const QString& windowId);
593
599 bool isAutoSnapped(const QString& windowId) const;
600
606 bool clearAutoSnapped(const QString& windowId) override;
607
637 bool consumePendingAssignment(const QString& windowId) override;
638
639 // ═══════════════════════════════════════════════════════════════════════════
640 // Navigation Helpers
641 // ═══════════════════════════════════════════════════════════════════════════
642
648 QString findEmptyZone(const QString& screenId = QString()) const override;
649
655 PhosphorProtocol::EmptyZoneList getEmptyZones(const QString& screenId) const;
656
663 QRect zoneGeometry(const QString& zoneId, const QString& screenId = QString()) const override;
664
671 QRect multiZoneGeometry(const QStringList& zoneIds, const QString& screenId = QString()) const;
672
692 void populateResnapBufferForAllScreens(const QSet<QString>& excludeScreens = {},
693 const QSet<QString>& includeScreens = {}, int desktopFilter = 0);
694
702 {
703 m_resnapBuffer.clear();
704 }
705
716 QStringList buildZoneOrderedWindowList(const QString& screenId) const;
717
718 // ═══════════════════════════════════════════════════════════════════════════
719 // Virtual Screen Migration
720 // ═══════════════════════════════════════════════════════════════════════════
721
741 void migrateScreenAssignmentsToVirtual(const QString& physicalScreenId, const QStringList& virtualScreenIds,
743
753 void migrateScreenAssignmentsFromVirtual(const QString& physicalScreenId);
754
778 QSet<QString> physicalScreensWithStaleVirtualAssignments(const QSet<QString>& subdividedPhysicalIds) const;
779
780 // ═══════════════════════════════════════════════════════════════════════════
781 // Resolution Change Handling
782 // ═══════════════════════════════════════════════════════════════════════════
783
790 QHash<QString, QRect> updatedWindowGeometries() const;
791
801 {
802 QRect geometry;
803 QString screenId;
804 };
805
820 QHash<QString, PendingRestoreTarget> pendingRestoreGeometries() const;
821
822 // ═══════════════════════════════════════════════════════════════════════════
823 // Window Lifecycle
824 // ═══════════════════════════════════════════════════════════════════════════
825
836
841
842 // ═══════════════════════════════════════════════════════════════════════════
843 // State Access (for adaptor persistence via KConfig)
844 // ═══════════════════════════════════════════════════════════════════════════
845
850 const QHash<QString, QStringList>& zoneAssignments() const override;
851
854 QStringList recordedSnapZones(const QString& windowId) const override;
855
859 const QHash<QString, QString>& screenAssignments() const override;
860
864 const QHash<QString, int>& desktopAssignments() const;
865
868
872 const QHash<QString, QList<PendingRestore>>& pendingRestoreQueues() const override
873 {
874 return m_pendingRestoreQueues;
875 }
876
877 QVector<ResnapEntry> takeResnapBuffer() override
878 {
879 return std::exchange(m_resnapBuffer, {});
880 }
881
885 const QSet<QString>& userSnappedClasses() const;
886
894 void setActiveAssignments(const QHash<QString, QStringList>& zones, const QHash<QString, QString>& screens,
895 const QHash<QString, int>& desktops);
896
900 void setPendingRestoreQueues(const QHash<QString, QList<PendingRestore>>& queues)
901 {
902 m_pendingRestoreQueues = queues;
903 }
904
908 void setUserSnappedClasses(const QSet<QString>& classes);
909
913 void setLastUsedZone(const QString& zoneId, const QString& screenId, const QString& zoneClass, int desktop);
914
918 void setFloatingWindows(const QSet<QString>& windows)
919 {
920 m_floatingWindows = windows;
921 }
922
928 const QHash<QString, QStringList>& preFloatZoneAssignments() const;
929 const QHash<QString, QString>& preFloatScreenAssignments() const;
930
936 void setPreFloatZoneAssignments(const QHash<QString, QStringList>& assignments);
937 void setPreFloatScreenAssignments(const QHash<QString, QString>& assignments);
938
939 // ═══════════════════════════════════════════════════════════════════════
940 // Dirty field tracking (Phase 3 of refactor/dbus-performance)
941 //
942 // Replaces "any mutation forces a full re-serialization" with a bitfield
943 // mask of which persisted state has changed since the last successful
944 // save. WindowTrackingAdaptor::saveState() reads this mask to decide
945 // which JSON maps to re-write, and the persistence worker's write-
946 // completed signal clears the committed bits — surviving bits either
947 // represent new mutations that landed during the in-flight write, or
948 // the write itself failed (same treatment in both cases: retry on the
949 // next tick).
950 //
951 // The mask is initialized to All so the first save after a daemon
952 // startup always writes every field. loadState() should clear the mask
953 // immediately after populating in-memory state so the first real save
954 // doesn't redundantly write back what we just loaded.
955 // ═══════════════════════════════════════════════════════════════════════
956 // NOTE: several bits below (DirtyZoneAssignments, DirtyPendingRestores,
957 // DirtyPreTileGeometries, DirtyPreFloatZones, DirtyPreFloatScreens,
958 // DirtyAutotileOrders, DirtyAutotilePending) no longer have a dedicated save
959 // block — their legacy keys were collapsed into DirtyWindowPlacements. The
960 // runtime mutators that still OR them in are retained because the act of
961 // marking ANY bit schedules a save, and saveState()'s refreshOpenWindowPlacements()
962 // re-derives the affected per-window state into the placement record. They are
963 // therefore "schedule a save" triggers, not independent persisted fields; only
964 // DirtyActiveLayoutId / DirtyLastUsedZone / DirtyUserSnapped / DirtyWindowPlacements
965 // map to their own on-disk key.
966 enum DirtyField : uint32_t {
967 DirtyNone = 0,
968 DirtyActiveLayoutId = 1u << 0,
969 DirtyZoneAssignments = 1u << 1, // legacy save-trigger → DirtyWindowPlacements
970 DirtyPendingRestores = 1u << 2, // legacy save-trigger → DirtyWindowPlacements
971 DirtyPreTileGeometries = 1u << 3, // legacy save-trigger → DirtyWindowPlacements
972 DirtyLastUsedZone = 1u << 4,
973 DirtyPreFloatZones = 1u << 5, // legacy save-trigger → DirtyWindowPlacements
974 DirtyPreFloatScreens = 1u << 6, // legacy save-trigger → DirtyWindowPlacements
975 DirtyUserSnapped = 1u << 7,
976 DirtyAutotileOrders = 1u << 8, // legacy save-trigger → DirtyWindowPlacements
977 DirtyAutotilePending = 1u << 9, // legacy save-trigger → DirtyWindowPlacements
978 // bit 10 reserved (was DirtyFloatRestores, removed with the FloatRestoreQueues key)
979 DirtyWindowPlacements = 1u << 11,
980 DirtyAll = 0xFFFu, // covers bits 0-11 incl. the reserved bit 10
981 };
982 using DirtyMask = uint32_t;
983
991 void markDirty(DirtyMask fields);
992
996
1000 {
1001 return m_dirtyMask;
1002 }
1003
1008
1009Q_SIGNALS:
1010 // WARNING: AutotileEngine connects to this signal via string-based SIGNAL/SLOT
1011 // (it holds IWindowTrackingService*, not WindowTrackingService*, so PMF connect
1012 // is unavailable). Renaming this signal will silently break autotile zone tracking.
1013 void windowZoneChanged(const QString& windowId, const QString& zoneId);
1014
1019
1020private:
1021 // Minimum visible area for geometry validation
1022 static constexpr int MinVisibleWidth = 100;
1023 static constexpr int MinVisibleHeight = 100;
1024
1025 // Helpers
1026 //
1027 // scheduleSaveState() wraps markDirty(DirtyAll). Retained as the
1028 // default entry point for mutators that haven't been updated to
1029 // declare which specific fields they touch — marking everything dirty
1030 // is behaviorally equivalent to the pre-refactor code. Hot-path
1031 // mutators (assign/unassign zone, storePreTileGeometry, etc.) should
1032 // call markDirty() directly with a narrow mask so the next save
1033 // only re-serializes the fields that actually changed.
1034 void scheduleSaveState(DirtyMask fields = DirtyAll);
1035 bool isGeometryOnScreen(const QRect& geometry) const;
1036 QRect adjustGeometryToScreen(const QRect& geometry) const;
1037 PhosphorZones::Zone* findZoneById(const QString& zoneId) const;
1038
1040 template<typename Func>
1041 auto preFloatLookup(const QString& windowId, Func&& getter) const -> decltype(getter(windowId));
1042
1044 void validateLastUsedZone(const QString& targetScreen);
1045
1048 static QString findNearestVirtualScreen(const QStringList& vsIds, int oldIndex);
1049
1052 struct ZoneLookupResult
1053 {
1054 PhosphorZones::Zone* zone = nullptr;
1055 PhosphorZones::Layout* layout = nullptr;
1056 };
1057 ZoneLookupResult findZoneInAllLayouts(const QUuid& zoneUuid) const;
1058
1059public:
1062 QString resolveEffectiveScreenId(const QString& screenId) const override;
1063
1066 QRect resolveZoneGeometry(const QStringList& zoneIds, const QString& screenId) const override;
1067
1068 QString findEmptyZoneInLayout(PhosphorZones::Layout* layout, const QString& screenId,
1069 int desktopFilter = 0) const override;
1070
1071 // Zone sort / position-map helpers now live in PhosphorZones::LayoutUtils.
1072 // Call PhosphorZones::LayoutUtils::sortZonesByNumber / buildZonePositionMap directly.
1073
1084 QSet<QUuid> buildOccupiedZoneSet(const QString& screenFilter = QString(), int desktopFilter = 0) const override;
1085
1094 QString currentAppIdFor(const QString& anyWindowId) const override;
1095
1102 QString canonicalizeForLookup(const QString& rawWindowId) const;
1103
1104private:
1105 // Dependencies
1106 PhosphorZones::LayoutRegistry* m_layoutManager;
1107 PhosphorZones::IZoneDetector* m_zoneDetector;
1108 PhosphorSnapEngine::SnapState* m_snapState = nullptr;
1109 PhosphorEngine::WindowPlacementStore m_placementStore;
1110 IGeometryResolver* m_geometryResolver;
1111 PlacementConfig m_config;
1112 PhosphorWorkspaces::VirtualDesktopManager* m_virtualDesktopManager;
1113 // Shared registry for current-class queries and canonical key translation.
1114 // Not owned. Null in unit tests.
1115 PhosphorEngine::WindowRegistry* m_windowRegistry = nullptr;
1116 PhosphorScreens::ScreenManager* m_screenManager = nullptr;
1117 QPointer<PhosphorEngine::PlacementEngineBase> m_snapEngine;
1118 AutotileModePredicate m_autotileModePredicate{};
1119 AutotileTiledPredicate m_autotileTiledPredicate{};
1120
1121 // Floating windows: full windowId at runtime, appId for session-restored entries
1122 // Converted from windowId to appId on window close for persistence.
1123 //
1124 // LEGACY FALLBACK ONLY: used when no per-engine resolver/writer is wired
1125 // (unit tests / early init). In production the daemon injects
1126 // m_engineFloatResolver / m_engineFloatWriter and this set is never read or
1127 // written by isWindowFloating / setWindowFloating.
1128 QSet<QString> m_floatingWindows;
1129
1130 // Daemon-injected per-engine float reader/writer/lister. See setEngineFloatResolver.
1131 EngineFloatResolver m_engineFloatResolver{};
1132 EngineFloatWriter m_engineFloatWriter{};
1133 EngineFloatLister m_engineFloatLister{};
1134
1135 // Session persistence: consumption queue (appId -> list of pending restores, consumed FIFO)
1136 QHash<QString, QList<PendingRestore>> m_pendingRestoreQueues;
1137
1138 // Optional daemon-injected gate consulted before recording a PendingRestore
1139 // on windowClosed. When unset (e.g. unit tests), every context is treated
1140 // as active and the historical write-everything behavior is preserved.
1141 ShouldTrackPredicate m_shouldTrackPredicate{};
1142
1143 // Pre-float zone and screen state is owned by SnapState (authoritative store).
1144 // WTS preFloat getter methods add appId-fallback queries for session-restored
1145 // entries keyed by appId. SnapState itself uses windowId-only keys.
1146
1147 // Sticky window states
1148 QHash<QString, bool> m_windowStickyStates;
1149
1150 QVector<ResnapEntry> m_resnapBuffer;
1151
1152 // Delta-persistence dirty mask. Initial value DirtyAll forces the first
1153 // save after daemon startup to serialize every field. Cleared by
1154 // loadState() once in-memory state mirrors the disk file.
1155 DirtyMask m_dirtyMask = DirtyAll;
1156
1157 // Note: No save timer - persistence handled by WindowTrackingAdaptor via KConfig
1158 // Service emits stateChanged() signal when state needs saving
1159};
1160
1161} // namespace PhosphorPlacement
Definition IWindowTrackingService.h:34
Abstract base class for placement engines.
Definition PlacementEngineBase.h:30
The single source of truth for window restore state in the unified model.
Definition WindowPlacementStore.h:34
Definition WindowRegistry.h:82
Definition IGeometryResolver.h:17
Window-zone tracking service (business logic layer)
Definition WindowTrackingService.h:80
void recordFreeGeometry(const QString &windowId, const QString &screenId, const QRect &geometry, bool overwrite) override
Write the window's shared free/float geometry into the unified record (the single float-back store).
const QHash< QString, QList< PendingRestore > > & pendingRestoreQueues() const override
Get pending restore queues (consumption queue: appId -> list of pending restores)
Definition WindowTrackingService.h:872
bool consumePendingAssignment(const QString &windowId) override
Pop the oldest pending restore entry for this window's appId.
QString zoneForWindow(const QString &windowId) const override
Get the primary zone ID for a window.
bool isWindowInAutotileMode(const QString &windowId) const
True if the window's CURRENT screen mode is autotile.
Definition WindowTrackingService.h:224
void markDirty(DirtyMask fields)
OR the given fields into the dirty mask AND emit stateChanged.
PhosphorProtocol::EmptyZoneList getEmptyZones(const QString &screenId) const
Get typed list of all empty zones for Snap Assist continuation.
const QHash< QString, QStringList > & zoneAssignments() const override
Get all zone assignments for persistence.
bool isWindowSnapped(const QString &windowId) const override
Check if a window is assigned to any zone.
void assignWindowToZone(const QString &windowId, const QString &zoneId, const QString &screenId, int virtualDesktop) override
Assign a window to a zone.
void clearResnapBuffer()
Clear the resnap buffer.
Definition WindowTrackingService.h:701
QString screenForWindow(const QString &windowId, const QString &defaultScreen) const override
Same, but returns defaultScreen when the window has no screen assignment — the canonicalizing replace...
void recordSnapIntent(const QString &windowId, bool wasUserInitiated) override
Record that a window class was user-snapped.
QVector< ResnapEntry > takeResnapBuffer() override
Definition WindowTrackingService.h:877
bool isWindowFloating(const QString &windowId) const override
Check if a window is floating (excluded from snapping)
QString findEmptyZoneInLayout(PhosphorZones::Layout *layout, const QString &screenId, int desktopFilter=0) const override
void setFloatingWindows(const QSet< QString > &windows)
Set floating windows (loaded from KConfig by adaptor)
Definition WindowTrackingService.h:918
QString preFloatScreen(const QString &windowId) const override
Get the screen name where the window was snapped before floating.
QStringList buildZoneOrderedWindowList(const QString &screenId) const
Build a zone-ordered window list for a screen from current zone assignments.
bool isWindowSticky(const QString &windowId) const override
Check if window is sticky.
void clearPreFloatZoneForWindow(const QString &windowId)
Clear pre-float zone for a specific window only (not appId)
uint32_t DirtyMask
Definition WindowTrackingService.h:982
DirtyMask peekDirty() const
Return the current dirty mask without clearing.
Definition WindowTrackingService.h:999
const PhosphorEngine::WindowPlacementStore & placementStore() const
Definition WindowTrackingService.h:132
void setPreFloatScreenAssignments(const QHash< QString, QString > &assignments)
void clearPreFloatZone(const QString &windowId)
Clear pre-float zone after restore (both windowId and appId keys)
void setSnapEngine(PhosphorEngine::PlacementEngineBase *engine)
Wire the snap-mode placement engine.
Definition WindowTrackingService.h:191
QString currentAppIdFor(const QString &anyWindowId) const override
Current app class for a windowId, preferring the live registry.
QSet< QString > physicalScreensWithStaleVirtualAssignments(const QSet< QString > &subdividedPhysicalIds) const
Find physical screens whose state still references virtual ids, excluding screens the caller knows ar...
bool isAutoSnapped(const QString &windowId) const
Check if a window was auto-snapped.
void setPendingRestoreQueues(const QHash< QString, QList< PendingRestore > > &queues)
Set pending restore queues (loaded from KConfig by adaptor)
Definition WindowTrackingService.h:900
void unassignWindow(const QString &windowId) override
Remove window from its assigned zone.
bool isWindowAutotileTiled(const QString &windowId) const
True if the autotile engine reports the window actively tiled.
Definition WindowTrackingService.h:251
QObject * asQObject() override
Definition WindowTrackingService.h:101
void setPreFloatZoneAssignments(const QHash< QString, QStringList > &assignments)
Set pre-float zone assignments (loaded from KConfig by adaptor)
void migrateScreenAssignmentsToVirtual(const QString &physicalScreenId, const QStringList &virtualScreenIds, PhosphorScreens::ScreenManager *mgr)
Migrate window screen assignments from physical to virtual screen IDs.
PhosphorScreens::ScreenManager * screenManager() const override
Definition WindowTrackingService.h:264
QString preFloatZone(const QString &windowId) const
Get primary zone to restore to when unfloating.
void setEngineFloatResolver(EngineFloatResolver resolver)
Definition WindowTrackingService.h:425
QHash< QString, QRect > updatedWindowGeometries() const
Get updated geometries for all tracked windows.
bool clearAutoSnapped(const QString &windowId) override
Clear auto-snapped flag for a window.
QRect zoneGeometry(const QString &zoneId, const QString &screenId=QString()) const override
Get geometry for a zone on a specific screen.
QString lastUsedScreenName() const
Screen name companion of the last-used-zone tracking.
int pruneStaleAssignments(const QSet< QString > &aliveWindowIds)
Remove zone/screen/desktop assignments for windows not in the alive set.
void populateResnapBufferForAllScreens(const QSet< QString > &excludeScreens={}, const QSet< QString > &includeScreens={}, int desktopFilter=0)
Populate the resnap buffer for all screens independently.
std::function< void(const QString &windowId, bool floating)> EngineFloatWriter
Definition WindowTrackingService.h:422
std::optional< QRect > validateGeometryForScreen(const QRect &geo, const QString &savedScreen, const QString &currentScreenName) const
Validate and adjust a saved geometry for screen-aware restore.
void setActiveAssignments(const QHash< QString, QStringList > &zones, const QHash< QString, QString > &screens, const QHash< QString, int > &desktops)
Set active zone/screen/desktop assignments (loaded from KConfig by adaptor)
QStringList snappedWindows() const
Get all snapped windows.
QString lastUsedZoneId() const
Get last used zone ID.
WindowTrackingService(PhosphorZones::LayoutRegistry *layoutManager, PhosphorZones::IZoneDetector *zoneDetector, PhosphorScreens::ScreenManager *screenManager, PhosphorWorkspaces::VirtualDesktopManager *vdm, IGeometryResolver *geometryResolver=nullptr, PlacementConfig config={}, QObject *parent=nullptr)
bool clearFloatingForSnap(const QString &windowId) override
Clear floating state when snapping a floating window.
void assignWindowToZones(const QString &windowId, const QStringList &zoneIds, const QString &screenId, int virtualDesktop) override
Assign a window to multiple zones (multi-zone snap)
void recordFloatingClose(const QString &windowId, const QString &screenId, const QRect &geometry)
Authoritative float-back capture for a window closing on screenId.
QStringList recordedSnapZones(const QString &windowId) const override
Live snap zones if present, else the durable placement-record snap slot.
QStringList preFloatZones(const QString &windowId) const override
Get all zones to restore to when unfloating (multi-zone support)
void setEngineFloatLister(EngineFloatLister lister)
Aggregates both engines' floating windows for the engine-agnostic floatingWindows() enumeration.
Definition WindowTrackingService.h:435
DirtyField
Definition WindowTrackingService.h:966
void clearDirty()
Clear every dirty bit.
void windowZoneChanged(const QString &windowId, const QString &zoneId)
void setAutotileTiledPredicate(AutotileTiledPredicate predicate)
Definition WindowTrackingService.h:244
QRect resolveZoneGeometry(const QStringList &zoneIds, const QString &screenId) const override
Resolve zone geometry: combined geometry for multi-zone, single for single zone.
PhosphorEngine::WindowPlacementStore & placementStore() override
The unified, engine-agnostic placement store (one WindowPlacement record per window).
Definition WindowTrackingService.h:128
void migrateScreenAssignmentsFromVirtual(const QString &physicalScreenId)
Reverse migration: virtual screen IDs → physical screen ID.
int lastUsedDesktop() const
Virtual-desktop companion of the last-used-zone tracking.
const QHash< QString, int > & desktopAssignments() const
Get all desktop assignments for persistence.
QStringList floatingWindows() const
Get all floating window IDs.
PhosphorEngine::WindowRegistry * windowRegistry() const
Accessor for consumers that need direct access (effect, adaptor).
Definition WindowTrackingService.h:259
std::optional< QRect > validatedUnmanagedGeometry(const QString &windowId, const QString &screenId, bool exactOnly=false) const override
Look up a window's free (unmanaged) geometry from the unified WindowPlacementStore,...
void setLastUsedZone(const QString &zoneId, const QString &screenId, const QString &zoneClass, int desktop)
Set last used zone info (loaded from KConfig by adaptor)
void setAutotileModePredicate(AutotileModePredicate predicate)
Definition WindowTrackingService.h:210
QString canonicalizeForLookup(const QString &rawWindowId) const
Canonicalize for read-only callers (no map mutation).
QHash< QString, PendingRestoreTarget > pendingRestoreGeometries() const
Pre-compute zone geometries for all pending restore entries.
void setShouldTrackPredicate(ShouldTrackPredicate predicate)
Inject a context-active predicate.
Definition WindowTrackingService.h:175
void unsnapForFloat(const QString &windowId) override
Unsnap window for floating (saves zone for later restore)
QString findEmptyZone(const QString &screenId=QString()) const override
Find the first empty zone in the layout for a screen.
DirtyMask takeDirty()
Return the current dirty mask, clearing it atomically.
QString screenForWindow(const QString &windowId) const override
The screen a window is assigned to, or empty when it has none.
std::function< QStringList()> EngineFloatLister
Definition WindowTrackingService.h:423
void setWindowFloating(const QString &windowId, bool floating) override
Set window floating state.
QSet< QUuid > buildOccupiedZoneSet(const QString &screenFilter=QString(), int desktopFilter=0) const override
Build set of occupied zone UUIDs, optionally filtered by screen and virtual desktop.
void updateLastUsedZone(const QString &zoneId, const QString &screenId, const QString &windowClass, int virtualDesktop) override
Update last used zone tracking.
void onLayoutChanged()
Handle layout change - validate/clear stale zone assignments.
QRect multiZoneGeometry(const QStringList &zoneIds, const QString &screenId=QString()) const
Get combined geometry for multiple zones on a specific screen.
const QHash< QString, QString > & preFloatScreenAssignments() const
void setWindowSticky(const QString &windowId, bool sticky)
Record whether a window is sticky (on all desktops)
void clearFreeGeometry(const QString &windowId) override
Clear a window's shared free/float geometry from the record.
void setWindowRegistry(PhosphorEngine::WindowRegistry *registry)
Wire up the shared WindowRegistry.
Definition WindowTrackingService.h:116
const QHash< QString, QStringList > & preFloatZoneAssignments() const
Get pre-float zone assignments for persistence.
void setUserSnappedClasses(const QSet< QString > &classes)
Set user-snapped classes (loaded from KConfig by adaptor)
const QHash< QString, QString > & screenAssignments() const override
Get all screen assignments for persistence.
void stateChanged()
Emitted when state needs to be saved.
QStringList windowsInZone(const QString &zoneId) const override
Get all windows in a specific zone.
void windowClosed(const QString &windowId, PhosphorEngine::WindowKind kind=PhosphorEngine::WindowKind::Unknown)
Clean up all tracking data for a closed window.
std::function< bool(const QString &windowId)> AutotileModePredicate
Predicate: is the window currently in Autotile mode?
Definition WindowTrackingService.h:209
std::function< bool(const QString &windowId)> EngineFloatResolver
Per-engine float resolver/writer.
Definition WindowTrackingService.h:421
void setSnapState(PhosphorSnapEngine::SnapState *state)
Definition WindowTrackingService.h:121
const QSet< QString > & userSnappedClasses() const
Get user-snapped classes.
QStringList zonesForWindow(const QString &windowId) const override
Get all zone IDs for a window (multi-zone support)
const PlacementConfig & config() const
The placement config installed at construction.
Definition WindowTrackingService.h:96
void markAsAutoSnapped(const QString &windowId)
Mark a window as auto-snapped.
void retagLastUsedZoneClass(const QString &newClass)
Update the last-used-zone class tag without touching zone/screen.
PhosphorEngine::PlacementEngineBase * snapEngine() const
Definition WindowTrackingService.h:196
QString lastUsedZoneClass() const
App class string stamped on the last-used-zone tracking.
QString resolveEffectiveScreenId(const QString &screenId) const override
Resolve a screen ID to an effective screen ID, falling back to the physical screen ID if a virtual sc...
std::function< bool(const QString &windowId)> AutotileTiledPredicate
Predicate: is the window ACTIVELY TILED by the autotile engine right now (engine-owned,...
Definition WindowTrackingService.h:243
void setEngineFloatWriter(EngineFloatWriter writer)
Definition WindowTrackingService.h:429
std::function< bool(const QString &screenId, int virtualDesktop)> ShouldTrackPredicate
Predicate type for "is this snap-mode context active?".
Definition WindowTrackingService.h:155
Centralized screen-topology service.
Definition Manager.h:75
Per-screen snap placement state.
Definition SnapState.h:33
Definition VirtualDesktopManager.h:19
Abstract interface for zone detection + highlight lifecycle.
Definition IZoneDetector.h:84
Manual zone-layout registry + per-context assignment store.
Definition LayoutRegistry.h:78
Represents a collection of zones that form a layout.
Definition Layout.h:40
Represents a single zone within a layout.
Definition Zone.h:44
Definition EngineTypes.h:13
WindowKind
Coarse structural classification for the snap-restore consume gate.
Definition EngineTypes.h:39
Definition IGeometryResolver.h:14
constexpr QLatin1String LayoutRegistry("org.plasmazones.LayoutRegistry")
QList< EmptyZoneEntry > EmptyZoneList
Definition ZoneTypes.h:58
Definition IWindowTrackingService.h:27
Definition WindowTrackingService.h:38
Definition WindowTrackingService.h:46
Definition IWindowTrackingService.h:23
Definition EngineTypes.h:73
Definition EngineTypes.h:65
Definition PlacementConfig.h:11
Pre-computed snap restore target: zone geometry + the saved screen it lives on.
Definition WindowTrackingService.h:801
QString screenId
Definition WindowTrackingService.h:803
QRect geometry
Definition WindowTrackingService.h:802