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

source code of kwindowsystem/src/kx11extras.h