1 /*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6 SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #ifndef KWIN_UTILS_H
12 #define KWIN_UTILS_H
13
14 // cmake stuff
15 #include <config-kwin.h>
16 #include <kwinconfig.h>
17 // kwin
18 #include <kwinglobals.h>
19 // Qt
20 #include <QLoggingCategory>
21 #include <QList>
22 #include <QMatrix4x4>
23 #include <QPoint>
24 #include <QRect>
25 #include <QScopedPointer>
26 #include <QProcess>
27 // system
28 #include <climits>
29 Q_DECLARE_LOGGING_CATEGORY(KWIN_CORE)
Q_DECLARE_LOGGING_CATEGORY(KWIN_VIRTUALKEYBOARD)30 Q_DECLARE_LOGGING_CATEGORY(KWIN_VIRTUALKEYBOARD)
31 namespace KWin
32 {
33 Q_NAMESPACE
34
35 const QPoint invalidPoint(INT_MIN, INT_MIN);
36
37 enum Layer {
38 UnknownLayer = -1,
39 FirstLayer = 0,
40 DesktopLayer = FirstLayer,
41 BelowLayer,
42 NormalLayer,
43 DockLayer,
44 AboveLayer,
45 NotificationLayer, // layer for windows of type notification
46 ActiveLayer, // active fullscreen, or active dialog
47 PopupLayer, // tooltips, sub- and context menus
48 CriticalNotificationLayer, // layer for notifications that should be shown even on top of fullscreen
49 OnScreenDisplayLayer, // layer for On Screen Display windows such as volume feedback
50 UnmanagedLayer, // layer for override redirect windows.
51 NumLayers, // number of layers, must be last
52 };
53 Q_ENUM_NS(Layer)
54
55 enum StrutArea {
56 StrutAreaInvalid = 0, // Null
57 StrutAreaTop = 1 << 0,
58 StrutAreaRight = 1 << 1,
59 StrutAreaBottom = 1 << 2,
60 StrutAreaLeft = 1 << 3,
61 StrutAreaAll = StrutAreaTop | StrutAreaRight | StrutAreaBottom | StrutAreaLeft,
62 };
63 Q_DECLARE_FLAGS(StrutAreas, StrutArea)
64
65 class StrutRect : public QRect
66 {
67 public:
68 explicit StrutRect(QRect rect = QRect(), StrutArea area = StrutAreaInvalid);
69 StrutRect(int x, int y, int width, int height, StrutArea area = StrutAreaInvalid);
70 StrutRect(const StrutRect& other);
71 StrutRect &operator=(const StrutRect& other);
72 inline StrutArea area() const {
73 return m_area;
74 }
75 private:
76 StrutArea m_area;
77 };
78 typedef QVector<StrutRect> StrutRects;
79
80 enum ShadeMode {
81 ShadeNone, // not shaded
82 ShadeNormal, // normally shaded - isShade() is true only here
83 ShadeHover, // "shaded", but visible due to hover unshade
84 ShadeActivated // "shaded", but visible due to alt+tab to the window
85 };
86
87 /**
88 * Maximize mode. These values specify how a window is maximized.
89 *
90 * @note these values are written to session files, don't change the order
91 */
92 enum MaximizeMode {
93 MaximizeRestore = 0, ///< The window is not maximized in any direction.
94 MaximizeVertical = 1, ///< The window is maximized vertically.
95 MaximizeHorizontal = 2, ///< The window is maximized horizontally.
96 /// Equal to @p MaximizeVertical | @p MaximizeHorizontal
97 MaximizeFull = MaximizeVertical | MaximizeHorizontal,
98 };
99
100 inline
101 MaximizeMode operator^(MaximizeMode m1, MaximizeMode m2)
102 {
103 return MaximizeMode(int(m1) ^ int(m2));
104 }
105
106 enum class QuickTileFlag {
107 None = 0,
108 Left = 1 << 0,
109 Right = 1 << 1,
110 Top = 1 << 2,
111 Bottom = 1 << 3,
112 Horizontal = Left | Right,
113 Vertical = Top | Bottom,
114 Maximize = Left | Right | Top | Bottom,
115 };
116 Q_DECLARE_FLAGS(QuickTileMode, QuickTileFlag)
117
118 template <typename T> using ScopedCPointer = QScopedPointer<T, QScopedPointerPodDeleter>;
119
120 void KWIN_EXPORT updateXTime();
121 void KWIN_EXPORT grabXServer();
122 void KWIN_EXPORT ungrabXServer();
123 bool KWIN_EXPORT grabXKeyboard(xcb_window_t w = XCB_WINDOW_NONE);
124 void KWIN_EXPORT ungrabXKeyboard();
125
126 /**
127 * QPainter::setWindow() doesn't work as expected when the device pixel ratio of the paint
128 * device is less than 1.
129 *
130 * QPainter simply doesn't allow the effective scale factor to be less than 1. Use this function
131 * to determine the effective device pixel ratio by which the window rect has to be scaled.
132 */
133 qreal KWIN_EXPORT qPainterEffectiveDevicePixelRatio(const QPainter *painter);
134
135 static inline QRegion mapRegion(const QMatrix4x4 &matrix, const QRegion ®ion)
136 {
137 QRegion result;
138 for (const QRect &rect : region) {
139 result += matrix.mapRect(rect);
140 }
141 return result;
142 }
143
144 /**
145 * Small helper class which performs grabXServer in the ctor and
146 * ungrabXServer in the dtor. Use this class to ensure that grab and
147 * ungrab are matched.
148 */
149 class XServerGrabber
150 {
151 public:
152 XServerGrabber() {
153 grabXServer();
154 }
155 ~XServerGrabber() {
156 ungrabXServer();
157 }
158 };
159
160 // the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint
161 #ifndef UrgencyHint
162 #define UrgencyHint XUrgencyHint
163 #endif
164
165 // converting between X11 mouse/keyboard state mask and Qt button/keyboard states
166 Qt::MouseButton x11ToQtMouseButton(int button);
167 Qt::MouseButton KWIN_EXPORT x11ToQtMouseButton(int button);
168 Qt::MouseButtons KWIN_EXPORT x11ToQtMouseButtons(int state);
169 Qt::KeyboardModifiers KWIN_EXPORT x11ToQtKeyboardModifiers(int state);
170
171 /**
172 * Separate the concept of an unet QPoint and 0,0
173 */
174 class ClearablePoint
175 {
176 public:
177 inline bool isValid() const {
178 return m_valid;
179 }
180
181 inline void clear(){
182 m_valid = false;
183 }
184
185 inline void setPoint(const QPoint &point) {
186 m_point = point; m_valid = true;
187 }
188
189 inline QPoint point() const {
190 return m_point;
191 }
192
193 private:
194 QPoint m_point;
195 bool m_valid = false;
196 };
197
198 /**
199 * QProcess subclass which unblocks SIGUSR in the child process.
200 */
201 class KWIN_EXPORT Process : public QProcess
202 {
203 Q_OBJECT
204 public:
205 explicit Process(QObject *parent = nullptr);
206 ~Process() override;
207
208 #ifndef KCMRULES
209 protected:
210 void setupChildProcess() override;
211 #endif
212 };
213
214 /**
215 * The DamageJournal class is a helper that tracks last N damage regions.
216 */
217 class KWIN_EXPORT DamageJournal
218 {
219 public:
220 /**
221 * Returns the maximum number of damage regions that can be stored in the journal.
222 */
223 int capacity() const
224 {
225 return m_capacity;
226 }
227
228 /**
229 * Sets the maximum number of damage regions that can be stored in the journal
230 * to @a capacity.
231 */
232 void setCapacity(int capacity)
233 {
234 m_capacity = capacity;
235 }
236
237 /**
238 * Adds the specified @a region to the journal.
239 */
240 void add(const QRegion ®ion)
241 {
242 while (m_log.size() >= m_capacity) {
243 m_log.takeLast();
244 }
245 m_log.prepend(region);
246 }
247
248 /**
249 * Clears the damage journal. Typically, one would want to clear the damage journal
250 * if a buffer swap fails for some reason.
251 */
252 void clear()
253 {
254 m_log.clear();
255 }
256
257 /**
258 * Accumulates the damage regions in the log up to the specified @a bufferAge.
259 *
260 * If the specified buffer age value refers to a damage region older than the last
261 * one in the journal, @a fallback will be returned.
262 */
263 QRegion accumulate(int bufferAge, const QRegion &fallback = QRegion()) const
264 {
265 QRegion region;
266 if (bufferAge > 0 && bufferAge <= m_log.size()) {
267 for (int i = 0; i < bufferAge - 1; ++i) {
268 region |= m_log[i];
269 }
270 } else {
271 region = fallback;
272 }
273 return region;
274 }
275
276 private:
277 QList<QRegion> m_log;
278 int m_capacity = 10;
279 };
280
281 } // namespace
282
283 // Must be outside namespace
284 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::StrutAreas)
285 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::QuickTileMode)
286
287 #endif
288