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