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     if (role == Client && p->mapping_state != Withdrawn) {
02721 
02722 #ifdef NETWMDEBUG
02723         fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n",
02724                 state, mask);
02725 #endif // NETWMDEBUG
02726 
02727     XEvent e;
02728     e.xclient.type = ClientMessage;
02729     e.xclient.message_type = net_wm_state;
02730     e.xclient.display = p->display;
02731     e.xclient.window = p->window;
02732     e.xclient.format = 32;
02733     e.xclient.data.l[3] = 0l;
02734     e.xclient.data.l[4] = 0l;
02735 
02736     if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
02737         e.xclient.data.l[0] = (state & Modal) ? 1 : 0;
02738         e.xclient.data.l[1] = net_wm_state_modal;
02739         e.xclient.data.l[2] = 0l;
02740 
02741         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02742     }
02743 
02744     if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
02745         e.xclient.data.l[0] = (state & Sticky) ? 1 : 0;
02746         e.xclient.data.l[1] = net_wm_state_sticky;
02747         e.xclient.data.l[2] = 0l;
02748 
02749         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02750     }
02751 
02752     if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) {
02753 
02754         unsigned long wishstate = (p->state & ~mask) | (state & mask);
02755         if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) )
02756          && ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) {
02757         if ( (wishstate & Max) == Max ) {
02758             e.xclient.data.l[0] = 1;
02759             e.xclient.data.l[1] = net_wm_state_max_horiz;
02760             e.xclient.data.l[2] = net_wm_state_max_vert;
02761             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02762         } else if ( (wishstate & Max) == 0 ) {
02763             e.xclient.data.l[0] = 0;
02764             e.xclient.data.l[1] = net_wm_state_max_horiz;
02765             e.xclient.data.l[2] = net_wm_state_max_vert;
02766             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02767         } else {
02768             e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
02769             e.xclient.data.l[1] = net_wm_state_max_horiz;
02770             e.xclient.data.l[2] = 0;
02771             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02772             e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
02773             e.xclient.data.l[1] = net_wm_state_max_vert;
02774             e.xclient.data.l[2] = 0;
02775             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02776         }
02777         } else  if ( (wishstate & MaxVert) != (p->state & MaxVert) ) {
02778         e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
02779         e.xclient.data.l[1] = net_wm_state_max_vert;
02780         e.xclient.data.l[2] = 0;
02781         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02782         } else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) {
02783         e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
02784         e.xclient.data.l[1] = net_wm_state_max_horiz;
02785         e.xclient.data.l[2] = 0;
02786         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02787         }
02788     }
02789 
02790     if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
02791         e.xclient.data.l[0] = (state & Shaded) ? 1 : 0;
02792         e.xclient.data.l[1] = net_wm_state_shaded;
02793         e.xclient.data.l[2] = 0l;
02794 
02795         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02796     }
02797 
02798     if ((mask & SkipTaskbar) &&
02799         ((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
02800         e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0;
02801         e.xclient.data.l[1] = net_wm_state_skip_taskbar;
02802         e.xclient.data.l[2] = 0l;
02803 
02804         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02805     }
02806 
02807         if ((mask & SkipPager) &&
02808         ((p->state & SkipPager) != (state & SkipPager))) {
02809             e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0;
02810             e.xclient.data.l[1] = net_wm_state_skip_pager;
02811             e.xclient.data.l[2] = 0l;
02812 
02813             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02814         }
02815 
02816         if ((mask & Hidden) &&
02817         ((p->state & Hidden) != (state & Hidden))) {
02818             e.xclient.data.l[0] = (state & Hidden) ? 1 : 0;
02819             e.xclient.data.l[1] = net_wm_state_hidden;
02820             e.xclient.data.l[2] = 0l;
02821 
02822             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02823         }
02824 
02825         if ((mask & FullScreen) &&
02826         ((p->state & FullScreen) != (state & FullScreen))) {
02827             e.xclient.data.l[0] = (state & FullScreen) ? 1 : 0;
02828             e.xclient.data.l[1] = net_wm_state_fullscreen;
02829             e.xclient.data.l[2] = 0l;
02830 
02831             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02832         }
02833 
02834         if ((mask & KeepAbove) &&
02835         ((p->state & KeepAbove) != (state & KeepAbove))) {
02836             e.xclient.data.l[0] = (state & KeepAbove) ? 1 : 0;
02837             e.xclient.data.l[1] = net_wm_state_above;
02838             e.xclient.data.l[2] = 0l;
02839 
02840             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02841         }
02842 
02843         if ((mask & KeepBelow) &&
02844         ((p->state & KeepBelow) != (state & KeepBelow))) {
02845             e.xclient.data.l[0] = (state & KeepBelow) ? 1 : 0;
02846             e.xclient.data.l[1] = net_wm_state_below;
02847             e.xclient.data.l[2] = 0l;
02848 
02849             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02850         }
02851 
02852     if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) {
02853         e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0;
02854         e.xclient.data.l[1] = net_wm_state_stays_on_top;
02855         e.xclient.data.l[2] = 0l;
02856 
02857         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02858     }
02859 
02860         if ((mask & DemandsAttention) &&
02861         ((p->state & DemandsAttention) != (state & DemandsAttention))) {
02862             e.xclient.data.l[0] = (state & DemandsAttention) ? 1 : 0;
02863             e.xclient.data.l[1] = net_wm_state_demands_attention;
02864             e.xclient.data.l[2] = 0l;
02865 
02866             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02867         }
02868 
02869     } else {
02870     p->state &= ~mask;
02871     p->state |= state;
02872 
02873     long data[50];
02874     int count = 0;
02875 
02876     // hints
02877     if (p->state & Modal) data[count++] = net_wm_state_modal;
02878     if (p->state & MaxVert) data[count++] = net_wm_state_max_vert;
02879     if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz;
02880     if (p->state & Shaded) data[count++] = net_wm_state_shaded;
02881     if (p->state & Hidden) data[count++] = net_wm_state_hidden;
02882     if (p->state & FullScreen) data[count++] = net_wm_state_fullscreen;
02883     if (p->state & DemandsAttention) data[count++] = net_wm_state_demands_attention;
02884 
02885     // policy
02886     if (p->state & KeepAbove) data[count++] = net_wm_state_above;
02887     if (p->state & KeepBelow) data[count++] = net_wm_state_below;
02888     if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top;
02889     if (p->state & Sticky) data[count++] = net_wm_state_sticky;
02890     if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar;
02891     if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager;
02892 
02893 #ifdef NETWMDEBUG
02894     fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
02895     for (int i = 0; i < count; i++) {
02896             char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
02897         fprintf(stderr, "NETWinInfo::setState:   state %ld '%s'\n",
02898             data[i], data_ret);
02899             if ( data_ret )
02900                 XFree( data_ret );
02901         }
02902 
02903 #endif
02904 
02905     XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32,
02906             PropModeReplace, (unsigned char *) data, count);
02907     }
02908 }
02909 
02910 
02911 void NETWinInfo::setWindowType(WindowType type) {
02912     if (role != Client) return;
02913 
02914     int len;
02915     long data[2];
02916 
02917     switch (type) {
02918     case Override:
02919     // spec extension: override window type.  we must comply with the spec
02920     // and provide a fall back (normal seems best)
02921     data[0] = kde_net_wm_window_type_override;
02922     data[1] = net_wm_window_type_normal;
02923     len = 2;
02924     break;
02925 
02926     case  Dialog:
02927     data[0] = net_wm_window_type_dialog;
02928     data[1] = None;
02929     len = 1;
02930     break;
02931 
02932     case Menu:
02933     data[0] = net_wm_window_type_menu;
02934     data[1] = None;
02935     len = 1;
02936     break;
02937 
02938     case TopMenu:
02939     // spec extension: override window type.  we must comply with the spec
02940     // and provide a fall back (dock seems best)
02941     data[0] = kde_net_wm_window_type_topmenu;
02942     data[1] = net_wm_window_type_dock;
02943     len = 2;
02944     break;
02945 
02946     case Tool:
02947     data[0] = net_wm_window_type_toolbar;
02948     data[1] = None;
02949     len = 1;
02950     break;
02951 
02952     case Dock:
02953     data[0] = net_wm_window_type_dock;
02954     data[1] = None;
02955     len = 1;
02956     break;
02957 
02958     case Desktop:
02959     data[0] = net_wm_window_type_desktop;
02960     data[1] = None;
02961     len = 1;
02962     break;
02963 
02964     case Utility:
02965     data[0] = net_wm_window_type_utility;
02966     data[1] = net_wm_window_type_dialog; // fallback for old netwm version
02967     len = 2;
02968     break;
02969 
02970     case Splash:
02971     data[0] = net_wm_window_type_splash;
02972     data[1] = net_wm_window_type_dock; // fallback (dock seems best)
02973     len = 2;
02974     break;
02975 
02976     default:
02977     case Normal:
02978     data[0] = net_wm_window_type_normal;
02979     data[1] = None;
02980     len = 1;
02981     break;
02982     }
02983 
02984     XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32,
02985             PropModeReplace, (unsigned char *) &data, len);
02986 }
02987 
02988 
02989 void NETWinInfo::setName(const char *name) {
02990     if (role != Client) return;
02991 
02992     delete [] p->name;
02993     p->name = nstrdup(name);
02994     if( p->name[ 0 ] != '\0' )
02995         XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8,
02996             PropModeReplace, (unsigned char *) p->name,
02997             strlen(p->name));
02998     else
02999         XDeleteProperty(p->display, p->window, net_wm_name);
03000 }
03001 
03002 
03003 void NETWinInfo::setVisibleName(const char *visibleName) {
03004     if (role != WindowManager) return;
03005 
03006     delete [] p->visible_name;
03007     p->visible_name = nstrdup(visibleName);
03008     if( p->visible_name[ 0 ] != '\0' )
03009         XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8,
03010             PropModeReplace, (unsigned char *) p->visible_name,
03011             strlen(p->visible_name));
03012     else
03013         XDeleteProperty(p->display, p->window, net_wm_visible_name);
03014 }
03015 
03016 
03017 void NETWinInfo::setIconName(const char *iconName) {
03018     if (role != Client) return;
03019 
03020     delete [] p->icon_name;
03021     p->icon_name = nstrdup(iconName);
03022     if( p->icon_name[ 0 ] != '\0' )
03023         XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8,
03024             PropModeReplace, (unsigned char *) p->icon_name,
03025             strlen(p->icon_name));
03026     else
03027         XDeleteProperty(p->display, p->window, net_wm_icon_name);
03028 }
03029 
03030 
03031 void NETWinInfo::setVisibleIconName(const char *visibleIconName) {
03032     if (role != WindowManager) return;
03033 
03034     delete [] p->visible_icon_name;
03035     p->visible_icon_name = nstrdup(visibleIconName);
03036     if( p->visible_icon_name[ 0 ] != '\0' )
03037         XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8,
03038             PropModeReplace, (unsigned char *) p->visible_icon_name,
03039             strlen(p->visible_icon_name));
03040     else
03041         XDeleteProperty(p->display, p->window, net_wm_visible_icon_name);
03042 }
03043 
03044 
03045 void NETWinInfo::setDesktop(int desktop) {
03046     if (p->mapping_state_dirty)
03047     updateWMState();
03048 
03049     if (role == Client && p->mapping_state != Withdrawn) {
03050     // we only send a ClientMessage if we are 1) a client and 2) managed
03051 
03052     if ( desktop == 0 )
03053         return; // we can't do that while being managed
03054 
03055     XEvent e;
03056 
03057     e.xclient.type = ClientMessage;
03058     e.xclient.message_type = net_wm_desktop;
03059     e.xclient.display = p->display;
03060     e.xclient.window = p->window;
03061     e.xclient.format = 32;
03062     e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1;
03063     e.xclient.data.l[1] = 0l;
03064     e.xclient.data.l[2] = 0l;
03065     e.xclient.data.l[3] = 0l;
03066     e.xclient.data.l[4] = 0l;
03067 
03068     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
03069     } else {
03070     // otherwise we just set or remove the property directly
03071     p->desktop = desktop;
03072     long d = desktop;
03073 
03074     if ( d != OnAllDesktops ) {
03075         if ( d == 0 ) {
03076         XDeleteProperty( p->display, p->window, net_wm_desktop );
03077         return;
03078         }
03079 
03080         d -= 1;
03081     }
03082 
03083     XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32,
03084             PropModeReplace, (unsigned char *) &d, 1);
03085     }
03086 }
03087 
03088 
03089 void NETWinInfo::setPid(int pid) {
03090     if (role != Client) return;
03091 
03092     p->pid = pid;
03093     long d = pid;
03094     XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32,
03095             PropModeReplace, (unsigned char *) &d, 1);
03096 }
03097 
03098 
03099 void NETWinInfo::setHandledIcons(Bool handled) {
03100     if (role != Client) return;
03101 
03102     p->handled_icons = handled;
03103     long d = handled;
03104     XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32,
03105             PropModeReplace, (unsigned char *) &d, 1);
03106 }
03107 
03108 void NETWinInfo::setStartupId(const char* id) {
03109     if (role != Client) return;
03110 
03111     delete[] p->startup_id;
03112     p->startup_id = nstrdup(id);
03113     XChangeProperty(p->display, p->window, net_startup_id, UTF8_STRING, 8,
03114         PropModeReplace, reinterpret_cast< unsigned char* >( p->startup_id ),
03115         strlen( p->startup_id ));
03116 }
03117 
03118 void NETWinInfo::setAllowedActions( unsigned long actions ) {
03119     if( role != WindowManager )
03120         return;
03121     long data[50];
03122     int count = 0;
03123 
03124     p->allowed_actions = actions;
03125     if (p->allowed_actions & ActionMove) data[count++] = net_wm_action_move;
03126     if (p->allowed_actions & ActionResize) data[count++] = net_wm_action_resize;
03127     if (p->allowed_actions & ActionMinimize) data[count++] = net_wm_action_minimize;
03128     if (p->allowed_actions & ActionShade) data[count++] = net_wm_action_shade;
03129     if (p->allowed_actions & ActionStick) data[count++] = net_wm_action_stick;
03130     if (p->allowed_actions & ActionMaxVert) data[count++] = net_wm_action_max_vert;
03131     if (p->allowed_actions & ActionMaxHoriz) data[count++] = net_wm_action_max_horiz;
03132     if (p->allowed_actions & ActionFullScreen) data[count++] = net_wm_action_fullscreen;
03133     if (p->allowed_actions & ActionChangeDesktop) data[count++] = net_wm_action_change_desk;
03134     if (p->allowed_actions & ActionClose) data[count++] = net_wm_action_close;
03135 
03136 #ifdef NETWMDEBUG
03137     fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count);
03138     for (int i = 0; i < count; i++) {
03139         char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
03140         fprintf(stderr, "NETWinInfo::setAllowedActions:   action %ld '%s'\n",
03141         data[i], data_ret);
03142         if ( data_ret )
03143             XFree(data_ret);
03144     }
03145 #endif
03146 
03147     XChangeProperty(p->display, p->window, net_wm_allowed_actions, XA_ATOM, 32,
03148             PropModeReplace, (unsigned char *) data, count);
03149 }
03150 
03151 void NETWinInfo::setKDESystemTrayWinFor(Window window) {
03152     if (role != Client) return;
03153 
03154     p->kde_system_tray_win_for = window;
03155     XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
03156             XA_WINDOW, 32, PropModeReplace,
03157             (unsigned char *) &(p->kde_system_tray_win_for), 1);
03158 }
03159 
03160 
03161 void NETWinInfo::setKDEFrameStrut(NETStrut strut) {
03162     if (role != WindowManager) return;
03163 
03164     p->frame_strut = strut;
03165 
03166     long d[4];
03167     d[0] = strut.left;
03168     d[1] = strut.right;
03169     d[2] = strut.top;
03170     d[3] = strut.bottom;
03171 
03172     XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32,
03173             PropModeReplace, (unsigned char *) d, 4);
03174 }
03175 
03176 
03177 void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) {
03178     if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
03179     Window unused;
03180     int x, y;
03181     unsigned int w, h, junk;
03182     XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk);
03183     XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused
03184                   );
03185 
03186     p->win_geom.pos.x = x;
03187     p->win_geom.pos.y = y;
03188 
03189     p->win_geom.size.width = w;
03190     p->win_geom.size.height = h;
03191     }
03192 // TODO try to work also without _KDE_NET_WM_FRAME_STRUT
03193     window = p->win_geom;
03194 
03195     frame.pos.x = window.pos.x - p->frame_strut.left;
03196     frame.pos.y = window.pos.y - p->frame_strut.top;
03197     frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
03198     frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
03199 }
03200 
03201 
03202 NETIcon NETWinInfo::icon(int width, int height) const {
03203     NETIcon result;
03204 
03205     if ( !p->icon_count ) {
03206     result.size.width = 0;
03207     result.size.height = 0;
03208     result.data = 0;
03209     return result;
03210     }
03211 
03212     result = p->icons[0];
03213 
03214     // find the icon that's closest in size to w x h...
03215     // return the first icon if w and h are -1
03216     if (width == height && height == -1) return result;
03217 
03218     int i;
03219     for (i = 0; i < p->icons.size(); i++) {
03220     if ((p->icons[i].size.width >= width &&
03221          p->icons[i].size.width < result.size.width) &&
03222         (p->icons[i].size.height >= height &&
03223          p->icons[i].size.height < result.size.height))
03224         result = p->icons[i];
03225     }
03226 
03227     return result;
03228 }
03229 
03230 void NETWinInfo::setUserTime( Time time ) {
03231     if (role != Client) return;
03232 
03233     p->user_time = time;
03234     long d = time;
03235     XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32,
03236             PropModeReplace, (unsigned char *) &d, 1);
03237 }
03238 
03239 
03240 unsigned long NETWinInfo::event(XEvent *ev )
03241 {
03242     unsigned long props[ 1 ];
03243     event( ev, props, 1 );
03244     return props[ 0 ];
03245 }
03246 
03247 void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) {
03248     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 };
03249     assert( PROPERTIES_SIZE == 2 ); // add elements above
03250     unsigned long& dirty = props[ PROTOCOLS ];
03251     unsigned long& dirty2 = props[ PROTOCOLS2 ];
03252     bool do_update = false;
03253 
03254     if (role == WindowManager && event->type == ClientMessage &&
03255     event->xclient.format == 32) {
03256 
03257 #ifdef NETWMDEBUG
03258         fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
03259 #endif // NETWMDEBUG
03260 
03261     if (event->xclient.message_type == net_wm_state) {
03262         dirty = WMState;
03263 
03264         // we need to generate a change mask
03265 
03266 #ifdef NETWMDEBUG
03267         fprintf(stderr,
03268             "NETWinInfo::event: state client message, getting new state/mask\n");
03269 #endif
03270 
03271         int i;
03272         long state = 0, mask = 0;
03273 
03274         for (i = 1; i < 3; i++) {
03275 #ifdef NETWMDEBUG
03276                 char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]);
03277         fprintf(stderr, "NETWinInfo::event:  message %ld '%s'\n",
03278             event->xclient.data.l[i], debug_txt );
03279                 if ( debug_txt )
03280                     XFree( debug_txt );
03281 #endif
03282 
03283         if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
03284             mask |= Modal;
03285         else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
03286             mask |= Sticky;
03287         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
03288             mask |= MaxVert;
03289         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
03290             mask |= MaxHoriz;
03291         else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
03292             mask |= Shaded;
03293         else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
03294             mask |= SkipTaskbar;
03295                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
03296             mask |= SkipPager;
03297                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden)
03298             mask |= Hidden;
03299                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen)
03300             mask |= FullScreen;
03301                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_above)
03302             mask |= KeepAbove;
03303                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_below)
03304             mask |= KeepBelow;
03305                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention)
03306             mask |= DemandsAttention;
03307         else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
03308             mask |= StaysOnTop;
03309         }
03310 
03311         // when removing, we just leave newstate == 0
03312         switch (event->xclient.data.l[0]) {
03313         case 1: // set
03314         // to set... the change state should be the same as the mask
03315         state = mask;
03316         break;
03317 
03318         case 2: // toggle
03319         // to toggle, we need to xor the current state with the new state
03320         state = (p->state & mask) ^ mask;
03321         break;
03322 
03323         default:
03324         // to clear state, the new state should stay zero
03325         ;
03326         }
03327 
03328 #ifdef NETWMDEBUG
03329         fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
03330             state, mask);
03331 #endif
03332 
03333         changeState(state, mask);
03334     } else if (event->xclient.message_type == net_wm_desktop) {
03335         dirty = WMDesktop;
03336 
03337         if( event->xclient.data.l[0] == OnAllDesktops )
03338         changeDesktop( OnAllDesktops );
03339         else
03340             changeDesktop(event->xclient.data.l[0] + 1);
03341     }
03342     }
03343 
03344     if (event->type == PropertyNotify) {
03345 
03346 #ifdef    NETWMDEBUG
03347     fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
03348 #endif
03349 
03350     XEvent pe = *event;
03351 
03352     Bool done = False;
03353     Bool compaction = False;
03354     while (! done) {
03355 
03356 #ifdef    NETWMDEBUG
03357         fprintf(stderr, "NETWinInfo::event: loop fire\n");
03358 #endif
03359 
03360         if (pe.xproperty.atom == net_wm_name)
03361         dirty |= WMName;
03362         else if (pe.xproperty.atom == net_wm_visible_name)
03363         dirty |= WMVisibleName;
03364         else if (pe.xproperty.atom == net_wm_desktop)
03365         dirty |= WMDesktop;
03366         else if (pe.xproperty.atom == net_wm_window_type)
03367         dirty |=WMWindowType;
03368         else if (pe.xproperty.atom == net_wm_state)
03369         dirty |= WMState;
03370         else if (pe.xproperty.atom == net_wm_strut)
03371         dirty |= WMStrut;
03372         else if (pe.xproperty.atom == net_wm_icon_geometry)
03373         dirty |= WMIconGeometry;
03374         else if (pe.xproperty.atom == net_wm_icon)
03375         dirty |= WMIcon;
03376         else if (pe.xproperty.atom == net_wm_pid)
03377         dirty |= WMPid;
03378         else if (pe.xproperty.atom == net_wm_handled_icons)
03379         dirty |= WMHandledIcons;
03380         else if (pe.xproperty.atom == net_startup_id)
03381         dirty2 |= WM2StartupId;
03382         else if (pe.xproperty.atom == net_wm_allowed_actions)
03383         dirty2 |= WM2AllowedActions;
03384         else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
03385         dirty |= WMKDESystemTrayWinFor;
03386         else if (pe.xproperty.atom == xa_wm_state)
03387         dirty |= XAWMState;
03388         else if (pe.xproperty.atom == kde_net_wm_frame_strut)
03389         dirty |= WMKDEFrameStrut;
03390         else if (pe.xproperty.atom == net_wm_icon_name)
03391         dirty |= WMIconName;
03392         else if (pe.xproperty.atom == net_wm_visible_icon_name)
03393         dirty |= WMVisibleIconName;
03394         else if (pe.xproperty.atom == net_wm_user_time)
03395         dirty2 |= WM2UserTime;
03396             else if (pe.xproperty.atom == XA_WM_HINTS)
03397                 dirty2 |= WM2GroupLeader;
03398             else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR)
03399                 dirty2 |= WM2TransientFor;
03400         else {
03401 
03402 #ifdef    NETWMDEBUG
03403         fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
03404 #endif
03405 
03406         if ( compaction )
03407             XPutBackEvent(p->display, &pe);
03408         break;
03409         }
03410 
03411         if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
03412         compaction = True;
03413         else
03414         break;
03415     }
03416 
03417     do_update = true;
03418     } else if (event->type == ConfigureNotify) {
03419 
03420 #ifdef NETWMDEBUG
03421     fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
03422 #endif
03423 
03424     dirty |= WMGeometry;
03425 
03426     // update window geometry
03427     p->win_geom.pos.x = event->xconfigure.x;
03428     p->win_geom.pos.y = event->xconfigure.y;
03429     p->win_geom.size.width = event->xconfigure.width;
03430     p->win_geom.size.height = event->xconfigure.height;
03431     }
03432 
03433     if( do_update )
03434         update( props );
03435 
03436     if( properties_size > PROPERTIES_SIZE )
03437         properties_size = PROPERTIES_SIZE;
03438     for( int i = 0;
03439          i < properties_size;
03440          ++i )
03441         properties[ i ] = props[ i ];
03442 }
03443 
03444 void NETWinInfo::updateWMState() {
03445     unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 };
03446     assert( PROPERTIES_SIZE == 2 ); // add elements above
03447     update( props );
03448 }
03449 
03450 void NETWinInfo::update(const unsigned long dirty_props[]) {
03451     Atom type_ret;
03452     int format_ret;
03453     unsigned long nitems_ret, unused;
03454     unsigned char *data_ret;
03455     unsigned long props[ PROPERTIES_SIZE ];
03456     for( int i = 0;
03457          i < PROPERTIES_SIZE;
03458          ++i )
03459         props[ i ] = dirty_props[ i ] & p->properties[ i ];
03460     const unsigned long& dirty = props[ PROTOCOLS ];
03461     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
03462 
03463     // we *always* want to update WM_STATE if set in dirty_props
03464     if( dirty_props[ PROTOCOLS ] & XAWMState )
03465         props[ PROTOCOLS ] |= XAWMState;
03466 
03467     if (dirty & XAWMState) {
03468         p->mapping_state = Withdrawn;
03469     if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
03470                    False, xa_wm_state, &type_ret, &format_ret,
03471                    &nitems_ret, &unused, &data_ret)
03472         == Success) {
03473         if (type_ret == xa_wm_state && format_ret == 32 &&
03474         nitems_ret == 1) {
03475         long *state = (long *) data_ret;
03476 
03477         switch(*state) {
03478             case IconicState:
03479             p->mapping_state = Iconic;
03480             break;
03481             case NormalState:
03482             p->mapping_state = Visible;
03483                         break;
03484             case WithdrawnState:
03485             default:
03486             p->mapping_state = Withdrawn;
03487             break;
03488         }
03489 
03490         p->mapping_state_dirty = False;
03491         }
03492         if ( data_ret )
03493         XFree(data_ret);
03494     }
03495     }
03496 
03497     if (dirty & WMState) {
03498     p->state = 0;
03499     if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
03500                    False, XA_ATOM, &type_ret, &format_ret,
03501                    &nitems_ret, &unused, &data_ret)
03502         == Success) {
03503         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03504         // determine window state
03505 #ifdef NETWMDEBUG
03506         fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
03507             nitems_ret);
03508 #endif
03509 
03510         long *states = (long *) data_ret;
03511         unsigned long count;
03512 
03513         for (count = 0; count < nitems_ret; count++) {
03514 #ifdef NETWMDEBUG
03515                     char* data_ret = XGetAtomName(p->display, (Atom) states[count]);
03516             fprintf(stderr,
03517                 "NETWinInfo::update:   adding window state %ld '%s'\n",
03518                 states[count], data_ret );
03519                     if ( data_ret )
03520                         XFree( data_ret );
03521 #endif
03522 
03523             if ((Atom) states[count] == net_wm_state_modal)
03524             p->state |= Modal;
03525             else if ((Atom) states[count] == net_wm_state_sticky)
03526             p->state |= Sticky;
03527             else if ((Atom) states[count] == net_wm_state_max_vert)
03528             p->state |= MaxVert;
03529             else if ((Atom) states[count] == net_wm_state_max_horiz)
03530             p->state |= MaxHoriz;
03531             else if ((Atom) states[count] == net_wm_state_shaded)
03532             p->state |= Shaded;
03533             else if ((Atom) states[count] == net_wm_state_skip_taskbar)
03534             p->state |= SkipTaskbar;
03535             else if ((Atom) states[count] == net_wm_state_skip_pager)
03536             p->state |= SkipPager;
03537             else if ((Atom) states[count] == net_wm_state_hidden)
03538             p->state |= Hidden;
03539             else if ((Atom) states[count] == net_wm_state_fullscreen)
03540             p->state |= FullScreen;
03541             else if ((Atom) states[count] == net_wm_state_above)
03542             p->state |= KeepAbove;
03543             else if ((Atom) states[count] == net_wm_state_below)
03544             p->state |= KeepBelow;
03545             else if ((Atom) states[count] == net_wm_state_demands_attention)
03546             p->state |= DemandsAttention;
03547             else if ((Atom) states[count] == net_wm_state_stays_on_top)
03548             p->state |= StaysOnTop;
03549         }
03550         }
03551         if ( data_ret )
03552         XFree(data_ret);
03553     }
03554     }
03555 
03556     if (dirty & WMDesktop) {
03557     p->desktop = 0;
03558     if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
03559                    False, XA_CARDINAL, &type_ret,
03560                    &format_ret, &nitems_ret,
03561                    &unused, &data_ret)
03562         == Success) {
03563         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03564         nitems_ret == 1) {
03565         p->desktop = *((long *) data_ret);
03566         if ((signed) p->desktop != OnAllDesktops)
03567             p->desktop++;
03568 
03569         if ( p->desktop == 0 )
03570             p->desktop = OnAllDesktops;
03571         }
03572         if ( data_ret )
03573         XFree(data_ret);
03574     }
03575     }
03576 
03577     if (dirty & WMName) {
03578         delete[] p->name;
03579         p->name = NULL;
03580     if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
03581                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03582                    &format_ret, &nitems_ret, &unused, &data_ret)
03583         == Success) {
03584         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03585         p->name = nstrndup((const char *) data_ret, nitems_ret);
03586         }
03587 
03588         if( data_ret )
03589         XFree(data_ret);
03590     }
03591     }
03592 
03593     if (dirty & WMVisibleName) {
03594         delete[] p->visible_name;
03595         p->visible_name = NULL;
03596     if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
03597                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03598                    &format_ret, &nitems_ret, &unused, &data_ret)
03599         == Success) {
03600         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03601         p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
03602         }
03603 
03604         if( data_ret )
03605         XFree(data_ret);
03606     }
03607     }
03608 
03609     if (dirty & WMIconName) {
03610         delete[] p->icon_name;
03611         p->icon_name = NULL;
03612     if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
03613                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03614                    &format_ret, &nitems_ret, &unused, &data_ret)
03615         == Success) {
03616         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03617         p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
03618         }
03619 
03620         if( data_ret )
03621         XFree(data_ret);
03622     }
03623     }
03624 
03625     if (dirty & WMVisibleIconName)
03626     {
03627         delete[] p->visible_icon_name;
03628         p->visible_icon_name = NULL;
03629     if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
03630                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03631                    &format_ret, &nitems_ret, &unused, &data_ret)
03632         == Success) {
03633         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03634         p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
03635         }
03636 
03637         if( data_ret )
03638         XFree(data_ret);
03639     }
03640     }
03641 
03642     if (dirty & WMWindowType) {
03643     p->types.reset();
03644     p->types[ 0 ] = Unknown;
03645         p->has_net_support = false;
03646     if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
03647                    False, XA_ATOM, &type_ret, &format_ret,
03648                    &nitems_ret, &unused, &data_ret)
03649         == Success) {
03650         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03651         // determine the window type
03652 #ifdef NETWMDEBUG
03653         fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
03654             nitems_ret);
03655 #endif
03656 
03657                 p->has_net_support = true;
03658 
03659         unsigned long count = 0;
03660         long *types = (long *) data_ret;
03661         int pos = 0;
03662 
03663         while (count < nitems_ret) {
03664             // remember all window types we know
03665 #ifdef NETWMDEBUG
03666                     char* debug_type = XGetAtomName(p->display, (Atom) types[count]);
03667             fprintf(stderr,
03668                 "NETWinInfo::update:   examining window type %ld %s\n",
03669                 types[count], debug_type );
03670                     if ( debug_type )
03671                         XFree( debug_type );
03672 #endif
03673 
03674             if ((Atom) types[count] == net_wm_window_type_normal)
03675             p->types[ pos++ ] = Normal;
03676             else if ((Atom) types[count] == net_wm_window_type_desktop)
03677             p->types[ pos++ ] = Desktop;
03678             else if ((Atom) types[count] == net_wm_window_type_dock)
03679             p->types[ pos++ ] = Dock;
03680             else if ((Atom) types[count] == net_wm_window_type_toolbar)
03681             p->types[ pos++ ] = Tool;
03682             else if ((Atom) types[count] == net_wm_window_type_menu)
03683             p->types[ pos++ ] = Menu;
03684             else if ((Atom) types[count] == net_wm_window_type_dialog)
03685             p->types[ pos++ ] = Dialog;
03686             else if ((Atom) types[count] == net_wm_window_type_utility)
03687             p->types[ pos++ ] = Utility;
03688             else if ((Atom) types[count] == net_wm_window_type_splash)
03689             p->types[ pos++ ] = Splash;
03690             else if ((Atom) types[count] == kde_net_wm_window_type_override)
03691             p->types[ pos++ ] = Override;
03692             else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
03693             p->types[ pos++ ] = TopMenu;
03694 
03695             count++;
03696         }
03697         }
03698 
03699         if ( data_ret )
03700         XFree(data_ret);
03701     }
03702     }
03703 
03704     if (dirty & WMStrut) {
03705         p->strut = NETStrut();
03706     if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
03707                    False, XA_CARDINAL, &type_ret, &format_ret,
03708                    &nitems_ret, &unused, &data_ret)
03709         == Success) {
03710         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03711         nitems_ret == 4) {
03712         long *d = (long *) data_ret;
03713         p->strut.left   = d[0];
03714         p->strut.right  = d[1];
03715         p->strut.top    = d[2];
03716         p->strut.bottom = d[3];
03717         }
03718         if ( data_ret )
03719         XFree(data_ret);
03720     }
03721     }
03722 
03723     if (dirty & WMIconGeometry) {
03724         p->icon_geom = NETRect();
03725     if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
03726                    False, XA_CARDINAL, &type_ret, &format_ret,
03727                    &nitems_ret, &unused, &data_ret)
03728         == Success) {
03729         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03730         nitems_ret == 4) {
03731         long *d = (long *) data_ret;
03732         p->icon_geom.pos.x       = d[0];
03733         p->icon_geom.pos.y       = d[1];
03734         p->icon_geom.size.width  = d[2];
03735         p->icon_geom.size.height = d[3];
03736         }
03737         if ( data_ret )
03738         XFree(data_ret);
03739     }
03740     }
03741 
03742     if (dirty & WMIcon) {
03743     readIcon(p);
03744     }
03745 
03746     if (dirty & WMKDESystemTrayWinFor) {
03747     p->kde_system_tray_win_for = 0;
03748     if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
03749                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
03750                    &nitems_ret, &unused, &data_ret)
03751         == Success) {
03752         if (type_ret == XA_WINDOW && format_ret == 32 &&
03753         nitems_ret == 1) {
03754         p->kde_system_tray_win_for = *((Window *) data_ret);
03755         if ( p->kde_system_tray_win_for == 0 )
03756             p->kde_system_tray_win_for = p->root;
03757         }
03758         if ( data_ret )
03759         XFree(data_ret);
03760         }
03761     }
03762 
03763     if (dirty & WMKDEFrameStrut) {
03764         p->frame_strut = NETStrut();
03765     if (XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
03766                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
03767                    &nitems_ret, &unused, &data_ret) == Success) {
03768         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
03769         long *d = (long *) data_ret;
03770 
03771         p->frame_strut.left   = d[0];
03772         p->frame_strut.right  = d[1];
03773         p->frame_strut.top    = d[2];
03774         p->frame_strut.bottom = d[3];
03775         }
03776         if ( data_ret )
03777         XFree(data_ret);
03778     }
03779     }
03780 
03781     if (dirty & WMPid) {
03782     p->pid = 0;
03783     if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
03784                    False, XA_CARDINAL, &type_ret, &format_ret,
03785                    &nitems_ret, &unused, &data_ret) == Success) {
03786         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
03787         p->pid = *((long *) data_ret);
03788         }
03789         if ( data_ret )
03790         XFree(data_ret);
03791     }
03792     }
03793 
03794     if (dirty2 & WM2StartupId)
03795     {
03796         delete[] p->startup_id;
03797         p->startup_id = NULL;
03798     if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l,
03799                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03800                    &format_ret, &nitems_ret, &unused, &data_ret)
03801         == Success) {
03802         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
03803         p->startup_id = nstrndup((const char *) data_ret, nitems_ret);
03804         }
03805 
03806         if( data_ret )
03807         XFree(data_ret);
03808     }
03809     }
03810 
03811     if( dirty2 & WM2AllowedActions ) {
03812         p->allowed_actions = 0;
03813     if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l,
03814                    False, XA_ATOM, &type_ret, &format_ret,
03815                    &nitems_ret, &unused, &data_ret)
03816         == Success) {
03817         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03818         // determine actions
03819 #ifdef NETWMDEBUG
03820         fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n",
03821             nitems_ret);
03822 #endif
03823 
03824         long *actions = (long *) data_ret;
03825         unsigned long count;
03826 
03827         for (count = 0; count < nitems_ret; count++) {
03828 #ifdef NETWMDEBUG
03829             fprintf(stderr,
03830                 "NETWinInfo::update:   adding allowed action %ld '%s'\n",
03831                 actions[count],
03832                 XGetAtomName(p->display, (Atom) actions[count]));
03833 #endif
03834 
03835             if ((Atom) actions[count] == net_wm_action_move)
03836             p->allowed_actions |= ActionMove;
03837             if ((Atom) actions[count] == net_wm_action_resize)
03838             p->allowed_actions |= ActionResize;
03839             if ((Atom) actions[count] == net_wm_action_minimize)
03840             p->allowed_actions |= ActionMinimize;
03841             if ((Atom) actions[count] == net_wm_action_shade)
03842             p->allowed_actions |= ActionShade;
03843             if ((Atom) actions[count] == net_wm_action_stick)
03844             p->allowed_actions |= ActionStick;
03845             if ((Atom) actions[count] == net_wm_action_max_vert)
03846             p->allowed_actions |= ActionMaxVert;
03847             if ((Atom) actions[count] == net_wm_action_max_horiz)
03848             p->allowed_actions |= ActionMaxHoriz;
03849             if ((Atom) actions[count] == net_wm_action_fullscreen)
03850             p->allowed_actions |= ActionFullScreen;
03851             if ((Atom) actions[count] == net_wm_action_change_desk)
03852             p->allowed_actions |= ActionChangeDesktop;
03853             if ((Atom) actions[count] == net_wm_action_close)
03854             p->allowed_actions |= ActionClose;
03855         }
03856         }
03857         if ( data_ret )
03858         XFree(data_ret);
03859     }
03860     }
03861 
03862     if (dirty2 & WM2UserTime) {
03863     p->user_time = -1U;
03864     if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l,
03865                    False, XA_CARDINAL, &type_ret, &format_ret,
03866                    &nitems_ret, &unused, &data_ret) == Success) {
03867             // don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it
03868         if (type_ret == XA_CARDINAL && format_ret == 32 /*&& nitems_ret == 1*/) {
03869         p->user_time = *((long *) data_ret);
03870         }
03871         if ( data_ret )
03872         XFree(data_ret);
03873     }
03874     }
03875 
03876     if (dirty2 & WM2TransientFor) {
03877     p->transient_for = None;
03878         XGetTransientForHint(p->display, p->window, &p->transient_for);
03879     }
03880 
03881     if (dirty2 & WM2GroupLeader) {
03882         XWMHints *hints = XGetWMHints(p->display, p->window);
03883         p->window_group = None;
03884         if ( hints )
03885         {
03886             if( hints->flags & WindowGroupHint )
03887                 p->window_group = hints->window_group;
03888             XFree( reinterpret_cast< char* >( hints ));
03889         }
03890     }
03891 
03892 }
03893 
03894 
03895 NETRect NETWinInfo::iconGeometry() const {
03896     return p->icon_geom;
03897 }
03898 
03899 
03900 unsigned long NETWinInfo::state() const {
03901     return p->state;
03902 }
03903 
03904 
03905 NETStrut NETWinInfo::strut() const {
03906     return p->strut;
03907 }
03908 
03909 NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const {
03910     for( int i = 0;
03911      i < p->types.size();
03912      ++i ) {
03913     switch( p->types[ i ] ) {
03914     // return the type only if the application supports it
03915 #define CHECK_TYPE_MASK( type ) \
03916         case type: \
03917         if( supported_types & type##Mask ) \
03918             return type; \
03919         break;
03920         CHECK_TYPE_MASK( Normal )
03921         CHECK_TYPE_MASK( Desktop )
03922         CHECK_TYPE_MASK( Dock )
03923         CHECK_TYPE_MASK( Toolbar )
03924         CHECK_TYPE_MASK( Menu )
03925         CHECK_TYPE_MASK( Dialog )
03926         CHECK_TYPE_MASK( Override )
03927         CHECK_TYPE_MASK( TopMenu )
03928         CHECK_TYPE_MASK( Utility )
03929         CHECK_TYPE_MASK( Splash )
03930 #undef CHECK_TYPE_MASK
03931         default:
03932         break;
03933     }
03934     }
03935     return Unknown;
03936 }
03937 
03938 NET::WindowType NETWinInfo::windowType() const {
03939     return p->types[ 0 ];
03940 }
03941 
03942 
03943 const char *NETWinInfo::name() const {
03944     return p->name;
03945 }
03946 
03947 
03948 const char *NETWinInfo::visibleName() const {
03949     return p->visible_name;
03950 }
03951 
03952 
03953 const char *NETWinInfo::iconName() const {
03954     return p->icon_name;
03955 }
03956 
03957 
03958 const char *NETWinInfo::visibleIconName() const {
03959     return p->visible_icon_name;
03960 }
03961 
03962 
03963 int NETWinInfo::desktop() const {
03964     return p->desktop;
03965 }
03966 
03967 int NETWinInfo::pid() const {
03968     return p->pid;
03969 }
03970 
03971 Time NETWinInfo::userTime() const {
03972     return p->user_time;
03973 }
03974 
03975 const char* NETWinInfo::startupId() const {
03976     return p->startup_id;
03977 }
03978 
03979 unsigned long NETWinInfo::allowedActions() const {
03980     return p->allowed_actions;
03981 }
03982 
03983 bool NETWinInfo::hasNETSupport() const {
03984     return p->has_net_support;
03985 }
03986 
03987 Window NETWinInfo::transientFor() const {
03988     return p->transient_for;
03989 }
03990 
03991 Window NETWinInfo::groupLeader() const {
03992     return p->window_group;
03993 }
03994 
03995 Bool NETWinInfo::handledIcons() const {
03996     return p->handled_icons;
03997 }
03998 
03999 
04000 Window NETWinInfo::kdeSystemTrayWinFor() const {
04001     return p->kde_system_tray_win_for;
04002 }
04003 
04004 const unsigned long* NETWinInfo::passedProperties() const {
04005     return p->properties;
04006 }
04007 
04008 unsigned long NETWinInfo::properties() const {
04009     return p->properties[ PROTOCOLS ];
04010 }
04011 
04012 
04013 NET::MappingState NETWinInfo::mappingState() const {
04014     return p->mapping_state;
04015 }
04016 
04017 void NETRootInfo::virtual_hook( int, void* )
04018 { /*BASE::virtual_hook( id, data );*/ }
04019 
04020 void NETWinInfo::virtual_hook( int, void* )
04021 { /*BASE::virtual_hook( id, data );*/ }
04022 
04023 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun May 16 22:01:24 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003