1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999 Matthias Ettrich <ettrich@kde.org>
4 SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-or-later
7*/
8
9#ifndef KX11EXTRAS_H
10#define KX11EXTRAS_H
11
12#include <QObject>
13#include <QWindow>
14
15#include <kwindowsystem_export.h>
16
17#include "netwm_def.h"
18
19class NETWinInfo;
20class NETEventFilter;
21
22/*!
23 * \qmltype KX11Extras
24 * \inqmlmodule org.kde.kwindowsystem
25 * \nativetype KX11Extras
26 * \brief A collection of functions to obtain information from and manipulate X11 windows.
27 *
28 * These are generally not applicable to other window systems.
29 *
30 * \since 5.101
31 */
32/*!
33 * \class KX11Extras
34 * \inmodule KWindowSystem
35 * \brief A collection of functions to obtain information from and manipulate X11 windows.
36 *
37 * These are generally not applicable to other window systems.
38 *
39 * \since 5.101
40 */
41class KWINDOWSYSTEM_EXPORT KX11Extras : public QObject
42{
43 Q_OBJECT
44
45 /*!
46 * \qmlproperty bool KX11Extras::compositingActive
47 * \brief Whether desktop compositing is active.
48 */
49 /*!
50 * \property KX11Extras::compositingActive
51 * \brief Whether desktop compositing is active.
52 */
53 Q_PROPERTY(bool compositingActive READ compositingActive NOTIFY compositingChanged)
54
55public:
56 /*! */
57 static KX11Extras *self();
58
59 /*!
60 * Returns the list of all toplevel windows currently managed by the
61 * window manager in the order of creation.
62 *
63 * Please do not rely on indexes of this list:
64 * Whenever you enter Qt's event loop in your
65 * application, it may happen that entries are removed or added.
66 * Your module should perhaps work on a copy of this list and verify a
67 * window with hasWId() before any operations.
68 *
69 * Iteration over this list can be done easily with:
70 * \code
71 * QList<WId> windows = KWindowSystem::windows();
72 * for (auto it = windows.cbegin(), end = windows.cend(); it != end; ++it) {
73 * ... do something here, (*it) is the current WId.
74 * }
75 * \endcode
76 */
77 static QList<WId> windows();
78
79 /*!
80 * Returns whether \a id is still managed at present.
81 */
82 static bool hasWId(WId id);
83
84 /*!
85 * Returns the list of all toplevel windows currently managed by the
86 * window manager in the current stacking order (from lower to
87 * higher).
88 *
89 * May be useful for pagers.
90 */
91 static QList<WId> stackingOrder();
92
93 /*!
94 * Returns the currently active window id, or 0 if no window is active.
95 */
96 static WId activeWindow();
97
98 /*!
99 * Requests that window \a win is activated, with the optional
100 * X server timestamp \a time of the user activity that caused this request.
101 *
102 * There are two ways how to activate a window, by calling
103 * activateWindow() and forceActiveWindow(). Generally,
104 * applications shouldn't make attempts to explicitly activate
105 * their windows, and instead let the user to activate them.
106 * In the special cases where this may be needed, applications
107 * should use activateWindow(). Window manager may consider whether
108 * this request wouldn't result in focus stealing, which
109 * would be obtrusive, and may refuse the request.
110 *
111 * The usage of forceActiveWindow() is meant only for pagers
112 * and similar tools, which represent direct user actions
113 * related to window manipulation.
114 * Except for rare cases, this request will be always honored,
115 * and normal applications are forbidden to use it.
116 */
117 static void activateWindow(WId win, long time = 0);
118
119 /*!
120 * Sets window \a win to be the active window, with the optional
121 * X server timestamp \a time of the user activity that caused this request.
122 *
123 * Note that this should be called only in special cases, applications
124 * shouldn't force themselves or other windows to be the active
125 * window. Generally, this call should used only by pagers
126 * and similar tools. See the explanation in description
127 * of activateWindow().
128 */
129 static void forceActiveWindow(WId win, long time = 0);
130
131 /*!
132 * \qmlmethod void KX11Extras::forceActiveWindow(Window *window, long time = 0)
133 * Sets \a window to be the active window, with the optional
134 * X server timestamp \a time of the user activity that caused this request.
135 *
136 * Note that this should be called only in special cases, applications
137 * shouldn't force themselves or other windows to be the active
138 * window. Generally, this call should used only by pagers
139 * and similar tools. See the explanation in the description
140 * of KX11Extras::activateWindow().
141 *
142 * \since 6.0
143 */
144 Q_INVOKABLE static void forceActiveWindow(QWindow *window, long time = 0);
145
146 /*!
147 * Returns true if a compositing manager is running (i.e. ARGB windows
148 * are supported, effects will be provided, etc.).
149 */
150 static bool compositingActive();
151
152 /*!
153 * Returns the current virtual desktop.
154 */
155 static int currentDesktop();
156
157 /*!
158 * Returns the number of virtual desktops.
159 */
160 static int numberOfDesktops();
161
162 /*!
163 * Convenience function to set the current desktop to \a desktop number.
164 *
165 * See NETRootInfo.
166 */
167 static void setCurrentDesktop(int desktop);
168
169 /*!
170 * Sets window id \a win to be present on all virtual desktops if \a b
171 * is true. Otherwise the window lives only on one single desktop.
172 */
173 static void setOnAllDesktops(WId win, bool b);
174
175 /*!
176 * Moves window id \a win to \a desktop.
177 */
178 static void setOnDesktop(WId win, int desktop);
179
180 /*!
181 * Moves window id \a win to the list of \a activities UUIDs.
182 *
183 * \sa KWindowInfo::activities
184 */
185 static void setOnActivities(WId win, const QStringList &activities);
186
187 /*!
188 * Returns an icon for window \a win.
189 *
190 * If \a width and \a height are specified, the best icon for the requested
191 * size is returned.
192 *
193 * If \a scale is true, the icon is smooth-scaled to have exactly
194 * the requested size.
195 */
196 static QPixmap icon(WId win, int width = -1, int height = -1, bool scale = false);
197
198 /*!
199 * \enum KX11Extras::IconSource
200 * Masks specifying from which sources to read an icon.
201 *
202 * They are tried from the best until an icon is found.
203 * \value NETWM Property from the window manager specification.
204 * \value WMHints From WMHints property.
205 * \value ClassHint Load icon after getting name from the classhint.
206 * \value XApp Load the standard X icon (last fallback).
207 */
208 enum IconSource {
209 NETWM = 1,
210 WMHints = 2,
211 ClassHint = 4,
212 XApp = 8,
213 };
214 /*!
215 * \overload
216 *
217 * Overloaded variant that allows specifying from which sources the icon should be read.
218 * You should usually prefer the simpler variant which tries all possibilities to get
219 * an icon.
220 *
221 * \a win The id of the window.
222 * \a width The desired width, or -1.
223 * \a height The desired height, or -1.
224 * \a scale If true the icon will be scaled to the desired size. Otherwise the
225 * icon will not be modified.
226 * \a flags OR-ed flags from the IconSource enum.
227 */
228 static QPixmap icon(WId win, int width, int height, bool scale, int flags);
229
230 /*!
231 * \overload
232 *
233 * Overloaded variant that allows passing in the NETWinInfo \a info to use for reading the
234 * information. This variant is only useful on the X11 platform, other platforms do not
235 * use NETWinInfo and delegate to the variant without NETWinInfo. Though if compiled with
236 * X11 support the X11 variant is used on other platforms if \a info is not \c nullptr.
237 * This can be used by applications using e.g. platform wayland but also connecting to an
238 * XServer.
239 *
240 * The NETWinInfo must be constructed with properties:
241 *
242 * \list
243 * \li NET::WMIcon to use the IconSource flag NETWM
244 * \li NET::WM2IconPixmap to use the IconSource flag WMHints
245 * \li NET::WM2WindowClass to use the IconSource flag ClassHint
246 * \endlist
247 *
248 * \a win The id of the window.
249 *
250 * \a width The desired width, or -1.
251 *
252 * \a height The desired height, or -1.
253 *
254 * \a scale If true the icon will be scaled to the desired size. Otherwise the
255 * icon will not be modified.
256 *
257 * \a flags OR-ed flags from the IconSource enum.
258 */
259 static QPixmap icon(WId win, int width, int height, bool scale, int flags, NETWinInfo *info);
260
261 /*!
262 * Minimizes the window with id \a win.
263 *
264 * On X11 this follows the protocol described in ICCCM section 4.1.4.
265 * \sa unminimizeWindow()
266 */
267 static void minimizeWindow(WId win);
268 /*!
269 * Unminimizes the window with id \a win.
270 *
271 * On X11 this follows the protocol described in ICCCM section 4.1.4.
272 * \sa minimizeWindow()
273 */
274 static void unminimizeWindow(WId win);
275
276 /*!
277 * Returns the workarea for the specified \a desktop, or the current
278 * work area if no desktop has been specified.
279 *
280 * The current desktop corresponds to -1.
281 */
282 static QRect workArea(int desktop = -1);
283
284 /*!
285 * Returns the workarea for the specified \a desktop, or the current
286 * work area if no desktop has been specified.
287 *
288 * A list of struts belonging to clients can be specified with \a excludes.
289 */
290 static QRect workArea(const QList<WId> &excludes, int desktop = -1);
291
292 /*!
293 * Returns the name of the specified \a desktop number.
294 */
295 static QString desktopName(int desktop);
296
297 /*!
298 * Sets the \a name of the specified \a desktop number.
299 */
300 static void setDesktopName(int desktop, const QString &name);
301
302 /*!
303 * Reads and returns the contents of the given text
304 * property (WM_NAME, WM_ICON_NAME,...).
305 */
306 static QString readNameProperty(WId window, unsigned long atom);
307
308 /*!
309 * Returns true if viewports are mapped to virtual desktops.
310 */
311 static bool mapViewport();
312
313 /*!
314 * Sets the strut of window \a win to \a left_width
315 * ranging from \a left_start to \a left_end on the left edge,
316 * and simiarly for the other edges. For not reserving a strut, pass 0 as the width.
317 * E.g. to reserve 10x10 square in the topleft corner, use e.g.
318 * setExtendedStrut( w, 10, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 ).
319 *
320 * \a win The id of the window.
321 *
322 * \a left_width Width of the strut at the left edge.
323 *
324 * \a left_start Starting y coordinate of the strut at the left edge.
325 *
326 * \a left_end Ending y coordinate of the strut at the left edge.
327 *
328 * \a right_width Width of the strut at the right edge.
329 *
330 * \a right_start Starting y coordinate of the strut at the right edge.
331 *
332 * \a right_end Ending y coordinate of the strut at the right edge.
333 *
334 * \a top_width Width of the strut at the top edge.
335 *
336 * \a top_start Starting x coordinate of the strut at the top edge.
337 *
338 * \a top_end Ending x coordinate of the strut at the top edge.
339 *
340 * \a bottom_width Width of the strut at the bottom edge.
341 *
342 * \a bottom_start Starting x coordinate of the strut at the bottom edge.
343 *
344 * \a bottom_end Ending x coordinate of the strut at the bottom edge.
345 */
346 static void setExtendedStrut(WId win,
347 qreal left_width,
348 qreal left_start,
349 qreal left_end,
350 qreal right_width,
351 qreal right_start,
352 qreal right_end,
353 qreal top_width,
354 qreal top_start,
355 qreal top_end,
356 qreal bottom_width,
357 qreal bottom_start,
358 qreal bottom_end);
359 /*!
360 * Convenience function for setExtendedStrut() that automatically makes struts
361 * as wide/high as the screen width/height.
362 * Sets the strut of window \a win to \a left, \a right, \a top, \a bottom.
363 * \sa setExtendedStrut
364 */
365 static void setStrut(WId win, qreal left, qreal right, qreal top, qreal bottom);
366
367 /*!
368 * Sets the type of window \a win to \a windowType.
369 * \sa NET::WindowType
370 * \since 6.0
371 */
372 static void setType(WId win, NET::WindowType windowType);
373
374 /*!
375 * Clears the state of window \a win from \a state.
376 *
377 * Possible values are OR'ed combinations of:
378 *
379 * \list
380 * \li NET::Modal
381 * \li NET::Sticky
382 * \li NET::MaxVert
383 * \li NET::MaxHoriz
384 * \li NET::Shaded
385 * \li NET::SkipTaskbar
386 * \li NET::SkipPager
387 * \li NET::Hidden
388 * \li NET::FullScreen
389 * \li NET::KeepAbove
390 * \li NET::KeepBelow
391 * \li NET::SkipSwitcher
392 * \endlist
393 * \since 6.0
394 */
395 static void clearState(WId win, NET::States state);
396
397 /*!
398 * Sets the state of window \a win to \a state.
399 *
400 * Possible values are OR'ed combinations of:
401 * \list
402 * \li NET::Modal
403 * \li NET::Sticky
404 * \li NET::MaxVert
405 * \li NET::MaxHoriz
406 * \li NET::Shaded
407 * \li NET::SkipTaskbar
408 * \li NET::SkipPager
409 * \li NET::Hidden
410 * \li NET::FullScreen
411 * \li NET::KeepAbove
412 * \li NET::KeepBelow
413 * \li NET::SkipSwitcher
414 * \endlist
415 * \since 6.0
416 */
417 static void setState(WId win, NET::States state);
418
419Q_SIGNALS:
420
421 /*!
422 * Switched to another virtual \a desktop.
423 */
424 void currentDesktopChanged(int desktop);
425
426 /*!
427 * A window with the given \a id has been added.
428 */
429 void windowAdded(WId id);
430
431 /*!
432 * A window with the given \a id has been removed.
433 */
434 void windowRemoved(WId id);
435
436 /*!
437 * Hint that <Window> with the given \a id is active (= has focus) now.
438 */
439 void activeWindowChanged(WId id);
440
441 /*!
442 * Desktops have been renamed.
443 */
444 void desktopNamesChanged();
445
446 /*!
447 * The number \a num of desktops changed.
448 */
449 void numberOfDesktopsChanged(int num);
450
451 /*!
452 * The workarea has changed.
453 */
454 void workAreaChanged();
455
456 /*!
457 * Something changed with the struts, may or may not have changed the work area.
458 *
459 * Usually just using the workAreaChanged() signal is sufficient.
460 */
461 void strutChanged();
462
463 /*!
464 * Emitted when the stacking order of the window changed.
465 *
466 * The new order can be obtained with stackingOrder().
467 */
468 void stackingOrderChanged();
469
470 /*!
471 * The window with the given \a id changed.
472 *
473 * Carries the NET::Properties \a properties and
474 * NET::Properties2 \a properties2 that were changed.
475 */
476 void windowChanged(WId id, NET::Properties properties, NET::Properties2 properties2);
477
478 /*!
479 * Compositing was \a enabled or disabled.
480 *
481 * Note that this signal may be emitted before any compositing plugins
482 * have been initialized in the window manager.
483 *
484 * If you need to check if a specific compositing plugin such as the
485 * blur effect is enabled, you should track that separately rather
486 * than test for it in a slot connected to this signal.
487 */
488 void compositingChanged(bool enabled);
489
490protected:
491 void connectNotify(const QMetaMethod &signal) override;
492
493private:
494 friend class KWindowInfo;
495 friend class KWindowSystemPrivateX11;
496 friend class NETEventFilter;
497 friend class MainThreadInstantiator;
498
499 enum FilterInfo {
500 INFO_BASIC = 1, // desktop info, not per-window
501 INFO_WINDOWS = 2, // also per-window info
502 };
503
504 KWINDOWSYSTEM_NO_EXPORT void init(FilterInfo info);
505 KWINDOWSYSTEM_NO_EXPORT QPoint desktopToViewport(int desktop, bool absolute);
506 KWINDOWSYSTEM_NO_EXPORT int viewportToDesktop(const QPoint &pos);
507
508 KWINDOWSYSTEM_NO_EXPORT QPoint constrainViewportRelativePosition(const QPoint &pos);
509
510 // used in xcb/kwindowsystem.cpp
511 static bool showingDesktop();
512 static void setShowingDesktop(bool showing);
513
514 /*!
515 * \internal
516 * Returns mapped virtual desktop for the given window geometry.
517 */
518 KWINDOWSYSTEM_NO_EXPORT static int viewportWindowToDesktop(const QRect &r);
519
520 KWINDOWSYSTEM_NO_EXPORT NETEventFilter *s_d_func()
521 {
522 return d.get();
523 }
524 std::unique_ptr<NETEventFilter> d;
525};
526
527#endif
528

source code of kwindowsystem/src/kx11extras.h