KWindowSystem

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

KDE's Doxygen guidelines are available online.