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

Per-screen snap placement state. More...

#include <phosphor-snap-engine/include/PhosphorSnapEngine/SnapState.h>

Inheritance diagram for PhosphorSnapEngine::SnapState:
[legend]

Classes

struct  UnassignResult
 

Signals

void windowAssigned (const QString &windowId, const QString &zoneId)
 
void windowUnassigned (const QString &windowId)
 
void floatingChanged (const QString &windowId, bool floating)
 
void stateChanged ()
 

Public Member Functions

 SnapState (const QString &screenId, QObject *parent=nullptr)
 
 ~SnapState () override
 
 SnapState (const SnapState &)=delete
 
SnapStateoperator= (const SnapState &)=delete
 
void setWindowRegistry (PhosphorEngine::IWindowRegistry *registry)
 Attach the daemon's shared window registry so every windowId-keyed accessor can canonicalize the incoming id to the stable first-seen composite (instanceId → first observed appId|instanceId).
 
QString screenId () const override
 Screen this state object manages.
 
int windowCount () const override
 Total number of managed windows (tiled + floating).
 
QStringList managedWindows () const override
 All windows managed by this state (tiled + floating).
 
bool containsWindow (const QString &windowId) const override
 Whether the window is in this state's managed set.
 
bool isFloating (const QString &windowId) const override
 Whether the window is floating (excluded from placement).
 
QStringList floatingWindows () const override
 All currently-floating windows.
 
QString placementIdForWindow (const QString &windowId) const override
 Opaque placement identifier for the window's current slot.
 
void assignWindowToZone (const QString &windowId, const QString &zoneId, const QString &screenId, int virtualDesktop)
 
void assignWindowToZones (const QString &windowId, const QStringList &zoneIds, const QString &screenId, int virtualDesktop)
 
UnassignResult unassignWindow (const QString &windowId)
 
bool clearScreenAndDesktop (const QString &windowId)
 Drop ONLY the screen/desktop residence entries, leaving the zone assignment, the floating bit and the pre-float capture untouched.
 
QString zoneForWindow (const QString &windowId) const
 
QStringList zonesForWindow (const QString &windowId) const
 
QStringList windowsInZone (const QString &zoneId) const
 
QStringList snappedWindows () const
 
bool isWindowSnapped (const QString &windowId) const
 
void noteFocused (const QString &windowId)
 Layer-side focus memory for switch-focus-between-floating-and-tiling.
 
QString lastSnappedFocus () const
 
QString lastFloatingFocus () const
 
QString screenForWindow (const QString &windowId) const
 
void recordResidence (const QString &windowId, const QString &screenId, int virtualDesktop)
 Record screen + desktop residence WITHOUT a zone assignment and without touching the floating set.
 
int desktopForWindow (const QString &windowId) const
 
bool reassignDesktop (const QString &windowId, int virtualDesktop)
 Re-stamp a snapped window's virtual-desktop membership to virtualDesktop, keeping its zone and screen.
 
QStringList windowsOnScreenAndDesktop (const QString &screenId, int virtualDesktop) const
 Windows with a recorded desktop assignment (snapped, or floated-on-screen via setFloatingOnScreen / unsnapForFloat) on screenId whose desktop membership is virtualDesktop, sorted by id for deterministic entry-window choice.
 
const QHash< QString, QString > & screenAssignments () const
 
const QHash< QString, int > & desktopAssignments () const
 
void setScreenAssignments (const QHash< QString, QString > &s)
 
void setFloating (const QString &windowId, bool floating)
 
void setFloatingOnScreen (const QString &windowId, const QString &screenId, int virtualDesktop)
 Mark a window floating AND record its screen+desktop without a zone.
 
UnassignResult unsnapForFloat (const QString &windowId)
 Save zone assignment before floating for later restore.
 
QString preFloatZone (const QString &windowId) const
 
QStringList preFloatZones (const QString &windowId) const
 
QString preFloatScreen (const QString &windowId) const
 
bool clearPreFloatZone (const QString &windowId)
 Returns true when an entry was actually removed, so callers can gate their dirty-marking on a real mutation.
 
