• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

netwm.cpp

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

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal