KWindowSystem

netwm.cpp
1/*
2 SPDX-FileCopyrightText: 2000 Troll Tech AS
3 SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
4
5 SPDX-License-Identifier: MIT
6*/
7
8//#define NETWMDEBUG
9#include "netwm.h"
10
11#include <xcb/xproto.h>
12
13#include "atoms_p.h"
14#include "netwm_p.h"
15#include "kxcbevent_p.h"
16
17#if KWINDOWSYSTEM_HAVE_X11 // FIXME
18
19#include <QGuiApplication>
20#include <QHash>
21
22#include <private/qtx11extras_p.h>
23
24#include <kwindowinfo.h>
25#include <kwindowsystem.h>
26#include <kx11extras.h>
27#include <kxutils_p.h>
28
29#include <assert.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34// This struct is defined here to avoid a dependency on xcb-icccm
35struct kde_wm_hints {
36 uint32_t flags;
37 uint32_t input;
38 int32_t initial_state;
39 xcb_pixmap_t icon_pixmap;
40 xcb_window_t icon_window;
41 int32_t icon_x;
42 int32_t icon_y;
43 xcb_pixmap_t icon_mask;
44 xcb_window_t window_group;
45};
46
48Q_GLOBAL_STATIC(AtomHash, s_gAtomsHash)
49
50static QSharedDataPointer<Atoms> atomsForConnection(xcb_connection_t *c)
51{
52 auto it = s_gAtomsHash->constFind(c);
53 if (it == s_gAtomsHash->constEnd()) {
54 QSharedDataPointer<Atoms> atom(new Atoms(c));
55 s_gAtomsHash->insert(c, atom);
56 return atom;
57 }
58 return it.value();
59}
60
61Atoms::Atoms(xcb_connection_t *c)
62 : QSharedData()
63 , m_connection(c)
64{
65 for (int i = 0; i < KwsAtomCount; ++i) {
66 m_atoms[i] = XCB_ATOM_NONE;
67 }
68 init();
69}
70
71static const uint32_t netwm_sendevent_mask = (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
72
73const long MAX_PROP_SIZE = 100000;
74
75static char *nstrdup(const char *s1)
76{
77 if (!s1) {
78 return (char *)nullptr;
79 }
80
81 int l = strlen(s1) + 1;
82 char *s2 = new char[l];
83 strncpy(s2, s1, l);
84 return s2;
85}
86
87static char *nstrndup(const char *s1, int l)
88{
89 if (!s1 || l == 0) {
90 return (char *)nullptr;
91 }
92
93 char *s2 = new char[l + 1];
94 strncpy(s2, s1, l);
95 s2[l] = '\0';
96 return s2;
97}
98
99static xcb_window_t *nwindup(const xcb_window_t *w1, int n)
100{
101 if (!w1 || n == 0) {
102 return (xcb_window_t *)nullptr;
103 }
104
105 xcb_window_t *w2 = new xcb_window_t[n];
106 while (n--) {
107 w2[n] = w1[n];
108 }
109 return w2;
110}
111
112static void refdec_nri(NETRootInfoPrivate *p)
113{
114#ifdef NETWMDEBUG
115 fprintf(stderr, "NET: decrementing NETRootInfoPrivate::ref (%d)\n", p->ref - 1);
116#endif
117
118 if (!--p->ref) {
119#ifdef NETWMDEBUG
120 fprintf(stderr, "NET: \tno more references, deleting\n");
121#endif
122
123 delete[] p->name;
124 delete[] p->stacking;
125 delete[] p->clients;
126 delete[] p->virtual_roots;
127 delete[] p->temp_buf;
128
129 int i;
130 for (i = 0; i < p->desktop_names.size(); i++) {
131 delete[] p->desktop_names[i];
132 }
133 }
134}
135
136static void refdec_nwi(NETWinInfoPrivate *p)
137{
138#ifdef NETWMDEBUG
139 fprintf(stderr, "NET: decrementing NETWinInfoPrivate::ref (%d)\n", p->ref - 1);
140#endif
141
142 if (!--p->ref) {
143#ifdef NETWMDEBUG
144 fprintf(stderr, "NET: \tno more references, deleting\n");
145#endif
146
147 delete[] p->name;
148 delete[] p->visible_name;
149 delete[] p->window_role;
150 delete[] p->icon_name;
151 delete[] p->visible_icon_name;
152 delete[] p->startup_id;
153 delete[] p->class_class;
154 delete[] p->class_name;
155 delete[] p->activities;
156 delete[] p->client_machine;
157 delete[] p->desktop_file;
158 delete[] p->gtk_application_id;
159 delete[] p->appmenu_object_path;
160 delete[] p->appmenu_service_name;
161
162 int i;
163 for (i = 0; i < p->icons.size(); i++) {
164 delete[] p->icons[i].data;
165 }
166 delete[] p->icon_sizes;
167 }
168}
169
170template<typename T>
171T get_value_reply(xcb_connection_t *c, const xcb_get_property_cookie_t cookie, xcb_atom_t type, T def, bool *success = nullptr)
172{
173 T value = def;
174
175 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, nullptr);
176
177 if (success) {
178 *success = false;
179 }
180
181 if (reply) {
182 if (reply->type == type && reply->value_len == 1 && reply->format == sizeof(T) * 8) {
183 value = *reinterpret_cast<T *>(xcb_get_property_value(reply));
184
185 if (success) {
186 *success = true;
187 }
188 }
189
190 free(reply);
191 }
192
193 return value;
194}
195
196template<typename T>
197QList<T> get_array_reply(xcb_connection_t *c, const xcb_get_property_cookie_t cookie, xcb_atom_t type)
198{
199 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, nullptr);
200 if (!reply) {
201 return QList<T>();
202 }
203
204 QList<T> vector;
205
206 if (reply->type == type && reply->value_len > 0 && reply->format == sizeof(T) * 8) {
207 T *data = reinterpret_cast<T *>(xcb_get_property_value(reply));
208
209 vector.resize(reply->value_len);
210 memcpy((void *)&vector.first(), (void *)data, reply->value_len * sizeof(T));
211 }
212
213 free(reply);
214 return vector;
215}
216
217static QByteArray get_string_reply(xcb_connection_t *c, const xcb_get_property_cookie_t cookie, xcb_atom_t type)
218{
219 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, nullptr);
220 if (!reply) {
221 return QByteArray();
222 }
223
224 QByteArray value;
225
226 if (reply->type == type && reply->format == 8 && reply->value_len > 0) {
227 const char *data = (const char *)xcb_get_property_value(reply);
228 int len = reply->value_len;
229
230 if (data) {
231 value = QByteArray(data, data[len - 1] ? len : len - 1);
232 }
233 }
234
235 free(reply);
236 return value;
237}
238
239static QList<QByteArray> get_stringlist_reply(xcb_connection_t *c, const xcb_get_property_cookie_t cookie, xcb_atom_t type)
240{
241 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, nullptr);
242 if (!reply) {
243 return QList<QByteArray>();
244 }
245
247
248 if (reply->type == type && reply->format == 8 && reply->value_len > 0) {
249 const char *data = (const char *)xcb_get_property_value(reply);
250 int len = reply->value_len;
251
252 if (data) {
253 const QByteArray ba = QByteArray(data, data[len - 1] ? len : len - 1);
254 list = ba.split('\0');
255 }
256 }
257
258 free(reply);
259 return list;
260}
261
262#ifdef NETWMDEBUG
263static QByteArray get_atom_name(xcb_connection_t *c, xcb_atom_t atom)
264{
265 const xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(c, atom);
266
267 xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(c, cookie, 0);
268 if (!reply) {
269 return QByteArray();
270 }
271
272 QByteArray ba(xcb_get_atom_name_name(reply));
273 free(reply);
274
275 return ba;
276}
277#endif
278
279void Atoms::init()
280{
281#define ENUM_CREATE_CHAR_ARRAY 1
282#include "atoms_p.h" // creates const char* array "KwsAtomStrings"
283 // Send the intern atom requests
284 xcb_intern_atom_cookie_t cookies[KwsAtomCount];
285 for (int i = 0; i < KwsAtomCount; ++i) {
286 cookies[i] = xcb_intern_atom(m_connection, false, strlen(KwsAtomStrings[i]), KwsAtomStrings[i]);
287 }
288
289 // Get the replies
290 for (int i = 0; i < KwsAtomCount; ++i) {
291 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(m_connection, cookies[i], nullptr);
292 if (!reply) {
293 continue;
294 }
295
296 m_atoms[i] = reply->atom;
297 free(reply);
298 }
299}
300
301static void readIcon(xcb_connection_t *c, const xcb_get_property_cookie_t cookie, NETRArray<NETIcon> &icons, int &icon_count)
302{
303#ifdef NETWMDEBUG
304 fprintf(stderr, "NET: readIcon\n");
305#endif
306
307 // reset
308 for (int i = 0; i < icons.size(); i++) {
309 delete[] icons[i].data;
310 }
311
312 icons.reset();
313 icon_count = 0;
314
315 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, nullptr);
316
317 if (!reply || reply->value_len < 3 || reply->format != 32 || reply->type != XCB_ATOM_CARDINAL) {
318 if (reply) {
319 free(reply);
320 }
321
322 return;
323 }
324
325 uint32_t *data = (uint32_t *)xcb_get_property_value(reply);
326
327 for (unsigned int i = 0, j = 0; j < reply->value_len - 2; i++) {
328 uint32_t width = data[j++];
329 uint32_t height = data[j++];
330 uint32_t size = width * height * sizeof(uint32_t);
331
332 if (width == 0 || height == 0) {
333 fprintf(stderr, "Invalid icon size (%d x %d)\n", width, height);
334 break;
335 }
336
337 constexpr int maxIconSize = 8192;
338 if (width > maxIconSize || height > maxIconSize) {
339 fprintf(stderr, "Icon size larger than maximum (%d x %d)\n", width, height);
340 break;
341 }
342
343 if (j + width * height > reply->value_len) {
344 fprintf(stderr, "Ill-encoded icon data; proposed size leads to out of bounds access. Skipping. (%d x %d)\n", width, height);
345 break;
346 }
347
348 icons[i].size.width = width;
349 icons[i].size.height = height;
350 icons[i].data = new unsigned char[size];
351
352 memcpy((void *)icons[i].data, (const void *)&data[j], size);
353
354 j += width * height;
355 icon_count++;
356 }
357
358 free(reply);
359
360#ifdef NETWMDEBUG
361 fprintf(stderr, "NET: readIcon got %d icons\n", icon_count);
362#endif
363}
364
365static void send_client_message(xcb_connection_t *c, uint32_t mask, xcb_window_t destination, xcb_window_t window, xcb_atom_t message, const uint32_t data[])
366{
367 KXcbEvent<xcb_client_message_event_t> event;
368 event.response_type = XCB_CLIENT_MESSAGE;
369 event.format = 32;
370 event.sequence = 0;
371 event.window = window;
372 event.type = message;
373
374 for (int i = 0; i < 5; i++) {
375 event.data.data32[i] = data[i];
376 }
377
378 xcb_send_event(c, false, destination, mask, event.buffer());
379}
380
381template<class Z>
382NETRArray<Z>::NETRArray()
383 : sz(0)
384 , capacity(2)
385{
386 d = (Z *)calloc(capacity, sizeof(Z)); // allocate 2 elts and set to zero
387}
388
389template<class Z>
390NETRArray<Z>::~NETRArray()
391{
392 free(d);
393}
394
395template<class Z>
396void NETRArray<Z>::reset()
397{
398 sz = 0;
399 capacity = 2;
400 d = (Z *)realloc(d, sizeof(Z) * capacity);
401 memset((void *)d, 0, sizeof(Z) * capacity);
402}
403
404template<class Z>
405Z &NETRArray<Z>::operator[](int index)
406{
407 if (index >= capacity) {
408 // allocate space for the new data
409 // open table has amortized O(1) access time
410 // when N elements appended consecutively -- exa
411 int newcapacity = 2 * capacity > index + 1 ? 2 * capacity : index + 1; // max
412 // copy into new larger memory block using realloc
413 d = (Z *)realloc(d, sizeof(Z) * newcapacity);
414 memset((void *)&d[capacity], 0, sizeof(Z) * (newcapacity - capacity));
415 capacity = newcapacity;
416 }
417 if (index >= sz) { // at this point capacity>index
418 sz = index + 1;
419 }
420
421 return d[index];
422}
423
424/*
425 The viewport<->desktop matching is a bit backwards, since NET* classes are the base
426 (and were originally even created with the intention of being the reference WM spec
427 implementation) and KWindowSystem builds on top of it. However it's simpler to add watching
428 whether the WM uses viewport is simpler to KWindowSystem and not having this mapping
429 in NET* classes could result in some code using it directly and not supporting viewport.
430 So NET* classes check if mapping is needed and if yes they forward to KWindowSystem,
431 which will forward again back to NET* classes, but to viewport calls instead of desktop calls.
432*/
433
434// Construct a new NETRootInfo object.
435
436NETRootInfo::NETRootInfo(xcb_connection_t *connection,
437 xcb_window_t supportWindow,
438 const char *wmName,
439 NET::Properties properties,
440 NET::WindowTypes windowTypes,
441 NET::States states,
442 NET::Properties2 properties2,
443 NET::Actions actions,
444 int screen,
445 bool doActivate)
446{
447#ifdef NETWMDEBUG
448 fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
449#endif
450
451 p = new NETRootInfoPrivate;
452 p->ref = 1;
453 p->atoms = atomsForConnection(connection);
454
455 p->name = nstrdup(wmName);
456
457 p->conn = connection;
458
459 p->temp_buf = nullptr;
460 p->temp_buf_size = 0;
461
462 const xcb_setup_t *setup = xcb_get_setup(p->conn);
463 xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
464
465 if (screen != -1 && screen < setup->roots_len) {
466 for (int i = 0; i < screen; i++) {
467 xcb_screen_next(&it);
468 }
469 }
470
471 p->root = it.data->root;
472 p->supportwindow = supportWindow;
473 p->number_of_desktops = p->current_desktop = 0;
474 p->active = XCB_WINDOW_NONE;
475 p->clients = p->stacking = p->virtual_roots = (xcb_window_t *)nullptr;
476 p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
477 p->showing_desktop = false;
478 p->desktop_layout_orientation = OrientationHorizontal;
479 p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
480 p->desktop_layout_columns = p->desktop_layout_rows = 0;
481 setDefaultProperties();
482 p->properties = properties;
483 p->properties2 = properties2;
484 p->windowTypes = windowTypes;
485 p->states = states;
486 p->actions = actions;
487 // force support for Supported and SupportingWMCheck for window managers
488 p->properties |= (Supported | SupportingWMCheck);
489 p->clientProperties = DesktopNames // the only thing that can be changed by clients
490 | WMPing; // or they can reply to this
491 p->clientProperties2 = WM2DesktopLayout;
492
493 p->role = WindowManager;
494
495 if (doActivate) {
496 activate();
497 }
498}
499
500NETRootInfo::NETRootInfo(xcb_connection_t *connection, NET::Properties properties, NET::Properties2 properties2, int screen, bool doActivate)
501{
502#ifdef NETWMDEBUG
503 fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
504#endif
505
506 p = new NETRootInfoPrivate;
507 p->ref = 1;
508 p->atoms = atomsForConnection(connection);
509
510 p->name = nullptr;
511
512 p->conn = connection;
513
514 p->temp_buf = nullptr;
515 p->temp_buf_size = 0;
516
517 const xcb_setup_t *setup = xcb_get_setup(p->conn);
518 xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
519
520 if (screen != -1 && screen < setup->roots_len) {
521 for (int i = 0; i < screen; i++) {
522 xcb_screen_next(&it);
523 }
524 }
525
526 p->root = it.data->root;
527 p->rootSize.width = it.data->width_in_pixels;
528 p->rootSize.height = it.data->height_in_pixels;
529
530 p->supportwindow = XCB_WINDOW_NONE;
531 p->number_of_desktops = p->current_desktop = 0;
532 p->active = XCB_WINDOW_NONE;
533 p->clients = p->stacking = p->virtual_roots = (xcb_window_t *)nullptr;
534 p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
535 p->showing_desktop = false;
536 p->desktop_layout_orientation = OrientationHorizontal;
537 p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
538 p->desktop_layout_columns = p->desktop_layout_rows = 0;
539 setDefaultProperties();
540 p->clientProperties = properties;
541 p->clientProperties2 = properties2;
542 p->properties = NET::Properties();
543 p->properties2 = NET::Properties2();
544 p->windowTypes = NET::WindowTypes();
545 p->states = NET::States();
546 p->actions = NET::Actions();
547
548 p->role = Client;
549
550 if (doActivate) {
551 activate();
552 }
553}
554
555// Copy an existing NETRootInfo object.
556
558{
559#ifdef NETWMDEBUG
560 fprintf(stderr, "NETRootInfo::NETRootInfo: using copy constructor\n");
561#endif
562
563 p = rootinfo.p;
564
565 p->ref++;
566}
567
568// Be gone with our NETRootInfo.
569
571{
572 refdec_nri(p);
573
574 if (!p->ref) {
575 delete p;
576 }
577}
578
579void NETRootInfo::setDefaultProperties()
580{
581 p->properties = Supported | SupportingWMCheck;
583 p->states = Modal | Sticky | MaxVert | MaxHoriz | Shaded | SkipTaskbar | KeepAbove;
584 p->properties2 = NET::Properties2();
585 p->actions = NET::Actions();
586 p->clientProperties = NET::Properties();
587 p->clientProperties2 = NET::Properties2();
588}
589
591{
592 if (p->role == WindowManager) {
593#ifdef NETWMDEBUG
594 fprintf(stderr, "NETRootInfo::activate: setting supported properties on root\n");
595#endif
596
597 setSupported();
598 update(p->clientProperties, p->clientProperties2);
599 } else {
600#ifdef NETWMDEBUG
601 fprintf(stderr, "NETRootInfo::activate: updating client information\n");
602#endif
603
604 update(p->clientProperties, p->clientProperties2);
605 }
606}
607
608void NETRootInfo::setClientList(const xcb_window_t *windows, unsigned int count)
609{
610 if (p->role != WindowManager) {
611 return;
612 }
613
614 p->clients_count = count;
615
616 delete[] p->clients;
617 p->clients = nwindup(windows, count);
618
619#ifdef NETWMDEBUG
620 fprintf(stderr, "NETRootInfo::setClientList: setting list with %ld windows\n", p->clients_count);
621#endif
622
623 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_CLIENT_LIST), XCB_ATOM_WINDOW, 32, p->clients_count, (const void *)windows);
624}
625
626void NETRootInfo::setClientListStacking(const xcb_window_t *windows, unsigned int count)
627{
628 if (p->role != WindowManager) {
629 return;
630 }
631
632 p->stacking_count = count;
633 delete[] p->stacking;
634 p->stacking = nwindup(windows, count);
635
636#ifdef NETWMDEBUG
637 fprintf(stderr, "NETRootInfo::setClientListStacking: setting list with %ld windows\n", p->clients_count);
638#endif
639
640 xcb_change_property(p->conn,
641 XCB_PROP_MODE_REPLACE,
642 p->root,
643 p->atom(_NET_CLIENT_LIST_STACKING),
644 XCB_ATOM_WINDOW,
645 32,
646 p->stacking_count,
647 (const void *)windows);
648}
649
650void NETRootInfo::setNumberOfDesktops(int numberOfDesktops)
651{
652#ifdef NETWMDEBUG
653 fprintf(stderr, "NETRootInfo::setNumberOfDesktops: setting desktop count to %d (%s)\n", numberOfDesktops, (p->role == WindowManager) ? "WM" : "Client");
654#endif
655
656 if (p->role == WindowManager) {
657 p->number_of_desktops = numberOfDesktops;
658 const uint32_t d = numberOfDesktops;
659 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_NUMBER_OF_DESKTOPS), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
660 } else {
661 const uint32_t data[5] = {uint32_t(numberOfDesktops), 0, 0, 0, 0};
662
663 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->root, p->atom(_NET_NUMBER_OF_DESKTOPS), data);
664 }
665}
666
667void NETRootInfo::setCurrentDesktop(int desktop, bool ignore_viewport)
668{
669#ifdef NETWMDEBUG
670 fprintf(stderr, "NETRootInfo::setCurrentDesktop: setting current desktop = %d (%s)\n", desktop, (p->role == WindowManager) ? "WM" : "Client");
671#endif
672
673 if (p->role == WindowManager) {
674 p->current_desktop = desktop;
675 uint32_t d = p->current_desktop - 1;
676 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_CURRENT_DESKTOP), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
677 } else {
678 if (!ignore_viewport && KX11Extras::mapViewport()) {
680 return;
681 }
682
683 const uint32_t data[5] = {uint32_t(desktop - 1), 0, 0, 0, 0};
684
685 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->root, p->atom(_NET_CURRENT_DESKTOP), data);
686 }
687}
688
689void NETRootInfo::setDesktopName(int desktop, const char *desktopName)
690{
691 // Allow setting desktop names even for non-existent desktops, see the spec, sect.3.7.
692 if (desktop < 1) {
693 return;
694 }
695
696 delete[] p->desktop_names[desktop - 1];
697 p->desktop_names[desktop - 1] = nstrdup(desktopName);
698
699 unsigned int i;
700 unsigned int proplen;
701 unsigned int num = ((p->number_of_desktops > p->desktop_names.size()) ? p->number_of_desktops : p->desktop_names.size());
702 for (i = 0, proplen = 0; i < num; i++) {
703 proplen += (p->desktop_names[i] != nullptr ? strlen(p->desktop_names[i]) + 1 : 1);
704 }
705
706 char *prop = new char[proplen];
707 char *propp = prop;
708
709 for (i = 0; i < num; i++) {
710 if (p->desktop_names[i]) {
711 strcpy(propp, p->desktop_names[i]);
712 propp += strlen(p->desktop_names[i]) + 1;
713 } else {
714 *propp++ = '\0';
715 }
716 }
717
718#ifdef NETWMDEBUG
719 fprintf(stderr,
720 "NETRootInfo::setDesktopName(%d, '%s')\n"
721 "NETRootInfo::setDesktopName: total property length = %d",
722 desktop,
724 proplen);
725#endif
726
727 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_DESKTOP_NAMES), p->atom(UTF8_STRING), 8, proplen, (const void *)prop);
728
729 delete[] prop;
730}
731
733{
734#ifdef NETWMDEBUG
735 fprintf(stderr, "NETRootInfo::setDesktopGeometry( -- , { %d, %d }) (%s)\n", geometry.width, geometry.height, (p->role == WindowManager) ? "WM" : "Client");
736#endif
737
738 if (p->role == WindowManager) {
739 p->geometry = geometry;
740
741 uint32_t data[2];
742 data[0] = p->geometry.width;
743 data[1] = p->geometry.height;
744
745 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_DESKTOP_GEOMETRY), XCB_ATOM_CARDINAL, 32, 2, (const void *)data);
746 } else {
747 uint32_t data[5] = {uint32_t(geometry.width), uint32_t(geometry.height), 0, 0, 0};
748
749 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->root, p->atom(_NET_DESKTOP_GEOMETRY), data);
750 }
751}
752
753void NETRootInfo::setDesktopViewport(int desktop, const NETPoint &viewport)
754{
755#ifdef NETWMDEBUG
756 fprintf(stderr, "NETRootInfo::setDesktopViewport(%d, { %d, %d }) (%s)\n", desktop, viewport.x, viewport.y, (p->role == WindowManager) ? "WM" : "Client");
757#endif
758
759 if (desktop < 1) {
760 return;
761 }
762
763 if (p->role == WindowManager) {
764 p->viewport[desktop - 1] = viewport;
765
766 int d;
767 int i;
768 int l;
769 l = p->number_of_desktops * 2;
770 uint32_t *data = new uint32_t[l];
771 for (d = 0, i = 0; d < p->number_of_desktops; d++) {
772 data[i++] = p->viewport[d].x;
773 data[i++] = p->viewport[d].y;
774 }
775
776 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_DESKTOP_VIEWPORT), XCB_ATOM_CARDINAL, 32, l, (const void *)data);
777
778 delete[] data;
779 } else {
780 const uint32_t data[5] = {uint32_t(viewport.x), uint32_t(viewport.y), 0, 0, 0};
781
782 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->root, p->atom(_NET_DESKTOP_VIEWPORT), data);
783 }
784}
785
786void NETRootInfo::setSupported()
787{
788 if (p->role != WindowManager) {
789#ifdef NETWMDEBUG
790 fprintf(stderr, "NETRootInfo::setSupported - role != WindowManager\n");
791#endif
792
793 return;
794 }
795
796 xcb_atom_t atoms[KwsAtomCount];
797 int pnum = 2;
798
799 // Root window properties/messages
800 atoms[0] = p->atom(_NET_SUPPORTED);
801 atoms[1] = p->atom(_NET_SUPPORTING_WM_CHECK);
802
803 if (p->properties & ClientList) {
804 atoms[pnum++] = p->atom(_NET_CLIENT_LIST);
805 }
806
807 if (p->properties & ClientListStacking) {
808 atoms[pnum++] = p->atom(_NET_CLIENT_LIST_STACKING);
809 }
810
811 if (p->properties & NumberOfDesktops) {
812 atoms[pnum++] = p->atom(_NET_NUMBER_OF_DESKTOPS);
813 }
814
815 if (p->properties & DesktopGeometry) {
816 atoms[pnum++] = p->atom(_NET_DESKTOP_GEOMETRY);
817 }
818
819 if (p->properties & DesktopViewport) {
820 atoms[pnum++] = p->atom(_NET_DESKTOP_VIEWPORT);
821 }
822
823 if (p->properties & CurrentDesktop) {
824 atoms[pnum++] = p->atom(_NET_CURRENT_DESKTOP);
825 }
826
827 if (p->properties & DesktopNames) {
828 atoms[pnum++] = p->atom(_NET_DESKTOP_NAMES);
829 }
830
831 if (p->properties & ActiveWindow) {
832 atoms[pnum++] = p->atom(_NET_ACTIVE_WINDOW);
833 }
834
835 if (p->properties & WorkArea) {
836 atoms[pnum++] = p->atom(_NET_WORKAREA);
837 }
838
839 if (p->properties & VirtualRoots) {
840 atoms[pnum++] = p->atom(_NET_VIRTUAL_ROOTS);
841 }
842
843 if (p->properties2 & WM2DesktopLayout) {
844 atoms[pnum++] = p->atom(_NET_DESKTOP_LAYOUT);
845 }
846
847 if (p->properties & CloseWindow) {
848 atoms[pnum++] = p->atom(_NET_CLOSE_WINDOW);
849 }
850
851 if (p->properties2 & WM2RestackWindow) {
852 atoms[pnum++] = p->atom(_NET_RESTACK_WINDOW);
853 }
854
855 if (p->properties2 & WM2ShowingDesktop) {
856 atoms[pnum++] = p->atom(_NET_SHOWING_DESKTOP);
857 }
858
859 // Application window properties/messages
860 if (p->properties & WMMoveResize) {
861 atoms[pnum++] = p->atom(_NET_WM_MOVERESIZE);
862 }
863
864 if (p->properties2 & WM2MoveResizeWindow) {
865 atoms[pnum++] = p->atom(_NET_MOVERESIZE_WINDOW);
866 }
867
868 if (p->properties & WMName) {
869 atoms[pnum++] = p->atom(_NET_WM_NAME);
870 }
871
872 if (p->properties & WMVisibleName) {
873 atoms[pnum++] = p->atom(_NET_WM_VISIBLE_NAME);
874 }
875
876 if (p->properties & WMIconName) {
877 atoms[pnum++] = p->atom(_NET_WM_ICON_NAME);
878 }
879
880 if (p->properties & WMVisibleIconName) {
881 atoms[pnum++] = p->atom(_NET_WM_VISIBLE_ICON_NAME);
882 }
883
884 if (p->properties & WMDesktop) {
885 atoms[pnum++] = p->atom(_NET_WM_DESKTOP);
886 }
887
888 if (p->properties & WMWindowType) {
889 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE);
890
891 // Application window types
892 if (p->windowTypes & NormalMask) {
893 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_NORMAL);
894 }
895 if (p->windowTypes & DesktopMask) {
896 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_DESKTOP);
897 }
898 if (p->windowTypes & DockMask) {
899 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_DOCK);
900 }
901 if (p->windowTypes & ToolbarMask) {
902 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_TOOLBAR);
903 }
904 if (p->windowTypes & MenuMask) {
905 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_MENU);
906 }
907 if (p->windowTypes & DialogMask) {
908 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_DIALOG);
909 }
910 if (p->windowTypes & UtilityMask) {
911 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_UTILITY);
912 }
913 if (p->windowTypes & SplashMask) {
914 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_SPLASH);
915 }
916 if (p->windowTypes & DropdownMenuMask) {
917 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU);
918 }
919 if (p->windowTypes & PopupMenuMask) {
920 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_POPUP_MENU);
921 }
922 if (p->windowTypes & TooltipMask) {
923 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_TOOLTIP);
924 }
925 if (p->windowTypes & NotificationMask) {
926 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION);
927 }
928 if (p->windowTypes & ComboBoxMask) {
929 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_COMBO);
930 }
931 if (p->windowTypes & DNDIconMask) {
932 atoms[pnum++] = p->atom(_NET_WM_WINDOW_TYPE_DND);
933 }
934 // KDE extensions
935 if (p->windowTypes & OverrideMask) {
936 atoms[pnum++] = p->atom(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
937 }
938 if (p->windowTypes & TopMenuMask) {
939 atoms[pnum++] = p->atom(_KDE_NET_WM_WINDOW_TYPE_TOPMENU);
940 }
941 if (p->windowTypes & OnScreenDisplayMask) {
942 atoms[pnum++] = p->atom(_KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY);
943 }
944 if (p->windowTypes & CriticalNotificationMask) {
945 atoms[pnum++] = p->atom(_KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION);
946 }
947 if (p->windowTypes & AppletPopupMask) {
948 atoms[pnum++] = p->atom(_KDE_NET_WM_WINDOW_TYPE_APPLET_POPUP);
949 }
950 }
951
952 if (p->properties & WMState) {
953 atoms[pnum++] = p->atom(_NET_WM_STATE);
954
955 // Application window states
956 if (p->states & Modal) {
957 atoms[pnum++] = p->atom(_NET_WM_STATE_MODAL);
958 }
959 if (p->states & Sticky) {
960 atoms[pnum++] = p->atom(_NET_WM_STATE_STICKY);
961 }
962 if (p->states & MaxVert) {
963 atoms[pnum++] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
964 }
965 if (p->states & MaxHoriz) {
966 atoms[pnum++] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
967 }
968 if (p->states & Shaded) {
969 atoms[pnum++] = p->atom(_NET_WM_STATE_SHADED);
970 }
971 if (p->states & SkipTaskbar) {
972 atoms[pnum++] = p->atom(_NET_WM_STATE_SKIP_TASKBAR);
973 }
974 if (p->states & SkipPager) {
975 atoms[pnum++] = p->atom(_NET_WM_STATE_SKIP_PAGER);
976 }
977 if (p->states & SkipSwitcher) {
978 atoms[pnum++] = p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER);
979 }
980 if (p->states & Hidden) {
981 atoms[pnum++] = p->atom(_NET_WM_STATE_HIDDEN);
982 }
983 if (p->states & FullScreen) {
984 atoms[pnum++] = p->atom(_NET_WM_STATE_FULLSCREEN);
985 }
986 if (p->states & KeepAbove) {
987 atoms[pnum++] = p->atom(_NET_WM_STATE_ABOVE);
988 // deprecated variant
989 atoms[pnum++] = p->atom(_NET_WM_STATE_STAYS_ON_TOP);
990 }
991 if (p->states & KeepBelow) {
992 atoms[pnum++] = p->atom(_NET_WM_STATE_BELOW);
993 }
994 if (p->states & DemandsAttention) {
995 atoms[pnum++] = p->atom(_NET_WM_STATE_DEMANDS_ATTENTION);
996 }
997
998 if (p->states & Focused) {
999 atoms[pnum++] = p->atom(_NET_WM_STATE_FOCUSED);
1000 }
1001 }
1002
1003 if (p->properties & WMStrut) {
1004 atoms[pnum++] = p->atom(_NET_WM_STRUT);
1005 }
1006
1007 if (p->properties2 & WM2ExtendedStrut) {
1008 atoms[pnum++] = p->atom(_NET_WM_STRUT_PARTIAL);
1009 }
1010
1011 if (p->properties & WMIconGeometry) {
1012 atoms[pnum++] = p->atom(_NET_WM_ICON_GEOMETRY);
1013 }
1014
1015 if (p->properties & WMIcon) {
1016 atoms[pnum++] = p->atom(_NET_WM_ICON);
1017 }
1018
1019 if (p->properties & WMPid) {
1020 atoms[pnum++] = p->atom(_NET_WM_PID);
1021 }
1022
1023 if (p->properties & WMHandledIcons) {
1024 atoms[pnum++] = p->atom(_NET_WM_HANDLED_ICONS);
1025 }
1026
1027 if (p->properties & WMPing) {
1028 atoms[pnum++] = p->atom(_NET_WM_PING);
1029 }
1030
1031 if (p->properties2 & WM2UserTime) {
1032 atoms[pnum++] = p->atom(_NET_WM_USER_TIME);
1033 }
1034
1035 if (p->properties2 & WM2StartupId) {
1036 atoms[pnum++] = p->atom(_NET_STARTUP_ID);
1037 }
1038
1039 if (p->properties2 & WM2Opacity) {
1040 atoms[pnum++] = p->atom(_NET_WM_WINDOW_OPACITY);
1041 }
1042
1043 if (p->properties2 & WM2FullscreenMonitors) {
1044 atoms[pnum++] = p->atom(_NET_WM_FULLSCREEN_MONITORS);
1045 }
1046
1047 if (p->properties2 & WM2AllowedActions) {
1048 atoms[pnum++] = p->atom(_NET_WM_ALLOWED_ACTIONS);
1049
1050 // Actions
1051 if (p->actions & ActionMove) {
1052 atoms[pnum++] = p->atom(_NET_WM_ACTION_MOVE);
1053 }
1054 if (p->actions & ActionResize) {
1055 atoms[pnum++] = p->atom(_NET_WM_ACTION_RESIZE);
1056 }
1057 if (p->actions & ActionMinimize) {
1058 atoms[pnum++] = p->atom(_NET_WM_ACTION_MINIMIZE);
1059 }
1060 if (p->actions & ActionShade) {
1061 atoms[pnum++] = p->atom(_NET_WM_ACTION_SHADE);
1062 }
1063 if (p->actions & ActionStick) {
1064 atoms[pnum++] = p->atom(_NET_WM_ACTION_STICK);
1065 }
1066 if (p->actions & ActionMaxVert) {
1067 atoms[pnum++] = p->atom(_NET_WM_ACTION_MAXIMIZE_VERT);
1068 }
1069 if (p->actions & ActionMaxHoriz) {
1070 atoms[pnum++] = p->atom(_NET_WM_ACTION_MAXIMIZE_HORZ);
1071 }
1072 if (p->actions & ActionFullScreen) {
1073 atoms[pnum++] = p->atom(_NET_WM_ACTION_FULLSCREEN);
1074 }
1075 if (p->actions & ActionChangeDesktop) {
1076 atoms[pnum++] = p->atom(_NET_WM_ACTION_CHANGE_DESKTOP);
1077 }
1078 if (p->actions & ActionClose) {
1079 atoms[pnum++] = p->atom(_NET_WM_ACTION_CLOSE);
1080 }
1081 }
1082
1083 if (p->properties & WMFrameExtents) {
1084 atoms[pnum++] = p->atom(_NET_FRAME_EXTENTS);
1085 atoms[pnum++] = p->atom(_KDE_NET_WM_FRAME_STRUT);
1086 }
1087
1088 if (p->properties2 & WM2FrameOverlap) {
1089 atoms[pnum++] = p->atom(_NET_WM_FRAME_OVERLAP);
1090 }
1091
1092 if (p->properties2 & WM2KDETemporaryRules) {
1093 atoms[pnum++] = p->atom(_KDE_NET_WM_TEMPORARY_RULES);
1094 }
1095 if (p->properties2 & WM2FullPlacement) {
1096 atoms[pnum++] = p->atom(_NET_WM_FULL_PLACEMENT);
1097 }
1098
1099 if (p->properties2 & WM2Activities) {
1100 atoms[pnum++] = p->atom(_KDE_NET_WM_ACTIVITIES);
1101 }
1102
1103 if (p->properties2 & WM2BlockCompositing) {
1104 atoms[pnum++] = p->atom(_KDE_NET_WM_BLOCK_COMPOSITING);
1105 atoms[pnum++] = p->atom(_NET_WM_BYPASS_COMPOSITOR);
1106 }
1107
1108 if (p->properties2 & WM2KDEShadow) {
1109 atoms[pnum++] = p->atom(_KDE_NET_WM_SHADOW);
1110 }
1111
1112 if (p->properties2 & WM2OpaqueRegion) {
1113 atoms[pnum++] = p->atom(_NET_WM_OPAQUE_REGION);
1114 }
1115
1116 if (p->properties2 & WM2GTKFrameExtents) {
1117 atoms[pnum++] = p->atom(_GTK_FRAME_EXTENTS);
1118 }
1119
1120 if (p->properties2 & WM2GTKShowWindowMenu) {
1121 atoms[pnum++] = p->atom(_GTK_SHOW_WINDOW_MENU);
1122 }
1123
1124 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_SUPPORTED), XCB_ATOM_ATOM, 32, pnum, (const void *)atoms);
1125
1126 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_SUPPORTING_WM_CHECK), XCB_ATOM_WINDOW, 32, 1, (const void *)&(p->supportwindow));
1127
1128#ifdef NETWMDEBUG
1129 fprintf(stderr,
1130 "NETRootInfo::setSupported: _NET_SUPPORTING_WM_CHECK = 0x%lx on 0x%lx\n"
1131 " : _NET_WM_NAME = '%s' on 0x%lx\n",
1132 p->supportwindow,
1133 p->supportwindow,
1134 p->name,
1135 p->supportwindow);
1136#endif
1137
1138 xcb_change_property(p->conn,
1139 XCB_PROP_MODE_REPLACE,
1140 p->supportwindow,
1141 p->atom(_NET_SUPPORTING_WM_CHECK),
1142 XCB_ATOM_WINDOW,
1143 32,
1144 1,
1145 (const void *)&(p->supportwindow));
1146
1147 xcb_change_property(p->conn,
1148 XCB_PROP_MODE_REPLACE,
1149 p->supportwindow,
1150 p->atom(_NET_WM_NAME),
1151 p->atom(UTF8_STRING),
1152 8,
1153 strlen(p->name),
1154 (const void *)p->name);
1155}
1156
1157void NETRootInfo::updateSupportedProperties(xcb_atom_t atom)
1158{
1159 if (atom == p->atom(_NET_SUPPORTED)) {
1160 p->properties |= Supported;
1161 }
1162
1163 else if (atom == p->atom(_NET_SUPPORTING_WM_CHECK)) {
1164 p->properties |= SupportingWMCheck;
1165 }
1166
1167 else if (atom == p->atom(_NET_CLIENT_LIST)) {
1168 p->properties |= ClientList;
1169 }
1170
1171 else if (atom == p->atom(_NET_CLIENT_LIST_STACKING)) {
1172 p->properties |= ClientListStacking;
1173 }
1174
1175 else if (atom == p->atom(_NET_NUMBER_OF_DESKTOPS)) {
1176 p->properties |= NumberOfDesktops;
1177 }
1178
1179 else if (atom == p->atom(_NET_DESKTOP_GEOMETRY)) {
1180 p->properties |= DesktopGeometry;
1181 }
1182
1183 else if (atom == p->atom(_NET_DESKTOP_VIEWPORT)) {
1184 p->properties |= DesktopViewport;
1185 }
1186
1187 else if (atom == p->atom(_NET_CURRENT_DESKTOP)) {
1188 p->properties |= CurrentDesktop;
1189 }
1190
1191 else if (atom == p->atom(_NET_DESKTOP_NAMES)) {
1192 p->properties |= DesktopNames;
1193 }
1194
1195 else if (atom == p->atom(_NET_ACTIVE_WINDOW)) {
1196 p->properties |= ActiveWindow;
1197 }
1198
1199 else if (atom == p->atom(_NET_WORKAREA)) {
1200 p->properties |= WorkArea;
1201 }
1202
1203 else if (atom == p->atom(_NET_VIRTUAL_ROOTS)) {
1204 p->properties |= VirtualRoots;
1205 }
1206
1207 else if (atom == p->atom(_NET_DESKTOP_LAYOUT)) {
1208 p->properties2 |= WM2DesktopLayout;
1209 }
1210
1211 else if (atom == p->atom(_NET_CLOSE_WINDOW)) {
1212 p->properties |= CloseWindow;
1213 }
1214
1215 else if (atom == p->atom(_NET_RESTACK_WINDOW)) {
1216 p->properties2 |= WM2RestackWindow;
1217 }
1218
1219 else if (atom == p->atom(_NET_SHOWING_DESKTOP)) {
1220 p->properties2 |= WM2ShowingDesktop;
1221 }
1222
1223 // Application window properties/messages
1224 else if (atom == p->atom(_NET_WM_MOVERESIZE)) {
1225 p->properties |= WMMoveResize;
1226 }
1227
1228 else if (atom == p->atom(_NET_MOVERESIZE_WINDOW)) {
1229 p->properties2 |= WM2MoveResizeWindow;
1230 }
1231
1232 else if (atom == p->atom(_NET_WM_NAME)) {
1233 p->properties |= WMName;
1234 }
1235
1236 else if (atom == p->atom(_NET_WM_VISIBLE_NAME)) {
1237 p->properties |= WMVisibleName;
1238 }
1239
1240 else if (atom == p->atom(_NET_WM_ICON_NAME)) {
1241 p->properties |= WMIconName;
1242 }
1243
1244 else if (atom == p->atom(_NET_WM_VISIBLE_ICON_NAME)) {
1245 p->properties |= WMVisibleIconName;
1246 }
1247
1248 else if (atom == p->atom(_NET_WM_DESKTOP)) {
1249 p->properties |= WMDesktop;
1250 }
1251
1252 else if (atom == p->atom(_NET_WM_WINDOW_TYPE)) {
1253 p->properties |= WMWindowType;
1254 }
1255
1256 // Application window types
1257 else if (atom == p->atom(_NET_WM_WINDOW_TYPE_NORMAL)) {
1258 p->windowTypes |= NormalMask;
1259 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_DESKTOP)) {
1260 p->windowTypes |= DesktopMask;
1261 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_DOCK)) {
1262 p->windowTypes |= DockMask;
1263 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_TOOLBAR)) {
1264 p->windowTypes |= ToolbarMask;
1265 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_MENU)) {
1266 p->windowTypes |= MenuMask;
1267 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_DIALOG)) {
1268 p->windowTypes |= DialogMask;
1269 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_UTILITY)) {
1270 p->windowTypes |= UtilityMask;
1271 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_SPLASH)) {
1272 p->windowTypes |= SplashMask;
1273 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)) {
1274 p->windowTypes |= DropdownMenuMask;
1275 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_POPUP_MENU)) {
1276 p->windowTypes |= PopupMenuMask;
1277 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_TOOLTIP)) {
1278 p->windowTypes |= TooltipMask;
1279 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION)) {
1280 p->windowTypes |= NotificationMask;
1281 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_COMBO)) {
1282 p->windowTypes |= ComboBoxMask;
1283 } else if (atom == p->atom(_NET_WM_WINDOW_TYPE_DND)) {
1284 p->windowTypes |= DNDIconMask;
1285 }
1286 // KDE extensions
1287 else if (atom == p->atom(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)) {
1288 p->windowTypes |= OverrideMask;
1289 } else if (atom == p->atom(_KDE_NET_WM_WINDOW_TYPE_TOPMENU)) {
1290 p->windowTypes |= TopMenuMask;
1291 } else if (atom == p->atom(_KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY)) {
1292 p->windowTypes |= OnScreenDisplayMask;
1293 } else if (atom == p->atom(_KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION)) {
1294 p->windowTypes |= CriticalNotificationMask;
1295 } else if (atom == p->atom(_KDE_NET_WM_WINDOW_TYPE_APPLET_POPUP)) {
1296 p->windowTypes |= AppletPopupMask;
1297 }
1298
1299 else if (atom == p->atom(_NET_WM_STATE)) {
1300 p->properties |= WMState;
1301 }
1302
1303 // Application window states
1304 else if (atom == p->atom(_NET_WM_STATE_MODAL)) {
1305 p->states |= Modal;
1306 } else if (atom == p->atom(_NET_WM_STATE_STICKY)) {
1307 p->states |= Sticky;
1308 } else if (atom == p->atom(_NET_WM_STATE_MAXIMIZED_VERT)) {
1309 p->states |= MaxVert;
1310 } else if (atom == p->atom(_NET_WM_STATE_MAXIMIZED_HORZ)) {
1311 p->states |= MaxHoriz;
1312 } else if (atom == p->atom(_NET_WM_STATE_SHADED)) {
1313 p->states |= Shaded;
1314 } else if (atom == p->atom(_NET_WM_STATE_SKIP_TASKBAR)) {
1315 p->states |= SkipTaskbar;
1316 } else if (atom == p->atom(_NET_WM_STATE_SKIP_PAGER)) {
1317 p->states |= SkipPager;
1318 } else if (atom == p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER)) {
1319 p->states |= SkipSwitcher;
1320 } else if (atom == p->atom(_NET_WM_STATE_HIDDEN)) {
1321 p->states |= Hidden;
1322 } else if (atom == p->atom(_NET_WM_STATE_FULLSCREEN)) {
1323 p->states |= FullScreen;
1324 } else if (atom == p->atom(_NET_WM_STATE_ABOVE)) {
1325 p->states |= KeepAbove;
1326 } else if (atom == p->atom(_NET_WM_STATE_BELOW)) {
1327 p->states |= KeepBelow;
1328 } else if (atom == p->atom(_NET_WM_STATE_DEMANDS_ATTENTION)) {
1329 p->states |= DemandsAttention;
1330 } else if (atom == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) {
1331 p->states |= KeepAbove;
1332 } else if (atom == p->atom(_NET_WM_STATE_FOCUSED)) {
1333 p->states |= Focused;
1334 }
1335
1336 else if (atom == p->atom(_NET_WM_STRUT)) {
1337 p->properties |= WMStrut;
1338 }
1339
1340 else if (atom == p->atom(_NET_WM_STRUT_PARTIAL)) {
1341 p->properties2 |= WM2ExtendedStrut;
1342 }
1343
1344 else if (atom == p->atom(_NET_WM_ICON_GEOMETRY)) {
1345 p->properties |= WMIconGeometry;
1346 }
1347
1348 else if (atom == p->atom(_NET_WM_ICON)) {
1349 p->properties |= WMIcon;
1350 }
1351
1352 else if (atom == p->atom(_NET_WM_PID)) {
1353 p->properties |= WMPid;
1354 }
1355
1356 else if (atom == p->atom(_NET_WM_HANDLED_ICONS)) {
1357 p->properties |= WMHandledIcons;
1358 }
1359
1360 else if (atom == p->atom(_NET_WM_PING)) {
1361 p->properties |= WMPing;
1362 }
1363
1364 else if (atom == p->atom(_NET_WM_USER_TIME)) {
1365 p->properties2 |= WM2UserTime;
1366 }
1367
1368 else if (atom == p->atom(_NET_STARTUP_ID)) {
1369 p->properties2 |= WM2StartupId;
1370 }
1371
1372 else if (atom == p->atom(_NET_WM_WINDOW_OPACITY)) {
1373 p->properties2 |= WM2Opacity;
1374 }
1375
1376 else if (atom == p->atom(_NET_WM_FULLSCREEN_MONITORS)) {
1377 p->properties2 |= WM2FullscreenMonitors;
1378 }
1379
1380 else if (atom == p->atom(_NET_WM_ALLOWED_ACTIONS)) {
1381 p->properties2 |= WM2AllowedActions;
1382 }
1383
1384 // Actions
1385 else if (atom == p->atom(_NET_WM_ACTION_MOVE)) {
1386 p->actions |= ActionMove;
1387 } else if (atom == p->atom(_NET_WM_ACTION_RESIZE)) {
1388 p->actions |= ActionResize;
1389 } else if (atom == p->atom(_NET_WM_ACTION_MINIMIZE)) {
1390 p->actions |= ActionMinimize;
1391 } else if (atom == p->atom(_NET_WM_ACTION_SHADE)) {
1392 p->actions |= ActionShade;
1393 } else if (atom == p->atom(_NET_WM_ACTION_STICK)) {
1394 p->actions |= ActionStick;
1395 } else if (atom == p->atom(_NET_WM_ACTION_MAXIMIZE_VERT)) {
1396 p->actions |= ActionMaxVert;
1397 } else if (atom == p->atom(_NET_WM_ACTION_MAXIMIZE_HORZ)) {
1398 p->actions |= ActionMaxHoriz;
1399 } else if (atom == p->atom(_NET_WM_ACTION_FULLSCREEN)) {
1400 p->actions |= ActionFullScreen;
1401 } else if (atom == p->atom(_NET_WM_ACTION_CHANGE_DESKTOP)) {
1402 p->actions |= ActionChangeDesktop;
1403 } else if (atom == p->atom(_NET_WM_ACTION_CLOSE)) {
1404 p->actions |= ActionClose;
1405 }
1406
1407 else if (atom == p->atom(_NET_FRAME_EXTENTS)) {
1408 p->properties |= WMFrameExtents;
1409 } else if (atom == p->atom(_KDE_NET_WM_FRAME_STRUT)) {
1410 p->properties |= WMFrameExtents;
1411 } else if (atom == p->atom(_NET_WM_FRAME_OVERLAP)) {
1412 p->properties2 |= WM2FrameOverlap;
1413 }
1414
1415 else if (atom == p->atom(_KDE_NET_WM_TEMPORARY_RULES)) {
1416 p->properties2 |= WM2KDETemporaryRules;
1417 } else if (atom == p->atom(_NET_WM_FULL_PLACEMENT)) {
1418 p->properties2 |= WM2FullPlacement;
1419 }
1420
1421 else if (atom == p->atom(_KDE_NET_WM_ACTIVITIES)) {
1422 p->properties2 |= WM2Activities;
1423 }
1424
1425 else if (atom == p->atom(_KDE_NET_WM_BLOCK_COMPOSITING) || atom == p->atom(_NET_WM_BYPASS_COMPOSITOR)) {
1426 p->properties2 |= WM2BlockCompositing;
1427 }
1428
1429 else if (atom == p->atom(_KDE_NET_WM_SHADOW)) {
1430 p->properties2 |= WM2KDEShadow;
1431 }
1432
1433 else if (atom == p->atom(_NET_WM_OPAQUE_REGION)) {
1434 p->properties2 |= WM2OpaqueRegion;
1435 }
1436
1437 else if (atom == p->atom(_GTK_FRAME_EXTENTS)) {
1438 p->properties2 |= WM2GTKFrameExtents;
1439 }
1440
1441 else if (atom == p->atom(_GTK_SHOW_WINDOW_MENU)) {
1442 p->properties2 |= WM2GTKShowWindowMenu;
1443 }
1444
1445 else if (atom == p->atom(_KDE_NET_WM_APPMENU_OBJECT_PATH)) {
1446 p->properties2 |= WM2AppMenuObjectPath;
1447 }
1448
1449 else if (atom == p->atom(_KDE_NET_WM_APPMENU_SERVICE_NAME)) {
1450 p->properties2 |= WM2AppMenuServiceName;
1451 }
1452}
1453
1454void NETRootInfo::setActiveWindow(xcb_window_t window)
1455{
1456 setActiveWindow(window, FromUnknown, QX11Info::appUserTime(), XCB_WINDOW_NONE);
1457}
1458
1459void NETRootInfo::setActiveWindow(xcb_window_t window, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window)
1460{
1461#ifdef NETWMDEBUG
1462 fprintf(stderr, "NETRootInfo::setActiveWindow(0x%lx) (%s)\n", window, (p->role == WindowManager) ? "WM" : "Client");
1463#endif
1464
1465 if (p->role == WindowManager) {
1466 p->active = window;
1467
1468 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_ACTIVE_WINDOW), XCB_ATOM_WINDOW, 32, 1, (const void *)&(p->active));
1469 } else {
1470 const uint32_t data[5] = {src, timestamp, active_window, 0, 0};
1471
1472 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_NET_ACTIVE_WINDOW), data);
1473 }
1474}
1475
1476void NETRootInfo::setWorkArea(int desktop, const NETRect &workarea)
1477{
1478#ifdef NETWMDEBUG
1479 fprintf(stderr,
1480 "NETRootInfo::setWorkArea(%d, { %d, %d, %d, %d }) (%s)\n",
1481 desktop,
1482 workarea.pos.x,
1483 workarea.pos.y,
1484 workarea.size.width,
1485 workarea.size.height,
1486 (p->role == WindowManager) ? "WM" : "Client");
1487#endif
1488
1489 if (p->role != WindowManager || desktop < 1) {
1490 return;
1491 }
1492
1493 p->workarea[desktop - 1] = workarea;
1494
1495 uint32_t *wa = new uint32_t[p->number_of_desktops * 4];
1496 int i;
1497 int o;
1498 for (i = 0, o = 0; i < p->number_of_desktops; i++) {
1499 wa[o++] = p->workarea[i].pos.x;
1500 wa[o++] = p->workarea[i].pos.y;
1501 wa[o++] = p->workarea[i].size.width;
1502 wa[o++] = p->workarea[i].size.height;
1503 }
1504
1505 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_WORKAREA), XCB_ATOM_CARDINAL, 32, p->number_of_desktops * 4, (const void *)wa);
1506
1507 delete[] wa;
1508}
1509
1510void NETRootInfo::setVirtualRoots(const xcb_window_t *windows, unsigned int count)
1511{
1512 if (p->role != WindowManager) {
1513 return;
1514 }
1515
1516 p->virtual_roots_count = count;
1517 delete[] p->virtual_roots;
1518 p->virtual_roots = nwindup(windows, count);
1519
1520#ifdef NETWMDEBUG
1521 fprintf(stderr, "NETRootInfo::setVirtualRoots: setting list with %ld windows\n", p->virtual_roots_count);
1522#endif
1523
1524 xcb_change_property(p->conn,
1525 XCB_PROP_MODE_REPLACE,
1526 p->root,
1527 p->atom(_NET_VIRTUAL_ROOTS),
1528 XCB_ATOM_WINDOW,
1529 32,
1530 p->virtual_roots_count,
1531 (const void *)windows);
1532}
1533
1534void NETRootInfo::setDesktopLayout(NET::Orientation orientation, int columns, int rows, NET::DesktopLayoutCorner corner)
1535{
1536 p->desktop_layout_orientation = orientation;
1537 p->desktop_layout_columns = columns;
1538 p->desktop_layout_rows = rows;
1539 p->desktop_layout_corner = corner;
1540
1541#ifdef NETWMDEBUG
1542 fprintf(stderr, "NETRootInfo::setDesktopLayout: %d %d %d %d\n", orientation, columns, rows, corner);
1543#endif
1544
1545 uint32_t data[4];
1546 data[0] = orientation;
1547 data[1] = columns;
1548 data[2] = rows;
1549 data[3] = corner;
1550
1551 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_DESKTOP_LAYOUT), XCB_ATOM_CARDINAL, 32, 4, (const void *)data);
1552}
1553
1555{
1556 if (p->role == WindowManager) {
1557 uint32_t d = p->showing_desktop = showing;
1558 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->root, p->atom(_NET_SHOWING_DESKTOP), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
1559 } else {
1560 uint32_t data[5] = {uint32_t(showing ? 1 : 0), 0, 0, 0, 0};
1561 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->root, p->atom(_NET_SHOWING_DESKTOP), data);
1562 }
1563}
1564
1566{
1567 return p->showing_desktop;
1568}
1569
1570void NETRootInfo::closeWindowRequest(xcb_window_t window)
1571{
1572#ifdef NETWMDEBUG
1573 fprintf(stderr, "NETRootInfo::closeWindowRequest: requesting close for 0x%lx\n", window);
1574#endif
1575
1576 const uint32_t data[5] = {0, 0, 0, 0, 0};
1577 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_NET_CLOSE_WINDOW), data);
1578}
1579
1580void NETRootInfo::moveResizeRequest(xcb_window_t window, int x_root, int y_root, Direction direction, xcb_button_t button, RequestSource source)
1581{
1582#ifdef NETWMDEBUG
1583 fprintf(stderr,
1584 "NETRootInfo::moveResizeRequest: requesting resize/move for 0x%lx (%d, %d, %d, %d, %d)\n",
1585 window,
1586 x_root,
1587 y_root,
1588 direction,
1589 button,
1590 source);
1591#endif
1592
1593 const uint32_t data[5] = {uint32_t(x_root), uint32_t(y_root), uint32_t(direction), uint32_t(button), uint32_t(source)};
1594
1595 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_NET_WM_MOVERESIZE), data);
1596}
1597
1598void NETRootInfo::moveResizeWindowRequest(xcb_window_t window, int flags, int x, int y, int width, int height)
1599{
1600#ifdef NETWMDEBUG
1601 fprintf(stderr, "NETRootInfo::moveResizeWindowRequest: resizing/moving 0x%lx (%d, %d, %d, %d, %d)\n", window, flags, x, y, width, height);
1602#endif
1603
1604 const uint32_t data[5] = {uint32_t(flags), uint32_t(x), uint32_t(y), uint32_t(width), uint32_t(height)};
1605
1606 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_NET_MOVERESIZE_WINDOW), data);
1607}
1608
1609void NETRootInfo::showWindowMenuRequest(xcb_window_t window, int device_id, int x_root, int y_root)
1610{
1611#ifdef NETWMDEBUG
1612 fprintf(stderr, "NETRootInfo::showWindowMenuRequest: requesting menu for 0x%lx (%d, %d, %d)\n", window, device_id, x_root, y_root);
1613#endif
1614
1615 const uint32_t data[5] = {uint32_t(device_id), uint32_t(x_root), uint32_t(y_root), 0, 0};
1616 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_GTK_SHOW_WINDOW_MENU), data);
1617}
1618
1619void NETRootInfo::restackRequest(xcb_window_t window, RequestSource src, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
1620{
1621#ifdef NETWMDEBUG
1622 fprintf(stderr, "NETRootInfo::restackRequest: requesting restack for 0x%lx (%lx, %d)\n", window, above, detail);
1623#endif
1624
1625 const uint32_t data[5] = {uint32_t(src), uint32_t(above), uint32_t(detail), uint32_t(timestamp), 0};
1626
1627 send_client_message(p->conn, netwm_sendevent_mask, p->root, window, p->atom(_NET_RESTACK_WINDOW), data);
1628}
1629
1630void NETRootInfo::sendPing(xcb_window_t window, xcb_timestamp_t timestamp)
1631{
1632 if (p->role != WindowManager) {
1633 return;
1634 }
1635
1636#ifdef NETWMDEBUG
1637 fprintf(stderr, "NETRootInfo::setPing: window 0x%lx, timestamp %lu\n", window, timestamp);
1638#endif
1639
1640 const uint32_t data[5] = {p->atom(_NET_WM_PING), timestamp, window, 0, 0};
1641
1642 send_client_message(p->conn, 0, window, window, p->atom(WM_PROTOCOLS), data);
1643}
1644
1645// assignment operator
1646
1648{
1649#ifdef NETWMDEBUG
1650 fprintf(stderr, "NETRootInfo::operator=()\n");
1651#endif
1652
1653 if (p != rootinfo.p) {
1654 refdec_nri(p);
1655
1656 if (!p->ref) {
1657 delete p;
1658 }
1659 }
1660
1661 p = rootinfo.p;
1662 p->ref++;
1663
1664 return *this;
1665}
1666
1667NET::Properties NETRootInfo::event(xcb_generic_event_t *ev)
1668{
1669 NET::Properties props;
1670 event(ev, &props);
1671 return props;
1672}
1673
1674void NETRootInfo::event(xcb_generic_event_t *event, NET::Properties *properties, NET::Properties2 *properties2)
1675{
1676 NET::Properties dirty;
1677 NET::Properties2 dirty2;
1678 bool do_update = false;
1679 const uint8_t eventType = event->response_type & ~0x80;
1680
1681 // the window manager will be interested in client messages... no other
1682 // client should get these messages
1683 if (p->role == WindowManager && eventType == XCB_CLIENT_MESSAGE && reinterpret_cast<xcb_client_message_event_t *>(event)->format == 32) {
1684 xcb_client_message_event_t *message = reinterpret_cast<xcb_client_message_event_t *>(event);
1685#ifdef NETWMDEBUG
1686 fprintf(stderr, "NETRootInfo::event: handling ClientMessage event\n");
1687#endif
1688
1689 if (message->type == p->atom(_NET_NUMBER_OF_DESKTOPS)) {
1690 dirty = NumberOfDesktops;
1691
1692#ifdef NETWMDEBUG
1693 fprintf(stderr, "NETRootInfo::event: changeNumberOfDesktops(%ld)\n", message->data.data32[0]);
1694#endif
1695
1696 changeNumberOfDesktops(message->data.data32[0]);
1697 } else if (message->type == p->atom(_NET_DESKTOP_GEOMETRY)) {
1698 dirty = DesktopGeometry;
1699
1700 NETSize sz;
1701 sz.width = message->data.data32[0];
1702 sz.height = message->data.data32[1];
1703
1704#ifdef NETWMDEBUG
1705 fprintf(stderr, "NETRootInfo::event: changeDesktopGeometry( -- , { %d, %d })\n", sz.width, sz.height);
1706#endif
1707
1708 changeDesktopGeometry(~0, sz);
1709 } else if (message->type == p->atom(_NET_DESKTOP_VIEWPORT)) {
1710 dirty = DesktopViewport;
1711
1712 NETPoint pt;
1713 pt.x = message->data.data32[0];
1714 pt.y = message->data.data32[1];
1715
1716#ifdef NETWMDEBUG
1717 fprintf(stderr, "NETRootInfo::event: changeDesktopViewport(%d, { %d, %d })\n", p->current_desktop, pt.x, pt.y);
1718#endif
1719
1720 changeDesktopViewport(p->current_desktop, pt);
1721 } else if (message->type == p->atom(_NET_CURRENT_DESKTOP)) {
1722 dirty = CurrentDesktop;
1723
1724#ifdef NETWMDEBUG
1725 fprintf(stderr, "NETRootInfo::event: changeCurrentDesktop(%ld)\n", message->data.data32[0] + 1);
1726#endif
1727
1728 changeCurrentDesktop(message->data.data32[0] + 1);
1729 } else if (message->type == p->atom(_NET_ACTIVE_WINDOW)) {
1730 dirty = ActiveWindow;
1731
1732#ifdef NETWMDEBUG
1733 fprintf(stderr, "NETRootInfo::event: changeActiveWindow(0x%lx)\n", message->window);
1734#endif
1735
1737 xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME;
1738 xcb_window_t active_window = XCB_WINDOW_NONE;
1739 // make sure there aren't unknown values
1740 if (message->data.data32[0] >= FromUnknown && message->data.data32[0] <= FromTool) {
1741 src = static_cast<RequestSource>(message->data.data32[0]);
1742 timestamp = message->data.data32[1];
1743 active_window = message->data.data32[2];
1744 }
1745 changeActiveWindow(message->window, src, timestamp, active_window);
1746 } else if (message->type == p->atom(_NET_WM_MOVERESIZE)) {
1747#ifdef NETWMDEBUG
1748 fprintf(stderr,
1749 "NETRootInfo::event: moveResize(%ld, %ld, %ld, %ld, %ld, %ld)\n",
1750 message->window,
1751 message->data.data32[0],
1752 message->data.data32[1],
1753 message->data.data32[2],
1754 message->data.data32[3],
1755 message->data.data32[4]);
1756#endif
1757
1758 moveResize(message->window,
1759 message->data.data32[0],
1760 message->data.data32[1],
1761 message->data.data32[2],
1762 message->data.data32[3],
1763 RequestSource(message->data.data32[4]));
1764 } else if (message->type == p->atom(_NET_MOVERESIZE_WINDOW)) {
1765#ifdef NETWMDEBUG
1766 fprintf(stderr,
1767 "NETRootInfo::event: moveResizeWindow(%ld, %ld, %ld, %ld, %ld, %ld)\n",
1768 message->window,
1769 message->data.data32[0],
1770 message->data.data32[1],
1771 message->data.data32[2],
1772 message->data.data32[3],
1773 message->data.data32[4]);
1774#endif
1775
1776 moveResizeWindow(message->window,
1777 message->data.data32[0],
1778 message->data.data32[1],
1779 message->data.data32[2],
1780 message->data.data32[3],
1781 message->data.data32[4]);
1782 } else if (message->type == p->atom(_NET_CLOSE_WINDOW)) {
1783#ifdef NETWMDEBUG
1784 fprintf(stderr, "NETRootInfo::event: closeWindow(0x%lx)\n", message->window);
1785#endif
1786
1787 closeWindow(message->window);
1788 } else if (message->type == p->atom(_NET_RESTACK_WINDOW)) {
1789#ifdef NETWMDEBUG
1790 fprintf(stderr, "NETRootInfo::event: restackWindow(0x%lx)\n", message->window);
1791#endif
1792
1794 xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME;
1795 // make sure there aren't unknown values
1796 if (message->data.data32[0] >= FromUnknown && message->data.data32[0] <= FromTool) {
1797 src = static_cast<RequestSource>(message->data.data32[0]);
1798 timestamp = message->data.data32[3];
1799 }
1800 restackWindow(message->window, src, message->data.data32[1], message->data.data32[2], timestamp);
1801 } else if (message->type == p->atom(WM_PROTOCOLS) && (xcb_atom_t)message->data.data32[0] == p->atom(_NET_WM_PING)) {
1802 dirty = WMPing;
1803
1804#ifdef NETWMDEBUG
1805 fprintf(stderr, "NETRootInfo::event: gotPing(0x%lx,%lu)\n", message->window, message->data.data32[1]);
1806#endif
1807 gotPing(message->data.data32[2], message->data.data32[1]);
1808 } else if (message->type == p->atom(_NET_SHOWING_DESKTOP)) {
1809 dirty2 = WM2ShowingDesktop;
1810
1811#ifdef NETWMDEBUG
1812 fprintf(stderr, "NETRootInfo::event: changeShowingDesktop(%ld)\n", message->data.data32[0]);
1813#endif
1814
1815 changeShowingDesktop(message->data.data32[0]);
1816 } else if (message->type == p->atom(_GTK_SHOW_WINDOW_MENU)) {
1817#ifdef NETWMDEBUG
1818 fprintf(stderr,
1819 "NETRootInfo::event: showWindowMenu(%ld, %ld, %ld, %ld)\n",
1820 message->window,
1821 message->data.data32[0],
1822 message->data.data32[1],
1823 message->data.data32[2]);
1824#endif
1825
1826 showWindowMenu(message->window, message->data.data32[0], message->data.data32[1], message->data.data32[2]);
1827 }
1828 }
1829
1830 if (eventType == XCB_PROPERTY_NOTIFY) {
1831#ifdef NETWMDEBUG
1832 fprintf(stderr, "NETRootInfo::event: handling PropertyNotify event\n");
1833#endif
1834
1835 xcb_property_notify_event_t *pe = reinterpret_cast<xcb_property_notify_event_t *>(event);
1836 if (pe->atom == p->atom(_NET_CLIENT_LIST)) {
1837 dirty |= ClientList;
1838 } else if (pe->atom == p->atom(_NET_CLIENT_LIST_STACKING)) {
1839 dirty |= ClientListStacking;
1840 } else if (pe->atom == p->atom(_NET_DESKTOP_NAMES)) {
1841 dirty |= DesktopNames;
1842 } else if (pe->atom == p->atom(_NET_WORKAREA)) {
1843 dirty |= WorkArea;
1844 } else if (pe->atom == p->atom(_NET_NUMBER_OF_DESKTOPS)) {
1845 dirty |= NumberOfDesktops;
1846 } else if (pe->atom == p->atom(_NET_DESKTOP_GEOMETRY)) {
1847 dirty |= DesktopGeometry;
1848 } else if (pe->atom == p->atom(_NET_DESKTOP_VIEWPORT)) {
1849 dirty |= DesktopViewport;
1850 } else if (pe->atom == p->atom(_NET_CURRENT_DESKTOP)) {
1851 dirty |= CurrentDesktop;
1852 } else if (pe->atom == p->atom(_NET_ACTIVE_WINDOW)) {
1853 dirty |= ActiveWindow;
1854 } else if (pe->atom == p->atom(_NET_SHOWING_DESKTOP)) {
1855 dirty2 |= WM2ShowingDesktop;
1856 } else if (pe->atom == p->atom(_NET_SUPPORTED)) {
1857 dirty |= Supported; // update here?
1858 } else if (pe->atom == p->atom(_NET_SUPPORTING_WM_CHECK)) {
1859 dirty |= SupportingWMCheck;
1860 } else if (pe->atom == p->atom(_NET_VIRTUAL_ROOTS)) {
1861 dirty |= VirtualRoots;
1862 } else if (pe->atom == p->atom(_NET_DESKTOP_LAYOUT)) {
1863 dirty2 |= WM2DesktopLayout;
1864 }
1865
1866 do_update = true;
1867 }
1868
1869 if (do_update) {
1870 update(dirty, dirty2);
1871 }
1872
1873#ifdef NETWMDEBUG
1874 fprintf(stderr, "NETRootInfo::event: handled events, returning dirty = 0x%lx, 0x%lx\n", dirty, dirty2);
1875#endif
1876
1877 if (properties) {
1878 *properties = dirty;
1879 }
1880 if (properties2) {
1881 *properties2 = dirty2;
1882 }
1883}
1884
1885// private functions to update the data we keep
1886
1887void NETRootInfo::update(NET::Properties properties, NET::Properties2 properties2)
1888{
1889 NET::Properties dirty = properties & p->clientProperties;
1890 NET::Properties2 dirty2 = properties2 & p->clientProperties2;
1891
1892 xcb_get_property_cookie_t cookies[255];
1893 xcb_get_property_cookie_t wm_name_cookie;
1894 int c = 0;
1895
1896 // Send the property requests
1897 if (dirty & Supported) {
1898 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_SUPPORTED), XCB_ATOM_ATOM, 0, MAX_PROP_SIZE);
1899 }
1900
1901 if (dirty & ClientList) {
1902 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_CLIENT_LIST), XCB_ATOM_WINDOW, 0, MAX_PROP_SIZE);
1903 }
1904
1905 if (dirty & ClientListStacking) {
1906 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_CLIENT_LIST_STACKING), XCB_ATOM_WINDOW, 0, MAX_PROP_SIZE);
1907 }
1908
1909 if (dirty & NumberOfDesktops) {
1910 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_NUMBER_OF_DESKTOPS), XCB_ATOM_CARDINAL, 0, 1);
1911 }
1912
1913 if (dirty & DesktopGeometry) {
1914 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_DESKTOP_GEOMETRY), XCB_ATOM_CARDINAL, 0, 2);
1915 }
1916
1917 if (dirty & DesktopViewport) {
1918 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_DESKTOP_VIEWPORT), XCB_ATOM_CARDINAL, 0, MAX_PROP_SIZE);
1919 }
1920
1921 if (dirty & CurrentDesktop) {
1922 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_CURRENT_DESKTOP), XCB_ATOM_CARDINAL, 0, 1);
1923 }
1924
1925 if (dirty & DesktopNames) {
1926 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_DESKTOP_NAMES), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
1927 }
1928
1929 if (dirty & ActiveWindow) {
1930 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_ACTIVE_WINDOW), XCB_ATOM_WINDOW, 0, 1);
1931 }
1932
1933 if (dirty & WorkArea) {
1934 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_WORKAREA), XCB_ATOM_CARDINAL, 0, MAX_PROP_SIZE);
1935 }
1936
1937 if (dirty & SupportingWMCheck) {
1938 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_SUPPORTING_WM_CHECK), XCB_ATOM_WINDOW, 0, 1);
1939 }
1940
1941 if (dirty & VirtualRoots) {
1942 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, 0, 1);
1943 }
1944
1945 if (dirty2 & WM2DesktopLayout) {
1946 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_DESKTOP_LAYOUT), XCB_ATOM_CARDINAL, 0, MAX_PROP_SIZE);
1947 }
1948
1949 if (dirty2 & WM2ShowingDesktop) {
1950 cookies[c++] = xcb_get_property(p->conn, false, p->root, p->atom(_NET_SHOWING_DESKTOP), XCB_ATOM_CARDINAL, 0, 1);
1951 }
1952
1953 // Get the replies
1954 c = 0;
1955
1956 if (dirty & Supported) {
1957 // Only in Client mode
1958 p->properties = NET::Properties();
1959 p->properties2 = NET::Properties2();
1960 p->windowTypes = NET::WindowTypes();
1961 p->states = NET::States();
1962 p->actions = NET::Actions();
1963
1964 const QList<xcb_atom_t> atoms = get_array_reply<xcb_atom_t>(p->conn, cookies[c++], XCB_ATOM_ATOM);
1965 for (const xcb_atom_t atom : atoms) {
1966 updateSupportedProperties(atom);
1967 }
1968 }
1969
1970 if (dirty & ClientList) {
1971 QList<xcb_window_t> clientsToRemove;
1972 QList<xcb_window_t> clientsToAdd;
1973
1974 QList<xcb_window_t> clients = get_array_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_WINDOW);
1975 std::sort(clients.begin(), clients.end());
1976
1977 if (p->clients) {
1978 if (p->role == Client) {
1979 int new_index = 0;
1980 int old_index = 0;
1981 int old_count = p->clients_count;
1982 int new_count = clients.count();
1983
1984 while (old_index < old_count || new_index < new_count) {
1985 if (old_index == old_count) {
1986 clientsToAdd.append(clients[new_index++]);
1987 } else if (new_index == new_count) {
1988 clientsToRemove.append(p->clients[old_index++]);
1989 } else {
1990 if (p->clients[old_index] < clients[new_index]) {
1991 clientsToRemove.append(p->clients[old_index++]);
1992 } else if (clients[new_index] < p->clients[old_index]) {
1993 clientsToAdd.append(clients[new_index++]);
1994 } else {
1995 new_index++;
1996 old_index++;
1997 }
1998 }
1999 }
2000 }
2001
2002 delete[] p->clients;
2003 p->clients = nullptr;
2004 } else {
2005#ifdef NETWMDEBUG
2006 fprintf(stderr, "NETRootInfo::update: client list null, creating\n");
2007#endif
2008
2009 clientsToAdd.reserve(clients.count());
2010 for (int i = 0; i < clients.count(); i++) {
2011 clientsToAdd.append(clients[i]);
2012 }
2013 }
2014
2015 if (!clients.isEmpty()) {
2016 p->clients_count = clients.count();
2017 p->clients = new xcb_window_t[clients.count()];
2018 for (int i = 0; i < clients.count(); i++) {
2019 p->clients[i] = clients.at(i);
2020 }
2021 }
2022
2023#ifdef NETWMDEBUG
2024 fprintf(stderr, "NETRootInfo::update: client list updated (%ld clients)\n", p->clients_count);
2025#endif
2026
2027 for (int i = 0; i < clientsToRemove.size(); ++i) {
2028 removeClient(clientsToRemove.at(i));
2029 }
2030
2031 for (int i = 0; i < clientsToAdd.size(); ++i) {
2032 addClient(clientsToAdd.at(i));
2033 }
2034 }
2035
2036 if (dirty & ClientListStacking) {
2037 p->stacking_count = 0;
2038
2039 delete[] p->stacking;
2040 p->stacking = nullptr;
2041
2042 const QList<xcb_window_t> wins = get_array_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_WINDOW);
2043
2044 if (!wins.isEmpty()) {
2045 p->stacking_count = wins.count();
2046 p->stacking = new xcb_window_t[wins.count()];
2047 for (int i = 0; i < wins.count(); i++) {
2048 p->stacking[i] = wins.at(i);
2049 }
2050 }
2051
2052#ifdef NETWMDEBUG
2053 fprintf(stderr, "NETRootInfo::update: client stacking updated (%ld clients)\n", p->stacking_count);
2054#endif
2055 }
2056
2057 if (dirty & NumberOfDesktops) {
2058 p->number_of_desktops = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0);
2059
2060#ifdef NETWMDEBUG
2061 fprintf(stderr, "NETRootInfo::update: number of desktops = %d\n", p->number_of_desktops);
2062#endif
2063 }
2064
2065 if (dirty & DesktopGeometry) {
2066 p->geometry = p->rootSize;
2067
2068 const QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
2069 if (data.count() == 2) {
2070 p->geometry.width = data.at(0);
2071 p->geometry.height = data.at(1);
2072 }
2073
2074#ifdef NETWMDEBUG
2075 fprintf(stderr, "NETRootInfo::update: desktop geometry updated\n");
2076#endif
2077 }
2078
2079 if (dirty & DesktopViewport) {
2080 for (int i = 0; i < p->viewport.size(); i++) {
2081 p->viewport[i].x = p->viewport[i].y = 0;
2082 }
2083
2084 const QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
2085
2086 if (data.count() >= 2) {
2087 int n = data.count() / 2;
2088 for (int d = 0, i = 0; d < n; d++) {
2089 p->viewport[d].x = data[i++];
2090 p->viewport[d].y = data[i++];
2091 }
2092
2093#ifdef NETWMDEBUG
2094 fprintf(stderr, "NETRootInfo::update: desktop viewport array updated (%d entries)\n", p->viewport.size());
2095
2096 if (data.count() % 2 != 0) {
2097 fprintf(stderr,
2098 "NETRootInfo::update(): desktop viewport array "
2099 "size not a multiple of 2\n");
2100 }
2101#endif
2102 }
2103 }
2104
2105 if (dirty & CurrentDesktop) {
2106 p->current_desktop = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0) + 1;
2107
2108#ifdef NETWMDEBUG
2109 fprintf(stderr, "NETRootInfo::update: current desktop = %d\n", p->current_desktop);
2110#endif
2111 }
2112
2113 if (dirty & DesktopNames) {
2114 for (int i = 0; i < p->desktop_names.size(); ++i) {
2115 delete[] p->desktop_names[i];
2116 }
2117
2118 p->desktop_names.reset();
2119
2120 const QList<QByteArray> names = get_stringlist_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
2121 for (int i = 0; i < names.count(); i++) {
2122 p->desktop_names[i] = nstrndup(names[i].constData(), names[i].length());
2123 }
2124
2125#ifdef NETWMDEBUG
2126 fprintf(stderr, "NETRootInfo::update: desktop names array updated (%d entries)\n", p->desktop_names.size());
2127#endif
2128 }
2129
2130 if (dirty & ActiveWindow) {
2131 p->active = get_value_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_WINDOW, 0);
2132
2133#ifdef NETWMDEBUG
2134 fprintf(stderr, "NETRootInfo::update: active window = 0x%lx\n", p->active);
2135#endif
2136 }
2137
2138 if (dirty & WorkArea) {
2139 p->workarea.reset();
2140
2141 const QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
2142 if (data.count() == p->number_of_desktops * 4) {
2143 for (int i = 0, j = 0; i < p->number_of_desktops; i++) {
2144 p->workarea[i].pos.x = data[j++];
2145 p->workarea[i].pos.y = data[j++];
2146 p->workarea[i].size.width = data[j++];
2147 p->workarea[i].size.height = data[j++];
2148 }
2149 }
2150
2151#ifdef NETWMDEBUG
2152 fprintf(stderr, "NETRootInfo::update: work area array updated (%d entries)\n", p->workarea.size());
2153#endif
2154 }
2155
2156 if (dirty & SupportingWMCheck) {
2157 delete[] p->name;
2158 p->name = nullptr;
2159
2160 p->supportwindow = get_value_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_WINDOW, 0);
2161
2162 // We'll get the reply for this request at the bottom of this function,
2163 // after we've processing the other pending replies
2164 if (p->supportwindow) {
2165 wm_name_cookie = xcb_get_property(p->conn, false, p->supportwindow, p->atom(_NET_WM_NAME), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
2166 }
2167 }
2168
2169 if (dirty & VirtualRoots) {
2170 p->virtual_roots_count = 0;
2171
2172 delete[] p->virtual_roots;
2173 p->virtual_roots = nullptr;
2174
2175 const QList<xcb_window_t> wins = get_array_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
2176
2177 if (!wins.isEmpty()) {
2178 p->virtual_roots_count = wins.count();
2179 p->virtual_roots = new xcb_window_t[wins.count()];
2180 for (int i = 0; i < wins.count(); i++) {
2181 p->virtual_roots[i] = wins.at(i);
2182 }
2183 }
2184
2185#ifdef NETWMDEBUG
2186 fprintf(stderr, "NETRootInfo::updated: virtual roots updated (%ld windows)\n", p->virtual_roots_count);
2187#endif
2188 }
2189
2190 if (dirty2 & WM2DesktopLayout) {
2191 p->desktop_layout_orientation = OrientationHorizontal;
2192 p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
2193 p->desktop_layout_columns = p->desktop_layout_rows = 0;
2194
2195 const QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
2196
2197 if (data.count() >= 4 && data[3] <= 3) {
2198 p->desktop_layout_corner = (NET::DesktopLayoutCorner)data[3];
2199 }
2200
2201 if (data.count() >= 3) {
2202 if (data[0] <= 1) {
2203 p->desktop_layout_orientation = (NET::Orientation)data[0];
2204 }
2205
2206 p->desktop_layout_columns = data[1];
2207 p->desktop_layout_rows = data[2];
2208 }
2209
2210#ifdef NETWMDEBUG
2211 fprintf(stderr,
2212 "NETRootInfo::updated: desktop layout updated (%d %d %d %d)\n",
2213 p->desktop_layout_orientation,
2214 p->desktop_layout_columns,
2215 p->desktop_layout_rows,
2216 p->desktop_layout_corner);
2217#endif
2218 }
2219
2220 if (dirty2 & WM2ShowingDesktop) {
2221 const uint32_t val = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0);
2222 p->showing_desktop = bool(val);
2223
2224#ifdef NETWMDEBUG
2225 fprintf(stderr, "NETRootInfo::update: showing desktop = %d\n", p->showing_desktop);
2226#endif
2227 }
2228
2229 if ((dirty & SupportingWMCheck) && p->supportwindow) {
2230 const QByteArray ba = get_string_reply(p->conn, wm_name_cookie, p->atom(UTF8_STRING));
2231 if (ba.length() > 0) {
2232 p->name = nstrndup((const char *)ba.constData(), ba.length());
2233 }
2234
2235#ifdef NETWMDEBUG
2236 fprintf(stderr, "NETRootInfo::update: supporting window manager = '%s'\n", p->name);
2237#endif
2238 }
2239}
2240
2241xcb_connection_t *NETRootInfo::xcbConnection() const
2242{
2243 return p->conn;
2244}
2245
2246xcb_window_t NETRootInfo::rootWindow() const
2247{
2248 return p->root;
2249}
2250
2251xcb_window_t NETRootInfo::supportWindow() const
2252{
2253 return p->supportwindow;
2254}
2255
2256const char *NETRootInfo::wmName() const
2257{
2258 return p->name;
2259}
2260
2262{
2263 return p->properties;
2264}
2265
2267{
2268 return p->properties2;
2269}
2270
2272{
2273 return p->states;
2274}
2275
2277{
2278 return p->windowTypes;
2279}
2280
2282{
2283 return p->actions;
2284}
2285
2287{
2288 return p->role == WindowManager ? p->properties : p->clientProperties;
2289}
2290
2292{
2293 return p->role == WindowManager ? p->properties2 : p->clientProperties2;
2294}
2295
2297{
2298 return p->role == WindowManager ? p->states : NET::States();
2299}
2300
2302{
2303 return p->role == WindowManager ? p->windowTypes : NET::WindowTypes();
2304}
2305
2307{
2308 return p->role == WindowManager ? p->actions : NET::Actions();
2309}
2310
2312{
2313 if (p->role != WindowManager) {
2314 return;
2315 }
2316
2317 if (on && !isSupported(property)) {
2318 p->properties |= property;
2319 setSupported();
2320 } else if (!on && isSupported(property)) {
2321 p->properties &= ~property;
2322 setSupported();
2323 }
2324}
2325
2327{
2328 if (p->role != WindowManager) {
2329 return;
2330 }
2331
2332 if (on && !isSupported(property)) {
2333 p->properties2 |= property;
2334 setSupported();
2335 } else if (!on && isSupported(property)) {
2336 p->properties2 &= ~property;
2337 setSupported();
2338 }
2339}
2340
2342{
2343 if (p->role != WindowManager) {
2344 return;
2345 }
2346
2347 if (on && !isSupported(property)) {
2348 p->windowTypes |= property;
2349 setSupported();
2350 } else if (!on && isSupported(property)) {
2351 p->windowTypes &= ~property;
2352 setSupported();
2353 }
2354}
2355
2357{
2358 if (p->role != WindowManager) {
2359 return;
2360 }
2361
2362 if (on && !isSupported(property)) {
2363 p->states |= property;
2364 setSupported();
2365 } else if (!on && isSupported(property)) {
2366 p->states &= ~property;
2367 setSupported();
2368 }
2369}
2370
2372{
2373 if (p->role != WindowManager) {
2374 return;
2375 }
2376
2377 if (on && !isSupported(property)) {
2378 p->actions |= property;
2379 setSupported();
2380 } else if (!on && isSupported(property)) {
2381 p->actions &= ~property;
2382 setSupported();
2383 }
2384}
2385
2387{
2388 return p->properties & property;
2389}
2390
2392{
2393 return p->properties2 & property;
2394}
2395
2397{
2398 return p->windowTypes & type;
2399}
2400
2402{
2403 return p->states & state;
2404}
2405
2407{
2408 return p->actions & action;
2409}
2410
2411const xcb_window_t *NETRootInfo::clientList() const
2412{
2413 return p->clients;
2414}
2415
2417{
2418 return p->clients_count;
2419}
2420
2421const xcb_window_t *NETRootInfo::clientListStacking() const
2422{
2423 return p->stacking;
2424}
2425
2427{
2428 return p->stacking_count;
2429}
2430
2432{
2433 return p->geometry.width != 0 ? p->geometry : p->rootSize;
2434}
2435
2437{
2438 if (desktop < 1) {
2439 NETPoint pt; // set to (0,0)
2440 return pt;
2441 }
2442
2443 return p->viewport[desktop - 1];
2444}
2445
2447{
2448 if (desktop < 1) {
2449 NETRect rt;
2450 return rt;
2451 }
2452
2453 return p->workarea[desktop - 1];
2454}
2455
2456const char *NETRootInfo::desktopName(int desktop) const
2457{
2458 if (desktop < 1) {
2459 return nullptr;
2460 }
2461
2462 return p->desktop_names[desktop - 1];
2463}
2464
2465const xcb_window_t *NETRootInfo::virtualRoots() const
2466{
2467 return p->virtual_roots;
2468}
2469
2471{
2472 return p->virtual_roots_count;
2473}
2474
2476{
2477 return p->desktop_layout_orientation;
2478}
2479
2481{
2482 return QSize(p->desktop_layout_columns, p->desktop_layout_rows);
2483}
2484
2486{
2487 return p->desktop_layout_corner;
2488}
2489
2490int NETRootInfo::numberOfDesktops(bool ignore_viewport) const
2491{
2492 if (!ignore_viewport && KX11Extras::mapViewport()) {
2494 }
2495 return p->number_of_desktops == 0 ? 1 : p->number_of_desktops;
2496}
2497
2498int NETRootInfo::currentDesktop(bool ignore_viewport) const
2499{
2500 if (!ignore_viewport && KX11Extras::mapViewport()) {
2502 }
2503 return p->current_desktop == 0 ? 1 : p->current_desktop;
2504}
2505
2506xcb_window_t NETRootInfo::activeWindow() const
2507{
2508 return p->active;
2509}
2510
2511// NETWinInfo stuffs
2512
2513const int NETWinInfo::OnAllDesktops = NET::OnAllDesktops;
2514
2515NETWinInfo::NETWinInfo(xcb_connection_t *connection,
2516 xcb_window_t window,
2517 xcb_window_t rootWindow,
2518 NET::Properties properties,
2519 NET::Properties2 properties2,
2520 Role role)
2521{
2522#ifdef NETWMDEBUG
2523 fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n", (role == WindowManager) ? "WindowManager" : "Client");
2524#endif
2525
2526 p = new NETWinInfoPrivate;
2527 p->ref = 1;
2528 p->atoms = atomsForConnection(connection);
2529
2530 p->conn = connection;
2531 p->window = window;
2532 p->root = rootWindow;
2533 p->mapping_state = Withdrawn;
2534 p->mapping_state_dirty = true;
2535 p->state = NET::States();
2536 p->types[0] = Unknown;
2537 p->name = (char *)nullptr;
2538 p->visible_name = (char *)nullptr;
2539 p->icon_name = (char *)nullptr;
2540 p->visible_icon_name = (char *)nullptr;
2541 p->desktop = p->pid = 0;
2542 p->handled_icons = false;
2543 p->user_time = -1U;
2544 p->startup_id = nullptr;
2545 p->transient_for = XCB_NONE;
2546 p->opacity = 0xffffffffU;
2547 p->window_group = XCB_NONE;
2548 p->icon_pixmap = XCB_PIXMAP_NONE;
2549 p->icon_mask = XCB_PIXMAP_NONE;
2550 p->allowed_actions = NET::Actions();
2551 p->has_net_support = false;
2552 p->class_class = (char *)nullptr;
2553 p->class_name = (char *)nullptr;
2554 p->window_role = (char *)nullptr;
2555 p->client_machine = (char *)nullptr;
2556 p->icon_sizes = nullptr;
2557 p->activities = (char *)nullptr;
2558 p->desktop_file = nullptr;
2559 p->gtk_application_id = nullptr;
2560 p->appmenu_object_path = nullptr;
2561 p->appmenu_service_name = nullptr;
2562 p->blockCompositing = false;
2563 p->urgency = false;
2564 p->input = true;
2565 p->initialMappingState = NET::Withdrawn;
2566 p->protocols = NET::NoProtocol;
2567
2568 // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
2569 // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
2570 // p->frame_strut.bottom = 0;
2571
2572 p->properties = properties;
2573 p->properties2 = properties2;
2574
2575 p->icon_count = 0;
2576
2577 p->role = role;
2578
2579 update(p->properties, p->properties2);
2580}
2581
2583{
2584 p = wininfo.p;
2585 p->ref++;
2586}
2587
2589{
2590 refdec_nwi(p);
2591
2592 if (!p->ref) {
2593 delete p;
2594 }
2595}
2596
2597// assignment operator
2598
2600{
2601#ifdef NETWMDEBUG
2602 fprintf(stderr, "NETWinInfo::operator=()\n");
2603#endif
2604
2605 if (p != wininfo.p) {
2606 refdec_nwi(p);
2607
2608 if (!p->ref) {
2609 delete p;
2610 }
2611 }
2612
2613 p = wininfo.p;
2614 p->ref++;
2615
2616 return *this;
2617}
2618
2619void NETWinInfo::setIcon(NETIcon icon, bool replace)
2620{
2621 setIconInternal(p->icons, p->icon_count, p->atom(_NET_WM_ICON), icon, replace);
2622}
2623
2624void NETWinInfo::setIconInternal(NETRArray<NETIcon> &icons, int &icon_count, xcb_atom_t property, NETIcon icon, bool replace)
2625{
2626 if (p->role != Client) {
2627 return;
2628 }
2629
2630 if (replace) {
2631 for (int i = 0; i < icons.size(); i++) {
2632 delete[] icons[i].data;
2633
2634 icons[i].data = nullptr;
2635 icons[i].size.width = 0;
2636 icons[i].size.height = 0;
2637 }
2638
2639 icon_count = 0;
2640 }
2641
2642 // assign icon
2643 icons[icon_count] = icon;
2644 icon_count++;
2645
2646 // do a deep copy, we want to own the data
2647 NETIcon &ni = icons[icon_count - 1];
2648 int sz = ni.size.width * ni.size.height;
2649 uint32_t *d = new uint32_t[sz];
2650 ni.data = (unsigned char *)d;
2651 memcpy(d, icon.data, sz * sizeof(uint32_t));
2652
2653 // compute property length
2654 int proplen = 0;
2655 for (int i = 0; i < icon_count; i++) {
2656 proplen += 2 + (icons[i].size.width * icons[i].size.height);
2657 }
2658
2659 uint32_t *prop = new uint32_t[proplen];
2660 uint32_t *pprop = prop;
2661 for (int i = 0; i < icon_count; i++) {
2662 // copy size into property
2663 *pprop++ = icons[i].size.width;
2664 *pprop++ = icons[i].size.height;
2665
2666 // copy data into property
2667 sz = (icons[i].size.width * icons[i].size.height);
2668 uint32_t *d32 = (uint32_t *)icons[i].data;
2669 for (int j = 0; j < sz; j++) {
2670 *pprop++ = *d32++;
2671 }
2672 }
2673
2674 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, property, XCB_ATOM_CARDINAL, 32, proplen, (const void *)prop);
2675
2676 delete[] prop;
2677 delete[] p->icon_sizes;
2678 p->icon_sizes = nullptr;
2679}
2680
2682{
2683 if (p->role != Client) {
2684 return;
2685 }
2686
2687 const qreal scaleFactor = qApp->devicePixelRatio();
2688 geometry.pos.x *= scaleFactor;
2689 geometry.pos.y *= scaleFactor;
2690 geometry.size.width *= scaleFactor;
2691 geometry.size.height *= scaleFactor;
2692
2693 p->icon_geom = geometry;
2694
2695 if (geometry.size.width == 0) { // Empty
2696 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_ICON_GEOMETRY));
2697 } else {
2698 uint32_t data[4];
2699 data[0] = geometry.pos.x;
2700 data[1] = geometry.pos.y;
2701 data[2] = geometry.size.width;
2702 data[3] = geometry.size.height;
2703
2704 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_ICON_GEOMETRY), XCB_ATOM_CARDINAL, 32, 4, (const void *)data);
2705 }
2706}
2707
2709{
2710 if (p->role != Client) {
2711 return;
2712 }
2713
2714 p->extended_strut = extended_strut;
2715
2716 uint32_t data[12];
2717 data[0] = extended_strut.left_width;
2718 data[1] = extended_strut.right_width;
2719 data[2] = extended_strut.top_width;
2720 data[3] = extended_strut.bottom_width;
2721 data[4] = extended_strut.left_start;
2722 data[5] = extended_strut.left_end;
2723 data[6] = extended_strut.right_start;
2724 data[7] = extended_strut.right_end;
2725 data[8] = extended_strut.top_start;
2726 data[9] = extended_strut.top_end;
2727 data[10] = extended_strut.bottom_start;
2728 data[11] = extended_strut.bottom_end;
2729
2730 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_STRUT_PARTIAL), XCB_ATOM_CARDINAL, 32, 12, (const void *)data);
2731}
2732
2734{
2735 if (p->role != Client) {
2736 return;
2737 }
2738
2739 p->strut = strut;
2740
2741 uint32_t data[4];
2742 data[0] = strut.left;
2743 data[1] = strut.right;
2744 data[2] = strut.top;
2745 data[3] = strut.bottom;
2746
2747 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_STRUT), XCB_ATOM_CARDINAL, 32, 4, (const void *)data);
2748}
2749
2751{
2752 if (p->role == Client) {
2753 const uint32_t data[5] = {uint32_t(topology.top), uint32_t(topology.bottom), uint32_t(topology.left), uint32_t(topology.right), 1};
2754
2755 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->window, p->atom(_NET_WM_FULLSCREEN_MONITORS), data);
2756 } else {
2757 p->fullscreen_monitors = topology;
2758
2759 uint32_t data[4];
2760 data[0] = topology.top;
2761 data[1] = topology.bottom;
2762 data[2] = topology.left;
2763 data[3] = topology.right;
2764
2765 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_FULLSCREEN_MONITORS), XCB_ATOM_CARDINAL, 32, 4, (const void *)data);
2766 }
2767}
2768
2770{
2771 if (p->mapping_state_dirty) {
2772 updateWMState();
2773 }
2774
2775 // setState() needs to know the current state, so read it even if not requested
2776 if ((p->properties & WMState) == 0) {
2777 p->properties |= WMState;
2778
2779 update(WMState);
2780
2781 p->properties &= ~WMState;
2782 }
2783
2784 if (p->role == Client && p->mapping_state != Withdrawn) {
2785#ifdef NETWMDEBUG
2786 fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n", state, mask);
2787#endif // NETWMDEBUG
2788
2789 KXcbEvent<xcb_client_message_event_t> event;
2790 event.response_type = XCB_CLIENT_MESSAGE;
2791 event.format = 32;
2792 event.sequence = 0;
2793 event.window = p->window;
2794 event.type = p->atom(_NET_WM_STATE);
2795 event.data.data32[3] = 0;
2796 event.data.data32[4] = 0;
2797
2798 if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
2799 event.data.data32[0] = (state & Modal) ? 1 : 0;
2800 event.data.data32[1] = p->atom(_NET_WM_STATE_MODAL);
2801 event.data.data32[2] = 0l;
2802
2803 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2804 }
2805
2806 if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
2807 event.data.data32[0] = (state & Sticky) ? 1 : 0;
2808 event.data.data32[1] = p->atom(_NET_WM_STATE_STICKY);
2809 event.data.data32[2] = 0l;
2810
2811 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2812 }
2813
2814 if ((mask & Max) && (((p->state & mask) & Max) != (state & Max))) {
2815 NET::States wishstate = (p->state & ~mask) | (state & mask);
2816 if (((wishstate & MaxHoriz) != (p->state & MaxHoriz)) && ((wishstate & MaxVert) != (p->state & MaxVert))) {
2817 if ((wishstate & Max) == Max) {
2818 event.data.data32[0] = 1;
2819 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
2820 event.data.data32[2] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
2821 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2822 } else if ((wishstate & Max) == 0) {
2823 event.data.data32[0] = 0;
2824 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
2825 event.data.data32[2] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
2826 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2827 } else {
2828 event.data.data32[0] = (wishstate & MaxHoriz) ? 1 : 0;
2829 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
2830 event.data.data32[2] = 0;
2831 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2832
2833 event.data.data32[0] = (wishstate & MaxVert) ? 1 : 0;
2834 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
2835 event.data.data32[2] = 0;
2836 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2837 }
2838 } else if ((wishstate & MaxVert) != (p->state & MaxVert)) {
2839 event.data.data32[0] = (wishstate & MaxVert) ? 1 : 0;
2840 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
2841 event.data.data32[2] = 0;
2842
2843 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2844 } else if ((wishstate & MaxHoriz) != (p->state & MaxHoriz)) {
2845 event.data.data32[0] = (wishstate & MaxHoriz) ? 1 : 0;
2846 event.data.data32[1] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
2847 event.data.data32[2] = 0;
2848
2849 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2850 }
2851 }
2852
2853 if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
2854 event.data.data32[0] = (state & Shaded) ? 1 : 0;
2855 event.data.data32[1] = p->atom(_NET_WM_STATE_SHADED);
2856 event.data.data32[2] = 0l;
2857
2858 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2859 }
2860
2861 if ((mask & SkipTaskbar) && ((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
2862 event.data.data32[0] = (state & SkipTaskbar) ? 1 : 0;
2863 event.data.data32[1] = p->atom(_NET_WM_STATE_SKIP_TASKBAR);
2864 event.data.data32[2] = 0l;
2865
2866 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2867 }
2868
2869 if ((mask & SkipPager) && ((p->state & SkipPager) != (state & SkipPager))) {
2870 event.data.data32[0] = (state & SkipPager) ? 1 : 0;
2871 event.data.data32[1] = p->atom(_NET_WM_STATE_SKIP_PAGER);
2872 event.data.data32[2] = 0l;
2873
2874 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2875 }
2876
2877 if ((mask & SkipSwitcher) && ((p->state & SkipSwitcher) != (state & SkipSwitcher))) {
2878 event.data.data32[0] = (state & SkipSwitcher) ? 1 : 0;
2879 event.data.data32[1] = p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER);
2880 event.data.data32[2] = 0l;
2881
2882 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2883 }
2884
2885 if ((mask & Hidden) && ((p->state & Hidden) != (state & Hidden))) {
2886 event.data.data32[0] = (state & Hidden) ? 1 : 0;
2887 event.data.data32[1] = p->atom(_NET_WM_STATE_HIDDEN);
2888 event.data.data32[2] = 0l;
2889
2890 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2891 }
2892
2893 if ((mask & FullScreen) && ((p->state & FullScreen) != (state & FullScreen))) {
2894 event.data.data32[0] = (state & FullScreen) ? 1 : 0;
2895 event.data.data32[1] = p->atom(_NET_WM_STATE_FULLSCREEN);
2896 event.data.data32[2] = 0l;
2897
2898 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2899 }
2900
2901 if ((mask & KeepAbove) && ((p->state & KeepAbove) != (state & KeepAbove))) {
2902 event.data.data32[0] = (state & KeepAbove) ? 1 : 0;
2903 event.data.data32[1] = p->atom(_NET_WM_STATE_ABOVE);
2904 event.data.data32[2] = 0l;
2905
2906 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2907
2908 // deprecated variant
2909 event.data.data32[0] = (state & KeepAbove) ? 1 : 0;
2910 event.data.data32[1] = p->atom(_NET_WM_STATE_STAYS_ON_TOP);
2911 event.data.data32[2] = 0l;
2912
2913 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2914 }
2915
2916 if ((mask & KeepBelow) && ((p->state & KeepBelow) != (state & KeepBelow))) {
2917 event.data.data32[0] = (state & KeepBelow) ? 1 : 0;
2918 event.data.data32[1] = p->atom(_NET_WM_STATE_BELOW);
2919 event.data.data32[2] = 0l;
2920
2921 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2922 }
2923
2924 if ((mask & DemandsAttention) && ((p->state & DemandsAttention) != (state & DemandsAttention))) {
2925 event.data.data32[0] = (state & DemandsAttention) ? 1 : 0;
2926 event.data.data32[1] = p->atom(_NET_WM_STATE_DEMANDS_ATTENTION);
2927 event.data.data32[2] = 0l;
2928
2929 xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, event.buffer());
2930 }
2931
2932 // Focused is not added here as it is effectively "read only" set by the WM, a client setting it would be silly
2933 } else {
2934 p->state &= ~mask;
2935 p->state |= state;
2936
2937 uint32_t data[50];
2938 int count = 0;
2939
2940 // Hints
2941 if (p->state & Modal) {
2942 data[count++] = p->atom(_NET_WM_STATE_MODAL);
2943 }
2944 if (p->state & MaxVert) {
2945 data[count++] = p->atom(_NET_WM_STATE_MAXIMIZED_VERT);
2946 }
2947 if (p->state & MaxHoriz) {
2948 data[count++] = p->atom(_NET_WM_STATE_MAXIMIZED_HORZ);
2949 }
2950 if (p->state & Shaded) {
2951 data[count++] = p->atom(_NET_WM_STATE_SHADED);
2952 }
2953 if (p->state & Hidden) {
2954 data[count++] = p->atom(_NET_WM_STATE_HIDDEN);
2955 }
2956 if (p->state & FullScreen) {
2957 data[count++] = p->atom(_NET_WM_STATE_FULLSCREEN);
2958 }
2959 if (p->state & DemandsAttention) {
2960 data[count++] = p->atom(_NET_WM_STATE_DEMANDS_ATTENTION);
2961 }
2962 if (p->state & Focused) {
2963 data[count++] = p->atom(_NET_WM_STATE_FOCUSED);
2964 }
2965
2966 // Policy
2967 if (p->state & KeepAbove) {
2968 data[count++] = p->atom(_NET_WM_STATE_ABOVE);
2969 // deprecated variant
2970 data[count++] = p->atom(_NET_WM_STATE_STAYS_ON_TOP);
2971 }
2972 if (p->state & KeepBelow) {
2973 data[count++] = p->atom(_NET_WM_STATE_BELOW);
2974 }
2975 if (p->state & Sticky) {
2976 data[count++] = p->atom(_NET_WM_STATE_STICKY);
2977 }
2978 if (p->state & SkipTaskbar) {
2979 data[count++] = p->atom(_NET_WM_STATE_SKIP_TASKBAR);
2980 }
2981 if (p->state & SkipPager) {
2982 data[count++] = p->atom(_NET_WM_STATE_SKIP_PAGER);
2983 }
2984 if (p->state & SkipSwitcher) {
2985 data[count++] = p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER);
2986 }
2987
2988#ifdef NETWMDEBUG
2989 fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
2990 for (int i = 0; i < count; i++) {
2991 const QByteArray ba = get_atom_name(p->conn, data[i]);
2992 fprintf(stderr, "NETWinInfo::setState: state %ld '%s'\n", data[i], ba.constData());
2993 }
2994#endif
2995
2996 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_STATE), XCB_ATOM_ATOM, 32, count, (const void *)data);
2997 }
2998}
2999
3001{
3002 if (p->role != Client) {
3003 return;
3004 }
3005
3006 int len;
3007 uint32_t data[2];
3008
3009 switch (type) {
3010 case Override:
3011 // spec extension: override window type. we must comply with the spec
3012 // and provide a fall back (normal seems best)
3013 data[0] = p->atom(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
3014 data[1] = p->atom(_NET_WM_WINDOW_TYPE_NORMAL);
3015 len = 2;
3016 break;
3017
3018 case Dialog:
3019 data[0] = p->atom(_NET_WM_WINDOW_TYPE_DIALOG);
3020 data[1] = XCB_NONE;
3021 len = 1;
3022 break;
3023
3024 case Menu:
3025 data[0] = p->atom(_NET_WM_WINDOW_TYPE_MENU);
3026 data[1] = XCB_NONE;
3027 len = 1;
3028 break;
3029
3030 case TopMenu:
3031 // spec extension: override window type. we must comply with the spec
3032 // and provide a fall back (dock seems best)
3033 data[0] = p->atom(_KDE_NET_WM_WINDOW_TYPE_TOPMENU);
3034 data[1] = p->atom(_NET_WM_WINDOW_TYPE_DOCK);
3035 len = 2;
3036 break;
3037
3038 case Toolbar:
3039 data[0] = p->atom(_NET_WM_WINDOW_TYPE_TOOLBAR);
3040 data[1] = XCB_NONE;
3041 len = 1;
3042 break;
3043
3044 case Dock:
3045 data[0] = p->atom(_NET_WM_WINDOW_TYPE_DOCK);
3046 data[1] = XCB_NONE;
3047 len = 1;
3048 break;
3049
3050 case Desktop:
3051 data[0] = p->atom(_NET_WM_WINDOW_TYPE_DESKTOP);
3052 data[1] = XCB_NONE;
3053 len = 1;
3054 break;
3055
3056 case Utility:
3057 data[0] = p->atom(_NET_WM_WINDOW_TYPE_UTILITY);
3058 data[1] = p->atom(_NET_WM_WINDOW_TYPE_DIALOG); // fallback for old netwm version
3059 len = 2;
3060 break;
3061
3062 case Splash:
3063 data[0] = p->atom(_NET_WM_WINDOW_TYPE_SPLASH);
3064 data[1] = p->atom(_NET_WM_WINDOW_TYPE_DOCK); // fallback (dock seems best)
3065 len = 2;
3066 break;
3067
3068 case DropdownMenu:
3069 data[0] = p->atom(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU);
3070 data[1] = p->atom(_NET_WM_WINDOW_TYPE_MENU); // fallback (tearoff seems to be the best)
3071 len = 1;
3072 break;
3073
3074 case PopupMenu:
3075 data[0] = p->atom(_NET_WM_WINDOW_TYPE_POPUP_MENU);
3076 data[1] = p->atom(_NET_WM_WINDOW_TYPE_MENU); // fallback (tearoff seems to be the best)
3077 len = 1;
3078 break;
3079
3080 case Tooltip:
3081 data[0] = p->atom(_NET_WM_WINDOW_TYPE_TOOLTIP);
3082 data[1] = XCB_NONE;
3083 len = 1;
3084 break;
3085
3086 case Notification:
3087 data[0] = p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION);
3088 data[1] = p->atom(_NET_WM_WINDOW_TYPE_UTILITY); // fallback (utility seems to be the best)
3089 len = 1;
3090 break;
3091
3092 case ComboBox:
3093 data[0] = p->atom(_NET_WM_WINDOW_TYPE_COMBO);
3094 data[1] = XCB_NONE;
3095 len = 1;
3096 break;
3097
3098 case DNDIcon:
3099 data[0] = p->atom(_NET_WM_WINDOW_TYPE_DND);
3100 data[1] = XCB_NONE;
3101 len = 1;
3102 break;
3103
3104 case OnScreenDisplay:
3105 data[0] = p->atom(_KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY);
3106 data[1] = p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION);
3107 len = 2;
3108 break;
3109
3111 data[0] = p->atom(_KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION);
3112 data[1] = p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION);
3113 len = 2;
3114 break;
3115
3116 case AppletPopup:
3117 data[0] = p->atom(_KDE_NET_WM_WINDOW_TYPE_APPLET_POPUP);
3118 data[1] = XCB_NONE;
3119 len = 1;
3120 break;
3121
3122 default:
3123 case Normal:
3124 data[0] = p->atom(_NET_WM_WINDOW_TYPE_NORMAL);
3125 data[1] = XCB_NONE;
3126 len = 1;
3127 break;
3128 }
3129
3130 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, len, (const void *)&data);
3131}
3132
3133void NETWinInfo::setName(const char *name)
3134{
3135 if (p->role != Client) {
3136 return;
3137 }
3138
3139 delete[] p->name;
3140 p->name = nstrdup(name);
3141
3142 if (p->name[0] != '\0') {
3143 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_NAME), p->atom(UTF8_STRING), 8, strlen(p->name), (const void *)p->name);
3144 } else {
3145 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_NAME));
3146 }
3147}
3148
3149void NETWinInfo::setVisibleName(const char *visibleName)
3150{
3151 if (p->role != WindowManager) {
3152 return;
3153 }
3154
3155 delete[] p->visible_name;
3156 p->visible_name = nstrdup(visibleName);
3157
3158 if (p->visible_name[0] != '\0') {
3159 xcb_change_property(p->conn,
3160 XCB_PROP_MODE_REPLACE,
3161 p->window,
3162 p->atom(_NET_WM_VISIBLE_NAME),
3163 p->atom(UTF8_STRING),
3164 8,
3165 strlen(p->visible_name),
3166 (const void *)p->visible_name);
3167 } else {
3168 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_VISIBLE_NAME));
3169 }
3170}
3171
3172void NETWinInfo::setIconName(const char *iconName)
3173{
3174 if (p->role != Client) {
3175 return;
3176 }
3177
3178 delete[] p->icon_name;
3179 p->icon_name = nstrdup(iconName);
3180
3181 if (p->icon_name[0] != '\0') {
3182 xcb_change_property(p->conn,
3183 XCB_PROP_MODE_REPLACE,
3184 p->window,
3185 p->atom(_NET_WM_ICON_NAME),
3186 p->atom(UTF8_STRING),
3187 8,
3188 strlen(p->icon_name),
3189 (const void *)p->icon_name);
3190 } else {
3191 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_ICON_NAME));
3192 }
3193}
3194
3195void NETWinInfo::setVisibleIconName(const char *visibleIconName)
3196{
3197 if (p->role != WindowManager) {
3198 return;
3199 }
3200
3201 delete[] p->visible_icon_name;
3202 p->visible_icon_name = nstrdup(visibleIconName);
3203
3204 if (p->visible_icon_name[0] != '\0') {
3205 xcb_change_property(p->conn,
3206 XCB_PROP_MODE_REPLACE,
3207 p->window,
3208 p->atom(_NET_WM_VISIBLE_ICON_NAME),
3209 p->atom(UTF8_STRING),
3210 8,
3211 strlen(p->visible_icon_name),
3212 (const void *)p->visible_icon_name);
3213 } else {
3214 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_VISIBLE_ICON_NAME));
3215 }
3216}
3217
3218void NETWinInfo::setDesktop(int desktop, bool ignore_viewport)
3219{
3220 if (p->mapping_state_dirty) {
3221 updateWMState();
3222 }
3223
3224 if (p->role == Client && p->mapping_state != Withdrawn) {
3225 // We only send a ClientMessage if we are 1) a client and 2) managed
3226
3227 if (desktop == 0) {
3228 return; // We can't do that while being managed
3229 }
3230
3231 if (!ignore_viewport && KX11Extras::mapViewport()) {
3233 return;
3234 }
3235
3236 const uint32_t data[5] = {desktop == OnAllDesktops ? 0xffffffff : desktop - 1, 0, 0, 0, 0};
3237
3238 send_client_message(p->conn, netwm_sendevent_mask, p->root, p->window, p->atom(_NET_WM_DESKTOP), data);
3239 } else {
3240 // Otherwise we just set or remove the property directly
3241 p->desktop = desktop;
3242
3243 if (desktop == 0) {
3244 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_DESKTOP));
3245 } else {
3246 uint32_t d = (desktop == OnAllDesktops ? 0xffffffff : desktop - 1);
3247 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_DESKTOP), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
3248 }
3249 }
3250}
3251
3253{
3254 if (p->role != Client) {
3255 return;
3256 }
3257
3258 p->pid = pid;
3259 uint32_t d = pid;
3260 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_PID), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
3261}
3262
3264{
3265 if (p->role != Client) {
3266 return;
3267 }
3268
3269 p->handled_icons = handled;
3270 uint32_t d = handled;
3271 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_HANDLED_ICONS), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
3272}
3273
3274void NETWinInfo::setStartupId(const char *id)
3275{
3276 if (p->role != Client) {
3277 return;
3278 }
3279
3280 delete[] p->startup_id;
3281 p->startup_id = nstrdup(id);
3282
3283 xcb_change_property(p->conn,
3284 XCB_PROP_MODE_REPLACE,
3285 p->window,
3286 p->atom(_NET_STARTUP_ID),
3287 p->atom(UTF8_STRING),
3288 8,
3289 strlen(p->startup_id),
3290 (const void *)p->startup_id);
3291}
3292
3293void NETWinInfo::setOpacity(unsigned long opacity)
3294{
3295 // if (p->role != Client) return;
3296
3297 p->opacity = opacity;
3298 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_WINDOW_OPACITY), XCB_ATOM_CARDINAL, 32, 1, (const void *)&p->opacity);
3299}
3300
3301void NETWinInfo::setOpacityF(qreal opacity)
3302{
3303 setOpacity(static_cast<unsigned long>(opacity * 0xffffffff));
3304}
3305
3307{
3308 if (p->role != WindowManager) {
3309 return;
3310 }
3311
3312 uint32_t data[50];
3313 int count = 0;
3314
3315 p->allowed_actions = actions;
3316 if (p->allowed_actions & ActionMove) {
3317 data[count++] = p->atom(_NET_WM_ACTION_MOVE);
3318 }
3319 if (p->allowed_actions & ActionResize) {
3320 data[count++] = p->atom(_NET_WM_ACTION_RESIZE);
3321 }
3322 if (p->allowed_actions & ActionMinimize) {
3323 data[count++] = p->atom(_NET_WM_ACTION_MINIMIZE);
3324 }
3325 if (p->allowed_actions & ActionShade) {
3326 data[count++] = p->atom(_NET_WM_ACTION_SHADE);
3327 }
3328 if (p->allowed_actions & ActionStick) {
3329 data[count++] = p->atom(_NET_WM_ACTION_STICK);
3330 }
3331 if (p->allowed_actions & ActionMaxVert) {
3332 data[count++] = p->atom(_NET_WM_ACTION_MAXIMIZE_VERT);
3333 }
3334 if (p->allowed_actions & ActionMaxHoriz) {
3335 data[count++] = p->atom(_NET_WM_ACTION_MAXIMIZE_HORZ);
3336 }
3337 if (p->allowed_actions & ActionFullScreen) {
3338 data[count++] = p->atom(_NET_WM_ACTION_FULLSCREEN);
3339 }
3340 if (p->allowed_actions & ActionChangeDesktop) {
3341 data[count++] = p->atom(_NET_WM_ACTION_CHANGE_DESKTOP);
3342 }
3343 if (p->allowed_actions & ActionClose) {
3344 data[count++] = p->atom(_NET_WM_ACTION_CLOSE);
3345 }
3346
3347#ifdef NETWMDEBUG
3348 fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count);
3349 for (int i = 0; i < count; i++) {
3350 const QByteArray ba = get_atom_name(p->conn, data[i]);
3351 fprintf(stderr, "NETWinInfo::setAllowedActions: action %ld '%s'\n", data[i], ba.constData());
3352 }
3353#endif
3354
3355 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_ALLOWED_ACTIONS), XCB_ATOM_ATOM, 32, count, (const void *)data);
3356}
3357
3359{
3360 if (p->role != WindowManager) {
3361 return;
3362 }
3363
3364 p->frame_strut = strut;
3365
3366 uint32_t d[4];
3367 d[0] = strut.left;
3368 d[1] = strut.right;
3369 d[2] = strut.top;
3370 d[3] = strut.bottom;
3371
3372 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 32, 4, (const void *)d);
3373 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_KDE_NET_WM_FRAME_STRUT), XCB_ATOM_CARDINAL, 32, 4, (const void *)d);
3374}
3375
3377{
3378 return p->frame_strut;
3379}
3380
3382{
3383 if (strut.left != -1 || strut.top != -1 || strut.right != -1 || strut.bottom != -1) {
3384 strut.left = qMax(0, strut.left);
3385 strut.top = qMax(0, strut.top);
3386 strut.right = qMax(0, strut.right);
3387 strut.bottom = qMax(0, strut.bottom);
3388 }
3389
3390 p->frame_overlap = strut;
3391
3392 uint32_t d[4];
3393 d[0] = strut.left;
3394 d[1] = strut.right;
3395 d[2] = strut.top;
3396 d[3] = strut.bottom;
3397
3398 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_FRAME_OVERLAP), XCB_ATOM_CARDINAL, 32, 4, (const void *)d);
3399}
3400
3402{
3403 return p->frame_overlap;
3404}
3405
3407{
3408 p->gtk_frame_extents = strut;
3409
3410 uint32_t d[4];
3411 d[0] = strut.left;
3412 d[1] = strut.right;
3413 d[2] = strut.top;
3414 d[3] = strut.bottom;
3415
3416 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_GTK_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 32, 4, (const void *)d);
3417}
3418
3420{
3421 return p->gtk_frame_extents;
3422}
3423
3425{
3426 if (p->role != Client) {
3427 return;
3428 }
3429
3430 delete[] p->appmenu_object_path;
3431 p->appmenu_object_path = nstrdup(name);
3432
3433 xcb_change_property(p->conn,
3434 XCB_PROP_MODE_REPLACE,
3435 p->window,
3436 p->atom(_KDE_NET_WM_APPMENU_OBJECT_PATH),
3437 XCB_ATOM_STRING,
3438 8,
3439 strlen(p->appmenu_object_path),
3440 (const void *)p->appmenu_object_path);
3441}
3442
3444{
3445 if (p->role != Client) {
3446 return;
3447 }
3448
3449 delete[] p->appmenu_service_name;
3450 p->appmenu_service_name = nstrdup(name);
3451
3452 xcb_change_property(p->conn,
3453 XCB_PROP_MODE_REPLACE,
3454 p->window,
3455 p->atom(_KDE_NET_WM_APPMENU_SERVICE_NAME),
3456 XCB_ATOM_STRING,
3457 8,
3458 strlen(p->appmenu_service_name),
3459 (const void *)p->appmenu_service_name);
3460}
3461
3463{
3464 return p->appmenu_object_path;
3465}
3466
3468{
3469 return p->appmenu_service_name;
3470}
3471
3473{
3474 if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
3475 const xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry(p->conn, p->window);
3476
3477 const xcb_translate_coordinates_cookie_t translate_cookie = xcb_translate_coordinates(p->conn, p->window, p->root, 0, 0);
3478
3479 xcb_get_geometry_reply_t *geometry = xcb_get_geometry_reply(p->conn, geometry_cookie, nullptr);
3480 xcb_translate_coordinates_reply_t *translated = xcb_translate_coordinates_reply(p->conn, translate_cookie, nullptr);
3481
3482 if (geometry && translated) {
3483 p->win_geom.pos.x = translated->dst_x;
3484 p->win_geom.pos.y = translated->dst_y;
3485
3486 p->win_geom.size.width = geometry->width;
3487 p->win_geom.size.height = geometry->height;
3488 }
3489
3490 if (geometry) {
3491 free(geometry);
3492 }
3493
3494 if (translated) {
3495 free(translated);
3496 }
3497 }
3498
3499 // TODO try to work also without _NET_WM_FRAME_EXTENTS
3500 window = p->win_geom;
3501
3502 frame.pos.x = window.pos.x - p->frame_strut.left;
3503 frame.pos.y = window.pos.y - p->frame_strut.top;
3504 frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
3505 frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
3506}
3507
3508NETIcon NETWinInfo::icon(int width, int height) const
3509{
3510 return iconInternal(p->icons, p->icon_count, width, height);
3511}
3512
3513const int *NETWinInfo::iconSizes() const
3514{
3515 if (p->icon_sizes == nullptr) {
3516 p->icon_sizes = new int[p->icon_count * 2 + 2];
3517 for (int i = 0; i < p->icon_count; ++i) {
3518 p->icon_sizes[i * 2] = p->icons[i].size.width;
3519 p->icon_sizes[i * 2 + 1] = p->icons[i].size.height;
3520 }
3521 p->icon_sizes[p->icon_count * 2] = 0; // terminator
3522 p->icon_sizes[p->icon_count * 2 + 1] = 0;
3523 }
3524 return p->icon_sizes;
3525}
3526
3527NETIcon NETWinInfo::iconInternal(NETRArray<NETIcon> &icons, int icon_count, int width, int height) const
3528{
3529 NETIcon result;
3530
3531 if (!icon_count) {
3532 result.size.width = 0;
3533 result.size.height = 0;
3534 result.data = nullptr;
3535 return result;
3536 }
3537
3538 // find the largest icon
3539 result = icons[0];
3540 for (int i = 1; i < icons.size(); i++) {
3541 if (icons[i].size.width >= result.size.width && icons[i].size.height >= result.size.height) {
3542 result = icons[i];
3543 }
3544 }
3545
3546 // return the largest icon if w and h are -1
3547 if (width == -1 && height == -1) {
3548 return result;
3549 }
3550
3551 // find the icon that's closest in size to w x h...
3552 for (int i = 0; i < icons.size(); i++) {
3553 if ((icons[i].size.width >= width && icons[i].size.width < result.size.width)
3554 && (icons[i].size.height >= height && icons[i].size.height < result.size.height)) {
3555 result = icons[i];
3556 }
3557 }
3558
3559 return result;
3560}
3561
3562void NETWinInfo::setUserTime(xcb_timestamp_t time)
3563{
3564 if (p->role != Client) {
3565 return;
3566 }
3567
3568 p->user_time = time;
3569 uint32_t d = time;
3570
3571 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_USER_TIME), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
3572}
3573
3574NET::Properties NETWinInfo::event(xcb_generic_event_t *ev)
3575{
3576 NET::Properties properties;
3577 event(ev, &properties);
3578 return properties;
3579}
3580
3581void NETWinInfo::event(xcb_generic_event_t *event, NET::Properties *properties, NET::Properties2 *properties2)
3582{
3583 NET::Properties dirty;
3584 NET::Properties2 dirty2;
3585 bool do_update = false;
3586 const uint8_t eventType = event->response_type & ~0x80;
3587
3588 if (p->role == WindowManager && eventType == XCB_CLIENT_MESSAGE && reinterpret_cast<xcb_client_message_event_t *>(event)->format == 32) {
3589 xcb_client_message_event_t *message = reinterpret_cast<xcb_client_message_event_t *>(event);
3590#ifdef NETWMDEBUG
3591 fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
3592#endif // NETWMDEBUG
3593
3594 if (message->type == p->atom(_NET_WM_STATE)) {
3595 dirty = WMState;
3596
3597 // we need to generate a change mask
3598
3599#ifdef NETWMDEBUG
3600 fprintf(stderr, "NETWinInfo::event: state client message, getting new state/mask\n");
3601#endif
3602
3603 int i;
3605 NET::States mask = NET::States();
3606
3607 for (i = 1; i < 3; i++) {
3608#ifdef NETWMDEBUG
3609 const QByteArray ba = get_atom_name(p->conn, (xcb_atom_t)message->data.data32[i]);
3610 fprintf(stderr, "NETWinInfo::event: message %ld '%s'\n", message->data.data32[i], ba.constData());
3611#endif
3612
3613 if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_MODAL)) {
3614 mask |= Modal;
3615 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_STICKY)) {
3616 mask |= Sticky;
3617 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_MAXIMIZED_VERT)) {
3618 mask |= MaxVert;
3619 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_MAXIMIZED_HORZ)) {
3620 mask |= MaxHoriz;
3621 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_SHADED)) {
3622 mask |= Shaded;
3623 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_SKIP_TASKBAR)) {
3624 mask |= SkipTaskbar;
3625 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_SKIP_PAGER)) {
3626 mask |= SkipPager;
3627 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER)) {
3628 mask |= SkipSwitcher;
3629 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_HIDDEN)) {
3630 mask |= Hidden;
3631 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_FULLSCREEN)) {
3632 mask |= FullScreen;
3633 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_ABOVE)) {
3634 mask |= KeepAbove;
3635 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_BELOW)) {
3636 mask |= KeepBelow;
3637 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_DEMANDS_ATTENTION)) {
3638 mask |= DemandsAttention;
3639 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) {
3640 mask |= KeepAbove;
3641 } else if ((xcb_atom_t)message->data.data32[i] == p->atom(_NET_WM_STATE_FOCUSED)) {
3642 mask |= Focused;
3643 }
3644 }
3645
3646 // when removing, we just leave newstate == 0
3647 switch (message->data.data32[0]) {
3648 case 1: // set
3649 // to set... the change state should be the same as the mask
3650 state = mask;
3651 break;
3652
3653 case 2: // toggle
3654 // to toggle, we need to xor the current state with the new state
3655 state = (p->state & mask) ^ mask;
3656 break;
3657
3658 default:
3659 // to clear state, the new state should stay zero
3660 ;
3661 }
3662
3663#ifdef NETWMDEBUG
3664 fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n", state, mask);
3665#endif
3666
3667 changeState(state, mask);
3668 } else if (message->type == p->atom(_NET_WM_DESKTOP)) {
3669 dirty = WMDesktop;
3670
3671 if (message->data.data32[0] == (unsigned)OnAllDesktops) {
3673 } else {
3674 changeDesktop(message->data.data32[0] + 1);
3675 }
3676 } else if (message->type == p->atom(_NET_WM_FULLSCREEN_MONITORS)) {
3677 dirty2 = WM2FullscreenMonitors;
3678
3679 NETFullscreenMonitors topology;
3680 topology.top = message->data.data32[0];
3681 topology.bottom = message->data.data32[1];
3682 topology.left = message->data.data32[2];
3683 topology.right = message->data.data32[3];
3684
3685#ifdef NETWMDEBUG
3686 fprintf(stderr,
3687 "NETWinInfo2::event: calling changeFullscreenMonitors"
3688 "(%ld, %ld, %ld, %ld, %ld)\n",
3689 message->window,
3690 message->data.data32[0],
3691 message->data.data32[1],
3692 message->data.data32[2],
3693 message->data.data32[3]);
3694#endif
3695 changeFullscreenMonitors(topology);
3696 }
3697 }
3698
3699 if (eventType == XCB_PROPERTY_NOTIFY) {
3700#ifdef NETWMDEBUG
3701 fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
3702#endif
3703
3704 xcb_property_notify_event_t *pe = reinterpret_cast<xcb_property_notify_event_t *>(event);
3705
3706 if (pe->atom == p->atom(_NET_WM_NAME)) {
3707 dirty |= WMName;
3708 } else if (pe->atom == p->atom(_NET_WM_VISIBLE_NAME)) {
3709 dirty |= WMVisibleName;
3710 } else if (pe->atom == p->atom(_NET_WM_DESKTOP)) {
3711 dirty |= WMDesktop;
3712 } else if (pe->atom == p->atom(_NET_WM_WINDOW_TYPE)) {
3713 dirty |= WMWindowType;
3714 } else if (pe->atom == p->atom(_NET_WM_STATE)) {
3715 dirty |= WMState;
3716 } else if (pe->atom == p->atom(_NET_WM_STRUT)) {
3717 dirty |= WMStrut;
3718 } else if (pe->atom == p->atom(_NET_WM_STRUT_PARTIAL)) {
3719 dirty2 |= WM2ExtendedStrut;
3720 } else if (pe->atom == p->atom(_NET_WM_ICON_GEOMETRY)) {
3721 dirty |= WMIconGeometry;
3722 } else if (pe->atom == p->atom(_NET_WM_ICON)) {
3723 dirty |= WMIcon;
3724 } else if (pe->atom == p->atom(_NET_WM_PID)) {
3725 dirty |= WMPid;
3726 } else if (pe->atom == p->atom(_NET_WM_HANDLED_ICONS)) {
3727 dirty |= WMHandledIcons;
3728 } else if (pe->atom == p->atom(_NET_STARTUP_ID)) {
3729 dirty2 |= WM2StartupId;
3730 } else if (pe->atom == p->atom(_NET_WM_WINDOW_OPACITY)) {
3731 dirty2 |= WM2Opacity;
3732 } else if (pe->atom == p->atom(_NET_WM_ALLOWED_ACTIONS)) {
3733 dirty2 |= WM2AllowedActions;
3734 } else if (pe->atom == p->atom(WM_STATE)) {
3735 dirty |= XAWMState;
3736 } else if (pe->atom == p->atom(_NET_FRAME_EXTENTS)) {
3737 dirty |= WMFrameExtents;
3738 } else if (pe->atom == p->atom(_KDE_NET_WM_FRAME_STRUT)) {
3739 dirty |= WMFrameExtents;
3740 } else if (pe->atom == p->atom(_NET_WM_FRAME_OVERLAP)) {
3741 dirty2 |= WM2FrameOverlap;
3742 } else if (pe->atom == p->atom(_NET_WM_ICON_NAME)) {
3743 dirty |= WMIconName;
3744 } else if (pe->atom == p->atom(_NET_WM_VISIBLE_ICON_NAME)) {
3745 dirty |= WMVisibleIconName;
3746 } else if (pe->atom == p->atom(_NET_WM_USER_TIME)) {
3747 dirty2 |= WM2UserTime;
3748 } else if (pe->atom == XCB_ATOM_WM_HINTS) {
3749 dirty2 |= WM2GroupLeader;
3750 dirty2 |= WM2Urgency;
3751 dirty2 |= WM2Input;
3752 dirty2 |= WM2InitialMappingState;
3753 dirty2 |= WM2IconPixmap;
3754 } else if (pe->atom == XCB_ATOM_WM_TRANSIENT_FOR) {
3755 dirty2 |= WM2TransientFor;
3756 } else if (pe->atom == XCB_ATOM_WM_CLASS) {
3757 dirty2 |= WM2WindowClass;
3758 } else if (pe->atom == p->atom(WM_WINDOW_ROLE)) {
3759 dirty2 |= WM2WindowRole;
3760 } else if (pe->atom == XCB_ATOM_WM_CLIENT_MACHINE) {
3761 dirty2 |= WM2ClientMachine;
3762 } else if (pe->atom == p->atom(_KDE_NET_WM_ACTIVITIES)) {
3763 dirty2 |= WM2Activities;
3764 } else if (pe->atom == p->atom(_KDE_NET_WM_BLOCK_COMPOSITING) || pe->atom == p->atom(_NET_WM_BYPASS_COMPOSITOR)) {
3765 dirty2 |= WM2BlockCompositing;
3766 } else if (pe->atom == p->atom(_KDE_NET_WM_SHADOW)) {
3767 dirty2 |= WM2KDEShadow;
3768 } else if (pe->atom == p->atom(WM_PROTOCOLS)) {
3769 dirty2 |= WM2Protocols;
3770 } else if (pe->atom == p->atom(_NET_WM_OPAQUE_REGION)) {
3771 dirty2 |= WM2OpaqueRegion;
3772 } else if (pe->atom == p->atom(_KDE_NET_WM_DESKTOP_FILE)) {
3773 dirty2 = WM2DesktopFileName;
3774 } else if (pe->atom == p->atom(_GTK_APPLICATION_ID)) {
3775 dirty2 = WM2GTKApplicationId;
3776 } else if (pe->atom == p->atom(_NET_WM_FULLSCREEN_MONITORS)) {
3777 dirty2 = WM2FullscreenMonitors;
3778 } else if (pe->atom == p->atom(_GTK_FRAME_EXTENTS)) {
3779 dirty2 |= WM2GTKFrameExtents;
3780 } else if (pe->atom == p->atom(_GTK_SHOW_WINDOW_MENU)) {
3781 dirty2 |= WM2GTKShowWindowMenu;
3782 } else if (pe->atom == p->atom(_KDE_NET_WM_APPMENU_SERVICE_NAME)) {
3783 dirty2 |= WM2AppMenuServiceName;
3784 } else if (pe->atom == p->atom(_KDE_NET_WM_APPMENU_OBJECT_PATH)) {
3785 dirty2 |= WM2AppMenuObjectPath;
3786 }
3787
3788 do_update = true;
3789 } else if (eventType == XCB_CONFIGURE_NOTIFY) {
3790#ifdef NETWMDEBUG
3791 fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
3792#endif
3793
3794 dirty |= WMGeometry;
3795
3796 // update window geometry
3797 xcb_configure_notify_event_t *configure = reinterpret_cast<xcb_configure_notify_event_t *>(event);
3798 p->win_geom.pos.x = configure->x;
3799 p->win_geom.pos.y = configure->y;
3800 p->win_geom.size.width = configure->width;
3801 p->win_geom.size.height = configure->height;
3802 }
3803
3804 if (do_update) {
3805 update(dirty, dirty2);
3806 }
3807
3808 if (properties) {
3809 *properties = dirty;
3810 }
3811 if (properties2) {
3812 *properties2 = dirty2;
3813 }
3814}
3815
3816void NETWinInfo::updateWMState()
3817{
3818 update(XAWMState);
3819}
3820
3821void NETWinInfo::update(NET::Properties dirtyProperties, NET::Properties2 dirtyProperties2)
3822{
3823 Properties dirty = dirtyProperties & p->properties;
3824 Properties2 dirty2 = dirtyProperties2 & p->properties2;
3825
3826 // We *always* want to update WM_STATE if set in dirty_props
3827 if (dirtyProperties & XAWMState) {
3828 dirty |= XAWMState;
3829 }
3830
3831 xcb_get_property_cookie_t cookies[255];
3832 int c = 0;
3833
3834 if (dirty & XAWMState) {
3835 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(WM_STATE), p->atom(WM_STATE), 0, 1);
3836 }
3837
3838 if (dirty & WMState) {
3839 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_STATE), XCB_ATOM_ATOM, 0, 2048);
3840 }
3841
3842 if (dirty & WMDesktop) {
3843 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_DESKTOP), XCB_ATOM_CARDINAL, 0, 1);
3844 }
3845
3846 if (dirty & WMName) {
3847 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_NAME), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3848 }
3849
3850 if (dirty & WMVisibleName) {
3851 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_VISIBLE_NAME), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3852 }
3853
3854 if (dirty & WMIconName) {
3855 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_ICON_NAME), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3856 }
3857
3858 if (dirty & WMVisibleIconName) {
3859 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_VISIBLE_ICON_NAME), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3860 }
3861
3862 if (dirty & WMWindowType) {
3863 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 0, 2048);
3864 }
3865
3866 if (dirty & WMStrut) {
3867 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_STRUT), XCB_ATOM_CARDINAL, 0, 4);
3868 }
3869
3870 if (dirty2 & WM2ExtendedStrut) {
3871 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_STRUT_PARTIAL), XCB_ATOM_CARDINAL, 0, 12);
3872 }
3873
3874 if (dirty2 & WM2FullscreenMonitors) {
3875 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_FULLSCREEN_MONITORS), XCB_ATOM_CARDINAL, 0, 4);
3876 }
3877
3878 if (dirty & WMIconGeometry) {
3879 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_ICON_GEOMETRY), XCB_ATOM_CARDINAL, 0, 4);
3880 }
3881
3882 if (dirty & WMIcon) {
3883 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_ICON), XCB_ATOM_CARDINAL, 0, 0xffffffff);
3884 }
3885
3886 if (dirty & WMFrameExtents) {
3887 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
3888 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_FRAME_STRUT), XCB_ATOM_CARDINAL, 0, 4);
3889 }
3890
3891 if (dirty2 & WM2FrameOverlap) {
3892 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_FRAME_OVERLAP), XCB_ATOM_CARDINAL, 0, 4);
3893 }
3894
3895 if (dirty2 & WM2Activities) {
3896 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_ACTIVITIES), XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3897 }
3898
3899 if (dirty2 & WM2BlockCompositing) {
3900 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_BLOCK_COMPOSITING), XCB_ATOM_CARDINAL, 0, 1);
3901 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_BYPASS_COMPOSITOR), XCB_ATOM_CARDINAL, 0, 1);
3902 }
3903
3904 if (dirty & WMPid) {
3905 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_PID), XCB_ATOM_CARDINAL, 0, 1);
3906 }
3907
3908 if (dirty2 & WM2StartupId) {
3909 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_STARTUP_ID), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3910 }
3911
3912 if (dirty2 & WM2Opacity) {
3913 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_WINDOW_OPACITY), XCB_ATOM_CARDINAL, 0, 1);
3914 }
3915
3916 if (dirty2 & WM2AllowedActions) {
3917 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_ALLOWED_ACTIONS), XCB_ATOM_ATOM, 0, 2048);
3918 }
3919
3920 if (dirty2 & WM2UserTime) {
3921 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_USER_TIME), XCB_ATOM_CARDINAL, 0, 1);
3922 }
3923
3924 if (dirty2 & WM2TransientFor) {
3925 cookies[c++] = xcb_get_property(p->conn, false, p->window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 1);
3926 }
3927
3928 if (dirty2 & (WM2GroupLeader | WM2Urgency | WM2Input | WM2InitialMappingState | WM2IconPixmap)) {
3929 cookies[c++] = xcb_get_property(p->conn, false, p->window, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9);
3930 }
3931
3932 if (dirty2 & WM2WindowClass) {
3933 cookies[c++] = xcb_get_property(p->conn, false, p->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3934 }
3935
3936 if (dirty2 & WM2WindowRole) {
3937 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(WM_WINDOW_ROLE), XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3938 }
3939
3940 if (dirty2 & WM2ClientMachine) {
3941 cookies[c++] = xcb_get_property(p->conn, false, p->window, XCB_ATOM_WM_CLIENT_MACHINE, XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3942 }
3943
3944 if (dirty2 & WM2Protocols) {
3945 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(WM_PROTOCOLS), XCB_ATOM_ATOM, 0, 2048);
3946 }
3947
3948 if (dirty2 & WM2OpaqueRegion) {
3949 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_NET_WM_OPAQUE_REGION), XCB_ATOM_CARDINAL, 0, MAX_PROP_SIZE);
3950 }
3951
3952 if (dirty2 & WM2DesktopFileName) {
3953 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_DESKTOP_FILE), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3954 }
3955
3956 if (dirty2 & WM2GTKApplicationId) {
3957 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_GTK_APPLICATION_ID), p->atom(UTF8_STRING), 0, MAX_PROP_SIZE);
3958 }
3959
3960 if (dirty2 & WM2GTKFrameExtents) {
3961 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_GTK_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
3962 }
3963
3964 if (dirty2 & WM2AppMenuObjectPath) {
3965 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_APPMENU_OBJECT_PATH), XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3966 }
3967
3968 if (dirty2 & WM2AppMenuServiceName) {
3969 cookies[c++] = xcb_get_property(p->conn, false, p->window, p->atom(_KDE_NET_WM_APPMENU_SERVICE_NAME), XCB_ATOM_STRING, 0, MAX_PROP_SIZE);
3970 }
3971
3972 c = 0;
3973
3974 if (dirty & XAWMState) {
3975 p->mapping_state = Withdrawn;
3976
3977 bool success;
3978 uint32_t state = get_value_reply<uint32_t>(p->conn, cookies[c++], p->atom(WM_STATE), 0, &success);
3979
3980 if (success) {
3981 switch (state) {
3982 case 3: // IconicState
3983 p->mapping_state = Iconic;
3984 break;
3985
3986 case 1: // NormalState
3987 p->mapping_state = Visible;
3988 break;
3989
3990 case 0: // WithdrawnState
3991 default:
3992 p->mapping_state = Withdrawn;
3993 break;
3994 }
3995
3996 p->mapping_state_dirty = false;
3997 }
3998 }
3999
4000 if (dirty & WMState) {
4001 p->state = NET::States();
4002 const QList<xcb_atom_t> states = get_array_reply<xcb_atom_t>(p->conn, cookies[c++], XCB_ATOM_ATOM);
4003
4004#ifdef NETWMDEBUG
4005 fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n", states.count());
4006#endif
4007
4008 for (const xcb_atom_t state : states) {
4009#ifdef NETWMDEBUG
4010 const QByteArray ba = get_atom_name(p->conn, state);
4011 fprintf(stderr, "NETWinInfo::update: adding window state %ld '%s'\n", state, ba.constData());
4012#endif
4013 if (state == p->atom(_NET_WM_STATE_MODAL)) {
4014 p->state |= Modal;
4015 }
4016
4017 else if (state == p->atom(_NET_WM_STATE_STICKY)) {
4018 p->state |= Sticky;
4019 }
4020
4021 else if (state == p->atom(_NET_WM_STATE_MAXIMIZED_VERT)) {
4022 p->state |= MaxVert;
4023 }
4024
4025 else if (state == p->atom(_NET_WM_STATE_MAXIMIZED_HORZ)) {
4026 p->state |= MaxHoriz;
4027 }
4028
4029 else if (state == p->atom(_NET_WM_STATE_SHADED)) {
4030 p->state |= Shaded;
4031 }
4032
4033 else if (state == p->atom(_NET_WM_STATE_SKIP_TASKBAR)) {
4034 p->state |= SkipTaskbar;
4035 }
4036
4037 else if (state == p->atom(_NET_WM_STATE_SKIP_PAGER)) {
4038 p->state |= SkipPager;
4039 }
4040
4041 else if (state == p->atom(_KDE_NET_WM_STATE_SKIP_SWITCHER)) {
4042 p->state |= SkipSwitcher;
4043 }
4044
4045 else if (state == p->atom(_NET_WM_STATE_HIDDEN)) {
4046 p->state |= Hidden;
4047 }
4048
4049 else if (state == p->atom(_NET_WM_STATE_FULLSCREEN)) {
4050 p->state |= FullScreen;
4051 }
4052
4053 else if (state == p->atom(_NET_WM_STATE_ABOVE)) {
4054 p->state |= KeepAbove;
4055 }
4056
4057 else if (state == p->atom(_NET_WM_STATE_BELOW)) {
4058 p->state |= KeepBelow;
4059 }
4060
4061 else if (state == p->atom(_NET_WM_STATE_DEMANDS_ATTENTION)) {
4062 p->state |= DemandsAttention;
4063 }
4064
4065 else if (state == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) {
4066 p->state |= KeepAbove;
4067 }
4068
4069 else if (state == p->atom(_NET_WM_STATE_FOCUSED)) {
4070 p->state |= Focused;
4071 }
4072 }
4073 }
4074
4075 if (dirty & WMDesktop) {
4076 p->desktop = 0;
4077
4078 bool success;
4079 uint32_t desktop = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0, &success);
4080
4081 if (success) {
4082 if (desktop != 0xffffffff) {
4083 p->desktop = desktop + 1;
4084 } else {
4085 p->desktop = OnAllDesktops;
4086 }
4087 }
4088 }
4089
4090 if (dirty & WMName) {
4091 delete[] p->name;
4092 p->name = nullptr;
4093
4094 const QByteArray str = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4095 if (str.length() > 0) {
4096 p->name = nstrndup(str.constData(), str.length());
4097 }
4098 }
4099
4100 if (dirty & WMVisibleName) {
4101 delete[] p->visible_name;
4102 p->visible_name = nullptr;
4103
4104 const QByteArray str = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4105 if (str.length() > 0) {
4106 p->visible_name = nstrndup(str.constData(), str.length());
4107 }
4108 }
4109
4110 if (dirty & WMIconName) {
4111 delete[] p->icon_name;
4112 p->icon_name = nullptr;
4113
4114 const QByteArray str = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4115 if (str.length() > 0) {
4116 p->icon_name = nstrndup(str.constData(), str.length());
4117 }
4118 }
4119
4120 if (dirty & WMVisibleIconName) {
4121 delete[] p->visible_icon_name;
4122 p->visible_icon_name = nullptr;
4123
4124 const QByteArray str = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4125 if (str.length() > 0) {
4126 p->visible_icon_name = nstrndup(str.constData(), str.length());
4127 }
4128 }
4129
4130 if (dirty & WMWindowType) {
4131 p->types.reset();
4132 p->types[0] = Unknown;
4133 p->has_net_support = false;
4134
4135 const QList<xcb_atom_t> types = get_array_reply<xcb_atom_t>(p->conn, cookies[c++], XCB_ATOM_ATOM);
4136
4137 if (!types.isEmpty()) {
4138#ifdef NETWMDEBUG
4139 fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n", types.count());
4140#endif
4141 p->has_net_support = true;
4142 int pos = 0;
4143
4144 for (const xcb_atom_t type : types) {
4145#ifdef NETWMDEBUG
4146 const QByteArray name = get_atom_name(p->conn, type);
4147 fprintf(stderr, "NETWinInfo::update: examining window type %ld %s\n", type, name.constData());
4148#endif
4149 if (type == p->atom(_NET_WM_WINDOW_TYPE_NORMAL)) {
4150 p->types[pos++] = Normal;
4151 }
4152
4153 else if (type == p->atom(_NET_WM_WINDOW_TYPE_DESKTOP)) {
4154 p->types[pos++] = Desktop;
4155 }
4156
4157 else if (type == p->atom(_NET_WM_WINDOW_TYPE_DOCK)) {
4158 p->types[pos++] = Dock;
4159 }
4160
4161 else if (type == p->atom(_NET_WM_WINDOW_TYPE_TOOLBAR)) {
4162 p->types[pos++] = Toolbar;
4163 }
4164
4165 else if (type == p->atom(_NET_WM_WINDOW_TYPE_MENU)) {
4166 p->types[pos++] = Menu;
4167 }
4168
4169 else if (type == p->atom(_NET_WM_WINDOW_TYPE_DIALOG)) {
4170 p->types[pos++] = Dialog;
4171 }
4172
4173 else if (type == p->atom(_NET_WM_WINDOW_TYPE_UTILITY)) {
4174 p->types[pos++] = Utility;
4175 }
4176
4177 else if (type == p->atom(_NET_WM_WINDOW_TYPE_SPLASH)) {
4178 p->types[pos++] = Splash;
4179 }
4180
4181 else if (type == p->atom(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)) {
4182 p->types[pos++] = DropdownMenu;
4183 }
4184
4185 else if (type == p->atom(_NET_WM_WINDOW_TYPE_POPUP_MENU)) {
4186 p->types[pos++] = PopupMenu;
4187 }
4188
4189 else if (type == p->atom(_NET_WM_WINDOW_TYPE_TOOLTIP)) {
4190 p->types[pos++] = Tooltip;
4191 }
4192
4193 else if (type == p->atom(_NET_WM_WINDOW_TYPE_NOTIFICATION)) {
4194 p->types[pos++] = Notification;
4195 }
4196
4197 else if (type == p->atom(_NET_WM_WINDOW_TYPE_COMBO)) {
4198 p->types[pos++] = ComboBox;
4199 }
4200
4201 else if (type == p->atom(_NET_WM_WINDOW_TYPE_DND)) {
4202 p->types[pos++] = DNDIcon;
4203 }
4204
4205 else if (type == p->atom(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)) {
4206 p->types[pos++] = Override;
4207 }
4208
4209 else if (type == p->atom(_KDE_NET_WM_WINDOW_TYPE_TOPMENU)) {
4210 p->types[pos++] = TopMenu;
4211 }
4212
4213 else if (type == p->atom(_KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY)) {
4214 p->types[pos++] = OnScreenDisplay;
4215 }
4216
4217 else if (type == p->atom(_KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION)) {
4218 p->types[pos++] = CriticalNotification;
4219 }
4220
4221 else if (type == p->atom(_KDE_NET_WM_WINDOW_TYPE_APPLET_POPUP)) {
4222 p->types[pos++] = AppletPopup;
4223 }
4224 }
4225 }
4226 }
4227
4228 if (dirty & WMStrut) {
4229 p->strut = NETStrut();
4230
4231 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4232 if (data.count() == 4) {
4233 p->strut.left = data[0];
4234 p->strut.right = data[1];
4235 p->strut.top = data[2];
4236 p->strut.bottom = data[3];
4237 }
4238 }
4239
4240 if (dirty2 & WM2ExtendedStrut) {
4241 p->extended_strut = NETExtendedStrut();
4242
4243 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4244 if (data.count() == 12) {
4245 p->extended_strut.left_width = data[0];
4246 p->extended_strut.right_width = data[1];
4247 p->extended_strut.top_width = data[2];
4248 p->extended_strut.bottom_width = data[3];
4249 p->extended_strut.left_start = data[4];
4250 p->extended_strut.left_end = data[5];
4251 p->extended_strut.right_start = data[6];
4252 p->extended_strut.right_end = data[7];
4253 p->extended_strut.top_start = data[8];
4254 p->extended_strut.top_end = data[9];
4255 p->extended_strut.bottom_start = data[10];
4256 p->extended_strut.bottom_end = data[11];
4257 }
4258 }
4259
4260 if (dirty2 & WM2FullscreenMonitors) {
4261 p->fullscreen_monitors = NETFullscreenMonitors();
4262
4263 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4264 if (data.count() == 4) {
4265 p->fullscreen_monitors.top = data[0];
4266 p->fullscreen_monitors.bottom = data[1];
4267 p->fullscreen_monitors.left = data[2];
4268 p->fullscreen_monitors.right = data[3];
4269 }
4270 }
4271
4272 if (dirty & WMIconGeometry) {
4273 p->icon_geom = NETRect();
4274
4275 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4276 if (data.count() == 4) {
4277 p->icon_geom.pos.x = data[0];
4278 p->icon_geom.pos.y = data[1];
4279 p->icon_geom.size.width = data[2];
4280 p->icon_geom.size.height = data[3];
4281 }
4282 }
4283
4284 if (dirty & WMIcon) {
4285 readIcon(p->conn, cookies[c++], p->icons, p->icon_count);
4286 delete[] p->icon_sizes;
4287 p->icon_sizes = nullptr;
4288 }
4289
4290 if (dirty & WMFrameExtents) {
4291 p->frame_strut = NETStrut();
4292
4293 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4294
4295 if (data.isEmpty()) {
4296 data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4297 } else {
4298 xcb_discard_reply(p->conn, cookies[c++].sequence);
4299 }
4300
4301 if (data.count() == 4) {
4302 p->frame_strut.left = data[0];
4303 p->frame_strut.right = data[1];
4304 p->frame_strut.top = data[2];
4305 p->frame_strut.bottom = data[3];
4306 }
4307 }
4308
4309 if (dirty2 & WM2FrameOverlap) {
4310 p->frame_overlap = NETStrut();
4311
4312 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4313 if (data.count() == 4) {
4314 p->frame_overlap.left = data[0];
4315 p->frame_overlap.right = data[1];
4316 p->frame_overlap.top = data[2];
4317 p->frame_overlap.bottom = data[3];
4318 }
4319 }
4320
4321 if (dirty2 & WM2Activities) {
4322 delete[] p->activities;
4323 p->activities = nullptr;
4324
4325 const QByteArray activities = get_string_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4326 if (activities.length() > 0) {
4327 p->activities = nstrndup(activities.constData(), activities.length());
4328 }
4329 }
4330
4331 if (dirty2 & WM2BlockCompositing) {
4332 bool success;
4333 p->blockCompositing = false;
4334
4335 // _KDE_NET_WM_BLOCK_COMPOSITING
4336 uint32_t data = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0, &success);
4337 if (success) {
4338 p->blockCompositing = bool(data);
4339 }
4340
4341 // _NET_WM_BYPASS_COMPOSITOR
4342 data = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0, &success);
4343 if (success) {
4344 switch (data) {
4345 case 1:
4346 p->blockCompositing = true;
4347 break;
4348 case 2:
4349 p->blockCompositing = false;
4350 break;
4351 default:
4352 break; // yes, the standard /is/ that stupid.
4353 }
4354 }
4355 }
4356
4357 if (dirty & WMPid) {
4358 p->pid = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0);
4359 }
4360
4361 if (dirty2 & WM2StartupId) {
4362 delete[] p->startup_id;
4363 p->startup_id = nullptr;
4364
4365 const QByteArray id = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4366 if (id.length() > 0) {
4367 p->startup_id = nstrndup(id.constData(), id.length());
4368 }
4369 }
4370
4371 if (dirty2 & WM2Opacity) {
4372 p->opacity = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0xffffffff);
4373 }
4374
4375 if (dirty2 & WM2AllowedActions) {
4376 p->allowed_actions = NET::Actions();
4377
4378 const QList<xcb_atom_t> actions = get_array_reply<xcb_atom_t>(p->conn, cookies[c++], XCB_ATOM_ATOM);
4379 if (!actions.isEmpty()) {
4380#ifdef NETWMDEBUG
4381 fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n", actions.count());
4382#endif
4383
4384 for (const xcb_atom_t action : actions) {
4385#ifdef NETWMDEBUG
4386 const QByteArray name = get_atom_name(p->conn, action);
4387 fprintf(stderr, "NETWinInfo::update: adding allowed action %ld '%s'\n", action, name.constData());
4388#endif
4389 if (action == p->atom(_NET_WM_ACTION_MOVE)) {
4390 p->allowed_actions |= ActionMove;
4391 }
4392
4393 else if (action == p->atom(_NET_WM_ACTION_RESIZE)) {
4394 p->allowed_actions |= ActionResize;
4395 }
4396
4397 else if (action == p->atom(_NET_WM_ACTION_MINIMIZE)) {
4398 p->allowed_actions |= ActionMinimize;
4399 }
4400
4401 else if (action == p->atom(_NET_WM_ACTION_SHADE)) {
4402 p->allowed_actions |= ActionShade;
4403 }
4404
4405 else if (action == p->atom(_NET_WM_ACTION_STICK)) {
4406 p->allowed_actions |= ActionStick;
4407 }
4408
4409 else if (action == p->atom(_NET_WM_ACTION_MAXIMIZE_VERT)) {
4410 p->allowed_actions |= ActionMaxVert;
4411 }
4412
4413 else if (action == p->atom(_NET_WM_ACTION_MAXIMIZE_HORZ)) {
4414 p->allowed_actions |= ActionMaxHoriz;
4415 }
4416
4417 else if (action == p->atom(_NET_WM_ACTION_FULLSCREEN)) {
4418 p->allowed_actions |= ActionFullScreen;
4419 }
4420
4421 else if (action == p->atom(_NET_WM_ACTION_CHANGE_DESKTOP)) {
4422 p->allowed_actions |= ActionChangeDesktop;
4423 }
4424
4425 else if (action == p->atom(_NET_WM_ACTION_CLOSE)) {
4426 p->allowed_actions |= ActionClose;
4427 }
4428 }
4429 }
4430 }
4431
4432 if (dirty2 & WM2UserTime) {
4433 p->user_time = -1U;
4434
4435 bool success;
4436 uint32_t value = get_value_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL, 0, &success);
4437
4438 if (success) {
4439 p->user_time = value;
4440 }
4441 }
4442
4443 if (dirty2 & WM2TransientFor) {
4444 p->transient_for = get_value_reply<xcb_window_t>(p->conn, cookies[c++], XCB_ATOM_WINDOW, 0);
4445 }
4446
4447 if (dirty2 & (WM2GroupLeader | WM2Urgency | WM2Input | WM2InitialMappingState | WM2IconPixmap)) {
4448 xcb_get_property_reply_t *reply = xcb_get_property_reply(p->conn, cookies[c++], nullptr);
4449
4450 if (reply && reply->format == 32 && reply->value_len == 9 && reply->type == XCB_ATOM_WM_HINTS) {
4451 kde_wm_hints *hints = reinterpret_cast<kde_wm_hints *>(xcb_get_property_value(reply));
4452
4453 if (hints->flags & (1 << 0) /*Input*/) {
4454 p->input = hints->input;
4455 }
4456 if (hints->flags & (1 << 1) /*StateHint*/) {
4457 switch (hints->initial_state) {
4458 case 3: // IconicState
4459 p->initialMappingState = Iconic;
4460 break;
4461
4462 case 1: // NormalState
4463 p->initialMappingState = Visible;
4464 break;
4465
4466 case 0: // WithdrawnState
4467 default:
4468 p->initialMappingState = Withdrawn;
4469 break;
4470 }
4471 }
4472 if (hints->flags & (1 << 2) /*IconPixmapHint*/) {
4473 p->icon_pixmap = hints->icon_pixmap;
4474 }
4475 if (hints->flags & (1 << 5) /*IconMaskHint*/) {
4476 p->icon_mask = hints->icon_mask;
4477 }
4478 if (hints->flags & (1 << 6) /*WindowGroupHint*/) {
4479 p->window_group = hints->window_group;
4480 }
4481 p->urgency = (hints->flags & (1 << 8) /*UrgencyHint*/);
4482 }
4483
4484 if (reply) {
4485 free(reply);
4486 }
4487 }
4488
4489 if (dirty2 & WM2WindowClass) {
4490 delete[] p->class_name;
4491 delete[] p->class_class;
4492 p->class_name = nullptr;
4493 p->class_class = nullptr;
4494
4495 const QList<QByteArray> list = get_stringlist_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4496 if (list.count() == 2) {
4497 p->class_name = nstrdup(list.at(0).constData());
4498 p->class_class = nstrdup(list.at(1).constData());
4499 } else if (list.count() == 1) { // Not fully compliant client. Provides a single string
4500 p->class_name = nstrdup(list.at(0).constData());
4501 p->class_class = nstrdup(list.at(0).constData());
4502 }
4503 }
4504
4505 if (dirty2 & WM2WindowRole) {
4506 delete[] p->window_role;
4507 p->window_role = nullptr;
4508
4509 const QByteArray role = get_string_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4510 if (role.length() > 0) {
4511 p->window_role = nstrndup(role.constData(), role.length());
4512 }
4513 }
4514
4515 if (dirty2 & WM2ClientMachine) {
4516 delete[] p->client_machine;
4517 p->client_machine = nullptr;
4518
4519 const QByteArray value = get_string_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4520 if (value.length() > 0) {
4521 p->client_machine = nstrndup(value.constData(), value.length());
4522 }
4523 }
4524
4525 if (dirty2 & WM2Protocols) {
4526 const QList<xcb_atom_t> protocols = get_array_reply<xcb_atom_t>(p->conn, cookies[c++], XCB_ATOM_ATOM);
4527 p->protocols = NET::NoProtocol;
4528 for (auto it = protocols.begin(); it != protocols.end(); ++it) {
4529 if ((*it) == p->atom(WM_TAKE_FOCUS)) {
4530 p->protocols |= TakeFocusProtocol;
4531 } else if ((*it) == p->atom(WM_DELETE_WINDOW)) {
4532 p->protocols |= DeleteWindowProtocol;
4533 } else if ((*it) == p->atom(_NET_WM_PING)) {
4534 p->protocols |= PingProtocol;
4535 } else if ((*it) == p->atom(_NET_WM_SYNC_REQUEST)) {
4536 p->protocols |= SyncRequestProtocol;
4537 } else if ((*it) == p->atom(_NET_WM_CONTEXT_HELP)) {
4538 p->protocols |= ContextHelpProtocol;
4539 }
4540 }
4541 }
4542
4543 if (dirty2 & WM2OpaqueRegion) {
4544 const QList<qint32> values = get_array_reply<qint32>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4545 p->opaqueRegion.clear();
4546 p->opaqueRegion.reserve(values.count() / 4);
4547 for (int i = 0; i < values.count() - 3; i += 4) {
4548 NETRect rect;
4549 rect.pos.x = values.at(i);
4550 rect.pos.y = values.at(i + 1);
4551 rect.size.width = values.at(i + 2);
4552 rect.size.height = values.at(i + 3);
4553 p->opaqueRegion.push_back(rect);
4554 }
4555 }
4556
4557 if (dirty2 & WM2DesktopFileName) {
4558 delete[] p->desktop_file;
4559 p->desktop_file = nullptr;
4560
4561 const QByteArray id = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4562 if (id.length() > 0) {
4563 p->desktop_file = nstrndup(id.constData(), id.length());
4564 }
4565 }
4566
4567 if (dirty2 & WM2GTKApplicationId) {
4568 delete[] p->gtk_application_id;
4569 p->gtk_application_id = nullptr;
4570
4571 const QByteArray id = get_string_reply(p->conn, cookies[c++], p->atom(UTF8_STRING));
4572 if (id.length() > 0) {
4573 p->gtk_application_id = nstrndup(id.constData(), id.length());
4574 }
4575 }
4576
4577 if (dirty2 & WM2GTKFrameExtents) {
4578 p->gtk_frame_extents = NETStrut();
4579
4580 QList<uint32_t> data = get_array_reply<uint32_t>(p->conn, cookies[c++], XCB_ATOM_CARDINAL);
4581 if (data.count() == 4) {
4582 p->gtk_frame_extents.left = data[0];
4583 p->gtk_frame_extents.right = data[1];
4584 p->gtk_frame_extents.top = data[2];
4585 p->gtk_frame_extents.bottom = data[3];
4586 }
4587 }
4588
4589 if (dirty2 & WM2AppMenuObjectPath) {
4590 delete[] p->appmenu_object_path;
4591 p->appmenu_object_path = nullptr;
4592
4593 const QByteArray id = get_string_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4594 if (id.length() > 0) {
4595 p->appmenu_object_path = nstrndup(id.constData(), id.length());
4596 }
4597 }
4598
4599 if (dirty2 & WM2AppMenuServiceName) {
4600 delete[] p->appmenu_service_name;
4601 p->appmenu_service_name = nullptr;
4602
4603 const QByteArray id = get_string_reply(p->conn, cookies[c++], XCB_ATOM_STRING);
4604 if (id.length() > 0) {
4605 p->appmenu_service_name = nstrndup(id.constData(), id.length());
4606 }
4607 }
4608}
4609
4611{
4612 return p->icon_geom;
4613}
4614
4616{
4617 return p->state;
4618}
4619
4621{
4622 return p->strut;
4623}
4624
4626{
4627 return p->extended_strut;
4628}
4629
4631{
4632 return p->fullscreen_monitors;
4633}
4634
4636{
4637 switch (type) {
4638 // clang-format off
4639#define CHECK_TYPE_MASK( type ) \
4640case type: \
4641 if( mask & type##Mask ) \
4642 return true; \
4643 break;
4644 // clang-format on
4645 CHECK_TYPE_MASK(Normal)
4646 CHECK_TYPE_MASK(Desktop)
4647 CHECK_TYPE_MASK(Dock)
4648 CHECK_TYPE_MASK(Toolbar)
4649 CHECK_TYPE_MASK(Menu)
4650 CHECK_TYPE_MASK(Dialog)
4651 CHECK_TYPE_MASK(Override)
4652 CHECK_TYPE_MASK(TopMenu)
4653 CHECK_TYPE_MASK(Utility)
4654 CHECK_TYPE_MASK(Splash)
4655 CHECK_TYPE_MASK(DropdownMenu)
4656 CHECK_TYPE_MASK(PopupMenu)
4657 CHECK_TYPE_MASK(Tooltip)
4658 CHECK_TYPE_MASK(Notification)
4659 CHECK_TYPE_MASK(ComboBox)
4660 CHECK_TYPE_MASK(DNDIcon)
4661 CHECK_TYPE_MASK(OnScreenDisplay)
4662 CHECK_TYPE_MASK(CriticalNotification)
4663 CHECK_TYPE_MASK(AppletPopup)
4664#undef CHECK_TYPE_MASK
4665 default:
4666 break;
4667 }
4668 return false;
4669}
4670
4672{
4673 for (int i = 0; i < p->types.size(); ++i) {
4674 // return the type only if the application supports it
4675 if (typeMatchesMask(p->types[i], supported_types)) {
4676 return p->types[i];
4677 }
4678 }
4679 return Unknown;
4680}
4681
4683{
4684 return p->types.size() > 0;
4685}
4686
4687const char *NETWinInfo::name() const
4688{
4689 return p->name;
4690}
4691
4692const char *NETWinInfo::visibleName() const
4693{
4694 return p->visible_name;
4695}
4696
4697const char *NETWinInfo::iconName() const
4698{
4699 return p->icon_name;
4700}
4701
4703{
4704 return p->visible_icon_name;
4705}
4706
4707int NETWinInfo::desktop(bool ignore_viewport) const
4708{
4709 if (!ignore_viewport && KX11Extras::mapViewport()) {
4710 const KWindowInfo info(p->window, NET::WMDesktop);
4711 return info.desktop();
4712 }
4713 return p->desktop;
4714}
4715
4717{
4718 return p->pid;
4719}
4720
4721xcb_timestamp_t NETWinInfo::userTime() const
4722{
4723 return p->user_time;
4724}
4725
4726const char *NETWinInfo::startupId() const
4727{
4728 return p->startup_id;
4729}
4730
4731unsigned long NETWinInfo::opacity() const
4732{
4733 return p->opacity;
4734}
4735
4737{
4738 if (p->opacity == 0xffffffff) {
4739 return 1.0;
4740 }
4741 return p->opacity * 1.0 / 0xffffffff;
4742}
4743
4745{
4746 return p->allowed_actions;
4747}
4748
4750{
4751 return p->has_net_support;
4752}
4753
4754xcb_window_t NETWinInfo::transientFor() const
4755{
4756 return p->transient_for;
4757}
4758
4759xcb_window_t NETWinInfo::groupLeader() const
4760{
4761 return p->window_group;
4762}
4763
4765{
4766 return p->urgency;
4767}
4768
4770{
4771 return p->input;
4772}
4773
4775{
4776 return p->initialMappingState;
4777}
4778
4780{
4781 return p->icon_pixmap;
4782}
4783
4785{
4786 return p->icon_mask;
4787}
4788
4790{
4791 return p->class_class;
4792}
4793
4795{
4796 return p->class_name;
4797}
4798
4799const char *NETWinInfo::windowRole() const
4800{
4801 return p->window_role;
4802}
4803
4804const char *NETWinInfo::clientMachine() const
4805{
4806 return p->client_machine;
4807}
4808
4809const char *NETWinInfo::activities() const
4810{
4811 return p->activities;
4812}
4813
4814void NETWinInfo::setActivities(const char *activities)
4815{
4816 delete[] p->activities;
4817
4818 if (activities == (char *)nullptr || activities[0] == '\0') {
4819 // on all activities
4820 static const char nulluuid[] = KDE_ALL_ACTIVITIES_UUID;
4821
4822 p->activities = nstrdup(nulluuid);
4823
4824 } else {
4825 p->activities = nstrdup(activities);
4826 }
4827
4828 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_KDE_NET_WM_ACTIVITIES), XCB_ATOM_STRING, 8, strlen(p->activities), p->activities);
4829}
4830
4832{
4833 if (p->role != Client) {
4834 return;
4835 }
4836
4837 p->blockCompositing = active;
4838 if (active) {
4839 uint32_t d = 1;
4840 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_KDE_NET_WM_BLOCK_COMPOSITING), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
4841 xcb_change_property(p->conn, XCB_PROP_MODE_REPLACE, p->window, p->atom(_NET_WM_BYPASS_COMPOSITOR), XCB_ATOM_CARDINAL, 32, 1, (const void *)&d);
4842 } else {
4843 xcb_delete_property(p->conn, p->window, p->atom(_KDE_NET_WM_BLOCK_COMPOSITING));
4844 xcb_delete_property(p->conn, p->window, p->atom(_NET_WM_BYPASS_COMPOSITOR));
4845 }
4846}
4847
4849{
4850 return p->blockCompositing;
4851}
4852
4854{
4855 return p->handled_icons;
4856}
4857
4859{
4860 return p->properties;
4861}
4862
4864{
4865 return p->properties2;
4866}
4867
4869{
4870 return p->mapping_state;
4871}
4872
4874{
4875 return p->protocols;
4876}
4877
4879{
4880 return p->protocols.testFlag(protocol);
4881}
4882
4883std::vector<NETRect> NETWinInfo::opaqueRegion() const
4884{
4885 return p->opaqueRegion;
4886}
4887
4888xcb_connection_t *NETWinInfo::xcbConnection() const
4889{
4890 return p->conn;
4891}
4892
4894{
4895 if (p->role != Client) {
4896 return;
4897 }
4898
4899 delete[] p->desktop_file;
4900 p->desktop_file = nstrdup(name);
4901
4902 xcb_change_property(p->conn,
4903 XCB_PROP_MODE_REPLACE,
4904 p->window,
4905 p->atom(_KDE_NET_WM_DESKTOP_FILE),
4906 p->atom(UTF8_STRING),
4907 8,
4908 strlen(p->desktop_file),
4909 (const void *)p->desktop_file);
4910}
4911
4913{
4914 return p->desktop_file;
4915}
4916
4918{
4919 return p->gtk_application_id;
4920}
4921
4923{
4924 /*BASE::virtual_hook( id, data );*/
4925}
4926
4928{
4929 /*BASE::virtual_hook( id, data );*/
4930}
4931
4932int NET::timestampCompare(unsigned long time1, unsigned long time2)
4933{
4934 return KXUtils::timestampCompare(time1, time2);
4935}
4936
4937int NET::timestampDiff(unsigned long time1, unsigned long time2)
4938{
4939 return KXUtils::timestampDiff(time1, time2);
4940}
4941
4942#endif
This class provides information about a given X11 window.
Definition kwindowinfo.h:60
int desktop() const
Returns the virtual desktop this window is on.
static bool mapViewport()
Returns true if viewports are mapped to virtual desktops.
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 setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
Common API for root window properties/protocols.
Definition netwm.h:41
virtual void closeWindow(xcb_window_t window)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:805
virtual void changeDesktopViewport(int desktop, const NETPoint &viewport)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:781
void setClientList(const xcb_window_t *windows, unsigned int count)
Sets the list of managed windows on the Root/Desktop window.
Definition netwm.cpp:608
int clientListCount() const
Returns the number of managed windows in clientList array.
Definition netwm.cpp:2416
void setDesktopLayout(NET::Orientation orientation, int columns, int rows, NET::DesktopLayoutCorner corner)
Sets the desktop layout.
Definition netwm.cpp:1534
virtual void addClient(xcb_window_t window)
A Client should subclass NETRootInfo and reimplement this function when it wants to know when a windo...
Definition netwm.h:729
NET::States passedStates() const
Definition netwm.cpp:2296
NET::Orientation desktopLayoutOrientation() const
Returns the desktop layout orientation.
Definition netwm.cpp:2475
virtual void moveResizeWindow(xcb_window_t window, int flags, int x, int y, int width, int height)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:878
xcb_connection_t * xcbConnection() const
Returns the xcb connection used.
Definition netwm.cpp:2241
int virtualRootsCount() const
Returns the number of window in the virtualRoots array.
Definition netwm.cpp:2470
void moveResizeRequest(xcb_window_t window, int x_root, int y_root, Direction direction, xcb_button_t button=XCB_BUTTON_INDEX_ANY, RequestSource source=RequestSource::FromUnknown)
Clients (such as pagers/taskbars) that wish to start a WMMoveResize (where the window manager control...
Definition netwm.cpp:1580
xcb_window_t rootWindow() const
Returns the Window id of the rootWindow.
Definition netwm.cpp:2246
virtual void gotPing(xcb_window_t window, xcb_timestamp_t timestamp)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to receive r...
Definition netwm.h:843
void showWindowMenuRequest(xcb_window_t window, int device_id, int x_root, int y_root)
Clients that wish to show the window menu using WM2GTKShowWindowMenu (_GTK_SHOW_WINDOW_MENU) should c...
Definition netwm.cpp:1609
void setDesktopViewport(int desktop, const NETPoint &viewport)
Sets the viewport for the current desktop to the specified point.
Definition netwm.cpp:753
virtual void showWindowMenu(xcb_window_t window, int device_id, int x_root, int y_root)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:929
virtual void restackWindow(xcb_window_t window, RequestSource source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:899
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
virtual void changeActiveWindow(xcb_window_t window, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:858
void restackRequest(xcb_window_t window, RequestSource source, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
Sends the _NET_RESTACK_WINDOW request.
Definition netwm.cpp:1619
void setDesktopName(int desktop, const char *desktopName)
Sets the name of the specified desktop.
Definition netwm.cpp:689
void sendPing(xcb_window_t window, xcb_timestamp_t timestamp)
Sends a ping with the given timestamp to the window, using the _NET_WM_PING protocol.
Definition netwm.cpp:1630
const xcb_window_t * virtualRoots() const
Returns an array of Window id's, which contain the virtual root windows.
Definition netwm.cpp:2465
void activate()
Window Managers must call this after creating the NETRootInfo object, and before using any other meth...
Definition netwm.cpp:590
NET::Properties2 supportedProperties2() const
In the Window Manager mode, this is equivalent to the properties2 argument passed to the constructor.
Definition netwm.cpp:2266
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
NET::Properties passedProperties() const
Definition netwm.cpp:2286
void setWorkArea(int desktop, const NETRect &workArea)
Sets the workarea for the specified desktop.
Definition netwm.cpp:1476
virtual ~NETRootInfo()
Destroys the NETRootInfo object.
Definition netwm.cpp:570
NETRootInfo(xcb_connection_t *connection, xcb_window_t supportWindow, const char *wmName, NET::Properties properties, NET::WindowTypes windowTypes, NET::States states, NET::Properties2 properties2, NET::Actions actions, int screen=-1, bool doActivate=true)
Window Managers should use this constructor to create a NETRootInfo object, which will be used to set...
Definition netwm.cpp:436
NET::WindowTypes passedWindowTypes() const
Definition netwm.cpp:2301
void setSupported(NET::Property property, bool on=true)
Sets the given property if on is true, and clears the property otherwise.
Definition netwm.cpp:2311
virtual void virtual_hook(int id, void *data)
Virtual hook, used to add new "virtual" functions while maintaining binary compatibility.
Definition netwm.cpp:4922
virtual void changeDesktopGeometry(int desktop, const NETSize &geom)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:766
xcb_window_t supportWindow() const
Returns the Window id of the supportWindow.
Definition netwm.cpp:2251
NET::DesktopLayoutCorner desktopLayoutCorner() const
Returns the desktop layout starting corner.
Definition netwm.cpp:2485
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
NET::Properties supportedProperties() const
In the Window Manager mode, this is equivalent to the properties argument passed to the constructor.
Definition netwm.cpp:2261
void closeWindowRequest(xcb_window_t window)
Clients (such as pagers/taskbars) that wish to close a window should call this function.
Definition netwm.cpp:1570
virtual void removeClient(xcb_window_t window)
A Client should subclass NETRootInfo and reimplement this function when it wants to know when a windo...
Definition netwm.h:740
void setShowingDesktop(bool showing)
Sets the _NET_SHOWING_DESKTOP status (whether desktop is being shown).
Definition netwm.cpp:1554
virtual void changeNumberOfDesktops(int numberOfDesktops)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:752
void setDesktopGeometry(const NETSize &geometry)
Sets the desktop geometry to the specified geometry.
Definition netwm.cpp:732
virtual void moveResize(xcb_window_t window, int x_root, int y_root, unsigned long direction, xcb_button_t button, RequestSource source)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:827
void setCurrentDesktop(int desktop, bool ignore_viewport=false)
Sets the current desktop to the specified desktop.
Definition netwm.cpp:667
QSize desktopLayoutColumnsRows() const
Returns the desktop layout number of columns and rows.
Definition netwm.cpp:2480
const xcb_window_t * clientList() const
Returns an array of Window id's, which contain all managed windows.
Definition netwm.cpp:2411
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 setVirtualRoots(const xcb_window_t *windows, unsigned int count)
Sets the list of virtual root windows on the root window.
Definition netwm.cpp:1510
NET::Properties2 passedProperties2() const
Definition netwm.cpp:2291
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
NET::WindowTypes supportedWindowTypes() const
In the Window Manager mode, this is equivalent to the windowTypes argument passed to the constructor.
Definition netwm.cpp:2276
void setNumberOfDesktops(int numberOfDesktops)
Sets the number of desktops to the specified number.
Definition netwm.cpp:650
NETRect workArea(int desktop) const
Returns the workArea for the specified desktop.
Definition netwm.cpp:2446
NET::States supportedStates() const
In the Window Manager mode, this is equivalent to the states argument passed to the constructor.
Definition netwm.cpp:2271
virtual void changeCurrentDesktop(int desktop)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:794
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Definition netwm.cpp:2386
NET::Actions passedActions() const
Definition netwm.cpp:2306
NET::Actions supportedActions() const
In the Window Manager mode, this is equivalent to the actions argument passed to the constructor.
Definition netwm.cpp:2281
void setActiveWindow(xcb_window_t window, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window)
Requests that the specified window becomes the active (focused) one.
Definition netwm.cpp:1459
const NETRootInfo & operator=(const NETRootInfo &rootinfo)
Assignment operator.
Definition netwm.cpp:1647
void setClientListStacking(const xcb_window_t *windows, unsigned int count)
Sets the list of managed windows in stacking order on the Root/Desktop window.
Definition netwm.cpp:626
const char * wmName() const
Returns the name of the Window Manager.
Definition netwm.cpp:2256
virtual void changeShowingDesktop(bool showing)
A Window Manager should subclass NETRootInfo and reimplement this function when it wants to know when...
Definition netwm.h:915
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
bool supportsProtocol(NET::Protocol protocol) const
Definition netwm.cpp:4878
void setHandledIcons(bool handled)
Set whether this application window handles icons.
Definition netwm.cpp:3263
void setPid(int pid)
Set the application window's process id.
Definition netwm.cpp:3252
void setFrameOverlap(NETStrut strut)
Sets the window frame overlap strut, i.e.
Definition netwm.cpp:3381
bool hasWindowType() const
This function returns false if the window has not window type specified at all.
Definition netwm.cpp:4682
xcb_connection_t * xcbConnection() const
Returns the xcb connection used.
Definition netwm.cpp:4888
void event(xcb_generic_event_t *event, NET::Properties *properties, NET::Properties2 *properties2=nullptr)
This function takes the passed in xcb_generic_event_t and returns the updated properties in the passe...
Definition netwm.cpp:3581
void setOpacityF(qreal opacity)
Sets opacity (0 = transparent, 1 = opaque) on the window.
Definition netwm.cpp:3301
void setState(NET::States state, NET::States mask)
Set the state for the application window (see the NET base class documentation for a description of w...
Definition netwm.cpp:2769
const char * gtkApplicationId() const
Definition netwm.cpp:4917
void setOpacity(unsigned long opacity)
Sets opacity (0 = transparent, 0xffffffff = opaque ) on the window.
Definition netwm.cpp:3293
NET::Properties2 passedProperties2() const
Definition netwm.cpp:4863
void kdeGeometry(NETRect &frame, NETRect &window)
Places the window frame geometry in frame, and the application window geometry in window.
Definition netwm.cpp:3472
virtual void changeDesktop(int desktop)
A Window Manager should subclass NETWinInfo and reimplement this function when it wants to know when ...
Definition netwm.h:1669
const char * activities() const
returns a comma-separated list of the activities the window is associated with.
Definition netwm.cpp:4809
bool isBlockingCompositing() const
Returns whether the client wishes to block compositing (for better performance)
Definition netwm.cpp:4848
int desktop(bool ignore_viewport=false) const
Returns the desktop where the window is residing.
Definition netwm.cpp:4707
MappingState initialMappingState() const
Returns the initial mapping state as set in WM_HINTS.
Definition netwm.cpp:4774
const char * name() const
Returns the name of the window in UTF-8 format.
Definition netwm.cpp:4687
xcb_window_t transientFor() const
Returns the WM_TRANSIENT_FOR property for the window, i.e.
Definition netwm.cpp:4754
void setDesktopFileName(const char *name)
Sets the name as the desktop file name.
Definition netwm.cpp:4893
bool input() const
Returns whether the Input flag is set in WM_HINTS.
Definition netwm.cpp:4769
unsigned long opacity() const
Returns the opacity of the window.
Definition netwm.cpp:4731
MappingState mappingState() const
Returns the mapping state for the window (see the NET base class documentation for a description of m...
Definition netwm.cpp:4868
void setStrut(NETStrut strut)
Definition netwm.cpp:2733
virtual void changeState(NET::States state, NET::States mask)
A Window Manager should subclass NETWinInfo and reimplement this function when it wants to know when ...
Definition netwm.h:1683
const char * windowRole() const
Returns the window role for the window (i.e.
Definition netwm.cpp:4799
NET::Properties passedProperties() const
Definition netwm.cpp:4858
NETStrut frameExtents() const
Returns the frame decoration strut, i.e.
Definition netwm.cpp:3376
void setIconName(const char *name)
Sets the iconic name for the application window.
Definition netwm.cpp:3172
NETIcon icon(int width=-1, int height=-1) const
Returns an icon.
Definition netwm.cpp:3508
virtual void changeFullscreenMonitors(NETFullscreenMonitors topology)
A Window Manager should subclass NETWinInfo2 and reimplement this function when it wants to know when...
Definition netwm.h:1697
NET::Protocols protocols() const
Definition netwm.cpp:4873
xcb_pixmap_t icccmIconPixmapMask() const
Returns the mask for the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4784
WindowType windowType(WindowTypes supported_types) const
Returns the window type for this client (see the NET base class documentation for a description of th...
Definition netwm.cpp:4671
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
void setGtkFrameExtents(NETStrut strut)
Sets the extents of the drop-shadow drawn by the client.
Definition netwm.cpp:3406
std::vector< NETRect > opaqueRegion() const
Definition netwm.cpp:4883
NETStrut gtkFrameExtents() const
Returns the extents of the drop-shadow drawn by a GTK client.
Definition netwm.cpp:3419
void setAppMenuServiceName(const char *name)
Sets the name as the D-BUS service name for the application menu.
Definition netwm.cpp:3443
NETExtendedStrut extendedStrut() const
Returns the extended (partial) strut specified by this client.
Definition netwm.cpp:4625
const char * appMenuObjectPath() const
Definition netwm.cpp:3462
const NETWinInfo & operator=(const NETWinInfo &wintinfo)
Assignment operator.
Definition netwm.cpp:2599
const char * visibleIconName() const
Returns the visible iconic name as set by the window manager in UTF-8 format.
Definition netwm.cpp:4702
const char * appMenuServiceName() const
Definition netwm.cpp:3467
const char * iconName() const
Returns the iconic name of the window in UTF-8 format.
Definition netwm.cpp:4697
const int * iconSizes() const
Returns a list of provided icon sizes.
Definition netwm.cpp:3513
void setActivities(const char *activities)
Sets the comma-separated list of activities the window is associated with.
Definition netwm.cpp:4814
xcb_pixmap_t icccmIconPixmap() const
Returns the icon pixmap as set in WM_HINTS.
Definition netwm.cpp:4779
const char * desktopFileName() const
Definition netwm.cpp:4912
NET::States state() const
Returns the state of the window (see the NET base class documentation for a description of the variou...
Definition netwm.cpp:4615
const char * startupId() const
Returns the startup notification id of the window.
Definition netwm.cpp:4726
void setFrameExtents(NETStrut strut)
Set the frame decoration strut, i.e.
Definition netwm.cpp:3358
qreal opacityF() const
Returns the opacity of the window.
Definition netwm.cpp:4736
void setWindowType(WindowType type)
Sets the window type for this client (see the NET base class documentation for a description of the v...
Definition netwm.cpp:3000
virtual void virtual_hook(int id, void *data)
Virtual hook, used to add new "virtual" functions while maintaining binary compatibility.
Definition netwm.cpp:4927
NETStrut frameOverlap() const
Returns the frame overlap strut, i.e.
Definition netwm.cpp:3401
const char * clientMachine() const
Returns the client machine for the window (i.e.
Definition netwm.cpp:4804
void setVisibleName(const char *visibleName)
For Window Managers only: set the visible name ( i.e.
Definition netwm.cpp:3149
void setBlockingCompositing(bool active)
Sets whether the client wishes to block compositing (for better performance)
Definition netwm.cpp:4831
bool handledIcons() const
Returns whether or not this client handles icons.
Definition netwm.cpp:4853
void setVisibleIconName(const char *name)
For Window Managers only: set the visible iconic name ( i.e.
Definition netwm.cpp:3195
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 * visibleName() const
Returns the visible name as set by the window manager in UTF-8 format.
Definition netwm.cpp:4692
xcb_window_t groupLeader() const
Returns the leader window for the group the window is in, if any.
Definition netwm.cpp:4759
void setStartupId(const char *startup_id)
Sets the startup notification id id on the window.
Definition netwm.cpp:3274
bool hasNETSupport() const
Returns true if the window has any window type set, even if the type itself is not known to this impl...
Definition netwm.cpp:4749
xcb_timestamp_t userTime() const
Returns the time of last user action on the window, or -1 if not set.
Definition netwm.cpp:4721
int pid() const
Returns the process id for the client window.
Definition netwm.cpp:4716
NETWinInfo(xcb_connection_t *connection, xcb_window_t window, xcb_window_t rootWindow, NET::Properties properties, NET::Properties2 properties2, Role role=Client)
Create a NETWinInfo object, which will be used to set/read/change information stored on an applicatio...
Definition netwm.cpp:2515
bool urgency() const
Returns whether the UrgencyHint is set in the WM_HINTS.flags.
Definition netwm.cpp:4764
void setFullscreenMonitors(NETFullscreenMonitors topology)
Sets the desired multiple-monitor topology (4 monitor indices indicating the top, bottom,...
Definition netwm.cpp:2750
virtual ~NETWinInfo()
Destroys the NETWinInfo object.
Definition netwm.cpp:2588
void setAppMenuObjectPath(const char *path)
Sets the name as the D-BUS object path for the application menu.
Definition netwm.cpp:3424
void setUserTime(xcb_timestamp_t time)
Sets user timestamp time on the window (property _NET_WM_USER_TIME).
Definition netwm.cpp:3562
void setIcon(NETIcon icon, bool replace=true)
Set icons for the application window.
Definition netwm.cpp:2619
NET::Actions allowedActions() const
Returns actions that the window manager allows for the window.
Definition netwm.cpp:4744
NETFullscreenMonitors fullscreenMonitors() const
Returns the desired fullscreen monitor topology for this client, should it be in fullscreen state.
Definition netwm.cpp:4630
const char * windowClassName() const
Returns the name component of the window class for the window (i.e.
Definition netwm.cpp:4794
void setAllowedActions(NET::Actions actions)
Sets actions that the window manager allows for the window.
Definition netwm.cpp:3306
const char * windowClassClass() const
Returns the class component of the window class for the window (i.e.
Definition netwm.cpp:4789
NETRect iconGeometry() const
Returns the icon geometry.
Definition netwm.cpp:4610
void setIconGeometry(NETRect geometry)
Set the icon geometry for the application window.
Definition netwm.cpp:2681
void setName(const char *name)
Sets the name for the application window.
Definition netwm.cpp:3133
Protocol
Protocols supported by the client.
Definition netwm_def.h:881
@ DeleteWindowProtocol
WM_DELETE_WINDOW.
Definition netwm_def.h:884
@ ContextHelpProtocol
_NET_WM_CONTEXT_HELP, NON STANDARD!
Definition netwm_def.h:887
@ TakeFocusProtocol
WM_TAKE_FOCUS.
Definition netwm_def.h:883
@ PingProtocol
_NET_WM_PING from EWMH
Definition netwm_def.h:885
@ SyncRequestProtocol
_NET_WM_SYNC_REQUEST from EWMH
Definition netwm_def.h:886
State
Window state.
Definition netwm_def.h:503
@ MaxHoriz
indicates that the window is horizontally maximized.
Definition netwm_def.h:523
@ Sticky
indicates that the Window Manager SHOULD keep the window's position fixed on the screen,...
Definition netwm_def.h:515
@ Max
convenience value.
Definition netwm_def.h:527
@ Shaded
indicates that the window is shaded (rolled-up).
Definition netwm_def.h:531
@ MaxVert
indicates that the window is vertically maximized.
Definition netwm_def.h:519
@ DemandsAttention
there was an attempt to activate this window, but the window manager prevented this.
Definition netwm_def.h:564
@ SkipTaskbar
indicates that a window should not be included on a taskbar.
Definition netwm_def.h:535
@ FullScreen
indicates that a window should fill the entire screen and have no window decorations.
Definition netwm_def.h:554
@ SkipSwitcher
indicates that a window should not be included on a switcher.
Definition netwm_def.h:570
@ Modal
indicates that this is a modal dialog box.
Definition netwm_def.h:509
@ KeepAbove
indicates that a window should on top of most windows (but below fullscreen windows).
Definition netwm_def.h:540
@ Hidden
indicates that a window should not be visible on the screen (e.g.
Definition netwm_def.h:549
@ SkipPager
indicates that a window should not be included on a pager.
Definition netwm_def.h:544
@ KeepBelow
indicates that a window should be below most windows (but above any desktop windows).
Definition netwm_def.h:558
@ Focused
indicates that a client should render as though it has focus Only the window manager is allowed to ch...
Definition netwm_def.h:576
WindowTypeMask
Values for WindowType when they should be OR'ed together, e.g.
Definition netwm_def.h:453
@ DialogMask
Definition netwm_def.h:459
@ TooltipMask
Definition netwm_def.h:466
@ MenuMask
Definition netwm_def.h:458
@ OnScreenDisplayMask
NON STANDARD.
Definition netwm_def.h:470
@ SplashMask
Definition netwm_def.h:463
@ UtilityMask
Definition netwm_def.h:462
@ OverrideMask
Definition netwm_def.h:460
@ DNDIconMask
Definition netwm_def.h:469
@ ToolbarMask
Definition netwm_def.h:457
@ DockMask
Definition netwm_def.h:456
@ PopupMenuMask
Definition netwm_def.h:465
@ CriticalNotificationMask
NON STANDARD.
Definition netwm_def.h:471
@ NormalMask
Definition netwm_def.h:454
@ DesktopMask
Definition netwm_def.h:455
@ TopMenuMask
Definition netwm_def.h:461
@ NotificationMask
Definition netwm_def.h:467
@ AppletPopupMask
NON STANDARD.
Definition netwm_def.h:472
@ DropdownMenuMask
Definition netwm_def.h:464
@ ComboBoxMask
Definition netwm_def.h:468
QFlags< WindowTypeMask > WindowTypes
Stores a combination of WindowTypeMask values.
Definition netwm_def.h:478
QFlags< State > States
Stores a combination of State values.
Definition netwm_def.h:581
static bool typeMatchesMask(WindowType type, WindowTypes mask)
Returns true if the given window type matches the mask given using WindowTypeMask flags.
Definition netwm.cpp:4635
QFlags< Property2 > Properties2
Stores a combination of Property2 values.
Definition netwm_def.h:827
DesktopLayoutCorner
Starting corner for desktop layout.
Definition netwm_def.h:867
WindowType
Window type.
Definition netwm_def.h:357
@ Splash
indicates that this window is a splash screen window.
Definition netwm_def.h:407
@ Notification
indicates a notification window
Definition netwm_def.h:423
@ Override
Definition netwm_def.h:394
@ Desktop
indicates a desktop feature.
Definition netwm_def.h:372
@ DNDIcon
indicates a window that represents the dragged object during DND operation
Definition netwm_def.h:431
@ Normal
indicates that this is a normal, top-level window
Definition netwm_def.h:365
@ Unknown
indicates that the window did not define a window type.
Definition netwm_def.h:361
@ OnScreenDisplay
indicates an On Screen Display window (such as volume feedback)
Definition netwm_def.h:436
@ TopMenu
indicates a toplevel menu (AKA macmenu).
Definition netwm_def.h:399
@ AppletPopup
indicates that this window is an applet.
Definition netwm_def.h:445
@ Tooltip
indicates a tooltip window
Definition netwm_def.h:419
@ Dialog
indicates that this is a dialog window
Definition netwm_def.h:388
@ Toolbar
indicates a toolbar window
Definition netwm_def.h:380
@ Menu
indicates a pinnable (torn-off) menu window
Definition netwm_def.h:384
@ DropdownMenu
indicates a dropdown menu (from a menubar typically)
Definition netwm_def.h:411
@ PopupMenu
indicates a popup menu (a context menu typically)
Definition netwm_def.h:415
@ CriticalNotification
indicates a critical notification (such as battery is running out)
Definition netwm_def.h:441
@ ComboBox
indicates that the window is a list for a combobox
Definition netwm_def.h:427
@ Dock
indicates a dock or panel feature
Definition netwm_def.h:376
@ Utility
indicates a utility window
Definition netwm_def.h:403
Role
Application role.
Definition netwm_def.h:342
@ Client
indicates that the application is a client application.
Definition netwm_def.h:346
@ WindowManager
indicates that the application is a window manager application.
Definition netwm_def.h:350
Property2
Supported properties.
Definition netwm_def.h:788
QFlags< Property > Properties
Stores a combination of Property values.
Definition netwm_def.h:750
static int timestampCompare(unsigned long time1, unsigned long time2)
Compares two X timestamps, taking into account wrapping and 64bit architectures.
Definition netwm.cpp:4932
QFlags< Action > Actions
Stores a combination of Action values.
Definition netwm_def.h:660
Property
Supported properties.
Definition netwm_def.h:708
RequestSource
Source of the request.
Definition netwm_def.h:841
@ FromTool
indicated that the request comes from pager or similar tool
Definition netwm_def.h:853
@ FromUnknown
Definition netwm_def.h:845
Direction
Direction for WMMoveResize.
Definition netwm_def.h:602
static int timestampDiff(unsigned long time1, unsigned long time2)
Returns a difference of two X timestamps, time2 - time1, where time2 must be later than time1,...
Definition netwm.cpp:4937
Action
Actions that can be done with a window (_NET_WM_ALLOWED_ACTIONS).
Definition netwm_def.h:644
Orientation
Orientation.
Definition netwm_def.h:859
MappingState
Client window mapping state.
Definition netwm_def.h:623
@ Iconic
indicates that the client window is not visible, but its icon is.
Definition netwm_def.h:637
@ Withdrawn
indicates that neither the client window nor its icon is visible.
Definition netwm_def.h:631
@ Visible
indicates the client window is visible to the user.
Definition netwm_def.h:627
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
QWidget * window(QObject *job)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const char * constData() const const
qsizetype length() const const
QList< QByteArray > split(char sep) const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
iterator begin()
qsizetype count() const const
iterator end()
T & first()
bool isEmpty() const const
void reserve(qsizetype size)
void resize(qsizetype size)
qsizetype size() 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 multiple monitor topology class for NET classes.
Definition netwm_def.h:277
int right
Monitor index whose right border defines the right edge of the topology.
Definition netwm_def.h:308
int top
Monitor index whose top border defines the top edge of the topology.
Definition netwm_def.h:293
int left
Monitor index whose left border defines the left edge of the topology.
Definition netwm_def.h:303
int bottom
Monitor index whose bottom border defines the bottom edge of the topology.
Definition netwm_def.h:298
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 20 2024 11:51:19 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.