Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PhosphorEngine::IPlacementEngine Class Referenceabstract

Unified placement engine interface. More...

#include <phosphor-engine/include/PhosphorEngine/IPlacementEngine.h>

Inheritance diagram for PhosphorEngine::IPlacementEngine:
[legend]

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
 
IPlacementEngineoperator= (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< WindowPlacementcapturePlacement (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 IPlacementStatestateForScreen (const QString &screenId)=0
 Per-screen state object for the given screen.
 
virtual const IPlacementStatestateForScreen (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
 

Detailed Description

Unified placement engine interface.

Required vs Optional Methods

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.

Design Rationale

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.

Member Enumeration Documentation

◆ LayoutSupport

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.

Enumerator
None 

No layout concept at all: the daemon suppresses the picker/popup and answers the layout shortcuts with a "not available" OSD instead of falling back to snap-layout semantics.

Placement 

Layouts drive window placement (snap zone layouts, autotile algorithm cards): the classic picker semantics.

Templates 

The engine consumes a first-class TEMPLATE object rather than a placement layout.

For the scrolling engine that object is a native ScrollingTemplate: a seed blueprint of column widths and displays, the default-width trio for columns beyond it, and the preset width and height vocabularies the size shortcuts cycle through. Picking an entry sets the screen's template, it does not place windows. The daemon routes such applies to the assignment's template slot and makes the native template cards the candidate set (no zone layouts, no autotile cards).

Constructor & Destructor Documentation

◆ IPlacementEngine() [1/2]

PhosphorEngine::IPlacementEngine::IPlacementEngine ( )
protecteddefault

◆ ~IPlacementEngine()

virtual PhosphorEngine::IPlacementEngine::~IPlacementEngine ( )
virtualdefault

◆ IPlacementEngine() [2/2]

PhosphorEngine::IPlacementEngine::IPlacementEngine ( const IPlacementEngine )
delete

Member Function Documentation

◆ activeScreen()

virtual QString PhosphorEngine::IPlacementEngine::activeScreen ( ) const
inlinevirtual

◆ activeScreens()

virtual QSet< QString > PhosphorEngine::IPlacementEngine::activeScreens ( ) const
inlinevirtual

◆ algorithmId()

virtual QString PhosphorEngine::IPlacementEngine::algorithmId ( ) const
inlinevirtual

◆ applyPerScreenConfig()

virtual void PhosphorEngine::IPlacementEngine::applyPerScreenConfig ( const QString &  screenId,
const QVariantMap &  overrides 
)
inlinevirtual

◆ beginArrivalBurst()

virtual void PhosphorEngine::IPlacementEngine::beginArrivalBurst ( )
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.

◆ beginDragInsertPreview()

virtual bool PhosphorEngine::IPlacementEngine::beginDragInsertPreview ( const QString &  windowId,
const QString &  screenId 
)
inlinevirtual

◆ cancelDragAutoScroll()

virtual void PhosphorEngine::IPlacementEngine::cancelDragAutoScroll ( )
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.

◆ cancelDragInsertPreview()

virtual void PhosphorEngine::IPlacementEngine::cancelDragInsertPreview ( )
inlinevirtual

◆ capturePlacement()

virtual std::optional< WindowPlacement > PhosphorEngine::IPlacementEngine::capturePlacement ( const QString &  windowId) const
inlinevirtual

Report windowId's CURRENT placement for persistence, or nullopt if this engine does not manage it.

Fill the engine's EngineSlotstate 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.

◆ claimCrossScreenReopen()

virtual bool PhosphorEngine::IPlacementEngine::claimCrossScreenReopen ( const QString &  windowId,
const QString &  openingScreenId,
int  minWidth = 0,
int  minHeight = 0 
)
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:

  • Self-gate on first observation by MEMBERSHIP (a window the engine already holds in a state is an in-session move, never a session restore — and the raw reverse-map key is not membership).
  • Decide via WindowPlacementStore::peekForReclaim, never plain peek(): the live-instance exclusion is what stops a fresh second instance being yanked onto its open sibling's monitor.
  • Return the REAL adoption outcome, verified by membership after the open-path re-entry. Answering true optimistically converts every downstream refusal into a window no engine manages: the caller hands a claimed window to no other engine.

Reimplemented in PhosphorTileEngine::AutotileEngine.

◆ clearCurrentDesktopForScreen()

virtual void PhosphorEngine::IPlacementEngine::clearCurrentDesktopForScreen ( const QString &  screenId)
inlinevirtual

Drop a screen's per-output desktop, reverting it to the global current.

Reimplemented in PhosphorTileEngine::AutotileEngine.

◆ clearModeSpecificFloatMarker()

virtual void PhosphorEngine::IPlacementEngine::clearModeSpecificFloatMarker ( const QString &  windowId)
inlinevirtual

◆ clearPerScreenConfig()

virtual void PhosphorEngine::IPlacementEngine::clearPerScreenConfig ( const QString &  screenId)
inlinevirtual

◆ commitDragInsertPreview()

virtual void PhosphorEngine::IPlacementEngine::commitDragInsertPreview ( )
inlinevirtual

◆ computeDragInsertTargetAtPoint()

virtual DragInsertTarget PhosphorEngine::IPlacementEngine::computeDragInsertTargetAtPoint ( const QString &  screenId,
const QPoint &  cursorPos 
) const
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.

◆ cycleFocus()

virtual void PhosphorEngine::IPlacementEngine::cycleFocus ( bool  forward,
const NavigationContext ctx 
)
pure virtual

Cycle keyboard focus through managed windows.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ decreaseMasterCount()

virtual void PhosphorEngine::IPlacementEngine::decreaseMasterCount ( )
inlinevirtual

◆ decreaseMasterRatio()

virtual void PhosphorEngine::IPlacementEngine::decreaseMasterRatio ( qreal  delta = kDefaultSplitRatioStep)
inlinevirtual

◆ desktopsWithActiveState()

virtual QSet< int > PhosphorEngine::IPlacementEngine::desktopsWithActiveState ( ) const
inlinevirtual

◆ dragAutoScrollActive()

virtual bool PhosphorEngine::IPlacementEngine::dragAutoScrollActive ( ) const
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.

◆ dragAutoScrollTick()

virtual bool PhosphorEngine::IPlacementEngine::dragAutoScrollTick ( const QString &  screenId,
const QPoint &  cursorPos,
qreal  dtSeconds 
)
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.

◆ dragInsertIndicatorRect()

virtual QRect PhosphorEngine::IPlacementEngine::dragInsertIndicatorRect ( const QString &  screenId) const
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.

◆ dragInsertPreviewPriorScreenId()

virtual QString PhosphorEngine::IPlacementEngine::dragInsertPreviewPriorScreenId ( ) const
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.

◆ dragInsertPreviewScreenId()

virtual QString PhosphorEngine::IPlacementEngine::dragInsertPreviewScreenId ( ) const
inlinevirtual

◆ effectiveSplitRatioStep()

virtual qreal PhosphorEngine::IPlacementEngine::effectiveSplitRatioStep ( const QString &  screenId) const
inlinevirtual

◆ endArrivalBurst()

virtual void PhosphorEngine::IPlacementEngine::endArrivalBurst ( )
inlinevirtual

◆ engineId()

virtual QString PhosphorEngine::IPlacementEngine::engineId ( ) const
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.

◆ focusInDirection()

virtual void PhosphorEngine::IPlacementEngine::focusInDirection ( const QString &  direction,
const NavigationContext ctx 
)
pure virtual

Move keyboard focus to the adjacent window.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ focusMaster()

virtual void PhosphorEngine::IPlacementEngine::focusMaster ( )
inlinevirtual

◆ handoffReceive()

virtual void PhosphorEngine::IPlacementEngine::handoffReceive ( const HandoffContext ctx)
inlinevirtual

Receive ownership of a window from another engine.

Implementations should:

  • Add the window to their own tracking (per-screen/per-state).
  • Decide placement (snap to zone / tile / float) using the context and engine-local policy. Drag drops typically place at dropPos; non-drag handoffs (cross-engine focus changes, programmatic moves) typically respect wasFloating (the window keeps its live frame, so no geometry is carried in the context).
  • Emit any 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.

◆ handoffRelease()

virtual void PhosphorEngine::IPlacementEngine::handoffRelease ( const QString &  windowId)
inlinevirtual

Release ownership of a window WITHOUT modifying its geometry.

Implementations should:

  • Remove the window from per-screen/per-state tracking.
  • Clear zone assignments (if any) WITHOUT triggering a resnap of neighbours — that's the receiving engine's job once it places the window in its layout.
  • Preserve any pre-tile / pre-float captured geometry that should survive the cross-engine move (the receiving engine may consult it via the HandoffContext for size preservation).

Default is a no-op for the same reason as handoffReceive.

Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ hasDragInsertPreview()

virtual bool PhosphorEngine::IPlacementEngine::hasDragInsertPreview ( ) const
inlinevirtual

◆ heldScreenForWindow()

virtual QString PhosphorEngine::IPlacementEngine::heldScreenForWindow ( const QString &  windowId) const
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.

◆ increaseMasterCount()

virtual void PhosphorEngine::IPlacementEngine::increaseMasterCount ( )
inlinevirtual

◆ increaseMasterRatio()

virtual void PhosphorEngine::IPlacementEngine::increaseMasterRatio ( qreal  delta = kDefaultSplitRatioStep)
inlinevirtual

◆ isActiveOnScreen()

virtual bool PhosphorEngine::IPlacementEngine::isActiveOnScreen ( const QString &  screenId) const
pure virtual

Whether this engine is active on the given screen.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ isEnabled()

virtual bool PhosphorEngine::IPlacementEngine::isEnabled ( ) const
inlinevirtualnoexcept

◆ isModeSpecificFloated()

virtual bool PhosphorEngine::IPlacementEngine::isModeSpecificFloated ( const QString &  windowId) const
inlinevirtual

◆ isWindowManaged()

virtual bool PhosphorEngine::IPlacementEngine::isWindowManaged ( const QString &  windowId) const
inlinevirtual

Whether the engine considers the window "managed" (eligible for layout operations).

Semantics are engine-specific:

  • Autotile: equivalent to isWindowTiled (floating windows excluded).
  • Scrolling: the window occupies a strip column (floating windows excluded), same shape as autotile.
  • Snap: NOT implemented — SnapEngine keeps the inherited false. Callers that need a consistent cross-engine check for "engine owns this window at all" should use isWindowTracked instead; that is also the only correct check on a snap screen.

Reimplemented in PhosphorTileEngine::AutotileEngine.

◆ isWindowTiled()

virtual bool PhosphorEngine::IPlacementEngine::isWindowTiled ( const QString &  windowId) const
inlinevirtual

Whether the window is actively tiled (engine-owned, non-floating).

Distinct from isWindowTracked (which includes floating windows).

Reimplemented in PhosphorTileEngine::AutotileEngine.

◆ isWindowTracked()

virtual bool PhosphorEngine::IPlacementEngine::isWindowTracked ( const QString &  windowId) const
inlinevirtual

◆ layoutSupport()

virtual LayoutSupport PhosphorEngine::IPlacementEngine::layoutSupport ( ) const
inlinevirtual

Default None: an engine must opt in to being a layout consumer.

Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ loadState()

virtual void PhosphorEngine::IPlacementEngine::loadState ( )
pure virtual

◆ managedFocusedWindow()

virtual QString PhosphorEngine::IPlacementEngine::managedFocusedWindow ( const QString &  screenId) const
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.

◆ managedWindowOrder()

virtual QStringList PhosphorEngine::IPlacementEngine::managedWindowOrder ( const QString &  screenId) const
inlinevirtual

◆ markModeSpecificFloated()

virtual void PhosphorEngine::IPlacementEngine::markModeSpecificFloated ( const QString &  windowId)
inlinevirtual

◆ moveFocusedInDirection()

virtual void PhosphorEngine::IPlacementEngine::moveFocusedInDirection ( const QString &  direction,
const NavigationContext ctx 
)
pure virtual

Move the focused window to the adjacent slot.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ moveFocusedToPosition()

virtual void PhosphorEngine::IPlacementEngine::moveFocusedToPosition ( int  position,
const NavigationContext ctx 
)
pure virtual

Move the focused window to the Nth position.

Implemented in PhosphorTileEngine::AutotileEngine, and PhosphorSnapEngine::SnapEngine.

◆ onWindowResized()

virtual void PhosphorEngine::IPlacementEngine::onWindowResized ( const QString &  windowId,
const QRect &  oldFrame,
const QRect &  newFrame,
const QString &  screenId 
)
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.

◆ operator=()

IPlacementEngine & PhosphorEngine::IPlacementEngine::operator= ( const IPlacementEngine )
delete

◆ perScreenOverrides()

virtual QVariantMap PhosphorEngine::IPlacementEngine::perScreenOverrides ( const QString &  screenId) const
inlinevirtual

◆ providesDragInsertSelector()

virtual bool PhosphorEngine::IPlacementEngine::providesDragInsertSelector ( ) const
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).

◆ pruneStatesForActivities()

virtual void PhosphorEngine::IPlacementEngine::pruneStatesForActivities ( const QStringList &  validActivities)
inlinevirtual

◆ pruneStatesForDesktop()

virtual void PhosphorEngine::IPlacementEngine::pruneStatesForDesktop ( int  removedDesktop)
inlinevirtual

◆ pruneStatesForRemovedScreen()

virtual void PhosphorEngine::IPlacementEngine::pruneStatesForRemovedScreen ( const QString &  physicalScreenId)
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.

◆ pushToEmptyZone()

virtual void PhosphorEngine::IPlacementEngine::pushToEmptyZone ( const NavigationContext ctx)
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.

◆ reapplyLayout()

virtual void PhosphorEngine::IPlacementEngine::reapplyLayout ( const NavigationContext ctx)
pure virtual

Re-apply the current layout to all managed windows.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ reapplyManagedWindowAppearance()

virtual void PhosphorEngine::IPlacementEngine::reapplyManagedWindowAppearance ( )
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.

◆ refreshConfigFromSettings()

virtual void PhosphorEngine::IPlacementEngine::refreshConfigFromSettings ( )
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.

◆ restoreFocusedWindow()

virtual void PhosphorEngine::IPlacementEngine::restoreFocusedWindow ( const NavigationContext ctx)
pure virtual

Restore the focused window out of its managed state.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ restorePlacement()

virtual bool PhosphorEngine::IPlacementEngine::restorePlacement ( const WindowPlacement placement,
const QString &  screenId 
)
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.

◆ retile()

virtual void PhosphorEngine::IPlacementEngine::retile ( const QString &  screenId = QString())
inlinevirtual

◆ rotateWindows()

virtual void PhosphorEngine::IPlacementEngine::rotateWindows ( bool  clockwise,
const NavigationContext ctx 
)
pure virtual

Rotate all managed windows on the screen.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ runtimeMaxWindows()

virtual int PhosphorEngine::IPlacementEngine::runtimeMaxWindows ( ) const
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.

◆ savedMaxWindowsForAlgorithm()

virtual std::optional< int > PhosphorEngine::IPlacementEngine::savedMaxWindowsForAlgorithm ( const QString &  algorithmId) const
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.

◆ saveState()

virtual void PhosphorEngine::IPlacementEngine::saveState ( )
pure virtual

◆ scheduleRetileForScreen()

virtual void PhosphorEngine::IPlacementEngine::scheduleRetileForScreen ( const QString &  screenId)
inlinevirtual

◆ screenForTrackedWindow()

virtual QString PhosphorEngine::IPlacementEngine::screenForTrackedWindow ( const QString &  windowId) const
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.

◆ setActiveScreenHint()

virtual void PhosphorEngine::IPlacementEngine::setActiveScreenHint ( const QString &  screenId)
inlinevirtual

◆ setActiveScreens()

virtual void PhosphorEngine::IPlacementEngine::setActiveScreens ( const QSet< QString > &  screens)
inlinevirtual

◆ setAlgorithm()

virtual void PhosphorEngine::IPlacementEngine::setAlgorithm ( const QString &  algorithmId)
inlinevirtual

◆ setCrossSurfaceResolver()

virtual void PhosphorEngine::IPlacementEngine::setCrossSurfaceResolver ( ICrossSurfaceResolver resolver)
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.

◆ setCurrentActivity()

virtual void PhosphorEngine::IPlacementEngine::setCurrentActivity ( const QString &  activity)
inlinevirtual

◆ setCurrentDesktop()

virtual void PhosphorEngine::IPlacementEngine::setCurrentDesktop ( int  desktop)
inlinevirtual

◆ setCurrentDesktopForScreen()

virtual void PhosphorEngine::IPlacementEngine::setCurrentDesktopForScreen ( const QString &  screenId,
int  desktop 
)
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.

◆ setInitialFocusedWindow()

virtual void PhosphorEngine::IPlacementEngine::setInitialFocusedWindow ( const QString &  screenId,
const QString &  windowId 
)
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.

◆ setInitialWindowOrder()

virtual void PhosphorEngine::IPlacementEngine::setInitialWindowOrder ( const QString &  screenId,
const QStringList &  windowIds 
)
inlinevirtual

◆ setInteractiveDragWindow()

virtual void PhosphorEngine::IPlacementEngine::setInteractiveDragWindow ( const QString &  windowId)
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.

◆ setWindowFloat()

virtual void PhosphorEngine::IPlacementEngine::setWindowFloat ( const QString &  windowId,
bool  shouldFloat,
const QString &  screenId = QString() 
)
pure virtual

Set floating state explicitly (directional, not toggle).

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

◆ setWindowRegistry()

virtual void PhosphorEngine::IPlacementEngine::setWindowRegistry ( QObject *  registry)
inlinevirtual

Attach a window-class registry (QObject carrying WindowRegistry).

Engines qobject_cast to their concrete type internally.

Parameters
registryNot owned; must outlive this engine.

Reimplemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ snapAllWindows()

virtual void PhosphorEngine::IPlacementEngine::snapAllWindows ( const NavigationContext ctx)
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.

◆ spanFocusedInDirection()

virtual void PhosphorEngine::IPlacementEngine::spanFocusedInDirection ( const QString &  direction,
const NavigationContext ctx 
)
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.

◆ stateForScreen() [1/2]

virtual const IPlacementState * PhosphorEngine::IPlacementEngine::stateForScreen ( const QString &  screenId) const
pure virtual

◆ stateForScreen() [2/2]

virtual IPlacementState * PhosphorEngine::IPlacementEngine::stateForScreen ( const QString &  screenId)
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.

◆ stickyPinnedDesktopForScreen()

virtual int PhosphorEngine::IPlacementEngine::stickyPinnedDesktopForScreen ( const QString &  screenId) const
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.

◆ swapFocusedInDirection()

virtual void PhosphorEngine::IPlacementEngine::swapFocusedInDirection ( const QString &  direction,
const NavigationContext ctx 
)
pure virtual

Swap the focused window with the adjacent window.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ swapFocusedWithMaster()

virtual void PhosphorEngine::IPlacementEngine::swapFocusedWithMaster ( )
inlinevirtual

◆ switchFocusBetweenFloatingAndTiling()

virtual void PhosphorEngine::IPlacementEngine::switchFocusBetweenFloatingAndTiling ( const QString &  screenId)
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.

◆ toggleFocusedFloat()

virtual void PhosphorEngine::IPlacementEngine::toggleFocusedFloat ( const NavigationContext ctx)
pure virtual

Toggle the focused window between managed and floating.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ toggleWindowFloat()

virtual void PhosphorEngine::IPlacementEngine::toggleWindowFloat ( const QString &  windowId,
const QString &  screenId 
)
pure virtual

Toggle between managed and floating.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ updateDragInsertPreview()

virtual void PhosphorEngine::IPlacementEngine::updateDragInsertPreview ( const DragInsertTarget target)
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.

◆ updateStickyScreenPins()

virtual void PhosphorEngine::IPlacementEngine::updateStickyScreenPins ( const std::function< bool(const QString &)> &  isWindowSticky)
inlinevirtual

◆ windowClosed()

virtual void PhosphorEngine::IPlacementEngine::windowClosed ( const QString &  windowId)
pure virtual

A window was closed.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

◆ windowFocused()

virtual void PhosphorEngine::IPlacementEngine::windowFocused ( const QString &  windowId,
const QString &  screenId 
)
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.

◆ windowMinimumSize()

virtual QSize PhosphorEngine::IPlacementEngine::windowMinimumSize ( const QString &  windowId) const
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.

◆ windowMinSizeUpdated()

virtual void PhosphorEngine::IPlacementEngine::windowMinSizeUpdated ( const QString &  windowId,
int  minWidth,
int  minHeight 
)
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.

◆ windowOpened() [1/2]

void PhosphorEngine::IPlacementEngine::windowOpened ( const QString &  windowId,
const QString &  screenId 
)
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.

◆ windowOpened() [2/2]

virtual void PhosphorEngine::IPlacementEngine::windowOpened ( const QString &  windowId,
const QString &  screenId,
int  minWidth = 0,
int  minHeight = 0 
)
pure virtual

A new window appeared on this engine's screen.

Implemented in PhosphorSnapEngine::SnapEngine, and PhosphorTileEngine::AutotileEngine.

Member Data Documentation

◆ kDefaultSplitRatioStep

constexpr qreal PhosphorEngine::IPlacementEngine::kDefaultSplitRatioStep = 0.05
staticconstexpr

One home for the master/split ratio step so the default return below and the two default arguments cannot drift apart.


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