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     // find the largest icon
03471     result = icons[0];
03472     for (int i = 1; i < icons.size(); i++) {
03473     if( icons[i].size.width >= result.size.width &&
03474          icons[i].size.height >= result.size.height )
03475         result = icons[i];
03476     }
03477 
03478     // return the largest icon if w and h are -1
03479     if (width == -1 && height == -1) return result;
03480 
03481     // find the icon that's closest in size to w x h...
03482     for (int i = 0; i < icons.size(); i++) {
03483     if ((icons[i].size.width >= width &&
03484          icons[i].size.width < result.size.width) &&
03485         (icons[i].size.height >= height &&
03486          icons[i].size.height < result.size.height))
03487         result = icons[i];
03488     }
03489 
03490     return result;
03491 }
03492 
03493 void NETWinInfo::setUserTime( Time time ) {
03494     if (role != Client) return;
03495 
03496     p->user_time = time;
03497     long d = time;
03498     XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32,
03499             PropModeReplace, (unsigned char *) &d, 1);
03500 }
03501 
03502 
03503 unsigned long NETWinInfo::event(XEvent *ev )
03504 {
03505     unsigned long props[ 1 ];
03506     event( ev, props, 1 );
03507     return props[ 0 ];
03508 }
03509 
03510 void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) {
03511     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 };
03512     assert( PROPERTIES_SIZE == 2 ); // add elements above
03513     unsigned long& dirty = props[ PROTOCOLS ];
03514     unsigned long& dirty2 = props[ PROTOCOLS2 ];
03515     bool do_update = false;
03516 
03517     if (role == WindowManager && event->type == ClientMessage &&
03518     event->xclient.format == 32) {
03519 
03520 #ifdef NETWMDEBUG
03521         fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
03522 #endif // NETWMDEBUG
03523 
03524     if (event->xclient.message_type == net_wm_state) {
03525         dirty = WMState;
03526 
03527         // we need to generate a change mask
03528 
03529 #ifdef NETWMDEBUG
03530         fprintf(stderr,
03531             "NETWinInfo::event: state client message, getting new state/mask\n");
03532 #endif
03533 
03534         int i;
03535         long state = 0, mask = 0;
03536 
03537         for (i = 1; i < 3; i++) {
03538 #ifdef NETWMDEBUG
03539                 char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]);
03540         fprintf(stderr, "NETWinInfo::event:  message %ld '%s'\n",
03541             event->xclient.data.l[i], debug_txt );
03542                 if ( debug_txt )
03543                     XFree( debug_txt );
03544 #endif
03545 
03546         if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
03547             mask |= Modal;
03548         else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
03549             mask |= Sticky;
03550         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
03551             mask |= MaxVert;
03552         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
03553             mask |= MaxHoriz;
03554         else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
03555             mask |= Shaded;
03556         else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
03557             mask |= SkipTaskbar;
03558                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
03559             mask |= SkipPager;
03560                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden)
03561             mask |= Hidden;
03562                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen)
03563             mask |= FullScreen;
03564                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_above)
03565             mask |= KeepAbove;
03566                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_below)
03567             mask |= KeepBelow;
03568                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention)
03569             mask |= DemandsAttention;
03570         else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
03571             mask |= StaysOnTop;
03572         }
03573 
03574         // when removing, we just leave newstate == 0
03575         switch (event->xclient.data.l[0]) {
03576         case 1: // set
03577         // to set... the change state should be the same as the mask
03578         state = mask;
03579         break;
03580 
03581         case 2: // toggle
03582         // to toggle, we need to xor the current state with the new state
03583         state = (p->state & mask) ^ mask;
03584         break;
03585 
03586         default:
03587         // to clear state, the new state should stay zero
03588         ;
03589         }
03590 
03591 #ifdef NETWMDEBUG
03592         fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
03593             state, mask);
03594 #endif
03595 
03596         changeState(state, mask);
03597     } else if (event->xclient.message_type == net_wm_desktop) {
03598         dirty = WMDesktop;
03599 
03600         if( event->xclient.data.l[0] == OnAllDesktops )
03601         changeDesktop( OnAllDesktops );
03602         else
03603             changeDesktop(event->xclient.data.l[0] + 1);
03604     }
03605     }
03606 
03607     if (event->type == PropertyNotify) {
03608 
03609 #ifdef    NETWMDEBUG
03610     fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
03611 #endif
03612 
03613     XEvent pe = *event;
03614 
03615     Bool done = False;
03616     Bool compaction = False;
03617     while (! done) {
03618 
03619 #ifdef    NETWMDEBUG
03620         fprintf(stderr, "NETWinInfo::event: loop fire\n");
03621 #endif
03622 
03623         if (pe.xproperty.atom == net_wm_name)
03624         dirty |= WMName;
03625         else if (pe.xproperty.atom == net_wm_visible_name)
03626         dirty |= WMVisibleName;
03627         else if (pe.xproperty.atom == net_wm_desktop)
03628         dirty |= WMDesktop;
03629         else if (pe.xproperty.atom == net_wm_window_type)
03630         dirty |=WMWindowType;
03631         else if (pe.xproperty.atom == net_wm_state)
03632         dirty |= WMState;
03633         else if (pe.xproperty.atom == net_wm_strut)
03634         dirty |= WMStrut;
03635         else if (pe.xproperty.atom == net_wm_extended_strut)
03636         dirty2 |= WM2ExtendedStrut;
03637         else if (pe.xproperty.atom == net_wm_icon_geometry)
03638         dirty |= WMIconGeometry;
03639         else if (pe.xproperty.atom == net_wm_icon)
03640         dirty |= WMIcon;
03641         else if (pe.xproperty.atom == net_wm_pid)
03642         dirty |= WMPid;
03643         else if (pe.xproperty.atom == net_wm_handled_icons)
03644         dirty |= WMHandledIcons;
03645         else if (pe.xproperty.atom == net_startup_id)
03646         dirty2 |= WM2StartupId;
03647         else if (pe.xproperty.atom == net_wm_allowed_actions)
03648         dirty2 |= WM2AllowedActions;
03649         else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
03650         dirty |= WMKDESystemTrayWinFor;
03651         else if (pe.xproperty.atom == xa_wm_state)
03652         dirty |= XAWMState;
03653         else if (pe.xproperty.atom == net_frame_extents)
03654         dirty |= WMFrameExtents;
03655         else if (pe.xproperty.atom == kde_net_wm_frame_strut)
03656         dirty |= WMKDEFrameStrut;
03657         else if (pe.xproperty.atom == net_wm_icon_name)
03658         dirty |= WMIconName;
03659         else if (pe.xproperty.atom == net_wm_visible_icon_name)
03660         dirty |= WMVisibleIconName;
03661         else if (pe.xproperty.atom == net_wm_user_time)
03662         dirty2 |= WM2UserTime;
03663             else if (pe.xproperty.atom == XA_WM_HINTS)
03664                 dirty2 |= WM2GroupLeader;
03665             else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR)
03666                 dirty2 |= WM2TransientFor;
03667             else if (pe.xproperty.atom == XA_WM_CLASS)
03668                 dirty2 |= WM2WindowClass;
03669             else if (pe.xproperty.atom == wm_window_role)
03670                 dirty2 |= WM2WindowRole;
03671             else if (pe.xproperty.atom == XA_WM_CLIENT_MACHINE)
03672                 dirty2 |= WM2ClientMachine;
03673         else {
03674 
03675 #ifdef    NETWMDEBUG
03676         fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
03677 #endif
03678 
03679         if ( compaction )
03680             XPutBackEvent(p->display, &pe);
03681         break;
03682         }
03683 
03684         if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
03685         compaction = True;
03686         else
03687         break;
03688     }
03689 
03690     do_update = true;
03691     } else if (event->type == ConfigureNotify) {
03692 
03693 #ifdef NETWMDEBUG
03694     fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
03695 #endif
03696 
03697     dirty |= WMGeometry;
03698 
03699     // update window geometry
03700     p->win_geom.pos.x = event->xconfigure.x;
03701     p->win_geom.pos.y = event->xconfigure.y;
03702     p->win_geom.size.width = event->xconfigure.width;
03703     p->win_geom.size.height = event->xconfigure.height;
03704     }
03705 
03706     if( do_update )
03707         update( props );
03708 
03709     if( properties_size > PROPERTIES_SIZE )
03710         properties_size = PROPERTIES_SIZE;
03711     for( int i = 0;
03712          i < properties_size;
03713          ++i )
03714         properties[ i ] = props[ i ];
03715 }
03716 
03717 void NETWinInfo::updateWMState() {
03718     unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 };
03719     assert( PROPERTIES_SIZE == 2 ); // add elements above
03720     update( props );
03721 }
03722 
03723 void NETWinInfo::update(const unsigned long dirty_props[]) {
03724     Atom type_ret;
03725     int format_ret;
03726     unsigned long nitems_ret, unused;
03727     unsigned char *data_ret;
03728     unsigned long props[ PROPERTIES_SIZE ];
03729     for( int i = 0;
03730          i < PROPERTIES_SIZE;
03731          ++i )
03732         props[ i ] = dirty_props[ i ] & p->properties[ i ];
03733     const unsigned long& dirty = props[ PROTOCOLS ];
03734     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
03735 
03736     // we *always* want to update WM_STATE if set in dirty_props
03737     if( dirty_props[ PROTOCOLS ] & XAWMState )
03738         props[ PROTOCOLS ] |= XAWMState;
03739 
03740     if (dirty & XAWMState) {
03741         p->mapping_state = Withdrawn;
03742     if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
03743                    False, xa_wm_state, &type_ret, &format_ret,
03744                    &nitems_ret, &unused, &data_ret)
03745         == Success) {
03746         if (type_ret == xa_wm_state && format_ret == 32 &&
03747         nitems_ret == 1) {
03748         long *state = (long *) data_ret;
03749 
03750         switch(*state) {
03751             case IconicState:
03752             p->mapping_state = Iconic;
03753             break;
03754             case NormalState:
03755             p->mapping_state = Visible;
03756                         break;
03757             case WithdrawnState:
03758             default:
03759             p->mapping_state = Withdrawn;
03760             break;
03761         }
03762 
03763         p->mapping_state_dirty = False;
03764         }
03765         if ( data_ret )
03766         XFree(data_ret);
03767     }
03768     }
03769 
03770     if (dirty & WMState) {
03771     p->state = 0;
03772     if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
03773                    False, XA_ATOM, &type_ret, &format_ret,
03774                    &nitems_ret, &unused, &data_ret)
03775         == Success) {
03776         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03777         // determine window state
03778 #ifdef NETWMDEBUG
03779         fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
03780             nitems_ret);
03781 #endif
03782 
03783         long *states = (long *) data_ret;
03784         unsigned long count;
03785 
03786         for (count = 0; count < nitems_ret; count++) {
03787 #ifdef NETWMDEBUG
03788                     char* data_ret = XGetAtomName(p->display, (Atom) states[count]);
03789             fprintf(stderr,
03790                 "NETWinInfo::update:   adding window state %ld '%s'\n",
03791                 states[count], data_ret );
03792                     if ( data_ret )
03793                         XFree( data_ret );
03794 #endif
03795 
03796             if ((Atom) states[count] == net_wm_state_modal)
03797             p->state |= Modal;
03798             else if ((Atom) states[count] == net_wm_state_sticky)
03799             p->state |= Sticky;
03800             else if ((Atom) states[count] == net_wm_state_max_vert)
03801             p->state |= MaxVert;
03802             else if ((Atom) states[count] == net_wm_state_max_horiz)
03803             p->state |= MaxHoriz;
03804             else if ((Atom) states[count] == net_wm_state_shaded)
03805             p->state |= Shaded;
03806             else if ((Atom) states[count] == net_wm_state_skip_taskbar)
03807             p->state |= SkipTaskbar;
03808             else if ((Atom) states[count] == net_wm_state_skip_pager)
03809             p->state |= SkipPager;
03810             else if ((Atom) states[count] == net_wm_state_hidden)
03811             p->state |= Hidden;
03812             else if ((Atom) states[count] == net_wm_state_fullscreen)
03813             p->state |= FullScreen;
03814             else if ((Atom) states[count] == net_wm_state_above)
03815             p->state |= KeepAbove;
03816             else if ((Atom) states[count] == net_wm_state_below)
03817             p->state |= KeepBelow;
03818             else if ((Atom) states[count] == net_wm_state_demands_attention)
03819             p->state |= DemandsAttention;
03820             else if ((Atom) states[count] == net_wm_state_stays_on_top)
03821             p->state |= StaysOnTop;
03822         }
03823         }
03824         if ( data_ret )
03825         XFree(data_ret);
03826     }
03827     }
03828 
03829     if (dirty & WMDesktop) {
03830     p->desktop = 0;
03831     if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
03832                    False, XA_CARDINAL, &type_ret,
03833                    &format_ret, &nitems_ret,
03834                    &unused, &data_ret)
03835         == Success) {
03836         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03837         nitems_ret == 1) {
03838         p->desktop = *((long *) data_ret);
03839         if ((signed) p->desktop != OnAllDesktops)
03840             p->desktop++;
03841 
03842         if ( p->desktop == 0 )
03843             p->desktop = OnAllDesktops;
03844         }
03845         if ( data_ret )
03846         XFree(data_ret);
03847     }
03848     }
03849 
03850     if (dirty & WMName) {
03851         delete[] p->name;
03852         p->name = NULL;
03853     if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
03854                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03855                    &format_ret, &nitems_ret, &unused, &data_ret)
03856         == Success) {
03857         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03858         p->name = nstrndup((const char *) data_ret, nitems_ret);
03859         }
03860 
03861         if( data_ret )
03862         XFree(data_ret);
03863     }
03864     }
03865 
03866     if (dirty & WMVisibleName) {
03867         delete[] p->visible_name;
03868         p->visible_name = NULL;
03869     if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
03870                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03871                    &format_ret, &nitems_ret, &unused, &data_ret)
03872         == Success) {
03873         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03874         p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
03875         }
03876 
03877         if( data_ret )
03878         XFree(data_ret);
03879     }
03880     }
03881 
03882     if (dirty & WMIconName) {
03883         delete[] p->icon_name;
03884         p->icon_name = NULL;
03885     if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
03886                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03887                    &format_ret, &nitems_ret, &unused, &data_ret)
03888         == Success) {
03889         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03890         p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
03891         }
03892 
03893         if( data_ret )
03894         XFree(data_ret);
03895     }
03896     }
03897 
03898     if (dirty & WMVisibleIconName)
03899     {
03900         delete[] p->visible_icon_name;
03901         p->visible_icon_name = NULL;
03902     if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
03903                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03904                    &format_ret, &nitems_ret, &unused, &data_ret)
03905         == Success) {
03906         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03907         p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
03908         }
03909 
03910         if( data_ret )
03911         XFree(data_ret);
03912     }
03913     }
03914 
03915     if (dirty & WMWindowType) {
03916     p->types.reset();
03917     p->types[ 0 ] = Unknown;
03918         p->has_net_support = false;
03919     if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
03920                    False, XA_ATOM, &type_ret, &format_ret,
03921                    &nitems_ret, &unused, &data_ret)
03922         == Success) {
03923         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03924         // determine the window type
03925 #ifdef NETWMDEBUG
03926         fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
03927             nitems_ret);
03928 #endif
03929 
03930                 p->has_net_support = true;
03931 
03932         unsigned long count = 0;
03933         long *types = (long *) data_ret;
03934         int pos = 0;
03935 
03936         while (count < nitems_ret) {
03937             // remember all window types we know
03938 #ifdef NETWMDEBUG
03939                     char* debug_type = XGetAtomName(p->display, (Atom) types[count]);
03940             fprintf(stderr,
03941                 "NETWinInfo::update:   examining window type %ld %s\n",
03942                 types[count], debug_type );
03943                     if ( debug_type )
03944                         XFree( debug_type );
03945 #endif
03946 
03947             if ((Atom) types[count] == net_wm_window_type_normal)
03948             p->types[ pos++ ] = Normal;
03949             else if ((Atom) types[count] == net_wm_window_type_desktop)
03950             p->types[ pos++ ] = Desktop;
03951             else if ((Atom) types[count] == net_wm_window_type_dock)
03952             p->types[ pos++ ] = Dock;
03953             else if ((Atom) types[count] == net_wm_window_type_toolbar)
03954             p->types[ pos++ ] = Tool;
03955             else if ((Atom) types[count] == net_wm_window_type_menu)
03956             p->types[ pos++ ] = Menu;
03957             else if ((Atom) types[count] == net_wm_window_type_dialog)
03958             p->types[ pos++ ] = Dialog;
03959             else if ((Atom) types[count] == net_wm_window_type_utility)
03960             p->types[ pos++ ] = Utility;
03961             else if ((Atom) types[count] == net_wm_window_type_splash)
03962             p->types[ pos++ ] = Splash;
03963             else if ((Atom) types[count] == kde_net_wm_window_type_override)
03964             p->types[ pos++ ] = Override;
03965             else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
03966             p->types[ pos++ ] = TopMenu;
03967 
03968             count++;
03969         }
03970         }
03971 
03972         if ( data_ret )
03973         XFree(data_ret);
03974     }
03975     }
03976 
03977     if (dirty & WMStrut) {
03978         p->strut = NETStrut();
03979     if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
03980                    False, XA_CARDINAL, &type_ret, &format_ret,
03981                    &nitems_ret, &unused, &data_ret)
03982         == Success) {
03983         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03984         nitems_ret == 4) {
03985         long *d = (long *) data_ret;
03986         p->strut.left   = d[0];
03987         p->strut.right  = d[1];
03988         p->strut.top    = d[2];
03989         p->strut.bottom = d[3];
03990         }
03991         if ( data_ret )
03992         XFree(data_ret);
03993     }
03994     }
03995 
03996     if (dirty2 & WM2ExtendedStrut) {
03997         p->extended_strut = NETExtendedStrut();
03998     if (XGetWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l,
03999                    False, XA_CARDINAL, &type_ret, &format_ret,
04000                    &nitems_ret, &unused, &data_ret)
04001         == Success) {
04002         if (type_ret == XA_CARDINAL && format_ret == 32 &&
04003         nitems_ret == 12) {
04004         long *d = (long *) data_ret;
04005         p->extended_strut.left_width = d[0];
04006         p->extended_strut.right_width = d[1];
04007         p->extended_strut.top_width = d[2];
04008         p->extended_strut.bottom_width = d[3];
04009                 p->extended_strut.left_start = d[4];
04010                 p->extended_strut.left_end = d[5];
04011                 p->extended_strut.right_start = d[6];
04012                 p->extended_strut.right_end = d[7];
04013                 p->extended_strut.top_start = d[8];
04014                 p->extended_strut.top_end = d[9];
04015                 p->extended_strut.bottom_start = d[10];
04016                 p->extended_strut.bottom_end = d[11];
04017         }
04018         if ( data_ret )
04019         XFree(data_ret);
04020     }
04021     }
04022 
04023     if (dirty & WMIconGeometry) {
04024         p->icon_geom = NETRect();
04025     if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
04026                    False, XA_CARDINAL, &type_ret, &format_ret,
04027                    &nitems_ret, &unused, &data_ret)
04028         == Success) {
04029         if (type_ret == XA_CARDINAL && format_ret == 32 &&
04030         nitems_ret == 4) {
04031         long *d = (long *) data_ret;
04032         p->icon_geom.pos.x       = d[0];
04033         p->icon_geom.pos.y       = d[1];
04034         p->icon_geom.size.width  = d[2];
04035         p->icon_geom.size.height = d[3];
04036         }
04037         if ( data_ret )
04038         XFree(data_ret);
04039     }
04040     }
04041 
04042     if (dirty & WMIcon) {
04043     readIcon(p->display,p->window,net_wm_icon,p->icons,p->icon_count);
04044     }
04045 
04046     if (dirty & WMKDESystemTrayWinFor) {
04047     p->kde_system_tray_win_for = 0;
04048     if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
04049                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
04050                    &nitems_ret, &unused, &data_ret)
04051         == Success) {
04052         if (type_ret == XA_WINDOW && format_ret == 32 &&
04053         nitems_ret == 1) {
04054         p->kde_system_tray_win_for = *((Window *) data_ret);
04055         if ( p->kde_system_tray_win_for == 0 )
04056             p->kde_system_tray_win_for = p->root;
04057         }
04058         if ( data_ret )
04059         XFree(data_ret);
04060         }
04061     }
04062 
04063     if (dirty & WMFrameExtents) {
04064         p->frame_strut = NETStrut();
04065         bool ok = false;
04066     if (XGetWindowProperty(p->display, p->window, net_frame_extents,
04067                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
04068                    &nitems_ret, &unused, &data_ret) == Success) {
04069         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
04070                 ok = true;
04071         long *d = (long *) data_ret;
04072 
04073         p->frame_strut.left   = d[0];
04074         p->frame_strut.right  = d[1];
04075         p->frame_strut.top    = d[2];
04076         p->frame_strut.bottom = d[3];
04077         }
04078         if ( data_ret )
04079         XFree(data_ret);
04080         }
04081     if (!ok && XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
04082                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
04083                    &nitems_ret, &unused, &data_ret) == Success) {
04084         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
04085                 ok = true;
04086         long *d = (long *) data_ret;
04087 
04088         p->frame_strut.left   = d[0];
04089         p->frame_strut.right  = d[1];
04090         p->frame_strut.top    = d[2];
04091         p->frame_strut.bottom = d[3];
04092         }
04093         if ( data_ret )
04094         XFree(data_ret);
04095     }
04096     }
04097 
04098     if (dirty & WMPid) {
04099     p->pid = 0;
04100     if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
04101                    False, XA_CARDINAL, &type_ret, &format_ret,
04102                    &nitems_ret, &unused, &data_ret) == Success) {
04103         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
04104         p->pid = *((long *) data_ret);
04105         }
04106         if ( data_ret )
04107         XFree(data_ret);
04108     }
04109     }
04110 
04111     if (dirty2 & WM2StartupId)
04112     {
04113         delete[] p->startup_id;
04114         p->startup_id = NULL;
04115     if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l,
04116                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
04117                    &format_ret, &nitems_ret, &unused, &data_ret)
04118         == Success) {
04119         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
04120         p->startup_id = nstrndup((const char *) data_ret, nitems_ret);
04121         }
04122 
04123         if( data_ret )
04124         XFree(data_ret);
04125     }
04126     }
04127 
04128     if( dirty2 & WM2AllowedActions ) {
04129         p->allowed_actions = 0;
04130     if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l,
04131                    False, XA_ATOM, &type_ret, &format_ret,
04132                    &nitems_ret, &unused, &data_ret)
04133         == Success) {
04134         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
04135         // determine actions
04136 #ifdef NETWMDEBUG
04137         fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n",
04138             nitems_ret);
04139 #endif
04140 
04141         long *actions = (long *) data_ret;
04142         unsigned long count;
04143 
04144         for (count = 0; count < nitems_ret; count++) {
04145 #ifdef NETWMDEBUG
04146             fprintf(stderr,
04147                 "NETWinInfo::update:   adding allowed action %ld '%s'\n",
04148                 actions[count],
04149                 XGetAtomName(p->display, (Atom) actions[count]));
04150 #endif
04151 
04152             if ((Atom) actions[count] == net_wm_action_move)
04153             p->allowed_actions |= ActionMove;
04154             if ((Atom) actions[count] == net_wm_action_resize)
04155             p->allowed_actions |= ActionResize;
04156             if ((Atom) actions[count] == net_wm_action_minimize)
04157             p->allowed_actions |= ActionMinimize;
04158             if ((Atom) actions[count] == net_wm_action_shade)
04159             p->allowed_actions |= ActionShade;
04160             if ((Atom) actions[count] == net_wm_action_stick)
04161             p->allowed_actions |= ActionStick;
04162             if ((Atom) actions[count] == net_wm_action_max_vert)
04163             p->allowed_actions |= ActionMaxVert;
04164             if ((Atom) actions[count] == net_wm_action_max_horiz)
04165             p->allowed_actions |= ActionMaxHoriz;
04166             if ((Atom) actions[count] == net_wm_action_fullscreen)
04167             p->allowed_actions |= ActionFullScreen;
04168             if ((Atom) actions[count] == net_wm_action_change_desk)
04169             p->allowed_actions |= ActionChangeDesktop;
04170             if ((Atom) actions[count] == net_wm_action_close)
04171             p->allowed_actions |= ActionClose;
04172         }
04173         }
04174         if ( data_ret )
04175         XFree(data_ret);
04176     }
04177     }
04178 
04179     if (dirty2 & WM2UserTime) {
04180     p->user_time = -1U;
04181     if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l,
04182                    False, XA_CARDINAL, &type_ret, &format_ret,
04183                    &nitems_ret, &unused, &data_ret) == Success) {
04184             // don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it
04185         if (type_ret == XA_CARDINAL && format_ret == 32 /*&& nitems_ret == 1*/) {
04186         p->user_time = *((long *) data_ret);
04187         }
04188         if ( data_ret )
04189         XFree(data_ret);
04190     }
04191     }
04192 
04193     if (dirty2 & WM2TransientFor) {
04194     p->transient_for = None;
04195         XGetTransientForHint(p->display, p->window, &p->transient_for);
04196     }
04197 
04198     if (dirty2 & WM2GroupLeader) {
04199         XWMHints *hints = XGetWMHints(p->display, p->window);
04200         p->window_group = None;
04201         if ( hints )
04202         {
04203             if( hints->flags & WindowGroupHint )
04204                 p->window_group = hints->window_group;
04205             XFree( reinterpret_cast< char* >( hints ));
04206         }
04207     }
04208     
04209     if( dirty2 & WM2WindowClass ) {
04210         delete[] p->class_class;
04211         delete[] p->class_name;
04212         p->class_class = NULL;
04213         p->class_name = NULL;
04214         XClassHint hint;
04215         if( XGetClassHint( p->display, p->window, &hint )) {
04216             p->class_class = strdup( hint.res_class );
04217             p->class_name = strdup( hint.res_name );
04218             XFree( hint.res_class );
04219             XFree( hint.res_name );
04220         }
04221     }
04222 
04223     if( dirty2 & WM2WindowRole ) {
04224         delete[] p->role;
04225         p->role = NULL;
04226     if (XGetWindowProperty(p->display, p->window, wm_window_role, 0l,
04227                    MAX_PROP_SIZE, False, XA_STRING, &type_ret,
04228                    &format_ret, &nitems_ret, &unused, &data_ret)
04229         == Success) {
04230         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
04231         p->role = nstrndup((const char *) data_ret, nitems_ret);
04232         }
04233         if( data_ret )
04234         XFree(data_ret);
04235     }
04236     }
04237 
04238     if( dirty2 & WM2ClientMachine ) {
04239         delete[] p->client_machine;
04240         p->client_machine = NULL;
04241     if (XGetWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l,
04242                    MAX_PROP_SIZE, False, XA_STRING, &type_ret,
04243                    &format_ret, &nitems_ret, &unused, &data_ret)
04244         == Success) {
04245         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
04246         p->client_machine = nstrndup((const char *) data_ret, nitems_ret);
04247         }
04248         if( data_ret )
04249         XFree(data_ret);
04250     }
04251     }
04252 }
04253 
04254 
04255 NETRect NETWinInfo::iconGeometry() const {
04256     return p->icon_geom;
04257 }
04258 
04259 
04260 unsigned long NETWinInfo::state() const {
04261     return p->state;
04262 }
04263 
04264 
04265 NETStrut NETWinInfo::strut() const {
04266     return p->strut;
04267 }
04268 
04269 NETExtendedStrut NETWinInfo::extendedStrut() const {
04270     return p->extended_strut;
04271 }
04272 
04273 bool NET::typeMatchesMask( WindowType type, unsigned long mask ) {
04274     switch( type ) {
04275 #define CHECK_TYPE_MASK( type ) \
04276         case type: \
04277             if( mask & type##Mask ) \
04278             return true; \
04279         break;
04280         CHECK_TYPE_MASK( Normal )
04281         CHECK_TYPE_MASK( Desktop )
04282         CHECK_TYPE_MASK( Dock )
04283         CHECK_TYPE_MASK( Toolbar )
04284         CHECK_TYPE_MASK( Menu )
04285         CHECK_TYPE_MASK( Dialog )
04286         CHECK_TYPE_MASK( Override )
04287         CHECK_TYPE_MASK( TopMenu )
04288         CHECK_TYPE_MASK( Utility )
04289         CHECK_TYPE_MASK( Splash )
04290 #undef CHECK_TYPE_MASK
04291         default:
04292             break;
04293     }
04294     return false;
04295 }
04296 
04297 NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const {
04298     for( int i = 0;
04299      i < p->types.size();
04300      ++i ) {
04301     // return the type only if the application supports it
04302         if( typeMatchesMask( p->types[ i ], supported_types ))
04303             return p->types[ i ];
04304     }
04305     return Unknown;
04306 }
04307 
04308 NET::WindowType NETWinInfo::windowType() const {
04309     return p->types[ 0 ];
04310 }
04311 
04312 
04313 const char *NETWinInfo::name() const {
04314     return p->name;
04315 }
04316 
04317 
04318 const char *NETWinInfo::visibleName() const {
04319     return p->visible_name;
04320 }
04321 
04322 
04323 const char *NETWinInfo::iconName() const {
04324     return p->icon_name;
04325 }
04326 
04327 
04328 const char *NETWinInfo::visibleIconName() const {
04329     return p->visible_icon_name;
04330 }
04331 
04332 
04333 int NETWinInfo::desktop() const {
04334     return p->desktop;
04335 }
04336 
04337 int NETWinInfo::pid() const {
04338     return p->pid;
04339 }
04340 
04341 Time NETWinInfo::userTime() const {
04342     return p->user_time;
04343 }
04344 
04345 const char* NETWinInfo::startupId() const {
04346     return p->startup_id;
04347 }
04348 
04349 unsigned long NETWinInfo::allowedActions() const {
04350     return p->allowed_actions;
04351 }
04352 
04353 bool NETWinInfo::hasNETSupport() const {
04354     return p->has_net_support;
04355 }
04356 
04357 Window NETWinInfo::transientFor() const {
04358     return p->transient_for;
04359 }
04360 
04361 Window NETWinInfo::groupLeader() const {
04362     return p->window_group;
04363 }
04364 
04365 const char* NETWinInfo::windowClassClass() const {
04366     return p->class_class;
04367 }
04368 
04369 const char* NETWinInfo::windowClassName() const {
04370     return p->class_name;
04371 }
04372 
04373 const char* NETWinInfo::windowRole() const {
04374     return p->role;
04375 }
04376 
04377 const char* NETWinInfo::clientMachine() const {
04378     return p->client_machine;
04379 }
04380 
04381 Bool NETWinInfo::handledIcons() const {
04382     return p->handled_icons;
04383 }
04384 
04385 
04386 Window NETWinInfo::kdeSystemTrayWinFor() const {
04387     return p->kde_system_tray_win_for;
04388 }
04389 
04390 const unsigned long* NETWinInfo::passedProperties() const {
04391     return p->properties;
04392 }
04393 
04394 unsigned long NETWinInfo::properties() const {
04395     return p->properties[ PROTOCOLS ];
04396 }
04397 
04398 
04399 NET::MappingState NETWinInfo::mappingState() const {
04400     return p->mapping_state;
04401 }
04402 
04403 void NETRootInfo::virtual_hook( int, void* )
04404 { /*BASE::virtual_hook( id, data );*/ }
04405 
04406 void NETWinInfo::virtual_hook( int, void* )
04407 { /*BASE::virtual_hook( id, data );*/ }
04408 
04409 // Functions for X timestamp comparing. For Time being 32bit they're fairly simple
04410 // (the #if 0 part), but on 64bit architectures Time is 64bit unsigned long,
04411 // so there special care needs to be taken to always use only the lower 32bits.
04412 #if 0
04413 int NET::timestampCompare( Time time1, Time time2 ) // like strcmp()
04414     {
04415     if( time1 == time2 )
04416         return 0;
04417     return ( time1 - time2 ) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
04418     }
04419 
04420 Time NET::timestampDiff( Time time1, Time time2 ) // returns time2 - time1
04421     { // no need to handle wrapping?
04422     return time2 - time1;
04423     }
04424 #else
04425 int NET::timestampCompare( unsigned long time1_, unsigned long time2_ ) // like strcmp()
04426     {
04427     Q_UINT32 time1 = time1_;
04428     Q_UINT32 time2 = time2_;
04429     if( time1 == time2 )
04430         return 0;
04431     return Q_UINT32( time1 - time2 ) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
04432     }
04433 
04434 int NET::timestampDiff( unsigned long time1_, unsigned long time2_ ) // returns time2 - time1
04435     { // no need to handle wrapping?
04436     Q_UINT32 time1 = time1_;
04437     Q_UINT32 time2 = time2_;
04438     return Q_UINT32( time2 - time1 );
04439     }
04440 #endif
04441 
04442 
04443 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys