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

KDEUI

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

kdelibs

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