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

KDE's Doxygen guidelines are available online.