Unified placement engine interface. More...
#include <phosphor-engine/include/PhosphorEngine/IPlacementEngine.h>
Classes | |
| struct | DragInsertTarget |
| Where a drag-insert preview should place the dragged window, in the TARGET ENGINE's slot vocabulary. More... | |
| struct | HandoffContext |
| Context for a cross-engine window handoff. More... | |
Public Types | |
| enum class | LayoutSupport { None , Placement , Templates } |
| How this engine relates to user-selectable layouts — the entries the layout picker, drag layout popup, quick-layout slots and layout cycle operate on. More... | |
Public Member Functions | |
| virtual | ~IPlacementEngine ()=default |
| IPlacementEngine (const IPlacementEngine &)=delete | |
| IPlacementEngine & | operator= (const IPlacementEngine &)=delete |
| virtual bool | isActiveOnScreen (const QString &screenId) const =0 |
| Whether this engine is active on the given screen. | |
| virtual void | windowOpened (const QString &windowId, const QString &screenId, int minWidth=0, int minHeight=0)=0 |
| A new window appeared on this engine's screen. | |
| void | windowOpened (const QString &windowId, const QString &screenId) |
| Convenience overload — equivalent to windowOpened(id, screen, 0, 0). | |
| virtual bool | claimCrossScreenReopen (const QString &windowId, const QString &openingScreenId, int minWidth=0, int minHeight=0) |
| OPTIONAL: cross-screen session reclaim, the tiling-engine counterpart of the snap engine's recorded-screen restore. | |
| virtual QString | heldScreenForWindow (const QString &windowId) const |
| OPTIONAL: the screen this engine genuinely HOLDS the window on IN THE SCREEN'S CURRENT CONTEXT — a MEMBERSHIP answer (tiled or engine-floating both count; a phantom reverse-map key does not), empty when the engine does not hold it or holds it only in a background context. | |
| virtual void | beginArrivalBurst () |
| Bracket a BURST of windowOpened calls delivered together (the adaptor's three dispatch loops: windowsOpenedBatch, the deferred-open flush, and the parked-open replay — daemon bring-up re-announce and mode flips). | |
| virtual void | endArrivalBurst () |
| virtual void | windowClosed (const QString &windowId)=0 |
| A window was closed. | |
| virtual void | windowFocused (const QString &windowId, const QString &screenId)=0 |
| A window gained focus (called when the compositor reports activation). | |
| virtual void | toggleWindowFloat (const QString &windowId, const QString &screenId)=0 |
| Toggle between managed and floating. | |
| virtual void | setWindowFloat (const QString &windowId, bool shouldFloat, const QString &screenId=QString())=0 |
| Set floating state explicitly (directional, not toggle). | |
| virtual void | focusInDirection (const QString &direction, const NavigationContext &ctx)=0 |
| Move keyboard focus to the adjacent window. | |
| virtual void | moveFocusedInDirection (const QString &direction, const NavigationContext &ctx)=0 |
| Move the focused window to the adjacent slot. | |
| virtual void | spanFocusedInDirection (const QString &direction, const NavigationContext &ctx) |
| Grow or shrink the focused window's zone span toward the direction: extend into the adjacent zone(s) when some exist beyond that edge, otherwise retract the opposite edge. | |
| virtual void | switchFocusBetweenFloatingAndTiling (const QString &screenId) |
| Jump focus between the float layer and the engine's placement layer (niri's switch-focus-between-floating-and-tiling): activate the last focused window on the OTHER layer, falling back to a scan when that memory is stale. | |
| virtual void | swapFocusedInDirection (const QString &direction, const NavigationContext &ctx)=0 |
| Swap the focused window with the adjacent window. | |
| virtual void | moveFocusedToPosition (int position, const NavigationContext &ctx)=0 |
| Move the focused window to the Nth position. | |
| virtual void | rotateWindows (bool clockwise, const NavigationContext &ctx)=0 |
| Rotate all managed windows on the screen. | |
| virtual void | reapplyLayout (const NavigationContext &ctx)=0 |
| Re-apply the current layout to all managed windows. | |
| virtual void | snapAllWindows (const NavigationContext &ctx)=0 |
| Bring every unmanaged window on the screen back under this engine's placement (zones for snap, the strip for scrolling). | |
| virtual void | cycleFocus (bool forward, const NavigationContext &ctx)=0 |
| Cycle keyboard focus through managed windows. | |
| virtual void | pushToEmptyZone (const NavigationContext &ctx)=0 |
| Move the focused window to the first empty slot. | |
| virtual void | restoreFocusedWindow (const NavigationContext &ctx)=0 |
| Restore the focused window out of its managed state. | |
| virtual void | toggleFocusedFloat (const NavigationContext &ctx)=0 |
| Toggle the focused window between managed and floating. | |
| virtual QSet< QString > | activeScreens () const |
| virtual void | setActiveScreens (const QSet< QString > &screens) |
| virtual void | reapplyManagedWindowAppearance () |
| Re-drive the compositor's per-window appearance (border, hidden title bar) for every window this engine currently manages, WITHOUT recomputing the layout — windows keep their current zones/positions. | |
| virtual std::optional< WindowPlacement > | capturePlacement (const QString &windowId) const |
Report windowId's CURRENT placement for persistence, or nullopt if this engine does not manage it. | |
| virtual bool | restorePlacement (const WindowPlacement &placement, const QString &screenId) |
Apply placement to a (re)opening window on screenId. | |
| virtual QStringList | managedWindowOrder (const QString &screenId) const |
| virtual void | setInitialWindowOrder (const QString &screenId, const QStringList &windowIds) |
| virtual QString | managedFocusedWindow (const QString &screenId) const |
The window this engine considers focused on screenId, or empty. | |
| virtual int | stickyPinnedDesktopForScreen (const QString &screenId) const |
The desktop this engine has PINNED screenId to, or 0 when it has not pinned it (which is the normal case, and the default here). | |
| virtual void | setInitialFocusedWindow (const QString &screenId, const QString &windowId) |
| Hand the incoming engine the focus captured from the outgoing one. | |
| virtual void | applyPerScreenConfig (const QString &screenId, const QVariantMap &overrides) |
| virtual void | clearPerScreenConfig (const QString &screenId) |
| virtual QVariantMap | perScreenOverrides (const QString &screenId) const |
| virtual void | markModeSpecificFloated (const QString &windowId) |
| virtual bool | isModeSpecificFloated (const QString &windowId) const |
| virtual void | clearModeSpecificFloatMarker (const QString &windowId) |
| virtual bool | hasDragInsertPreview () const |
| virtual bool | beginDragInsertPreview (const QString &windowId, const QString &screenId) |
| virtual void | commitDragInsertPreview () |
| virtual void | cancelDragInsertPreview () |
| virtual QString | dragInsertPreviewScreenId () const |
| virtual QString | dragInsertPreviewPriorScreenId () const |
| The screen the previewed window was on BEFORE begin adopted it, or empty when it had no prior state (begin took it from untracked) or no preview is live. | |
| virtual DragInsertTarget | computeDragInsertTargetAtPoint (const QString &screenId, const QPoint &cursorPos) const |
| Compute the drop target for a cursor position on a managed screen. | |
| virtual void | updateDragInsertPreview (const DragInsertTarget &target) |
| Update the drop target for an active drag-insert preview. | |
| virtual bool | dragAutoScrollTick (const QString &screenId, const QPoint &cursorPos, qreal dtSeconds) |
| Advance edge auto-scroll for a live drag-insert preview (niri's dnd-edge-view-scroll): an engine whose layout is a scrollable viewport moves its VIEW while the cursor sits inside a band at the work area's edge, so a drop can reach a column that is off screen. | |
| virtual bool | dragAutoScrollActive () const |
| Whether edge auto-scroll currently owns the drop target. | |
| virtual void | cancelDragAutoScroll () |
| Give the drop target back and forget any armed band, WITHOUT moving the view or re-aiming. | |
| virtual QRect | dragInsertIndicatorRect (const QString &screenId) const |
The rect the dragged window would occupy if the live preview were dropped now, in absolute px on screenId, for a caller that wants to PAINT the drop target. | |
| virtual void | setInteractiveDragWindow (const QString &windowId) |
| The window currently under a compositor interactive move (the whole drag, preview or not). | |
| virtual bool | isWindowTracked (const QString &windowId) const |
| virtual bool | isWindowManaged (const QString &windowId) const |
| Whether the engine considers the window "managed" (eligible for layout operations). | |
| virtual bool | isWindowTiled (const QString &windowId) const |
| Whether the window is actively tiled (engine-owned, non-floating). | |
| virtual QString | screenForTrackedWindow (const QString &windowId) const |
| Return the screen this engine considers the window to be on, or empty if the window isn't tracked by this engine. | |
| virtual QSize | windowMinimumSize (const QString &windowId) const |
| The window's client-reported minimum size as last known by this engine, or an UNKNOWN answer when it has none. | |
| virtual void | windowMinSizeUpdated (const QString &windowId, int minWidth, int minHeight) |
| Update a window's minimum size after the initial windowOpened. | |
| virtual void | onWindowResized (const QString &windowId, const QRect &oldFrame, const QRect &newFrame, const QString &screenId) |
| Notify the engine that a tracked window finished an interactive resize. | |
| virtual void | handoffReceive (const HandoffContext &ctx) |
| Receive ownership of a window from another engine. | |
| virtual void | handoffRelease (const QString &windowId) |
| Release ownership of a window WITHOUT modifying its geometry. | |
| virtual QString | engineId () const |
| Stable engine identity for HandoffContext.fromEngineId. | |
| virtual LayoutSupport | layoutSupport () const |
| Default None: an engine must opt in to being a layout consumer. | |
| virtual bool | providesDragInsertSelector () const |
| Whether the daemon's edge-triggered drag popup (the zone selector surface) should render this engine's DRAG-INSERT vocabulary — strip column cards whose gap / join / half targets translate into DragInsertTarget — instead of zone layouts, on screens this engine owns. | |
| virtual QString | algorithmId () const |
| virtual void | setAlgorithm (const QString &algorithmId) |
| virtual bool | isEnabled () const noexcept |
| virtual QString | activeScreen () const |
| virtual void | setActiveScreenHint (const QString &screenId) |
| virtual void | setCurrentDesktop (int desktop) |
| virtual void | setCurrentDesktopForScreen (const QString &screenId, int desktop) |
| Set a single screen's current virtual desktop (Plasma 6.7 "switch desktops
independently for each screen"). | |
| virtual void | clearCurrentDesktopForScreen (const QString &screenId) |
| Drop a screen's per-output desktop, reverting it to the global current. | |
| virtual void | setCurrentActivity (const QString &activity) |
| virtual void | setCrossSurfaceResolver (ICrossSurfaceResolver *resolver) |
| Inject the cross-surface resolver used to find a neighbouring output / desktop when directional navigation reaches a surface boundary. | |
| virtual void | updateStickyScreenPins (const std::function< bool(const QString &)> &isWindowSticky) |
| virtual QSet< int > | desktopsWithActiveState () const |
| virtual void | pruneStatesForDesktop (int removedDesktop) |
| virtual void | pruneStatesForActivities (const QStringList &validActivities) |
| virtual void | pruneStatesForRemovedScreen (const QString &physicalScreenId) |
| Prune per-(screen, desktop, activity) state for a PHYSICALLY REMOVED output (monitor hot-unplug), matching every virtual sub-screen of the removed physical id. | |
| virtual void | refreshConfigFromSettings () |
| Re-read all tuning values from the engine's settings interface. | |
| virtual qreal | effectiveSplitRatioStep (const QString &screenId) const |
| virtual int | runtimeMaxWindows () const |
| Runtime max-windows limit. | |
| virtual std::optional< int > | savedMaxWindowsForAlgorithm (const QString &algorithmId) const |
The user's saved per-algorithm max-windows tuning for algorithmId, or std::nullopt when the engine keeps no such slot. | |
| virtual void | retile (const QString &screenId=QString()) |
| virtual void | scheduleRetileForScreen (const QString &screenId) |
| virtual void | setWindowRegistry (QObject *registry) |
| Attach a window-class registry (QObject carrying WindowRegistry). | |
| virtual void | increaseMasterRatio (qreal delta=kDefaultSplitRatioStep) |
| virtual void | decreaseMasterRatio (qreal delta=kDefaultSplitRatioStep) |
| virtual void | increaseMasterCount () |
| virtual void | decreaseMasterCount () |
| virtual void | focusMaster () |
| virtual void | swapFocusedWithMaster () |
| virtual void | saveState ()=0 |
| virtual void | loadState ()=0 |
| virtual IPlacementState * | stateForScreen (const QString &screenId)=0 |
| Per-screen state object for the given screen. | |
| virtual const IPlacementState * | stateForScreen (const QString &screenId) const =0 |
Static Public Attributes | |
| static constexpr qreal | kDefaultSplitRatioStep = 0.05 |
| One home for the master/split ratio step so the default return below and the two default arguments cannot drift apart. | |
Protected Member Functions | |
| IPlacementEngine ()=default | |
Unified placement engine interface.
Methods are divided into two categories:
REQUIRED (pure virtual, = 0): Every engine MUST implement these. They represent the core contract: screen ownership, window lifecycle, float management, and navigation intents.
OPTIONAL (have default no-op implementations): Engines override only the capabilities they support. A snap engine ignores master operations; an autotile engine ignores per-screen config. The defaults are safe no-ops so the daemon can call any method without branching on engine type.
All three engines — snap (manual zone layouts), autotile (automatic tiling algorithms), and scrolling (niri-style column strip) — implement this so the daemon can dispatch all window lifecycle events and user navigation intents through a single polymorphic call — zero mode branches.
Each method represents a USER INTENT, not a mode-specific implementation step. "Move focused window left" has different internal meaning in tile-swap mode vs. zone-snap mode, but the user's request is the same — the interface names the request and each engine fulfills it in its own terms.
The REQUIRED navigation intents are idempotent with respect to "no focused window" — each engine's implementation emits navigation feedback with a sensible reason code when there's nothing to act on, rather than erroring out. The OPTIONAL surface below does not share that promise: its defaults are deliberately silent no-ops.
|
strong |
How this engine relates to user-selectable layouts — the entries the layout picker, drag layout popup, quick-layout slots and layout cycle operate on.
The daemon consults this per screen (via the router's engineFor) to decide what layout-selection UI and shortcuts mean there.
|
protecteddefault |
|
virtualdefault |
|
delete |
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Bracket a BURST of windowOpened calls delivered together (the adaptor's three dispatch loops: windowsOpenedBatch, the deferred-open flush, and the parked-open replay — daemon bring-up re-announce and mode flips).
The cross-screen reclaim's windowOpened re-entry is a fourth caller: inside the tiling dispatch it inherits that loop's bracket; off the snap facade it is deliberately UNBRACKETED — each resolveWindowRestore is its own D-Bus message, so there is no batch to bracket, matching the per-window cadence snap restores have always had on that channel. An engine that applies geometry per arrival may defer those applies until endArrivalBurst so a restore of an unchanged session resolves one final layout instead of N visible intermediates marching across the screen. Defaults are no-ops: an engine whose arrivals already coalesce (autotile's queued retile) needs nothing. Brackets may nest; only the outermost end flushes. Model state is fully updated during the burst either way — only the compositor-facing geometry apply is deferred.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Give the drop target back and forget any armed band, WITHOUT moving the view or re-aiming.
For a caller that is taking over aiming by another route (the strip selector popup) and needs the engine to stop owning the target and to serve a fresh start delay next time.
Distinct from letting a tick disarm on its own: a tick reads the cursor, so it can only release ownership when the cursor has actually left the band, and it can just as easily TAKE ownership. This never takes it.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Report windowId's CURRENT placement for persistence, or nullopt if this engine does not manage it.
Fill the engine's EngineSlot — state from its token vocabulary (free/floating/snapped/tiled/...) plus its slot reference (zone IDs / tile order) — under engines[engineId()], and the screen/desktop/ activity context. Do NOT set freeGeometryByScreen: the capture orchestrator fills the shared free/float geometry from the live frame, and only when the state is free/floating, so a managed rect never becomes the float-back.
This is the polymorphic capture seam the common layer drives — the WTA close hook and the save-time snapshot call it for every window.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
OPTIONAL: cross-screen session reclaim, the tiling-engine counterpart of the snap engine's recorded-screen restore.
Offered a window that opened on openingScreenId — a screen this engine may not own — the engine checks the unified placement store for ITS OWN managed slot recorded on a DIFFERENT screen that is still in this engine's mode (PhosphorEngine::pendingCrossScreenManagedRestore), and on a match adopts the window into that recorded home screen (its retile then physically moves the window there). KWin's session restore opens windows on a nondeterministic output, so without this a whole strip's windows strand floated on whatever monitor KWin picked at login. Default false: an engine without a cross-screen restore story (snap claims through resolveWindowRestore instead) never claims here.
Contract for implementations:
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Drop a screen's per-output desktop, reverting it to the global current.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Compute the drop target for a cursor position on a managed screen.
Returns an invalid target when the screen has no active state.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Cycle keyboard focus through managed windows.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Whether edge auto-scroll currently owns the drop target.
True from the moment the band's delay elapses until the cursor leaves the band, the preview ends, the strip shrinks to fit the viewport, the feature is switched off, or any other condition that makes the scroll incoherent (the implementation's disarm paths are the full list — a vanished state, a dead work area, no visible column, a foreign screen). Not an exhaustive contract, so do not read it as one. Reaching a strip end does NOT end ownership: the view is pinned but the cursor is still asking to insert past that edge, and that edge slot stays the promise. Handing the target back there would resume per-column hit-testing the instant the strip pins, which is the churn this whole mechanism exists to prevent.
While true the caller keeps pushing the indicator but must leave computeDragInsertTargetAtPoint alone.
|
inlinevirtual |
Advance edge auto-scroll for a live drag-insert preview (niri's dnd-edge-view-scroll): an engine whose layout is a scrollable viewport moves its VIEW while the cursor sits inside a band at the work area's edge, so a drop can reach a column that is off screen.
Structure is untouched — this is the one thing a DETACH-ONCE engine may move mid-drag.
Driven by the daemon's repeating drag-scroll timer, NOT by cursor motion: the whole point is that a PARKED cursor keeps scrolling, and motion events stop arriving the moment the hand stops. dtSeconds is the real elapsed time since the previous tick, so the speed ramp is frame-rate independent and a stalled timer cannot lurch.
Returns true when the caller should REPAINT the drop indicator, which is not the same as "the view moved". A tick that is pinned at a strip end moves nothing yet still rewrites the owned target, and a tick that carries the cursor out of the band hands the target back and repairs it — both need the indicator redrawn. An implementation that returned true only for actual view motion would drop those repaints.
While this is scrolling, the implementation OWNS the drop target: it writes the edge slot itself and the caller must not re-hit-test (see dragAutoScrollActive). Columns sliding under a stationary cursor otherwise re-resolve the target on every boundary that passes, which flips the indicator between a new column and a join.
|
inlinevirtual |
The rect the dragged window would occupy if the live preview were dropped now, in absolute px on screenId, for a caller that wants to PAINT the drop target.
Empty when no preview is live, no target has been hit-tested yet, or the preview belongs to another screen.
Measured in the layout's CURRENT view. A drop may additionally scroll the view — the scroll engine focuses the dropped window, which can re-anchor the strip — so this marks the place under the cursor that the user is aiming at, not the screen position the window settles at once any post-drop scroll finishes. Painting the post-scroll position would move the indicator away from the cursor while the user is still choosing, which is the worse of the two.
Default empty, and that is the right answer for an engine that restructures live: autotile's feedback IS its restructure, so painting a second indicator over it would double-report the same thing. Only an engine that defers structure to the drop (the scroll strip, per the DETACH-ONCE contract above) has a target that is otherwise invisible.
Mostly not clamped to the viewport — a join target's rect is where the slot genuinely is — with two deliberate NEW-COLUMN exceptions, both niri's insert-hint rules: a before-the-first slot is placed just OUTSIDE the first column (its raw post-insert position coincides with that column and would read as "replace this"), and any new-column slot past a visible edge is clamped so at least half the rect stays on screen. Without the clamp, the end slots of a FULL viewport resolve entirely off screen and the overlay clips the indicator away, leaving the drop that most needs feedback with none; the half-in band at the edge marks "insert past this edge" without pretending to be the slot's true position.
|
inlinevirtual |
The screen the previewed window was on BEFORE begin adopted it, or empty when it had no prior state (begin took it from untracked) or no preview is live.
Distinct from dragInsertPreviewScreenId whenever the drag crossed outputs, and the two together are what a caller needs to decide whether an output going away concerns this preview: cancel restores the window to the PRIOR screen, so a preview whose prior screen is disappearing can no longer be cancelled meaningfully even though its target survives.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
|
inlinevirtual |
Stable engine identity for HandoffContext.fromEngineId.
Conventional values: "snap" / "autotile" / "scrolling". Empty string means "unidentified" and disables receive-side reasoning that depends on the source mode.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Move keyboard focus to the adjacent window.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Receive ownership of a window from another engine.
Implementations should:
windowFloatingChanged / placement signals their normal placement paths emit, so downstream state stays consistent.Default is a no-op so engines that don't yet implement the handoff don't reject the call — the orchestrator falls back to its legacy path.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Release ownership of a window WITHOUT modifying its geometry.
Implementations should:
Default is a no-op for the same reason as handoffReceive.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
OPTIONAL: the screen this engine genuinely HOLDS the window on IN THE SCREEN'S CURRENT CONTEXT — a MEMBERSHIP answer (tiled or engine-floating both count; a phantom reverse-map key does not), empty when the engine does not hold it or holds it only in a background context.
This exists for the adaptor's post-reclaim ownership check: after a cross-screen reclaim, the effect's already-queued arrival announce still carries the ARRIVAL screen, and dispatching it would migrate the window straight back. isWindowTracked cannot serve — it answers from the raw reverse-map key, which a refused adoption can leave dangling (its ~20 callers want exactly that raw semantic, so its meaning must not change). isWindowManaged/isWindowTiled cannot serve either — both exclude engine-floating windows, which a reclaim can legitimately produce.
CURRENT-context only, and that restriction is what keeps the check from suppressing repair. A reclaim's adoption always keys by the home screen's current context, so a fresh reclaim is always visible here; a hold in a BACKGROUND context (a mode flip preserves other-desktop states and their keys) is never a fresh reclaim, and the announce that would heal such a stale hold — the engines' own cross-screen migration in windowOpened — must not be refused. A stale hold in the CURRENT context is still indistinguishable from a fresh one here and remains healed by windowFocused instead.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Whether this engine is active on the given screen.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtualnoexcept |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Whether the engine considers the window "managed" (eligible for layout operations).
Semantics are engine-specific:
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Whether the window is actively tiled (engine-owned, non-floating).
Distinct from isWindowTracked (which includes floating windows).
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Default None: an engine must opt in to being a layout consumer.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
The window this engine considers focused on screenId, or empty.
The focus half of the mode-transition capture that managedWindowOrder supplies the position half of. Order alone is not enough to hand a flip back to the user unchanged: an engine with a VIEW (the strip) has to know which window to anchor on, and re-deriving that from position picks whichever column the seed happened to adopt first.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Move the focused window to the adjacent slot.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Move the focused window to the Nth position.
Implemented in PhosphorTileEngine::AutotileEngine, and PhosphorSnapEngine::SnapEngine.
|
inlinevirtual |
Notify the engine that a tracked window finished an interactive resize.
The daemon's WindowTracking adaptor forwards the compositor's interactive-resize-finished event here so an engine can reflow the rest of its layout to absorb the change (autotile fills the freed gap; GitHub #652). oldFrame / newFrame are the window's frame geometry before and after the resize; screenId is the screen the daemon resolved the window to. Default is a no-op for engines (e.g. snap) that have no neighbour-reflow model.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
delete |
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Whether the daemon's edge-triggered drag popup (the zone selector surface) should render this engine's DRAG-INSERT vocabulary — strip column cards whose gap / join / half targets translate into DragInsertTarget — instead of zone layouts, on screens this engine owns.
Consumed by WindowDragAdaptor's trigger gate and OverlayService's model selection. Default false: the screen's drag popup speaks the zone-layout vocabulary instead (snap screens keep the classic zone selector; an ENGINE-owned screen without this capability suppresses the popup entirely — the pre-existing autotile behaviour — because the engine owns placement there and has no picker of its own).
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Prune per-(screen, desktop, activity) state for a PHYSICALLY REMOVED output (monitor hot-unplug), matching every virtual sub-screen of the removed physical id.
All three engines override this and the daemon drives each from its screenRemoved handling: snap's stores are created lazily on placement with no screens set to reap them, and the two tiling engines' screens-set sweeps only reap CURRENT-context states, so sibling-context states (other desktops/activities) of the removed output would leak without the explicit whole-output prune. A tiling-family engine must emit windowsReleased for the windows it drops here, AFTER its reverse-map cleanup, so the daemon's restore consumers can re-home them; snap does not, because it is the engine those releases are restored INTO.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Move the focused window to the first empty slot.
Engines whose placement has no empty-slot concept answer with a "push"/"not_supported" feedback emit rather than silence — the shortcut must not read as broken (same policy the span default documents above).
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Re-apply the current layout to all managed windows.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Re-drive the compositor's per-window appearance (border, hidden title bar) for every window this engine currently manages, WITHOUT recomputing the layout — windows keep their current zones/positions.
The compositor derives each window's chrome from the geometry/state this re-emits.
Called by the daemon when the compositor bridge (re)registers: on a daemon or effect restart the compositor drops its per-window appearance state, so it must be re-driven from the daemon's authoritative placement state. Distinct from reapplyLayout(), which is a user navigation action that recomputes the layout and may move windows. Default is a no-op for engines that don't manage compositor-side window chrome.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Re-read all tuning values from the engine's settings interface.
Called by the daemon after any settings change. Engines that cache config values (e.g. AutotileEngine) override this to repopulate their config struct. Engines that read on demand (e.g. SnapEngine) leave this as a no-op.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Restore the focused window out of its managed state.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Apply placement to a (re)opening window on screenId.
Return true if this engine claimed and applied it. Dispatch on placement.slotFor(engineId()) .state, reading the engine's slot reference and the shared freeGeometryByScreen.
Contract pair of capturePlacement() and the engine-agnostic entry point for a new engine. NOTE: NO built-in engine overrides this today — snap, autotile and scrolling all apply restore inline in their own open paths (SnapEngine::resolveWindowRestore consults the store and returns a SnapResult to the effect; AutotileEngine::insertWindow and the scroll engine's open path take()/claim the record themselves) because those paths carry engine-specific policy (snap's auto-snap fallback chain; autotile's burst-insert coalescing; scrolling's strip-stash claim) that a single apply-this-record call cannot express. NOTHING in-tree calls this virtual today — a minimal future engine that implements it MUST have its own open path invoke it directly; no orchestrator will.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Rotate all managed windows on the screen.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Runtime max-windows limit.
Returns -1 (unlimited sentinel) by default; engines that enforce a cap override with the actual value. Callers must treat -1 as "no limit" — never use as a divisor.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
The user's saved per-algorithm max-windows tuning for algorithmId, or std::nullopt when the engine keeps no such slot.
Engines with per-algorithm tuning (AutotileEngine) override this; both mixed- algorithm cap paths consult it — the daemon's per-screen MaxWindows injection and PerScreenConfigResolver::effectiveMaxWindows step 3 — so a screen pinned to a non-global algorithm gets the user's saved cap, not the algorithm's built-in default.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Return the screen this engine considers the window to be on, or empty if the window isn't tracked by this engine.
The daemon-side shortcut router consults this across engines to resolve the active window's current screen for routing decisions (float, focus, move). Without it, a cross-engine handoff (e.g. drag-insert from snap into autotile) leaves the daemon's screenAssignments lookup empty because the source engine has released its tracking, and the next shortcut routes to whichever engine the cached focus screen pointed at rather than the engine that now owns the window.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Inject the cross-surface resolver used to find a neighbouring output / desktop when directional navigation reaches a surface boundary.
The resolver is borrowed, not owned; the caller must keep it alive for the engine's lifetime (in the daemon it outlives both engines by member order). Engines that don't support cross-surface navigation ignore it.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Set a single screen's current virtual desktop (Plasma 6.7 "switch desktops independently for each screen").
A PURE context swap — it selects which per-(screen, desktop) tiling state is current for this screen; it does NOT migrate windows between desktop states (the other desktop's state must stay put so it reappears when that screen returns). Default no-op for engines that are not per-screen-desktop-aware.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Hand the incoming engine the focus captured from the outgoing one.
Advisory. WHEN to apply it is the implementor's choice, not part of this contract: the seeded window is usually not the LAST to re-announce, so an implementor that re-derives focus from arrivals has to defer the seed past them or have it overwritten. The scroll engine consumes it at the end of its arrival burst for exactly that reason; an implementor with no burst concept is free to apply it however it likes.
An empty windowId is not a no-op: it means the capturing transition found no focus to report, and it must CLEAR any seed an earlier one left, or a stale seed outlives the transition that owned it.
An engine with no view of its own has nothing to do with this and the default no-op is the right implementation for it — the focused window is wherever the compositor already has it.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
The window currently under a compositor interactive move (the whole drag, preview or not).
Empty clears. While set, an engine that still models the window as tiled must neither emit geometry for it nor reconcile its geometry acks — KWin's interactive move owns the frame until drop, and fighting it yanks the window from the cursor (and a per-ack reconcile pins size intents to transient drag frames). The daemon sets it at beginDrag and clears it before the drop is finalized, so commit/float paths apply normally. Today the daemon calls this on the SCROLL engine only, and only ScrollEngine overrides it: autotile also retiles mid-drag but exempts the dragged window inside applyTiling's emit filter instead. Override this when an engine has no such filter of its own.
|
pure virtual |
Set floating state explicitly (directional, not toggle).
| screenId | The window's authoritative current screen, when the caller knows it (the D-Bus setWindowFloatingForScreen threads the effect's live output here). An engine WITHOUT live per-window screen tracking MUST prefer this over its own tracked association, which can be stale after a floating window drifts across monitors — using the stale screen makes the unfloat's cross-monitor guard non-deterministic (snap and scroll honour it for exactly that reason). AutotileEngine deliberately resolves from its own tracking instead: its focus-driven migration keeps the association current, and the parameter can lag it mid-handoff. Empty (the default) means "resolve it yourself" for internal callers. |
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Attach a window-class registry (QObject carrying WindowRegistry).
Engines qobject_cast to their concrete type internally.
| registry | Not owned; must outlive this engine. |
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Bring every unmanaged window on the screen back under this engine's placement (zones for snap, the strip for scrolling).
Stated layout-neutrally on purpose: an engine without a layout concept (layoutSupport() == LayoutSupport::None) still implements this intent.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Grow or shrink the focused window's zone span toward the direction: extend into the adjacent zone(s) when some exist beyond that edge, otherwise retract the opposite edge.
Zone spanning is a snap-mode concept, so unlike the required intents above this has a default no-op, keeping the daemon free of engine-type branching. Engines that want the shortcut to give feedback instead of silence override it — AutotileEngine reports a "not_supported" failure OSD.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Per-screen state object for the given screen.
May return nullptr if the engine does not manage the screen OR if per-screen state ownership has not yet been wired for that engine. Callers must not use a non-null return as a proxy for "engine manages this screen" — use isActiveOnScreen() for that check.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
The desktop this engine has PINNED screenId to, or 0 when it has not pinned it (which is the normal case, and the default here).
A pin is an engine-private override for a screen whose windows are all sticky: it outranks the compositor's per-output desktop inside the engine's own key resolution, and is invisible from outside. That makes it the one way a capture can read one desktop's state while filing the result under another's key, recording a pairing that never existed.
Reports the PIN specifically, not the engine's resolved desktop, so a caller comparing against its own desktop cannot be tripped by the two merely LABELLING a screen differently — an engine and a caller can hold consistent but differently-numbered views of the same screen (a virtual sub-screen resolves through its parent for one and not the other), and that costs nothing as long as each is self-consistent.
Meant for a comparison gate, not for re-keying: the pin is dropped when the engine releases the screen, so filing by the pinned desktop would store under a key the re-entry lookup never consults.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Swap the focused window with the adjacent window.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Jump focus between the float layer and the engine's placement layer (niri's switch-focus-between-floating-and-tiling): activate the last focused window on the OTHER layer, falling back to a scan when that memory is stale.
Minimized-window filtering is each engine's own LayerSwitchSide::isEligible — the resolver applies no policy of its own, so a new engine must install the filter itself (a compositor state the registry has not reported is treated as visible: a focus verb must not refuse a window merely because its state is unknown). All three engines implement it on the shared resolver (resolveLayerFocusSwitch), so the default is a no-op only for hypothetical future engines — defaulted rather than pure so the daemon routes it mode-agnostically like spanFocusedInDirection.
Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Toggle the focused window between managed and floating.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
Toggle between managed and floating.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Update the drop target for an active drag-insert preview.
An invalid target is IGNORED, never clamped — implementations keep the previous stored target (autotile's engine-local int form clamps instead; that contract does not cross this seam).
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
pure virtual |
A window was closed.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
pure virtual |
A window gained focus (called when the compositor reports activation).
Named "focused" here because it's the engine's perspective; the D-Bus protocol and DaemonClient use "windowActivated" — same event.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
The window's client-reported minimum size as last known by this engine, or an UNKNOWN answer when it has none.
Read by the cross-engine handoff dispatcher to seed HandoffContext::minSize; must be queried before handoffRelease. Default suits engines without a min-size model.
"Unknown" is spelled two ways in the tree and a caller must accept both: a default-constructed 0x0, and an INVALID QSize (-1x-1), which the scroll engine returns deliberately to distinguish "no entry" from "a real zero". Every in-tree consumer clamps with qMax against 0, which treats the two identically; a new consumer must do the same rather than assuming either.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inlinevirtual |
Update a window's minimum size after the initial windowOpened.
The compositor discovers a min size late for some clients (or the client raises it at runtime); engines that fit windows to slots re-validate their layout on a change. Default is a no-op for engines without a min-size model.
Reimplemented in PhosphorTileEngine::AutotileEngine.
|
inline |
Convenience overload — equivalent to windowOpened(id, screen, 0, 0).
UNCALLABLE through this interface as written: every implementation overrides the four-argument virtual, and an override HIDES every same-named base overload, so engine->windowOpened(id, screen) fails to compile against a concrete engine. Each engine restores it with a using IPlacementEngine::windowOpened;, which is what actually makes the two-argument form work — so this overload is real but only for implementations that opt back into it, not for interface-typed callers that never see a concrete type.
|
pure virtual |
A new window appeared on this engine's screen.
Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.
|
staticconstexpr |
One home for the master/split ratio step so the default return below and the two default arguments cannot drift apart.