Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PhosphorPlacement::WindowTrackingService Class Reference

Window-zone tracking service (business logic layer) More...

#include <phosphor-placement/include/PhosphorPlacement/WindowTrackingService.h>

Inheritance diagram for PhosphorPlacement::WindowTrackingService:
[legend]

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 , DirtyAll = 0x3FFu
}
 
using ShouldTrackPredicate = std::function< bool(const QString &screenId, int virtualDesktop)>
 Predicate type for "is this snap-mode context active?".
 
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, Phosphor::Screens::ScreenManager *screenManager, PhosphorWorkspaces::VirtualDesktopManager *vdm, IGeometryResolver *geometryResolver=nullptr, PlacementConfig config={}, QObject *parent=nullptr)
 
void setConfig (const PlacementConfig &config)
 
const PlacementConfigconfig () const
 
QObject * asQObject () override
 
 ~WindowTrackingService () override
 
void setWindowRegistry (PhosphorEngine::WindowRegistry *registry)
 Wire up the shared WindowRegistry.
 
void setSnapState (PhosphorSnapEngine::SnapState *state)
 
void setShouldTrackPredicate (ShouldTrackPredicate predicate)
 Inject a context-active predicate.
 
void setSnapEngine (PhosphorEngine::PlacementEngineBase *engine)
 Wire the snap-mode placement engine for unmanaged geometry queries.
 
PhosphorEngine::PlacementEngineBasesnapEngine () const
 
PhosphorEngine::WindowRegistrywindowRegistry () const
 Accessor for consumers that need direct access (effect, adaptor).
 
Phosphor::Screens::ScreenManagerscreenManager () 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)
 
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 &currentScreenName) 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 unmanaged geometry from the snap engine with appId fallback and validate.
 
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.
 
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.
 
int pruneExcludedPendingRestores (const QStringList &exclusionPatterns)
 Drop pending-restore queues whose appId matches any exclusion pattern.
 
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, Phosphor::Screens::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, PendingRestoreTargetpendingRestoreGeometries () 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.
 
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< ResnapEntrytakeResnapBuffer () 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
 

Detailed Description

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:

  • PhosphorZones::Zone assignment management (which window is in which zone)
  • Pre-snap geometry storage (for restoring original size)
  • Floating window state tracking
  • Session persistence (save/load state across restarts)
  • Auto-snap logic (snap new windows to last zone)
  • Window rotation calculations

The WindowTrackingAdaptor becomes a thin D-Bus facade that delegates all business logic to this service.

Design benefits:

  • Testable: Service can be unit tested without D-Bus
  • Reusable: Logic can be used by other components
  • Maintainable: Clear separation of concerns
  • Debuggable: Easier to trace logic flow

Member Typedef Documentation

◆ DirtyMask

◆ PendingRestore

◆ ResnapEntry

◆ ShouldTrackPredicate

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.

Member Enumeration Documentation

◆ DirtyField

Enumerator
DirtyNone 
DirtyActiveLayoutId 
DirtyZoneAssignments 
DirtyPendingRestores 
DirtyPreTileGeometries 
DirtyLastUsedZone 
DirtyPreFloatZones 
DirtyPreFloatScreens 
DirtyUserSnapped 
DirtyAutotileOrders 
DirtyAutotilePending 
DirtyAll 

Constructor & Destructor Documentation

◆ WindowTrackingService()

PhosphorPlacement::WindowTrackingService::WindowTrackingService ( PhosphorZones::LayoutRegistry layoutManager,
PhosphorZones::IZoneDetector zoneDetector,
Phosphor::Screens::ScreenManager screenManager,
PhosphorWorkspaces::VirtualDesktopManager vdm,
IGeometryResolver geometryResolver = nullptr,
PlacementConfig  config = {},
QObject *  parent = nullptr 
)
explicit

◆ ~WindowTrackingService()

PhosphorPlacement::WindowTrackingService::~WindowTrackingService ( )
override

Member Function Documentation

◆ asQObject()

QObject * PhosphorPlacement::WindowTrackingService::asQObject ( )
inlineoverridevirtual

◆ assignWindowToZone()

void PhosphorPlacement::WindowTrackingService::assignWindowToZone ( const QString &  windowId,
const QString &  zoneId,
const QString &  screenId,
int  virtualDesktop 
)
overridevirtual

Assign a window to a zone.

