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