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