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