Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
AutotileState.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 <QColor>
7#include <QHash>
8#include <QPair>
9#include <QRect>
10#include <QRectF>
11#include <QSet>
12#include <QString>
13#include <QVector>
14#include <optional>
15
17
27{
31 QHash<QString, QSet<QString>> borderlessWindowsByScreen;
33 QHash<QString, QSet<QString>> tiledWindowsByScreen;
36 QHash<QString, QRect> zoneGeometries;
37 bool hideTitleBars = false;
38 bool showBorder = false;
39 int width = 2;
40 int radius = 0;
41 QColor color;
43};
44
51namespace AutotileStateHelpers {
52
53// ═══════════════════════════════════════════════════════════════════════════════
54// Saved geometry helpers (pure QHash operations)
55// ═══════════════════════════════════════════════════════════════════════════════
56
60inline QString findSavedGeometryKey(const QHash<QString, QRectF>& savedGeometries, const QString& windowId)
61{
62 auto it = savedGeometries.constFind(windowId);
63 if (it != savedGeometries.constEnd()) {
64 return it.key();
65 }
66 return QString();
67}
68
72inline bool hasSavedGeometryForWindow(const QHash<QString, QRectF>& savedGeometries, const QString& windowId)
73{
74 return !findSavedGeometryKey(savedGeometries, windowId).isEmpty();
75}
76
77// ═══════════════════════════════════════════════════════════════════════════════
78// Border state accessors (pure data queries)
79// ═══════════════════════════════════════════════════════════════════════════════
80
81inline bool isBorderlessWindow(const BorderState& border, const QString& windowId)
82{
83 for (auto it = border.borderlessWindowsByScreen.constBegin(); it != border.borderlessWindowsByScreen.constEnd();
84 ++it) {
85 if (it.value().contains(windowId)) {
86 return true;
87 }
88 }
89 return false;
90}
91
92inline bool isTiledWindow(const BorderState& border, const QString& windowId)
93{
94 for (auto it = border.tiledWindowsByScreen.constBegin(); it != border.tiledWindowsByScreen.constEnd(); ++it) {
95 if (it.value().contains(windowId)) {
96 return true;
97 }
98 }
99 return false;
100}
101
102inline bool shouldShowBorderForWindow(const BorderState& border, const QString& windowId)
103{
104 if (!border.showBorder)
105 return false;
106 return isBorderlessWindow(border, windowId) || isTiledWindow(border, windowId);
107}
108
109inline bool shouldApplyBorderInset(const BorderState& border, const QString& windowId)
110{
111 return border.hideTitleBars && border.width > 0 && isBorderlessWindow(border, windowId);
112}
113
114inline std::optional<QRect> borderZoneGeometry(const BorderState& border, const QString& windowId)
115{
116 auto it = border.zoneGeometries.constFind(windowId);
117 if (it != border.zoneGeometries.constEnd()) {
118 return it.value();
119 }
120 return std::nullopt;
121}
122
123inline QVector<QRect> allBorderZoneGeometries(const BorderState& border)
124{
125 QVector<QRect> result;
126 result.reserve(border.zoneGeometries.size());
127 for (auto it = border.zoneGeometries.constBegin(); it != border.zoneGeometries.constEnd(); ++it) {
128 result.append(it.value());
129 }
130 return result;
131}
132
136inline QRect applyBorderInset(const QRect& geo, int borderWidth)
137{
138 return geo.adjusted(borderWidth, borderWidth, -borderWidth, -borderWidth);
139}
140
144inline bool shouldInsetForBorder(const BorderState& border, const QString& windowId, const QRect& geo)
145{
146 return shouldApplyBorderInset(border, windowId) && geo.width() > border.width * 2
147 && geo.height() > border.width * 2;
148}
149
150// ═══════════════════════════════════════════════════════════════════════════════
151// Window closed cleanup (pure state bookkeeping)
152// ═══════════════════════════════════════════════════════════════════════════════
153
161{
162 QSet<QString>& notifiedWindows;
163 QHash<QString, QString>& notifiedWindowScreens;
165 QHash<QString, QRect>& autotileTargetZones;
166 QHash<QString, QRect>& centeredWaylandZones;
168 QHash<QString, QHash<QString, QRectF>>& preAutotileGeometries;
169};
170
177inline void cleanupClosedWindowState(const QString& windowId, const QString& screenId, BorderState& border,
178 AutotileWindowState& state)
179{
180 state.notifiedWindows.remove(windowId);
181 state.notifiedWindowScreens.remove(windowId);
182 state.minimizeFloatedWindows.remove(windowId);
183 state.autotileTargetZones.remove(windowId);
184 state.centeredWaylandZones.remove(windowId);
185 state.monocleMaximizedWindows.remove(windowId);
186 // Closed windows must be removed from every screen bucket — the effect
187 // may have stale entries if the window crossed screens before closing.
188 for (auto it = border.borderlessWindowsByScreen.begin(); it != border.borderlessWindowsByScreen.end();) {
189 it.value().remove(windowId);
190 if (it.value().isEmpty()) {
191 it = border.borderlessWindowsByScreen.erase(it);
192 } else {
193 ++it;
194 }
195 }
196 for (auto it = border.tiledWindowsByScreen.begin(); it != border.tiledWindowsByScreen.end();) {
197 it.value().remove(windowId);
198 if (it.value().isEmpty()) {
199 it = border.tiledWindowsByScreen.erase(it);
200 } else {
201 ++it;
202 }
203 }
204 border.zoneGeometries.remove(windowId);
205
206 if (!screenId.isEmpty()) {
207 auto it = state.preAutotileGeometries.find(screenId);
208 if (it != state.preAutotileGeometries.end()) {
209 it->remove(windowId);
210 }
211 }
212}
213
214// ═══════════════════════════════════════════════════════════════════════════════
215// Per-screen BorderState mutators
216// ═══════════════════════════════════════════════════════════════════════════════
217
219inline void addBorderlessOnScreen(BorderState& border, const QString& screenId, const QString& windowId)
220{
221 border.borderlessWindowsByScreen[screenId].insert(windowId);
222}
223
225inline void addTiledOnScreen(BorderState& border, const QString& screenId, const QString& windowId)
226{
227 border.tiledWindowsByScreen[screenId].insert(windowId);
228}
229
232inline bool removeBorderlessOnScreen(BorderState& border, const QString& screenId, const QString& windowId)
233{
234 auto it = border.borderlessWindowsByScreen.find(screenId);
235 if (it == border.borderlessWindowsByScreen.end()) {
236 return false;
237 }
238 const bool removed = it.value().remove(windowId);
239 if (it.value().isEmpty()) {
240 border.borderlessWindowsByScreen.erase(it);
241 }
242 return removed;
243}
244
247inline bool removeTiledOnScreen(BorderState& border, const QString& screenId, const QString& windowId)
248{
249 auto it = border.tiledWindowsByScreen.find(screenId);
250 if (it == border.tiledWindowsByScreen.end()) {
251 return false;
252 }
253 const bool removed = it.value().remove(windowId);
254 if (it.value().isEmpty()) {
255 border.tiledWindowsByScreen.erase(it);
256 }
257 return removed;
258}
259
262inline bool removeFromAllScreens(BorderState& border, const QString& windowId)
263{
264 bool any = false;
265 for (auto it = border.borderlessWindowsByScreen.begin(); it != border.borderlessWindowsByScreen.end();) {
266 if (it.value().remove(windowId)) {
267 any = true;
268 }
269 if (it.value().isEmpty()) {
270 it = border.borderlessWindowsByScreen.erase(it);
271 } else {
272 ++it;
273 }
274 }
275 for (auto it = border.tiledWindowsByScreen.begin(); it != border.tiledWindowsByScreen.end();) {
276 if (it.value().remove(windowId)) {
277 any = true;
278 }
279 if (it.value().isEmpty()) {
280 it = border.tiledWindowsByScreen.erase(it);
281 } else {
282 ++it;
283 }
284 }
285 return any;
286}
287
289inline QSet<QString> tiledOnScreen(const BorderState& border, const QString& screenId)
290{
291 return border.tiledWindowsByScreen.value(screenId);
292}
293
295inline QSet<QString> borderlessOnScreen(const BorderState& border, const QString& screenId)
296{
297 return border.borderlessWindowsByScreen.value(screenId);
298}
299
303inline QVector<QPair<QString, QString>> allBorderlessPairs(const BorderState& border)
304{
305 QVector<QPair<QString, QString>> result;
306 for (auto it = border.borderlessWindowsByScreen.constBegin(); it != border.borderlessWindowsByScreen.constEnd();
307 ++it) {
308 for (const QString& wid : it.value()) {
309 result.append({wid, it.key()});
310 }
311 }
312 return result;
313}
314
316inline QVector<QPair<QString, QString>> allTiledPairs(const BorderState& border)
317{
318 QVector<QPair<QString, QString>> result;
319 for (auto it = border.tiledWindowsByScreen.constBegin(); it != border.tiledWindowsByScreen.constEnd(); ++it) {
320 for (const QString& wid : it.value()) {
321 result.append({wid, it.key()});
322 }
323 }
324 return result;
325}
326
327} // namespace AutotileStateHelpers
328} // namespace PhosphorCompositor
QSet< QString > tiledOnScreen(const BorderState &border, const QString &screenId)
Read-only view of the set of tiled windows on a given screen. Empty if none.
Definition AutotileState.h:289
QRect applyBorderInset(const QRect &geo, int borderWidth)
Apply border inset to a geometry (shrink by border width on all sides)
Definition AutotileState.h:136
bool shouldApplyBorderInset(const BorderState &border, const QString &windowId)
Definition AutotileState.h:109
QVector< QRect > allBorderZoneGeometries(const BorderState &border)
Definition AutotileState.h:123
bool shouldInsetForBorder(const BorderState &border, const QString &windowId, const QRect &geo)
Check if border inset should be applied for a window's geometry.
Definition AutotileState.h:144
void cleanupClosedWindowState(const QString &windowId, const QString &screenId, BorderState &border, AutotileWindowState &state)
Clean up all state tracking for a closed window.
Definition AutotileState.h:177
std::optional< QRect > borderZoneGeometry(const BorderState &border, const QString &windowId)
Definition AutotileState.h:114
bool hasSavedGeometryForWindow(const QHash< QString, QRectF > &savedGeometries, const QString &windowId)
Check if we already have saved geometry for this window.
Definition AutotileState.h:72
bool isBorderlessWindow(const BorderState &border, const QString &windowId)
Definition AutotileState.h:81
bool removeFromAllScreens(BorderState &border, const QString &windowId)
Remove a window from all screen buckets (both borderless and tiled).
Definition AutotileState.h:262
QVector< QPair< QString, QString > > allBorderlessPairs(const BorderState &border)
Collect every borderless (windowId, screenId) pair for bulk operations (feature disable,...
Definition AutotileState.h:303
bool shouldShowBorderForWindow(const BorderState &border, const QString &windowId)
Definition AutotileState.h:102
void addTiledOnScreen(BorderState &border, const QString &screenId, const QString &windowId)
Add a window to a screen's tiled bucket. Idempotent.
Definition AutotileState.h:225
void addBorderlessOnScreen(BorderState &border, const QString &screenId, const QString &windowId)
Add a window to a screen's borderless bucket. Idempotent.
Definition AutotileState.h:219
QString findSavedGeometryKey(const QHash< QString, QRectF > &savedGeometries, const QString &windowId)
Find key in saved geometries map for a window (exact match only)
Definition AutotileState.h:60
bool isTiledWindow(const BorderState &border, const QString &windowId)
Definition AutotileState.h:92
bool removeBorderlessOnScreen(BorderState &border, const QString &screenId, const QString &windowId)
Remove a window from a specific screen's borderless bucket.
Definition AutotileState.h:232
QSet< QString > borderlessOnScreen(const BorderState &border, const QString &screenId)
Read-only view of the set of borderless windows on a given screen. Empty if none.
Definition AutotileState.h:295
QVector< QPair< QString, QString > > allTiledPairs(const BorderState &border)
Same for tiled. Used by updateHideTitleBarsSetting's toggle-on path.
Definition AutotileState.h:316
bool removeTiledOnScreen(BorderState &border, const QString &screenId, const QString &windowId)
Remove a window from a specific screen's tiled bucket.
Definition AutotileState.h:247
Definition AutotileState.h:16
Bundles per-window state maps for cleanup operations.
Definition AutotileState.h:161
QSet< QString > & minimizeFloatedWindows
Definition AutotileState.h:164
QHash< QString, QString > & notifiedWindowScreens
Definition AutotileState.h:163
QHash< QString, QHash< QString, QRectF > > & preAutotileGeometries
Definition AutotileState.h:168
QSet< QString > & notifiedWindows
Definition AutotileState.h:162
QHash< QString, QRect > & centeredWaylandZones
Definition AutotileState.h:166
QHash< QString, QRect > & autotileTargetZones
Definition AutotileState.h:165
QSet< QString > & monocleMaximizedWindows
Definition AutotileState.h:167
Compositor-agnostic autotile border state.
Definition AutotileState.h:27
QHash< QString, QRect > zoneGeometries
PhosphorZones::Zone geometries remain windowId-keyed — a window only lives in one zone at a time,...
Definition AutotileState.h:36
QHash< QString, QSet< QString > > borderlessWindowsByScreen
windowId → screen bucket owning its borderless state.
Definition AutotileState.h:31
bool hideTitleBars
Definition AutotileState.h:37
bool showBorder
Definition AutotileState.h:38
QColor inactiveColor
Definition AutotileState.h:42
int width
Definition AutotileState.h:39
QColor color
Definition AutotileState.h:41
QHash< QString, QSet< QString > > tiledWindowsByScreen
Same shape for the full tiled set (superset of borderless).
Definition AutotileState.h:33
int radius
Definition AutotileState.h:40