KWindowSystem

kx11extras.cpp
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 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.1-or-later
8*/
9
10#include "kx11extras.h"
11
12// clang-format off
13#include <kxerrorhandler_p.h>
14#include <fixx11h.h>
15#include <kxutils_p.h>
16// clang-format on
17
18#include "cptr_p.h"
19#include "kwindowsystem.h"
20#include "kwindowsystem_debug.h"
21#include "netwm.h"
22
23#include <QAbstractNativeEventFilter>
24#include <QGuiApplication>
25#include <QMetaMethod>
26#include <QRect>
27#include <QScreen>
28#include <private/qtx11extras_p.h>
29
30#include <X11/Xatom.h>
31#include <X11/Xutil.h>
32#include <X11/extensions/Xfixes.h>
33#include <xcb/xcb.h>
34#include <xcb/xfixes.h>
35
36// QPoint and QSize all have handy / operators which are useful for scaling, positions and sizes for high DPI support
37// QRect does not, so we create one for internal purposes within this class
38inline QRect operator/(const QRect &rectangle, qreal factor)
39{
40 return QRect(rectangle.topLeft() / factor, rectangle.size() / factor);
41}
42
43class MainThreadInstantiator : public QObject
44{
46
47public:
48 MainThreadInstantiator(KX11Extras::FilterInfo _what);
49 Q_INVOKABLE NETEventFilter *createNETEventFilter();
50
51private:
52 KX11Extras::FilterInfo m_what;
53};
54
55class NETEventFilter : public NETRootInfo, public QAbstractNativeEventFilter
56{
57public:
58 NETEventFilter(KX11Extras::FilterInfo _what);
59 ~NETEventFilter() override;
60 void activate();
61 QList<WId> windows;
62 QList<WId> stackingOrder;
63
64 struct StrutData {
65 StrutData(WId window_, const NETStrut &strut_, int desktop_)
66 : window(window_)
67 , strut(strut_)
68 , desktop(desktop_)
69 {
70 }
71 WId window;
72 NETStrut strut;
73 int desktop;
74 };
75 QList<StrutData> strutWindows;
76 QList<WId> possibleStrutWindows;
77 bool strutSignalConnected;
78 bool compositingEnabled;
79 bool haveXfixes;
80 KX11Extras::FilterInfo what;
81 int xfixesEventBase;
82 bool mapViewport();
83
84 bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override;
85
86 void updateStackingOrder();
87 bool removeStrutWindow(WId);
88
89protected:
90 void addClient(xcb_window_t) override;
91 void removeClient(xcb_window_t) override;
92
93private:
94 bool nativeEventFilter(xcb_generic_event_t *event);
95 xcb_window_t winId;
96 xcb_window_t m_appRootWindow;
97};
98
99static Atom net_wm_cm;
100static void create_atoms();
101
102static inline const QRect &displayGeometry()
103{
104 static QRect displayGeometry;
105 static bool isDirty = true;
106
107 if (isDirty) {
108 static QList<QMetaObject::Connection> connections;
109 auto dirtify = [&] {
110 isDirty = true;
111 for (const QMetaObject::Connection &con : std::as_const(connections)) {
113 }
114 connections.clear();
115 };
116
119 const QList<QScreen *> screenList = QGuiApplication::screens();
120 QRegion region;
121 for (int i = 0; i < screenList.count(); ++i) {
122 const QScreen *screen = screenList.at(i);
123 connections << QObject::connect(screen, &QScreen::geometryChanged, dirtify);
124 const QRect geometry = screen->geometry();
125 const qreal dpr = screen->devicePixelRatio();
126 region += QRect(geometry.topLeft(), geometry.size() * dpr);
127 }
128 displayGeometry = region.boundingRect();
129 isDirty = false;
130 }
131
132 return displayGeometry;
133}
134
135static inline int displayWidth()
136{
137 return displayGeometry().width();
138}
139
140static inline int displayHeight()
141{
142 return displayGeometry().height();
143}
144
145// clang-format off
146static const NET::Properties windowsProperties = NET::ClientList | NET::ClientListStacking |
147 NET::Supported |
148 NET::NumberOfDesktops |
149 NET::DesktopGeometry |
150 NET::DesktopViewport |
151 NET::CurrentDesktop |
152 NET::DesktopNames |
153 NET::ActiveWindow |
154 NET::WorkArea;
155static const NET::Properties2 windowsProperties2 = NET::WM2ShowingDesktop;
156
157// ClientList and ClientListStacking is not per-window information, but a desktop information,
158// so track it even with only INFO_BASIC
159static const NET::Properties desktopProperties = NET::ClientList | NET::ClientListStacking |
160 NET::Supported |
161 NET::NumberOfDesktops |
162 NET::DesktopGeometry |
163 NET::DesktopViewport |
164 NET::CurrentDesktop |
165 NET::DesktopNames |
166 NET::ActiveWindow |
167 NET::WorkArea;
168static const NET::Properties2 desktopProperties2 = NET::WM2ShowingDesktop;
169// clang-format on
170
171MainThreadInstantiator::MainThreadInstantiator(KX11Extras::FilterInfo _what)
172 : QObject()
173 , m_what(_what)
174{
175}
176
177NETEventFilter *MainThreadInstantiator::createNETEventFilter()
178{
179 return new NETEventFilter(m_what);
180}
181
182NETEventFilter::NETEventFilter(KX11Extras::FilterInfo _what)
183 : NETRootInfo(QX11Info::connection(),
184 _what >= KX11Extras::INFO_WINDOWS ? windowsProperties : desktopProperties,
185 _what >= KX11Extras::INFO_WINDOWS ? windowsProperties2 : desktopProperties2,
186 QX11Info::appScreen(),
187 false)
189 , strutSignalConnected(false)
190 , compositingEnabled(false)
191 , haveXfixes(false)
192 , what(_what)
193 , winId(XCB_WINDOW_NONE)
194 , m_appRootWindow(QX11Info::appRootWindow())
195{
197
198 int errorBase;
199 if ((haveXfixes = XFixesQueryExtension(QX11Info::display(), &xfixesEventBase, &errorBase))) {
200 create_atoms();
201 winId = xcb_generate_id(QX11Info::connection());
202 uint32_t values[] = {true, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
203 xcb_create_window(QX11Info::connection(),
204 XCB_COPY_FROM_PARENT,
205 winId,
206 m_appRootWindow,
207 0,
208 0,
209 1,
210 1,
211 0,
212 XCB_WINDOW_CLASS_INPUT_ONLY,
213 XCB_COPY_FROM_PARENT,
214 XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
215 values);
216 XFixesSelectSelectionInput(QX11Info::display(),
217 winId,
218 net_wm_cm,
219 XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask);
220 compositingEnabled = XGetSelectionOwner(QX11Info::display(), net_wm_cm) != None;
221 }
222}
223
224NETEventFilter::~NETEventFilter()
225{
226 if (QX11Info::connection() && winId != XCB_WINDOW_NONE) {
227 xcb_destroy_window(QX11Info::connection(), winId);
228 winId = XCB_WINDOW_NONE;
229 }
230}
231
232// not virtual, but it's called directly only from init()
233void NETEventFilter::activate()
234{
236 updateStackingOrder();
237}
238
239bool NETEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *)
240{
241 if (eventType != "xcb_generic_event_t") {
242 // only interested in XCB events of course
243 return false;
244 }
245 return nativeEventFilter(reinterpret_cast<xcb_generic_event_t *>(message));
246}
247
248bool NETEventFilter::nativeEventFilter(xcb_generic_event_t *ev)
249{
251 const uint8_t eventType = ev->response_type & ~0x80;
252
253 if (eventType == xfixesEventBase + XCB_XFIXES_SELECTION_NOTIFY) {
254 xcb_xfixes_selection_notify_event_t *event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(ev);
255 if (event->window == winId) {
256 bool haveOwner = event->owner != XCB_WINDOW_NONE;
257 if (compositingEnabled != haveOwner) {
258 compositingEnabled = haveOwner;
259 Q_EMIT KX11Extras::self()->compositingChanged(compositingEnabled);
260 }
261 return true;
262 }
263 // Qt compresses XFixesSelectionNotifyEvents without caring about the actual window
264 // gui/kernel/qapplication_x11.cpp
265 // until that can be assumed fixed, we also react on events on the root (caused by Qts own compositing tracker)
266 if (event->window == m_appRootWindow) {
267 if (event->selection == net_wm_cm) {
268 bool haveOwner = event->owner != XCB_WINDOW_NONE;
269 if (compositingEnabled != haveOwner) {
270 compositingEnabled = haveOwner;
271 Q_EMIT KX11Extras::self()->compositingChanged(compositingEnabled);
272 }
273 // NOTICE this is not our event, we just randomly captured it from Qt -> pass on
274 return false;
275 }
276 }
277 return false;
278 }
279
280 xcb_window_t eventWindow = XCB_WINDOW_NONE;
281 switch (eventType) {
282 case XCB_CLIENT_MESSAGE:
283 eventWindow = reinterpret_cast<xcb_client_message_event_t *>(ev)->window;
284 break;
285 case XCB_PROPERTY_NOTIFY:
286 eventWindow = reinterpret_cast<xcb_property_notify_event_t *>(ev)->window;
287 break;
288 case XCB_CONFIGURE_NOTIFY:
289 eventWindow = reinterpret_cast<xcb_configure_notify_event_t *>(ev)->window;
290 break;
291 }
292
293 if (eventWindow == m_appRootWindow) {
294 int old_current_desktop = currentDesktop();
295 xcb_window_t old_active_window = activeWindow();
296 int old_number_of_desktops = numberOfDesktops();
297 bool old_showing_desktop = showingDesktop();
298 NET::Properties props;
299 NET::Properties2 props2;
300 NETRootInfo::event(ev, &props, &props2);
301
302 if ((props & CurrentDesktop) && currentDesktop() != old_current_desktop) {
303 Q_EMIT KX11Extras::self()->currentDesktopChanged(currentDesktop());
304 }
305 if ((props & DesktopViewport) && mapViewport() && currentDesktop() != old_current_desktop) {
306 Q_EMIT KX11Extras::self()->currentDesktopChanged(currentDesktop());
307 }
308 if ((props & ActiveWindow) && activeWindow() != old_active_window) {
309 Q_EMIT KX11Extras::self()->activeWindowChanged(activeWindow());
310 }
311 if (props & DesktopNames) {
312 Q_EMIT KX11Extras::self()->desktopNamesChanged();
313 }
314 if ((props & NumberOfDesktops) && numberOfDesktops() != old_number_of_desktops) {
315 Q_EMIT KX11Extras::self()->numberOfDesktopsChanged(numberOfDesktops());
316 }
317 if ((props & DesktopGeometry) && mapViewport() && numberOfDesktops() != old_number_of_desktops) {
318 Q_EMIT KX11Extras::self()->numberOfDesktopsChanged(numberOfDesktops());
319 }
320 if (props & WorkArea) {
321 Q_EMIT KX11Extras::self()->workAreaChanged();
322 }
323 if (props & ClientListStacking) {
324 updateStackingOrder();
325 Q_EMIT KX11Extras::self()->stackingOrderChanged();
326 }
327 if ((props2 & WM2ShowingDesktop) && showingDesktop() != old_showing_desktop) {
329 }
330 } else if (windows.contains(eventWindow)) {
331 NETWinInfo ni(QX11Info::connection(), eventWindow, m_appRootWindow, NET::Properties(), NET::Properties2());
332 NET::Properties dirtyProperties;
333 NET::Properties2 dirtyProperties2;
334 ni.event(ev, &dirtyProperties, &dirtyProperties2);
335 if (eventType == XCB_PROPERTY_NOTIFY) {
336 xcb_property_notify_event_t *event = reinterpret_cast<xcb_property_notify_event_t *>(ev);
337 if (event->atom == XCB_ATOM_WM_HINTS) {
338 dirtyProperties |= NET::WMIcon; // support for old icons
339 } else if (event->atom == XCB_ATOM_WM_NAME) {
340 dirtyProperties |= NET::WMName; // support for old name
341 } else if (event->atom == XCB_ATOM_WM_ICON_NAME) {
342 dirtyProperties |= NET::WMIconName; // support for old iconic name
343 }
344 }
345 if (mapViewport() && (dirtyProperties & (NET::WMState | NET::WMGeometry))) {
346 /* geometry change -> possible viewport change
347 * state change -> possible NET::Sticky change
348 */
349 dirtyProperties |= NET::WMDesktop;
350 }
351 if ((dirtyProperties & NET::WMStrut) != 0) {
352 removeStrutWindow(eventWindow);
353 if (!possibleStrutWindows.contains(eventWindow)) {
354 possibleStrutWindows.append(eventWindow);
355 }
356 }
357 if (dirtyProperties || dirtyProperties2) {
358 Q_EMIT KX11Extras::self()->windowChanged(eventWindow, dirtyProperties, dirtyProperties2);
359
360 if ((dirtyProperties & NET::WMStrut) != 0) {
361 Q_EMIT KX11Extras::self()->strutChanged();
362 }
363 }
364 }
365
366 return false;
367}
368
369bool NETEventFilter::removeStrutWindow(WId w)
370{
371 for (QList<StrutData>::Iterator it = strutWindows.begin(); it != strutWindows.end(); ++it) {
372 if ((*it).window == w) {
373 strutWindows.erase(it);
374 return true;
375 }
376 }
377 return false;
378}
379
380void NETEventFilter::updateStackingOrder()
381{
382 stackingOrder.clear();
383 for (int i = 0; i < clientListStackingCount(); i++) {
384 stackingOrder.append(clientListStacking()[i]);
385 }
386}
387
388void NETEventFilter::addClient(xcb_window_t w)
389{
390 if ((what >= KX11Extras::INFO_WINDOWS)) {
391 xcb_connection_t *c = QX11Info::connection();
392 UniqueCPointer<xcb_get_window_attributes_reply_t> attr(xcb_get_window_attributes_reply(c, xcb_get_window_attributes_unchecked(c, w), nullptr));
393
394 uint32_t events = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
395 if (attr) {
396 events = events | attr->your_event_mask;
397 }
398 xcb_change_window_attributes(c, w, XCB_CW_EVENT_MASK, &events);
399 }
400
401 bool emit_strutChanged = false;
402
403 if (strutSignalConnected) {
404 NETWinInfo info(QX11Info::connection(), w, QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop, NET::Properties2());
405 NETStrut strut = info.strut();
406 if (strut.left || strut.top || strut.right || strut.bottom) {
407 strutWindows.append(StrutData(w, strut, info.desktop()));
408 emit_strutChanged = true;
409 }
410 } else {
411 possibleStrutWindows.append(w);
412 }
413
414 windows.append(w);
415 Q_EMIT KX11Extras::self()->windowAdded(w);
416 if (emit_strutChanged) {
417 Q_EMIT KX11Extras::self()->strutChanged();
418 }
419}
420
421void NETEventFilter::removeClient(xcb_window_t w)
422{
423 bool emit_strutChanged = removeStrutWindow(w);
424 if (strutSignalConnected && possibleStrutWindows.contains(w)) {
425 NETWinInfo info(QX11Info::connection(), w, QX11Info::appRootWindow(), NET::WMStrut, NET::Properties2());
426 NETStrut strut = info.strut();
427 if (strut.left || strut.top || strut.right || strut.bottom) {
428 emit_strutChanged = true;
429 }
430 }
431
432 possibleStrutWindows.removeAll(w);
433 windows.removeAll(w);
434 Q_EMIT KX11Extras::self()->windowRemoved(w);
435 if (emit_strutChanged) {
436 Q_EMIT KX11Extras::self()->strutChanged();
437 }
438}
439
440bool NETEventFilter::mapViewport()
441{
442 // compiz claims support even though it doesn't use virtual desktops :(
443 // if( isSupported( NET::DesktopViewport ) && !isSupported( NET::NumberOfDesktops ))
444
445 // this test is duplicated in KWindowSystem::mapViewport()
446 if (isSupported(NET::DesktopViewport) && numberOfDesktops(true) <= 1
447 && (desktopGeometry().width > displayWidth() || desktopGeometry().height > displayHeight())) {
448 return true;
449 }
450 return false;
451}
452
453static bool atoms_created = false;
454
455static Atom _wm_protocols;
456static Atom _wm_change_state;
457static Atom kwm_utf8_string;
458
459static void create_atoms()
460{
461 if (!atoms_created) {
462 const int max = 20;
463 Atom *atoms[max];
464 const char *names[max];
465 Atom atoms_return[max];
466 int n = 0;
467
468 atoms[n] = &_wm_protocols;
469 names[n++] = "WM_PROTOCOLS";
470
471 atoms[n] = &_wm_change_state;
472 names[n++] = "WM_CHANGE_STATE";
473
474 atoms[n] = &kwm_utf8_string;
475 names[n++] = "UTF8_STRING";
476
477 char net_wm_cm_name[100];
478 sprintf(net_wm_cm_name, "_NET_WM_CM_S%d", QX11Info::appScreen());
479 atoms[n] = &net_wm_cm;
480 names[n++] = net_wm_cm_name;
481
482 // we need a const_cast for the shitty X API
483 XInternAtoms(QX11Info::display(), const_cast<char **>(names), n, false, atoms_return);
484 for (int i = 0; i < n; i++) {
485 *atoms[i] = atoms_return[i];
486 }
487
488 atoms_created = True;
489 }
490}
491
492#define CHECK_X11 \
493 if (!KWindowSystem::isPlatformX11()) { \
494 qCWarning(LOG_KWINDOWSYSTEM) << Q_FUNC_INFO << "may only be used on X11"; \
495 return {}; \
496 }
497
498#define CHECK_X11_VOID \
499 if (!KWindowSystem::isPlatformX11()) { \
500 qCWarning(LOG_KWINDOWSYSTEM) << Q_FUNC_INFO << "may only be used on X11"; \
501 return; \
502 }
503
504// WARNING
505// you have to call s_d_func() again after calling this function if you want a valid pointer!
506void KX11Extras::init(FilterInfo what)
507{
508 NETEventFilter *const s_d = s_d_func();
509
510 if (what >= INFO_WINDOWS) {
511 what = INFO_WINDOWS;
512 } else {
513 what = INFO_BASIC;
514 }
515
516 if (!s_d || s_d->what < what) {
517 const bool wasCompositing = s_d ? s_d->compositingEnabled : false;
518 MainThreadInstantiator instantiator(what);
519 NETEventFilter *filter;
520 if (instantiator.thread() == QCoreApplication::instance()->thread()) {
521 filter = instantiator.createNETEventFilter();
522 } else {
523 // the instantiator is not in the main app thread, which implies
524 // we are being called in a thread that is not the main app thread
525 // so we move the instantiator to the main app thread and invoke
526 // the method with a blocking call
527 instantiator.moveToThread(QCoreApplication::instance()->thread());
528 QMetaObject::invokeMethod(&instantiator, "createNETEventFilter", Qt::BlockingQueuedConnection, Q_RETURN_ARG(NETEventFilter *, filter));
529 }
530 d.reset(filter);
531 d->activate();
532 if (wasCompositing != s_d_func()->compositingEnabled) {
533 Q_EMIT KX11Extras::self()->compositingChanged(s_d_func()->compositingEnabled);
534 }
535 }
536}
537
538KX11Extras *KX11Extras::self()
539{
540 static KX11Extras instance;
541 return &instance;
542}
543
545{
546 CHECK_X11
547 KX11Extras::self()->init(INFO_BASIC);
548 return KX11Extras::self()->s_d_func()->windows;
549}
550
552{
553 CHECK_X11
554 return windows().contains(w);
555}
556
558{
559 CHECK_X11
560 KX11Extras::self()->init(INFO_BASIC);
561 return KX11Extras::self()->s_d_func()->stackingOrder;
562}
563
565{
566 CHECK_X11
567 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
568 if (s_d) {
569 return s_d->activeWindow();
570 }
571 NETRootInfo info(QX11Info::connection(), NET::ActiveWindow, NET::Properties2(), QX11Info::appScreen());
572 return info.activeWindow();
573}
574
575void KX11Extras::activateWindow(WId win, long time)
576{
577 CHECK_X11_VOID
578 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
579 if (time == 0) {
580 time = QX11Info::appUserTime();
581 }
582 info.setActiveWindow(win, NET::FromApplication, time, QGuiApplication::focusWindow() ? QGuiApplication::focusWindow()->winId() : 0);
583}
584
585void KX11Extras::forceActiveWindow(WId win, long time)
586{
587 CHECK_X11_VOID
588 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
589 if (time == 0) {
590 time = QX11Info::appTime();
591 }
592 info.setActiveWindow(win, NET::FromTool, time, 0);
593}
594
596{
597 CHECK_X11_VOID
598 forceActiveWindow(win->winId(), time);
599}
600
602{
603 CHECK_X11
604 KX11Extras::self()->init(INFO_BASIC);
605 if (KX11Extras::self()->s_d_func()->haveXfixes) {
606 return KX11Extras::self()->s_d_func()->compositingEnabled;
607 } else {
608 create_atoms();
609 return XGetSelectionOwner(QX11Info::display(), net_wm_cm);
610 }
611}
612
614{
615 CHECK_X11
616 if (!QX11Info::connection()) {
617 return 1;
618 }
619
620 if (mapViewport()) {
621 KX11Extras::self()->init(INFO_BASIC);
622 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
623 NETPoint p = s_d->desktopViewport(s_d->currentDesktop(true));
624 return KX11Extras::self()->viewportToDesktop(QPoint(p.x, p.y) / qApp->devicePixelRatio());
625 }
626
627 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
628 if (s_d) {
629 return s_d->currentDesktop(true);
630 }
631 NETRootInfo info(QX11Info::connection(), NET::CurrentDesktop, NET::Properties2(), QX11Info::appScreen());
632 return info.currentDesktop(true);
633}
634
636{
637 CHECK_X11
638 if (!QX11Info::connection()) {
639 return 1;
640 }
641
642 if (mapViewport()) {
643 KX11Extras::self()->init(INFO_BASIC);
644 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
645 NETSize s = s_d->desktopGeometry();
646 return s.width / displayWidth() * s.height / displayHeight();
647 }
648
649 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
650 if (s_d) {
651 return s_d->numberOfDesktops(true);
652 }
653 NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops, NET::Properties2(), QX11Info::appScreen());
654 return info.numberOfDesktops(true);
655}
656
658{
659 CHECK_X11_VOID
660 if (mapViewport()) {
661 KX11Extras::self()->init(INFO_BASIC);
662 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
663 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
664 QPoint pos = KX11Extras::self()->desktopToViewport(desktop, true);
665 NETPoint p;
666 p.x = pos.x();
667 p.y = pos.y();
668 info.setDesktopViewport(s_d->currentDesktop(true), p);
669 return;
670 }
671 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
672 info.setCurrentDesktop(desktop, true);
673}
674
675void KX11Extras::setOnAllDesktops(WId win, bool b)
676{
677 CHECK_X11_VOID
678 if (mapViewport()) {
679 if (b) {
680 setState(win, NET::Sticky);
681 } else {
683 }
684 return;
685 }
686 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMDesktop, NET::Properties2());
687 if (b) {
689 } else if (info.desktop(true) == NETWinInfo::OnAllDesktops) {
690 NETRootInfo rinfo(QX11Info::connection(), NET::CurrentDesktop, NET::Properties2(), QX11Info::appScreen());
691 info.setDesktop(rinfo.currentDesktop(true), true);
692 }
693}
694
695void KX11Extras::setOnDesktop(WId win, int desktop)
696{
697 CHECK_X11_VOID
698 if (mapViewport()) {
699 if (desktop == NET::OnAllDesktops) {
700 return setOnAllDesktops(win, true);
701 } else {
703 }
704 KX11Extras::self()->init(INFO_BASIC);
705 QPoint p = KX11Extras::self()->desktopToViewport(desktop, false);
706 Window dummy;
707 int x;
708 int y;
709 unsigned int w;
710 unsigned int h;
711 unsigned int b;
712 unsigned int dp;
713 XGetGeometry(QX11Info::display(), win, &dummy, &x, &y, &w, &h, &b, &dp);
714 // get global position
715 XTranslateCoordinates(QX11Info::display(), win, QX11Info::appRootWindow(), 0, 0, &x, &y, &dummy);
716 x += w / 2; // center
717 y += h / 2;
718 // transform to coordinates on the current "desktop"
719 x = x % displayWidth();
720 y = y % displayHeight();
721 if (x < 0) {
722 x = x + displayWidth();
723 }
724 if (y < 0) {
725 y = y + displayHeight();
726 }
727 x += p.x(); // move to given "desktop"
728 y += p.y();
729 x -= w / 2; // from center back to topleft
730 y -= h / 2;
731 p = KX11Extras::self()->constrainViewportRelativePosition(QPoint(x, y));
732 int flags = (NET::FromTool << 12) | (0x03 << 8) | 10; // from tool(?), x/y, static gravity
733 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
734 s_d->moveResizeWindowRequest(win, flags, p.x(), p.y(), w, h);
735 return;
736 }
737 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMDesktop, NET::Properties2());
738 info.setDesktop(desktop, true);
739}
740
741void KX11Extras::setOnActivities(WId win, const QStringList &activities)
742{
743 CHECK_X11_VOID
744 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::Properties(), NET::WM2Activities);
745 info.setActivities(activities.join(QLatin1Char(',')).toLatin1().constData());
746}
747
748QPixmap KX11Extras::icon(WId win, int width, int height, bool scale)
749{
750 CHECK_X11
751 return icon(win, width, height, scale, NETWM | WMHints | ClassHint | XApp);
752}
753
754QPixmap iconFromNetWinInfo(int width, int height, bool scale, int flags, NETWinInfo *info)
755{
756 QPixmap result;
757 if (!info) {
758 return result;
759 }
760 if (flags & KX11Extras::NETWM) {
761 NETIcon ni = info->icon(width, height);
762 if (ni.data && ni.size.width > 0 && ni.size.height > 0) {
763 QImage img((uchar *)ni.data, (int)ni.size.width, (int)ni.size.height, QImage::Format_ARGB32);
764 if (scale && width > 0 && height > 0 && img.size() != QSize(width, height) && !img.isNull()) {
765 img = img.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
766 }
767 if (!img.isNull()) {
768 result = QPixmap::fromImage(img);
769 }
770 return result;
771 }
772 }
773
774 if (flags & KX11Extras::WMHints) {
775 xcb_pixmap_t p = info->icccmIconPixmap();
776 xcb_pixmap_t p_mask = info->icccmIconPixmapMask();
777
778 if (p != XCB_PIXMAP_NONE) {
779 QPixmap pm = KXUtils::createPixmapFromHandle(info->xcbConnection(), p, p_mask);
780 if (scale && width > 0 && height > 0 && !pm.isNull() //
781 && (pm.width() != width || pm.height() != height)) {
783 } else {
784 result = pm;
785 }
786 }
787 }
788
789 // Since width can be any arbitrary size, but the icons cannot,
790 // take the nearest value for best results (ignoring 22 pixel
791 // icons as they don't exist for apps):
792 int iconWidth;
793 if (width < 24) {
794 iconWidth = 16;
795 } else if (width < 40) {
796 iconWidth = 32;
797 } else if (width < 56) {
798 iconWidth = 48;
799 } else if (width < 96) {
800 iconWidth = 64;
801 } else if (width < 192) {
802 iconWidth = 128;
803 } else {
804 iconWidth = 256;
805 }
806
807 if (flags & KX11Extras::ClassHint) {
808 // Try to load the icon from the classhint if the app didn't specify
809 // its own:
810 if (result.isNull()) {
812 const QPixmap pm = icon.isNull() ? QPixmap() : icon.pixmap(iconWidth, iconWidth);
813 if (scale && !pm.isNull()) {
815 } else {
816 result = pm;
817 }
818 }
819 }
820
821 if (flags & KX11Extras::XApp) {
822 // If the icon is still a null pixmap, load the icon for X applications
823 // as a last resort:
824 if (result.isNull()) {
825 const QIcon icon = QIcon::fromTheme(QStringLiteral("xorg"));
826 const QPixmap pm = icon.isNull() ? QPixmap() : icon.pixmap(iconWidth, iconWidth);
827 if (scale && !pm.isNull()) {
829 } else {
830 result = pm;
831 }
832 }
833 }
834 return result;
835}
836
837QPixmap KX11Extras::icon(WId win, int width, int height, bool scale, int flags)
838{
839 CHECK_X11
840 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMIcon, NET::WM2WindowClass | NET::WM2IconPixmap);
841 return iconFromNetWinInfo(width, height, scale, flags, &info);
842}
843
844QPixmap KX11Extras::icon(WId win, int width, int height, bool scale, int flags, NETWinInfo *info)
845{
846 // No CHECK_X11 here, kwin_wayland calls this to get the icon for XWayland windows
847 width *= qGuiApp->devicePixelRatio();
848 height *= qGuiApp->devicePixelRatio();
849
850 if (info) {
851 return iconFromNetWinInfo(width, height, scale, flags, info);
852 }
853 CHECK_X11
854
855 NETWinInfo newInfo(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMIcon, NET::WM2WindowClass | NET::WM2IconPixmap);
856
857 return iconFromNetWinInfo(width, height, scale, flags, &newInfo);
858}
859
860// enum values for ICCCM 4.1.2.4 and 4.1.4, defined to not depend on xcb-icccm
861enum {
862 _ICCCM_WM_STATE_WITHDRAWN = 0,
863 _ICCCM_WM_STATE_NORMAL = 1,
864 _ICCCM_WM_STATE_ICONIC = 3,
865};
866
868{
869 CHECK_X11_VOID
870 create_atoms();
871 // as described in ICCCM 4.1.4
872 xcb_client_message_event_t ev;
873 memset(&ev, 0, sizeof(ev));
874 ev.response_type = XCB_CLIENT_MESSAGE;
875 ev.window = win;
876 ev.type = _wm_change_state;
877 ev.format = 32;
878 ev.data.data32[0] = _ICCCM_WM_STATE_ICONIC;
879 ev.data.data32[1] = 0;
880 ev.data.data32[2] = 0;
881 ev.data.data32[3] = 0;
882 ev.data.data32[4] = 0;
883 xcb_send_event(QX11Info::connection(),
884 false,
885 QX11Info::appRootWindow(),
886 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
887 reinterpret_cast<const char *>(&ev));
888}
889
891{
892 CHECK_X11_VOID
893 xcb_map_window(QX11Info::connection(), win);
894}
895
897{
898 CHECK_X11
899 KX11Extras::self()->init(INFO_BASIC);
900 int desk = (desktop > 0 && desktop <= (int)KX11Extras::self()->s_d_func()->numberOfDesktops()) ? desktop : currentDesktop();
901 if (desk <= 0) {
902 return displayGeometry() / qApp->devicePixelRatio();
903 }
904
905 NETRect r = KX11Extras::self()->s_d_func()->workArea(desk);
906 if (r.size.width <= 0 || r.size.height <= 0) { // not set
907 return displayGeometry() / qApp->devicePixelRatio();
908 }
909
910 return QRect(r.pos.x, r.pos.y, r.size.width, r.size.height) / qApp->devicePixelRatio();
911}
912
913QRect KX11Extras::workArea(const QList<WId> &exclude, int desktop)
914{
915 CHECK_X11
916 KX11Extras::self()->init(INFO_WINDOWS); // invalidates s_d_func's return value
917 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
918
919 QRect all = displayGeometry();
920 QRect a = all;
921
922 if (desktop == -1) {
923 desktop = s_d->currentDesktop();
924 }
925
927 for (it1 = s_d->windows.constBegin(); it1 != s_d->windows.constEnd(); ++it1) {
928 if (exclude.contains(*it1)) {
929 continue;
930 }
931
932 // Kicker (very) extensively calls this function, causing hundreds of roundtrips just
933 // to repeatedly find out struts of all windows. Therefore strut values for strut
934 // windows are cached here.
935 NETStrut strut;
936 auto it2 = s_d->strutWindows.begin();
937 for (; it2 != s_d->strutWindows.end(); ++it2) {
938 if ((*it2).window == *it1) {
939 break;
940 }
941 }
942
943 if (it2 != s_d->strutWindows.end()) {
944 if (!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops)) {
945 continue;
946 }
947
948 strut = (*it2).strut;
949 } else if (s_d->possibleStrutWindows.contains(*it1)) {
950 NETWinInfo info(QX11Info::connection(), (*it1), QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop, NET::Properties2());
951 strut = info.strut();
952 s_d->possibleStrutWindows.removeAll(*it1);
953 s_d->strutWindows.append(NETEventFilter::StrutData(*it1, info.strut(), info.desktop()));
954
955 if (!(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops)) {
956 continue;
957 }
958 } else {
959 continue; // not a strut window
960 }
961
962 QRect r = all;
963 if (strut.left > 0) {
964 r.setLeft(r.left() + (int)strut.left);
965 }
966 if (strut.top > 0) {
967 r.setTop(r.top() + (int)strut.top);
968 }
969 if (strut.right > 0) {
970 r.setRight(r.right() - (int)strut.right);
971 }
972 if (strut.bottom > 0) {
973 r.setBottom(r.bottom() - (int)strut.bottom);
974 }
975
976 a = a.intersected(r);
977 }
978 return a / qApp->devicePixelRatio();
979}
980
982{
983 CHECK_X11
984 KX11Extras::self()->init(INFO_BASIC);
985 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
986
987 bool isDesktopSane = (desktop > 0 && desktop <= (int)s_d->numberOfDesktops());
988 const char *name = s_d->desktopName(isDesktopSane ? desktop : currentDesktop());
989
990 if (name && name[0]) {
991 return QString::fromUtf8(name);
992 }
993
994 return KWindowSystem::tr("Desktop %1").arg(desktop);
995}
996
997void KX11Extras::setDesktopName(int desktop, const QString &name)
998{
999 CHECK_X11_VOID
1000 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
1001
1002 if (desktop <= 0 || desktop > (int)numberOfDesktops()) {
1003 desktop = currentDesktop();
1004 }
1005
1006 if (s_d) {
1007 s_d->setDesktopName(desktop, name.toUtf8().constData());
1008 return;
1009 }
1010
1011 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
1012 info.setDesktopName(desktop, name.toUtf8().constData());
1013}
1014
1015QString KX11Extras::readNameProperty(WId win, unsigned long atom)
1016{
1017 CHECK_X11
1018 XTextProperty tp;
1019 char **text = nullptr;
1020 int count;
1021 QString result;
1022 if (XGetTextProperty(QX11Info::display(), win, &tp, atom) != 0 && tp.value != nullptr) {
1023 create_atoms();
1024
1025 if (tp.encoding == kwm_utf8_string) {
1026 result = QString::fromUtf8((const char *)tp.value);
1027 } else if (XmbTextPropertyToTextList(QX11Info::display(), &tp, &text, &count) == Success && text != nullptr && count > 0) {
1028 result = QString::fromLocal8Bit(text[0]);
1029 } else if (tp.encoding == XA_STRING) {
1030 result = QString::fromLocal8Bit((const char *)tp.value);
1031 }
1032 if (text != nullptr) {
1033 XFreeStringList(text);
1034 }
1035 XFree(tp.value);
1036 }
1037 return result;
1038}
1039
1041{
1042 CHECK_X11
1043 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
1044 if (s_d) {
1045 return s_d->mapViewport();
1046 }
1047
1048 // Handle case of not having a QGuiApplication
1049 if (!QX11Info::connection()) {
1050 return false;
1051 }
1052
1053 // avoid creating KWindowSystemPrivate
1054 NETRootInfo infos(QX11Info::connection(), NET::Supported, NET::Properties2(), QX11Info::appScreen());
1055 if (!infos.isSupported(NET::DesktopViewport)) {
1056 return false;
1057 }
1058 NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops | NET::CurrentDesktop | NET::DesktopGeometry, NET::Properties2(), QX11Info::appScreen());
1059 if (info.numberOfDesktops(true) <= 1 && (info.desktopGeometry().width > displayWidth() || info.desktopGeometry().height > displayHeight())) {
1060 return true;
1061 }
1062 return false;
1063}
1064
1065int KX11Extras::viewportWindowToDesktop(const QRect &rect)
1066{
1067 CHECK_X11
1068 const QRect r = rect / qApp->devicePixelRatio();
1069
1070 KX11Extras::self()->init(INFO_BASIC);
1071 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
1072 QPoint p = r.center();
1073 // make absolute
1074 p = QPoint(p.x() + s_d->desktopViewport(s_d->currentDesktop(true)).x, p.y() + s_d->desktopViewport(s_d->currentDesktop(true)).y);
1075 NETSize s = s_d->desktopGeometry();
1076 QSize vs(displayWidth(), displayHeight());
1077 int xs = s.width / vs.width();
1078 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
1079 int ys = s.height / vs.height();
1080 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
1081 return y * xs + x + 1;
1082}
1083
1085 qreal left_width,
1086 qreal left_start,
1087 qreal left_end,
1088 qreal right_width,
1089 qreal right_start,
1090 qreal right_end,
1091 qreal top_width,
1092 qreal top_start,
1093 qreal top_end,
1094 qreal bottom_width,
1095 qreal bottom_start,
1096 qreal bottom_end)
1097{
1098 CHECK_X11_VOID
1099 const qreal dpr = qApp->devicePixelRatio();
1100
1101 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::Properties(), NET::Properties2());
1102 NETExtendedStrut strut;
1103 strut.left_width = std::lround(left_width * dpr);
1104 strut.right_width = std::lround(right_width * dpr);
1105 strut.top_width = std::lround(top_width * dpr);
1106 strut.bottom_width = std::lround(bottom_width * dpr);
1107 strut.left_start = std::lround(left_start * dpr);
1108 strut.left_end = std::lround(left_end * dpr);
1109 strut.right_start = std::lround(right_start * dpr);
1110 strut.right_end = std::lround(right_end * dpr);
1111 strut.top_start = std::lround(top_start * dpr);
1112 strut.top_end = std::lround(top_end * dpr);
1113 strut.bottom_start = std::lround(bottom_start * dpr);
1114 strut.bottom_end = std::lround(bottom_end * dpr);
1115 info.setExtendedStrut(strut);
1116 NETStrut oldstrut;
1117 oldstrut.left = std::lround(left_width * dpr);
1118 oldstrut.right = std::lround(right_width * dpr);
1119 oldstrut.top = std::lround(top_width * dpr);
1120 oldstrut.bottom = std::lround(bottom_width * dpr);
1121 info.setStrut(oldstrut);
1122}
1123
1124void KX11Extras::setStrut(WId win, qreal left, qreal right, qreal top, qreal bottom)
1125{
1126 CHECK_X11_VOID
1127 const qreal dpr = qApp->devicePixelRatio();
1128
1129 int w = displayWidth();
1130 int h = displayHeight();
1131 setExtendedStrut(win,
1132 std::lround(left * dpr),
1133 0,
1134 std::lround(left * dpr) != 0 ? w : 0,
1135 std::lround(right * dpr),
1136 0,
1137 std::lround(right * dpr) != 0 ? w : 0,
1138 std::lround(top * dpr),
1139 0,
1140 std::lround(top * dpr) != 0 ? h : 0,
1141 std::lround(bottom * dpr),
1142 0,
1143 std::lround(bottom * dpr) != 0 ? h : 0);
1144}
1145
1146// optimalization - create private only when needed and only for what is needed
1147void KX11Extras::connectNotify(const QMetaMethod &signal)
1148{
1149 CHECK_X11_VOID
1150 FilterInfo what = INFO_BASIC;
1152 what = INFO_WINDOWS;
1153 } else if (signal == QMetaMethod::fromSignal(&KX11Extras::strutChanged)) {
1154 what = INFO_WINDOWS;
1155 } else if (signal == QMetaMethod::fromSignal(&KX11Extras::windowChanged)) {
1156 what = INFO_WINDOWS;
1157 }
1158
1159 init(what);
1160 NETEventFilter *const s_d = s_d_func();
1161 if (!s_d->strutSignalConnected && signal == QMetaMethod::fromSignal(&KX11Extras::strutChanged)) {
1162 s_d->strutSignalConnected = true;
1163 }
1164 QObject::connectNotify(signal);
1165}
1166
1167void KX11Extras::setType(WId win, NET::WindowType windowType)
1168{
1169 CHECK_X11_VOID
1170 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::Properties(), NET::Properties2());
1171 info.setWindowType(windowType);
1172}
1173
1175{
1176 CHECK_X11_VOID
1177 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMState, NET::Properties2());
1178 info.setState(state, state);
1179}
1180
1182{
1183 CHECK_X11_VOID
1184 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMState, NET::Properties2());
1185 info.setState(NET::States(), state);
1186}
1187
1188int KX11Extras::viewportToDesktop(const QPoint &p)
1189{
1190 CHECK_X11
1191 KX11Extras::self()->init(INFO_BASIC);
1192 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
1193 NETSize s = s_d->desktopGeometry();
1194 QSize vs(displayWidth(), displayHeight());
1195 int xs = s.width / vs.width();
1196 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
1197 int ys = s.height / vs.height();
1198 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
1199 return y * xs + x + 1;
1200}
1201
1202QPoint KX11Extras::constrainViewportRelativePosition(const QPoint &pos)
1203{
1204 CHECK_X11
1205 init(INFO_BASIC);
1206 NETEventFilter *const s_d = s_d_func();
1207 NETSize s = s_d->desktopGeometry();
1208 NETPoint c = s_d->desktopViewport(s_d->currentDesktop(true));
1209 int x = (pos.x() + c.x) % s.width;
1210 int y = (pos.y() + c.y) % s.height;
1211 if (x < 0) {
1212 x += s.width;
1213 }
1214 if (y < 0) {
1215 y += s.height;
1216 }
1217 return QPoint(x - c.x, y - c.y);
1218}
1219
1220QPoint KX11Extras::desktopToViewport(int desktop, bool absolute)
1221{
1222 CHECK_X11
1223 init(INFO_BASIC);
1224 NETEventFilter *const s_d = s_d_func();
1225 NETSize s = s_d->desktopGeometry();
1226 QSize vs(displayWidth(), displayHeight());
1227 int xs = s.width / vs.width();
1228 int ys = s.height / vs.height();
1229 if (desktop <= 0 || desktop > xs * ys) {
1230 return QPoint(0, 0);
1231 }
1232 --desktop;
1233 QPoint ret(vs.width() * (desktop % xs), vs.height() * (desktop / xs));
1234 if (!absolute) {
1235 ret = QPoint(ret.x() - s_d->desktopViewport(s_d->currentDesktop(true)).x, ret.y() - s_d->desktopViewport(s_d->currentDesktop(true)).y);
1236 if (ret.x() >= s.width) {
1237 ret.setX(ret.x() - s.width);
1238 }
1239 if (ret.x() < 0) {
1240 ret.setX(ret.x() + s.width);
1241 }
1242 if (ret.y() >= s.height) {
1243 ret.setY(ret.y() - s.height);
1244 }
1245 if (ret.y() < 0) {
1246 ret.setY(ret.y() + s.height);
1247 }
1248 }
1249 return ret;
1250}
1251
1252bool KX11Extras::showingDesktop()
1253{
1254 KX11Extras::self()->init(INFO_BASIC);
1255 return KX11Extras::self()->s_d_func()->showingDesktop();
1256}
1257
1258void KX11Extras::setShowingDesktop(bool showing)
1259{
1260 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::WM2ShowingDesktop, QX11Info::appScreen());
1261 info.setShowingDesktop(showing);
1262}
1263
1264#include "kx11extras.moc"
1265#include "moc_kx11extras.cpp"
Convenience access to certain properties and features of window systems.
void showingDesktopChanged(bool showing)
The state of showing the desktop has changed.
static KWindowSystem * self()
Access to the singleton instance.
A collection of functions to obtain information from and manipulate X11 windows.
Definition kx11extras.h:29
static bool mapViewport()
Returns true if viewports are mapped to virtual desktops.
static void setDesktopName(int desktop, const QString &name)
Sets the name of the specified desktop.
static void setOnAllDesktops(WId win, bool b)
Sets window win to be present on all virtual desktops if is true.
static void setState(WId win, NET::States state)
Sets the state of window win to state.
static QString readNameProperty(WId window, unsigned long atom)
Function that reads and returns the contents of the given text property (WM_NAME, WM_ICON_NAME,...
static bool hasWId(WId id)
Test to see if id still managed at present.
static QPixmap icon(WId win, int width=-1, int height=-1, bool scale=false)
Returns an icon for window win.
bool compositingActive
Whether desktop compositing is active.
Definition kx11extras.h:35
static void forceActiveWindow(WId win, long time=0)
Sets window win to be the active window.
void windowChanged(WId id, NET::Properties properties, NET::Properties2 properties2)
The window changed.
static void setStrut(WId win, qreal left, qreal right, qreal top, qreal bottom)
Convenience function for setExtendedStrut() that automatically makes struts as wide/high as the scree...
void activeWindowChanged(WId id)
Hint that <Window> is active (= has focus) now.
void numberOfDesktopsChanged(int num)
The number of desktops changed.
static void minimizeWindow(WId win)
Minimizes the window with id win.
static QRect workArea(int desktop=-1)
Returns the workarea for the specified desktop, or the current work area if no desktop has been speci...
static int currentDesktop()
Returns the current virtual desktop.
static int numberOfDesktops()
Returns the number of virtual desktops.
static void setCurrentDesktop(int desktop)
Convenience function to set the current desktop to desktop.
static void unminimizeWindow(WId win)
Unminimizes the window with id win.
@ NETWM
read from property from the window manager specification
Definition kx11extras.h:218
@ WMHints
read from WMHints property
Definition kx11extras.h:219
@ ClassHint
load icon after getting name from the classhint
Definition kx11extras.h:220
@ XApp
load the standard X icon (last fallback)
Definition kx11extras.h:221
static void clearState(WId win, NET::States state)
Clears the state of window win from state.
static QList< WId > stackingOrder()
Returns the list of all toplevel windows currently managed by the window manager in the current stack...
static WId activeWindow()
Returns the currently active window, or 0 if no window is active.
static void setExtendedStrut(WId win, qreal left_width, qreal left_start, qreal left_end, qreal right_width, qreal right_start, qreal right_end, qreal top_width, qreal top_start, qreal top_end, qreal bottom_width, qreal bottom_start, qreal bottom_end)
Sets the strut of window win to left_width ranging from left_start to left_end on the left edge,...
void windowRemoved(WId id)
A window has been removed.
void strutChanged()
Something changed with the struts, may or may not have changed the work area.
static QList< WId > windows()
Returns the list of all toplevel windows currently managed by the window manager in the order of crea...
void desktopNamesChanged()
Desktops have been renamed.
static void activateWindow(WId win, long time=0)
Requests that window win is activated.
static void setOnActivities(WId win, const QStringList &activities)
Moves window win to activities activities.
void stackingOrderChanged()
Emitted when the stacking order of the window changed.
void windowAdded(WId id)
A window has been added.
void compositingChanged(bool enabled)
Compositing was enabled or disabled.
static QString desktopName(int desktop)
Returns the name of the specified desktop.
void workAreaChanged()
The workarea has changed.
void currentDesktopChanged(int desktop)
Switched to another virtual desktop.
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
static void setType(WId win, NET::WindowType windowType)
Sets the type of window win to windowType.
Common API for root window properties/protocols.
Definition netwm.h:41
void setDesktopViewport(int desktop, const NETPoint &viewport)
Sets the viewport for the current desktop to the specified point.
Definition netwm.cpp:745
int currentDesktop(bool ignore_viewport=false) const
Returns the current desktop.
Definition netwm.cpp:2490
xcb_window_t activeWindow() const
Returns the active (focused) window.
Definition netwm.cpp:2498
const xcb_window_t * clientListStacking() const
Returns an array of Window id's, which contain all managed windows in stacking order.
Definition netwm.cpp:2413
void setDesktopName(int desktop, const char *desktopName)
Sets the name of the specified desktop.
Definition netwm.cpp:681
void activate()
Window Managers must call this after creating the NETRootInfo object, and before using any other meth...
Definition netwm.cpp:582
int clientListStackingCount() const
Returns the number of managed windows in the clientListStacking array.
Definition netwm.cpp:2418
NETPoint desktopViewport(int desktop) const
Returns the viewport of the specified desktop.
Definition netwm.cpp:2428
NETSize desktopGeometry() const
Returns the desktop geometry size.
Definition netwm.cpp:2423
const char * desktopName(int desktop) const
Returns the name for the specified desktop.
Definition netwm.cpp:2448
void setCurrentDesktop(int desktop, bool ignore_viewport=false)
Sets the current desktop to the specified desktop.
Definition netwm.cpp:659
void event(xcb_generic_event_t *event, NET::Properties *properties, NET::Properties2 *properties2=nullptr)
This function takes the passed xcb_generic_event_t and returns the updated properties in the passed i...
Definition netwm.cpp:1666
void moveResizeWindowRequest(xcb_window_t window, int flags, int x, int y, int width, int height)
Clients (such as pagers/taskbars) that wish to move/resize a window using WM2MoveResizeWindow (_NET_M...
Definition netwm.cpp:1590
NETRect workArea(int desktop) const
Returns the workArea for the specified desktop.
Definition netwm.cpp:2438
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Definition netwm.cpp:2378
int numberOfDesktops(bool ignore_viewport=false) const
Returns the number of desktops.
Definition netwm.cpp:2482
bool showingDesktop() const
Returns the status of _NET_SHOWING_DESKTOP.
Definition netwm.cpp:1557
Common API for application window properties/protocols.
Definition netwm.h:967
xcb_connection_t * xcbConnection() const
Returns the xcb connection used.
Definition netwm.cpp:4880
int desktop(bool ignore_viewport=false) const
Returns the desktop where the window is residing.
Definition netwm.cpp:4699
void setStrut(NETStrut strut)
Definition netwm.cpp:2725
NETIcon icon(int width=-1, int height=-1) const
Returns an icon.
Definition netwm.cpp:3500
xcb_pixmap_t icccmIconPixmapMask() const
Returns the mask for the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4776
void setExtendedStrut(const NETExtendedStrut &extended_strut)
Set the extended (partial) strut for the application window.
Definition netwm.cpp:2700
NETStrut strut() const
Definition netwm.cpp:4612
xcb_pixmap_t icccmIconPixmap() const
Returns the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4771
void setDesktop(int desktop, bool ignore_viewport=false)
Set which window the desktop is (should be) on.
Definition netwm.cpp:3210
static const int OnAllDesktops
Sentinel value to indicate that the client wishes to be visible on all desktops.
Definition netwm.h:1659
const char * windowClassClass() const
Returns the class component of the window class for the window (i.e.
Definition netwm.cpp:4781
@ Sticky
indicates that the Window Manager SHOULD keep the window's position fixed on the screen,...
Definition netwm_def.h:515
WindowType
Window type.
Definition netwm_def.h:357
@ FromApplication
indicates that the request comes from a normal application
Definition netwm_def.h:849
@ FromTool
indicated that the request comes from pager or similar tool
Definition netwm_def.h:853
const char * constData() const const
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
QCoreApplication * instance()
QWindow * focusWindow()
void screenAdded(QScreen *screen)
void screenRemoved(QScreen *screen)
QList< QScreen * > screens()
QIcon fromTheme(const QString &name)
bool isNull() const const
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
void append(const T &value)
const T & at(int i) const const
QList::iterator begin()
void clear()
QList::const_iterator constBegin() const const
QList::const_iterator constEnd() const const
bool contains(const T &value) const const
int count(const T &value) const const
QList::iterator end()
QList::iterator erase(QList::iterator pos)
int removeAll(const T &value)
QMetaMethod fromSignal(PointerToMemberFunction signal)
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
Q_EMITQ_EMIT
Q_INVOKABLEQ_INVOKABLE
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual void connectNotify(const QMetaMethod &signal)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QThread * thread() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
int height() const const
bool isNull() const const
QImage toImage() const const
int width() const const
int x() const const
int y() const const
int bottom() const const
int height() const const
QRect intersected(const QRect &rectangle) const const
int left() const const
int right() const const
void setBottom(int y)
void setLeft(int x)
void setRight(int x)
void setTop(int y)
QSize size() const const
int top() const const
QPoint topLeft() const const
int width() const const
QRect boundingRect() const const
void geometryChanged(const QRect &geometry)
bool isNull() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLocal8Bit(const char *str, int size)
QString fromUtf8(const char *str, int size)
QString toLower() const const
QByteArray toUtf8() const const
QString join(const QString &separator) const const
IgnoreAspectRatio
BlockingQueuedConnection
SmoothTransformation
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
WId winId() const const
Partial strut class for NET classes.
Definition netwm_def.h:180
int bottom_width
Bottom border of the strut, width and range.
Definition netwm_def.h:218
int left_width
Left border of the strut, width and range.
Definition netwm_def.h:203
int right_width
Right border of the strut, width and range.
Definition netwm_def.h:208
int top_width
Top border of the strut, width and range.
Definition netwm_def.h:213
Simple icon class for NET classes.
Definition netwm_def.h:147
NETSize size
Size of the icon.
Definition netwm_def.h:161
unsigned char * data
Image data for the icon.
Definition netwm_def.h:168
Simple point class for NET classes.
Definition netwm_def.h:27
int x
x coordinate.
Definition netwm_def.h:51
int y
y coordinate
Definition netwm_def.h:52
Simple rectangle class for NET classes.
Definition netwm_def.h:105
NETPoint pos
Position of the rectangle.
Definition netwm_def.h:126
NETSize size
Size of the rectangle.
Definition netwm_def.h:133
Simple size class for NET classes.
Definition netwm_def.h:68
int height
Height.
Definition netwm_def.h:92
int width
Width.
Definition netwm_def.h:91
int bottom
Bottom border of the strut.
Definition netwm_def.h:262
int left
Left border of the strut.
Definition netwm_def.h:247
int right
Right border of the strut.
Definition netwm_def.h:252
int top
Top border of the strut.
Definition netwm_def.h:257
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:40:55 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.