Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
SnapEngine.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <phosphorsnapengine_export.h>
16#include <PhosphorWindowRules/RuleEvaluator.h>
17#include <QObject>
18#include <QPointer>
19#include <QRect>
20#include <QString>
21#include <QStringList>
22#include <functional>
23#include <optional>
24#include <memory>
25
26namespace PhosphorZones {
27class IZoneDetector;
28class LayoutRegistry;
29class Layout;
30}
31
32// PhosphorWindowRules::RuleEvaluator is included as a member type of
33// std::optional below (needs a complete type at declaration); WindowRuleSet
34// is referenced only by pointer / reference, so a forward declaration would
35// suffice — but including RuleEvaluator.h pulls in WindowRuleSet.h
36// transitively anyway, so leave the explicit forward decls out and let
37// RuleEvaluator.h provide both.
38
39namespace PhosphorSnapEngine {
40
41class INavigationStateProvider;
42class IZoneAdjacencyResolver;
43class SnapNavigationTargetResolver;
44class SnapState;
45
60class PHOSPHORSNAPENGINE_EXPORT SnapEngine : public PhosphorEngine::PlacementEngineBase
61{
62 Q_OBJECT
63
64public:
68 QObject* parent = nullptr);
69 ~SnapEngine() override;
70
84 int currentVirtualDesktopForScreen(const QString& screenId) const;
85 QString currentActivity() const;
86
93 std::pair<QString, QRect> resolveCrossDesktopZone(const QString& currentZoneId, const QString& screenId,
94 int targetDesktop) const;
95
101 QString entryZoneForCrossing(const QString& direction, const QString& neighbourScreen) const;
102
107 QString windowInZoneOnScreen(const QString& zoneId, const QString& screenId) const;
108
109 // ═══════════════════════════════════════════════════════════════════════════
110 // IPlacementEngine — lifecycle
111 // ═══════════════════════════════════════════════════════════════════════════
112
113 bool isActiveOnScreen(const QString& screenId) const override;
119 bool isEnabled() const noexcept override;
120 using IPlacementEngine::windowOpened;
121 void windowOpened(const QString& windowId, const QString& screenId, int minWidth, int minHeight) override;
122
148 using ShouldRestorePredicate = std::function<bool(const QString& screenId)>;
149
157 void setShouldRestorePredicate(ShouldRestorePredicate predicate)
158 {
159 m_shouldRestorePredicate = std::move(predicate);
160 }
161
192 using RestorePositionPredicate = std::function<bool(const QString& windowId)>;
193
201 {
202 m_restorePositionPredicate = std::move(predicate);
203 }
204
222 using ManagedRestorePredicate = std::function<bool(const QString& windowId)>;
223
231 {
232 m_managedRestorePredicate = std::move(predicate);
233 }
234
244 using FloatPredicate = std::function<bool(const QString& windowId)>;
245
247 {
248 m_floatPredicate = std::move(predicate);
249 }
250
267 using PlacementZonesResolver = std::function<PlacementDirective(const QString& windowId, const QString& screenId)>;
268
270 {
271 m_placementZonesResolver = std::move(resolver);
272 }
273
274 void windowClosed(const QString& windowId) override;
275 void windowFocused(const QString& windowId, const QString& screenId) override;
276 void toggleWindowFloat(const QString& windowId, const QString& screenId) override;
277 void setWindowFloat(const QString& windowId, bool shouldFloat) override;
278 void saveState() override;
279 void loadState() override;
280
281 // Cross-engine handoff
282 QString engineId() const override
283 {
284 return QStringLiteral("snap");
285 }
286 void handoffReceive(const HandoffContext& ctx) override;
287 void handoffRelease(const QString& windowId) override;
288 QString screenForTrackedWindow(const QString& windowId) const override;
293 bool isWindowTracked(const QString& windowId) const override;
294
302
307 void resnapCurrentAssignments(const QString& screenFilter = QString());
308
315 void resnapFromAutotileOrder(const QStringList& autotileWindowOrder, const QString& screenId);
316
333 QVector<PhosphorEngine::ZoneAssignmentEntry>
334 calculateResnapEntriesFromAutotileOrder(const QStringList& autotileWindowOrder, const QString& screenId,
335 const QStringList& preClaimedZoneIds = {});
336
343 PhosphorProtocol::SnapAllResultList calculateSnapAllWindows(const QStringList& windowIds, const QString& screenId);
344
354 void emitBatchedResnap(const QVector<PhosphorEngine::ZoneAssignmentEntry>& entries);
355
360 void snapAllWindows(const QString& screenId);
361
362 // ═══════════════════════════════════════════════════════════════════════════
363 // Window restore (auto-snap on window open)
364 // ═══════════════════════════════════════════════════════════════════════════
365
390 resolveWindowRestore(const QString& windowId, const QString& screenId, bool sticky,
392
393 // ═══════════════════════════════════════════════════════════════════════════
394 // Autotile engine reference (for isActiveOnScreen routing)
395 // ═══════════════════════════════════════════════════════════════════════════
396
406
408 {
409 return m_snapState;
410 }
411
412 // ═══════════════════════════════════════════════════════════════════════════
413 // Zone adjacency resolver (for daemon-driven navigation)
414 // ═══════════════════════════════════════════════════════════════════════════
415
426
431
432 // ═══════════════════════════════════════════════════════════════════════════
433 // Navigation state provider
434 // ═══════════════════════════════════════════════════════════════════════════
435
448
449 // ═══════════════════════════════════════════════════════════════════════════
450 // Navigation (moved out of WindowTrackingAdaptor)
451 //
452 // Every method takes a PhosphorEngine::NavigationContext populated by the daemon's
453 // shortcut handler. The engine uses ctx.windowId directly rather than
454 // re-reading it from the WTA shadow, which is a step toward retiring
455 // the SnapEngine -> WTA back-reference entirely. When ctx.windowId is
456 // empty, the engine may consult m_navState->lastActiveWindowId() as a
457 // best-effort fallback -- but in the normal path the daemon always
458 // provides a resolved target.
459 // ═══════════════════════════════════════════════════════════════════════════
460
461 // ═══════════════════════════════════════════════════════════════════════════
462 // IPlacementEngine — navigation overrides
463 // ═══════════════════════════════════════════════════════════════════════════
464
467 void focusInDirection(const QString& direction, const PhosphorEngine::NavigationContext& ctx) override;
468
471 void moveFocusedInDirection(const QString& direction, const PhosphorEngine::NavigationContext& ctx) override;
472
475 void swapFocusedInDirection(const QString& direction, const PhosphorEngine::NavigationContext& ctx) override;
476
479 void moveFocusedToPosition(int zoneNumber, const PhosphorEngine::NavigationContext& ctx) override;
480
483 void rotateWindows(bool clockwise, const PhosphorEngine::NavigationContext& ctx) override;
484
488
494
497 std::optional<PhosphorEngine::WindowPlacement> capturePlacement(const QString& windowId) const override;
498
503
506
509
512
516 void cycleFocus(bool forward, const PhosphorEngine::NavigationContext& ctx) override;
517
518 // ═══════════════════════════════════════════════════════════════════════════
519 // Snap commit orchestration
520 //
521 // Full snap lifecycle: clear floating, assign to zone, update tracking,
522 // emit state-changed signals. Owns the orchestration that was previously
523 // on WindowTrackingService.
524 // ═══════════════════════════════════════════════════════════════════════════
525
530 void commitSnap(const QString& windowId, const QString& zoneId, const QString& screenId,
532 int virtualDesktop = 0);
533
534 void commitMultiZoneSnap(const QString& windowId, const QStringList& zoneIds, const QString& screenId,
536 int virtualDesktop = 0);
537
538 void uncommitSnap(const QString& windowId);
539
540 PhosphorEngine::UnfloatResult resolveUnfloatGeometry(const QString& windowId, const QString& fallbackScreen) const;
541
549 const QString& fallbackScreen) const;
550
552 applyBatchAssignments(const QVector<PhosphorEngine::ZoneAssignmentEntry>& entries,
554 std::function<QString()> fallbackScreenResolver = {});
555
556 // ═══════════════════════════════════════════════════════════════════════════
557 // Auto-snap calculations (moved from WTS)
558 // ═══════════════════════════════════════════════════════════════════════════
559
560 PhosphorEngine::SnapResult calculateSnapToPlacementRule(const QString& windowId, const QString& windowScreenName,
561 bool isSticky) const;
562 PhosphorEngine::SnapResult calculateSnapToLastZone(const QString& windowId, const QString& windowScreenId,
563 bool isSticky) const;
564 PhosphorEngine::SnapResult calculateSnapToEmptyZone(const QString& windowId, const QString& windowScreenId,
565 bool isSticky) const;
566
567 // ═══════════════════════════════════════════════════════════════════════════
568 // Resnap / rotation calculations (moved from WTS)
569 // ═══════════════════════════════════════════════════════════════════════════
570
571 QVector<PhosphorEngine::ZoneAssignmentEntry> calculateResnapFromPreviousLayout();
572 QVector<PhosphorEngine::ZoneAssignmentEntry>
573 calculateResnapFromCurrentAssignments(const QString& screenFilter = QString()) const;
574 QVector<PhosphorEngine::ZoneAssignmentEntry>
575 calculateResnapFromAutotileOrder(const QStringList& autotileWindowOrder, const QString& screenId,
576 const QStringList& preClaimedZoneIds = {}) const;
577 QVector<PhosphorEngine::ZoneAssignmentEntry> calculateSnapAllWindowEntries(const QStringList& windowIds,
578 const QString& screenId) const;
579 QVector<PhosphorEngine::ZoneAssignmentEntry> calculateRotation(bool clockwise,
580 const QString& screenFilter = QString()) const;
581
582 // ═══════════════════════════════════════════════════════════════════════════
583 // Effect-reported windows (runtime flag — not persisted)
584 // ═══════════════════════════════════════════════════════════════════════════
585
586 void markWindowReported(const QString& windowId);
587 const QSet<QString>& effectReportedWindows() const
588 {
589 return m_effectReportedWindows;
590 }
591
592 int pruneStaleWindows(const QSet<QString>& aliveWindowIds) override;
593
594 // ═══════════════════════════════════════════════════════════════════════════
595 // IPlacementEngine — state access
596 //
597 // Returns the single SnapState wired by Daemon::init(). Currently a
598 // global state (not per-screen); a future PR will introduce per-screen
599 // ownership. Returns nullptr in headless unit tests that don't wire a
600 // SnapState.
601 // ═══════════════════════════════════════════════════════════════════════════
602
603 PhosphorEngine::IPlacementState* stateForScreen(const QString& screenId) override;
604 const PhosphorEngine::IPlacementState* stateForScreen(const QString& screenId) const override;
605
606 // ═══════════════════════════════════════════════════════════════════════════
607 // Internal navigation helpers (concrete SnapEngine methods that the
608 // IPlacementEngine overrides delegate to)
609 // ═══════════════════════════════════════════════════════════════════════════
610
614
616 void rotateWindowsInLayout(bool clockwise, const QString& screenId);
617
618 // ═══════════════════════════════════════════════════════════════════════════
619 // Persistence delegate
620 // ═══════════════════════════════════════════════════════════════════════════
621
632 void setPersistenceDelegate(std::function<void()> saveFn, std::function<void()> loadFn)
633 {
634 m_saveFn = std::move(saveFn);
635 m_loadFn = std::move(loadFn);
636 }
637
642 QString lastActiveScreenId() const
643 {
644 return m_lastActiveScreenId;
645 }
646
667 void setExcludeRuleSet(const PhosphorWindowRules::WindowRuleSet* ruleSet);
668
680 std::function<std::optional<PhosphorWindowRules::WindowQuery>(const QString& windowId)>;
681
686 {
687 m_exclusionQueryProvider = std::move(provider);
688 }
689
700 bool isAppIdExcluded(const QString& appId) const;
701
709 bool isWindowExcluded(const QString& windowId) const;
710
711Q_SIGNALS:
712 // ═══════════════════════════════════════════════════════════════════════════
713 // Signals (relayed via SnapAdaptor -> WTA -> D-Bus -> effect)
714 // ═══════════════════════════════════════════════════════════════════════════
715
717 void windowSnapStateChanged(const QString& windowId, const PhosphorProtocol::WindowStateEntry& entry);
718
720 void windowFloatingClearedForSnap(const QString& windowId, const QString& screenId);
721
723 void applyGeometryRequested(const QString& windowId, int x, int y, int width, int height, const QString& zoneId,
724 const QString& screenId, bool sizeOnly);
725
727 void resnapToNewLayoutRequested(const QString& resnapData);
728
730 void snapAllWindowsRequested(const QString& screenId);
731
738 void applyGeometriesBatch(const PhosphorProtocol::WindowGeometryList& geometries, const QString& action);
739
740private:
741 PhosphorEngine::ISnapSettings* snapSettings() const;
742
743 struct GapParams
744 {
745 int zonePadding;
747 };
748 // Resolve zone padding + outer gaps for @p screenId, honoring the same
749 // precedence the main geometry pipeline uses (minus the context-rule tier,
750 // which the engine has no registry for): per-screen snapping override (with
751 // virtual->physical fallback) -> @p layout override -> global. An empty
752 // screenId skips the per-screen tier; a null layout skips the layout tier.
753 GapParams resolveGapParams(const QString& screenId, PhosphorZones::Layout* layout) const;
754
755 void commitSnapImpl(const QString& windowId, const QStringList& zoneIds, const QString& screenId,
756 PhosphorEngine::SnapIntent intent, int virtualDesktop = 0);
757
763 QString resolveUnfloatScreen(const QString& primaryScreen, const QString& fallbackScreen) const;
764
765 PhosphorZones::LayoutRegistry* m_layoutManager = nullptr;
766 PhosphorEngine::IWindowTrackingService* m_windowTracker = nullptr;
767 SnapState* m_snapState = nullptr;
768 PhosphorZones::IZoneDetector* m_zoneDetector = nullptr;
769 PhosphorEngine::IVirtualDesktopManager* m_virtualDesktopManager = nullptr;
770 QPointer<QObject> m_autotileEngineObj;
771 PhosphorEngine::IPlacementEngine* m_autotileEngineTyped = nullptr;
772 IZoneAdjacencyResolver* m_zoneAdjacencyResolver = nullptr;
773 PhosphorEngine::ICrossSurfaceResolver* m_crossSurfaceResolver = nullptr;
774 // Typed navigation-state provider — replaces the opaque QObject* m_wta
775 // back-reference. Provides read-only access to compositor-layer shadows
776 // (last-active window, last-active screen, last-cursor screen, frame
777 // geometry). Not owned; must outlive SnapEngine.
778 INavigationStateProvider* m_navState = nullptr;
779 // Snap-mode navigation target resolver. Owned by SnapEngine — moved
780 // here in Phase 5E from WindowTrackingAdaptor. Constructed lazily on
781 // first navigation call (so the construction order isn't constrained
782 // by the fact that SnapEngine has to exist before a resolver that
783 // takes WTS + PhosphorZones::LayoutRegistry can be built).
784 std::unique_ptr<SnapNavigationTargetResolver> m_targetResolver;
785 QSet<QString> m_effectReportedWindows;
786
787 // ═══════════════════════════════════════════════════════════════════════════
788 // Float helpers (snapengine/float.cpp)
789 //
790 // The historical clearFloatingStateForSnap / assignToZones pair was
791 // removed — all snap commits now route through commitSnapImpl.
792 // ═══════════════════════════════════════════════════════════════════════════
793
794 bool unfloatToZone(const QString& windowId, const QString& screenId);
795 bool applyGeometryForFloat(const QString& windowId, const QString& screenId);
796
806 SnapNavigationTargetResolver* ensureTargetResolver(const QString& action = QString());
807
818 bool tryCrossDesktopMove(const QString& windowId, const QString& direction, const QString& screenId);
819
827 bool tryCrossModeOutput(const QString& windowId, const QString& direction, const QString& screenId, bool swap);
828
836 bool tryCrossDesktopFocus(const QString& focusedWindowId, const QString& direction, const QString& screenId);
837
843 bool isWindowExcludedForAction(const QString& windowId, const QString& action, const QString& screenId);
844
845 // `isAppIdExcluded` and `isWindowExcluded` are declared in the public
846 // section above (so the unit tests can drive the wiring directly); full
847 // docstrings live with those declarations.
848
852 bool evaluateExcludeRules(const PhosphorWindowRules::WindowQuery& query) const;
853
866 const PhosphorWindowRules::WindowRuleSet* m_excludeRuleSet = nullptr;
875 mutable std::optional<PhosphorWindowRules::RuleEvaluator> m_excludeEvaluator;
876
880 ExclusionQueryProvider m_exclusionQueryProvider{};
881
882 // Persistence delegates (KConfig stays in adaptor layer)
883 std::function<void()> m_saveFn;
884 std::function<void()> m_loadFn;
885
886 // Last-focused screen (updated by windowFocused)
887 QString m_lastActiveScreenId;
888
889 // Auto-snap entry gate. Empty until the daemon wires it; while empty
890 // the engine treats every screen as active — preserving the
891 // historical default that unit tests rely on. (The predicate's
892 // signature is `bool(const QString& screenId)` — the desktop and
893 // activity dimensions are resolved by the daemon-side closure at
894 // call time, not passed in here; see ShouldRestorePredicate doc
895 // above and discussion #461 item 7.)
896 ShouldRestorePredicate m_shouldRestorePredicate{};
897
898 // Unsnapped-position-restore gate. Empty until the daemon wires it; while
899 // empty the engine marks floated windows floating but restores their position
900 // only on the reopening screen — the historical behaviour unit tests rely on.
901 // See RestorePositionPredicate doc above.
902 RestorePositionPredicate m_restorePositionPredicate{};
903
904 // Managed (snapped-to-zone) restore gate. Empty until the daemon wires it;
905 // while empty the engine restores snapped records unconditionally — the
906 // historical behaviour unit tests rely on. See ManagedRestorePredicate.
907 ManagedRestorePredicate m_managedRestorePredicate{};
908
909 // Rule-driven open-floating gate. Empty until the daemon wires it; while
910 // empty no window is rule-floated. See FloatPredicate doc above.
911 FloatPredicate m_floatPredicate{};
912
913 // Rule-driven open-placement resolver (SnapToZone). Empty until the daemon
914 // wires it; while empty no window is rule-snapped. See PlacementZonesResolver
915 // doc above.
916 PlacementZonesResolver m_placementZonesResolver{};
917};
918
919} // namespace PhosphorSnapEngine
Resolves the neighbouring surface — output or virtual desktop — in a direction, for cross-surface win...
Definition ICrossSurfaceResolver.h:21
Unified placement engine interface.
Definition IPlacementEngine.h:61
Per-screen placement state contract.
Definition IPlacementState.h:26
Definition ISnapSettings.h:12
Definition IVirtualDesktopManager.h:13
Definition IWindowTrackingService.h:34
Abstract base class for placement engines.
Definition PlacementEngineBase.h:30
Narrow read-only interface for compositor-layer state queries.
Definition INavigationStateProvider.h:32
Narrow interface for zone-adjacency queries used by snap navigation.
Definition IZoneAdjacencyResolver.h:28
Engine for manual zone-based window snapping.
Definition SnapEngine.h:61
void windowSnapStateChanged(const QString &windowId, const PhosphorProtocol::WindowStateEntry &entry)
Snap state changed (commit / uncommit). WTA relays to D-Bus windowStateChanged.
void snapAllWindowsRequested(const QString &screenId)
Request KWin effect to collect unsnapped windows and snap them all.
void focusInDirection(const QString &direction, const PhosphorEngine::NavigationContext &ctx) override
Walk to the adjacent window in direction and transfer keyboard focus.
QString entryZoneForCrossing(const QString &direction, const QString &neighbourScreen) const
The zone a window ENTERS when it crosses onto neighbourScreen moving in direction: the first zone on ...
PhosphorEngine::SnapResult calculateSnapToPlacementRule(const QString &windowId, const QString &windowScreenName, bool isSticky) const
void markWindowReported(const QString &windowId)
void setPersistenceDelegate(std::function< void()> saveFn, std::function< void()> loadFn)
Set persistence callbacks for save/load.
Definition SnapEngine.h:632
std::function< bool(const QString &windowId)> ManagedRestorePredicate
Predicate consulted in resolveWindowRestore to decide whether a window that was SNAPPED at logout sho...
Definition SnapEngine.h:222
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateRotation(bool clockwise, const QString &screenFilter=QString()) const
void setRestorePositionPredicate(RestorePositionPredicate predicate)
Inject the unsnapped-position-restore gate.
Definition SnapEngine.h:200
void setExclusionQueryProvider(ExclusionQueryProvider provider)
Inject the exclusion query provider.
Definition SnapEngine.h:685
void setManagedRestorePredicate(ManagedRestorePredicate predicate)
Inject the managed (snapped-to-zone) restore gate.
Definition SnapEngine.h:230
void emitBatchedResnap(const QVector< PhosphorEngine::ZoneAssignmentEntry > &entries)
Emit a single batched resnapToNewLayoutRequested signal.
void setWindowFloat(const QString &windowId, bool shouldFloat) override
Set floating state explicitly (directional, not toggle).
const QSet< QString > & effectReportedWindows() const
Definition SnapEngine.h:587
PhosphorEngine::SnapResult calculateSnapToLastZone(const QString &windowId, const QString &windowScreenId, bool isSticky) const
int pruneStaleWindows(const QSet< QString > &aliveWindowIds) override
Drop any per-engine bookkeeping for windows not in aliveWindowIds.
bool isAppIdExcluded(const QString &appId) const
True if appId matches an enabled Exclude-action WindowRule resolved against an appId-ONLY WindowQuery...
void reapplyManagedWindowAppearance() override
Re-emit the snap geometry for every currently-snapped (non-floating) window so the compositor re-appl...
void rotateWindowsInLayout(bool clockwise, const QString &screenId)
Rotate snapped windows through the layout's zone order on screenId.
void toggleFocusedFloat(const PhosphorEngine::NavigationContext &ctx) override
Toggle the focused window between snapped and floating.
SnapState * snapState() const
Definition SnapEngine.h:407
std::function< bool(const QString &windowId)> FloatPredicate
Predicate deciding whether an opening window should start FLOATING because a "Float this app" window ...
Definition SnapEngine.h:244
PhosphorEngine::SnapResult calculateSnapToEmptyZone(const QString &windowId, const QString &windowScreenId, bool isSticky) const
QString screenForTrackedWindow(const QString &windowId) const override
Return the screen this engine considers the window to be on, or empty if the window isn't tracked by ...
void setPlacementZonesResolver(PlacementZonesResolver resolver)
Definition SnapEngine.h:269
void reapplyLayout(const PhosphorEngine::NavigationContext &ctx) override
Re-apply the current layout to all managed windows.
bool isActiveOnScreen(const QString &screenId) const override
Whether this engine is active on the given screen.
void pushToEmptyZone(const PhosphorEngine::NavigationContext &ctx) override
Move the focused window to the first empty zone on ctx.screenId.
void restoreFocusedWindow(const PhosphorEngine::NavigationContext &ctx) override
Restore the focused window to its captured pre-snap size and unsnap.
std::function< bool(const QString &screenId)> ShouldRestorePredicate
Predicate consulted on the auto-snap entry path to suppress zone restores onto a context the user dis...
Definition SnapEngine.h:148
void windowFloatingClearedForSnap(const QString &windowId, const QString &screenId)
Floating state cleared as part of a commit. WTA relays as windowFloatingChanged(id,...
void resnapFromAutotileOrder(const QStringList &autotileWindowOrder, const QString &screenId)
Resnap windows using autotile window order as assignment source.
PhosphorEngine::IPlacementState * stateForScreen(const QString &screenId) override
Per-screen state object for the given screen.
std::pair< QString, QRect > resolveCrossDesktopZone(const QString &currentZoneId, const QString &screenId, int targetDesktop) const
Resolve the zone on screenId's targetDesktop layout that is positionally equivalent to currentZoneId ...
void handoffReceive(const HandoffContext &ctx) override
Receive ownership of a window from another engine.
void snapAllWindows(const QString &screenId)
Request the KWin effect to collect and snap all unsnapped windows.
PhosphorEngine::UnfloatResult resolveFallbackUnfloatGeometry(const QString &windowId, const QString &fallbackScreen) const
Fallback unfloat target for a window with NO pre-float zone (a never-snapped window that defaulted to...
void setFloatPredicate(FloatPredicate predicate)
Definition SnapEngine.h:246
void moveFocusedToPosition(int zoneNumber, const PhosphorEngine::NavigationContext &ctx) override
Move the focused window to the layout zone with zoneNumber (1-based) on ctx.screenId.
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateResnapFromPreviousLayout()
int currentVirtualDesktopForScreen(const QString &screenId) const
This screen's current virtual desktop (Plasma 6.7 per-output virtual desktops, #648),...
void handoffRelease(const QString &windowId) override
Release ownership of a window WITHOUT modifying its geometry.
void moveFocusedInDirection(const QString &direction, const PhosphorEngine::NavigationContext &ctx) override
Move the focused window into the adjacent zone in direction (displacing or filling the target).
int currentVirtualDesktop() const
Current virtual desktop (1-based; 0 when no virtual-desktop manager is wired) and activity,...
std::function< PlacementDirective(const QString &windowId, const QString &screenId)> PlacementZonesResolver
Resolver yielding the open-placement directive — SnapToZone ordinals plus an optional RouteToScreen t...
Definition SnapEngine.h:267
bool isEnabled() const noexcept override
True when snapping is globally enabled.
std::function< bool(const QString &windowId)> RestorePositionPredicate
Predicate consulted in resolveWindowRestore to decide whether a FLOATED window should have its previo...
Definition SnapEngine.h:192
QString windowInZoneOnScreen(const QString &zoneId, const QString &screenId) const
The window snapped to zoneId on screenId (the daemon's stored assignment pins it to that output),...
QString engineId() const override
Stable engine identity for HandoffContext.fromEngineId.
Definition SnapEngine.h:282
PhosphorEngine::UnfloatResult resolveUnfloatGeometry(const QString &windowId, const QString &fallbackScreen) const
void applyGeometriesBatch(const PhosphorProtocol::WindowGeometryList &geometries, const QString &action)
Batch of window-geometry updates, applied by the KWin effect in a single operation.
std::function< std::optional< PhosphorWindowRules::WindowQuery >(const QString &windowId)> ExclusionQueryProvider
Provider that builds the full WindowQuery (window class / title / role / frame size / flags) for a li...
Definition SnapEngine.h:680
void resnapToNewLayoutRequested(const QString &resnapData)
Batched resnap data (routed through WTA::handleBatchedResnap for bookkeeping)
std::optional< PhosphorEngine::WindowPlacement > capturePlacement(const QString &windowId) const override
Unified placement model — report this window's current snap state (snapped or floated) for persistenc...
bool isWindowExcluded(const QString &windowId) const
Resolve exclusion for a live windowId using the FULL window attributes when the exclusion query provi...
void pushFocusedToEmptyZone(const PhosphorEngine::NavigationContext &ctx)
Move the focused window to the first empty zone on ctx.screenId.
void commitMultiZoneSnap(const QString &windowId, const QStringList &zoneIds, const QString &screenId, PhosphorEngine::SnapIntent intent=PhosphorEngine::SnapIntent::UserInitiated, int virtualDesktop=0)
void setExcludeRuleSet(const PhosphorWindowRules::WindowRuleSet *ruleSet)
Wire the daemon's filtered Exclude rule set into the snap engine.
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateSnapAllWindowEntries(const QStringList &windowIds, const QString &screenId) const
void windowClosed(const QString &windowId) override
A window was closed.
void snapAllWindows(const PhosphorEngine::NavigationContext &ctx) override
Snap every unmanaged window on the screen.
void rotateWindows(bool clockwise, const PhosphorEngine::NavigationContext &ctx) override
Rotate snapped windows through the layout's zone order, dispatched via IPlacementEngine.
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateResnapFromCurrentAssignments(const QString &screenFilter=QString()) const
const PhosphorEngine::IPlacementState * stateForScreen(const QString &screenId) const override
void applyGeometryRequested(const QString &windowId, int x, int y, int width, int height, const QString &zoneId, const QString &screenId, bool sizeOnly)
Daemon-driven geometry application (used by autotile float restore)
QString lastActiveScreenId() const
Last screen the engine saw via windowFocused.
Definition SnapEngine.h:642
void resnapToNewLayout()
Resnap windows from previous layout to current layout after layout switch.
bool isWindowTracked(const QString &windowId) const override
Whether this engine considers the window owned (snapped, snap-floated, or otherwise carried in SnapSt...
void windowFocused(const QString &windowId, const QString &screenId) override
A window gained focus (called when the compositor reports activation).
PhosphorProtocol::SnapAllResultList calculateSnapAllWindows(const QStringList &windowIds, const QString &screenId)
Calculate snap-all-windows assignments without applying them.
void cycleFocus(bool forward, const PhosphorEngine::NavigationContext &ctx) override
Cycle keyboard focus forward/backward through managed windows in the active zone (or the layout cycle...
void uncommitSnap(const QString &windowId)
PhosphorEngine::SnapResult resolveWindowRestore(const QString &windowId, const QString &screenId, bool sticky, PhosphorEngine::WindowKind kind=PhosphorEngine::WindowKind::Unknown)
Resolve auto-snap for a newly opened window.
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateResnapEntriesFromAutotileOrder(const QStringList &autotileWindowOrder, const QString &screenId, const QStringList &preClaimedZoneIds={})
Calculate resnap entries from autotile order WITHOUT emitting signal.
void commitSnap(const QString &windowId, const QString &zoneId, const QString &screenId, PhosphorEngine::SnapIntent intent=PhosphorEngine::SnapIntent::UserInitiated, int virtualDesktop=0)
virtualDesktop pins the assignment to a specific 1-based desktop; 0 (default) records it on the windo...
QVector< PhosphorEngine::ZoneAssignmentEntry > calculateResnapFromAutotileOrder(const QStringList &autotileWindowOrder, const QString &screenId, const QStringList &preClaimedZoneIds={}) const
void toggleWindowFloat(const QString &windowId, const QString &screenId) override
Toggle between managed and floating.
void setAutotileEngine(PhosphorEngine::IPlacementEngine *engine)
Set the autotile engine for screen ownership checks.
PhosphorProtocol::WindowGeometryList applyBatchAssignments(const QVector< PhosphorEngine::ZoneAssignmentEntry > &entries, PhosphorEngine::SnapIntent intent=PhosphorEngine::SnapIntent::UserInitiated, std::function< QString()> fallbackScreenResolver={})
void setNavigationStateProvider(INavigationStateProvider *provider)
Wire the typed navigation-state provider.
void setZoneAdjacencyResolver(IZoneAdjacencyResolver *resolver)
Set typed zone-adjacency resolver for directional navigation.
void setCrossSurfaceResolver(PhosphorEngine::ICrossSurfaceResolver *resolver) override
Inject the cross-surface resolver (neighbour output / desktop lookup), threaded into the navigation t...
void swapFocusedInDirection(const QString &direction, const PhosphorEngine::NavigationContext &ctx) override
Swap the focused window with whatever's in the adjacent zone in direction.
void resnapCurrentAssignments(const QString &screenFilter=QString())
Resnap windows to their current zone assignments (re-apply geometries)
SnapEngine(PhosphorZones::LayoutRegistry *layoutManager, PhosphorEngine::IWindowTrackingService *windowTracker, PhosphorZones::IZoneDetector *zoneDetector, PhosphorEngine::IVirtualDesktopManager *vdm, QObject *parent=nullptr)
Pure snap-mode navigation target resolver.
Definition snapnavigationtargets.h:79
Per-screen snap placement state.
Definition SnapState.h:33
Abstract interface for zone detection + highlight lifecycle.
Definition IZoneDetector.h:84
Manual zone-layout registry + per-context assignment store.
Definition LayoutRegistry.h:78
Represents a collection of zones that form a layout.
Definition Layout.h:40
SnapIntent
Definition EngineTypes.h:32
WindowKind
Coarse structural classification for the snap-restore consume gate.
Definition EngineTypes.h:39
constexpr QLatin1String LayoutRegistry("org.plasmazones.LayoutRegistry")
QList< SnapAllResultEntry > SnapAllResultList
Definition NavigationTypes.h:38
QList< WindowGeometryEntry > WindowGeometryList
Definition WindowTypes.h:51
Definition WindowTrackingService.h:38
Definition IWindowTrackingService.h:23
Context for a cross-engine window handoff.
Definition IPlacementEngine.h:385
Target window + screen for a navigation or lifecycle operation.
Definition NavigationContext.h:18
Definition EngineTypes.h:84
Definition EngineTypes.h:109
Per-side edge gap values (resolved, non-negative pixel values)
Definition EdgeGaps.h:27
D-Bus struct for window state: (sssbsasb)
Definition WindowTypes.h:77
What a matched open-placement rule directs for an opening window.
Definition PlacementDirective.h:34