• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

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

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.