• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

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

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.