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