void addPreFloatZone (const QString &windowId, const QStringList &zoneIds)
 
void addPreFloatScreen (const QString &windowId, const QString &screenId)
 
const QHash< QString, QStringList > & preFloatZoneAssignments () const
 
const QHash< QString, QString > & preFloatScreenAssignments () const
 
void setPreFloatScreenAssignments (const QHash< QString, QString > &a)
 
void windowClosed (const QString &windowId)
 
bool isEmpty () const
 
void clear ()
 
void migrateWindowTo (SnapState *target, const QString &windowId, const QString &newScreenId)
 Move windowId's per-window placement entries (zone assignment, live screen, desktop, floating bit, pre-float zone/screen, auto-snap flag) OUT of this store and INTO target, rewriting the LIVE screen assignment to newScreenId so target->screenForWindow(windowId) reports the destination monitor (the #724 cross-monitor determinism requirement).
 
bool removeWindowData (const QString &windowId)
 Remove ALL of windowId's per-window data from this store (zone/screen/ desktop assignment, floating bit, pre-float zone/screen, auto-snap flag), returning true if anything was removed.
 
void updateLastUsedZone (const QString &zoneId, const QString &screenId, const QString &windowClass, int virtualDesktop)
 Update last-used zone and emit stateChanged.
 
void restoreLastUsedZone (const QString &zoneId, const QString &screenId, const QString &zoneClass, int desktop)
 Restore last-used zone fields from persistence without emitting stateChanged.
 
QString lastUsedZoneId () const
 
QString lastUsedScreenId () const
 
QString lastUsedZoneClass () const
 
int lastUsedDesktop () const
 
quint64 lastUsedSeq () const
 Monotonic stamp bumped every time this store's last-used zone is set to a non-empty value (via updateLastUsedZone / restoreLastUsedZone).
 
void retagLastUsedZoneClass (const QString &newClass)
 
void recordSnapIntent (const QString &windowClass, bool wasUserInitiated)
 
const QSet< QString > & userSnappedClasses () const
 
void setUserSnappedClasses (const QSet< QString > &classes)
 
void markAsAutoSnapped (const QString &windowId)
 
bool isAutoSnapped (const QString &windowId) const
 
bool clearAutoSnapped (const QString &windowId)
 
QSet< QString > buildOccupiedZoneSet (const QString &screenFilter={}, int desktopFilter=0) const
 Build the set of zone IDs currently occupied by snapped windows.
 
int pruneStaleAssignments (const QSet< QString > &aliveWindowIds)
 Remove zone/screen/desktop assignments for windows not in the alive set.
 
const QHash< QString, QStringList > & zoneAssignments () const
 
- Public Member Functions inherited from PhosphorEngine::IPlacementState
virtual ~IPlacementState ()=default
 
virtual int tiledWindowCount () const
 Number of tiled (non-floating) windows in the managed set.
 
virtual int masterCount () const
 Number of master windows (autotile concept; snap returns 1).
 

Detailed Description

Per-screen snap placement state.

Owns the mutable state for manual zone-based snapping: which window is assigned to which zone, floating state, pre-tile geometry for restore, and pre-float zone memory for unfloat. Analogous to PhosphorTiles::TilingState for automatic tiling.

Both SnapState and TilingState implement PhosphorEngine::IPlacementState so the daemon's D-Bus adaptor can read state uniformly without branching on mode. The state itself is within-session; what persists is per-window, in the WindowPlacementStore.

Constructor & Destructor Documentation

◆ SnapState() [1/2]

PhosphorSnapEngine::SnapState::SnapState ( const QString &  screenId,
QObject *  parent = nullptr 
)
explicit

◆ ~SnapState()

PhosphorSnapEngine::SnapState::~SnapState ( )
override

◆ SnapState() [2/2]

PhosphorSnapEngine::SnapState::SnapState ( const SnapState )
delete

Member Function Documentation

◆ addPreFloatScreen()

void PhosphorSnapEngine::SnapState::addPreFloatScreen ( const QString &  windowId,
const QString &  screenId 
)