Parameters
windowIdFull window ID
zoneIdPhosphorZones::Zone UUID string
screenIdScreen where the zone is located
virtualDesktopVirtual desktop number (1-based, 0 = all)

Implements PhosphorEngine::IWindowTrackingService.

◆ assignWindowToZones()

void PhosphorPlacement::WindowTrackingService::assignWindowToZones ( const QString &  windowId,
const QStringList &  zoneIds,
const QString &  screenId,
int  virtualDesktop 
)
overridevirtual

Assign a window to multiple zones (multi-zone snap)

Parameters
windowIdFull window ID
zoneIdsList of zone UUID strings (first is primary)
screenIdScreen where the zones are located
virtualDesktopVirtual desktop number (1-based, 0 = all)

Implements PhosphorEngine::IWindowTrackingService.

◆ buildOccupiedZoneSet()

QSet< QUuid > PhosphorPlacement::WindowTrackingService::buildOccupiedZoneSet ( const QString &  screenFilter = QString(),
int  desktopFilter = 0 
) const
overridevirtual

Build set of occupied zone UUIDs, optionally filtered by screen and virtual desktop.

Uses Phosphor::Screens::ScreenIdentity::screensMatch() for format-agnostic screen comparison.

Parameters
desktopFilterWhen > 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.

◆ buildZoneOrderedWindowList()

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.

Parameters
screenIdScreen identifier to filter windows by
Returns
Window IDs sorted by zone number ascending

◆ canonicalizeForLookup()

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.

◆ clearAutoSnapped()

bool PhosphorPlacement::WindowTrackingService::clearAutoSnapped ( const QString &  windowId)
overridevirtual

Clear auto-snapped flag for a window.

Parameters
windowIdFull window ID
Returns
true if the window had the auto-snapped flag

Implements PhosphorEngine::IWindowTrackingService.

◆ clearDirty()

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.

◆ clearFloatingForSnap()

bool PhosphorPlacement::WindowTrackingService::clearFloatingForSnap ( const QString &  windowId)
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.

Parameters
windowIdWindow identifier
Returns
true if the window was floating (caller should emit windowFloatingChanged)

Implements PhosphorEngine::IWindowTrackingService.

◆ clearPreFloatZone()

void PhosphorPlacement::WindowTrackingService::clearPreFloatZone ( const QString &  windowId)

Clear pre-float zone after restore (both windowId and appId keys)

◆ clearPreFloatZoneForWindow()

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.

◆ clearResnapBuffer()

void PhosphorPlacement::WindowTrackingService::clearResnapBuffer ( )
inline

Clear the resnap buffer.

Called when virtual screen configuration changes to prevent stale resnap data from referencing old screen IDs.

◆ config()

const PlacementConfig & PhosphorPlacement::WindowTrackingService::config ( ) const
inline

◆ consumePendingAssignment()

bool PhosphorPlacement::WindowTrackingService::consumePendingAssignment ( const QString &  windowId)
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:

  1. After a successful session restore — so the same window isn't restored again if reopened, and so other instances of the same app class don't incorrectly restore onto this window's zone.
  2. After a user-initiated snap or unsnap — so a stale entry from a previous session doesn't drag the window back to a different zone on its next close/reopen cycle.

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.

Parameters
windowIdFull 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).
Returns
true if an entry was popped, false if the queue was empty. Callers that don't care about the result may ignore it.

Implements PhosphorEngine::IWindowTrackingService.

◆ currentAppIdFor()

QString PhosphorPlacement::WindowTrackingService::currentAppIdFor ( const QString &  anyWindowId) const
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.

◆ desktopAssignments()

const QHash< QString, int > & PhosphorPlacement::WindowTrackingService::desktopAssignments ( ) const

Get all desktop assignments for persistence.

◆ findEmptyZone()

QString PhosphorPlacement::WindowTrackingService::findEmptyZone ( const QString &  screenId = QString()) const
overridevirtual

Find the first empty zone in the layout for a screen.

Parameters
screenIdScreen to find layout for (empty = active layout)
Returns
PhosphorZones::Zone ID or empty string if all occupied

Implements PhosphorEngine::IWindowTrackingService.

◆ findEmptyZoneInLayout()

QString PhosphorPlacement::WindowTrackingService::findEmptyZoneInLayout ( PhosphorZones::Layout layout,
const QString &  screenId,
int  desktopFilter = 0 
) const
overridevirtual

