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

KDE's Doxygen guidelines are available online.