◆ addPreFloatZone()

void PhosphorSnapEngine::SnapState::addPreFloatZone ( const QString &  windowId,
const QStringList &  zoneIds 
)

◆ assignWindowToZone()

void PhosphorSnapEngine::SnapState::assignWindowToZone ( const QString &  windowId,
const QString &  zoneId,
const QString &  screenId,
int  virtualDesktop 
)

◆ assignWindowToZones()

void PhosphorSnapEngine::SnapState::assignWindowToZones ( const QString &  windowId,
const QStringList &  zoneIds,
const QString &  screenId,
int  virtualDesktop 
)

◆ buildOccupiedZoneSet()

QSet< QString > PhosphorSnapEngine::SnapState::buildOccupiedZoneSet ( const QString &  screenFilter = {},
int  desktopFilter = 0 
) const

Build the set of zone IDs currently occupied by snapped windows.

Desktop 0 means "on all desktops" per KWin convention — windows with desktop 0 pass the filter and appear occupied on every desktop.

◆ clear()

void PhosphorSnapEngine::SnapState::clear ( )

◆ clearAutoSnapped()

bool PhosphorSnapEngine::SnapState::clearAutoSnapped ( const QString &  windowId)

◆ clearPreFloatZone()

bool PhosphorSnapEngine::SnapState::clearPreFloatZone ( const QString &  windowId)

Returns true when an entry was actually removed, so callers can gate their dirty-marking on a real mutation.

◆ clearScreenAndDesktop()

bool PhosphorSnapEngine::SnapState::clearScreenAndDesktop ( const QString &  windowId)

Drop ONLY the screen/desktop residence entries, leaving the zone assignment, the floating bit and the pre-float capture untouched.

For the cross-engine handoff of a window that was FLOATING but not snapped: unassignWindow never runs for it (no zone assignment to clear), so setFloatingOnScreen's residence writes survived in this store. They are invisible to reverse-map reads but NOT to raw scans like windowsOnScreenAndDesktop, which feeds cross-desktop focus — snap could then offer and activate a window another engine now owns. removeWindowData is the wrong primitive here: it also wipes the pre-float capture that handoffRelease deliberately preserves.

Returns
true when an entry was removed.

◆ containsWindow()

bool PhosphorSnapEngine::SnapState::containsWindow ( const QString &  windowId) const
overridevirtual

Whether the window is in this state's managed set.

Implements PhosphorEngine::IPlacementState.

◆ desktopAssignments()

const QHash< QString, int > & PhosphorSnapEngine::SnapState::desktopAssignments ( ) const
inline

◆ desktopForWindow()

int PhosphorSnapEngine::SnapState::desktopForWindow ( const QString &  windowId) const

◆ floatingChanged

void PhosphorSnapEngine::SnapState::floatingChanged ( const QString &  windowId,
bool  floating 
)
signal

◆ floatingWindows()

QStringList PhosphorSnapEngine::SnapState::floatingWindows ( ) const
overridevirtual

All currently-floating windows.

Implements PhosphorEngine::IPlacementState.

◆ isAutoSnapped()

bool PhosphorSnapEngine::SnapState::isAutoSnapped ( const QString &  windowId) const

◆ isEmpty()

bool PhosphorSnapEngine::SnapState::isEmpty ( ) const

◆ isFloating()

bool PhosphorSnapEngine::SnapState::isFloating ( const QString &  windowId) const
overridevirtual

Whether the window is floating (excluded from placement).

Implements PhosphorEngine::IPlacementState.

◆ isWindowSnapped()

bool PhosphorSnapEngine::SnapState::isWindowSnapped ( const QString &  windowId) const

◆ lastFloatingFocus()

QString PhosphorSnapEngine::SnapState::lastFloatingFocus ( ) const
inline

◆ lastSnappedFocus()

QString PhosphorSnapEngine::SnapState::lastSnappedFocus ( ) const
inline

◆ lastUsedDesktop()

int PhosphorSnapEngine::SnapState::lastUsedDesktop ( ) const
inline

