netwm.cpp

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