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