KWindowSystem

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

KDE's Doxygen guidelines are available online.