KWindowSystem

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

KDE's Doxygen guidelines are available online.