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

KDEUI

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

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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