~ubuntu-branches/ubuntu/gutsy/kde4libs/gutsy

« back to all changes in this revision

Viewing changes to kdeui/windowmanagement/netwm.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-02-21 11:00:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070221110012-6kw8khr9knv6lmg1
Tags: 3.80.3-0ubuntu1
New upstream unstable release

Show diffs side-by-side

added added

removed removed

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