◆ lastUsedScreenId()

QString PhosphorSnapEngine::SnapState::lastUsedScreenId ( ) const
inline

◆ lastUsedSeq()

quint64 PhosphorSnapEngine::SnapState::lastUsedSeq ( ) const
inline

Monotonic stamp bumped every time this store's last-used zone is set to a non-empty value (via updateLastUsedZone / restoreLastUsedZone).

0 means "never set". The facade compares stamps across stores to pick the single representative last-used zone it persists to disk.

◆ lastUsedZoneClass()

QString PhosphorSnapEngine::SnapState::lastUsedZoneClass ( ) const
inline

◆ lastUsedZoneId()

QString PhosphorSnapEngine::SnapState::lastUsedZoneId ( ) const
inline

◆ managedWindows()

QStringList PhosphorSnapEngine::SnapState::managedWindows ( ) const
overridevirtual

All windows managed by this state (tiled + floating).

Implements PhosphorEngine::IPlacementState.

◆ markAsAutoSnapped()

void PhosphorSnapEngine::SnapState::markAsAutoSnapped ( const QString &  windowId)

◆ migrateWindowTo()

void PhosphorSnapEngine::SnapState::migrateWindowTo ( SnapState target,
const QString &  windowId,
const QString &  newScreenId 
)

Move windowId's per-window placement entries (zone assignment, live screen, desktop, floating bit, pre-float zone/screen, auto-snap flag) OUT of this store and INTO target, rewriting the LIVE screen assignment to newScreenId so target->screenForWindow(windowId) reports the destination monitor (the #724 cross-monitor determinism requirement).

The pre-float zone/screen ride along UNCHANGED: they name the SOURCE monitor's home zone, preserved so an unfloat on any monitor restores the home zone (cross-monitor restore is allowed; there is no refusal guard). The global-scalar fields (last-used-zone, user-snapped classes) are NOT moved — they stay global. No-op when target is null/this or the window has no entry in this store.

◆ noteFocused()

void PhosphorSnapEngine::SnapState::noteFocused ( const QString &  windowId)

Layer-side focus memory for switch-focus-between-floating-and-tiling.

SnapState holds no focus slot of its own (the engine reads the live focus from INavigationStateProvider on demand), so these remember only what noteFocused() classified from the engine's windowFocused reports: the last SNAPPED window focused and the last FLOATING window focused. Residence-only windows (screen recorded, no zone, no float bit) belong to neither layer and update neither memory. Cleared when the remembered window changes layer (setFloating and friends), leaves the store (removeWindowData, migrateWindowTo), and never serialized — focus history dies with the session. Consumers validate before use, so a stale value degrades to a fallback scan, never a wrong activation. Deliberate divergence from TilingState: the tiling twin RETAINS a non-focused window's old-side memory on a layer change (its transient floats round-trip), which needs a focus slot to condition on — snap holds none, so it clears unconditionally.

◆ operator=()

SnapState & PhosphorSnapEngine::SnapState::operator= ( const SnapState )
delete

◆ placementIdForWindow()

QString PhosphorSnapEngine::SnapState::placementIdForWindow ( const QString &  windowId) const
overridevirtual

Opaque placement identifier for the window's current slot.

Snap mode: zone UUID. Autotile mode: tiling-order index as string. Empty if the window is floating or unassigned.

NO in-tree caller today — the three implementations are reached only from their own tests. Kept because it is the one piece of this interface that answers "where is this window" in a form comparable ACROSS modes, which is what a cross-mode restore or a support bundle would need, and each implementation is a handful of lines over state it already holds. Anyone auditing for dead code has now found this note rather than the silence; delete it if the answer is still no consumer.

Implements PhosphorEngine::IPlacementState.

◆ preFloatScreen()

QString PhosphorSnapEngine::SnapState::preFloatScreen ( const QString &  windowId) const

◆ preFloatScreenAssignments()

const QHash< QString, QString > & PhosphorSnapEngine::SnapState::preFloatScreenAssignments ( ) const
inline

◆ preFloatZone()