◆ floatingWindows()

QStringList PhosphorPlacement::WindowTrackingService::floatingWindows ( ) const

Get all floating window IDs.

◆ getEmptyZones()

PhosphorProtocol::EmptyZoneList PhosphorPlacement::WindowTrackingService::getEmptyZones ( const QString &  screenId) const

Get typed list of all empty zones for Snap Assist continuation.

Parameters
screenIdScreen to find layout for (e.g. DP-1)
Returns
PhosphorProtocol::EmptyZoneList of empty zone entries with overlay-local geometry

◆ isAutoSnapped()

bool PhosphorPlacement::WindowTrackingService::isAutoSnapped ( const QString &  windowId) const

Check if a window was auto-snapped.

Parameters
windowIdFull window ID
Returns
true if the window was auto-snapped (not user-initiated)

◆ isWindowFloating()

bool PhosphorPlacement::WindowTrackingService::isWindowFloating ( const QString &  windowId) const
overridevirtual

Check if a window is floating (excluded from snapping)

Implements PhosphorEngine::IWindowTrackingService.

◆ isWindowSnapped()

bool PhosphorPlacement::WindowTrackingService::isWindowSnapped ( const QString &  windowId) const
overridevirtual

Check if a window is assigned to any zone.

Implements PhosphorEngine::IWindowTrackingService.

◆ isWindowSticky()

bool PhosphorPlacement::WindowTrackingService::isWindowSticky ( const QString &  windowId) const
overridevirtual

Check if window is sticky.

Implements PhosphorEngine::IWindowTrackingService.

◆ lastUsedZoneClass()

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.

◆ lastUsedZoneId()

QString PhosphorPlacement::WindowTrackingService::lastUsedZoneId ( ) const

Get last used zone ID.

◆ markAsAutoSnapped()

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.

Parameters
windowIdFull window ID

◆ markDirty()

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).

◆ migrateScreenAssignmentsFromVirtual()

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.

Parameters
physicalScreenIdThe physical screen ID to migrate back to

◆ migrateScreenAssignmentsToVirtual()

void PhosphorPlacement::WindowTrackingService::migrateScreenAssignmentsToVirtual ( const QString &  physicalScreenId,
const QStringList &  virtualScreenIds,
Phosphor::Screens::ScreenManager mgr 
)

Migrate window screen assignments from physical to virtual screen IDs.

Windows snapped before virtual screens were configured have physical screen IDs in m_windowScreenAssignments. 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.

Parameters
physicalScreenIdThe physical screen being subdivided
virtualScreenIdsVirtual screen IDs for the physical screen
mgrPhosphor::Screens::ScreenManager for geometry lookups

◆ multiZoneGeometry()

QRect PhosphorPlacement::WindowTrackingService::multiZoneGeometry ( const QStringList &  zoneIds,
const QString &  screenId = QString() 
) const

Get combined geometry for multiple zones on a specific screen.

Parameters
zoneIdsList of zone UUID strings
screenIdScreen identifier (empty = primary)
Returns
Union of all zone geometries, or invalid QRect if none found

◆ onLayoutChanged()

void PhosphorPlacement::WindowTrackingService::onLayoutChanged ( )

Handle layout change - validate/clear stale zone assignments.

◆ peekDirty()

DirtyMask PhosphorPlacement::WindowTrackingService::peekDirty ( ) const
inline

Return the current dirty mask without clearing.

Read-only accessor for tests and instrumentation.

◆ pendingRestoreGeometries()

QHash< QString, PendingRestoreTarget > PhosphorPlacement::WindowTrackingService::pendingRestoreGeometries ( ) const

Pre-compute zone geometries for all pending restore entries.

Returns
Map of appId -> {geometry, savedScreenId}

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. Only the first entry per appId is returned (FIFO consumption order). 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 layout/desktop context so the cache never contains geometries the async resolver would reject.

◆ pendingRestoreQueues()

const QHash< QString, QList< PendingRestore > > & PhosphorPlacement::WindowTrackingService::pendingRestoreQueues ( ) const
inlineoverridevirtual

Get pending restore queues (consumption queue: appId -> list of pending restores)

Implements PhosphorEngine::IWindowTrackingService.

◆ physicalScreensWithStaleVirtualAssignments()

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.

