kdecore Library: netwm.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# netwm.cpp

    00001 /*
    00002
    00003   Copyright (c) 2000 Troll Tech AS
    00004   Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
    00005
    00006   Permission is hereby granted, free of charge, to any person obtaining a
    00007   copy of this software and associated documentation files (the "Software"),
    00008   to deal in the Software without restriction, including without limitation
    00009   the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00010   and/or sell copies of the Software, and to permit persons to whom the
    00011   Software is furnished to do so, subject to the following conditions:
    00012
    00013   The above copyright notice and this permission notice shall be included in
    00014   all copies or substantial portions of the Software.
    00015
    00016   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00017   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00018   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    00019   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00020   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00021   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00022   DEALINGS IN THE SOFTWARE.
    00023
    00024 */
    00025
    00026 //#define NETWMDEBUG
    00027
    00028 #include <qwidget.h>
    00029 #ifdef Q_WS_X11 //FIXME
    00030
    00031 #include "netwm.h"
    00032
    00033 #include <string.h>
    00034 #include <stdio.h>
    00035 #include <assert.h>
    00036 #include <stdlib.h>
    00037
    00038 #include <X11/Xmd.h>
    00039
    00040 #include "netwm_p.h"
    00041
    00042 // UTF-8 string
    00043 static Atom UTF8_STRING = 0;
    00044
    00045 // root window properties
    00046 static Atom net_supported            = 0;
    00047 static Atom net_client_list          = 0;
    00048 static Atom net_client_list_stacking = 0;
    00049 static Atom net_desktop_geometry     = 0;
    00050 static Atom net_desktop_viewport     = 0;
    00051 static Atom net_current_desktop      = 0;
    00052 static Atom net_desktop_names        = 0;
    00053 static Atom net_number_of_desktops   = 0;
    00054 static Atom net_active_window        = 0;
    00055 static Atom net_workarea             = 0;
    00056 static Atom net_supporting_wm_check  = 0;
    00057 static Atom net_virtual_roots        = 0;
    00058
    00059 // root window messages
    00060 static Atom net_close_window         = 0;
    00061 static Atom net_restack_window       = 0;
    00062 static Atom net_wm_moveresize        = 0;
    00063 static Atom net_moveresize_window    = 0;
    00064
    00065 // application window properties
    00066 static Atom net_wm_name              = 0;
    00067 static Atom net_wm_visible_name      = 0;
    00068 static Atom net_wm_icon_name         = 0;
    00069 static Atom net_wm_visible_icon_name = 0;
    00070 static Atom net_wm_desktop           = 0;
    00071 static Atom net_wm_window_type       = 0;
    00072 static Atom net_wm_state             = 0;
    00073 static Atom net_wm_strut             = 0;
    00074 static Atom net_wm_extended_strut    = 0; // the atom is called _NET_WM_STRUT_PARTIAL
    00075 static Atom net_wm_icon_geometry     = 0;
    00076 static Atom net_wm_icon              = 0;
    00077 static Atom net_wm_pid               = 0;
    00078 static Atom net_wm_user_time         = 0;
    00079 static Atom net_wm_handled_icons     = 0;
    00080 static Atom net_startup_id           = 0;
    00081 static Atom net_wm_allowed_actions   = 0;
    00082 static Atom wm_window_role           = 0;
    00083
    00084 // KDE extensions
    00085 static Atom kde_net_system_tray_windows       = 0;
    00086 static Atom kde_net_wm_system_tray_window_for = 0;
    00087 static Atom kde_net_wm_frame_strut            = 0;
    00088 static Atom kde_net_wm_window_type_override   = 0;
    00089 static Atom kde_net_wm_window_type_topmenu    = 0;
    00090 static Atom kde_net_wm_temporary_rules        = 0;
    00091
    00092 // application protocols
    00093 static Atom wm_protocols = 0;
    00094 static Atom net_wm_ping = 0;
    00095 static Atom net_wm_take_activity = 0;
    00096
    00097 // application window types
    00098 static Atom net_wm_window_type_normal  = 0;
    00099 static Atom net_wm_window_type_desktop = 0;
    00100 static Atom net_wm_window_type_dock    = 0;
    00101 static Atom net_wm_window_type_toolbar = 0;
    00102 static Atom net_wm_window_type_menu    = 0;
    00103 static Atom net_wm_window_type_dialog  = 0;
    00104 static Atom net_wm_window_type_utility = 0;
    00105 static Atom net_wm_window_type_splash  = 0;
    00106
    00107 // application window state
    00108 static Atom net_wm_state_modal        = 0;
    00109 static Atom net_wm_state_sticky       = 0;
    00110 static Atom net_wm_state_max_vert     = 0;
    00111 static Atom net_wm_state_max_horiz    = 0;
    00112 static Atom net_wm_state_shaded       = 0;
    00113 static Atom net_wm_state_skip_taskbar = 0;
    00114 static Atom net_wm_state_skip_pager   = 0;
    00115 static Atom net_wm_state_hidden       = 0;
    00116 static Atom net_wm_state_fullscreen   = 0;
    00117 static Atom net_wm_state_above        = 0;
    00118 static Atom net_wm_state_below        = 0;
    00119 static Atom net_wm_state_demands_attention = 0;
    00120
    00121 // allowed actions
    00122 static Atom net_wm_action_move        = 0;
    00123 static Atom net_wm_action_resize      = 0;
    00124 static Atom net_wm_action_minimize    = 0;
    00125 static Atom net_wm_action_shade       = 0;
    00126 static Atom net_wm_action_stick       = 0;
    00127 static Atom net_wm_action_max_vert    = 0;
    00128 static Atom net_wm_action_max_horiz   = 0;
    00129 static Atom net_wm_action_fullscreen  = 0;
    00130 static Atom net_wm_action_change_desk = 0;
    00131 static Atom net_wm_action_close       = 0;
    00132
    00133 // KDE extension that's not in the specs - Replaced by state_above now?
    00134 static Atom net_wm_state_stays_on_top = 0;
    00135
    00136 // used to determine whether application window is managed or not
    00137 static Atom xa_wm_state = 0;
    00138
    00139 static Bool netwm_atoms_created      = False;
    00140 const unsigned long netwm_sendevent_mask = (SubstructureRedirectMask|
    00141                          SubstructureNotifyMask);
    00142
    00143
    00144 const long MAX_PROP_SIZE = 100000;
    00145
    00146 static char *nstrdup(const char *s1) {
    00147     if (! s1) return (char *) 0;
    00148
    00149     int l = strlen(s1) + 1;
    00150     char *s2 = new char[l];
    00151     strncpy(s2, s1, l);
    00152     return s2;
    00153 }
    00154
    00155
    00156 static char *nstrndup(const char *s1, int l) {
    00157     if (! s1 || l == 0) return (char *) 0;
    00158
    00159     char *s2 = new char[l+1];
    00160     strncpy(s2, s1, l);
    00161     s2[l] = '\0';
    00162     return s2;
    00163 }
    00164
    00165
    00166 static Window *nwindup(Window *w1, int n) {
    00167     if (! w1 || n == 0) return (Window *) 0;
    00168
    00169     Window *w2 = new Window[n];
    00170     while (n--) w2[n] = w1[n];
    00171     return w2;
    00172 }
    00173
    00174
    00175 static void refdec_nri(NETRootInfoPrivate *p) {
    00176
    00177 #ifdef    NETWMDEBUG
    00178     fprintf(stderr, "NET: decrementing NETRootInfoPrivate::ref (%d)\n", p->ref - 1);
    00179 #endif
    00180
    00181     if (! --p->ref) {
    00182
    00183 #ifdef    NETWMDEBUG
    00184     fprintf(stderr, "NET: \tno more references, deleting\n");
    00185 #endif
    00186
    00187     delete [] p->name;
    00188     delete [] p->stacking;
    00189     delete [] p->clients;
    00190     delete [] p->virtual_roots;
    00191     delete [] p->kde_system_tray_windows;
    00192
    00193     int i;
    00194     for (i = 0; i < p->desktop_names.size(); i++)
    00195         delete [] p->desktop_names[i];
    00196     }
    00197 }
    00198
    00199
    00200 static void refdec_nwi(NETWinInfoPrivate *p) {
    00201
    00202 #ifdef    NETWMDEBUG
    00203     fprintf(stderr, "NET: decrementing NETWinInfoPrivate::ref (%d)\n", p->ref - 1);
    00204 #endif
    00205
    00206     if (! --p->ref) {
    00207
    00208 #ifdef    NETWMDEBUG
    00209     fprintf(stderr, "NET: \tno more references, deleting\n");
    00210 #endif
    00211
    00212     delete [] p->name;
    00213     delete [] p->visible_name;
    00214     delete [] p->icon_name;
    00215     delete [] p->visible_icon_name;
    00216     delete [] p->startup_id;
    00217
    00218     int i;
    00219     for (i = 0; i < p->icons.size(); i++)
    00220         delete [] p->icons[i].data;
    00221     }
    00222 }
    00223
    00224
    00225 static int wcmp(const void *a, const void *b) {
    00226     return *((Window *) a) - *((Window *) b);
    00227 }
    00228
    00229
    00230 static const int netAtomCount = 75;
    00231 static void create_atoms(Display *d) {
    00232     static const char * const names[netAtomCount] =
    00233     {
    00234     "UTF8_STRING",
    00235         "_NET_SUPPORTED",
    00236         "_NET_SUPPORTING_WM_CHECK",
    00237         "_NET_CLIENT_LIST",
    00238         "_NET_CLIENT_LIST_STACKING",
    00239         "_NET_NUMBER_OF_DESKTOPS",
    00240         "_NET_DESKTOP_GEOMETRY",
    00241         "_NET_DESKTOP_VIEWPORT",
    00242         "_NET_CURRENT_DESKTOP",
    00243         "_NET_DESKTOP_NAMES",
    00244         "_NET_ACTIVE_WINDOW",
    00245         "_NET_WORKAREA",
    00246         "_NET_VIRTUAL_ROOTS",
    00247         "_NET_CLOSE_WINDOW",
    00248             "_NET_RESTACK_WINDOW",
    00249
    00250         "_NET_WM_MOVERESIZE",
    00251             "_NET_MOVERESIZE_WINDOW",
    00252         "_NET_WM_NAME",
    00253         "_NET_WM_VISIBLE_NAME",
    00254         "_NET_WM_ICON_NAME",
    00255         "_NET_WM_VISIBLE_ICON_NAME",
    00256         "_NET_WM_DESKTOP",
    00257         "_NET_WM_WINDOW_TYPE",
    00258         "_NET_WM_STATE",
    00259         "_NET_WM_STRUT",
    00260             "_NET_WM_STRUT_PARTIAL",
    00261         "_NET_WM_ICON_GEOMETRY",
    00262         "_NET_WM_ICON",
    00263         "_NET_WM_PID",
    00264         "_NET_WM_USER_TIME",
    00265         "_NET_WM_HANDLED_ICONS",
    00266             "_NET_STARTUP_ID",
    00267             "_NET_WM_ALLOWED_ACTIONS",
    00268         "_NET_WM_PING",
    00269             "_NET_WM_TAKE_ACTIVITY",
    00270             "WM_WINDOW_ROLE",
    00271
    00272         "_NET_WM_WINDOW_TYPE_NORMAL",
    00273         "_NET_WM_WINDOW_TYPE_DESKTOP",
    00274         "_NET_WM_WINDOW_TYPE_DOCK",
    00275         "_NET_WM_WINDOW_TYPE_TOOLBAR",
    00276         "_NET_WM_WINDOW_TYPE_MENU",
    00277         "_NET_WM_WINDOW_TYPE_DIALOG",
    00278         "_NET_WM_WINDOW_TYPE_UTILITY",
    00279         "_NET_WM_WINDOW_TYPE_SPLASH",
    00280
    00281         "_NET_WM_STATE_MODAL",
    00282         "_NET_WM_STATE_STICKY",
    00283         "_NET_WM_STATE_MAXIMIZED_VERT",
    00284         "_NET_WM_STATE_MAXIMIZED_HORZ",
    00285         "_NET_WM_STATE_SHADED",
    00286         "_NET_WM_STATE_SKIP_TASKBAR",
    00287         "_NET_WM_STATE_SKIP_PAGER",
    00288         "_NET_WM_STATE_HIDDEN",
    00289         "_NET_WM_STATE_FULLSCREEN",
    00290         "_NET_WM_STATE_ABOVE",
    00291         "_NET_WM_STATE_BELOW",
    00292         "_NET_WM_STATE_DEMANDS_ATTENTION",
    00293
    00294             "_NET_WM_ACTION_MOVE",
    00295             "_NET_WM_ACTION_RESIZE",
    00296             "_NET_WM_ACTION_MINIMIZE",
    00297             "_NET_WM_ACTION_SHADE",
    00298             "_NET_WM_ACTION_STICK",
    00299             "_NET_WM_ACTION_MAXIMIZE_VERT",
    00300             "_NET_WM_ACTION_MAXIMIZE_HORZ",
    00301             "_NET_WM_ACTION_FULLSCREEN",
    00302             "_NET_WM_ACTION_CHANGE_DESKTOP",
    00303             "_NET_WM_ACTION_CLOSE",
    00304
    00305         "_NET_WM_STATE_STAYS_ON_TOP",
    00306
    00307         "_KDE_NET_SYSTEM_TRAY_WINDOWS",
    00308         "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
    00309         "_KDE_NET_WM_FRAME_STRUT",
    00310         "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE",
    00311         "_KDE_NET_WM_WINDOW_TYPE_TOPMENU",
    00312             "_KDE_NET_WM_TEMPORARY_RULES",
    00313
    00314         "WM_STATE",
    00315         "WM_PROTOCOLS"
    00316         };
    00317
    00318     Atom atoms[netAtomCount], *atomsp[netAtomCount] =
    00319     {
    00320     &UTF8_STRING,
    00321         &net_supported,
    00322         &net_supporting_wm_check,
    00323         &net_client_list,
    00324         &net_client_list_stacking,
    00325         &net_number_of_desktops,
    00326         &net_desktop_geometry,
    00327         &net_desktop_viewport,
    00328         &net_current_desktop,
    00329         &net_desktop_names,
    00330         &net_active_window,
    00331         &net_workarea,
    00332         &net_virtual_roots,
    00333         &net_close_window,
    00334             &net_restack_window,
    00335
    00336         &net_wm_moveresize,
    00337             &net_moveresize_window,
    00338         &net_wm_name,
    00339         &net_wm_visible_name,
    00340         &net_wm_icon_name,
    00341         &net_wm_visible_icon_name,
    00342         &net_wm_desktop,
    00343         &net_wm_window_type,
    00344         &net_wm_state,
    00345         &net_wm_strut,
    00346             &net_wm_extended_strut,
    00347         &net_wm_icon_geometry,
    00348         &net_wm_icon,
    00349         &net_wm_pid,
    00350         &net_wm_user_time,
    00351         &net_wm_handled_icons,
    00352             &net_startup_id,
    00353             &net_wm_allowed_actions,
    00354         &net_wm_ping,
    00355             &net_wm_take_activity,
    00356             &wm_window_role,
    00357
    00358         &net_wm_window_type_normal,
    00359         &net_wm_window_type_desktop,
    00360         &net_wm_window_type_dock,
    00361         &net_wm_window_type_toolbar,
    00362         &net_wm_window_type_menu,
    00363         &net_wm_window_type_dialog,
    00364         &net_wm_window_type_utility,
    00365         &net_wm_window_type_splash,
    00366
    00367         &net_wm_state_modal,
    00368         &net_wm_state_sticky,
    00369         &net_wm_state_max_vert,
    00370         &net_wm_state_max_horiz,
    00371         &net_wm_state_shaded,
    00372         &net_wm_state_skip_taskbar,
    00373         &net_wm_state_skip_pager,
    00374         &net_wm_state_hidden,
    00375         &net_wm_state_fullscreen,
    00376         &net_wm_state_above,
    00377         &net_wm_state_below,
    00378         &net_wm_state_demands_attention,
    00379
    00380             &net_wm_action_move,
    00381             &net_wm_action_resize,
    00382             &net_wm_action_minimize,
    00383             &net_wm_action_shade,
    00384             &net_wm_action_stick,
    00385             &net_wm_action_max_vert,
    00386             &net_wm_action_max_horiz,
    00387             &net_wm_action_fullscreen,
    00388             &net_wm_action_change_desk,
    00389             &net_wm_action_close,
    00390
    00391         &net_wm_state_stays_on_top,
    00392
    00393         &kde_net_system_tray_windows,
    00394         &kde_net_wm_system_tray_window_for,
    00395         &kde_net_wm_frame_strut,
    00396         &kde_net_wm_window_type_override,
    00397         &kde_net_wm_window_type_topmenu,
    00398             &kde_net_wm_temporary_rules,
    00399
    00400         &xa_wm_state,
    00401         &wm_protocols
    00402         };
    00403
    00404     assert( !netwm_atoms_created );
    00405
    00406     int i = netAtomCount;
    00407     while (i--)
    00408     atoms[i] = 0;
    00409
    00410     XInternAtoms(d, (char **) names, netAtomCount, False, atoms);
    00411
    00412     i = netAtomCount;
    00413     while (i--)
    00414     *atomsp[i] = atoms[i];
    00415
    00416     netwm_atoms_created = True;
    00417 }
    00418
    00419
    00420 static void readIcon(NETWinInfoPrivate *p) {
    00421
    00422 #ifdef    NETWMDEBUG
    00423     fprintf(stderr, "NET: readIcon\n");
    00424 #endif
    00425
    00426     Atom type_ret;
    00427     int format_ret;
    00428     unsigned long nitems_ret = 0, after_ret = 0;
    00429     unsigned char *data_ret = 0;
    00430
    00431     // reset
    00432     for (int i = 0; i < p->icons.size(); i++)
    00433         delete [] p->icons[i].data;
    00434     p->icons.reset();
    00435     p->icon_count = 0;
    00436
    00437     // allocate buffers
    00438     unsigned char *buffer = 0;
    00439     unsigned long offset = 0;
    00440     unsigned long buffer_offset = 0;
    00441     unsigned long bufsize = 0;
    00442
    00443     // read data
    00444     do {
    00445     if (XGetWindowProperty(p->display, p->window, net_wm_icon, offset,
    00446                    MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret,
    00447                    &format_ret, &nitems_ret, &after_ret, &data_ret)
    00448         == Success) {
    00449             if (!bufsize)
    00450             {
    00451                if (nitems_ret < 3 || type_ret != XA_CARDINAL ||
    00452                   format_ret != 32) {
    00453                   // either we didn't get the property, or the property has less than
    00454                   // 3 elements in it
    00455                   // NOTE: 3 is the ABSOLUTE minimum:
    00456                   //     width = 1, height = 1, length(data) = 1 (width * height)
    00457                   if ( data_ret )
    00458                      XFree(data_ret);
    00459                   return;
    00460                }
    00461
    00462                bufsize = nitems_ret * sizeof(long) + after_ret;
    00463                buffer = (unsigned char *) malloc(bufsize);
    00464             }
    00465             else if (buffer_offset + nitems_ret*sizeof(long) > bufsize)
    00466             {
    00467 fprintf(stderr, "NETWM: Warning readIcon() needs buffer adjustment!\n");
    00468                bufsize = buffer_offset + nitems_ret * sizeof(long) + after_ret;
    00469                buffer = (unsigned char *) realloc(buffer, bufsize);
    00470             }
    00471         memcpy((buffer + buffer_offset), data_ret, nitems_ret * sizeof(long));
    00472         buffer_offset += nitems_ret * sizeof(long);
    00473         offset += nitems_ret;
    00474
    00475         if ( data_ret )
    00476         XFree(data_ret);
    00477     } else {
    00478             if (buffer)
    00479                free(buffer);
    00480         return; // Some error occurred cq. property didn't exist.
    00481     }
    00482     }
    00483     while (after_ret > 0);
    00484
    00485     CARD32 *data32;
    00486     unsigned long i, j, k, sz, s;
    00487     unsigned long *d = (unsigned long *) buffer;
    00488     for (i = 0, j = 0; i < bufsize; i++) {
    00489     p->icons[j].size.width = *d++;
    00490     i += sizeof(long);
    00491     p->icons[j].size.height = *d++;
    00492     i += sizeof(long);
    00493
    00494     sz = p->icons[j].size.width * p->icons[j].size.height;
    00495     s = sz * sizeof(long);
    00496
    00497     if ( i + s - 1 > bufsize || sz == 0 || sz > 1024 * 1024 ) {
    00498         break;
    00499     }
    00500
    00501     delete [] p->icons[j].data;
    00502     data32 = new CARD32[sz];
    00503     p->icons[j].data = (unsigned char *) data32;
    00504     for (k = 0; k < sz; k++, i += sizeof(long)) {
    00505         *data32++ = (CARD32) *d++;
    00506     }
    00507     j++;
    00508         p->icon_count++;
    00509     }
    00510
    00511 #ifdef    NETWMDEBUG
    00512     fprintf(stderr, "NET: readIcon got %d icons\n", p->icon_count);
    00513 #endif
    00514
    00515     free(buffer);
    00516 }
    00517
    00518
    00519 template <class Z>
    00520 NETRArray<Z>::NETRArray()
    00521   : sz(0),  capacity(2)
    00522 {
    00523     d = (Z*) calloc(capacity, sizeof(Z)); // allocate 2 elts and set to zero
    00524 }
    00525
    00526
    00527 template <class Z>
    00528 NETRArray<Z>::~NETRArray() {
    00529     free(d);
    00530 }
    00531
    00532
    00533 template <class Z>
    00534 void NETRArray<Z>::reset() {
    00535     sz = 0;
    00536     capacity = 2;
    00537     d = (Z*) realloc(d, sizeof(Z)*capacity);
    00538     memset( (void*) d, 0, sizeof(Z)*capacity );
    00539 }
    00540
    00541 template <class Z>
    00542 Z &NETRArray<Z>::operator[](int index) {
    00543     if (index >= capacity) {
    00544     // allocate space for the new data
    00545     // open table has amortized O(1) access time
    00546     // when N elements appended consecutively -- exa
    00547         int newcapacity = 2*capacity > index+1 ? 2*capacity : index+1; // max
    00548     // copy into new larger memory block using realloc
    00549         d = (Z*) realloc(d, sizeof(Z)*newcapacity);
    00550         memset( (void*) &d[capacity], 0, sizeof(Z)*(newcapacity-capacity) );
    00551     capacity = newcapacity;
    00552     }
    00553     if (index >= sz)            // at this point capacity>index
    00554         sz = index + 1;
    00555
    00556     return d[index];
    00557 }
    00558
    00559
    00560 // Construct a new NETRootInfo object.
    00561
    00562 NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
    00563              const unsigned long properties[], int properties_size,
    00564                          int screen, bool doActivate)
    00565 {
    00566
    00567 #ifdef    NETWMDEBUG
    00568     fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
    00569 #endif
    00570
    00571     p = new NETRootInfoPrivate;
    00572     p->ref = 1;
    00573
    00574     p->display = display;
    00575     p->name = nstrdup(wmName);
    00576
    00577     if (screen != -1) {
    00578     p->screen = screen;
    00579     } else {
    00580     p->screen = DefaultScreen(p->display);
    00581     }
    00582
    00583     p->root = RootWindow(p->display, p->screen);
    00584     p->supportwindow = supportWindow;
    00585     p->number_of_desktops = p->current_desktop = 0;
    00586     p->active = None;
    00587     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
    00588     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
    00589     p->kde_system_tray_windows = 0;
    00590     p->kde_system_tray_windows_count = 0;
    00591     setDefaultProperties();
    00592     if( properties_size > PROPERTIES_SIZE ) {
    00593         fprintf( stderr, "NETRootInfo::NETRootInfo(): properties array too large\n");
    00594         properties_size = PROPERTIES_SIZE;
    00595     }
    00596     for( int i = 0; i < properties_size; ++i )
    00597         p->properties[ i ] = properties[ i ];
    00598     // force support for Supported and SupportingWMCheck for window managers
    00599     p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
    00600     p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients
    00601                             | WMPing; // or they can reply to this
    00602     p->client_properties[ PROTOCOLS2 ] = WM2TakeActivity;
    00603
    00604     role = WindowManager;
    00605
    00606     if (! netwm_atoms_created) create_atoms(p->display);
    00607
    00608     if (doActivate) activate();
    00609 }
    00610
    00611 NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
    00612              unsigned long properties, int screen, bool doActivate)
    00613 {
    00614
    00615 #ifdef    NETWMDEBUG
    00616     fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
    00617 #endif
    00618
    00619     p = new NETRootInfoPrivate;
    00620     p->ref = 1;
    00621
    00622     p->display = display;
    00623     p->name = nstrdup(wmName);
    00624
    00625     if (screen != -1) {
    00626     p->screen = screen;
    00627     } else {
    00628     p->screen = DefaultScreen(p->display);
    00629     }
    00630
    00631     p->root = RootWindow(p->display, p->screen);
    00632     p->supportwindow = supportWindow;
    00633     p->number_of_desktops = p->current_desktop = 0;
    00634     p->active = None;
    00635     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
    00636     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
    00637     p->kde_system_tray_windows = 0;
    00638     p->kde_system_tray_windows_count = 0;
    00639     setDefaultProperties();
    00640     p->properties[ PROTOCOLS ] = properties;
    00641     // force support for Supported and SupportingWMCheck for window managers
    00642     p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
    00643     p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients
    00644                             | WMPing; // or they can reply to this
    00645     p->client_properties[ PROTOCOLS2 ] = WM2TakeActivity;
    00646
    00647     role = WindowManager;
    00648
    00649     if (! netwm_atoms_created) create_atoms(p->display);
    00650
    00651     if (doActivate) activate();
    00652 }
    00653
    00654
    00655 NETRootInfo::NETRootInfo(Display *display, const unsigned long properties[], int properties_size,
    00656                          int screen, bool doActivate)
    00657 {
    00658
    00659 #ifdef    NETWMDEBUG
    00660     fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
    00661 #endif
    00662
    00663     p = new NETRootInfoPrivate;
    00664     p->ref = 1;
    00665
    00666     p->name = 0;
    00667
    00668     p->display = display;
    00669
    00670     if (screen != -1) {
    00671     p->screen = screen;
    00672     } else {
    00673     p->screen = DefaultScreen(p->display);
    00674     }
    00675
    00676     p->root = RootWindow(p->display, p->screen);
    00677     p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
    00678     p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
    00679
    00680     p->supportwindow = None;
    00681     p->number_of_desktops = p->current_desktop = 0;
    00682     p->active = None;
    00683     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
    00684     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
    00685     p->kde_system_tray_windows = 0;
    00686     p->kde_system_tray_windows_count = 0;
    00687     setDefaultProperties();
    00688     if( properties_size > 2 ) {
    00689         fprintf( stderr, "NETWinInfo::NETWinInfo(): properties array too large\n");
    00690         properties_size = 2;
    00691     }
    00692     for( int i = 0; i < properties_size; ++i )
    00693         // remap from [0]=NET::Property,[1]=NET::Property2
    00694         switch( i ) {
    00695             case 0:
    00696                 p->client_properties[ PROTOCOLS ] = properties[ i ];
    00697                 break;
    00698             case 1:
    00699                 p->client_properties[ PROTOCOLS2 ] = properties[ i ];
    00700                 break;
    00701         }
    00702     for( int i = 0; i < PROPERTIES_SIZE; ++i )
    00703         p->properties[ i ] = 0;
    00704
    00705     role = Client;
    00706
    00707     if (! netwm_atoms_created) create_atoms(p->display);
    00708
    00709     if (doActivate) activate();
    00710 }
    00711
    00712 NETRootInfo::NETRootInfo(Display *display, unsigned long properties, int screen,
    00713              bool doActivate)
    00714 {
    00715
    00716 #ifdef    NETWMDEBUG
    00717     fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
    00718 #endif
    00719
    00720     p = new NETRootInfoPrivate;
    00721     p->ref = 1;
    00722
    00723     p->name = 0;
    00724
    00725     p->display = display;
    00726
    00727     if (screen != -1) {
    00728     p->screen = screen;
    00729     } else {
    00730     p->screen = DefaultScreen(p->display);
    00731     }
    00732
    00733     p->root = RootWindow(p->display, p->screen);
    00734     p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
    00735     p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
    00736
    00737     p->supportwindow = None;
    00738     p->number_of_desktops = p->current_desktop = 0;
    00739     p->active = None;
    00740     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
    00741     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
    00742     p->kde_system_tray_windows = 0;
    00743     p->kde_system_tray_windows_count = 0;
    00744     setDefaultProperties();
    00745     p->client_properties[ PROTOCOLS ] = properties;
    00746     for( int i = 0; i < PROPERTIES_SIZE; ++i )
    00747         p->properties[ i ] = 0;
    00748
    00749     role = Client;
    00750
    00751     if (! netwm_atoms_created) create_atoms(p->display);
    00752
    00753     if (doActivate) activate();
    00754 }
    00755
    00756
    00757 NETRootInfo2::NETRootInfo2(Display *display, Window supportWindow, const char *wmName,
    00758              unsigned long properties[], int properties_size,
    00759                          int screen, bool doActivate)
    00760     : NETRootInfo( display, supportWindow, wmName, properties, properties_size,
    00761     screen, doActivate )
    00762 {
    00763 }
    00764
    00765 NETRootInfo3::NETRootInfo3(Display *display, Window supportWindow, const char *wmName,
    00766              unsigned long properties[], int properties_size,
    00767                          int screen, bool doActivate)
    00768     : NETRootInfo2( display, supportWindow, wmName, properties, properties_size,
    00769     screen, doActivate )
    00770 {
    00771 }
    00772
    00773 // Copy an existing NETRootInfo object.
    00774
    00775 NETRootInfo::NETRootInfo(const NETRootInfo &rootinfo) {
    00776
    00777 #ifdef    NETWMDEBUG
    00778     fprintf(stderr, "NETRootInfo::NETRootInfo: using copy constructor\n");
    00779 #endif
    00780
    00781     p = rootinfo.p;
    00782     role = rootinfo.role;
    00783
    00784     p->ref++;
    00785 }
    00786
    00787
    00788 // Be gone with our NETRootInfo.
    00789
    00790 NETRootInfo::~NETRootInfo() {
    00791     refdec_nri(p);
    00792
    00793     if (! p->ref) delete p;
    00794 }
    00795
    00796
    00797 void NETRootInfo::setDefaultProperties()
    00798 {
    00799     p->properties[ PROTOCOLS ] = Supported | SupportingWMCheck;
    00800     p->properties[ WINDOW_TYPES ] = NormalMask | DesktopMask | DockMask
    00801         | ToolbarMask | MenuMask | DialogMask;
    00802     p->properties[ STATES ] = Modal | Sticky | MaxVert | MaxHoriz | Shaded
    00803         | SkipTaskbar | StaysOnTop;
    00804     p->properties[ PROTOCOLS2 ] = 0;
    00805     p->properties[ ACTIONS ] = 0;
    00806     p->client_properties[ PROTOCOLS ] = 0;
    00807     p->client_properties[ WINDOW_TYPES ] = 0; // these two actually don't
    00808     p->client_properties[ STATES ] = 0;       // make sense in client_properties
    00809     p->client_properties[ PROTOCOLS2 ] = 0;
    00810     p->client_properties[ ACTIONS ] = 0;
    00811 }
    00812
    00813 void NETRootInfo::activate() {
    00814     if (role == WindowManager) {
    00815
    00816 #ifdef    NETWMDEBUG
    00817     fprintf(stderr,
    00818         "NETRootInfo::activate: setting supported properties on root\n");
    00819 #endif
    00820
    00821     setSupported();
    00822     } else {
    00823
    00824 #ifdef    NETWMDEBUG
    00825     fprintf(stderr, "NETRootInfo::activate: updating client information\n");
    00826 #endif
    00827
    00828     update(p->client_properties);
    00829     }
    00830 }
    00831
    00832
    00833 void NETRootInfo::setClientList(Window *windows, unsigned int count) {
    00834     if (role != WindowManager) return;
    00835
    00836     p->clients_count = count;
    00837
    00838     delete [] p->clients;
    00839     p->clients = nwindup(windows, count);
    00840
    00841 #ifdef    NETWMDEBUG
    00842     fprintf(stderr, "NETRootInfo::setClientList: setting list with %ld windows\n",
    00843         p->clients_count);
    00844 #endif
    00845
    00846     XChangeProperty(p->display, p->root, net_client_list, XA_WINDOW, 32,
    00847             PropModeReplace, (unsigned char *)p->clients,
    00848             p->clients_count);
    00849 }
    00850
    00851
    00852 void NETRootInfo::setClientListStacking(Window *windows, unsigned int count) {
    00853     if (role != WindowManager) return;
    00854
    00855     p->stacking_count = count;
    00856     delete [] p->stacking;
    00857     p->stacking = nwindup(windows, count);
    00858
    00859 #ifdef    NETWMDEBUG
    00860     fprintf(stderr,
    00861         "NETRootInfo::setClientListStacking: setting list with %ld windows\n",
    00862         p->clients_count);
    00863 #endif
    00864
    00865     XChangeProperty(p->display, p->root, net_client_list_stacking, XA_WINDOW, 32,
    00866             PropModeReplace, (unsigned char *) p->stacking,
    00867             p->stacking_count);
    00868 }
    00869
    00870
    00871 void NETRootInfo::setKDESystemTrayWindows(Window *windows, unsigned int count) {
    00872     if (role != WindowManager) return;
    00873
    00874     p->kde_system_tray_windows_count = count;
    00875     delete [] p->kde_system_tray_windows;
    00876     p->kde_system_tray_windows = nwindup(windows, count);
    00877
    00878 #ifdef    NETWMDEBUG
    00879     fprintf(stderr,
    00880         "NETRootInfo::setKDESystemTrayWindows: setting list with %ld windows\n",
    00881         p->kde_system_tray_windows_count);
    00882 #endif
    00883
    00884     XChangeProperty(p->display, p->root, kde_net_system_tray_windows, XA_WINDOW, 32,
    00885             PropModeReplace,
    00886             (unsigned char *) p->kde_system_tray_windows,
    00887             p->kde_system_tray_windows_count);
    00888 }
    00889
    00890
    00891 void NETRootInfo::setNumberOfDesktops(int numberOfDesktops) {
    00892
    00893 #ifdef    NETWMDEBUG
    00894     fprintf(stderr,
    00895         "NETRootInfo::setNumberOfDesktops: setting desktop count to %d (%s)\n",
    00896         numberOfDesktops, (role == WindowManager) ? "WM" : "Client");
    00897 #endif
    00898
    00899     if (role == WindowManager) {
    00900     p->number_of_desktops = numberOfDesktops;
    00901     long d = numberOfDesktops;
    00902     XChangeProperty(p->display, p->root, net_number_of_desktops, XA_CARDINAL, 32,
    00903             PropModeReplace, (unsigned char *) &d, 1);
    00904     } else {
    00905     XEvent e;
    00906
    00907     e.xclient.type = ClientMessage;
    00908     e.xclient.message_type = net_number_of_desktops;
    00909     e.xclient.display = p->display;
    00910     e.xclient.window = p->root;
    00911     e.xclient.format = 32;
    00912     e.xclient.data.l[0] = numberOfDesktops;
    00913     e.xclient.data.l[1] = 0l;
    00914     e.xclient.data.l[2] = 0l;
    00915     e.xclient.data.l[3] = 0l;
    00916     e.xclient.data.l[4] = 0l;
    00917
    00918     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    00919     }
    00920 }
    00921
    00922
    00923 void NETRootInfo::setCurrentDesktop(int desktop) {
    00924
    00925 #ifdef    NETWMDEBUG
    00926     fprintf(stderr,
    00927         "NETRootInfo::setCurrentDesktop: setting current desktop = %d (%s)\n",
    00928         desktop, (role == WindowManager) ? "WM" : "Client");
    00929 #endif
    00930
    00931     if (role == WindowManager) {
    00932     p->current_desktop = desktop;
    00933     long d = p->current_desktop - 1;
    00934     XChangeProperty(p->display, p->root, net_current_desktop, XA_CARDINAL, 32,
    00935             PropModeReplace, (unsigned char *) &d, 1);
    00936     } else {
    00937     XEvent e;
    00938
    00939     e.xclient.type = ClientMessage;
    00940     e.xclient.message_type = net_current_desktop;
    00941     e.xclient.display = p->display;
    00942     e.xclient.window = p->root;
    00943     e.xclient.format = 32;
    00944     e.xclient.data.l[0] = desktop - 1;
    00945     e.xclient.data.l[1] = 0l;
    00946     e.xclient.data.l[2] = 0l;
    00947     e.xclient.data.l[3] = 0l;
    00948     e.xclient.data.l[4] = 0l;
    00949
    00950     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    00951     }
    00952 }
    00953
    00954
    00955 void NETRootInfo::setDesktopName(int desktop, const char *desktopName) {
    00956     // allow setting desktop names even for non-existant desktops, see the spec, sect.3.7.
    00957     if (desktop < 1) return;
    00958
    00959     delete [] p->desktop_names[desktop - 1];
    00960     p->desktop_names[desktop - 1] = nstrdup(desktopName);
    00961
    00962     unsigned int i, proplen,
    00963     num = ((p->number_of_desktops > p->desktop_names.size()) ?
    00964            p->number_of_desktops : p->desktop_names.size());
    00965     for (i = 0, proplen = 0; i < num; i++)
    00966     proplen += (p->desktop_names[i] != 0 ? strlen(p->desktop_names[i])+1 : 1 );
    00967
    00968     char *prop = new char[proplen], *propp = prop;
    00969
    00970     for (i = 0; i < num; i++)
    00971     if (p->desktop_names[i]) {
    00972         strcpy(propp, p->desktop_names[i]);
    00973         propp += strlen(p->desktop_names[i]) + 1;
    00974     } else
    00975         *propp++ = '\0';
    00976
    00977 #ifdef    NETWMDEBUG
    00978     fprintf(stderr,
    00979         "NETRootInfo::setDesktopName(%d, '%s')\n"
    00980         "NETRootInfo::setDesktopName: total property length = %d",
    00981         desktop, desktopName, proplen);
    00982 #endif
    00983
    00984     XChangeProperty(p->display, p->root, net_desktop_names, UTF8_STRING, 8,
    00985             PropModeReplace, (unsigned char *) prop, proplen);
    00986
    00987     delete [] prop;
    00988 }
    00989
    00990
    00991 void NETRootInfo::setDesktopGeometry(int , const NETSize &geometry) {
    00992
    00993 #ifdef    NETWMDEBUG
    00994     fprintf(stderr, "NETRootInfo::setDesktopGeometry( -- , { %d, %d }) (%s)\n",
    00995         geometry.width, geometry.height, (role == WindowManager) ? "WM" : "Client");
    00996 #endif
    00997
    00998     if (role == WindowManager) {
    00999     p->geometry = geometry;
    01000
    01001     long data[2];
    01002     data[0] = p->geometry.width;
    01003     data[1] = p->geometry.height;
    01004
    01005     XChangeProperty(p->display, p->root, net_desktop_geometry, XA_CARDINAL, 32,
    01006             PropModeReplace, (unsigned char *) data, 2);
    01007     } else {
    01008     XEvent e;
    01009
    01010     e.xclient.type = ClientMessage;
    01011     e.xclient.message_type = net_desktop_geometry;
    01012     e.xclient.display = p->display;
    01013     e.xclient.window = p->root;
    01014     e.xclient.format = 32;
    01015     e.xclient.data.l[0] = geometry.width;
    01016     e.xclient.data.l[1] = geometry.height;
    01017     e.xclient.data.l[2] = 0l;
    01018     e.xclient.data.l[3] = 0l;
    01019     e.xclient.data.l[4] = 0l;
    01020
    01021     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01022     }
    01023 }
    01024
    01025
    01026 void NETRootInfo::setDesktopViewport(int desktop, const NETPoint &viewport) {
    01027
    01028 #ifdef    NETWMDEBUG
    01029     fprintf(stderr, "NETRootInfo::setDesktopViewport(%d, { %d, %d }) (%s)\n",
    01030         desktop, viewport.x, viewport.y, (role == WindowManager) ? "WM" : "Client");
    01031 #endif
    01032
    01033     if (desktop < 1) return;
    01034
    01035     if (role == WindowManager) {
    01036     p->viewport[desktop - 1] = viewport;
    01037
    01038     int d, i, l;
    01039     l = p->number_of_desktops * 2;
    01040     long *data = new long[l];
    01041     for (d = 0, i = 0; d < p->number_of_desktops; d++) {
    01042         data[i++] = p->viewport[d].x;
    01043         data[i++] = p->viewport[d].y;
    01044     }
    01045
    01046     XChangeProperty(p->display, p->root, net_desktop_viewport, XA_CARDINAL, 32,
    01047             PropModeReplace, (unsigned char *) data, l);
    01048
    01049     delete [] data;
    01050     } else {
    01051     XEvent e;
    01052
    01053     e.xclient.type = ClientMessage;
    01054     e.xclient.message_type = net_desktop_viewport;
    01055     e.xclient.display = p->display;
    01056     e.xclient.window = p->root;
    01057     e.xclient.format = 32;
    01058     e.xclient.data.l[0] = viewport.x;
    01059     e.xclient.data.l[1] = viewport.y;
    01060     e.xclient.data.l[2] = 0l;
    01061     e.xclient.data.l[3] = 0l;
    01062     e.xclient.data.l[4] = 0l;
    01063
    01064     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01065     }
    01066 }
    01067
    01068
    01069 void NETRootInfo::setSupported() {
    01070     if (role != WindowManager) {
    01071 #ifdef    NETWMDEBUG
    01072     fprintf(stderr, "NETRootInfo::setSupported - role != WindowManager\n");
    01073 #endif
    01074
    01075     return;
    01076     }
    01077
    01078     Atom atoms[netAtomCount];
    01079     int pnum = 2;
    01080
    01081     // Root window properties/messages
    01082     atoms[0] = net_supported;
    01083     atoms[1] = net_supporting_wm_check;
    01084
    01085     if (p->properties[ PROTOCOLS ] & ClientList)
    01086     atoms[pnum++] = net_client_list;
    01087
    01088     if (p->properties[ PROTOCOLS ] & ClientListStacking)
    01089     atoms[pnum++] = net_client_list_stacking;
    01090
    01091     if (p->properties[ PROTOCOLS ] & NumberOfDesktops)
    01092     atoms[pnum++] = net_number_of_desktops;
    01093
    01094     if (p->properties[ PROTOCOLS ] & DesktopGeometry)
    01095     atoms[pnum++] = net_desktop_geometry;
    01096
    01097     if (p->properties[ PROTOCOLS ] & DesktopViewport)
    01098     atoms[pnum++] = net_desktop_viewport;
    01099
    01100     if (p->properties[ PROTOCOLS ] & CurrentDesktop)
    01101     atoms[pnum++] = net_current_desktop;
    01102
    01103     if (p->properties[ PROTOCOLS ] & DesktopNames)
    01104     atoms[pnum++] = net_desktop_names;
    01105
    01106     if (p->properties[ PROTOCOLS ] & ActiveWindow)
    01107     atoms[pnum++] = net_active_window;
    01108
    01109     if (p->properties[ PROTOCOLS ] & WorkArea)
    01110     atoms[pnum++] = net_workarea;
    01111
    01112     if (p->properties[ PROTOCOLS ] & VirtualRoots)
    01113     atoms[pnum++] = net_virtual_roots;
    01114
    01115     if (p->properties[ PROTOCOLS ] & CloseWindow)
    01116     atoms[pnum++] = net_close_window;
    01117
    01118     if (p->properties[ PROTOCOLS2 ] & WM2RestackWindow)
    01119     atoms[pnum++] = net_restack_window;
    01120
    01121     // Application window properties/messages
    01122     if (p->properties[ PROTOCOLS ] & WMMoveResize)
    01123     atoms[pnum++] = net_wm_moveresize;
    01124
    01125     if (p->properties[ PROTOCOLS2 ] & WM2MoveResizeWindow)
    01126     atoms[pnum++] = net_moveresize_window;
    01127
    01128     if (p->properties[ PROTOCOLS ] & WMName)
    01129     atoms[pnum++] = net_wm_name;
    01130
    01131     if (p->properties[ PROTOCOLS ] & WMVisibleName)
    01132     atoms[pnum++] = net_wm_visible_name;
    01133
    01134     if (p->properties[ PROTOCOLS ] & WMIconName)
    01135     atoms[pnum++] = net_wm_icon_name;
    01136
    01137     if (p->properties[ PROTOCOLS ] & WMVisibleIconName)
    01138     atoms[pnum++] = net_wm_visible_icon_name;
    01139
    01140     if (p->properties[ PROTOCOLS ] & WMDesktop)
    01141     atoms[pnum++] = net_wm_desktop;
    01142
    01143     if (p->properties[ PROTOCOLS ] & WMWindowType) {
    01144     atoms[pnum++] = net_wm_window_type;
    01145
    01146     // Application window types
    01147         if (p->properties[ WINDOW_TYPES ] & NormalMask)
    01148         atoms[pnum++] = net_wm_window_type_normal;
    01149         if (p->properties[ WINDOW_TYPES ] & DesktopMask)
    01150         atoms[pnum++] = net_wm_window_type_desktop;
    01151         if (p->properties[ WINDOW_TYPES ] & DockMask)
    01152             atoms[pnum++] = net_wm_window_type_dock;
    01153         if (p->properties[ WINDOW_TYPES ] & ToolbarMask)
    01154         atoms[pnum++] = net_wm_window_type_toolbar;
    01155         if (p->properties[ WINDOW_TYPES ] & MenuMask)
    01156         atoms[pnum++] = net_wm_window_type_menu;
    01157         if (p->properties[ WINDOW_TYPES ] & DialogMask)
    01158         atoms[pnum++] = net_wm_window_type_dialog;
    01159         if (p->properties[ WINDOW_TYPES ] & UtilityMask)
    01160         atoms[pnum++] = net_wm_window_type_utility;
    01161         if (p->properties[ WINDOW_TYPES ] & SplashMask)
    01162         atoms[pnum++] = net_wm_window_type_splash;
    01163     // KDE extensions
    01164         if (p->properties[ WINDOW_TYPES ] & OverrideMask)
    01165         atoms[pnum++] = kde_net_wm_window_type_override;
    01166         if (p->properties[ WINDOW_TYPES ] & TopMenuMask)
    01167         atoms[pnum++] = kde_net_wm_window_type_topmenu;
    01168     }
    01169
    01170     if (p->properties[ PROTOCOLS ] & WMState) {
    01171     atoms[pnum++] = net_wm_state;
    01172
    01173     // Application window states
    01174         if (p->properties[ STATES ] & Modal)
    01175             atoms[pnum++] = net_wm_state_modal;
    01176         if (p->properties[ STATES ] & Sticky)
    01177         atoms[pnum++] = net_wm_state_sticky;
    01178         if (p->properties[ STATES ] & MaxVert)
    01179         atoms[pnum++] = net_wm_state_max_vert;
    01180         if (p->properties[ STATES ] & MaxHoriz)
    01181         atoms[pnum++] = net_wm_state_max_horiz;
    01182         if (p->properties[ STATES ] & Shaded)
    01183         atoms[pnum++] = net_wm_state_shaded;
    01184         if (p->properties[ STATES ] & SkipTaskbar)
    01185         atoms[pnum++] = net_wm_state_skip_taskbar;
    01186         if (p->properties[ STATES ] & SkipPager)
    01187         atoms[pnum++] = net_wm_state_skip_pager;
    01188         if (p->properties[ STATES ] & Hidden)
    01189         atoms[pnum++] = net_wm_state_hidden;
    01190         if (p->properties[ STATES ] & FullScreen)
    01191         atoms[pnum++] = net_wm_state_fullscreen;
    01192         if (p->properties[ STATES ] & KeepAbove)
    01193         atoms[pnum++] = net_wm_state_above;
    01194         if (p->properties[ STATES ] & KeepBelow)
    01195         atoms[pnum++] = net_wm_state_below;
    01196         if (p->properties[ STATES ] & DemandsAttention)
    01197         atoms[pnum++] = net_wm_state_demands_attention;
    01198
    01199         if (p->properties[ STATES ] & StaysOnTop)
    01200         atoms[pnum++] = net_wm_state_stays_on_top;
    01201     }
    01202
    01203     if (p->properties[ PROTOCOLS ] & WMStrut)
    01204     atoms[pnum++] = net_wm_strut;
    01205
    01206     if (p->properties[ PROTOCOLS2 ] & WM2ExtendedStrut)
    01207     atoms[pnum++] = net_wm_extended_strut;
    01208
    01209     if (p->properties[ PROTOCOLS ] & WMIconGeometry)
    01210     atoms[pnum++] = net_wm_icon_geometry;
    01211
    01212     if (p->properties[ PROTOCOLS ] & WMIcon)
    01213     atoms[pnum++] = net_wm_icon;
    01214
    01215     if (p->properties[ PROTOCOLS ] & WMPid)
    01216     atoms[pnum++] = net_wm_pid;
    01217
    01218     if (p->properties[ PROTOCOLS ] & WMHandledIcons)
    01219     atoms[pnum++] = net_wm_handled_icons;
    01220
    01221     if (p->properties[ PROTOCOLS ] & WMPing)
    01222     atoms[pnum++] = net_wm_ping;
    01223
    01224     if (p->properties[ PROTOCOLS2 ] & WM2TakeActivity)
    01225     atoms[pnum++] = net_wm_take_activity;
    01226
    01227     if (p->properties[ PROTOCOLS2 ] & WM2UserTime)
    01228     atoms[pnum++] = net_wm_user_time;
    01229
    01230     if (p->properties[ PROTOCOLS2 ] & WM2StartupId)
    01231     atoms[pnum++] = net_startup_id;
    01232
    01233     if (p->properties[ PROTOCOLS2 ] & WM2AllowedActions) {
    01234         atoms[pnum++] = net_wm_allowed_actions;
    01235
    01236     // Actions
    01237         if (p->properties[ ACTIONS ] & ActionMove)
    01238             atoms[pnum++] = net_wm_action_move;
    01239         if (p->properties[ ACTIONS ] & ActionResize)
    01240             atoms[pnum++] = net_wm_action_resize;
    01241         if (p->properties[ ACTIONS ] & ActionMinimize)
    01242             atoms[pnum++] = net_wm_action_minimize;
    01243         if (p->properties[ ACTIONS ] & ActionShade)
    01244             atoms[pnum++] = net_wm_action_shade;
    01245         if (p->properties[ ACTIONS ] & ActionStick)
    01246             atoms[pnum++] = net_wm_action_stick;
    01247         if (p->properties[ ACTIONS ] & ActionMaxVert)
    01248             atoms[pnum++] = net_wm_action_max_vert;
    01249         if (p->properties[ ACTIONS ] & ActionMaxHoriz)
    01250             atoms[pnum++] = net_wm_action_max_horiz;
    01251         if (p->properties[ ACTIONS ] & ActionFullScreen)
    01252             atoms[pnum++] = net_wm_action_fullscreen;
    01253         if (p->properties[ ACTIONS ] & ActionChangeDesktop)
    01254             atoms[pnum++] = net_wm_action_change_desk;
    01255         if (p->properties[ ACTIONS ] & ActionClose)
    01256             atoms[pnum++] = net_wm_action_close;
    01257     }
    01258
    01259     // KDE specific extensions
    01260     if (p->properties[ PROTOCOLS ] & KDESystemTrayWindows)
    01261     atoms[pnum++] = kde_net_system_tray_windows;
    01262
    01263     if (p->properties[ PROTOCOLS ] & WMKDESystemTrayWinFor)
    01264     atoms[pnum++] = kde_net_wm_system_tray_window_for;
    01265
    01266     if (p->properties[ PROTOCOLS ] & WMKDEFrameStrut)
    01267     atoms[pnum++] = kde_net_wm_frame_strut;
    01268
    01269     if (p->properties[ PROTOCOLS2 ] & WM2KDETemporaryRules)
    01270     atoms[pnum++] = kde_net_wm_temporary_rules;
    01271
    01272     XChangeProperty(p->display, p->root, net_supported, XA_ATOM, 32,
    01273             PropModeReplace, (unsigned char *) atoms, pnum);
    01274     XChangeProperty(p->display, p->root, net_supporting_wm_check, XA_WINDOW, 32,
    01275             PropModeReplace, (unsigned char *) &(p->supportwindow), 1);
    01276
    01277 #ifdef    NETWMDEBUG
    01278     fprintf(stderr,
    01279         "NETRootInfo::setSupported: _NET_SUPPORTING_WM_CHECK = 0x%lx on 0x%lx\n"
    01280         "                         : _NET_WM_NAME = '%s' on 0x%lx\n",
    01281         p->supportwindow, p->supportwindow, p->name, p->supportwindow);
    01282 #endif
    01283
    01284     XChangeProperty(p->display, p->supportwindow, net_supporting_wm_check,
    01285             XA_WINDOW, 32, PropModeReplace,
    01286             (unsigned char *) &(p->supportwindow), 1);
    01287     XChangeProperty(p->display, p->supportwindow, net_wm_name, UTF8_STRING, 8,
    01288             PropModeReplace, (unsigned char *) p->name,
    01289             strlen(p->name));
    01290 }
    01291
    01292 void NETRootInfo::updateSupportedProperties( Atom atom )
    01293 {
    01294     if( atom == net_supported )
    01295         p->properties[ PROTOCOLS ] |= Supported;
    01296
    01297     else if( atom == net_supporting_wm_check )
    01298         p->properties[ PROTOCOLS ] |= SupportingWMCheck;
    01299
    01300     else if( atom == net_client_list )
    01301         p->properties[ PROTOCOLS ] |= ClientList;
    01302
    01303     else if( atom == net_client_list_stacking )
    01304         p->properties[ PROTOCOLS ] |= ClientListStacking;
    01305
    01306     else if( atom == net_number_of_desktops )
    01307         p->properties[ PROTOCOLS ] |= NumberOfDesktops;
    01308
    01309     else if( atom == net_desktop_geometry )
    01310         p->properties[ PROTOCOLS ] |= DesktopGeometry;
    01311
    01312     else if( atom == net_desktop_viewport )
    01313         p->properties[ PROTOCOLS ] |= DesktopViewport;
    01314
    01315     else if( atom == net_current_desktop )
    01316         p->properties[ PROTOCOLS ] |= CurrentDesktop;
    01317
    01318     else if( atom == net_desktop_names )
    01319         p->properties[ PROTOCOLS ] |= DesktopNames;
    01320
    01321     else if( atom == net_active_window )
    01322         p->properties[ PROTOCOLS ] |= ActiveWindow;
    01323
    01324     else if( atom == net_workarea )
    01325         p->properties[ PROTOCOLS ] |= WorkArea;
    01326
    01327     else if( atom == net_virtual_roots )
    01328         p->properties[ PROTOCOLS ] |= VirtualRoots;
    01329
    01330     else if( atom == net_close_window )
    01331         p->properties[ PROTOCOLS ] |= CloseWindow;
    01332
    01333     else if( atom == net_restack_window )
    01334         p->properties[ PROTOCOLS2 ] |= WM2RestackWindow;
    01335
    01336
    01337     // Application window properties/messages
    01338     else if( atom == net_wm_moveresize )
    01339         p->properties[ PROTOCOLS ] |= WMMoveResize;
    01340
    01341     else if( atom == net_moveresize_window )
    01342         p->properties[ PROTOCOLS2 ] |= WM2MoveResizeWindow;
    01343
    01344     else if( atom == net_wm_name )
    01345         p->properties[ PROTOCOLS ] |= WMName;
    01346
    01347     else if( atom == net_wm_visible_name )
    01348         p->properties[ PROTOCOLS ] |= WMVisibleName;
    01349
    01350     else if( atom == net_wm_icon_name )
    01351         p->properties[ PROTOCOLS ] |= WMIconName;
    01352
    01353     else if( atom == net_wm_visible_icon_name )
    01354         p->properties[ PROTOCOLS ] |= WMVisibleIconName;
    01355
    01356     else if( atom == net_wm_desktop )
    01357         p->properties[ PROTOCOLS ] |= WMDesktop;
    01358
    01359     else if( atom == net_wm_window_type )
    01360         p->properties[ PROTOCOLS ] |= WMWindowType;
    01361
    01362     // Application window types
    01363     else if( atom == net_wm_window_type_normal )
    01364         p->properties[ WINDOW_TYPES ] |= NormalMask;
    01365     else if( atom == net_wm_window_type_desktop )
    01366         p->properties[ WINDOW_TYPES ] |= DesktopMask;
    01367     else if( atom == net_wm_window_type_dock )
    01368         p->properties[ WINDOW_TYPES ] |= DockMask;
    01369     else if( atom == net_wm_window_type_toolbar )
    01370         p->properties[ WINDOW_TYPES ] |= ToolbarMask;
    01371     else if( atom == net_wm_window_type_menu )
    01372         p->properties[ WINDOW_TYPES ] |= MenuMask;
    01373     else if( atom == net_wm_window_type_dialog )
    01374         p->properties[ WINDOW_TYPES ] |= DialogMask;
    01375     else if( atom == net_wm_window_type_utility )
    01376         p->properties[ WINDOW_TYPES ] |= UtilityMask;
    01377     else if( atom == net_wm_window_type_splash )
    01378         p->properties[ WINDOW_TYPES ] |= SplashMask;
    01379     // KDE extensions
    01380     else if( atom == kde_net_wm_window_type_override )
    01381         p->properties[ WINDOW_TYPES ] |= OverrideMask;
    01382     else if( atom == kde_net_wm_window_type_topmenu )
    01383         p->properties[ WINDOW_TYPES ] |= TopMenuMask;
    01384
    01385     else if( atom == net_wm_state )
    01386         p->properties[ PROTOCOLS ] |= WMState;
    01387
    01388     // Application window states
    01389     else if( atom == net_wm_state_modal )
    01390         p->properties[ STATES ] |= Modal;
    01391     else if( atom == net_wm_state_sticky )
    01392         p->properties[ STATES ] |= Sticky;
    01393     else if( atom == net_wm_state_max_vert )
    01394         p->properties[ STATES ] |= MaxVert;
    01395     else if( atom == net_wm_state_max_horiz )
    01396         p->properties[ STATES ] |= MaxHoriz;
    01397     else if( atom == net_wm_state_shaded )
    01398         p->properties[ STATES ] |= Shaded;
    01399     else if( atom == net_wm_state_skip_taskbar )
    01400         p->properties[ STATES ] |= SkipTaskbar;
    01401     else if( atom == net_wm_state_skip_pager )
    01402         p->properties[ STATES ] |= SkipPager;
    01403     else if( atom == net_wm_state_hidden )
    01404         p->properties[ STATES ] |= Hidden;
    01405     else if( atom == net_wm_state_fullscreen )
    01406         p->properties[ STATES ] |= FullScreen;
    01407     else if( atom == net_wm_state_above )
    01408         p->properties[ STATES ] |= KeepAbove;
    01409     else if( atom == net_wm_state_below )
    01410         p->properties[ STATES ] |= KeepBelow;
    01411     else if( atom == net_wm_state_demands_attention )
    01412         p->properties[ STATES ] |= DemandsAttention;
    01413
    01414     else if( atom == net_wm_state_stays_on_top )
    01415         p->properties[ STATES ] |= StaysOnTop;
    01416
    01417     else if( atom == net_wm_strut )
    01418         p->properties[ PROTOCOLS ] |= WMStrut;
    01419
    01420     else if( atom == net_wm_extended_strut )
    01421         p->properties[ PROTOCOLS2 ] |= WM2ExtendedStrut;
    01422
    01423     else if( atom == net_wm_icon_geometry )
    01424         p->properties[ PROTOCOLS ] |= WMIconGeometry;
    01425
    01426     else if( atom == net_wm_icon )
    01427         p->properties[ PROTOCOLS ] |= WMIcon;
    01428
    01429     else if( atom == net_wm_pid )
    01430         p->properties[ PROTOCOLS ] |= WMPid;
    01431
    01432     else if( atom == net_wm_handled_icons )
    01433         p->properties[ PROTOCOLS ] |= WMHandledIcons;
    01434
    01435     else if( atom == net_wm_ping )
    01436         p->properties[ PROTOCOLS ] |= WMPing;
    01437
    01438     else if( atom == net_wm_take_activity )
    01439         p->properties[ PROTOCOLS2 ] |= WM2TakeActivity;
    01440
    01441     else if( atom == net_wm_user_time )
    01442         p->properties[ PROTOCOLS2 ] |= WM2UserTime;
    01443
    01444     else if( atom == net_startup_id )
    01445         p->properties[ PROTOCOLS2 ] |= WM2StartupId;
    01446
    01447     else if( atom == net_wm_allowed_actions )
    01448         p->properties[ PROTOCOLS2 ] |= WM2AllowedActions;
    01449
    01450         // Actions
    01451     else if( atom == net_wm_action_move )
    01452         p->properties[ ACTIONS ] |= ActionMove;
    01453     else if( atom == net_wm_action_resize )
    01454         p->properties[ ACTIONS ] |= ActionResize;
    01455     else if( atom == net_wm_action_minimize )
    01456         p->properties[ ACTIONS ] |= ActionMinimize;
    01457     else if( atom == net_wm_action_shade )
    01458         p->properties[ ACTIONS ] |= ActionShade;
    01459     else if( atom == net_wm_action_stick )
    01460         p->properties[ ACTIONS ] |= ActionStick;
    01461     else if( atom == net_wm_action_max_vert )
    01462         p->properties[ ACTIONS ] |= ActionMaxVert;
    01463     else if( atom == net_wm_action_max_horiz )
    01464         p->properties[ ACTIONS ] |= ActionMaxHoriz;
    01465     else if( atom == net_wm_action_fullscreen )
    01466         p->properties[ ACTIONS ] |= ActionFullScreen;
    01467     else if( atom == net_wm_action_change_desk )
    01468         p->properties[ ACTIONS ] |= ActionChangeDesktop;
    01469     else if( atom == net_wm_action_close )
    01470         p->properties[ ACTIONS ] |= ActionClose;
    01471
    01472     // KDE specific extensions
    01473     else if( atom == kde_net_system_tray_windows )
    01474         p->properties[ PROTOCOLS ] |= KDESystemTrayWindows;
    01475
    01476     else if( atom == kde_net_wm_system_tray_window_for )
    01477         p->properties[ PROTOCOLS ] |= WMKDESystemTrayWinFor;
    01478
    01479     else if( atom == kde_net_wm_frame_strut )
    01480         p->properties[ PROTOCOLS ] |= WMKDEFrameStrut;
    01481
    01482     else if( atom == kde_net_wm_temporary_rules )
    01483         p->properties[ PROTOCOLS2 ] |= WM2KDETemporaryRules;
    01484 }
    01485
    01486 extern Time qt_x_user_time;
    01487 void NETRootInfo::setActiveWindow(Window window) {
    01488     setActiveWindow( window, FromUnknown, qt_x_user_time, None );
    01489 }
    01490
    01491 void NETRootInfo::setActiveWindow(Window window, NET::RequestSource src,
    01492     Time timestamp, Window active_window ) {
    01493
    01494 #ifdef    NETWMDEBUG
    01495     fprintf(stderr, "NETRootInfo::setActiveWindow(0x%lx) (%s)\n",
    01496             window, (role == WindowManager) ? "WM" : "Client");
    01497 #endif
    01498
    01499     if (role == WindowManager) {
    01500     p->active = window;
    01501     XChangeProperty(p->display, p->root, net_active_window, XA_WINDOW, 32,
    01502             PropModeReplace, (unsigned char *) &(p->active), 1);
    01503     } else {
    01504     XEvent e;
    01505
    01506     e.xclient.type = ClientMessage;
    01507     e.xclient.message_type = net_active_window;
    01508     e.xclient.display = p->display;
    01509     e.xclient.window = window;
    01510     e.xclient.format = 32;
    01511     e.xclient.data.l[0] = src;
    01512     e.xclient.data.l[1] = timestamp;
    01513     e.xclient.data.l[2] = active_window;
    01514     e.xclient.data.l[3] = 0l;
    01515     e.xclient.data.l[4] = 0l;
    01516
    01517     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01518     }
    01519 }
    01520
    01521
    01522 void NETRootInfo::setWorkArea(int desktop, const NETRect &workarea) {
    01523
    01524 #ifdef    NETWMDEBUG
    01525     fprintf(stderr, "NETRootInfo::setWorkArea(%d, { %d, %d, %d, %d }) (%s)\n",
    01526         desktop, workarea.pos.x, workarea.pos.y, workarea.size.width, workarea.size.height,
    01527         (role == WindowManager) ? "WM" : "Client");
    01528 #endif
    01529
    01530     if (role != WindowManager || desktop < 1) return;
    01531
    01532     p->workarea[desktop - 1] = workarea;
    01533
    01534     long *wa = new long[p->number_of_desktops * 4];
    01535     int i, o;
    01536     for (i = 0, o = 0; i < p->number_of_desktops; i++) {
    01537     wa[o++] = p->workarea[i].pos.x;
    01538     wa[o++] = p->workarea[i].pos.y;
    01539     wa[o++] = p->workarea[i].size.width;
    01540     wa[o++] = p->workarea[i].size.height;
    01541     }
    01542
    01543     XChangeProperty(p->display, p->root, net_workarea, XA_CARDINAL, 32,
    01544             PropModeReplace, (unsigned char *) wa,
    01545             p->number_of_desktops * 4);
    01546
    01547     delete [] wa;
    01548 }
    01549
    01550
    01551 void NETRootInfo::setVirtualRoots(Window *windows, unsigned int count) {
    01552     if (role != WindowManager) return;
    01553
    01554     p->virtual_roots_count = count;
    01555     p->virtual_roots = windows;
    01556
    01557 #ifdef   NETWMDEBUG
    01558     fprintf(stderr, "NETRootInfo::setVirtualRoots: setting list with %ld windows\n",
    01559         p->virtual_roots_count);
    01560 #endif
    01561
    01562     XChangeProperty(p->display, p->root, net_virtual_roots, XA_WINDOW, 32,
    01563             PropModeReplace, (unsigned char *) p->virtual_roots,
    01564             p->virtual_roots_count);
    01565 }
    01566
    01567
    01568 void NETRootInfo::closeWindowRequest(Window window) {
    01569
    01570 #ifdef    NETWMDEBUG
    01571     fprintf(stderr, "NETRootInfo::closeWindowRequest: requesting close for 0x%lx\n",
    01572         window);
    01573 #endif
    01574
    01575     XEvent e;
    01576
    01577     e.xclient.type = ClientMessage;
    01578     e.xclient.message_type = net_close_window;
    01579     e.xclient.display = p->display;
    01580     e.xclient.window = window;
    01581     e.xclient.format = 32;
    01582     e.xclient.data.l[0] = 0l;
    01583     e.xclient.data.l[1] = 0l;
    01584     e.xclient.data.l[2] = 0l;
    01585     e.xclient.data.l[3] = 0l;
    01586     e.xclient.data.l[4] = 0l;
    01587
    01588     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01589 }
    01590
    01591
    01592 void NETRootInfo::moveResizeRequest(Window window, int x_root, int y_root,
    01593                     Direction direction)
    01594 {
    01595
    01596 #ifdef    NETWMDEBUG
    01597     fprintf(stderr,
    01598         "NETRootInfo::moveResizeRequest: requesting resize/move for 0x%lx (%d, %d, %d)\n",
    01599         window, x_root, y_root, direction);
    01600 #endif
    01601
    01602     XEvent e;
    01603
    01604     e.xclient.type = ClientMessage;
    01605     e.xclient.message_type = net_wm_moveresize;
    01606     e.xclient.display = p->display;
    01607     e.xclient.window = window,
    01608     e.xclient.format = 32;
    01609     e.xclient.data.l[0] = x_root;
    01610     e.xclient.data.l[1] = y_root;
    01611     e.xclient.data.l[2] = direction;
    01612     e.xclient.data.l[3] = 0l;
    01613     e.xclient.data.l[4] = 0l;
    01614
    01615     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01616 }
    01617
    01618 void NETRootInfo::moveResizeWindowRequest(Window window, int flags, int x, int y, int width, int height )
    01619 {
    01620
    01621 #ifdef    NETWMDEBUG
    01622     fprintf(stderr,
    01623         "NETRootInfo::moveResizeWindowRequest: resizing/moving 0x%lx (%d, %d, %d, %d, %d)\n",
    01624         window, flags, x, y, width, height);
    01625 #endif
    01626
    01627     XEvent e;
    01628
    01629     e.xclient.type = ClientMessage;
    01630     e.xclient.message_type = net_moveresize_window;
    01631     e.xclient.display = p->display;
    01632     e.xclient.window = window,
    01633     e.xclient.format = 32;
    01634     e.xclient.data.l[0] = flags;
    01635     e.xclient.data.l[1] = x;
    01636     e.xclient.data.l[2] = y;
    01637     e.xclient.data.l[3] = width;
    01638     e.xclient.data.l[4] = height;
    01639
    01640     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01641 }
    01642
    01643 void NETRootInfo::restackRequest(Window window, Window above, int detail)
    01644 {
    01645     restackRequest( window, FromTool, above, detail, qt_x_user_time );
    01646 }
    01647
    01648 void NETRootInfo::restackRequest(Window window, RequestSource src, Window above, int detail, Time timestamp )
    01649 {
    01650 #ifdef    NETWMDEBUG
    01651     fprintf(stderr,
    01652         "NETRootInfo::restackRequest: requesting restack for 0x%lx (%lx, %d)\n",
    01653         window, above, detail);
    01654 #endif
    01655
    01656     XEvent e;
    01657
    01658     e.xclient.type = ClientMessage;
    01659     e.xclient.message_type = net_restack_window;
    01660     e.xclient.display = p->display;
    01661     e.xclient.window = window,
    01662     e.xclient.format = 32;
    01663     e.xclient.data.l[0] = src;
    01664     e.xclient.data.l[1] = above;
    01665     e.xclient.data.l[2] = detail;
    01666     e.xclient.data.l[3] = timestamp;
    01667     e.xclient.data.l[4] = 0l;
    01668
    01669     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    01670 }
    01671
    01672 void NETRootInfo2::sendPing( Window window, Time timestamp )
    01673 {
    01674     if (role != WindowManager) return;
    01675 #ifdef   NETWMDEBUG
    01676     fprintf(stderr, "NETRootInfo2::setPing: window 0x%lx, timestamp %lu\n",
    01677     window, timestamp );
    01678 #endif
    01679     XEvent e;
    01680     e.xclient.type = ClientMessage;
    01681     e.xclient.message_type = wm_protocols;
    01682     e.xclient.display = p->display;
    01683     e.xclient.window = window,
    01684     e.xclient.format = 32;
    01685     e.xclient.data.l[0] = net_wm_ping;
    01686     e.xclient.data.l[1] = timestamp;
    01687     e.xclient.data.l[2] = window;
    01688     e.xclient.data.l[3] = 0;
    01689     e.xclient.data.l[4] = 0;
    01690
    01691     XSendEvent(p->display, window, False, 0, &e);
    01692 }
    01693
    01694 void NETRootInfo3::takeActivity( Window window, Time timestamp, long flags )
    01695 {
    01696     if (role != WindowManager) return;
    01697 #ifdef   NETWMDEBUG
    01698     fprintf(stderr, "NETRootInfo2::takeActivity: window 0x%lx, timestamp %lu, flags 0x%lx\n",
    01699     window, timestamp, flags );
    01700 #endif
    01701     XEvent e;
    01702     e.xclient.type = ClientMessage;
    01703     e.xclient.message_type = wm_protocols;
    01704     e.xclient.display = p->display;
    01705     e.xclient.window = window,
    01706     e.xclient.format = 32;
    01707     e.xclient.data.l[0] = net_wm_take_activity;
    01708     e.xclient.data.l[1] = timestamp;
    01709     e.xclient.data.l[2] = window;
    01710     e.xclient.data.l[3] = flags;
    01711     e.xclient.data.l[4] = 0;
    01712
    01713     XSendEvent(p->display, window, False, 0, &e);
    01714 }
    01715
    01716
    01717
    01718 // assignment operator
    01719
    01720 const NETRootInfo &NETRootInfo::operator=(const NETRootInfo &rootinfo) {
    01721
    01722 #ifdef   NETWMDEBUG
    01723     fprintf(stderr, "NETRootInfo::operator=()\n");
    01724 #endif
    01725
    01726     if (p != rootinfo.p) {
    01727     refdec_nri(p);
    01728
    01729     if (! p->ref) delete p;
    01730     }
    01731
    01732     p = rootinfo.p;
    01733     role = rootinfo.role;
    01734     p->ref++;
    01735
    01736     return *this;
    01737 }
    01738
    01739 unsigned long NETRootInfo::event(XEvent *ev )
    01740 {
    01741     unsigned long props[ 1 ];
    01742     event( ev, props, 1 );
    01743     return props[ 0 ];
    01744 }
    01745
    01746 void NETRootInfo::event(XEvent *event, unsigned long* properties, int properties_size )
    01747 {
    01748     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0, 0, 0, 0 };
    01749     assert( PROPERTIES_SIZE == 5 ); // add elements above
    01750     unsigned long& dirty = props[ PROTOCOLS ];
    01751     unsigned long& dirty2 = props[ PROTOCOLS2 ];
    01752     bool do_update = false;
    01753
    01754     Q_UNUSED( dirty2 ); // for now
    01755
    01756     // the window manager will be interested in client messages... no other
    01757     // client should get these messages
    01758     if (role == WindowManager && event->type == ClientMessage &&
    01759     event->xclient.format == 32) {
    01760 #ifdef    NETWMDEBUG
    01761     fprintf(stderr, "NETRootInfo::event: handling ClientMessage event\n");
    01762 #endif
    01763
    01764     if (event->xclient.message_type == net_number_of_desktops) {
    01765         dirty = NumberOfDesktops;
    01766
    01767 #ifdef   NETWMDEBUG
    01768         fprintf(stderr, "NETRootInfo::event: changeNumberOfDesktops(%ld)\n",
    01769             event->xclient.data.l[0]);
    01770 #endif
    01771
    01772         changeNumberOfDesktops(event->xclient.data.l[0]);
    01773     } else if (event->xclient.message_type == net_desktop_geometry) {
    01774         dirty = DesktopGeometry;
    01775
    01776         NETSize sz;
    01777         sz.width = event->xclient.data.l[0];
    01778         sz.height = event->xclient.data.l[1];
    01779
    01780 #ifdef    NETWMDEBUG
    01781         fprintf(stderr, "NETRootInfo::event: changeDesktopGeometry( -- , { %d, %d })\n",
    01782             sz.width, sz.height);
    01783 #endif
    01784
    01785         changeDesktopGeometry(~0, sz);
    01786     } else if (event->xclient.message_type == net_desktop_viewport) {
    01787         dirty = DesktopViewport;
    01788
    01789         NETPoint pt;
    01790         pt.x = event->xclient.data.l[0];
    01791         pt.y = event->xclient.data.l[1];
    01792
    01793 #ifdef   NETWMDEBUG
    01794         fprintf(stderr, "NETRootInfo::event: changeDesktopViewport(%d, { %d, %d })\n",
    01795             p->current_desktop, pt.x, pt.y);
    01796 #endif
    01797
    01798         changeDesktopViewport(p->current_desktop, pt);
    01799     } else if (event->xclient.message_type == net_current_desktop) {
    01800         dirty = CurrentDesktop;
    01801
    01802 #ifdef   NETWMDEBUG
    01803         fprintf(stderr, "NETRootInfo::event: changeCurrentDesktop(%ld)\n",
    01804             event->xclient.data.l[0] + 1);
    01805 #endif
    01806
    01807         changeCurrentDesktop(event->xclient.data.l[0] + 1);
    01808     } else if (event->xclient.message_type == net_active_window) {
    01809         dirty = ActiveWindow;
    01810
    01811 #ifdef    NETWMDEBUG
    01812         fprintf(stderr, "NETRootInfo::event: changeActiveWindow(0x%lx)\n",
    01813             event->xclient.window);
    01814 #endif
    01815
    01816         changeActiveWindow(event->xclient.window);
    01817         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
    01818             {
    01819                 RequestSource src = FromUnknown;
    01820                 Time timestamp = CurrentTime;
    01821                 Window active_window = None;
    01822                 // make sure there aren't unknown values
    01823                 if( event->xclient.data.l[0] >= FromUnknown
    01824                     && event->xclient.data.l[0] <= FromTool )
    01825                     {
    01826                     src = static_cast< RequestSource >( event->xclient.data.l[0] );
    01827                     timestamp = event->xclient.data.l[1];
    01828                     active_window = event->xclient.data.l[2];
    01829                     }
    01830         this2->changeActiveWindow( event->xclient.window, src, timestamp, active_window );
    01831             }
    01832     } else if (event->xclient.message_type == net_wm_moveresize) {
    01833
    01834 #ifdef    NETWMDEBUG
    01835         fprintf(stderr, "NETRootInfo::event: moveResize(%ld, %ld, %ld, %ld)\n",
    01836             event->xclient.window,
    01837             event->xclient.data.l[0],
    01838             event->xclient.data.l[1],
    01839             event->xclient.data.l[2]
    01840             );
    01841 #endif
    01842
    01843         moveResize(event->xclient.window,
    01844                event->xclient.data.l[0],
    01845                event->xclient.data.l[1],
    01846                event->xclient.data.l[2]);
    01847     } else if (event->xclient.message_type == net_moveresize_window) {
    01848
    01849 #ifdef    NETWMDEBUG
    01850         fprintf(stderr, "NETRootInfo::event: moveResizeWindow(%ld, %ld, %ld, %ld, %ld, %ld)\n",
    01851             event->xclient.window,
    01852             event->xclient.data.l[0],
    01853             event->xclient.data.l[1],
    01854             event->xclient.data.l[2],
    01855             event->xclient.data.l[3],
    01856             event->xclient.data.l[4]
    01857             );
    01858 #endif
    01859
    01860         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
    01861             this2->moveResizeWindow(event->xclient.window,
    01862                    event->xclient.data.l[0],
    01863                    event->xclient.data.l[1],
    01864                    event->xclient.data.l[2],
    01865                    event->xclient.data.l[3],
    01866                    event->xclient.data.l[4]);
    01867     } else if (event->xclient.message_type == net_close_window) {
    01868
    01869 #ifdef   NETWMDEBUG
    01870         fprintf(stderr, "NETRootInfo::event: closeWindow(0x%lx)\n",
    01871             event->xclient.window);
    01872 #endif
    01873
    01874         closeWindow(event->xclient.window);
    01875     } else if (event->xclient.message_type == net_restack_window) {
    01876
    01877 #ifdef   NETWMDEBUG
    01878         fprintf(stderr, "NETRootInfo::event: restackWindow(0x%lx)\n",
    01879             event->xclient.window);
    01880 #endif
    01881
    01882         if( NETRootInfo3* this3 = dynamic_cast< NETRootInfo3* >( this ))
    01883             {
    01884                 RequestSource src = FromUnknown;
    01885                 Time timestamp = CurrentTime;
    01886                 // make sure there aren't unknown values
    01887                 if( event->xclient.data.l[0] >= FromUnknown
    01888                     && event->xclient.data.l[0] <= FromTool )
    01889                     {
    01890                     src = static_cast< RequestSource >( event->xclient.data.l[0] );
    01891                     timestamp = event->xclient.data.l[3];
    01892                     }
    01893             this3->restackWindow(event->xclient.window, src,
    01894                     event->xclient.data.l[1], event->xclient.data.l[2], timestamp);
    01895             }
    01896         else if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
    01897             this2->restackWindow(event->xclient.window,
    01898                     event->xclient.data.l[1], event->xclient.data.l[2]);
    01899     } else if (event->xclient.message_type == wm_protocols
    01900         && (Atom)event->xclient.data.l[ 0 ] == net_wm_ping) {
    01901         dirty = WMPing;
    01902
    01903 #ifdef   NETWMDEBUG
    01904         fprintf(stderr, "NETRootInfo2::event: gotPing(0x%lx,%lu)\n",
    01905         event->xclient.window, event->xclient.data.l[1]);
    01906 #endif
    01907         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
    01908         this2->gotPing( event->xclient.data.l[2], event->xclient.data.l[1]);
    01909     } else if (event->xclient.message_type == wm_protocols
    01910         && (Atom)event->xclient.data.l[ 0 ] == net_wm_take_activity) {
    01911         dirty2 = WM2TakeActivity;
    01912
    01913 #ifdef   NETWMDEBUG
    01914         fprintf(stderr, "NETRootInfo2::event: gotTakeActivity(0x%lx,%lu,0x%lx)\n",
    01915         event->xclient.window, event->xclient.data.l[1], event->xclient.data.l[3]);
    01916 #endif
    01917         if( NETRootInfo3* this3 = dynamic_cast< NETRootInfo3* >( this ))
    01918         this3->gotTakeActivity( event->xclient.data.l[2], event->xclient.data.l[1],
    01919                     event->xclient.data.l[3]);
    01920     }
    01921     }
    01922
    01923     if (event->type == PropertyNotify) {
    01924
    01925 #ifdef    NETWMDEBUG
    01926     fprintf(stderr, "NETRootInfo::event: handling PropertyNotify event\n");
    01927 #endif
    01928
    01929     XEvent pe = *event;
    01930
    01931     Bool done = False;
    01932     Bool compaction = False;
    01933     while (! done) {
    01934
    01935 #ifdef   NETWMDEBUG
    01936         fprintf(stderr, "NETRootInfo::event: loop fire\n");
    01937 #endif
    01938
    01939         if (pe.xproperty.atom == net_client_list)
    01940         dirty |= ClientList;
    01941         else if (pe.xproperty.atom == net_client_list_stacking)
    01942         dirty |= ClientListStacking;
    01943         else if (pe.xproperty.atom == kde_net_system_tray_windows)
    01944         dirty |= KDESystemTrayWindows;
    01945         else if (pe.xproperty.atom == net_desktop_names)
    01946         dirty |= DesktopNames;
    01947         else if (pe.xproperty.atom == net_workarea)
    01948         dirty |= WorkArea;
    01949         else if (pe.xproperty.atom == net_number_of_desktops)
    01950         dirty |= NumberOfDesktops;
    01951         else if (pe.xproperty.atom == net_desktop_geometry)
    01952         dirty |= DesktopGeometry;
    01953         else if (pe.xproperty.atom == net_desktop_viewport)
    01954         dirty |= DesktopViewport;
    01955         else if (pe.xproperty.atom == net_current_desktop)
    01956         dirty |= CurrentDesktop;
    01957         else if (pe.xproperty.atom == net_active_window)
    01958         dirty |= ActiveWindow;
    01959         else {
    01960
    01961 #ifdef    NETWMDEBUG
    01962         fprintf(stderr, "NETRootInfo::event: putting back event and breaking\n");
    01963 #endif
    01964
    01965         if ( compaction )
    01966             XPutBackEvent(p->display, &pe);
    01967         break;
    01968         }
    01969
    01970         if (XCheckTypedWindowEvent(p->display, p->root, PropertyNotify, &pe) )
    01971         compaction = True;
    01972         else
    01973         break;
    01974     }
    01975
    01976     do_update = true;
    01977     }
    01978
    01979     if( do_update )
    01980         update( props );
    01981
    01982 #ifdef   NETWMDEBUG
    01983      fprintf(stderr, "NETRootInfo::event: handled events, returning dirty = 0x%lx, 0x%lx\n",
    01984         dirty, dirty2);
    01985 #endif
    01986
    01987     if( properties_size > PROPERTIES_SIZE )
    01988         properties_size = PROPERTIES_SIZE;
    01989     for( int i = 0;
    01990          i < properties_size;
    01991          ++i )
    01992         properties[ i ] = props[ i ];
    01993 }
    01994
    01995
    01996 // private functions to update the data we keep
    01997
    01998 void NETRootInfo::update( const unsigned long dirty_props[] )
    01999 {
    02000     Atom type_ret;
    02001     int format_ret;
    02002     unsigned char *data_ret;
    02003     unsigned long nitems_ret, unused;
    02004     unsigned long props[ PROPERTIES_SIZE ];
    02005     for( int i = 0;
    02006          i < PROPERTIES_SIZE;
    02007          ++i )
    02008         props[ i ] = dirty_props[ i ] & p->client_properties[ i ];
    02009     const unsigned long& dirty = props[ PROTOCOLS ];
    02010     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
    02011
    02012     Q_UNUSED( dirty2 ); // for now
    02013
    02014     if (dirty & Supported ) {
    02015         // only in Client mode
    02016         for( int i = 0; i < PROPERTIES_SIZE; ++i )
    02017             p->properties[ i ] = 0;
    02018         if( XGetWindowProperty(p->display, p->root, net_supported,
    02019                                0l, MAX_PROP_SIZE, False, XA_ATOM, &type_ret,
    02020                                &format_ret, &nitems_ret, &unused, &data_ret)
    02021             == Success ) {
    02022             if( type_ret == XA_ATOM && format_ret == 32 ) {
    02023                 Atom* atoms = (Atom*) data_ret;
    02024                 for( unsigned int i = 0;
    02025                      i < nitems_ret;
    02026                      ++i )
    02027                     updateSupportedProperties( atoms[ i ] );
    02028             }
    02029         if ( data_ret )
    02030         XFree(data_ret);
    02031         }
    02032     }
    02033
    02034     if (dirty & ClientList) {
    02035         bool read_ok = false;
    02036     if (XGetWindowProperty(p->display, p->root, net_client_list,
    02037                    0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
    02038                    &format_ret, &nitems_ret, &unused, &data_ret)
    02039         == Success) {
    02040         if (type_ret == XA_WINDOW && format_ret == 32) {
    02041         Window *wins = (Window *) data_ret;
    02042
    02043         qsort(wins, nitems_ret, sizeof(Window), wcmp);
    02044
    02045         if (p->clients) {
    02046             if (role == Client) {
    02047             unsigned long new_index = 0, old_index = 0;
    02048             unsigned long new_count = nitems_ret,
    02049                       old_count = p->clients_count;
    02050
    02051             while (old_index < old_count || new_index < new_count) {
    02052                 if (old_index == old_count) {
    02053                 addClient(wins[new_index++]);
    02054                 } else if (new_index == new_count) {
    02055                 removeClient(p->clients[old_index++]);
    02056                 } else {
    02057                 if (p->clients[old_index] <
    02058                     wins[new_index]) {
    02059                     removeClient(p->clients[old_index++]);
    02060                 } else if (wins[new_index] <
    02061                        p->clients[old_index]) {
    02062                     addClient(wins[new_index++]);
    02063                 } else {
    02064                     new_index++;
    02065                     old_index++;
    02066                 }
    02067                 }
    02068             }
    02069             }
    02070
    02071             delete [] p->clients;
    02072         } else {
    02073 #ifdef    NETWMDEBUG
    02074             fprintf(stderr, "NETRootInfo::update: client list null, creating\n");
    02075 #endif
    02076
    02077             unsigned long n;
    02078             for (n = 0; n < nitems_ret; n++) {
    02079             addClient(wins[n]);
    02080             }
    02081         }
    02082
    02083         p->clients_count = nitems_ret;
    02084         p->clients = nwindup(wins, p->clients_count);
    02085                 read_ok = true;
    02086         }
    02087
    02088         if ( data_ret )
    02089         XFree(data_ret);
    02090     }
    02091         if( !read_ok ) {
    02092             for( unsigned int i = 0; i < p->clients_count; ++ i )
    02093             removeClient(p->clients[i]);
    02094             p->clients_count = 0;
    02095             delete[] p->clients;
    02096             p->clients = NULL;
    02097         }
    02098
    02099 #ifdef    NETWMDEBUG
    02100     fprintf(stderr, "NETRootInfo::update: client list updated (%ld clients)\n",
    02101         p->clients_count);
    02102 #endif
    02103     }
    02104
    02105     if (dirty & KDESystemTrayWindows) {
    02106         bool read_ok = false;
    02107     if (XGetWindowProperty(p->display, p->root, kde_net_system_tray_windows,
    02108                    0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
    02109                    &format_ret, &nitems_ret, &unused, &data_ret)
    02110         == Success) {
    02111         if (type_ret == XA_WINDOW && format_ret == 32) {
    02112         Window *wins = (Window *) data_ret;
    02113
    02114         qsort(wins, nitems_ret, sizeof(Window), wcmp);
    02115
    02116         if (p->kde_system_tray_windows) {
    02117             if (role == Client) {
    02118             unsigned long new_index = 0, new_count = nitems_ret;
    02119             unsigned long old_index = 0,
    02120                       old_count = p->kde_system_tray_windows_count;
    02121
    02122             while(old_index < old_count || new_index < new_count) {
    02123                 if (old_index == old_count) {
    02124                 addSystemTrayWin(wins[new_index++]);
    02125                 } else if (new_index == new_count) {
    02126                 removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
    02127                 } else {
    02128                 if (p->kde_system_tray_windows[old_index] <
    02129                     wins[new_index]) {
    02130                     removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
    02131                 } else if (wins[new_index] <
    02132                        p->kde_system_tray_windows[old_index]) {
    02133                     addSystemTrayWin(wins[new_index++]);
    02134                 } else {
    02135                     new_index++;
    02136                     old_index++;
    02137                 }
    02138                 }
    02139             }
    02140             }
    02141
    02142         } else {
    02143             unsigned long n;
    02144             for (n = 0; n < nitems_ret; n++) {
    02145             addSystemTrayWin(wins[n]);
    02146             }
    02147         }
    02148
    02149         p->kde_system_tray_windows_count = nitems_ret;
    02150         delete [] p->kde_system_tray_windows;
    02151         p->kde_system_tray_windows =
    02152             nwindup(wins, p->kde_system_tray_windows_count);
    02153                 read_ok = true;
    02154         }
    02155
    02156         if ( data_ret )
    02157         XFree(data_ret);
    02158     }
    02159         if( !read_ok ) {
    02160             for( unsigned int i = 0; i < p->kde_system_tray_windows_count; ++i )
    02161                 removeSystemTrayWin(p->kde_system_tray_windows[i]);
    02162             p->kde_system_tray_windows_count = 0;
    02163         delete [] p->kde_system_tray_windows;
    02164             p->kde_system_tray_windows = NULL;
    02165         }
    02166     }
    02167
    02168     if (dirty & ClientListStacking) {
    02169         p->stacking_count = 0;
    02170         delete[] p->stacking;
    02171         p->stacking = NULL;
    02172     if (XGetWindowProperty(p->display, p->root, net_client_list_stacking,
    02173                    0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
    02174                    &format_ret, &nitems_ret, &unused, &data_ret)
    02175         == Success) {
    02176         if (type_ret == XA_WINDOW && format_ret == 32) {
    02177         Window *wins = (Window *) data_ret;
    02178
    02179         p->stacking_count = nitems_ret;
    02180         p->stacking = nwindup(wins, p->stacking_count);
    02181         }
    02182
    02183 #ifdef    NETWMDEBUG
    02184         fprintf(stderr,"NETRootInfo::update: client stacking updated (%ld clients)\n",
    02185             p->stacking_count);
    02186 #endif
    02187
    02188         if ( data_ret )
    02189         XFree(data_ret);
    02190     }
    02191     }
    02192
    02193     if (dirty & NumberOfDesktops) {
    02194     p->number_of_desktops = 0;
    02195
    02196     if (XGetWindowProperty(p->display, p->root, net_number_of_desktops,
    02197                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
    02198                    &nitems_ret, &unused, &data_ret)
    02199         == Success) {
    02200         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
    02201         p->number_of_desktops = *((long *) data_ret);
    02202         }
    02203
    02204 #ifdef    NETWMDEBUG
    02205         fprintf(stderr, "NETRootInfo::update: number of desktops = %d\n",
    02206             p->number_of_desktops);
    02207 #endif
    02208         if ( data_ret )
    02209         XFree(data_ret);
    02210     }
    02211     }
    02212
    02213     if (dirty & DesktopGeometry) {
    02214         p->geometry = p->rootSize;
    02215     if (XGetWindowProperty(p->display, p->root, net_desktop_geometry,
    02216                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
    02217                    &nitems_ret, &unused, &data_ret)
    02218         == Success) {
    02219         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    02220         nitems_ret == 2) {
    02221         long *data = (long *) data_ret;
    02222
    02223         p->geometry.width  = data[0];
    02224         p->geometry.height = data[1];
    02225
    02226 #ifdef    NETWMDEBUG
    02227         fprintf(stderr, "NETRootInfo::update: desktop geometry updated\n");
    02228 #endif
    02229         }
    02230         if ( data_ret )
    02231         XFree(data_ret);
    02232     }
    02233     }
    02234
    02235     if (dirty & DesktopViewport) {
    02236     for (int i = 0; i < p->viewport.size(); i++)
    02237         p->viewport[i].x = p->viewport[i].y = 0;
    02238     if (XGetWindowProperty(p->display, p->root, net_desktop_viewport,
    02239                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
    02240                    &nitems_ret, &unused, &data_ret)
    02241         == Success) {
    02242         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    02243         nitems_ret == 2) {
    02244         long *data = (long *) data_ret;
    02245
    02246         int d, i, n;
    02247         n = nitems_ret / 2;
    02248         for (d = 0, i = 0; d < n; d++) {
    02249             p->viewport[d].x = data[i++];
    02250             p->viewport[d].y = data[i++];
    02251         }
    02252
    02253 #ifdef    NETWMDEBUG
    02254         fprintf(stderr,
    02255             "NETRootInfo::update: desktop viewport array updated (%d entries)\n",
    02256             p->viewport.size());
    02257
    02258         if (nitems_ret % 2 != 0) {
    02259             fprintf(stderr,
    02260                 "NETRootInfo::update(): desktop viewport array "
    02261                 "size not a multiple of 2\n");
    02262         }
    02263 #endif
    02264         }
    02265         if ( data_ret )
    02266         XFree(data_ret);
    02267     }
    02268     }
    02269
    02270     if (dirty & CurrentDesktop) {
    02271     p->current_desktop = 0;
    02272     if (XGetWindowProperty(p->display, p->root, net_current_desktop,
    02273                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
    02274                    &nitems_ret, &unused, &data_ret)
    02275         == Success) {
    02276         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
    02277         p->current_desktop = *((long *) data_ret) + 1;
    02278         }
    02279
    02280 #ifdef    NETWMDEBUG
    02281         fprintf(stderr, "NETRootInfo::update: current desktop = %d\n",
    02282             p->current_desktop);
    02283 #endif
    02284         if ( data_ret )
    02285         XFree(data_ret);
    02286     }
    02287     }
    02288
    02289     if (dirty & DesktopNames) {
    02290         for( int i = 0; i < p->desktop_names.size(); ++i )
    02291             delete[] p->desktop_names[ i ];
    02292         p->desktop_names.reset();
    02293     if (XGetWindowProperty(p->display, p->root, net_desktop_names,
    02294                    0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    02295                    &format_ret, &nitems_ret, &unused, &data_ret)
    02296         == Success) {
    02297         if (type_ret == UTF8_STRING && format_ret == 8) {
    02298         const char *d = (const char *) data_ret;
    02299         unsigned int s, n, index;
    02300
    02301         for (s = 0, n = 0, index = 0; n < nitems_ret; n++) {
    02302             if (d[n] == '\0') {
    02303             delete [] p->desktop_names[index];
    02304             p->desktop_names[index++] = nstrndup((d + s), n - s + 1);
    02305             s = n + 1;
    02306             }
    02307         }
    02308         }
    02309
    02310 #ifdef    NETWMDEBUG
    02311         fprintf(stderr, "NETRootInfo::update: desktop names array updated (%d entries)\n",
    02312             p->desktop_names.size());
    02313 #endif
    02314         if ( data_ret )
    02315         XFree(data_ret);
    02316     }
    02317     }
    02318
    02319     if (dirty & ActiveWindow) {
    02320         p->active = None;
    02321     if (XGetWindowProperty(p->display, p->root, net_active_window, 0l, 1l,
    02322                    False, XA_WINDOW, &type_ret, &format_ret,
    02323                    &nitems_ret, &unused, &data_ret)
    02324         == Success) {
    02325         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
    02326         p->active = *((Window *) data_ret);
    02327         }
    02328
    02329 #ifdef    NETWMDEBUG
    02330         fprintf(stderr, "NETRootInfo::update: active window = 0x%lx\n",
    02331             p->active);
    02332 #endif
    02333         if ( data_ret )
    02334         XFree(data_ret);
    02335     }
    02336     }
    02337
    02338     if (dirty & WorkArea) {
    02339         p->workarea.reset();
    02340     if (XGetWindowProperty(p->display, p->root, net_workarea, 0l,
    02341                    (p->number_of_desktops * 4), False, XA_CARDINAL,
    02342                    &type_ret, &format_ret, &nitems_ret, &unused,
    02343                    &data_ret)
    02344         == Success) {
    02345         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    02346         nitems_ret == (unsigned) (p->number_of_desktops * 4)) {
    02347         long *d = (long *) data_ret;
    02348         int i, j;
    02349         for (i = 0, j = 0; i < p->number_of_desktops; i++) {
    02350             p->workarea[i].pos.x       = d[j++];
    02351             p->workarea[i].pos.y       = d[j++];
    02352             p->workarea[i].size.width  = d[j++];
    02353             p->workarea[i].size.height = d[j++];
    02354         }
    02355         }
    02356
    02357 #ifdef    NETWMDEBUG
    02358         fprintf(stderr, "NETRootInfo::update: work area array updated (%d entries)\n",
    02359             p->workarea.size());
    02360 #endif
    02361         if ( data_ret )
    02362         XFree(data_ret);
    02363     }
    02364     }
    02365
    02366
    02367     if (dirty & SupportingWMCheck) {
    02368         p->supportwindow = None;
    02369         delete[] p->name;
    02370         p->name = NULL;
    02371     if (XGetWindowProperty(p->display, p->root, net_supporting_wm_check,
    02372                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
    02373                    &nitems_ret, &unused, &data_ret)
    02374         == Success) {
    02375         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
    02376         p->supportwindow = *((Window *) data_ret);
    02377
    02378         unsigned char *name_ret;
    02379         if (XGetWindowProperty(p->display, p->supportwindow,
    02380                        net_wm_name, 0l, MAX_PROP_SIZE, False,
    02381                        UTF8_STRING, &type_ret, &format_ret,
    02382                        &nitems_ret, &unused, &name_ret)
    02383             == Success) {
    02384             if (type_ret == UTF8_STRING && format_ret == 8)
    02385             p->name = nstrndup((const char *) name_ret, nitems_ret);
    02386
    02387             if ( name_ret )
    02388             XFree(name_ret);
    02389         }
    02390         }
    02391
    02392 #ifdef    NETWMDEBUG
    02393         fprintf(stderr,
    02394             "NETRootInfo::update: supporting window manager = '%s'\n",
    02395             p->name);
    02396 #endif
    02397         if ( data_ret )
    02398         XFree(data_ret);
    02399     }
    02400     }
    02401
    02402     if (dirty & VirtualRoots) {
    02403         p->virtual_roots_count = 0;
    02404         delete[] p->virtual_roots;
    02405         p->virtual_roots = NULL;
    02406     if (XGetWindowProperty(p->display, p->root, net_virtual_roots,
    02407                    0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
    02408                    &format_ret, &nitems_ret, &unused, &data_ret)
    02409         == Success) {
    02410         if (type_ret == XA_WINDOW && format_ret == 32) {
    02411         Window *wins = (Window *) data_ret;
    02412
    02413         p->virtual_roots_count = nitems_ret;
    02414         p->virtual_roots = nwindup(wins, p->virtual_roots_count);
    02415         }
    02416
    02417 #ifdef    NETWMDEBUG
    02418         fprintf(stderr, "NETRootInfo::updated: virtual roots updated (%ld windows)\n",
    02419             p->virtual_roots_count);
    02420 #endif
    02421         if ( data_ret )
    02422         XFree(data_ret);
    02423     }
    02424     }
    02425 }
    02426
    02427
    02428 Display *NETRootInfo::x11Display() const {
    02429     return p->display;
    02430 }
    02431
    02432
    02433 Window NETRootInfo::rootWindow() const {
    02434     return p->root;
    02435 }
    02436
    02437
    02438 Window NETRootInfo::supportWindow() const {
    02439     return p->supportwindow;
    02440 }
    02441
    02442
    02443 const char *NETRootInfo::wmName() const {
    02444     return p->name; }
    02445
    02446
    02447 int NETRootInfo::screenNumber() const {
    02448     return p->screen;
    02449 }
    02450
    02451
    02452 unsigned long NETRootInfo::supported() const {
    02453     return role == WindowManager
    02454         ? p->properties[ PROTOCOLS ]
    02455         : p->client_properties[ PROTOCOLS ];
    02456 }
    02457
    02458 const unsigned long* NETRootInfo::supportedProperties() const {
    02459     return p->properties;
    02460 }
    02461
    02462 const unsigned long* NETRootInfo::passedProperties() const {
    02463     return role == WindowManager
    02464         ? p->properties
    02465         : p->client_properties;
    02466 }
    02467
    02468 bool NETRootInfo::isSupported( NET::Property property ) const {
    02469     return p->properties[ PROTOCOLS ] & property;
    02470 }
    02471
    02472 bool NETRootInfo::isSupported( NET::Property2 property ) const {
    02473     return p->properties[ PROTOCOLS2 ] & property;
    02474 }
    02475
    02476 bool NETRootInfo::isSupported( NET::WindowType type ) const {
    02477     return p->properties[ WINDOW_TYPES ] & type;
    02478 }
    02479
    02480 bool NETRootInfo::isSupported( NET::State state ) const {
    02481     return p->properties[ STATES ] & state;
    02482 }
    02483
    02484 bool NETRootInfo::isSupported( NET::Action action ) const {
    02485     return p->properties[ ACTIONS ] & action;
    02486 }
    02487
    02488 const Window *NETRootInfo::clientList() const {
    02489     return p->clients;
    02490 }
    02491
    02492
    02493 int NETRootInfo::clientListCount() const {
    02494     return p->clients_count;
    02495 }
    02496
    02497
    02498 const Window *NETRootInfo::clientListStacking() const {
    02499     return p->stacking;
    02500 }
    02501
    02502
    02503 int NETRootInfo::clientListStackingCount() const {
    02504     return p->stacking_count;
    02505 }
    02506
    02507
    02508 const Window *NETRootInfo::kdeSystemTrayWindows() const {
    02509     return p->kde_system_tray_windows;
    02510 }
    02511
    02512
    02513 int NETRootInfo::kdeSystemTrayWindowsCount() const {
    02514     return p->kde_system_tray_windows_count;
    02515 }
    02516
    02517
    02518 NETSize NETRootInfo::desktopGeometry(int) const {
    02519     return p->geometry.width != 0 ? p->geometry : p->rootSize;
    02520 }
    02521
    02522
    02523 NETPoint NETRootInfo::desktopViewport(int desktop) const {
    02524     if (desktop < 1) {
    02525     NETPoint pt; // set to (0,0)
    02526     return pt;
    02527     }
    02528
    02529     return p->viewport[desktop - 1];
    02530 }
    02531
    02532
    02533 NETRect NETRootInfo::workArea(int desktop) const {
    02534     if (desktop < 1) {
    02535     NETRect rt;
    02536     return rt;
    02537     }
    02538
    02539     return p->workarea[desktop - 1];
    02540 }
    02541
    02542
    02543 const char *NETRootInfo::desktopName(int desktop) const {
    02544     if (desktop < 1) {
    02545     return 0;
    02546     }
    02547
    02548     return p->desktop_names[desktop - 1];
    02549 }
    02550
    02551
    02552 const Window *NETRootInfo::virtualRoots( ) const {
    02553     return p->virtual_roots;
    02554 }
    02555
    02556
    02557 int NETRootInfo::virtualRootsCount() const {
    02558     return p->virtual_roots_count;
    02559 }
    02560
    02561
    02562 int NETRootInfo::numberOfDesktops() const {
    02563     return p->number_of_desktops == 0 ? 1 : p->number_of_desktops;
    02564 }
    02565
    02566
    02567 int NETRootInfo::currentDesktop() const {
    02568     return p->current_desktop == 0 ? 1 : p->current_desktop;
    02569 }
    02570
    02571
    02572 Window NETRootInfo::activeWindow() const {
    02573     return p->active;
    02574 }
    02575
    02576
    02577 // NETWinInfo stuffs
    02578
    02579 const int NETWinInfo::OnAllDesktops = NET::OnAllDesktops;
    02580
    02581 NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
    02582                const unsigned long properties[], int properties_size,
    02583                        Role role)
    02584 {
    02585
    02586 #ifdef   NETWMDEBUG
    02587     fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
    02588         (role == WindowManager) ? "WindowManager" : "Client");
    02589 #endif
    02590
    02591     p = new NETWinInfoPrivate;
    02592     p->ref = 1;
    02593
    02594     p->display = display;
    02595     p->window = window;
    02596     p->root = rootWindow;
    02597     p->mapping_state = Withdrawn;
    02598     p->mapping_state_dirty = True;
    02599     p->state = 0;
    02600     p->types[ 0 ] = Unknown;
    02601     p->name = (char *) 0;
    02602     p->visible_name = (char *) 0;
    02603     p->icon_name = (char *) 0;
    02604     p->visible_icon_name = (char *) 0;
    02605     p->desktop = p->pid = p->handled_icons = 0;
    02606     p->user_time = -1U;
    02607     p->startup_id = NULL;
    02608     p->transient_for = None;
    02609     p->window_group = None;
    02610     p->allowed_actions = 0;
    02611     p->has_net_support = false;
    02612     p->class_class = (char*) 0;
    02613     p->class_name = (char*) 0;
    02614     p->role = (char*) 0;
    02615     p->client_machine = (char*) 0;
    02616
    02617     // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
    02618     // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
    02619     // p->frame_strut.bottom = 0;
    02620
    02621     p->kde_system_tray_win_for = 0;
    02622
    02623     for( int i = 0;
    02624          i < PROPERTIES_SIZE;
    02625          ++i )
    02626         p->properties[ i ] = 0;
    02627     if( properties_size > PROPERTIES_SIZE )
    02628         properties_size = PROPERTIES_SIZE;
    02629     for( int i = 0;
    02630          i < properties_size;
    02631          ++i )
    02632         p->properties[ i ] = properties[ i ];
    02633
    02634     p->icon_count = 0;
    02635
    02636     this->role = role;
    02637
    02638     if (! netwm_atoms_created) create_atoms(p->display);
    02639
    02640     update(p->properties);
    02641 }
    02642
    02643
    02644 NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
    02645                unsigned long properties, Role role)
    02646 {
    02647
    02648 #ifdef   NETWMDEBUG
    02649     fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
    02650         (role == WindowManager) ? "WindowManager" : "Client");
    02651 #endif
    02652
    02653     p = new NETWinInfoPrivate;
    02654     p->ref = 1;
    02655
    02656     p->display = display;
    02657     p->window = window;
    02658     p->root = rootWindow;
    02659     p->mapping_state = Withdrawn;
    02660     p->mapping_state_dirty = True;
    02661     p->state = 0;
    02662     p->types[ 0 ] = Unknown;
    02663     p->name = (char *) 0;
    02664     p->visible_name = (char *) 0;
    02665     p->icon_name = (char *) 0;
    02666     p->visible_icon_name = (char *) 0;
    02667     p->desktop = p->pid = p->handled_icons = 0;
    02668     p->user_time = -1U;
    02669     p->startup_id = NULL;
    02670     p->transient_for = None;
    02671     p->window_group = None;
    02672     p->allowed_actions = 0;
    02673     p->has_net_support = false;
    02674     p->class_class = (char*) 0;
    02675     p->class_name = (char*) 0;
    02676     p->role = (char*) 0;
    02677     p->client_machine = (char*) 0;
    02678
    02679     // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
    02680     // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
    02681     // p->frame_strut.bottom = 0;
    02682
    02683     p->kde_system_tray_win_for = 0;
    02684
    02685     for( int i = 0;
    02686          i < PROPERTIES_SIZE;
    02687          ++i )
    02688         p->properties[ i ] = 0;
    02689     p->properties[ PROTOCOLS ] = properties;
    02690
    02691     p->icon_count = 0;
    02692
    02693     this->role = role;
    02694
    02695     if (! netwm_atoms_created) create_atoms(p->display);
    02696
    02697     update(p->properties);
    02698 }
    02699
    02700
    02701 NETWinInfo::NETWinInfo(const NETWinInfo &wininfo) {
    02702     p = wininfo.p;
    02703     p->ref++;
    02704 }
    02705
    02706
    02707 NETWinInfo::~NETWinInfo() {
    02708     refdec_nwi(p);
    02709
    02710     if (! p->ref) delete p;
    02711 }
    02712
    02713
    02714 // assignment operator
    02715
    02716 const NETWinInfo &NETWinInfo::operator=(const NETWinInfo &wininfo) {
    02717
    02718 #ifdef   NETWMDEBUG
    02719     fprintf(stderr, "NETWinInfo::operator=()\n");
    02720 #endif
    02721
    02722     if (p != wininfo.p) {
    02723     refdec_nwi(p);
    02724
    02725     if (! p->ref) delete p;
    02726     }
    02727
    02728     p = wininfo.p;
    02729     role = wininfo.role;
    02730     p->ref++;
    02731
    02732     return *this;
    02733 }
    02734
    02735
    02736 void NETWinInfo::setIcon(NETIcon icon, Bool replace) {
    02737     if (role != Client) return;
    02738
    02739     int proplen, i, sz, j;
    02740
    02741     if (replace) {
    02742
    02743     for (i = 0; i < p->icons.size(); i++) {
    02744         delete [] p->icons[i].data;
    02745         p->icons[i].data = 0;
    02746         p->icons[i].size.width = 0;
    02747         p->icons[i].size.height = 0;
    02748     }
    02749
    02750     p->icon_count = 0;
    02751     }
    02752
    02753     // assign icon
    02754     p->icons[p->icon_count] = icon;
    02755     p->icon_count++;
    02756
    02757     // do a deep copy, we want to own the data
    02758     NETIcon &ni = p->icons[p->icon_count - 1];
    02759     sz = ni.size.width * ni.size.height;
    02760     CARD32 *d = new CARD32[sz];
    02761     ni.data = (unsigned char *) d;
    02762     memcpy(d, icon.data, sz * sizeof(CARD32));
    02763
    02764     // compute property length
    02765     for (i = 0, proplen = 0; i < p->icon_count; i++) {
    02766     proplen += 2 + (p->icons[i].size.width *
    02767             p->icons[i].size.height);
    02768     }
    02769
    02770     CARD32 *d32;
    02771     long *prop = new long[proplen], *pprop = prop;
    02772     for (i = 0; i < p->icon_count; i++) {
    02773     // copy size into property
    02774         *pprop++ = p->icons[i].size.width;
    02775     *pprop++ = p->icons[i].size.height;
    02776
    02777     // copy data into property
    02778     sz = (p->icons[i].size.width * p->icons[i].size.height);
    02779     d32 = (CARD32 *) p->icons[i].data;
    02780     for (j = 0; j < sz; j++) *pprop++ = *d32++;
    02781     }
    02782
    02783     XChangeProperty(p->display, p->window, net_wm_icon, XA_CARDINAL, 32,
    02784             PropModeReplace, (unsigned char *) prop, proplen);
    02785
    02786     delete [] prop;
    02787 }
    02788
    02789
    02790 void NETWinInfo::setIconGeometry(NETRect geometry) {
    02791     if (role != Client) return;
    02792
    02793     p->icon_geom = geometry;
    02794
    02795     long data[4];
    02796     data[0] = geometry.pos.x;
    02797     data[1] = geometry.pos.y;
    02798     data[2] = geometry.size.width;
    02799     data[3] = geometry.size.height;
    02800
    02801     XChangeProperty(p->display, p->window, net_wm_icon_geometry, XA_CARDINAL,
    02802             32, PropModeReplace, (unsigned char *) data, 4);
    02803 }
    02804
    02805
    02806 void NETWinInfo::setExtendedStrut(const NETExtendedStrut& extended_strut ) {
    02807     if (role != Client) return;
    02808
    02809     p->extended_strut = extended_strut;
    02810
    02811     long data[12];
    02812     data[0] = extended_strut.left_width;
    02813     data[1] = extended_strut.right_width;
    02814     data[2] = extended_strut.top_width;
    02815     data[3] = extended_strut.bottom_width;
    02816     data[4] = extended_strut.left_start;
    02817     data[5] = extended_strut.left_end;
    02818     data[6] = extended_strut.right_start;
    02819     data[7] = extended_strut.right_end;
    02820     data[8] = extended_strut.top_start;
    02821     data[9] = extended_strut.top_end;
    02822     data[10] = extended_strut.bottom_start;
    02823     data[11] = extended_strut.bottom_end;
    02824
    02825     XChangeProperty(p->display, p->window, net_wm_extended_strut, XA_CARDINAL, 32,
    02826             PropModeReplace, (unsigned char *) data, 12);
    02827 }
    02828
    02829
    02830 void NETWinInfo::setStrut(NETStrut strut) {
    02831     if (role != Client) return;
    02832
    02833     p->strut = strut;
    02834
    02835     long data[4];
    02836     data[0] = strut.left;
    02837     data[1] = strut.right;
    02838     data[2] = strut.top;
    02839     data[3] = strut.bottom;
    02840
    02841     XChangeProperty(p->display, p->window, net_wm_strut, XA_CARDINAL, 32,
    02842             PropModeReplace, (unsigned char *) data, 4);
    02843 }
    02844
    02845
    02846 void NETWinInfo::setState(unsigned long state, unsigned long mask) {
    02847     if (p->mapping_state_dirty)
    02848     updateWMState();
    02849
    02850     // setState() needs to know the current state, so read it even if not requested
    02851     if( ( p->properties[ PROTOCOLS ] & WMState ) == 0 ) {
    02852         p->properties[ PROTOCOLS ] |= WMState;
    02853         unsigned long props[ PROPERTIES_SIZE ] = { WMState, 0 };
    02854         assert( PROPERTIES_SIZE == 2 ); // add elements above
    02855         update( props );
    02856         p->properties[ PROTOCOLS ] &= ~WMState;
    02857     }
    02858
    02859     if (role == Client && p->mapping_state != Withdrawn) {
    02860
    02861 #ifdef NETWMDEBUG
    02862         fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n",
    02863                 state, mask);
    02864 #endif // NETWMDEBUG
    02865
    02866     XEvent e;
    02867     e.xclient.type = ClientMessage;
    02868     e.xclient.message_type = net_wm_state;
    02869     e.xclient.display = p->display;
    02870     e.xclient.window = p->window;
    02871     e.xclient.format = 32;
    02872     e.xclient.data.l[3] = 0l;
    02873     e.xclient.data.l[4] = 0l;
    02874
    02875     if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
    02876         e.xclient.data.l[0] = (state & Modal) ? 1 : 0;
    02877         e.xclient.data.l[1] = net_wm_state_modal;
    02878         e.xclient.data.l[2] = 0l;
    02879
    02880         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02881     }
    02882
    02883     if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
    02884         e.xclient.data.l[0] = (state & Sticky) ? 1 : 0;
    02885         e.xclient.data.l[1] = net_wm_state_sticky;
    02886         e.xclient.data.l[2] = 0l;
    02887
    02888         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02889     }
    02890
    02891     if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) {
    02892
    02893         unsigned long wishstate = (p->state & ~mask) | (state & mask);
    02894         if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) )
    02895          && ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) {
    02896         if ( (wishstate & Max) == Max ) {
    02897             e.xclient.data.l[0] = 1;
    02898             e.xclient.data.l[1] = net_wm_state_max_horiz;
    02899             e.xclient.data.l[2] = net_wm_state_max_vert;
    02900             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02901         } else if ( (wishstate & Max) == 0 ) {
    02902             e.xclient.data.l[0] = 0;
    02903             e.xclient.data.l[1] = net_wm_state_max_horiz;
    02904             e.xclient.data.l[2] = net_wm_state_max_vert;
    02905             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02906         } else {
    02907             e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
    02908             e.xclient.data.l[1] = net_wm_state_max_horiz;
    02909             e.xclient.data.l[2] = 0;
    02910             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02911             e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
    02912             e.xclient.data.l[1] = net_wm_state_max_vert;
    02913             e.xclient.data.l[2] = 0;
    02914             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02915         }
    02916         } else  if ( (wishstate & MaxVert) != (p->state & MaxVert) ) {
    02917         e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
    02918         e.xclient.data.l[1] = net_wm_state_max_vert;
    02919         e.xclient.data.l[2] = 0;
    02920         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02921         } else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) {
    02922         e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
    02923         e.xclient.data.l[1] = net_wm_state_max_horiz;
    02924         e.xclient.data.l[2] = 0;
    02925         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02926         }
    02927     }
    02928
    02929     if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
    02930         e.xclient.data.l[0] = (state & Shaded) ? 1 : 0;
    02931         e.xclient.data.l[1] = net_wm_state_shaded;
    02932         e.xclient.data.l[2] = 0l;
    02933
    02934         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02935     }
    02936
    02937     if ((mask & SkipTaskbar) &&
    02938         ((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
    02939         e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0;
    02940         e.xclient.data.l[1] = net_wm_state_skip_taskbar;
    02941         e.xclient.data.l[2] = 0l;
    02942
    02943         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02944     }
    02945
    02946         if ((mask & SkipPager) &&
    02947         ((p->state & SkipPager) != (state & SkipPager))) {
    02948             e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0;
    02949             e.xclient.data.l[1] = net_wm_state_skip_pager;
    02950             e.xclient.data.l[2] = 0l;
    02951
    02952             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02953         }
    02954
    02955         if ((mask & Hidden) &&
    02956         ((p->state & Hidden) != (state & Hidden))) {
    02957             e.xclient.data.l[0] = (state & Hidden) ? 1 : 0;
    02958             e.xclient.data.l[1] = net_wm_state_hidden;
    02959             e.xclient.data.l[2] = 0l;
    02960
    02961             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02962         }
    02963
    02964         if ((mask & FullScreen) &&
    02965         ((p->state & FullScreen) != (state & FullScreen))) {
    02966             e.xclient.data.l[0] = (state & FullScreen) ? 1 : 0;
    02967             e.xclient.data.l[1] = net_wm_state_fullscreen;
    02968             e.xclient.data.l[2] = 0l;
    02969
    02970             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02971         }
    02972
    02973         if ((mask & KeepAbove) &&
    02974         ((p->state & KeepAbove) != (state & KeepAbove))) {
    02975             e.xclient.data.l[0] = (state & KeepAbove) ? 1 : 0;
    02976             e.xclient.data.l[1] = net_wm_state_above;
    02977             e.xclient.data.l[2] = 0l;
    02978
    02979             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02980         }
    02981
    02982         if ((mask & KeepBelow) &&
    02983         ((p->state & KeepBelow) != (state & KeepBelow))) {
    02984             e.xclient.data.l[0] = (state & KeepBelow) ? 1 : 0;
    02985             e.xclient.data.l[1] = net_wm_state_below;
    02986             e.xclient.data.l[2] = 0l;
    02987
    02988             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02989         }
    02990
    02991     if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) {
    02992         e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0;
    02993         e.xclient.data.l[1] = net_wm_state_stays_on_top;
    02994         e.xclient.data.l[2] = 0l;
    02995
    02996         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    02997     }
    02998
    02999         if ((mask & DemandsAttention) &&
    03000         ((p->state & DemandsAttention) != (state & DemandsAttention))) {
    03001             e.xclient.data.l[0] = (state & DemandsAttention) ? 1 : 0;
    03002             e.xclient.data.l[1] = net_wm_state_demands_attention;
    03003             e.xclient.data.l[2] = 0l;
    03004
    03005             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    03006         }
    03007
    03008     } else {
    03009     p->state &= ~mask;
    03010     p->state |= state;
    03011
    03012     long data[50];
    03013     int count = 0;
    03014
    03015     // hints
    03016     if (p->state & Modal) data[count++] = net_wm_state_modal;
    03017     if (p->state & MaxVert) data[count++] = net_wm_state_max_vert;
    03018     if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz;
    03019     if (p->state & Shaded) data[count++] = net_wm_state_shaded;
    03020     if (p->state & Hidden) data[count++] = net_wm_state_hidden;
    03021     if (p->state & FullScreen) data[count++] = net_wm_state_fullscreen;
    03022     if (p->state & DemandsAttention) data[count++] = net_wm_state_demands_attention;
    03023
    03024     // policy
    03025     if (p->state & KeepAbove) data[count++] = net_wm_state_above;
    03026     if (p->state & KeepBelow) data[count++] = net_wm_state_below;
    03027     if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top;
    03028     if (p->state & Sticky) data[count++] = net_wm_state_sticky;
    03029     if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar;
    03030     if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager;
    03031
    03032 #ifdef NETWMDEBUG
    03033     fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
    03034     for (int i = 0; i < count; i++) {
    03035             char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
    03036         fprintf(stderr, "NETWinInfo::setState:   state %ld '%s'\n",
    03037             data[i], data_ret);
    03038             if ( data_ret )
    03039                 XFree( data_ret );
    03040         }
    03041
    03042 #endif
    03043
    03044     XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32,
    03045             PropModeReplace, (unsigned char *) data, count);
    03046     }
    03047 }
    03048
    03049
    03050 void NETWinInfo::setWindowType(WindowType type) {
    03051     if (role != Client) return;
    03052
    03053     int len;
    03054     long data[2];
    03055
    03056     switch (type) {
    03057     case Override:
    03058     // spec extension: override window type.  we must comply with the spec
    03059     // and provide a fall back (normal seems best)
    03060     data[0] = kde_net_wm_window_type_override;
    03061     data[1] = net_wm_window_type_normal;
    03062     len = 2;
    03063     break;
    03064
    03065     case  Dialog:
    03066     data[0] = net_wm_window_type_dialog;
    03067     data[1] = None;
    03068     len = 1;
    03069     break;
    03070
    03071     case Menu:
    03072     data[0] = net_wm_window_type_menu;
    03073     data[1] = None;
    03074     len = 1;
    03075     break;
    03076
    03077     case TopMenu:
    03078     // spec extension: override window type.  we must comply with the spec
    03079     // and provide a fall back (dock seems best)
    03080     data[0] = kde_net_wm_window_type_topmenu;
    03081     data[1] = net_wm_window_type_dock;
    03082     len = 2;
    03083     break;
    03084
    03085     case Tool:
    03086     data[0] = net_wm_window_type_toolbar;
    03087     data[1] = None;
    03088     len = 1;
    03089     break;
    03090
    03091     case Dock:
    03092     data[0] = net_wm_window_type_dock;
    03093     data[1] = None;
    03094     len = 1;
    03095     break;
    03096
    03097     case Desktop:
    03098     data[0] = net_wm_window_type_desktop;
    03099     data[1] = None;
    03100     len = 1;
    03101     break;
    03102
    03103     case Utility:
    03104     data[0] = net_wm_window_type_utility;
    03105     data[1] = net_wm_window_type_dialog; // fallback for old netwm version
    03106     len = 2;
    03107     break;
    03108
    03109     case Splash:
    03110     data[0] = net_wm_window_type_splash;
    03111     data[1] = net_wm_window_type_dock; // fallback (dock seems best)
    03112     len = 2;
    03113     break;
    03114
    03115     default:
    03116     case Normal:
    03117     data[0] = net_wm_window_type_normal;
    03118     data[1] = None;
    03119     len = 1;
    03120     break;
    03121     }
    03122
    03123     XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32,
    03124             PropModeReplace, (unsigned char *) &data, len);
    03125 }
    03126
    03127
    03128 void NETWinInfo::setName(const char *name) {
    03129     if (role != Client) return;
    03130
    03131     delete [] p->name;
    03132     p->name = nstrdup(name);
    03133     if( p->name[ 0 ] != '\0' )
    03134         XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8,
    03135             PropModeReplace, (unsigned char *) p->name,
    03136             strlen(p->name));
    03137     else
    03138         XDeleteProperty(p->display, p->window, net_wm_name);
    03139 }
    03140
    03141
    03142 void NETWinInfo::setVisibleName(const char *visibleName) {
    03143     if (role != WindowManager) return;
    03144
    03145     delete [] p->visible_name;
    03146     p->visible_name = nstrdup(visibleName);
    03147     if( p->visible_name[ 0 ] != '\0' )
    03148         XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8,
    03149             PropModeReplace, (unsigned char *) p->visible_name,
    03150             strlen(p->visible_name));
    03151     else
    03152         XDeleteProperty(p->display, p->window, net_wm_visible_name);
    03153 }
    03154
    03155
    03156 void NETWinInfo::setIconName(const char *iconName) {
    03157     if (role != Client) return;
    03158
    03159     delete [] p->icon_name;
    03160     p->icon_name = nstrdup(iconName);
    03161     if( p->icon_name[ 0 ] != '\0' )
    03162         XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8,
    03163             PropModeReplace, (unsigned char *) p->icon_name,
    03164             strlen(p->icon_name));
    03165     else
    03166         XDeleteProperty(p->display, p->window, net_wm_icon_name);
    03167 }
    03168
    03169
    03170 void NETWinInfo::setVisibleIconName(const char *visibleIconName) {
    03171     if (role != WindowManager) return;
    03172
    03173     delete [] p->visible_icon_name;
    03174     p->visible_icon_name = nstrdup(visibleIconName);
    03175     if( p->visible_icon_name[ 0 ] != '\0' )
    03176         XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8,
    03177             PropModeReplace, (unsigned char *) p->visible_icon_name,
    03178             strlen(p->visible_icon_name));
    03179     else
    03180         XDeleteProperty(p->display, p->window, net_wm_visible_icon_name);
    03181 }
    03182
    03183
    03184 void NETWinInfo::setDesktop(int desktop) {
    03185     if (p->mapping_state_dirty)
    03186     updateWMState();
    03187
    03188     if (role == Client && p->mapping_state != Withdrawn) {
    03189     // we only send a ClientMessage if we are 1) a client and 2) managed
    03190
    03191     if ( desktop == 0 )
    03192         return; // we can't do that while being managed
    03193
    03194     XEvent e;
    03195
    03196     e.xclient.type = ClientMessage;
    03197     e.xclient.message_type = net_wm_desktop;
    03198     e.xclient.display = p->display;
    03199     e.xclient.window = p->window;
    03200     e.xclient.format = 32;
    03201     e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1;
    03202     e.xclient.data.l[1] = 0l;
    03203     e.xclient.data.l[2] = 0l;
    03204     e.xclient.data.l[3] = 0l;
    03205     e.xclient.data.l[4] = 0l;
    03206
    03207     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
    03208     } else {
    03209     // otherwise we just set or remove the property directly
    03210     p->desktop = desktop;
    03211     long d = desktop;
    03212
    03213     if ( d != OnAllDesktops ) {
    03214         if ( d == 0 ) {
    03215         XDeleteProperty( p->display, p->window, net_wm_desktop );
    03216         return;
    03217         }
    03218
    03219         d -= 1;
    03220     }
    03221
    03222     XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32,
    03223             PropModeReplace, (unsigned char *) &d, 1);
    03224     }
    03225 }
    03226
    03227
    03228 void NETWinInfo::setPid(int pid) {
    03229     if (role != Client) return;
    03230
    03231     p->pid = pid;
    03232     long d = pid;
    03233     XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32,
    03234             PropModeReplace, (unsigned char *) &d, 1);
    03235 }
    03236
    03237
    03238 void NETWinInfo::setHandledIcons(Bool handled) {
    03239     if (role != Client) return;
    03240
    03241     p->handled_icons = handled;
    03242     long d = handled;
    03243     XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32,
    03244             PropModeReplace, (unsigned char *) &d, 1);
    03245 }
    03246
    03247 void NETWinInfo::setStartupId(const char* id) {
    03248     if (role != Client) return;
    03249
    03250     delete[] p->startup_id;
    03251     p->startup_id = nstrdup(id);
    03252     XChangeProperty(p->display, p->window, net_startup_id, UTF8_STRING, 8,
    03253         PropModeReplace, reinterpret_cast< unsigned char* >( p->startup_id ),
    03254         strlen( p->startup_id ));
    03255 }
    03256
    03257 void NETWinInfo::setAllowedActions( unsigned long actions ) {
    03258     if( role != WindowManager )
    03259         return;
    03260     long data[50];
    03261     int count = 0;
    03262
    03263     p->allowed_actions = actions;
    03264     if (p->allowed_actions & ActionMove) data[count++] = net_wm_action_move;
    03265     if (p->allowed_actions & ActionResize) data[count++] = net_wm_action_resize;
    03266     if (p->allowed_actions & ActionMinimize) data[count++] = net_wm_action_minimize;
    03267     if (p->allowed_actions & ActionShade) data[count++] = net_wm_action_shade;
    03268     if (p->allowed_actions & ActionStick) data[count++] = net_wm_action_stick;
    03269     if (p->allowed_actions & ActionMaxVert) data[count++] = net_wm_action_max_vert;
    03270     if (p->allowed_actions & ActionMaxHoriz) data[count++] = net_wm_action_max_horiz;
    03271     if (p->allowed_actions & ActionFullScreen) data[count++] = net_wm_action_fullscreen;
    03272     if (p->allowed_actions & ActionChangeDesktop) data[count++] = net_wm_action_change_desk;
    03273     if (p->allowed_actions & ActionClose) data[count++] = net_wm_action_close;
    03274
    03275 #ifdef NETWMDEBUG
    03276     fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count);
    03277     for (int i = 0; i < count; i++) {
    03278         char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
    03279         fprintf(stderr, "NETWinInfo::setAllowedActions:   action %ld '%s'\n",
    03280         data[i], data_ret);
    03281         if ( data_ret )
    03282             XFree(data_ret);
    03283     }
    03284 #endif
    03285
    03286     XChangeProperty(p->display, p->window, net_wm_allowed_actions, XA_ATOM, 32,
    03287             PropModeReplace, (unsigned char *) data, count);
    03288 }
    03289
    03290 void NETWinInfo::setKDESystemTrayWinFor(Window window) {
    03291     if (role != Client) return;
    03292
    03293     p->kde_system_tray_win_for = window;
    03294     XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
    03295             XA_WINDOW, 32, PropModeReplace,
    03296             (unsigned char *) &(p->kde_system_tray_win_for), 1);
    03297 }
    03298
    03299
    03300 void NETWinInfo::setKDEFrameStrut(NETStrut strut) {
    03301     if (role != WindowManager) return;
    03302
    03303     p->frame_strut = strut;
    03304
    03305     long d[4];
    03306     d[0] = strut.left;
    03307     d[1] = strut.right;
    03308     d[2] = strut.top;
    03309     d[3] = strut.bottom;
    03310
    03311     XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32,
    03312             PropModeReplace, (unsigned char *) d, 4);
    03313 }
    03314
    03315
    03316 void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) {
    03317     if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
    03318     Window unused;
    03319     int x, y;
    03320     unsigned int w, h, junk;
    03321     XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk);
    03322     XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused
    03323                   );
    03324
    03325     p->win_geom.pos.x = x;
    03326     p->win_geom.pos.y = y;
    03327
    03328     p->win_geom.size.width = w;
    03329     p->win_geom.size.height = h;
    03330     }
    03331 // TODO try to work also without _KDE_NET_WM_FRAME_STRUT
    03332     window = p->win_geom;
    03333
    03334     frame.pos.x = window.pos.x - p->frame_strut.left;
    03335     frame.pos.y = window.pos.y - p->frame_strut.top;
    03336     frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
    03337     frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
    03338 }
    03339
    03340
    03341 NETIcon NETWinInfo::icon(int width, int height) const {
    03342     NETIcon result;
    03343
    03344     if ( !p->icon_count ) {
    03345     result.size.width = 0;
    03346     result.size.height = 0;
    03347     result.data = 0;
    03348     return result;
    03349     }
    03350
    03351     result = p->icons[0];
    03352
    03353     // find the icon that's closest in size to w x h...
    03354     // return the first icon if w and h are -1
    03355     if (width == height && height == -1) return result;
    03356
    03357     int i;
    03358     for (i = 0; i < p->icons.size(); i++) {
    03359     if ((p->icons[i].size.width >= width &&
    03360          p->icons[i].size.width < result.size.width) &&
    03361         (p->icons[i].size.height >= height &&
    03362          p->icons[i].size.height < result.size.height))
    03363         result = p->icons[i];
    03364     }
    03365
    03366     return result;
    03367 }
    03368
    03369 void NETWinInfo::setUserTime( Time time ) {
    03370     if (role != Client) return;
    03371
    03372     p->user_time = time;
    03373     long d = time;
    03374     XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32,
    03375             PropModeReplace, (unsigned char *) &d, 1);
    03376 }
    03377
    03378
    03379 unsigned long NETWinInfo::event(XEvent *ev )
    03380 {
    03381     unsigned long props[ 1 ];
    03382     event( ev, props, 1 );
    03383     return props[ 0 ];
    03384 }
    03385
    03386 void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) {
    03387     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 };
    03388     assert( PROPERTIES_SIZE == 2 ); // add elements above
    03389     unsigned long& dirty = props[ PROTOCOLS ];
    03390     unsigned long& dirty2 = props[ PROTOCOLS2 ];
    03391     bool do_update = false;
    03392
    03393     if (role == WindowManager && event->type == ClientMessage &&
    03394     event->xclient.format == 32) {
    03395
    03396 #ifdef NETWMDEBUG
    03397         fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
    03398 #endif // NETWMDEBUG
    03399
    03400     if (event->xclient.message_type == net_wm_state) {
    03401         dirty = WMState;
    03402
    03403         // we need to generate a change mask
    03404
    03405 #ifdef NETWMDEBUG
    03406         fprintf(stderr,
    03407             "NETWinInfo::event: state client message, getting new state/mask\n");
    03408 #endif
    03409
    03410         int i;
    03411         long state = 0, mask = 0;
    03412
    03413         for (i = 1; i < 3; i++) {
    03414 #ifdef NETWMDEBUG
    03415                 char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]);
    03416         fprintf(stderr, "NETWinInfo::event:  message %ld '%s'\n",
    03417             event->xclient.data.l[i], debug_txt );
    03418                 if ( debug_txt )
    03419                     XFree( debug_txt );
    03420 #endif
    03421
    03422         if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
    03423             mask |= Modal;
    03424         else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
    03425             mask |= Sticky;
    03426         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
    03427             mask |= MaxVert;
    03428         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
    03429             mask |= MaxHoriz;
    03430         else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
    03431             mask |= Shaded;
    03432         else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
    03433             mask |= SkipTaskbar;
    03434                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
    03435             mask |= SkipPager;
    03436                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden)
    03437             mask |= Hidden;
    03438                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen)
    03439             mask |= FullScreen;
    03440                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_above)
    03441             mask |= KeepAbove;
    03442                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_below)
    03443             mask |= KeepBelow;
    03444                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention)
    03445             mask |= DemandsAttention;
    03446         else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
    03447             mask |= StaysOnTop;
    03448         }
    03449
    03450         // when removing, we just leave newstate == 0
    03451         switch (event->xclient.data.l[0]) {
    03452         case 1: // set
    03453         // to set... the change state should be the same as the mask
    03454         state = mask;
    03455         break;
    03456
    03457         case 2: // toggle
    03458         // to toggle, we need to xor the current state with the new state
    03459         state = (p->state & mask) ^ mask;
    03460         break;
    03461
    03462         default:
    03463         // to clear state, the new state should stay zero
    03464         ;
    03465         }
    03466
    03467 #ifdef NETWMDEBUG
    03468         fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
    03469             state, mask);
    03470 #endif
    03471
    03472         changeState(state, mask);
    03473     } else if (event->xclient.message_type == net_wm_desktop) {
    03474         dirty = WMDesktop;
    03475
    03476         if( event->xclient.data.l[0] == OnAllDesktops )
    03477         changeDesktop( OnAllDesktops );
    03478         else
    03479             changeDesktop(event->xclient.data.l[0] + 1);
    03480     }
    03481     }
    03482
    03483     if (event->type == PropertyNotify) {
    03484
    03485 #ifdef    NETWMDEBUG
    03486     fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
    03487 #endif
    03488
    03489     XEvent pe = *event;
    03490
    03491     Bool done = False;
    03492     Bool compaction = False;
    03493     while (! done) {
    03494
    03495 #ifdef    NETWMDEBUG
    03496         fprintf(stderr, "NETWinInfo::event: loop fire\n");
    03497 #endif
    03498
    03499         if (pe.xproperty.atom == net_wm_name)
    03500         dirty |= WMName;
    03501         else if (pe.xproperty.atom == net_wm_visible_name)
    03502         dirty |= WMVisibleName;
    03503         else if (pe.xproperty.atom == net_wm_desktop)
    03504         dirty |= WMDesktop;
    03505         else if (pe.xproperty.atom == net_wm_window_type)
    03506         dirty |=WMWindowType;
    03507         else if (pe.xproperty.atom == net_wm_state)
    03508         dirty |= WMState;
    03509         else if (pe.xproperty.atom == net_wm_strut)
    03510         dirty |= WMStrut;
    03511         else if (pe.xproperty.atom == net_wm_extended_strut)
    03512         dirty2 |= WM2ExtendedStrut;
    03513         else if (pe.xproperty.atom == net_wm_icon_geometry)
    03514         dirty |= WMIconGeometry;
    03515         else if (pe.xproperty.atom == net_wm_icon)
    03516         dirty |= WMIcon;
    03517         else if (pe.xproperty.atom == net_wm_pid)
    03518         dirty |= WMPid;
    03519         else if (pe.xproperty.atom == net_wm_handled_icons)
    03520         dirty |= WMHandledIcons;
    03521         else if (pe.xproperty.atom == net_startup_id)
    03522         dirty2 |= WM2StartupId;
    03523         else if (pe.xproperty.atom == net_wm_allowed_actions)
    03524         dirty2 |= WM2AllowedActions;
    03525         else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
    03526         dirty |= WMKDESystemTrayWinFor;
    03527         else if (pe.xproperty.atom == xa_wm_state)
    03528         dirty |= XAWMState;
    03529         else if (pe.xproperty.atom == kde_net_wm_frame_strut)
    03530         dirty |= WMKDEFrameStrut;
    03531         else if (pe.xproperty.atom == net_wm_icon_name)
    03532         dirty |= WMIconName;
    03533         else if (pe.xproperty.atom == net_wm_visible_icon_name)
    03534         dirty |= WMVisibleIconName;
    03535         else if (pe.xproperty.atom == net_wm_user_time)
    03536         dirty2 |= WM2UserTime;
    03537             else if (pe.xproperty.atom == XA_WM_HINTS)
    03538                 dirty2 |= WM2GroupLeader;
    03539             else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR)
    03540                 dirty2 |= WM2TransientFor;
    03541             else if (pe.xproperty.atom == XA_WM_CLASS)
    03542                 dirty2 |= WM2WindowClass;
    03543             else if (pe.xproperty.atom == wm_window_role)
    03544                 dirty2 |= WM2WindowRole;
    03545             else if (pe.xproperty.atom == XA_WM_CLIENT_MACHINE)
    03546                 dirty2 |= WM2ClientMachine;
    03547         else {
    03548
    03549 #ifdef    NETWMDEBUG
    03550         fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
    03551 #endif
    03552
    03553         if ( compaction )
    03554             XPutBackEvent(p->display, &pe);
    03555         break;
    03556         }
    03557
    03558         if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
    03559         compaction = True;
    03560         else
    03561         break;
    03562     }
    03563
    03564     do_update = true;
    03565     } else if (event->type == ConfigureNotify) {
    03566
    03567 #ifdef NETWMDEBUG
    03568     fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
    03569 #endif
    03570
    03571     dirty |= WMGeometry;
    03572
    03573     // update window geometry
    03574     p->win_geom.pos.x = event->xconfigure.x;
    03575     p->win_geom.pos.y = event->xconfigure.y;
    03576     p->win_geom.size.width = event->xconfigure.width;
    03577     p->win_geom.size.height = event->xconfigure.height;
    03578     }
    03579
    03580     if( do_update )
    03581         update( props );
    03582
    03583     if( properties_size > PROPERTIES_SIZE )
    03584         properties_size = PROPERTIES_SIZE;
    03585     for( int i = 0;
    03586          i < properties_size;
    03587          ++i )
    03588         properties[ i ] = props[ i ];
    03589 }
    03590
    03591 void NETWinInfo::updateWMState() {
    03592     unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 };
    03593     assert( PROPERTIES_SIZE == 2 ); // add elements above
    03594     update( props );
    03595 }
    03596
    03597 void NETWinInfo::update(const unsigned long dirty_props[]) {
    03598     Atom type_ret;
    03599     int format_ret;
    03600     unsigned long nitems_ret, unused;
    03601     unsigned char *data_ret;
    03602     unsigned long props[ PROPERTIES_SIZE ];
    03603     for( int i = 0;
    03604          i < PROPERTIES_SIZE;
    03605          ++i )
    03606         props[ i ] = dirty_props[ i ] & p->properties[ i ];
    03607     const unsigned long& dirty = props[ PROTOCOLS ];
    03608     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
    03609
    03610     // we *always* want to update WM_STATE if set in dirty_props
    03611     if( dirty_props[ PROTOCOLS ] & XAWMState )
    03612         props[ PROTOCOLS ] |= XAWMState;
    03613
    03614     if (dirty & XAWMState) {
    03615         p->mapping_state = Withdrawn;
    03616     if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
    03617                    False, xa_wm_state, &type_ret, &format_ret,
    03618                    &nitems_ret, &unused, &data_ret)
    03619         == Success) {
    03620         if (type_ret == xa_wm_state && format_ret == 32 &&
    03621         nitems_ret == 1) {
    03622         long *state = (long *) data_ret;
    03623
    03624         switch(*state) {
    03625             case IconicState:
    03626             p->mapping_state = Iconic;
    03627             break;
    03628             case NormalState:
    03629             p->mapping_state = Visible;
    03630                         break;
    03631             case WithdrawnState:
    03632             default:
    03633             p->mapping_state = Withdrawn;
    03634             break;
    03635         }
    03636
    03637         p->mapping_state_dirty = False;
    03638         }
    03639         if ( data_ret )
    03640         XFree(data_ret);
    03641     }
    03642     }
    03643
    03644     if (dirty & WMState) {
    03645     p->state = 0;
    03646     if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
    03647                    False, XA_ATOM, &type_ret, &format_ret,
    03648                    &nitems_ret, &unused, &data_ret)
    03649         == Success) {
    03650         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
    03651         // determine window state
    03652 #ifdef NETWMDEBUG
    03653         fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
    03654             nitems_ret);
    03655 #endif
    03656
    03657         long *states = (long *) data_ret;
    03658         unsigned long count;
    03659
    03660         for (count = 0; count < nitems_ret; count++) {
    03661 #ifdef NETWMDEBUG
    03662                     char* data_ret = XGetAtomName(p->display, (Atom) states[count]);
    03663             fprintf(stderr,
    03664                 "NETWinInfo::update:   adding window state %ld '%s'\n",
    03665                 states[count], data_ret );
    03666                     if ( data_ret )
    03667                         XFree( data_ret );
    03668 #endif
    03669
    03670             if ((Atom) states[count] == net_wm_state_modal)
    03671             p->state |= Modal;
    03672             else if ((Atom) states[count] == net_wm_state_sticky)
    03673             p->state |= Sticky;
    03674             else if ((Atom) states[count] == net_wm_state_max_vert)
    03675             p->state |= MaxVert;
    03676             else if ((Atom) states[count] == net_wm_state_max_horiz)
    03677             p->state |= MaxHoriz;
    03678             else if ((Atom) states[count] == net_wm_state_shaded)
    03679             p->state |= Shaded;
    03680             else if ((Atom) states[count] == net_wm_state_skip_taskbar)
    03681             p->state |= SkipTaskbar;
    03682             else if ((Atom) states[count] == net_wm_state_skip_pager)
    03683             p->state |= SkipPager;
    03684             else if ((Atom) states[count] == net_wm_state_hidden)
    03685             p->state |= Hidden;
    03686             else if ((Atom) states[count] == net_wm_state_fullscreen)
    03687             p->state |= FullScreen;
    03688             else if ((Atom) states[count] == net_wm_state_above)
    03689             p->state |= KeepAbove;
    03690             else if ((Atom) states[count] == net_wm_state_below)
    03691             p->state |= KeepBelow;
    03692             else if ((Atom) states[count] == net_wm_state_demands_attention)
    03693             p->state |= DemandsAttention;
    03694             else if ((Atom) states[count] == net_wm_state_stays_on_top)
    03695             p->state |= StaysOnTop;
    03696         }
    03697         }
    03698         if ( data_ret )
    03699         XFree(data_ret);
    03700     }
    03701     }
    03702
    03703     if (dirty & WMDesktop) {
    03704     p->desktop = 0;
    03705     if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
    03706                    False, XA_CARDINAL, &type_ret,
    03707                    &format_ret, &nitems_ret,
    03708                    &unused, &data_ret)
    03709         == Success) {
    03710         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    03711         nitems_ret == 1) {
    03712         p->desktop = *((long *) data_ret);
    03713         if ((signed) p->desktop != OnAllDesktops)
    03714             p->desktop++;
    03715
    03716         if ( p->desktop == 0 )
    03717             p->desktop = OnAllDesktops;
    03718         }
    03719         if ( data_ret )
    03720         XFree(data_ret);
    03721     }
    03722     }
    03723
    03724     if (dirty & WMName) {
    03725         delete[] p->name;
    03726         p->name = NULL;
    03727     if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
    03728                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    03729                    &format_ret, &nitems_ret, &unused, &data_ret)
    03730         == Success) {
    03731         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
    03732         p->name = nstrndup((const char *) data_ret, nitems_ret);
    03733         }
    03734
    03735         if( data_ret )
    03736         XFree(data_ret);
    03737     }
    03738     }
    03739
    03740     if (dirty & WMVisibleName) {
    03741         delete[] p->visible_name;
    03742         p->visible_name = NULL;
    03743     if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
    03744                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    03745                    &format_ret, &nitems_ret, &unused, &data_ret)
    03746         == Success) {
    03747         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
    03748         p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
    03749         }
    03750
    03751         if( data_ret )
    03752         XFree(data_ret);
    03753     }
    03754     }
    03755
    03756     if (dirty & WMIconName) {
    03757         delete[] p->icon_name;
    03758         p->icon_name = NULL;
    03759     if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
    03760                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    03761                    &format_ret, &nitems_ret, &unused, &data_ret)
    03762         == Success) {
    03763         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
    03764         p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
    03765         }
    03766
    03767         if( data_ret )
    03768         XFree(data_ret);
    03769     }
    03770     }
    03771
    03772     if (dirty & WMVisibleIconName)
    03773     {
    03774         delete[] p->visible_icon_name;
    03775         p->visible_icon_name = NULL;
    03776     if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
    03777                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    03778                    &format_ret, &nitems_ret, &unused, &data_ret)
    03779         == Success) {
    03780         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
    03781         p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
    03782         }
    03783
    03784         if( data_ret )
    03785         XFree(data_ret);
    03786     }
    03787     }
    03788
    03789     if (dirty & WMWindowType) {
    03790     p->types.reset();
    03791     p->types[ 0 ] = Unknown;
    03792         p->has_net_support = false;
    03793     if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
    03794                    False, XA_ATOM, &type_ret, &format_ret,
    03795                    &nitems_ret, &unused, &data_ret)
    03796         == Success) {
    03797         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
    03798         // determine the window type
    03799 #ifdef NETWMDEBUG
    03800         fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
    03801             nitems_ret);
    03802 #endif
    03803
    03804                 p->has_net_support = true;
    03805
    03806         unsigned long count = 0;
    03807         long *types = (long *) data_ret;
    03808         int pos = 0;
    03809
    03810         while (count < nitems_ret) {
    03811             // remember all window types we know
    03812 #ifdef NETWMDEBUG
    03813                     char* debug_type = XGetAtomName(p->display, (Atom) types[count]);
    03814             fprintf(stderr,
    03815                 "NETWinInfo::update:   examining window type %ld %s\n",
    03816                 types[count], debug_type );
    03817                     if ( debug_type )
    03818                         XFree( debug_type );
    03819 #endif
    03820
    03821             if ((Atom) types[count] == net_wm_window_type_normal)
    03822             p->types[ pos++ ] = Normal;
    03823             else if ((Atom) types[count] == net_wm_window_type_desktop)
    03824             p->types[ pos++ ] = Desktop;
    03825             else if ((Atom) types[count] == net_wm_window_type_dock)
    03826             p->types[ pos++ ] = Dock;
    03827             else if ((Atom) types[count] == net_wm_window_type_toolbar)
    03828             p->types[ pos++ ] = Tool;
    03829             else if ((Atom) types[count] == net_wm_window_type_menu)
    03830             p->types[ pos++ ] = Menu;
    03831             else if ((Atom) types[count] == net_wm_window_type_dialog)
    03832             p->types[ pos++ ] = Dialog;
    03833             else if ((Atom) types[count] == net_wm_window_type_utility)
    03834             p->types[ pos++ ] = Utility;
    03835             else if ((Atom) types[count] == net_wm_window_type_splash)
    03836             p->types[ pos++ ] = Splash;
    03837             else if ((Atom) types[count] == kde_net_wm_window_type_override)
    03838             p->types[ pos++ ] = Override;
    03839             else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
    03840             p->types[ pos++ ] = TopMenu;
    03841
    03842             count++;
    03843         }
    03844         }
    03845
    03846         if ( data_ret )
    03847         XFree(data_ret);
    03848     }
    03849     }
    03850
    03851     if (dirty & WMStrut) {
    03852         p->strut = NETStrut();
    03853     if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
    03854                    False, XA_CARDINAL, &type_ret, &format_ret,
    03855                    &nitems_ret, &unused, &data_ret)
    03856         == Success) {
    03857         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    03858         nitems_ret == 4) {
    03859         long *d = (long *) data_ret;
    03860         p->strut.left   = d[0];
    03861         p->strut.right  = d[1];
    03862         p->strut.top    = d[2];
    03863         p->strut.bottom = d[3];
    03864         }
    03865         if ( data_ret )
    03866         XFree(data_ret);
    03867     }
    03868     }
    03869
    03870     if (dirty2 & WM2ExtendedStrut) {
    03871         p->extended_strut = NETExtendedStrut();
    03872     if (XGetWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l,
    03873                    False, XA_CARDINAL, &type_ret, &format_ret,
    03874                    &nitems_ret, &unused, &data_ret)
    03875         == Success) {
    03876         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    03877         nitems_ret == 12) {
    03878         long *d = (long *) data_ret;
    03879         p->extended_strut.left_width = d[0];
    03880         p->extended_strut.right_width = d[1];
    03881         p->extended_strut.top_width = d[2];
    03882         p->extended_strut.bottom_width = d[3];
    03883                 p->extended_strut.left_start = d[4];
    03884                 p->extended_strut.left_end = d[5];
    03885                 p->extended_strut.right_start = d[6];
    03886                 p->extended_strut.right_end = d[7];
    03887                 p->extended_strut.top_start = d[8];
    03888                 p->extended_strut.top_end = d[9];
    03889                 p->extended_strut.bottom_start = d[10];
    03890                 p->extended_strut.bottom_end = d[11];
    03891         }
    03892         if ( data_ret )
    03893         XFree(data_ret);
    03894     }
    03895     }
    03896
    03897     if (dirty & WMIconGeometry) {
    03898         p->icon_geom = NETRect();
    03899     if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
    03900                    False, XA_CARDINAL, &type_ret, &format_ret,
    03901                    &nitems_ret, &unused, &data_ret)
    03902         == Success) {
    03903         if (type_ret == XA_CARDINAL && format_ret == 32 &&
    03904         nitems_ret == 4) {
    03905         long *d = (long *) data_ret;
    03906         p->icon_geom.pos.x       = d[0];
    03907         p->icon_geom.pos.y       = d[1];
    03908         p->icon_geom.size.width  = d[2];
    03909         p->icon_geom.size.height = d[3];
    03910         }
    03911         if ( data_ret )
    03912         XFree(data_ret);
    03913     }
    03914     }
    03915
    03916     if (dirty & WMIcon) {
    03917     readIcon(p);
    03918     }
    03919
    03920     if (dirty & WMKDESystemTrayWinFor) {
    03921     p->kde_system_tray_win_for = 0;
    03922     if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
    03923                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
    03924                    &nitems_ret, &unused, &data_ret)
    03925         == Success) {
    03926         if (type_ret == XA_WINDOW && format_ret == 32 &&
    03927         nitems_ret == 1) {
    03928         p->kde_system_tray_win_for = *((Window *) data_ret);
    03929         if ( p->kde_system_tray_win_for == 0 )
    03930             p->kde_system_tray_win_for = p->root;
    03931         }
    03932         if ( data_ret )
    03933         XFree(data_ret);
    03934         }
    03935     }
    03936
    03937     if (dirty & WMKDEFrameStrut) {
    03938         p->frame_strut = NETStrut();
    03939     if (XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
    03940                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
    03941                    &nitems_ret, &unused, &data_ret) == Success) {
    03942         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
    03943         long *d = (long *) data_ret;
    03944
    03945         p->frame_strut.left   = d[0];
    03946         p->frame_strut.right  = d[1];
    03947         p->frame_strut.top    = d[2];
    03948         p->frame_strut.bottom = d[3];
    03949         }
    03950         if ( data_ret )
    03951         XFree(data_ret);
    03952     }
    03953     }
    03954
    03955     if (dirty & WMPid) {
    03956     p->pid = 0;
    03957     if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
    03958                    False, XA_CARDINAL, &type_ret, &format_ret,
    03959                    &nitems_ret, &unused, &data_ret) == Success) {
    03960         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
    03961         p->pid = *((long *) data_ret);
    03962         }
    03963         if ( data_ret )
    03964         XFree(data_ret);
    03965     }
    03966     }
    03967
    03968     if (dirty2 & WM2StartupId)
    03969     {
    03970         delete[] p->startup_id;
    03971         p->startup_id = NULL;
    03972     if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l,
    03973                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
    03974                    &format_ret, &nitems_ret, &unused, &data_ret)
    03975         == Success) {
    03976         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
    03977         p->startup_id = nstrndup((const char *) data_ret, nitems_ret);
    03978         }
    03979
    03980         if( data_ret )
    03981         XFree(data_ret);
    03982     }
    03983     }
    03984
    03985     if( dirty2 & WM2AllowedActions ) {
    03986         p->allowed_actions = 0;
    03987     if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l,
    03988                    False, XA_ATOM, &type_ret, &format_ret,
    03989                    &nitems_ret, &unused, &data_ret)
    03990         == Success) {
    03991         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
    03992         // determine actions
    03993 #ifdef NETWMDEBUG
    03994         fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n",
    03995             nitems_ret);
    03996 #endif
    03997
    03998         long *actions = (long *) data_ret;
    03999         unsigned long count;
    04000
    04001         for (count = 0; count < nitems_ret; count++) {
    04002 #ifdef NETWMDEBUG
    04003             fprintf(stderr,
    04004                 "NETWinInfo::update:   adding allowed action %ld '%s'\n",
    04005                 actions[count],
    04006                 XGetAtomName(p->display, (Atom) actions[count]));
    04007 #endif
    04008
    04009             if ((Atom) actions[count] == net_wm_action_move)
    04010             p->allowed_actions |= ActionMove;
    04011             if ((Atom) actions[count] == net_wm_action_resize)
    04012             p->allowed_actions |= ActionResize;
    04013             if ((Atom) actions[count] == net_wm_action_minimize)
    04014             p->allowed_actions |= ActionMinimize;
    04015             if ((Atom) actions[count] == net_wm_action_shade)
    04016             p->allowed_actions |= ActionShade;
    04017             if ((Atom) actions[count] == net_wm_action_stick)
    04018             p->allowed_actions |= ActionStick;
    04019             if ((Atom) actions[count] == net_wm_action_max_vert)
    04020             p->allowed_actions |= ActionMaxVert;
    04021             if ((Atom) actions[count] == net_wm_action_max_horiz)
    04022             p->allowed_actions |= ActionMaxHoriz;
    04023             if ((Atom) actions[count] == net_wm_action_fullscreen)
    04024             p->allowed_actions |= ActionFullScreen;
    04025             if ((Atom) actions[count] == net_wm_action_change_desk)
    04026             p->allowed_actions |= ActionChangeDesktop;
    04027             if ((Atom) actions[count] == net_wm_action_close)
    04028             p->allowed_actions |= ActionClose;
    04029         }
    04030         }
    04031         if ( data_ret )
    04032         XFree(data_ret);
    04033     }
    04034     }
    04035
    04036     if (dirty2 & WM2UserTime) {
    04037     p->user_time = -1U;
    04038     if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l,
    04039                    False, XA_CARDINAL, &type_ret, &format_ret,
    04040                    &nitems_ret, &unused, &data_ret) == Success) {
    04041             // don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it
    04042         if (type_ret == XA_CARDINAL && format_ret == 32 /*&& nitems_ret == 1*/) {
    04043         p->user_time = *((long *) data_ret);
    04044         }
    04045         if ( data_ret )
    04046         XFree(data_ret);
    04047     }
    04048     }
    04049
    04050     if (dirty2 & WM2TransientFor) {
    04051     p->transient_for = None;
    04052         XGetTransientForHint(p->display, p->window, &p->transient_for);
    04053     }
    04054
    04055     if (dirty2 & WM2GroupLeader) {
    04056         XWMHints *hints = XGetWMHints(p->display, p->window);
    04057         p->window_group = None;
    04058         if ( hints )
    04059         {
    04060             if( hints->flags & WindowGroupHint )
    04061                 p->window_group = hints->window_group;
    04062             XFree( reinterpret_cast< char* >( hints ));
    04063         }
    04064     }
    04065
    04066     if( dirty2 & WM2WindowClass ) {
    04067         delete[] p->class_class;
    04068         delete[] p->class_name;
    04069         p->class_class = NULL;
    04070         p->class_name = NULL;
    04071         XClassHint hint;
    04072         if( XGetClassHint( p->display, p->window, &hint )) {
    04073             p->class_class = strdup( hint.res_class );
    04074             p->class_name = strdup( hint.res_name );
    04075             XFree( hint.res_class );
    04076             XFree( hint.res_name );
    04077         }
    04078     }
    04079
    04080     if( dirty2 & WM2WindowRole ) {
    04081         delete[] p->role;
    04082         p->role = NULL;
    04083     if (XGetWindowProperty(p->display, p->window, wm_window_role, 0l,
    04084                    MAX_PROP_SIZE, False, XA_STRING, &type_ret,
    04085                    &format_ret, &nitems_ret, &unused, &data_ret)
    04086         == Success) {
    04087         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
    04088         p->role = nstrndup((const char *) data_ret, nitems_ret);
    04089         }
    04090         if( data_ret )
    04091         XFree(data_ret);
    04092     }
    04093     }
    04094
    04095     if( dirty2 & WM2ClientMachine ) {
    04096         delete[] p->client_machine;
    04097         p->client_machine = NULL;
    04098     if (XGetWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l,
    04099                    MAX_PROP_SIZE, False, XA_STRING, &type_ret,
    04100                    &format_ret, &nitems_ret, &unused, &data_ret)
    04101         == Success) {
    04102         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
    04103         p->client_machine = nstrndup((const char *) data_ret, nitems_ret);
    04104         }
    04105         if( data_ret )
    04106         XFree(data_ret);
    04107     }
    04108     }
    04109 }
    04110
    04111
    04112 NETRect NETWinInfo::iconGeometry() const {
    04113     return p->icon_geom;
    04114 }
    04115
    04116
    04117 unsigned long NETWinInfo::state() const {
    04118     return p->state;
    04119 }
    04120
    04121
    04122 NETStrut NETWinInfo::strut() const {
    04123     return p->strut;
    04124 }
    04125
    04126 NETExtendedStrut NETWinInfo::extendedStrut() const {
    04127     return p->extended_strut;
    04128 }
    04129
    04130 bool NET::typeMatchesMask( WindowType type, unsigned long mask ) {
    04131     switch( type ) {
    04132 #define CHECK_TYPE_MASK( type ) \
    04133         case type: \
    04134             if( mask & type##Mask ) \
    04135             return true; \
    04136         break;
    04137         CHECK_TYPE_MASK( Normal )
    04138         CHECK_TYPE_MASK( Desktop )
    04139         CHECK_TYPE_MASK( Dock )
    04140         CHECK_TYPE_MASK( Toolbar )
    04141         CHECK_TYPE_MASK( Menu )
    04142         CHECK_TYPE_MASK( Dialog )
    04143         CHECK_TYPE_MASK( Override )
    04144         CHECK_TYPE_MASK( TopMenu )
    04145         CHECK_TYPE_MASK( Utility )
    04146         CHECK_TYPE_MASK( Splash )
    04147 #undef CHECK_TYPE_MASK
    04148         default:
    04149             break;
    04150     }
    04151     return false;
    04152 }
    04153
    04154 NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const {
    04155     for( int i = 0;
    04156      i < p->types.size();
    04157      ++i ) {
    04158     // return the type only if the application supports it
    04159         if( typeMatchesMask( p->types[ i ], supported_types ))
    04160             return p->types[ i ];
    04161     }
    04162     return Unknown;
    04163 }
    04164
    04165 NET::WindowType NETWinInfo::windowType() const {
    04166     return p->types[ 0 ];
    04167 }
    04168
    04169
    04170 const char *NETWinInfo::name() const {
    04171     return p->name;
    04172 }
    04173
    04174
    04175 const char *NETWinInfo::visibleName() const {
    04176     return p->visible_name;
    04177 }
    04178
    04179
    04180 const char *NETWinInfo::iconName() const {
    04181     return p->icon_name;
    04182 }
    04183
    04184
    04185 const char *NETWinInfo::visibleIconName() const {
    04186     return p->visible_icon_name;
    04187 }
    04188
    04189
    04190 int NETWinInfo::desktop() const {
    04191     return p->desktop;
    04192 }
    04193
    04194 int NETWinInfo::pid() const {
    04195     return p->pid;
    04196 }
    04197
    04198 Time NETWinInfo::userTime() const {
    04199     return p->user_time;
    04200 }
    04201
    04202 const char* NETWinInfo::startupId() const {
    04203     return p->startup_id;
    04204 }
    04205
    04206 unsigned long NETWinInfo::allowedActions() const {
    04207     return p->allowed_actions;
    04208 }
    04209
    04210 bool NETWinInfo::hasNETSupport() const {
    04211     return p->has_net_support;
    04212 }
    04213
    04214 Window NETWinInfo::transientFor() const {
    04215     return p->transient_for;
    04216 }
    04217
    04218 Window NETWinInfo::groupLeader() const {
    04219     return p->window_group;
    04220 }
    04221
    04222 const char* NETWinInfo::windowClassClass() const {
    04223     return p->class_class;
    04224 }
    04225
    04226 const char* NETWinInfo::windowClassName() const {
    04227     return p->class_name;
    04228 }
    04229
    04230 const char* NETWinInfo::windowRole() const {
    04231     return p->role;
    04232 }
    04233
    04234 const char* NETWinInfo::clientMachine() const {
    04235     return p->client_machine;
    04236 }
    04237
    04238 Bool NETWinInfo::handledIcons() const {
    04239     return p->handled_icons;
    04240 }
    04241
    04242
    04243 Window NETWinInfo::kdeSystemTrayWinFor() const {
    04244     return p->kde_system_tray_win_for;
    04245 }
    04246
    04247 const unsigned long* NETWinInfo::passedProperties() const {
    04248     return p->properties;
    04249 }
    04250
    04251 unsigned long NETWinInfo::properties() const {
    04252     return p->properties[ PROTOCOLS ];
    04253 }
    04254
    04255
    04256 NET::MappingState NETWinInfo::mappingState() const {
    04257     return p->mapping_state;
    04258 }
    04259
    04260 void NETRootInfo::virtual_hook( int, void* )
    04261 { /*BASE::virtual_hook( id, data );*/ }
    04262
    04263 void NETWinInfo::virtual_hook( int, void* )
    04264 { /*BASE::virtual_hook( id, data );*/ }
    04265
    04266 #endif

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:13 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003