Window-zone tracking service (business logic layer) More...
#include <phosphor-placement/include/PhosphorPlacement/WindowTrackingService.h>
Classes | |
| struct | PendingRestoreTarget |
| Pre-computed snap restore target: zone geometry + the saved screen it lives on. More... | |
Public Types | |
| enum | DirtyField : uint32_t { DirtyNone = 0 , DirtyActiveLayoutId = 1u << 0 , DirtyZoneAssignments = 1u << 1 , DirtyPendingRestores = 1u << 2 , DirtyPreTileGeometries = 1u << 3 , DirtyLastUsedZone = 1u << 4 , DirtyPreFloatZones = 1u << 5 , DirtyPreFloatScreens = 1u << 6 , DirtyUserSnapped = 1u << 7 , DirtyAutotileOrders = 1u << 8 , DirtyAutotilePending = 1u << 9 , DirtyWindowPlacements = 1u << 11 , DirtyAll = 0xFFFu } |
| using | ShouldTrackPredicate = std::function< bool(const QString &screenId, int virtualDesktop)> |
| Predicate type for "is this snap-mode context active?". | |
| using | AutotileModePredicate = std::function< bool(const QString &windowId)> |
| Predicate: is the window currently in Autotile mode? | |
| using | AutotileTiledPredicate = std::function< bool(const QString &windowId)> |
| Predicate: is the window ACTIVELY TILED by the autotile engine right now (engine-owned, non-floating)? | |
| using | EngineFloatResolver = std::function< bool(const QString &windowId)> |
| Per-engine float resolver/writer. | |
| using | EngineFloatWriter = std::function< void(const QString &windowId, bool floating)> |
| using | EngineFloatLister = std::function< QStringList()> |
| using | PendingRestore = PhosphorEngine::PendingRestore |
| using | ResnapEntry = PhosphorEngine::ResnapEntry |
| using | DirtyMask = uint32_t |
Signals | |
| void | windowZoneChanged (const QString &windowId, const QString &zoneId) |
| void | stateChanged () |
| Emitted when state needs to be saved. | |
Public Member Functions | |
| WindowTrackingService (PhosphorZones::LayoutRegistry *layoutManager, PhosphorZones::IZoneDetector *zoneDetector, PhosphorScreens::ScreenManager *screenManager, PhosphorWorkspaces::VirtualDesktopManager *vdm, IGeometryResolver *geometryResolver=nullptr, PlacementConfig config={}, QObject *parent=nullptr) | |
| const PlacementConfig & | config () const |
| The placement config installed at construction. | |
| QObject * | asQObject () override |
| ~WindowTrackingService () override | |
| void | setWindowRegistry (PhosphorEngine::WindowRegistry *registry) |
| Wire up the shared WindowRegistry. | |
| void | setSnapState (PhosphorSnapEngine::SnapState *state) |
| PhosphorEngine::WindowPlacementStore & | placementStore () override |
| The unified, engine-agnostic placement store (one WindowPlacement record per window). | |
| const PhosphorEngine::WindowPlacementStore & | placementStore () const |
| void | setShouldTrackPredicate (ShouldTrackPredicate predicate) |
| Inject a context-active predicate. | |
| void | setSnapEngine (PhosphorEngine::PlacementEngineBase *engine) |
| Wire the snap-mode placement engine. | |
| PhosphorEngine::PlacementEngineBase * | snapEngine () const |
| void | setAutotileModePredicate (AutotileModePredicate predicate) |
| bool | isWindowInAutotileMode (const QString &windowId) const |
| True if the window's CURRENT screen mode is autotile. | |
| void | setAutotileTiledPredicate (AutotileTiledPredicate predicate) |
| bool | isWindowAutotileTiled (const QString &windowId) const |
| True if the autotile engine reports the window actively tiled. | |
| PhosphorEngine::WindowRegistry * | windowRegistry () const |
| Accessor for consumers that need direct access (effect, adaptor). | |
| PhosphorScreens::ScreenManager * | screenManager () const override |
| void | assignWindowToZone (const QString &windowId, const QString &zoneId, const QString &screenId, int virtualDesktop) override |
| Assign a window to a zone. | |
| void | assignWindowToZones (const QString &windowId, const QStringList &zoneIds, const QString &screenId, int virtualDesktop) override |
| Assign a window to multiple zones (multi-zone snap) | |
| void | unassignWindow (const QString &windowId) override |
| Remove window from its assigned zone. | |
| QString | zoneForWindow (const QString &windowId) const override |
| Get the primary zone ID for a window. | |
| QStringList | zonesForWindow (const QString &windowId) const override |
| Get all zone IDs for a window (multi-zone support) | |
| QString | screenForWindow (const QString &windowId) const override |
| The screen a window is assigned to, or empty when it has none. | |
| QString | screenForWindow (const QString &windowId, const QString &defaultScreen) const override |
Same, but returns defaultScreen when the window has no screen assignment — the canonicalizing replacement for screenAssignments().value(windowId, defaultScreen). | |
| QStringList | windowsInZone (const QString &zoneId) const override |
| Get all windows in a specific zone. | |
| QStringList | snappedWindows () const |
| Get all snapped windows. | |
| int | pruneStaleAssignments (const QSet< QString > &aliveWindowIds) |
| Remove zone/screen/desktop assignments for windows not in the alive set. | |
| bool | isWindowSnapped (const QString &windowId) const override |
| Check if a window is assigned to any zone. | |
| std::optional< QRect > | validateGeometryForScreen (const QRect &geo, const QString &savedScreen, const QString ¤tScreenName) const |
| Validate and adjust a saved geometry for screen-aware restore. | |
| 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, with appId fallback, and validate it. | |
| 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). | |
| void | recordFloatingClose (const QString &windowId, const QString &screenId, const QRect &geometry) |
Authoritative float-back capture for a window closing on screenId. | |
| void | clearFreeGeometry (const QString &windowId) override |
| Clear a window's shared free/float geometry from the record. | |
| void | setEngineFloatResolver (EngineFloatResolver resolver) |
| void | setEngineFloatWriter (EngineFloatWriter writer) |
| void | setEngineFloatLister (EngineFloatLister lister) |
| Aggregates both engines' floating windows for the engine-agnostic floatingWindows() enumeration. | |
| bool | isWindowFloating (const QString &windowId) const override |
| Check if a window is floating (excluded from snapping) | |
| void | setWindowFloating (const QString &windowId, bool floating) override |
| Set window floating state. | |
| QStringList | floatingWindows () const |
| Get all floating window IDs. | |
| void | unsnapForFloat (const QString &windowId) override |
| Unsnap window for floating (saves zone for later restore) | |
| QString | preFloatZone (const QString &windowId) const |
| Get primary zone to restore to when unfloating. | |
| QStringList | preFloatZones (const QString &windowId) const override |
| Get all zones to restore to when unfloating (multi-zone support) | |
| QString | preFloatScreen (const QString &windowId) const override |
| Get the screen name where the window was snapped before floating. | |
| void | clearPreFloatZone (const QString &windowId) |
| Clear pre-float zone after restore (both windowId and appId keys) | |
| void | clearPreFloatZoneForWindow (const QString &windowId) |
| Clear pre-float zone for a specific window only (not appId) | |
| bool | clearFloatingForSnap (const QString &windowId) override |
| Clear floating state when snapping a floating window. | |
| void | setWindowSticky (const QString &windowId, bool sticky) |
| Record whether a window is sticky (on all desktops) | |
| bool | isWindowSticky (const QString &windowId) const override |
| Check if window is sticky. | |
| void | recordSnapIntent (const QString &windowId, bool wasUserInitiated) override |
| Record that a window class was user-snapped. | |
| QString | lastUsedZoneId () const |
| Get last used zone ID. | |
| QString | lastUsedZoneClass () const |
| App class string stamped on the last-used-zone tracking. | |
| QString | lastUsedScreenName () const |
| Screen name companion of the last-used-zone tracking. | |
| int | lastUsedDesktop () const |
| Virtual-desktop companion of the last-used-zone tracking. | |
| void | retagLastUsedZoneClass (const QString &newClass) |
| Update the last-used-zone class tag without touching zone/screen. | |
| void | updateLastUsedZone (const QString &zoneId, const QString &screenId, const QString &windowClass, int virtualDesktop) override |
| Update last used zone tracking. | |
| void | markAsAutoSnapped (const QString &windowId) |
| Mark a window as auto-snapped. | |
| bool | isAutoSnapped (const QString &windowId) const |
| Check if a window was auto-snapped. | |
| bool | clearAutoSnapped (const QString &windowId) override |
| Clear auto-snapped flag for a window. | |
| bool | consumePendingAssignment (const QString &windowId) override |
| Pop the oldest pending restore entry for this window's appId. | |
| QString | findEmptyZone (const QString &screenId=QString()) const override |
| Find the first empty zone in the layout for a screen. | |
| PhosphorProtocol::EmptyZoneList | getEmptyZones (const QString &screenId) const |
| Get typed list of all empty zones for Snap Assist continuation. | |
| QRect | zoneGeometry (const QString &zoneId, const QString &screenId=QString()) const override |
| Get geometry for a zone on a specific screen. | |
| QRect | multiZoneGeometry (const QStringList &zoneIds, const QString &screenId=QString()) const |
| Get combined geometry for multiple zones on a specific screen. | |
| void | populateResnapBufferForAllScreens (const QSet< QString > &excludeScreens={}, const QSet< QString > &includeScreens={}, int desktopFilter=0) |
| Populate the resnap buffer for all screens independently. | |
| void | clearResnapBuffer () |
| Clear the resnap buffer. | |
| QStringList | buildZoneOrderedWindowList (const QString &screenId) const |
| Build a zone-ordered window list for a screen from current zone assignments. | |
| void | migrateScreenAssignmentsToVirtual (const QString &physicalScreenId, const QStringList &virtualScreenIds, PhosphorScreens::ScreenManager *mgr) |
| Migrate window screen assignments from physical to virtual screen IDs. | |
| void | migrateScreenAssignmentsFromVirtual (const QString &physicalScreenId) |
| Reverse migration: virtual screen IDs → physical screen ID. | |
| QSet< QString > | physicalScreensWithStaleVirtualAssignments (const QSet< QString > &subdividedPhysicalIds) const |
| Find physical screens whose state still references virtual ids, excluding screens the caller knows are still subdivided. | |
| QHash< QString, QRect > | updatedWindowGeometries () const |
| Get updated geometries for all tracked windows. | |
| QHash< QString, PendingRestoreTarget > | pendingRestoreGeometries () const |
| Pre-compute zone geometries for all pending restore entries. | |
| void | windowClosed (const QString &windowId, PhosphorEngine::WindowKind kind=PhosphorEngine::WindowKind::Unknown) |
| Clean up all tracking data for a closed window. | |
| void | onLayoutChanged () |
| Handle layout change - validate/clear stale zone assignments. | |
| const QHash< QString, QStringList > & | zoneAssignments () const override |
| Get all zone assignments for persistence. | |
| QStringList | recordedSnapZones (const QString &windowId) const override |
| Live snap zones if present, else the durable placement-record snap slot. | |
| const QHash< QString, QString > & | screenAssignments () const override |
| Get all screen assignments for persistence. | |
| const QHash< QString, int > & | desktopAssignments () const |
| Get all desktop assignments for persistence. | |
| const QHash< QString, QList< PendingRestore > > & | pendingRestoreQueues () const override |
| Get pending restore queues (consumption queue: appId -> list of pending restores) | |
| QVector< ResnapEntry > | takeResnapBuffer () override |
| const QSet< QString > & | userSnappedClasses () const |
| Get user-snapped classes. | |
| 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) | |
| void | setPendingRestoreQueues (const QHash< QString, QList< PendingRestore > > &queues) |
| Set pending restore queues (loaded from KConfig by adaptor) | |
| void | setUserSnappedClasses (const QSet< QString > &classes) |
| Set user-snapped classes (loaded from KConfig by adaptor) | |
| void | setLastUsedZone (const QString &zoneId, const QString &screenId, const QString &zoneClass, int desktop) |
| Set last used zone info (loaded from KConfig by adaptor) | |
| void | setFloatingWindows (const QSet< QString > &windows) |
| Set floating windows (loaded from KConfig by adaptor) | |
| const QHash< QString, QStringList > & | preFloatZoneAssignments () const |
| Get pre-float zone assignments for persistence. | |
| const QHash< QString, QString > & | preFloatScreenAssignments () const |
| void | setPreFloatZoneAssignments (const QHash< QString, QStringList > &assignments) |
| Set pre-float zone assignments (loaded from KConfig by adaptor) | |
| void | setPreFloatScreenAssignments (const QHash< QString, QString > &assignments) |
| void | markDirty (DirtyMask fields) |
| OR the given fields into the dirty mask AND emit stateChanged. | |
| DirtyMask | takeDirty () |
| Return the current dirty mask, clearing it atomically. | |
| DirtyMask | peekDirty () const |
| Return the current dirty mask without clearing. | |
| void | clearDirty () |
| Clear every dirty bit. | |
| 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 screen no longer exists in the current configuration. | |
| QRect | resolveZoneGeometry (const QStringList &zoneIds, const QString &screenId) const override |
| Resolve zone geometry: combined geometry for multi-zone, single for single zone. | |
| QString | findEmptyZoneInLayout (PhosphorZones::Layout *layout, const QString &screenId, int desktopFilter=0) const override |
| 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. | |
| QString | currentAppIdFor (const QString &anyWindowId) const override |
| Current app class for a windowId, preferring the live registry. | |
| QString | canonicalizeForLookup (const QString &rawWindowId) const |
| Canonicalize for read-only callers (no map mutation). | |
Public Member Functions inherited from PhosphorEngine::IWindowTrackingService | |
| virtual | ~IWindowTrackingService ()=default |
Window-zone tracking service (business logic layer)
This service encapsulates all window tracking business logic that was previously in WindowTrackingAdaptor. Following the separation-of-concerns principle, it handles:
The WindowTrackingAdaptor becomes a thin D-Bus facade that delegates all business logic to this service.
Design benefits:
| using PhosphorPlacement::WindowTrackingService::AutotileModePredicate = std::function<bool(const QString& windowId)> |
Predicate: is the window currently in Autotile mode?
Injected by the daemon (engine-/settings-agnostic LGPL boundary). The single owning-engine signal used by the capture funnel and float routing (see isWindowInAutotileMode). When unset, every window is treated as snap-mode.
| using PhosphorPlacement::WindowTrackingService::AutotileTiledPredicate = std::function<bool(const QString& windowId)> |
Predicate: is the window ACTIVELY TILED by the autotile engine right now (engine-owned, non-floating)?
Injected by the daemon (same LGPL-boundary pattern as AutotileModePredicate). Distinct from the MODE predicate: a fresh spawn on an autotile screen is in autotile mode but not yet tiled — its frame is a genuine free geometry — while a tiled window's frame IS the tile rect and must never be recorded as a float-back. recordFreeGeometry uses this to refuse tiled frames the same way it refuses snapped frames; it complements the effect-side capture guard, which cannot help on an effect reload (the effect's border tracking starts empty while this engine still holds the tiling state).
| using PhosphorPlacement::WindowTrackingService::DirtyMask = uint32_t |
| using PhosphorPlacement::WindowTrackingService::EngineFloatLister = std::function<QStringList()> |
| using PhosphorPlacement::WindowTrackingService::EngineFloatResolver = std::function<bool(const QString& windowId)> |
Per-engine float resolver/writer.
Float state is genuinely per-engine: a window floated in autotile mode is NOT floating in snapping mode and vice versa. The authoritative store lives in each engine (SnapState::isFloating / TilingState::isFloating), keyed by the screen's current mode. The placement library is intentionally engine- and settings-agnostic (LGPL boundary), so the daemon injects a resolver (reader) and writer that route to the engine owning the window's CURRENT screen mode.
When unset (unit tests / early init before the engines are wired), the service falls back to the legacy shared m_floatingWindows set so existing single-engine tests keep their historical behaviour.
| using PhosphorPlacement::WindowTrackingService::EngineFloatWriter = std::function<void(const QString& windowId, bool floating)> |
| using PhosphorPlacement::WindowTrackingService::ShouldTrackPredicate = std::function<bool(const QString& screenId, int virtualDesktop)> |
Predicate type for "is this snap-mode context active?".
Receives the (screenId, virtualDesktop) tuple recorded for the closing window. Returns true when the context is ACTIVE (i.e. tracking should proceed); false when the context is disabled via the snapping-disabled monitor / desktop lists.
No activity parameter: SnapState does not track per-window activity, so the placement library has nothing to thread through. If activity-mode filtering grows here later, extend the signature then — until then the dead slot would be misleading.
The placement library is intentionally settings-agnostic (LGPL boundary), so the daemon adaptor injects the predicate. When unset, the service behaves as if every context is active — the historical default that unit tests rely on.
| enum PhosphorPlacement::WindowTrackingService::DirtyField : uint32_t |
|
explicit |
|
override |
|
inlineoverridevirtual |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Assign a window to a zone.
| windowId | Full window ID |
| zoneId | PhosphorZones::Zone UUID string |
| screenId | Screen where the zone is located |
| virtualDesktop | Virtual desktop number (1-based, 0 = all) |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Assign a window to multiple zones (multi-zone snap)
| windowId | Full window ID |
| zoneIds | List of zone UUID strings (first is primary) |
| screenId | Screen where the zones are located |
| virtualDesktop | Virtual desktop number (1-based, 0 = all) |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Build set of occupied zone UUIDs, optionally filtered by screen and virtual desktop.
Uses PhosphorScreens::ScreenIdentity::screensMatch() for format-agnostic screen comparison.
| desktopFilter | When > 0, only counts assignments whose window desktop matches (or is 0 = pinned/all-desktops). Pass the current virtual desktop for snap-assist / empty-zone queries so windows parked on other desktops do not make zones appear occupied — this mirrors the filtering done by SnapAssistHandler::buildCandidates() in the KWin effect, keeping the "occupied" and "candidate" definitions symmetric. |
Implements PhosphorEngine::IWindowTrackingService.
| QStringList PhosphorPlacement::WindowTrackingService::buildZoneOrderedWindowList | ( | const QString & | screenId | ) | const |
Build a zone-ordered window list for a screen from current zone assignments.
Iterates all window-zone assignments for the given screen, resolves each window's primary zone number from the active layout, and returns the window IDs sorted by zone number ascending. Used to pre-seed autotile window order during transitions.
| screenId | Screen identifier to filter windows by |
| QString PhosphorPlacement::WindowTrackingService::canonicalizeForLookup | ( | const QString & | rawWindowId | ) | const |
Canonicalize for read-only callers (no map mutation).
Delegates to the registry's canonicalizeForLookup when available. Unit tests that don't attach a registry get a passthrough.
|
overridevirtual |
Clear auto-snapped flag for a window.
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::clearDirty | ( | ) |
Clear every dirty bit.
Called from loadState's end after in-memory state mirrors the disk file — nothing is dirty until the next mutation lands.
|
overridevirtual |
Clear floating state when snapping a floating window.
Atomically clears floating flag and pre-float zone data. Shared logic used by both SnapEngine and WindowTrackingAdaptor to avoid duplicating the isFloating → clear → clearPreFloat pattern.
| windowId | Window identifier |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Clear a window's shared free/float geometry from the record.
See IWindowTrackingService::clearFreeGeometry.
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::clearPreFloatZone | ( | const QString & | windowId | ) |
Clear pre-float zone after restore (both windowId and appId keys)
| void PhosphorPlacement::WindowTrackingService::clearPreFloatZoneForWindow | ( | const QString & | windowId | ) |
Clear pre-float zone for a specific window only (not appId)
Used by autotile float sync to avoid destroying sibling instances' data.
|
inline |
Clear the resnap buffer.
Called when virtual screen configuration changes to prevent stale resnap data from referencing old screen IDs.
|
inline |
The placement config installed at construction.
Read-only after wiring: the constructor is the sole entry point. Consumers that observe m_config directly (no notify signal) rely on it being frozen post-construction; reassigning it later would silently desynchronise their cached values, which is why no setter is exposed.
|
overridevirtual |
Pop the oldest pending restore entry for this window's appId.
The pending-restore queue is keyed by appId (FIFO), mirroring KWin's takeSessionInfo pattern. Every call to this method consumes at most one entry — the oldest one — and erases the queue entry entirely once it's emptied. Call sites:
There is no "stale" vs "fresh" distinction inside the queue: every entry is a FIFO head, and this method pops the head regardless of provenance. Earlier versions split this into two methods (consumePendingAssignment / clearStalePendingAssignment) that were implementation-identical but named as if they did different things; the duplication has been removed.
| windowId | Full window ID — the appId is resolved via currentAppIdFor() so the queue lookup sees the live class (Electron/CEF apps that mutate their class mid-session still hit the right queue). |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Current app class for a windowId, preferring the live registry.
Equivalent to PhosphorIdentity::WindowId::extractAppId() when no registry is attached. With a registry, returns the latest appId for the instance id — so snap rule matching against a freshly-renamed window (Electron/CEF) sees the current class.
Implements PhosphorEngine::IWindowTrackingService.
| const QHash< QString, int > & PhosphorPlacement::WindowTrackingService::desktopAssignments | ( | ) | const |
Get all desktop assignments for persistence.
|
overridevirtual |
Find the first empty zone in the layout for a screen.
| screenId | Screen to find layout for (empty = active layout) |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Implements PhosphorEngine::IWindowTrackingService.
| QStringList PhosphorPlacement::WindowTrackingService::floatingWindows | ( | ) | const |
Get all floating window IDs.
| PhosphorProtocol::EmptyZoneList PhosphorPlacement::WindowTrackingService::getEmptyZones | ( | const QString & | screenId | ) | const |
Get typed list of all empty zones for Snap Assist continuation.
| screenId | Screen to find layout for (e.g. DP-1) |
| bool PhosphorPlacement::WindowTrackingService::isAutoSnapped | ( | const QString & | windowId | ) | const |
Check if a window was auto-snapped.
| windowId | Full window ID |
|
inline |
True if the autotile engine reports the window actively tiled.
Returns false when the predicate is unwired (snap-only tests).
|
overridevirtual |
Check if a window is floating (excluded from snapping)
Delegates to the per-engine resolver when wired; otherwise falls back to the legacy shared floating set.
Implements PhosphorEngine::IWindowTrackingService.
|
inline |
True if the window's CURRENT screen mode is autotile.
The single owning-engine signal — the same predicate that routes the float resolver, the float writer, and validatedUnmanagedGeometry. Exposed so the capture funnel (WindowTrackingAdaptor::captureWindowPlacement) picks the owning engine the SAME way, instead of a divergent isWindowTracked() check that disagrees mid-mode-flip. Returns false when the predicate is unwired (snap-only tests / early init).
|
overridevirtual |
Check if a window is assigned to any zone.
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Check if window is sticky.
Implements PhosphorEngine::IWindowTrackingService.
| int PhosphorPlacement::WindowTrackingService::lastUsedDesktop | ( | ) | const |
Virtual-desktop companion of the last-used-zone tracking.
| QString PhosphorPlacement::WindowTrackingService::lastUsedScreenName | ( | ) | const |
Screen name companion of the last-used-zone tracking.
Returned alongside lastUsedZoneId so persistence-layer reloads can round-trip the companion fields without blanking them.
| QString PhosphorPlacement::WindowTrackingService::lastUsedZoneClass | ( | ) | const |
App class string stamped on the last-used-zone tracking.
Used by the reactive metadata handler to detect stale class tags after a mid-session rename.
| QString PhosphorPlacement::WindowTrackingService::lastUsedZoneId | ( | ) | const |
Get last used zone ID.
| void PhosphorPlacement::WindowTrackingService::markAsAutoSnapped | ( | const QString & | windowId | ) |
Mark a window as auto-snapped.
Auto-snapped windows should not update the last-used zone tracking when snapped. This prevents unwanted zone changes when windows are automatically restored on open.
| windowId | Full window ID |
| void PhosphorPlacement::WindowTrackingService::markDirty | ( | DirtyMask | fields | ) |
OR the given fields into the dirty mask AND emit stateChanged.
Primary (and only) entry point for mutators — replaces direct scheduleSaveState(). Public because the adaptor also needs to mark dirty from outside, e.g. when the active-layout change is observed via PhosphorZones::LayoutRegistry or when a failed async write needs its bits re-marked for retry. Multiple calls are idempotent (OR semantics) and cheap (bit OR + one signal emission).
| void PhosphorPlacement::WindowTrackingService::migrateScreenAssignmentsFromVirtual | ( | const QString & | physicalScreenId | ) |
Reverse migration: virtual screen IDs → physical screen ID.
Called when virtual screen configuration is removed for a physical screen. Strips the "/vs:N" suffix from all tracked window screen assignments that belong to the given physical screen, reverting them to the physical ID.
| physicalScreenId | The physical screen ID to migrate back to |
| void PhosphorPlacement::WindowTrackingService::migrateScreenAssignmentsToVirtual | ( | const QString & | physicalScreenId, |
| const QStringList & | virtualScreenIds, | ||
| PhosphorScreens::ScreenManager * | mgr | ||
| ) |
Migrate window screen assignments from physical to virtual screen IDs.
Windows snapped before virtual screens were configured have physical screen IDs in SnapState's screen assignments (m_snapState->screenAssignments()). When virtual screens are active, all per-screen lookups use virtual IDs, so these windows become invisible to zone occupancy checks, snap assist, float/unfloat, etc.
This method iterates all screen assignments and, for any window whose screen matches the given physical screen, determines which virtual screen the window's zone falls within and updates the assignment accordingly.
Also migrates pre-float screen assignments in SnapState.
| physicalScreenId | The physical screen being subdivided |
| virtualScreenIds | Virtual screen IDs for the physical screen |
| mgr | PhosphorScreens::ScreenManager for geometry lookups |
| QRect PhosphorPlacement::WindowTrackingService::multiZoneGeometry | ( | const QStringList & | zoneIds, |
| const QString & | screenId = QString() |
||
| ) | const |
Get combined geometry for multiple zones on a specific screen.
| zoneIds | List of zone UUID strings |
| screenId | Screen identifier (empty = primary) |
| void PhosphorPlacement::WindowTrackingService::onLayoutChanged | ( | ) |
Handle layout change - validate/clear stale zone assignments.
|
inline |
Return the current dirty mask without clearing.
Read-only accessor for tests and instrumentation.
| QHash< QString, PendingRestoreTarget > PhosphorPlacement::WindowTrackingService::pendingRestoreGeometries | ( | ) | const |
Pre-compute zone geometries for all pending restore entries.
Used by the KWin effect to cache expected snap positions so that windows can be teleported to their zone immediately on windowAdded, eliminating the visible "flash" from KWin's session-restored position. Sourced from the unified WindowPlacementStore's snapped records; for a multi-instance appId the lowest-sequence (FIFO-head) record is chosen deterministically. Entries whose saved screen is currently in autotile mode are skipped: the effect cache is a snap-mode-only fast path, and autotile on the saved screen will own placement. Validates desktop context so the cache never contains geometries the async resolver rejects.
|
inlineoverridevirtual |
Get pending restore queues (consumption queue: appId -> list of pending restores)
Implements PhosphorEngine::IWindowTrackingService.
| QSet< QString > PhosphorPlacement::WindowTrackingService::physicalScreensWithStaleVirtualAssignments | ( | const QSet< QString > & | subdividedPhysicalIds | ) | const |
Find physical screens whose state still references virtual ids, excluding screens the caller knows are still subdivided.
Sweeps every state store that holds a screen id (active screen assignments, pre-float assignments, pending restore queues, pre-tile geometry on the snap engine) and returns the set of physical screen ids for which any stored value is still a "physId/vs:N" form whose physId is NOT in subdividedPhysicalIds.
Pair with migrateScreenAssignmentsFromVirtual on each returned id to clean up state left over from a config change applied while the daemon was offline.
Owning the scan here (rather than the daemon enumerating each store) keeps state-shape knowledge inside WTS — adding a new screen-id-bearing store updates this method, not every caller.
| subdividedPhysicalIds | Physical ids that legitimately have virtual subdivisions in the current config (these are kept). |
|
inline |
|
inlineoverridevirtual |
The unified, engine-agnostic placement store (one WindowPlacement record per window).
Both engines reach it via this service; the WTA persists it.
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::populateResnapBufferForAllScreens | ( | const QSet< QString > & | excludeScreens = {}, |
| const QSet< QString > & | includeScreens = {}, |
||
| int | desktopFilter = 0 |
||
| ) |
Populate the resnap buffer for all screens independently.
For each window, looks up its current zone assignment and determines the zone position using a global zoneId→position map built from all loaded layouts. This avoids relying on the global activeLayout/previousLayout which only tracks one layout at a time.
Used by the KCM save path where multiple screens can have different layout assignments changed simultaneously.
| excludeScreens | Screens to skip (e.g. autotile screens handled separately) |
| includeScreens | When non-empty, only process windows on these screens. Restricts resnap to screens whose layout actually changed. |
| desktopFilter | When > 0, only include windows whose virtualDesktop matches this value (or are sticky/unknown with virtualDesktop==0). Restricts resnap to a single virtual desktop so per-desktop layout changes don't reposition windows on other desktops. |
|
overridevirtual |
Get the screen name where the window was snapped before floating.
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
| const QHash< QString, QString > & PhosphorPlacement::WindowTrackingService::preFloatScreenAssignments | ( | ) | const |
| QString PhosphorPlacement::WindowTrackingService::preFloatZone | ( | const QString & | windowId | ) | const |
Get primary zone to restore to when unfloating.
| windowId | Full window ID |
| const QHash< QString, QStringList > & PhosphorPlacement::WindowTrackingService::preFloatZoneAssignments | ( | ) | const |
Get pre-float zone assignments for persistence.
Delegates to SnapState (authoritative store).
|
overridevirtual |
Get all zones to restore to when unfloating (multi-zone support)
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
| int PhosphorPlacement::WindowTrackingService::pruneStaleAssignments | ( | const QSet< QString > & | aliveWindowIds | ) |
Remove zone/screen/desktop assignments for windows not in the alive set.
Returns the number of pruned entries.
|
overridevirtual |
Live snap zones if present, else the durable placement-record snap slot.
See IWindowTrackingService::recordedSnapZones.
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::recordFloatingClose | ( | const QString & | windowId, |
| const QString & | screenId, | ||
| const QRect & | geometry | ||
| ) |
Authoritative float-back capture for a window closing on screenId.
Unlike recordFreeGeometry (a geometry-only partial that deliberately leaves the managed-context screen untouched), this records the float geometry AND updates the record's managed screenId to screenId — carrying an engine slot so the store merge adopts the new screen. Used by the close-capture fallback when a cross-screen move has orphaned the window from both engines, so the only authoritative source of its final screen is KWin (passed down from the effect). The existing record's per-engine slots and desktop/activity are preserved; only the screen and this screen's free geometry change.
|
overridevirtual |
Write the window's shared free/float geometry into the unified record (the single float-back store).
See IWindowTrackingService::recordFreeGeometry.
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Record that a window class was user-snapped.
| windowId | Full window ID to extract class from |
| wasUserInitiated | true if user-initiated snap |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Resolve a screen ID to an effective screen ID, falling back to the physical screen ID if a virtual screen no longer exists in the current configuration.
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Resolve zone geometry: combined geometry for multi-zone, single for single zone.
Avoids repeating the (size>1) ? multiZoneGeometry : zoneGeometry ternary.
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::retagLastUsedZoneClass | ( | const QString & | newClass | ) |
Update the last-used-zone class tag without touching zone/screen.
Called by the reactive metadata handler when a window renames mid-session and its old class was the class tracked on last-used-zone. Only the class string is refreshed so the next auto-snap-by-class lookup matches against the live name.
|
overridevirtual |
Get all screen assignments for persistence.
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
The screen a window is assigned to, or empty when it has none.
Point accessor over the screen-assignment map that canonicalizes windowId to the first-seen composite (via SnapState), so external callers resolve a window even after the effect-restart-after-class-mutation skew rather than reading the raw whole-map getter with a stale composite (issue #628).
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Same, but returns defaultScreen when the window has no screen assignment — the canonicalizing replacement for screenAssignments().value(windowId, defaultScreen).
Implements PhosphorEngine::IWindowTrackingService.
|
inlineoverridevirtual |
Implements PhosphorEngine::IWindowTrackingService.
| void PhosphorPlacement::WindowTrackingService::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)
Used to restore exact window-to-zone mappings after daemon-only restart (KWin still running, so internalId UUIDs are stable). Prevents wrong-instance restore for multi-instance apps (e.g. 2 Ghostty windows, only 1 was snapped).
|
inline |
|
inline |
|
inline |
Aggregates both engines' floating windows for the engine-agnostic floatingWindows() enumeration.
See setEngineFloatResolver rationale.
|
inline |
|
inline |
|
inline |
Set floating windows (loaded from KConfig by adaptor)
| void PhosphorPlacement::WindowTrackingService::setLastUsedZone | ( | const QString & | zoneId, |
| const QString & | screenId, | ||
| const QString & | zoneClass, | ||
| int | desktop | ||
| ) |
Set last used zone info (loaded from KConfig by adaptor)
|
inline |
Set pending restore queues (loaded from KConfig by adaptor)
| void PhosphorPlacement::WindowTrackingService::setPreFloatScreenAssignments | ( | const QHash< QString, QString > & | assignments | ) |
| void PhosphorPlacement::WindowTrackingService::setPreFloatZoneAssignments | ( | const QHash< QString, QStringList > & | assignments | ) |
Set pre-float zone assignments (loaded from KConfig by adaptor)
Delegates to SnapState (authoritative store).
|
inline |
Inject a context-active predicate.
See ShouldTrackPredicate.
Used to suppress PendingRestore writes for windows that close on a monitor/desktop the user has disabled snapping for. Without this, a window closed on a disabled monitor still gets a snap restore recorded against that monitor — when the same app reopens (or KWin rehomes the window onto a surviving monitor after sleep), the snap machinery picks the stale entry up and yanks the window back into a zone the user told us to stay out of. See discussion #461 item 2.
Ownership: the caller is responsible for keeping any captured state (e.g. this pointers to a settings adaptor) valid for the lifetime of this WindowTrackingService. If the captured object is destroyed before WTS, clear the predicate first (setShouldTrackPredicate({})) — otherwise a subsequent windowClosed call dereferences freed memory.
|
inline |
Wire the snap-mode placement engine.
Float-back / free geometry is SHARED across modes and lives in the single unified WindowPlacementStore (freeGeometryByScreen), not per-engine — so this pointer is not the geometry store (validatedUnmanagedGeometry reads the record directly). Retained for the engine reference used elsewhere (stale-window pruning, the D-Bus facade's snapEngine() accessor).
Must be set after construction. Not owned.
|
inline |
| void PhosphorPlacement::WindowTrackingService::setUserSnappedClasses | ( | const QSet< QString > & | classes | ) |
Set user-snapped classes (loaded from KConfig by adaptor)
|
overridevirtual |
Set window floating state.
Routes to the engine owning the window's current screen mode via the injected writer when wired; otherwise updates the legacy shared set and the snap state directly.
| windowId | Full window ID |
| floating | true to float, false to unfloat |
Implements PhosphorEngine::IWindowTrackingService.
|
inline |
Wire up the shared WindowRegistry.
Optional — unit tests construct WTS without a registry and fall back to parsing composite windowIds. Production daemons set this so the service queries live class via appIdFor() and ignores first-seen strings.
Must be set before start. Not owned.
| void PhosphorPlacement::WindowTrackingService::setWindowSticky | ( | const QString & | windowId, |
| bool | sticky | ||
| ) |
Record whether a window is sticky (on all desktops)
|
inline |
| QStringList PhosphorPlacement::WindowTrackingService::snappedWindows | ( | ) | const |
Get all snapped windows.
|
signal |
Emitted when state needs to be saved.
| DirtyMask PhosphorPlacement::WindowTrackingService::takeDirty | ( | ) |
Return the current dirty mask, clearing it atomically.
Used by the adaptor's saveState() to snapshot "what needs writing" in one step.
|
inlineoverridevirtual |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Remove window from its assigned zone.
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Unsnap window for floating (saves zone for later restore)
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
| QHash< QString, QRect > PhosphorPlacement::WindowTrackingService::updatedWindowGeometries | ( | ) | const |
Get updated geometries for all tracked windows.
Used when screen resolution changes to recalculate zone positions.
|
overridevirtual |
Update last used zone tracking.
Implements PhosphorEngine::IWindowTrackingService.
| const QSet< QString > & PhosphorPlacement::WindowTrackingService::userSnappedClasses | ( | ) | const |
Get user-snapped classes.
|
overridevirtual |
Look up a window's free (unmanaged) geometry from the unified WindowPlacementStore, with appId fallback, and validate it.
Combines the windowId lookup, appId fallback, and cross-screen validation into a single call. Returns nullopt if no geometry is recorded.
| windowId | Full window ID |
| screenId | Screen where the window currently is (for cross-screen adjustment) |
| exactOnly | If true, skip the appId fallback (strict per-instance lookup) |
Implements PhosphorEngine::IWindowTrackingService.
| std::optional< QRect > PhosphorPlacement::WindowTrackingService::validateGeometryForScreen | ( | const QRect & | geo, |
| const QString & | savedScreen, | ||
| const QString & | currentScreenName | ||
| ) | const |
Validate and adjust a saved geometry for screen-aware restore.
Pure utility — reads no internal state. Given a saved geometry and the screen it was captured on, returns the geometry adjusted for the currentScreenName. Cross-screen mismatches are resolved by centering on the target screen (size clamped to fit). On-screen geometries are returned as-is; off-screen geometries are nudged to the nearest screen.
| geo | Saved geometry (e.g. a window's recorded free geometry) |
| savedScreen | Screen connector name at capture time (may be empty) |
| currentScreenName | Screen where the window currently is |
geo is invalid | void PhosphorPlacement::WindowTrackingService::windowClosed | ( | const QString & | windowId, |
| PhosphorEngine::WindowKind | kind = PhosphorEngine::WindowKind::Unknown |
||
| ) |
Clean up all tracking data for a closed window.
| windowId | Full window ID |
| kind | Structural kind of the closing window. When a PendingRestore entry is enqueued for this close, the kind is stamped onto the entry so the consume path can refuse to assign it to a window of a different kind on reopen. Defaults to WindowKind::Unknown (the pre-fix behaviour: no kind gate). |
|
inline |
Accessor for consumers that need direct access (effect, adaptor).
|
overridevirtual |
Get all windows in a specific zone.
| zoneId | PhosphorZones::Zone UUID string |
Implements PhosphorEngine::IWindowTrackingService.
|
signal |
|
overridevirtual |
Get all zone assignments for persistence.
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Get the primary zone ID for a window.
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Get geometry for a zone on a specific screen.
| zoneId | PhosphorZones::Zone UUID string |
| screenId | Screen identifier (empty = primary) |
Implements PhosphorEngine::IWindowTrackingService.
|
overridevirtual |
Get all zone IDs for a window (multi-zone support)
| windowId | Full window ID |
Implements PhosphorEngine::IWindowTrackingService.