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

KDEUI

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

kdelibs

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