QString PhosphorSnapEngine::SnapState::preFloatZone ( const QString &  windowId) const

◆ preFloatZoneAssignments()

const QHash< QString, QStringList > & PhosphorSnapEngine::SnapState::preFloatZoneAssignments ( ) const
inline

◆ preFloatZones()

QStringList PhosphorSnapEngine::SnapState::preFloatZones ( const QString &  windowId) const

◆ pruneStaleAssignments()

int PhosphorSnapEngine::SnapState::pruneStaleAssignments ( const QSet< QString > &  aliveWindowIds)

Remove zone/screen/desktop assignments for windows not in the alive set.

◆ reassignDesktop()

bool PhosphorSnapEngine::SnapState::reassignDesktop ( const QString &  windowId,
int  virtualDesktop 
)

Re-stamp a snapped window's virtual-desktop membership to virtualDesktop, keeping its zone and screen.

The one place a desktop is re-stamped on an EXISTING assignment without touching its zone or screen — used by cross-desktop directional move, where the window relocates to another desktop but keeps its snapped slot. (Full assignment writes can also carry a non-current desktop: RouteToDesktop pins and batch-resnap desktop preservation both route through assignWindowToZones.) No-op for a window that isn't currently assigned. Returns true on change.

◆ recordResidence()

void PhosphorSnapEngine::SnapState::recordResidence ( const QString &  windowId,
const QString &  screenId,
int  virtualDesktop 
)

Record screen + desktop residence WITHOUT a zone assignment and without touching the floating set.

This is how a cross-engine handoff adopts a window as a plain FREE window (snapping's default for unmanaged windows): the arrival carries no resolvable zone and is not floating, but the adoption must still be VISIBLE — guardedHandoff verifies with isWindowTracked() after handoffReceive returns, and with no zone and no float only the screen-assignment arm can answer. Residence-only is an established state in this model (unsnapForFloat preserves it via clearZoneAssignment's preserve flag) and handoffRelease clears it symmetrically through clearScreenAndDesktop.

◆ recordSnapIntent()

void PhosphorSnapEngine::SnapState::recordSnapIntent ( const QString &  windowClass,
bool  wasUserInitiated 
)

◆ removeWindowData()

bool PhosphorSnapEngine::SnapState::removeWindowData ( const QString &  windowId)

Remove ALL of windowId's per-window data from this store (zone/screen/ desktop assignment, floating bit, pre-float zone/screen, auto-snap flag), returning true if anything was removed.

Emits NO signal: this is the snap engine's single-owner enforcement primitive — it evicts a window from every store EXCEPT the one the reverse map owns it in, so a re-keyed window never leaves a phantom copy behind (see SnapEngine::stateForWindowOnScreen). An evicted phantom was never a legitimate resident here, so firing windowUnassigned/stateChanged for it would be wrong. windowClosed() is the signalling wrapper for the genuine "this window went away" case.

◆ restoreLastUsedZone()

void PhosphorSnapEngine::SnapState::restoreLastUsedZone ( const QString &  zoneId,
const QString &  screenId,
const QString &  zoneClass,
int  desktop 
)

Restore last-used zone fields from persistence without emitting stateChanged.

◆ retagLastUsedZoneClass()

void PhosphorSnapEngine::SnapState::retagLastUsedZoneClass ( const QString &  newClass)
inline

◆ screenAssignments()

const QHash< QString, QString > & PhosphorSnapEngine::SnapState::screenAssignments ( ) const
inline

◆ screenForWindow()

QString PhosphorSnapEngine::SnapState::screenForWindow ( const QString &  windowId) const

◆ screenId()

QString PhosphorSnapEngine::SnapState::screenId ( ) const
overridevirtual

Screen this state object manages.

Implements PhosphorEngine::IPlacementState.

◆ setFloating()

void PhosphorSnapEngine::SnapState::setFloating ( const QString &  windowId,
bool  floating 
)

◆ setFloatingOnScreen()

void PhosphorSnapEngine::SnapState::setFloatingOnScreen ( const QString &  windowId,
const QString &  screenId,
int  virtualDesktop 
)