Parameters
subdividedPhysicalIdsPhysical ids that legitimately have virtual subdivisions in the current config (these are kept).
Returns
Physical ids that should have migrateScreenAssignmentsFromVirtual applied. Empty when state is consistent with the policy.

◆ populateResnapBufferForAllScreens()

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.

Parameters
excludeScreensScreens to skip (e.g. autotile screens handled separately)
includeScreensWhen non-empty, only process windows on these screens. Restricts resnap to screens whose layout actually changed.
desktopFilterWhen > 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.

◆ preFloatScreen()

QString PhosphorPlacement::WindowTrackingService::preFloatScreen ( const QString &  windowId) const
overridevirtual

Get the screen name where the window was snapped before floating.

Parameters
windowIdFull window ID
Returns
Screen name or empty string if unknown

Implements PhosphorEngine::IWindowTrackingService.

◆ preFloatScreenAssignments()

const QHash< QString, QString > & PhosphorPlacement::WindowTrackingService::preFloatScreenAssignments ( ) const

◆ preFloatZone()

QString PhosphorPlacement::WindowTrackingService::preFloatZone ( const QString &  windowId) const

Get primary zone to restore to when unfloating.

Parameters
windowIdFull window ID
Returns
PhosphorZones::Zone ID or empty string if none

◆ preFloatZoneAssignments()

const QHash< QString, QStringList > & PhosphorPlacement::WindowTrackingService::preFloatZoneAssignments ( ) const

Get pre-float zone assignments for persistence.

Delegates to SnapState (authoritative store).

◆ preFloatZones()

QStringList PhosphorPlacement::WindowTrackingService::preFloatZones ( const QString &  windowId) const
overridevirtual

Get all zones to restore to when unfloating (multi-zone support)

Parameters
windowIdFull window ID
Returns
List of zone IDs (empty if none)

Implements PhosphorEngine::IWindowTrackingService.

◆ pruneExcludedPendingRestores()

int PhosphorPlacement::WindowTrackingService::pruneExcludedPendingRestores ( const QStringList &  exclusionPatterns)

Drop pending-restore queues whose appId matches any exclusion pattern.

The snap engine already refuses to honor a pending restore for an excluded app at runtime. See resolveWindowRestore in phosphor-snap-engine/lifecycle.cpp. So the entries are functionally dead, yet they still live on disk in PendingRestoreQueues until the next save cycle. Their persistence generates one "pending snap:" log line per entry at every daemon startup, and bloats session state with values that can never be replayed. This method walks the queues and removes appIds that match any pattern via PhosphorIdentity::WindowId::appIdMatches. That is the same predicate the snap engine itself uses. When any removal happens it marks DirtyPendingRestores so the next debounced save persists the pruned set.

Called from the daemon adaptor at startup right after loadState. Also called on every excludedApplicationsChanged or excludedWindowClassesChanged signal so freshly excluded apps don't strand their old queues.

Parameters
exclusionPatternscombined list of excludedApplications and excludedWindowClasses entries. Empty patterns and an empty list are no-ops.
Returns
number of appId entries fully removed. The queue may have contained multiple PendingRestores for one appId. One removal counts once. This mirrors the shape of m_pendingRestoreQueues' QHash.

◆ pruneStaleAssignments()

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.

◆ recordSnapIntent()

void PhosphorPlacement::WindowTrackingService::recordSnapIntent ( const QString &  windowId,
bool  wasUserInitiated 
)
overridevirtual

Record that a window class was user-snapped.

Parameters
windowIdFull window ID to extract class from
wasUserInitiatedtrue if user-initiated snap

Implements PhosphorEngine::IWindowTrackingService.

◆ resolveEffectiveScreenId()

QString PhosphorPlacement::WindowTrackingService::resolveEffectiveScreenId ( const QString &  screenId) const
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.

◆ resolveZoneGeometry()

QRect PhosphorPlacement::WindowTrackingService::resolveZoneGeometry ( const QStringList &  zoneIds,
const QString &  screenId 
) const
overridevirtual

Resolve zone geometry: combined geometry for multi-zone, single for single zone.

Avoids repeating the (size>1) ? multiZoneGeometry : zoneGeometry ternary.

Implements PhosphorEngine::IWindowTrackingService.

◆ retagLastUsedZoneClass()

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.

◆ screenAssignments()

const QHash< QString, QString > & PhosphorPlacement::WindowTrackingService::screenAssignments ( ) const
overridevirtual

Get all screen assignments for persistence.

Implements PhosphorEngine::IWindowTrackingService.

◆ screenManager()

Phosphor::Screens::ScreenManager * PhosphorPlacement::WindowTrackingService::screenManager ( ) const
inlineoverridevirtual

◆ setActiveAssignments()

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).

◆ setConfig()

void PhosphorPlacement::WindowTrackingService::setConfig ( const PlacementConfig config)
inline

◆ setFloatingWindows()

void PhosphorPlacement::WindowTrackingService::setFloatingWindows ( const QSet< QString > &  windows)
inline

Set floating windows (loaded from KConfig by adaptor)

◆ setLastUsedZone()

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)

◆ setPendingRestoreQueues()

void PhosphorPlacement::WindowTrackingService::setPendingRestoreQueues ( const QHash< QString, QList< PendingRestore > > &  queues)
inline

Set pending restore queues (loaded from KConfig by adaptor)

◆ setPreFloatScreenAssignments()

void PhosphorPlacement::WindowTrackingService::setPreFloatScreenAssignments ( const QHash< QString, QString > &  assignments)

◆ setPreFloatZoneAssignments()

void PhosphorPlacement::WindowTrackingService::setPreFloatZoneAssignments ( const QHash< QString, QStringList > &  assignments)

Set pre-float zone assignments (loaded from KConfig by adaptor)

Delegates to SnapState (authoritative store).

◆ setShouldTrackPredicate()

void PhosphorPlacement::WindowTrackingService::setShouldTrackPredicate ( ShouldTrackPredicate  predicate)
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.

◆ setSnapEngine()

void PhosphorPlacement::WindowTrackingService::setSnapEngine ( PhosphorEngine::PlacementEngineBase engine)
inline

Wire the snap-mode placement engine for unmanaged geometry queries.

PlacementEngineBase is the single store for pre-tile (unmanaged) geometry. WTS delegates to this engine for geometry lookup, store, and clear operations used by the D-Bus facade and persistence layer.

Must be set after construction. Not owned.

◆ setSnapState()

void PhosphorPlacement::WindowTrackingService::setSnapState ( PhosphorSnapEngine::SnapState state)
inline

◆ setUserSnappedClasses()

void PhosphorPlacement::WindowTrackingService::setUserSnappedClasses ( const QSet< QString > &  classes)

Set user-snapped classes (loaded from KConfig by adaptor)

◆ setWindowFloating()

void PhosphorPlacement::WindowTrackingService::setWindowFloating ( const QString &  windowId,
bool  floating 
)
overridevirtual

Set window floating state.

Parameters
windowIdFull window ID
floatingtrue to float, false to unfloat

Implements PhosphorEngine::IWindowTrackingService.

◆ setWindowRegistry()

void PhosphorPlacement::WindowTrackingService::setWindowRegistry ( PhosphorEngine::WindowRegistry registry)
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.

◆ setWindowSticky()

void PhosphorPlacement::WindowTrackingService::setWindowSticky ( const QString &  windowId,
bool  sticky 
)

Record whether a window is sticky (on all desktops)

◆ snapEngine()

PhosphorEngine::PlacementEngineBase * PhosphorPlacement::WindowTrackingService::snapEngine ( ) const
inline

◆ snappedWindows()

QStringList PhosphorPlacement::WindowTrackingService::snappedWindows ( ) const

Get all snapped windows.

Returns
List of window IDs that are currently snapped

◆ stateChanged

void PhosphorPlacement::WindowTrackingService::stateChanged ( )
signal

Emitted when state needs to be saved.

◆ takeDirty()

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.

◆ takeResnapBuffer()

QVector< ResnapEntry > PhosphorPlacement::WindowTrackingService::takeResnapBuffer ( )
inlineoverridevirtual

◆ unassignWindow()

void PhosphorPlacement::WindowTrackingService::unassignWindow ( const QString &  windowId)
overridevirtual

Remove window from its assigned zone.

Parameters
windowIdFull window ID

Implements PhosphorEngine::IWindowTrackingService.

◆ unsnapForFloat()

void PhosphorPlacement::WindowTrackingService::unsnapForFloat ( const QString &  windowId)
overridevirtual

Unsnap window for floating (saves zone for later restore)

Parameters
windowIdFull window ID

Implements PhosphorEngine::IWindowTrackingService.

◆ updatedWindowGeometries()

