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#include "kxcbevent_p.h"
23
24#include <QAbstractNativeEventFilter>
25#include <QGuiApplication>
26#include <QMetaMethod>
27#include <QRect>
28#include <QScreen>
29#include <private/qtx11extras_p.h>
30
31#include <X11/Xatom.h>
32#include <X11/Xutil.h>
33#include <X11/extensions/Xfixes.h>
34#include <xcb/xcb.h>
35#include <xcb/xfixes.h>
36
37// QPoint and QSize all have handy / operators which are useful for scaling, positions and sizes for high DPI support
38// QRect does not, so we create one for internal purposes within this class
39inline QRect operator/(const QRect &rectangle, qreal factor)
40{
41 return QRect(rectangle.topLeft() / factor, rectangle.size() / factor);
42}
43
44class MainThreadInstantiator : public QObject
45{
47
48public:
49 MainThreadInstantiator(KX11Extras::FilterInfo _what);
50 Q_INVOKABLE NETEventFilter *createNETEventFilter();
51
52private:
53 KX11Extras::FilterInfo m_what;
54};
55
56class NETEventFilter : public NETRootInfo, public QAbstractNativeEventFilter
57{
58public:
59 NETEventFilter(KX11Extras::FilterInfo _what);
60 ~NETEventFilter() override;
61 void activate();
62 QList<WId> windows;
63 QList<WId> stackingOrder;
64
65 struct StrutData {
66 StrutData(WId window_, const NETStrut &strut_, int desktop_)
67 : window(window_)
68 , strut(strut_)
69 , desktop(desktop_)
70 {
71 }
72 WId window;
73 NETStrut strut;
74 int desktop;
75 };
76 QList<StrutData> strutWindows;
77 QList<WId> possibleStrutWindows;
78 bool strutSignalConnected;
79 bool compositingEnabled;
80 bool haveXfixes;
81 KX11Extras::FilterInfo what;
82 int xfixesEventBase;
83 bool mapViewport();
84
85 bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override;
86
87 void updateStackingOrder();
88 bool removeStrutWindow(WId);
89
90protected:
91 void addClient(xcb_window_t) override;
92 void removeClient(xcb_window_t) override;
93
94private:
95 bool nativeEventFilter(xcb_generic_event_t *event);
96 xcb_window_t winId;
97 xcb_window_t m_appRootWindow;
98};
99
100static Atom net_wm_cm;
101static void create_atoms();
102
103static inline const QRect &displayGeometry()
104{
105 static QRect displayGeometry;
106 static bool isDirty = true;
107
108 if (isDirty) {
109 static QList<QMetaObject::Connection> connections;
110 auto dirtify = [&] {
111 isDirty = true;
112 for (const QMetaObject::Connection &con : std::as_const(connections)) {
114 }
115 connections.clear();
116 };
117
120 const QList<QScreen *> screenList = QGuiApplication::screens();
121 QRegion region;
122 for (int i = 0; i < screenList.count(); ++i) {
123 const QScreen *screen = screenList.at(i);
124 connections << QObject::connect(screen, &QScreen::geometryChanged, dirtify);
125 const QRect geometry = screen->geometry();
126 const qreal dpr = screen->devicePixelRatio();
127 region += QRect(geometry.topLeft(), geometry.size() * dpr);
128 }
129 displayGeometry = region.boundingRect();
130 isDirty = false;
131 }
132
133 return displayGeometry;
134}
135
136static inline int displayWidth()
137{
138 return displayGeometry().width();
139}
140
141static inline int displayHeight()
142{
143 return displayGeometry().height();
144}
145
146// clang-format off
147static const NET::Properties windowsProperties = NET::ClientList | NET::ClientListStacking |
148 NET::Supported |
149 NET::NumberOfDesktops |
150 NET::DesktopGeometry |
151 NET::DesktopViewport |
152 NET::CurrentDesktop |
153 NET::DesktopNames |
154 NET::ActiveWindow |
155 NET::WorkArea;
156static const NET::Properties2 windowsProperties2 = NET::WM2ShowingDesktop;
157
158// ClientList and ClientListStacking is not per-window information, but a desktop information,
159// so track it even with only INFO_BASIC
160static const NET::Properties desktopProperties = NET::ClientList | NET::ClientListStacking |
161 NET::Supported |
162 NET::NumberOfDesktops |
163 NET::DesktopGeometry |
164 NET::DesktopViewport |
165 NET::CurrentDesktop |
166 NET::DesktopNames |
167 NET::ActiveWindow |
168 NET::WorkArea;
169static const NET::Properties2 desktopProperties2 = NET::WM2ShowingDesktop;
170// clang-format on
171
172MainThreadInstantiator::MainThreadInstantiator(KX11Extras::FilterInfo _what)
173 : QObject()
174 , m_what(_what)
175{
176}
177
178NETEventFilter *MainThreadInstantiator::createNETEventFilter()
179{
180 return new NETEventFilter(m_what);
181}
182
183NETEventFilter::NETEventFilter(KX11Extras::FilterInfo _what)
184 : NETRootInfo(QX11Info::connection(),
185 _what >= KX11Extras::INFO_WINDOWS ? windowsProperties : desktopProperties,
186 _what >= KX11Extras::INFO_WINDOWS ? windowsProperties2 : desktopProperties2,
187 QX11Info::appScreen(),
188 false)
190 , strutSignalConnected(false)
191 , compositingEnabled(false)
192 , haveXfixes(false)
193 , what(_what)
194 , winId(XCB_WINDOW_NONE)
195 , m_appRootWindow(QX11Info::appRootWindow())
196{
198
199 int errorBase;
200 if ((haveXfixes = XFixesQueryExtension(QX11Info::display(), &xfixesEventBase, &errorBase))) {
201 create_atoms();
202 winId = xcb_generate_id(QX11Info::connection());
203 uint32_t values[] = {true, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
204 xcb_create_window(QX11Info::connection(),
205 XCB_COPY_FROM_PARENT,
206 winId,
207 m_appRootWindow,
208 0,
209 0,
210 1,
211 1,
212 0,
213 XCB_WINDOW_CLASS_INPUT_ONLY,
214 XCB_COPY_FROM_PARENT,
215 XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
216 values);
217 XFixesSelectSelectionInput(QX11Info::display(),
218 winId,
219 net_wm_cm,
220 XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask);
221 compositingEnabled = XGetSelectionOwner(QX11Info::display(), net_wm_cm) != None;
222 }
223}
224
225NETEventFilter::~NETEventFilter()
226{
227 if (QX11Info::connection() && winId != XCB_WINDOW_NONE) {
228 xcb_destroy_window(QX11Info::connection(), winId);
229 winId = XCB_WINDOW_NONE;
230 }
231}
232
233// not virtual, but it's called directly only from init()
234void NETEventFilter::activate()
235{
237 updateStackingOrder();
238}
239
240bool NETEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *)
241{
242 if (eventType != "xcb_generic_event_t") {
243 // only interested in XCB events of course
244 return false;
245 }
246 return nativeEventFilter(reinterpret_cast<xcb_generic_event_t *>(message));
247}
248
249bool NETEventFilter::nativeEventFilter(xcb_generic_event_t *ev)
250{
252 const uint8_t eventType = ev->response_type & ~0x80;
253
254 if (eventType == xfixesEventBase + XCB_XFIXES_SELECTION_NOTIFY) {
255 xcb_xfixes_selection_notify_event_t *event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(ev);
256 if (event->window == winId) {
257 bool haveOwner = event->owner != XCB_WINDOW_NONE;
258 if (compositingEnabled != haveOwner) {
259 compositingEnabled = haveOwner;
260 Q_EMIT KX11Extras::self()->compositingChanged(compositingEnabled);
261 }
262 return true;
263 }
264 // Qt compresses XFixesSelectionNotifyEvents without caring about the actual window
265 // gui/kernel/qapplication_x11.cpp
266 // until that can be assumed fixed, we also react on events on the root (caused by Qts own compositing tracker)
267 if (event->window == m_appRootWindow) {
268 if (event->selection == net_wm_cm) {
269 bool haveOwner = event->owner != XCB_WINDOW_NONE;
270 if (compositingEnabled != haveOwner) {
271 compositingEnabled = haveOwner;
272 Q_EMIT KX11Extras::self()->compositingChanged(compositingEnabled);
273 }
274 // NOTICE this is not our event, we just randomly captured it from Qt -> pass on
275 return false;
276 }
277 }
278 return false;
279 }
280
281 xcb_window_t eventWindow = XCB_WINDOW_NONE;
282 switch (eventType) {
283 case XCB_CLIENT_MESSAGE:
284 eventWindow = reinterpret_cast<xcb_client_message_event_t *>(ev)->window;
285 break;
286 case XCB_PROPERTY_NOTIFY:
287 eventWindow = reinterpret_cast<xcb_property_notify_event_t *>(ev)->window;
288 break;
289 case XCB_CONFIGURE_NOTIFY:
290 eventWindow = reinterpret_cast<xcb_configure_notify_event_t *>(ev)->window;
291 break;
292 }
293
294 if (eventWindow == m_appRootWindow) {
295 int old_current_desktop = currentDesktop();
296 xcb_window_t old_active_window = activeWindow();
297 int old_number_of_desktops = numberOfDesktops();
298 bool old_showing_desktop = showingDesktop();
299 NET::Properties props;
300 NET::Properties2 props2;
301 NETRootInfo::event(ev, &props, &props2);
302
303 if ((props & CurrentDesktop) && currentDesktop() != old_current_desktop) {
304 Q_EMIT KX11Extras::self()->currentDesktopChanged(currentDesktop());
305 }
306 if ((props & DesktopViewport) && mapViewport() && currentDesktop() != old_current_desktop) {
307 Q_EMIT KX11Extras::self()->currentDesktopChanged(currentDesktop());
308 }
309 if ((props & ActiveWindow) && activeWindow() != old_active_window) {
310 Q_EMIT KX11Extras::self()->activeWindowChanged(activeWindow());
311 }
312 if (props & DesktopNames) {
313 Q_EMIT KX11Extras::self()->desktopNamesChanged();
314 }
315 if ((props & NumberOfDesktops) && numberOfDesktops() != old_number_of_desktops) {
316 Q_EMIT KX11Extras::self()->numberOfDesktopsChanged(numberOfDesktops());
317 }
318 if ((props & DesktopGeometry) && mapViewport() && numberOfDesktops() != old_number_of_desktops) {
319 Q_EMIT KX11Extras::self()->numberOfDesktopsChanged(numberOfDesktops());
320 }
321 if (props & WorkArea) {
322 Q_EMIT KX11Extras::self()->workAreaChanged();
323 }
324 if (props & ClientListStacking) {
325 updateStackingOrder();
326 Q_EMIT KX11Extras::self()->stackingOrderChanged();
327 }
328 if ((props2 & WM2ShowingDesktop) && showingDesktop() != old_showing_desktop) {
330 }
331 } else if (windows.contains(eventWindow)) {
332 NETWinInfo ni(QX11Info::connection(), eventWindow, m_appRootWindow, NET::Properties(), NET::Properties2());
333 NET::Properties dirtyProperties;
334 NET::Properties2 dirtyProperties2;
335 ni.event(ev, &dirtyProperties, &dirtyProperties2);
336 if (eventType == XCB_PROPERTY_NOTIFY) {
337 xcb_property_notify_event_t *event = reinterpret_cast<xcb_property_notify_event_t *>(ev);
338 if (event->atom == XCB_ATOM_WM_HINTS) {
339 dirtyProperties |= NET::WMIcon; // support for old icons
340 } else if (event->atom == XCB_ATOM_WM_NAME) {
341 dirtyProperties |= NET::WMName; // support for old name
342 } else if (event->atom == XCB_ATOM_WM_ICON_NAME) {
343 dirtyProperties |= NET::WMIconName; // support for old iconic name
344 }
345 }
346 if (mapViewport() && (dirtyProperties & (NET::WMState | NET::WMGeometry))) {
347 /* geometry change -> possible viewport change
348 * state change -> possible NET::Sticky change
349 */
350 dirtyProperties |= NET::WMDesktop;
351 }
352 if ((dirtyProperties & NET::WMStrut) != 0) {
353 removeStrutWindow(eventWindow);
354 if (!possibleStrutWindows.contains(eventWindow)) {
355 possibleStrutWindows.append(eventWindow);
356 }
357 }
358 if (dirtyProperties || dirtyProperties2) {
359 Q_EMIT KX11Extras::self()->windowChanged(eventWindow, dirtyProperties, dirtyProperties2);
360
361 if ((dirtyProperties & NET::WMStrut) != 0) {
362 Q_EMIT KX11Extras::self()->strutChanged();
363 }
364 }
365 }
366
367 return false;
368}
369
370bool NETEventFilter::removeStrutWindow(WId w)
371{
372 for (QList<StrutData>::Iterator it = strutWindows.begin(); it != strutWindows.end(); ++it) {
373 if ((*it).window == w) {
374 strutWindows.erase(it);
375 return true;
376 }
377 }
378 return false;
379}
380
381void NETEventFilter::updateStackingOrder()
382{
383 stackingOrder.clear();
384 for (int i = 0; i < clientListStackingCount(); i++) {
385 stackingOrder.append(clientListStacking()[i]);
386 }
387}
388
389void NETEventFilter::addClient(xcb_window_t w)
390{
391 if ((what >= KX11Extras::INFO_WINDOWS)) {
392 xcb_connection_t *c = QX11Info::connection();
393 UniqueCPointer<xcb_get_window_attributes_reply_t> attr(xcb_get_window_attributes_reply(c, xcb_get_window_attributes_unchecked(c, w), nullptr));
394
395 uint32_t events = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
396 if (attr) {
397 events = events | attr->your_event_mask;
398 }
399 xcb_change_window_attributes(c, w, XCB_CW_EVENT_MASK, &events);
400 }
401
402 bool emit_strutChanged = false;
403
404 if (strutSignalConnected) {
405 NETWinInfo info(QX11Info::connection(), w, QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop, NET::Properties2());
406 NETStrut strut = info.strut();
407 if (strut.left || strut.top || strut.right || strut.bottom) {
408 strutWindows.append(StrutData(w, strut, info.desktop()));
409 emit_strutChanged = true;
410 }
411 } else {
412 possibleStrutWindows.append(w);
413 }
414
415 windows.append(w);
416 Q_EMIT KX11Extras::self()->windowAdded(w);
417 if (emit_strutChanged) {
418 Q_EMIT KX11Extras::self()->strutChanged();
419 }
420}
421
422void NETEventFilter::removeClient(xcb_window_t w)
423{
424 bool emit_strutChanged = removeStrutWindow(w);
425 if (strutSignalConnected && possibleStrutWindows.contains(w)) {
426 NETWinInfo info(QX11Info::connection(), w, QX11Info::appRootWindow(), NET::WMStrut, NET::Properties2());
427 NETStrut strut = info.strut();
428 if (strut.left || strut.top || strut.right || strut.bottom) {
429 emit_strutChanged = true;
430 }
431 }
432
433 possibleStrutWindows.removeAll(w);
434 windows.removeAll(w);
435 Q_EMIT KX11Extras::self()->windowRemoved(w);
436 if (emit_strutChanged) {
437 Q_EMIT KX11Extras::self()->strutChanged();
438 }
439}
440
441bool NETEventFilter::mapViewport()
442{
443 // compiz claims support even though it doesn't use virtual desktops :(
444 // if( isSupported( NET::DesktopViewport ) && !isSupported( NET::NumberOfDesktops ))
445
446 // this test is duplicated in KWindowSystem::mapViewport()
447 if (isSupported(NET::DesktopViewport) && numberOfDesktops(true) <= 1
448 && (desktopGeometry().width > displayWidth() || desktopGeometry().height > displayHeight())) {
449 return true;
450 }
451 return false;
452}
453
454static bool atoms_created = false;
455
456static Atom _wm_protocols;
457static Atom _wm_change_state;
458static Atom kwm_utf8_string;
459
460static void create_atoms()
461{
462 if (!atoms_created) {
463 const int max = 20;
464 Atom *atoms[max];
465 const char *names[max];
466 Atom atoms_return[max];
467 int n = 0;
468
469 atoms[n] = &_wm_protocols;
470 names[n++] = "WM_PROTOCOLS";
471
472 atoms[n] = &_wm_change_state;
473 names[n++] = "WM_CHANGE_STATE";
474
475 atoms[n] = &kwm_utf8_string;
476 names[n++] = "UTF8_STRING";
477
478 char net_wm_cm_name[100];
479 sprintf(net_wm_cm_name, "_NET_WM_CM_S%d", QX11Info::appScreen());
480 atoms[n] = &net_wm_cm;
481 names[n++] = net_wm_cm_name;
482
483 // we need a const_cast for the shitty X API
484 XInternAtoms(QX11Info::display(), const_cast<char **>(names), n, false, atoms_return);
485 for (int i = 0; i < n; i++) {
486 *atoms[i] = atoms_return[i];
487 }
488
489 atoms_created = True;
490 }
491}
492
493#define CHECK_X11 \
494 if (!KWindowSystem::isPlatformX11()) { \
495 qCWarning(LOG_KWINDOWSYSTEM) << Q_FUNC_INFO << "may only be used on X11"; \
496 return {}; \
497 }
498
499#define CHECK_X11_VOID \
500 if (!KWindowSystem::isPlatformX11()) { \
501 qCWarning(LOG_KWINDOWSYSTEM) << Q_FUNC_INFO << "may only be used on X11"; \
502 return; \
503 }
504
505// WARNING
506// you have to call s_d_func() again after calling this function if you want a valid pointer!
507void KX11Extras::init(FilterInfo what)
508{
509 NETEventFilter *const s_d = s_d_func();
510
511 if (what >= INFO_WINDOWS) {
512 what = INFO_WINDOWS;
513 } else {
514 what = INFO_BASIC;
515 }
516
517 if (!s_d || s_d->what < what) {
518 const bool wasCompositing = s_d ? s_d->compositingEnabled : false;
519 MainThreadInstantiator instantiator(what);
520 NETEventFilter *filter;
521 if (instantiator.thread() == QCoreApplication::instance()->thread()) {
522 filter = instantiator.createNETEventFilter();
523 } else {
524 // the instantiator is not in the main app thread, which implies
525 // we are being called in a thread that is not the main app thread
526 // so we move the instantiator to the main app thread and invoke
527 // the method with a blocking call
528 instantiator.moveToThread(QCoreApplication::instance()->thread());
529 QMetaObject::invokeMethod(&instantiator, "createNETEventFilter", Qt::BlockingQueuedConnection, Q_RETURN_ARG(NETEventFilter *, filter));
530 }
531 d.reset(filter);
532 d->activate();
533 if (wasCompositing != s_d_func()->compositingEnabled) {
534 Q_EMIT KX11Extras::self()->compositingChanged(s_d_func()->compositingEnabled);
535 }
536 }
537}
538
539KX11Extras *KX11Extras::self()
540{
541 static KX11Extras instance;
542 return &instance;
543}
544
546{
547 CHECK_X11
548 KX11Extras::self()->init(INFO_BASIC);
549 return KX11Extras::self()->s_d_func()->windows;
550}
551
553{
554 CHECK_X11
555 return windows().contains(w);
556}
557
559{
560 CHECK_X11
561 KX11Extras::self()->init(INFO_BASIC);
562 return KX11Extras::self()->s_d_func()->stackingOrder;
563}
564
566{
567 CHECK_X11
568 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
569 if (s_d) {
570 return s_d->activeWindow();
571 }
572 NETRootInfo info(QX11Info::connection(), NET::ActiveWindow, NET::Properties2(), QX11Info::appScreen());
573 return info.activeWindow();
574}
575
576void KX11Extras::activateWindow(WId win, long time)
577{
578 CHECK_X11_VOID
579 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
580 if (time == 0) {
581 time = QX11Info::appUserTime();
582 }
583 info.setActiveWindow(win, NET::FromApplication, time, QGuiApplication::focusWindow() ? QGuiApplication::focusWindow()->winId() : 0);
584}
585
586void KX11Extras::forceActiveWindow(WId win, long time)
587{
588 CHECK_X11_VOID
589 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
590 if (time == 0) {
591 time = QX11Info::appTime();
592 }
593 info.setActiveWindow(win, NET::FromTool, time, 0);
594}
595
597{
598 CHECK_X11_VOID
599 forceActiveWindow(win->winId(), time);
600}
601
603{
604 CHECK_X11
605 KX11Extras::self()->init(INFO_BASIC);
606 if (KX11Extras::self()->s_d_func()->haveXfixes) {
607 return KX11Extras::self()->s_d_func()->compositingEnabled;
608 } else {
609 create_atoms();
610 return XGetSelectionOwner(QX11Info::display(), net_wm_cm);
611 }
612}
613
615{
616 CHECK_X11
617 if (!QX11Info::connection()) {
618 return 1;
619 }
620
621 if (mapViewport()) {
622 KX11Extras::self()->init(INFO_BASIC);
623 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
624 NETPoint p = s_d->desktopViewport(s_d->currentDesktop(true));
625 return KX11Extras::self()->viewportToDesktop(QPoint(p.x, p.y) / qApp->devicePixelRatio());
626 }
627
628 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
629 if (s_d) {
630 return s_d->currentDesktop(true);
631 }
632 NETRootInfo info(QX11Info::connection(), NET::CurrentDesktop, NET::Properties2(), QX11Info::appScreen());
633 return info.currentDesktop(true);
634}
635
637{
638 CHECK_X11
639 if (!QX11Info::connection()) {
640 return 1;
641 }
642
643 if (mapViewport()) {
644 KX11Extras::self()->init(INFO_BASIC);
645 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
646 NETSize s = s_d->desktopGeometry();
647 return s.width / displayWidth() * s.height / displayHeight();
648 }
649
650 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
651 if (s_d) {
652 return s_d->numberOfDesktops(true);
653 }
654 NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops, NET::Properties2(), QX11Info::appScreen());
655 return info.numberOfDesktops(true);
656}
657
659{
660 CHECK_X11_VOID
661 if (mapViewport()) {
662 KX11Extras::self()->init(INFO_BASIC);
663 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
664 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
665 QPoint pos = KX11Extras::self()->desktopToViewport(desktop, true);
666 NETPoint p;
667 p.x = pos.x();
668 p.y = pos.y();
669 info.setDesktopViewport(s_d->currentDesktop(true), p);
670 return;
671 }
672 NETRootInfo info(QX11Info::connection(), NET::Properties(), NET::Properties2(), QX11Info::appScreen());
673 info.setCurrentDesktop(desktop, true);
674}
675
676void KX11Extras::setOnAllDesktops(WId win, bool b)
677{
678 CHECK_X11_VOID
679 if (mapViewport()) {
680 if (b) {
681 setState(win, NET::Sticky);
682 } else {
684 }
685 return;
686 }
687 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMDesktop, NET::Properties2());
688 if (b) {
690 } else if (info.desktop(true) == NETWinInfo::OnAllDesktops) {
691 NETRootInfo rinfo(QX11Info::connection(), NET::CurrentDesktop, NET::Properties2(), QX11Info::appScreen());
692 info.setDesktop(rinfo.currentDesktop(true), true);
693 }
694}
695
696void KX11Extras::setOnDesktop(WId win, int desktop)
697{
698 CHECK_X11_VOID
699 if (mapViewport()) {
700 if (desktop == NET::OnAllDesktops) {
701 return setOnAllDesktops(win, true);
702 } else {
704 }
705 KX11Extras::self()->init(INFO_BASIC);
706 QPoint p = KX11Extras::self()->desktopToViewport(desktop, false);
707 Window dummy;
708 int x;
709 int y;
710 unsigned int w;
711 unsigned int h;
712 unsigned int b;
713 unsigned int dp;
714 XGetGeometry(QX11Info::display(), win, &dummy, &x, &y, &w, &h, &b, &dp);
715 // get global position
716 XTranslateCoordinates(QX11Info::display(), win, QX11Info::appRootWindow(), 0, 0, &x, &y, &dummy);
717 x += w / 2; // center
718 y += h / 2;
719 // transform to coordinates on the current "desktop"
720 x = x % displayWidth();
721 y = y % displayHeight();
722 if (x < 0) {
723 x = x + displayWidth();
724 }
725 if (y < 0) {
726 y = y + displayHeight();
727 }
728 x += p.x(); // move to given "desktop"
729 y += p.y();
730 x -= w / 2; // from center back to topleft
731 y -= h / 2;
732 p = KX11Extras::self()->constrainViewportRelativePosition(QPoint(x, y));
733 int flags = (NET::FromTool << 12) | (0x03 << 8) | 10; // from tool(?), x/y, static gravity
734 NETEventFilter *const s_d = KX11Extras::self()->s_d_func();
735 s_d->moveResizeWindowRequest(win, flags, p.x(), p.y(), w, h);
736 return;
737 }
738 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMDesktop, NET::Properties2());
739 info.setDesktop(desktop, true);
740}
741
742void KX11Extras::setOnActivities(WId win, const QStringList &activities)
743{
744 CHECK_X11_VOID
745 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::Properties(), NET::WM2Activities);
746 info.setActivities(activities.join(QLatin1Char(',')).toLatin1().constData());
747}
748
749QPixmap KX11Extras::icon(WId win, int width, int height, bool scale)
750{
751 CHECK_X11
752 return icon(win, width, height, scale, NETWM | WMHints | ClassHint | XApp);
753}
754
755QPixmap iconFromNetWinInfo(int width, int height, bool scale, int flags, NETWinInfo *info)
756{
757 QPixmap result;
758 if (!info) {
759 return result;
760 }
761 if (flags & KX11Extras::NETWM) {
762 NETIcon ni = info->icon(width, height);
763 if (ni.data && ni.size.width > 0 && ni.size.height > 0) {
764 QImage img((uchar *)ni.data, (int)ni.size.width, (int)ni.size.height, QImage::Format_ARGB32);
765 if (scale && width > 0 && height > 0 && img.size() != QSize(width, height) && !img.isNull()) {
766 img = img.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
767 }
768 if (!img.isNull()) {
769 result = QPixmap::fromImage(img);
770 }
771 return result;
772 }
773 }
774
775 if (flags & KX11Extras::WMHints) {
776 xcb_pixmap_t p = info->icccmIconPixmap();
777 xcb_pixmap_t p_mask = info->icccmIconPixmapMask();
778
779 if (p != XCB_PIXMAP_NONE) {
780 QPixmap pm = KXUtils::createPixmapFromHandle(info->xcbConnection(), p, p_mask);
781 if (scale && width > 0 && height > 0 && !pm.isNull() //
782 && (pm.width() != width || pm.height() != height)) {
784 } else {
785 result = pm;
786 }
787 }
788 }
789
790 // Since width can be any arbitrary size, but the icons cannot,
791 // take the nearest value for best results (ignoring 22 pixel
792 // icons as they don't exist for apps):
793 int iconWidth;
794 if (width < 24) {
795 iconWidth = 16;
796 } else if (width < 40) {
797 iconWidth = 32;
798 } else if (width < 56) {
799 iconWidth = 48;
800 } else if (width < 96) {
801 iconWidth = 64;
802 } else if (width < 192) {
803 iconWidth = 128;
804 } else {
805 iconWidth = 256;
806 }
807
808 if (flags & KX11Extras::ClassHint) {
809 // Try to load the icon from the classhint if the app didn't specify
810 // its own:
811 if (result.isNull()) {
813 const QPixmap pm = icon.isNull() ? QPixmap() : icon.pixmap(iconWidth, iconWidth);
814 if (scale && !pm.isNull()) {
815 result = QPixmap::fromImage(pm.toImage().scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
816 } else {
817 result = pm;
818 }
819 }
820 }
821
822 if (flags & KX11Extras::XApp) {
823 // If the icon is still a null pixmap, load the icon for X applications
824 // as a last resort:
825 if (result.isNull()) {
826 const QIcon icon = QIcon::fromTheme(QStringLiteral("xorg"));
827 const QPixmap pm = icon.isNull() ? QPixmap() : icon.pixmap(iconWidth, iconWidth);
828 if (scale && !pm.isNull()) {
829 result = QPixmap::fromImage(pm.toImage().scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
830 } else {
831 result = pm;
832 }
833 }
834 }
835 return result;
836}
837
838QPixmap KX11Extras::icon(WId win, int width, int height, bool scale, int flags)
839{
840 CHECK_X11
841 NETWinInfo info(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMIcon, NET::WM2WindowClass | NET::WM2IconPixmap);
842 return iconFromNetWinInfo(width, height, scale, flags, &info);
843}
844
845QPixmap KX11Extras::icon(WId win, int width, int height, bool scale, int flags, NETWinInfo *info)
846{
847 // No CHECK_X11 here, kwin_wayland calls this to get the icon for XWayland windows
848 width *= qGuiApp->devicePixelRatio();
849 height *= qGuiApp->devicePixelRatio();
850
851 if (info) {
852 return iconFromNetWinInfo(width, height, scale, flags, info);
853 }
854 CHECK_X11
855
856 NETWinInfo newInfo(QX11Info::connection(), win, QX11Info::appRootWindow(), NET::WMIcon, NET::WM2WindowClass | NET::WM2IconPixmap);
857
858 return iconFromNetWinInfo(width, height, scale, flags, &newInfo);
859}
860
861// enum values for ICCCM 4.1.2.4 and 4.1.4, defined to not depend on xcb-icccm
862enum {
863 _ICCCM_WM_STATE_WITHDRAWN = 0,
864 _ICCCM_WM_STATE_NORMAL = 1,
865 _ICCCM_WM_STATE_ICONIC = 3,
866};
867
869{
870 CHECK_X11_VOID
871 create_atoms();
872 // as described in ICCCM 4.1.4
873 KXcbEvent<xcb_client_message_event_t> 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 ev.buffer());
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:753
int currentDesktop(bool ignore_viewport=false) const
Returns the current desktop.
Definition netwm.cpp:2498
xcb_window_t activeWindow() const
Returns the active (focused) window.
Definition netwm.cpp:2506
const xcb_window_t * clientListStacking() const
Returns an array of Window id's, which contain all managed windows in stacking order.
Definition netwm.cpp:2421
void setDesktopName(int desktop, const char *desktopName)
Sets the name of the specified desktop.
Definition netwm.cpp:689
void activate()
Window Managers must call this after creating the NETRootInfo object, and before using any other meth...
Definition netwm.cpp:590
int clientListStackingCount() const
Returns the number of managed windows in the clientListStacking array.
Definition netwm.cpp:2426
NETPoint desktopViewport(int desktop) const
Returns the viewport of the specified desktop.
Definition netwm.cpp:2436
NETSize desktopGeometry() const
Returns the desktop geometry size.
Definition netwm.cpp:2431
const char * desktopName(int desktop) const
Returns the name for the specified desktop.
Definition netwm.cpp:2456
void setCurrentDesktop(int desktop, bool ignore_viewport=false)
Sets the current desktop to the specified desktop.
Definition netwm.cpp:667
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:1674
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:1598
NETRect workArea(int desktop) const
Returns the workArea for the specified desktop.
Definition netwm.cpp:2446
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Definition netwm.cpp:2386
int numberOfDesktops(bool ignore_viewport=false) const
Returns the number of desktops.
Definition netwm.cpp:2490
bool showingDesktop() const
Returns the status of _NET_SHOWING_DESKTOP.
Definition netwm.cpp:1565
Common API for application window properties/protocols.
Definition netwm.h:967
xcb_connection_t * xcbConnection() const
Returns the xcb connection used.
Definition netwm.cpp:4888
int desktop(bool ignore_viewport=false) const
Returns the desktop where the window is residing.
Definition netwm.cpp:4707
void setStrut(NETStrut strut)
Definition netwm.cpp:2733
NETIcon icon(int width=-1, int height=-1) const
Returns an icon.
Definition netwm.cpp:3508
xcb_pixmap_t icccmIconPixmapMask() const
Returns the mask for the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4784
void setExtendedStrut(const NETExtendedStrut &extended_strut)
Set the extended (partial) strut for the application window.
Definition netwm.cpp:2708
NETStrut strut() const
Definition netwm.cpp:4620
xcb_pixmap_t icccmIconPixmap() const
Returns the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4779
void setDesktop(int desktop, bool ignore_viewport=false)
Set which window the desktop is (should be) on.
Definition netwm.cpp:3218
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:4789
@ 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(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
iterator begin()
void clear()
const_iterator constBegin() const const
const_iterator constEnd() const const
bool contains(const AT &value) const const
qsizetype count() const const
iterator end()
iterator erase(const_iterator begin, const_iterator end)
qsizetype removeAll(const AT &t)
QMetaMethod fromSignal(PointerToMemberFunction signal)
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
Q_EMITQ_EMIT
Q_INVOKABLEQ_INVOKABLE
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual void connectNotify(const QMetaMethod &signal)
bool disconnect(const QMetaObject::Connection &connection)
QThread * thread() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QPixmap fromImage(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(Args &&... args) const const
QString fromLocal8Bit(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
QString toLower() const const
QByteArray toUtf8() const const
QString join(QChar separator) const const
IgnoreAspectRatio
BlockingQueuedConnection
SmoothTransformation
QFuture< void > filter(QThreadPool *pool, 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 Fri Dec 6 2024 12:03:59 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.