Mark a window floating AND record its screen+desktop without a zone.

Used by cross-engine handoff when the snap engine adopts a floating window from another engine — the screen entry is what makes the snap engine answerable for "where does this window live" lookups (screenAssignments / screenForTrackedWindow) so future shortcut routing reaches this engine.

◆ setPreFloatScreenAssignments()

void PhosphorSnapEngine::SnapState::setPreFloatScreenAssignments ( const QHash< QString, QString > &  a)
inline

◆ setScreenAssignments()

void PhosphorSnapEngine::SnapState::setScreenAssignments ( const QHash< QString, QString > &  s)
inline

◆ setUserSnappedClasses()

void PhosphorSnapEngine::SnapState::setUserSnappedClasses ( const QSet< QString > &  classes)
inline

◆ setWindowRegistry()

void PhosphorSnapEngine::SnapState::setWindowRegistry ( PhosphorEngine::IWindowRegistry registry)
inline

Attach the daemon's shared window registry so every windowId-keyed accessor can canonicalize the incoming id to the stable first-seen composite (instanceId → first observed appId|instanceId).

This makes the snap stores immune to the cross-process re-identification skew where the KWin effect restarts after a window's WM_CLASS mutated and re-derives a different composite for the same window (issue #628). Borrowed pointer, not owned (the daemon owns the registry); null in unit tests, in which case the accessors key on the raw id verbatim (today's behaviour).

◆ snappedWindows()

QStringList PhosphorSnapEngine::SnapState::snappedWindows ( ) const

◆ stateChanged

void PhosphorSnapEngine::SnapState::stateChanged ( )
signal

◆ unassignWindow()

UnassignResult PhosphorSnapEngine::SnapState::unassignWindow ( const QString &  windowId)

◆ unsnapForFloat()

UnassignResult PhosphorSnapEngine::SnapState::unsnapForFloat ( const QString &  windowId)

Save zone assignment before floating for later restore.

◆ updateLastUsedZone()

void PhosphorSnapEngine::SnapState::updateLastUsedZone ( const QString &  zoneId,
const QString &  screenId,
const QString &  windowClass,
int  virtualDesktop 
)

Update last-used zone and emit stateChanged.

◆ userSnappedClasses()

const QSet< QString > & PhosphorSnapEngine::SnapState::userSnappedClasses ( ) const
inline

◆ windowAssigned

void PhosphorSnapEngine::SnapState::windowAssigned ( const QString &  windowId,
const QString &  zoneId 
)
signal

◆ windowClosed()

void PhosphorSnapEngine::SnapState::windowClosed ( const QString &  windowId)

◆ windowCount()

int PhosphorSnapEngine::SnapState::windowCount ( ) const
overridevirtual

Total number of managed windows (tiled + floating).

Implements PhosphorEngine::IPlacementState.

◆ windowsInZone()

QStringList PhosphorSnapEngine::SnapState::windowsInZone ( const QString &  zoneId) const

◆ windowsOnScreenAndDesktop()

QStringList PhosphorSnapEngine::SnapState::windowsOnScreenAndDesktop ( const QString &  screenId,
int  virtualDesktop 
) const

Windows with a recorded desktop assignment (snapped, or floated-on-screen via setFloatingOnScreen / unsnapForFloat) on screenId whose desktop membership is virtualDesktop, sorted by id for deterministic entry-window choice.

Iterates the desktop-assignment map; a window floated without a desktop slot is not in that map and is excluded. Used by cross-desktop directional focus to find a window to land on.

◆ windowUnassigned

void PhosphorSnapEngine::SnapState::windowUnassigned ( const QString &  windowId)
signal

◆ zoneAssignments()

const QHash< QString, QStringList > & PhosphorSnapEngine::SnapState::zoneAssignments ( ) const
inline

◆ zoneForWindow()

QString PhosphorSnapEngine::SnapState::zoneForWindow ( const QString &  windowId) const

◆ zonesForWindow()

QStringList PhosphorSnapEngine::SnapState::zonesForWindow ( const QString &  windowId) const

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