kdecore Library API Documentation

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