netwm.cpp

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