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