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

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • 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.3
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