QHash< QString, QRect > PhosphorPlacement::WindowTrackingService::updatedWindowGeometries ( ) const

Get updated geometries for all tracked windows.

Returns
Map of windowId -> new geometry

Used when screen resolution changes to recalculate zone positions.

◆ updateLastUsedZone()

void PhosphorPlacement::WindowTrackingService::updateLastUsedZone ( const QString &  zoneId,
const QString &  screenId,
const QString &  windowClass,
int  virtualDesktop 
)
overridevirtual

Update last used zone tracking.

Implements PhosphorEngine::IWindowTrackingService.

◆ userSnappedClasses()

const QSet< QString > & PhosphorPlacement::WindowTrackingService::userSnappedClasses ( ) const

Get user-snapped classes.

◆ validatedUnmanagedGeometry()

std::optional< QRect > PhosphorPlacement::WindowTrackingService::validatedUnmanagedGeometry ( const QString &  windowId,
const QString &  screenId,
bool  exactOnly = false 
) const
overridevirtual

Look up unmanaged geometry from the snap engine with appId fallback and validate.

Combines the windowId lookup, appId fallback, and cross-screen validation into a single call. Returns nullopt if no geometry is found or if the snap engine is not wired.

Parameters
windowIdFull window ID
screenIdScreen where the window currently is (for cross-screen adjustment)
exactOnlyIf true, skip the appId fallback (strict per-instance lookup)

Implements PhosphorEngine::IWindowTrackingService.

◆ validateGeometryForScreen()

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.

Parameters
geoSaved geometry (e.g. from PlacementEngineBase::unmanagedGeometry)
savedScreenScreen connector name at capture time (may be empty)
currentScreenNameScreen where the window currently is
Returns
Adjusted geometry, or nullopt if geo is invalid

◆ windowClosed()

void PhosphorPlacement::WindowTrackingService::windowClosed ( const QString &  windowId,
PhosphorEngine::WindowKind  kind = PhosphorEngine::WindowKind::Unknown 
)

Clean up all tracking data for a closed window.

Parameters
windowIdFull window ID
kindStructural 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).

◆ windowRegistry()

PhosphorEngine::WindowRegistry * PhosphorPlacement::WindowTrackingService::windowRegistry ( ) const
inline

Accessor for consumers that need direct access (effect, adaptor).

◆ windowsInZone()

QStringList PhosphorPlacement::WindowTrackingService::windowsInZone ( const QString &  zoneId) const
overridevirtual

Get all windows in a specific zone.

Parameters
zoneIdPhosphorZones::Zone UUID string
Returns
List of window IDs

Implements PhosphorEngine::IWindowTrackingService.

◆ windowZoneChanged

void PhosphorPlacement::WindowTrackingService::windowZoneChanged ( const QString &  windowId,
const QString &  zoneId 
)
signal

◆ zoneAssignments()

const QHash< QString, QStringList > & PhosphorPlacement::WindowTrackingService::zoneAssignments ( ) const
overridevirtual

Get all zone assignments for persistence.

Returns
Map of windowId -> zoneIds (list of zone UUIDs)

Implements PhosphorEngine::IWindowTrackingService.

◆ zoneForWindow()

QString PhosphorPlacement::WindowTrackingService::zoneForWindow ( const QString &  windowId) const
overridevirtual

Get the primary zone ID for a window.

Parameters
windowIdFull window ID
Returns
PhosphorZones::Zone ID or empty string if not assigned

Implements PhosphorEngine::IWindowTrackingService.

◆ zoneGeometry()

QRect PhosphorPlacement::WindowTrackingService::zoneGeometry ( const QString &  zoneId,
const QString &  screenId = QString() 
) const
overridevirtual

Get geometry for a zone on a specific screen.

Parameters
zoneIdPhosphorZones::Zone UUID string
screenIdScreen identifier (empty = primary)
Returns
PhosphorZones::Zone geometry in pixels, or invalid QRect if not found

Implements PhosphorEngine::IWindowTrackingService.

◆ zonesForWindow()

QStringList PhosphorPlacement::WindowTrackingService::zonesForWindow ( const QString &  windowId) const
overridevirtual

Get all zone IDs for a window (multi-zone support)

Parameters
windowIdFull window ID
Returns
List of zone IDs (empty if not assigned)

Implements PhosphorEngine::IWindowTrackingService.


The documentation for this class was generated from the following file: