kdecore Library API Documentation

netwm.cpp

00001 /*
00002 
00003   Copyright (c) 2000 Troll Tech AS
00004 
00005   Permission is hereby granted, free of charge, to any person obtaining a
00006   copy of this software and associated documentation files (the "Software"),
00007   to deal in the Software without restriction, including without limitation
00008   the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009   and/or sell copies of the Software, and to permit persons to whom the
00010   Software is furnished to do so, subject to the following conditions:
00011 
00012   The above copyright notice and this permission notice shall be included in
00013   all copies or substantial portions of the Software.
00014 
00015   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00020   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00021   DEALINGS IN THE SOFTWARE.
00022 
00023 */
00024 
00025 // #define NETWMDEBUG
00026 
00027 #include <qwidget.h>
00028 #ifdef Q_WS_X11 //FIXME
00029 
00030 #include "netwm.h"
00031 
00032 #include <string.h>
00033 #include <stdio.h>
00034 
00035 #include <X11/Xlibint.h>
00036 #include <X11/Xmd.h>
00037 
00038 typedef Bool X11Bool;
00039 
00040 #include "netwm_p.h"
00041 
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 
00060 // root window messages
00061 static Atom net_close_window         = 0;
00062 static Atom net_wm_moveresize        = 0;
00063 
00064 // application window properties
00065 static Atom net_wm_name              = 0;
00066 static Atom net_wm_visible_name      = 0;
00067 static Atom net_wm_icon_name         = 0;
00068 static Atom net_wm_visible_icon_name = 0;
00069 static Atom net_wm_desktop           = 0;
00070 static Atom net_wm_window_type       = 0;
00071 static Atom net_wm_state             = 0;
00072 static Atom net_wm_strut             = 0;
00073 static Atom net_wm_icon_geometry     = 0;
00074 static Atom net_wm_icon              = 0;
00075 static Atom net_wm_pid               = 0;
00076 static Atom net_wm_handled_icons     = 0;
00077 
00078 // KDE extensions
00079 static Atom kde_net_system_tray_windows       = 0;
00080 static Atom kde_net_wm_system_tray_window_for = 0;
00081 static Atom kde_net_wm_frame_strut            = 0;
00082 static Atom kde_net_wm_window_type_override   = 0;
00083 static Atom kde_net_wm_window_type_topmenu    = 0;
00084 
00085 // application protocols
00086 static Atom net_wm_ping = 0;
00087 
00088 // application window types
00089 static Atom net_wm_window_type_normal  = 0;
00090 static Atom net_wm_window_type_desktop = 0;
00091 static Atom net_wm_window_type_dock    = 0;
00092 static Atom net_wm_window_type_toolbar = 0;
00093 static Atom net_wm_window_type_menu    = 0;
00094 static Atom net_wm_window_type_dialog  = 0;
00095 
00096 // application window state
00097 static Atom net_wm_state_modal        = 0;
00098 static Atom net_wm_state_sticky       = 0;
00099 static Atom net_wm_state_max_vert     = 0;
00100 static Atom net_wm_state_max_horiz    = 0;
00101 static Atom net_wm_state_shaded       = 0;
00102 static Atom net_wm_state_skip_taskbar = 0;
00103 static Atom net_wm_state_skip_pager   = 0;
00104 static Atom net_wm_state_stays_on_top = 0;
00105 
00106 // used to determine whether application window is managed or not
00107 static Atom xa_wm_state = 0;
00108 
00109 static Bool netwm_atoms_created      = False;
00110 const unsigned long netwm_sendevent_mask = (SubstructureRedirectMask|
00111                          SubstructureNotifyMask);
00112 
00113 
00114 static char *nstrdup(const char *s1) {
00115     if (! s1) return (char *) 0;
00116 
00117     int l = strlen(s1) + 1;
00118     char *s2 = new char[l];
00119     strncpy(s2, s1, l);
00120     return s2;
00121 }
00122 
00123 
00124 static char *nstrndup(const char *s1, int l) {
00125     if (! s1 || l == 0) return (char *) 0;
00126 
00127     char *s2 = new char[l+1];
00128     strncpy(s2, s1, l);
00129     s2[l] = '\0';
00130     return s2;
00131 }
00132 
00133 
00134 static Window *nwindup(Window *w1, int n) {
00135     if (! w1 || n == 0) return (Window *) 0;
00136 
00137     Window *w2 = new Window[n];
00138     while (n--) w2[n] = w1[n];
00139     return w2;
00140 }
00141 
00142 
00143 static void refdec_nri(NETRootInfoPrivate *p) {
00144 
00145 #ifdef    NETWMDEBUG
00146     fprintf(stderr, "NET: decrementing NETRootInfoPrivate::ref (%d)\n", p->ref - 1);
00147 #endif
00148 
00149     if (! --p->ref) {
00150 
00151 #ifdef    NETWMDEBUG
00152     fprintf(stderr, "NET: \tno more references, deleting\n");
00153 #endif
00154 
00155     if (p->name) delete [] p->name;
00156     if (p->stacking) delete [] p->stacking;
00157     if (p->clients) delete [] p->clients;
00158     if (p->virtual_roots) delete [] p->virtual_roots;
00159 
00160     int i;
00161     for (i = 0; i < p->desktop_names.size(); i++)
00162         if (p->desktop_names[i]) delete [] p->desktop_names[i];
00163     }
00164 }
00165 
00166 
00167 static void refdec_nwi(NETWinInfoPrivate *p) {
00168 
00169 #ifdef    NETWMDEBUG
00170     fprintf(stderr, "NET: decrementing NETWinInfoPrivate::ref (%d)\n", p->ref - 1);
00171 #endif
00172 
00173     if (! --p->ref) {
00174 
00175 #ifdef    NETWMDEBUG
00176     fprintf(stderr, "NET: \tno more references, deleting\n");
00177 #endif
00178 
00179     if (p->name) delete [] p->name;
00180     if (p->visible_name) delete [] p->visible_name;
00181 
00182     int i;
00183     for (i = 0; i < p->icons.size(); i++)
00184         if (p->icons[i].data) delete [] p->icons[i].data;
00185     }
00186 }
00187 
00188 
00189 static int wcmp(const void *a, const void *b) {
00190     return *((Window *) a) - *((Window *) b);
00191 }
00192 
00193 
00194 static const int netAtomCount = 48;
00195 static void create_atoms(Display *d) {
00196     static const char * const names[netAtomCount] =
00197     {
00198     "UTF8_STRING",
00199         "_NET_SUPPORTED",
00200         "_NET_SUPPORTING_WM_CHECK",
00201         "_NET_CLIENT_LIST",
00202         "_NET_CLIENT_LIST_STACKING",
00203         "_NET_NUMBER_OF_DESKTOPS",
00204         "_NET_DESKTOP_GEOMETRY",
00205         "_NET_DESKTOP_VIEWPORT",
00206         "_NET_CURRENT_DESKTOP",
00207         "_NET_DESKTOP_NAMES",
00208         "_NET_ACTIVE_WINDOW",
00209         "_NET_WORKAREA",
00210         "_NET_VIRTUAL_ROOTS",
00211         "_NET_CLOSE_WINDOW",
00212 
00213         "_NET_WM_MOVERESIZE",
00214         "_NET_WM_NAME",
00215         "_NET_WM_VISIBLE_NAME",
00216         "_NET_WM_ICON_NAME",
00217         "_NET_WM_VISIBLE_ICON_NAME",
00218         "_NET_WM_DESKTOP",
00219         "_NET_WM_WINDOW_TYPE",
00220         "_NET_WM_STATE",
00221         "_NET_WM_STRUT",
00222         "_NET_WM_ICON_GEOMETRY",
00223         "_NET_WM_ICON",
00224         "_NET_WM_PID",
00225         "_NET_WM_HANDLED_ICONS",
00226         "_NET_WM_PING",
00227 
00228         "_NET_WM_WINDOW_TYPE_NORMAL",
00229         "_NET_WM_WINDOW_TYPE_DESKTOP",
00230         "_NET_WM_WINDOW_TYPE_DOCK",
00231         "_NET_WM_WINDOW_TYPE_TOOLBAR",
00232         "_NET_WM_WINDOW_TYPE_MENU",
00233         "_NET_WM_WINDOW_TYPE_DIALOG",
00234 
00235         "_NET_WM_STATE_MODAL",
00236         "_NET_WM_STATE_STICKY",
00237         "_NET_WM_STATE_MAXIMIZED_VERT",
00238         "_NET_WM_STATE_MAXIMIZED_HORZ",
00239         "_NET_WM_STATE_SHADED",
00240         "_NET_WM_STATE_SKIP_TASKBAR",
00241         "_NET_WM_STATE_SKIP_PAGER",
00242         "_NET_WM_STATE_STAYS_ON_TOP",
00243 
00244         "_KDE_NET_SYSTEM_TRAY_WINDOWS",
00245         "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
00246         "_KDE_NET_WM_FRAME_STRUT",
00247         "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE",
00248         "_KDE_NET_WM_WINDOW_TYPE_TOPMENU",
00249 
00250         "WM_STATE"
00251         };
00252 
00253     Atom atoms[netAtomCount], *atomsp[netAtomCount] =
00254     {
00255     &UTF8_STRING,
00256         &net_supported,
00257         &net_supporting_wm_check,
00258         &net_client_list,
00259         &net_client_list_stacking,
00260         &net_number_of_desktops,
00261         &net_desktop_geometry,
00262         &net_desktop_viewport,
00263         &net_current_desktop,
00264         &net_desktop_names,
00265         &net_active_window,
00266         &net_workarea,
00267         &net_virtual_roots,
00268         &net_close_window,
00269 
00270         &net_wm_moveresize,
00271         &net_wm_name,
00272         &net_wm_visible_name,
00273         &net_wm_icon_name,
00274         &net_wm_visible_icon_name,
00275         &net_wm_desktop,
00276         &net_wm_window_type,
00277         &net_wm_state,
00278         &net_wm_strut,
00279         &net_wm_icon_geometry,
00280         &net_wm_icon,
00281         &net_wm_pid,
00282         &net_wm_handled_icons,
00283         &net_wm_ping,
00284 
00285         &net_wm_window_type_normal,
00286         &net_wm_window_type_desktop,
00287         &net_wm_window_type_dock,
00288         &net_wm_window_type_toolbar,
00289         &net_wm_window_type_menu,
00290         &net_wm_window_type_dialog,
00291 
00292         &net_wm_state_modal,
00293         &net_wm_state_sticky,
00294         &net_wm_state_max_vert,
00295         &net_wm_state_max_horiz,
00296         &net_wm_state_shaded,
00297         &net_wm_state_skip_taskbar,
00298         &net_wm_state_skip_pager,
00299         &net_wm_state_stays_on_top,
00300 
00301         &kde_net_system_tray_windows,
00302         &kde_net_wm_system_tray_window_for,
00303         &kde_net_wm_frame_strut,
00304         &kde_net_wm_window_type_override,
00305         &kde_net_wm_window_type_topmenu,
00306 
00307         &xa_wm_state,
00308         };
00309 
00310     int i = netAtomCount;
00311     while (i--)
00312     atoms[i] = 0;
00313 
00314     XInternAtoms(d, (char **) names, netAtomCount, False, atoms);
00315 
00316     i = netAtomCount;
00317     while (i--)
00318     *atomsp[i] = atoms[i];
00319 
00320     netwm_atoms_created = True;
00321 }
00322 
00323 
00324 static void readIcon(NETWinInfoPrivate *p) {
00325 
00326 #ifdef    NETWMDEBUG
00327     fprintf(stderr, "NET: readIcon\n");
00328 #endif
00329 
00330     Atom type_ret;
00331     int format_ret;
00332     unsigned long nitems_ret = 0, after_ret = 0;
00333     unsigned char *data_ret = 0;
00334 
00335     // allocate buffers
00336     unsigned char *buffer = 0;
00337     unsigned long offset = 0;
00338     unsigned long buffer_offset = 0;
00339     unsigned long bufsize = 0;
00340 
00341     // read data
00342     do {
00343     if (XGetWindowProperty(p->display, p->window, net_wm_icon, offset,
00344                    BUFSIZE, False, XA_CARDINAL, &type_ret,
00345                    &format_ret, &nitems_ret, &after_ret, &data_ret)
00346         == Success) {
00347             if (!bufsize)
00348             {
00349                if (nitems_ret < 3 || type_ret != XA_CARDINAL ||
00350                   format_ret != 32) {
00351                   // either we didn't get the property, or the property has less than
00352                   // 3 elements in it
00353                   // NOTE: 3 is the ABSOLUTE minimum:
00354                   //     width = 1, height = 1, length(data) = 1 (width * height)
00355                   if ( data_ret )
00356                      XFree(data_ret);
00357                   return;
00358                }
00359 
00360                bufsize = nitems_ret * sizeof(long) + after_ret;
00361                buffer = (unsigned char *) malloc(bufsize);
00362             }
00363             else if (buffer_offset + nitems_ret*sizeof(long) > bufsize)
00364             {
00365 fprintf(stderr, "NETWM: Warning readIcon() needs buffer adjustment!\n");
00366                bufsize = buffer_offset + nitems_ret * sizeof(long) + after_ret;
00367                buffer = (unsigned char *) realloc(buffer, bufsize);
00368             }
00369         memcpy((buffer + buffer_offset), data_ret, nitems_ret * sizeof(long));
00370         buffer_offset += nitems_ret * sizeof(long);
00371         offset += nitems_ret;
00372 
00373         if ( data_ret )
00374         XFree(data_ret);
00375     } else {
00376             if (buffer)
00377                free(buffer);
00378         return; // Some error occured cq. property didn't exist.
00379     }
00380     }
00381     while (after_ret > 0);
00382 
00383     CARD32 *data32;
00384     unsigned long i, j, k, sz, s;
00385     unsigned long *d = (unsigned long *) buffer;
00386     for (i = 0, j = 0; i < bufsize; i++) {
00387     p->icons[j].size.width = *d++;
00388     i += sizeof(long);
00389     p->icons[j].size.height = *d++;
00390     i += sizeof(long);
00391 
00392     sz = p->icons[j].size.width * p->icons[j].size.height;
00393     s = sz * sizeof(long);
00394 
00395     if ( i + s - 1 > bufsize ) {
00396         break;
00397     }
00398 
00399     if (p->icons[j].data) delete [] p->icons[j].data;
00400     data32 = new CARD32[sz];
00401     p->icons[j].data = (unsigned char *) data32;
00402     for (k = 0; k < sz; k++, i += sizeof(long)) {
00403         *data32++ = (CARD32) *d++;
00404     }
00405     j++;
00406     }
00407 
00408 #ifdef    NETWMDEBUG
00409     fprintf(stderr, "NET: readIcon got %d icons\n", p->icons.size());
00410 #endif
00411 
00412     free(buffer);
00413 }
00414 
00415 
00416 template <class Z>
00417 RArray<Z>::RArray() {
00418   sz = 0;
00419   d = 0;
00420 }
00421 
00422 
00423 template <class Z>
00424 RArray<Z>::~RArray() {
00425     if (d) delete [] d;
00426 }
00427 
00428 
00429 template <class Z>
00430 Z &RArray<Z>::operator[](int index) {
00431     if (!d) {
00432     d = new Z[index + 1];
00433     memset( (void*) &d[0], 0, sizeof(Z) );
00434     sz = 1;
00435     } else if (index >= sz) {
00436     // allocate space for the new data
00437     Z *newdata = new Z[index + 1];
00438 
00439     // move the old data into the new array
00440     int i;
00441     for (i = 0; i < sz; i++)
00442         newdata[i] = d[i];
00443     for (; i <= index; i++ )
00444         memset( (void*) &newdata[i], 0, sizeof(Z) );
00445 
00446     sz = index + 1;
00447 
00448     // delete old data and reassign
00449     delete [] d;
00450     d = newdata;
00451     }
00452 
00453     return d[index];
00454 }
00455 
00456 
00457 // Construct a new NETRootInfo object.
00458 
00459 NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
00460              unsigned long properties, int screen, bool doActivate)
00461 {
00462 
00463 #ifdef    NETWMDEBUG
00464     fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
00465 #endif
00466 
00467     p = new NETRootInfoPrivate;
00468     p->ref = 1;
00469 
00470     p->display = display;
00471     p->name = nstrdup(wmName);
00472 
00473     if (screen != -1) {
00474     p->screen = screen;
00475     } else {
00476     p->screen = DefaultScreen(p->display);
00477     }
00478 
00479     p->root = RootWindow(p->display, p->screen);
00480     p->supportwindow = supportWindow;
00481     p->protocols = properties;
00482     p->number_of_desktops = p->current_desktop = 0;
00483     p->active = None;
00484     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00485     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00486     p->kde_system_tray_windows = 0;
00487     p->kde_system_tray_windows_count = 0;
00488 
00489     role = WindowManager;
00490 
00491     if (! netwm_atoms_created) create_atoms(p->display);
00492 
00493     if (doActivate) activate();
00494 }
00495 
00496 
00497 NETRootInfo::NETRootInfo(Display *display, unsigned long properties, int screen,
00498              bool doActivate)
00499 {
00500 
00501 #ifdef    NETWMDEBUG
00502     fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
00503 #endif
00504 
00505     p = new NETRootInfoPrivate;
00506     p->ref = 1;
00507 
00508     p->name = 0;
00509 
00510     p->display = display;
00511 
00512     if (screen != -1) {
00513     p->screen = screen;
00514     } else {
00515     p->screen = DefaultScreen(p->display);
00516     }
00517 
00518     p->root = RootWindow(p->display, p->screen);
00519     p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
00520     p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
00521 
00522     p->supportwindow = None;
00523     p->protocols = properties;
00524     p->number_of_desktops = p->current_desktop = 0;
00525     p->active = None;
00526     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00527     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00528     p->kde_system_tray_windows = 0;
00529     p->kde_system_tray_windows_count = 0;
00530 
00531     role = Client;
00532 
00533     if (! netwm_atoms_created) create_atoms(p->display);
00534 
00535     if (doActivate) activate();
00536 }
00537 
00538 
00539 // Copy an existing NETRootInfo object.
00540 
00541 NETRootInfo::NETRootInfo(const NETRootInfo &rootinfo) {
00542 
00543 #ifdef    NETWMDEBUG
00544     fprintf(stderr, "NETRootInfo::NETRootInfo: using copy constructor\n");
00545 #endif
00546 
00547     p = rootinfo.p;
00548     role = rootinfo.role;
00549 
00550     p->ref++;
00551 }
00552 
00553 
00554 // Be gone with our NETRootInfo.
00555 
00556 NETRootInfo::~NETRootInfo() {
00557     refdec_nri(p);
00558 
00559     if (! p->ref) delete p;
00560 }
00561 
00562 
00563 void NETRootInfo::activate() {
00564     if (role == WindowManager) {
00565 
00566 #ifdef    NETWMDEBUG
00567     fprintf(stderr,
00568         "NETRootInfo::activate: setting supported properties on root\n");
00569 #endif
00570 
00571     // force support for Supported and SupportingWMCheck for window managers
00572     setSupported(p->protocols | Supported | SupportingWMCheck);
00573     } else {
00574 
00575 #ifdef    NETWMDEBUG
00576     fprintf(stderr, "NETRootInfo::activate: updating client information\n");
00577 #endif
00578 
00579     update(p->protocols);
00580     }
00581 }
00582 
00583 
00584 void NETRootInfo::setClientList(Window *windows, unsigned int count) {
00585     if (role != WindowManager) return;
00586 
00587     p->clients_count = count;
00588 
00589     if (p->clients) delete [] p->clients;
00590     p->clients = nwindup(windows, count);
00591 
00592 #ifdef    NETWMDEBUG
00593     fprintf(stderr, "NETRootInfo::setClientList: setting list with %ld windows\n",
00594         p->clients_count);
00595 #endif
00596 
00597     XChangeProperty(p->display, p->root, net_client_list, XA_WINDOW, 32,
00598             PropModeReplace, (unsigned char *)p->clients,
00599             p->clients_count);
00600 }
00601 
00602 
00603 void NETRootInfo::setClientListStacking(Window *windows, unsigned int count) {
00604     if (role != WindowManager) return;
00605 
00606     p->stacking_count = count;
00607     if (p->stacking) delete [] p->stacking;
00608     p->stacking = nwindup(windows, count);
00609 
00610 #ifdef    NETWMDEBUG
00611     fprintf(stderr,
00612         "NETRootInfo::setClientListStacking: setting list with %ld windows\n",
00613         p->clients_count);
00614 #endif
00615 
00616     XChangeProperty(p->display, p->root, net_client_list_stacking, XA_WINDOW, 32,
00617             PropModeReplace, (unsigned char *) p->stacking,
00618             p->stacking_count);
00619 }
00620 
00621 
00622 void NETRootInfo::setKDESystemTrayWindows(Window *windows, unsigned int count) {
00623     if (role != WindowManager) return;
00624 
00625     p->kde_system_tray_windows_count = count;
00626     if (p->kde_system_tray_windows) delete [] p->kde_system_tray_windows;
00627     p->kde_system_tray_windows = nwindup(windows, count);
00628 
00629 #ifdef    NETWMDEBUG
00630     fprintf(stderr,
00631         "NETRootInfo::setKDESystemTrayWindows: setting list with %ld windows\n",
00632         p->kde_system_tray_windows_count);
00633 #endif
00634 
00635     XChangeProperty(p->display, p->root, kde_net_system_tray_windows, XA_WINDOW, 32,
00636             PropModeReplace,
00637             (unsigned char *) p->kde_system_tray_windows,
00638             p->kde_system_tray_windows_count);
00639 }
00640 
00641 
00642 void NETRootInfo::setNumberOfDesktops(int numberOfDesktops) {
00643 
00644 #ifdef    NETWMDEBUG
00645     fprintf(stderr,
00646         "NETRootInfo::setNumberOfDesktops: setting desktop count to %d (%s)\n",
00647         numberOfDesktops, (role == WindowManager) ? "WM" : "Client");
00648 #endif
00649 
00650     if (role == WindowManager) {
00651     p->number_of_desktops = numberOfDesktops;
00652     long d = numberOfDesktops;
00653     XChangeProperty(p->display, p->root, net_number_of_desktops, XA_CARDINAL, 32,
00654             PropModeReplace, (unsigned char *) &d, 1);
00655     } else {
00656     XEvent e;
00657 
00658     e.xclient.type = ClientMessage;
00659     e.xclient.message_type = net_number_of_desktops;
00660     e.xclient.display = p->display;
00661     e.xclient.window = p->root;
00662     e.xclient.format = 32;
00663     e.xclient.data.l[0] = numberOfDesktops;
00664     e.xclient.data.l[1] = 0l;
00665     e.xclient.data.l[2] = 0l;
00666     e.xclient.data.l[3] = 0l;
00667     e.xclient.data.l[4] = 0l;
00668 
00669     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00670     }
00671 }
00672 
00673 
00674 void NETRootInfo::setCurrentDesktop(int desktop) {
00675 
00676 #ifdef    NETWMDEBUG
00677     fprintf(stderr,
00678         "NETRootInfo::setCurrentDesktop: setting current desktop = %d (%s)\n",
00679         desktop, (role == WindowManager) ? "WM" : "Client");
00680 #endif
00681 
00682     if (role == WindowManager) {
00683     p->current_desktop = desktop;
00684     long d = p->current_desktop - 1;
00685     XChangeProperty(p->display, p->root, net_current_desktop, XA_CARDINAL, 32,
00686             PropModeReplace, (unsigned char *) &d, 1);
00687     } else {
00688     XEvent e;
00689 
00690     e.xclient.type = ClientMessage;
00691     e.xclient.message_type = net_current_desktop;
00692     e.xclient.display = p->display;
00693     e.xclient.window = p->root;
00694     e.xclient.format = 32;
00695     e.xclient.data.l[0] = desktop - 1;
00696     e.xclient.data.l[1] = 0l;
00697     e.xclient.data.l[2] = 0l;
00698     e.xclient.data.l[3] = 0l;
00699     e.xclient.data.l[4] = 0l;
00700 
00701     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00702     }
00703 }
00704 
00705 
00706 void NETRootInfo::setDesktopName(int desktop, const char *desktopName) {
00707     // return immediately if the requested desk is out of range
00708     if (desktop < 1 || desktop > p->number_of_desktops) return;
00709 
00710     if (p->desktop_names[desktop - 1]) delete [] p->desktop_names[desktop - 1];
00711     p->desktop_names[desktop - 1] = nstrdup(desktopName);
00712 
00713     unsigned int i, proplen,
00714     num = ((p->number_of_desktops < p->desktop_names.size()) ?
00715            p->number_of_desktops : p->desktop_names.size());
00716     for (i = 0, proplen = 0; i < num; i++)
00717     proplen += (p->desktop_names[i] != 0 ? strlen(p->desktop_names[i]) : 1 ) + 1;
00718 
00719     char *prop = new char[proplen], *propp = prop;
00720 
00721     for (i = 0; i < num; i++)
00722     if (p->desktop_names[i]) {
00723         strcpy(propp, p->desktop_names[i]);
00724         propp += strlen(p->desktop_names[i]) + 1;
00725     } else
00726         *propp++ = '\0';
00727 
00728 #ifdef    NETWMDEBUG
00729     fprintf(stderr,
00730         "NETRootInfo::setDesktopName(%d, '%s')\n"
00731         "NETRootInfo::setDesktopName: total property length = %d",
00732         desktop, desktopName, proplen);
00733 #endif
00734 
00735     XChangeProperty(p->display, p->root, net_desktop_names, UTF8_STRING, 8,
00736             PropModeReplace, (unsigned char *) prop, proplen);
00737 
00738     delete [] prop;
00739 }
00740 
00741 
00742 void NETRootInfo::setDesktopGeometry(int , const NETSize &geometry) {
00743 
00744 #ifdef    NETWMDEBUG
00745     fprintf(stderr, "NETRootInfo::setDesktopGeometry( -- , { %d, %d }) (%s)\n",
00746         geometry.width, geometry.height, (role == WindowManager) ? "WM" : "Client");
00747 #endif
00748 
00749     if (role == WindowManager) {
00750     p->geometry = geometry;
00751 
00752     long data[2];
00753     data[0] = p->geometry.width;
00754     data[1] = p->geometry.height;
00755 
00756     XChangeProperty(p->display, p->root, net_desktop_geometry, XA_CARDINAL, 32,
00757             PropModeReplace, (unsigned char *) data, 2);
00758     } else {
00759     XEvent e;
00760 
00761     e.xclient.type = ClientMessage;
00762     e.xclient.message_type = net_desktop_geometry;
00763     e.xclient.display = p->display;
00764     e.xclient.window = p->root;
00765     e.xclient.format = 32;
00766     e.xclient.data.l[0] = geometry.width;
00767     e.xclient.data.l[1] = geometry.height;
00768     e.xclient.data.l[2] = 0l;
00769     e.xclient.data.l[3] = 0l;
00770     e.xclient.data.l[4] = 0l;
00771 
00772     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00773     }
00774 }
00775 
00776 
00777 void NETRootInfo::setDesktopViewport(int desktop, const NETPoint &viewport) {
00778 
00779 #ifdef    NETWMDEBUG
00780     fprintf(stderr, "NETRootInfo::setDesktopViewport(%d, { %d, %d }) (%s)\n",
00781         desktop, viewport.x, viewport.y, (role == WindowManager) ? "WM" : "Client");
00782 #endif
00783 
00784     if (desktop < 1) return;
00785 
00786     if (role == WindowManager) {
00787     p->viewport[desktop - 1] = viewport;
00788 
00789     int d, i, l;
00790     l = p->viewport.size() * 2;
00791     long *data = new long[l];
00792     for (d = 0, i = 0; d < p->viewport.size(); d++) {
00793         data[i++] = p->viewport[d].x;
00794         data[i++] = p->viewport[d].y;
00795     }
00796 
00797     XChangeProperty(p->display, p->root, net_desktop_viewport, XA_CARDINAL, 32,
00798             PropModeReplace, (unsigned char *) data, l);
00799 
00800     delete [] data;
00801     } else {
00802     XEvent e;
00803 
00804     e.xclient.type = ClientMessage;
00805     e.xclient.message_type = net_desktop_viewport;
00806     e.xclient.display = p->display;
00807     e.xclient.window = p->root;
00808     e.xclient.format = 32;
00809     e.xclient.data.l[0] = viewport.x;
00810     e.xclient.data.l[1] = viewport.y;
00811     e.xclient.data.l[2] = 0l;
00812     e.xclient.data.l[3] = 0l;
00813     e.xclient.data.l[4] = 0l;
00814 
00815     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00816     }
00817 }
00818 
00819 
00820 void NETRootInfo::setSupported(unsigned long pr) {
00821     p->protocols = pr;
00822 
00823     if (role != WindowManager) {
00824 #ifdef    NETWMDEBUG
00825     fprintf(stderr, "NETRootInfo::setSupported - role != WindowManager\n");
00826 #endif
00827 
00828     return;
00829     }
00830 
00831     Atom atoms[netAtomCount];
00832     int pnum = 2;
00833 
00834     // Root window properties/messages
00835     atoms[0] = net_supported;
00836     atoms[1] = net_supporting_wm_check;
00837 
00838     if (p->protocols & ClientList)
00839     atoms[pnum++] = net_client_list;
00840 
00841     if (p->protocols & ClientListStacking)
00842     atoms[pnum++] = net_client_list_stacking;
00843 
00844     if (p->protocols & NumberOfDesktops)
00845     atoms[pnum++] = net_number_of_desktops;
00846 
00847     if (p->protocols & DesktopGeometry)
00848     atoms[pnum++] = net_desktop_geometry;
00849 
00850     if (p->protocols & DesktopViewport)
00851     atoms[pnum++] = net_desktop_viewport;
00852 
00853     if (p->protocols & CurrentDesktop)
00854     atoms[pnum++] = net_current_desktop;
00855 
00856     if (p->protocols & DesktopNames)
00857     atoms[pnum++] = net_desktop_names;
00858 
00859     if (p->protocols & ActiveWindow)
00860     atoms[pnum++] = net_active_window;
00861 
00862     if (p->protocols & WorkArea)
00863     atoms[pnum++] = net_workarea;
00864 
00865     if (p->protocols & VirtualRoots)
00866     atoms[pnum++] = net_virtual_roots;
00867 
00868     if (p->protocols & CloseWindow)
00869     atoms[pnum++] = net_close_window;
00870 
00871 
00872     // Application window properties/messages
00873     if (p->protocols & WMMoveResize)
00874     atoms[pnum++] = net_wm_moveresize;
00875 
00876     if (p->protocols & WMName)
00877     atoms[pnum++] = net_wm_name;
00878 
00879     if (p->protocols & WMVisibleName)
00880     atoms[pnum++] = net_wm_visible_name;
00881 
00882     if (p->protocols & WMIconName)
00883     atoms[pnum++] = net_wm_icon_name;
00884 
00885     if (p->protocols & WMVisibleIconName)
00886     atoms[pnum++] = net_wm_visible_icon_name;
00887 
00888     if (p->protocols & WMDesktop)
00889     atoms[pnum++] = net_wm_desktop;
00890 
00891     if (p->protocols & WMWindowType) {
00892     atoms[pnum++] = net_wm_window_type;
00893 
00894     // Application window types
00895     atoms[pnum++] = net_wm_window_type_normal;
00896     atoms[pnum++] = net_wm_window_type_desktop;
00897     atoms[pnum++] = net_wm_window_type_dock;
00898     atoms[pnum++] = net_wm_window_type_toolbar;
00899     atoms[pnum++] = net_wm_window_type_menu;
00900     atoms[pnum++] = net_wm_window_type_dialog;
00901     atoms[pnum++] = kde_net_wm_window_type_override;
00902     atoms[pnum++] = kde_net_wm_window_type_topmenu;
00903     }
00904 
00905     if (p->protocols & WMState) {
00906     atoms[pnum++] = net_wm_state;
00907 
00908     // Application window states
00909     atoms[pnum++] = net_wm_state_modal;
00910     atoms[pnum++] = net_wm_state_sticky;
00911     atoms[pnum++] = net_wm_state_max_vert;
00912     atoms[pnum++] = net_wm_state_max_horiz;
00913     atoms[pnum++] = net_wm_state_shaded;
00914     atoms[pnum++] = net_wm_state_skip_taskbar;
00915     atoms[pnum++] = net_wm_state_skip_pager;
00916     atoms[pnum++] = net_wm_state_stays_on_top;
00917     }
00918 
00919     if (p->protocols & WMStrut)
00920     atoms[pnum++] = net_wm_strut;
00921 
00922     if (p->protocols & WMIconGeometry)
00923     atoms[pnum++] = net_wm_icon_geometry;
00924 
00925     if (p->protocols & WMIcon)
00926     atoms[pnum++] = net_wm_icon;
00927 
00928     if (p->protocols & WMPid)
00929     atoms[pnum++] = net_wm_pid;
00930 
00931     if (p->protocols & WMHandledIcons)
00932     atoms[pnum++] = net_wm_handled_icons;
00933 
00934     if (p->protocols & WMPing)
00935     atoms[pnum++] = net_wm_ping;
00936 
00937     // KDE specific extensions
00938     if (p->protocols & KDESystemTrayWindows)
00939     atoms[pnum++] = kde_net_system_tray_windows;
00940 
00941     if (p->protocols & WMKDESystemTrayWinFor)
00942     atoms[pnum++] = kde_net_wm_system_tray_window_for;
00943 
00944     if (p->protocols & WMKDEFrameStrut)
00945     atoms[pnum++] = kde_net_wm_frame_strut;
00946 
00947     XChangeProperty(p->display, p->root, net_supported, XA_ATOM, 32,
00948             PropModeReplace, (unsigned char *) atoms, pnum);
00949     XChangeProperty(p->display, p->root, net_supporting_wm_check, XA_WINDOW, 32,
00950             PropModeReplace, (unsigned char *) &(p->supportwindow), 1);
00951 
00952 #ifdef    NETWMDEBUG
00953     fprintf(stderr,
00954         "NETRootInfo::setSupported: _NET_SUPPORTING_WM_CHECK = 0x%lx on 0x%lx\n"
00955         "                         : _NET_WM_NAME = '%s' on 0x%lx\n",
00956         p->supportwindow, p->supportwindow, p->name, p->supportwindow);
00957 #endif
00958 
00959     XChangeProperty(p->display, p->supportwindow, net_supporting_wm_check,
00960             XA_WINDOW, 32, PropModeReplace,
00961             (unsigned char *) &(p->supportwindow), 1);
00962     XChangeProperty(p->display, p->supportwindow, net_wm_name, UTF8_STRING, 8,
00963             PropModeReplace, (unsigned char *) p->name,
00964             strlen(p->name));
00965 }
00966 
00967 
00968 void NETRootInfo::setActiveWindow(Window window) {
00969 
00970 #ifdef    NETWMDEBUG
00971     fprintf(stderr, "NETRootInfo::setActiveWindow(0x%lx) (%s)\n",
00972             window, (role == WindowManager) ? "WM" : "Client");
00973 #endif
00974 
00975     if (role == WindowManager) {
00976     p->active = window;
00977     XChangeProperty(p->display, p->root, net_active_window, XA_WINDOW, 32,
00978             PropModeReplace, (unsigned char *) &(p->active), 1);
00979     } else {
00980     XEvent e;
00981 
00982     e.xclient.type = ClientMessage;
00983     e.xclient.message_type = net_active_window;
00984     e.xclient.display = p->display;
00985     e.xclient.window = window;
00986     e.xclient.format = 32;
00987     e.xclient.data.l[0] = 0l;
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::setWorkArea(int desktop, const NETRect &workarea) {
00999 
01000 #ifdef    NETWMDEBUG
01001     fprintf(stderr, "NETRootInfo::setWorkArea(%d, { %d, %d, %d, %d }) (%s)\n",
01002         desktop, workarea.pos.x, workarea.pos.y, workarea.size.width, workarea.size.height,
01003         (role == WindowManager) ? "WM" : "Client");
01004 #endif
01005 
01006     if (role != WindowManager || desktop < 1) return;
01007 
01008     p->workarea[desktop - 1] = workarea;
01009 
01010     long *wa = new long[p->number_of_desktops * 4];
01011     int i, o;
01012     for (i = 0, o = 0; i < p->number_of_desktops; i++) {
01013     wa[o++] = p->workarea[i].pos.x;
01014     wa[o++] = p->workarea[i].pos.y;
01015     wa[o++] = p->workarea[i].size.width;
01016     wa[o++] = p->workarea[i].size.height;
01017     }
01018 
01019     XChangeProperty(p->display, p->root, net_workarea, XA_CARDINAL, 32,
01020             PropModeReplace, (unsigned char *) wa,
01021             p->number_of_desktops * 4);
01022 
01023     delete [] wa;
01024 }
01025 
01026 
01027 void NETRootInfo::setVirtualRoots(Window *windows, unsigned int count) {
01028     if (role != WindowManager) return;
01029 
01030     p->virtual_roots_count = count;
01031     p->virtual_roots = windows;
01032 
01033 #ifdef   NETWMDEBUG
01034     fprintf(stderr, "NETRootInfo::setVirtualRoots: setting list with %ld windows\n",
01035         p->virtual_roots_count);
01036 #endif
01037 
01038     XChangeProperty(p->display, p->root, net_virtual_roots, XA_WINDOW, 32,
01039             PropModeReplace, (unsigned char *) p->virtual_roots,
01040             p->virtual_roots_count);
01041 }
01042 
01043 
01044 void NETRootInfo::closeWindowRequest(Window window) {
01045 
01046 #ifdef    NETWMDEBUG
01047     fprintf(stderr, "NETRootInfo::closeWindowRequest: requesting close for 0x%lx\n",
01048         window);
01049 #endif
01050 
01051     XEvent e;
01052 
01053     e.xclient.type = ClientMessage;
01054     e.xclient.message_type = net_close_window;
01055     e.xclient.display = p->display;
01056     e.xclient.window = window;
01057     e.xclient.format = 32;
01058     e.xclient.data.l[0] = 0l;
01059     e.xclient.data.l[1] = 0l;
01060     e.xclient.data.l[2] = 0l;
01061     e.xclient.data.l[3] = 0l;
01062     e.xclient.data.l[4] = 0l;
01063 
01064     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01065 }
01066 
01067 
01068 void NETRootInfo::moveResizeRequest(Window window, int x_root, int y_root,
01069                     Direction direction)
01070 {
01071 
01072 #ifdef    NETWMDEBUG
01073     fprintf(stderr,
01074         "NETRootInfo::moveResizeRequest: requesting resize/move for 0x%lx (%d, %d, %d)\n",
01075         window, x_root, y_root, direction);
01076 #endif
01077 
01078     XEvent e;
01079 
01080     e.xclient.type = ClientMessage;
01081     e.xclient.message_type = net_wm_moveresize;
01082     e.xclient.display = p->display;
01083     e.xclient.window = window,
01084     e.xclient.format = 32;
01085     e.xclient.data.l[0] = x_root;
01086     e.xclient.data.l[1] = y_root;
01087     e.xclient.data.l[2] = direction;
01088     e.xclient.data.l[3] = 0l;
01089     e.xclient.data.l[4] = 0l;
01090 
01091     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01092 }
01093 
01094 
01095 // assignment operator
01096 
01097 const NETRootInfo &NETRootInfo::operator=(const NETRootInfo &rootinfo) {
01098 
01099 #ifdef   NETWMDEBUG
01100     fprintf(stderr, "NETRootInfo::operator=()\n");
01101 #endif
01102 
01103     if (p != rootinfo.p) {
01104     refdec_nri(p);
01105 
01106     if (! p->ref) delete p;
01107     }
01108 
01109     p = rootinfo.p;
01110     role = rootinfo.role;
01111     p->ref++;
01112 
01113     return *this;
01114 }
01115 
01116 
01117 unsigned long NETRootInfo::event(XEvent *event) {
01118     unsigned long dirty = 0;
01119 
01120     // the window manager will be interested in client messages... no other
01121     // client should get these messages
01122     if (role == WindowManager && event->type == ClientMessage &&
01123     event->xclient.format == 32) {
01124 #ifdef    NETWMDEBUG
01125     fprintf(stderr, "NETRootInfo::event: handling ClientMessage event\n");
01126 #endif
01127 
01128     if (event->xclient.message_type == net_number_of_desktops) {
01129         dirty = NumberOfDesktops;
01130 
01131 #ifdef   NETWMDEBUG
01132         fprintf(stderr, "NETRootInfo::event: changeNumberOfDesktops(%ld)\n",
01133             event->xclient.data.l[0]);
01134 #endif
01135 
01136         changeNumberOfDesktops(event->xclient.data.l[0]);
01137     } else if (event->xclient.message_type == net_desktop_geometry) {
01138         dirty = DesktopGeometry;
01139 
01140         NETSize sz;
01141         sz.width = event->xclient.data.l[0];
01142         sz.height = event->xclient.data.l[1];
01143 
01144 #ifdef    NETWMDEBUG
01145         fprintf(stderr, "NETRootInfo::event: changeDesktopGeometry( -- , { %d, %d })\n",
01146             sz.width, sz.height);
01147 #endif
01148 
01149         changeDesktopGeometry(~0, sz);
01150     } else if (event->xclient.message_type == net_desktop_viewport) {
01151         dirty = DesktopViewport;
01152 
01153         NETPoint pt;
01154         pt.x = event->xclient.data.l[0];
01155         pt.y = event->xclient.data.l[1];
01156 
01157 #ifdef   NETWMDEBUG
01158         fprintf(stderr, "NETRootInfo::event: changeDesktopViewport(%d, { %d, %d })\n",
01159             p->current_desktop, pt.x, pt.y);
01160 #endif
01161 
01162         changeDesktopViewport(p->current_desktop, pt);
01163     } else if (event->xclient.message_type == net_current_desktop) {
01164         dirty = CurrentDesktop;
01165 
01166 #ifdef   NETWMDEBUG
01167         fprintf(stderr, "NETRootInfo::event: changeCurrentDesktop(%ld)\n",
01168             event->xclient.data.l[0] + 1);
01169 #endif
01170 
01171         changeCurrentDesktop(event->xclient.data.l[0] + 1);
01172     } else if (event->xclient.message_type == net_active_window) {
01173         dirty = ActiveWindow;
01174 
01175 #ifdef    NETWMDEBUG
01176         fprintf(stderr, "NETRootInfo::event: changeActiveWindow(0x%lx)\n",
01177             event->xclient.window);
01178 #endif
01179 
01180         changeActiveWindow(event->xclient.window);
01181     } else if (event->xclient.message_type == net_wm_moveresize) {
01182 
01183 #ifdef    NETWMDEBUG
01184         fprintf(stderr, "NETRootInfo::event: moveResize(%ld, %ld, %ld, %ld)\n",
01185             event->xclient.window,
01186             event->xclient.data.l[0],
01187             event->xclient.data.l[1],
01188             event->xclient.data.l[2]
01189             );
01190 #endif
01191 
01192         moveResize(event->xclient.window,
01193                event->xclient.data.l[0],
01194                event->xclient.data.l[1],
01195                event->xclient.data.l[2]);
01196     } else if (event->xclient.message_type == net_close_window) {
01197 
01198 #ifdef   NETWMDEBUG
01199         fprintf(stderr, "NETRootInfo::event: closeWindow(0x%lx)\n",
01200             event->xclient.window);
01201 #endif
01202 
01203         closeWindow(event->xclient.window);
01204     }
01205     }
01206 
01207     if (event->type == PropertyNotify) {
01208 
01209 #ifdef    NETWMDEBUG
01210     fprintf(stderr, "NETRootInfo::event: handling PropertyNotify event\n");
01211 #endif
01212 
01213     XEvent pe = *event;
01214 
01215     Bool done = False;
01216     Bool compaction = False;
01217     while (! done) {
01218 
01219 #ifdef   NETWMDEBUG
01220         fprintf(stderr, "NETRootInfo::event: loop fire\n");
01221 #endif
01222 
01223         if (pe.xproperty.atom == net_client_list)
01224         dirty |= ClientList;
01225         else if (pe.xproperty.atom == net_client_list_stacking)
01226         dirty |= ClientListStacking;
01227         else if (pe.xproperty.atom == kde_net_system_tray_windows)
01228         dirty |= KDESystemTrayWindows;
01229         else if (pe.xproperty.atom == net_desktop_names)
01230         dirty |= DesktopNames;
01231         else if (pe.xproperty.atom == net_workarea)
01232         dirty |= WorkArea;
01233         else if (pe.xproperty.atom == net_number_of_desktops)
01234         dirty |= NumberOfDesktops;
01235         else if (pe.xproperty.atom == net_desktop_geometry)
01236         dirty |= DesktopGeometry;
01237         else if (pe.xproperty.atom == net_desktop_viewport)
01238         dirty |= DesktopViewport;
01239         else if (pe.xproperty.atom == net_current_desktop)
01240         dirty |= CurrentDesktop;
01241         else if (pe.xproperty.atom == net_active_window)
01242         dirty |= ActiveWindow;
01243         else {
01244 
01245 #ifdef    NETWMDEBUG
01246         fprintf(stderr, "NETRootInfo::event: putting back event and breaking\n");
01247 #endif
01248 
01249         if ( compaction )
01250             XPutBackEvent(p->display, &pe);
01251         break;
01252         }
01253 
01254         if (XCheckTypedWindowEvent(p->display, p->root, PropertyNotify, &pe) )
01255         compaction = True;
01256         else
01257         break;
01258     }
01259 
01260     update(dirty & p->protocols);
01261     }
01262 
01263 #ifdef   NETWMDEBUG
01264     fprintf(stderr, "NETRootInfo::event: handled events, returning dirty = 0x%lx\n",
01265         dirty & p->protocols);
01266 #endif
01267 
01268     return dirty & p->protocols;
01269 }
01270 
01271 
01272 // private functions to update the data we keep
01273 
01274 void NETRootInfo::update(unsigned long dirty) {
01275     Atom type_ret;
01276     int format_ret;
01277     unsigned char *data_ret;
01278     unsigned long nitems_ret, unused;
01279 
01280     dirty &= p->protocols;
01281 
01282     if (dirty & ClientList) {
01283     if (XGetWindowProperty(p->display, p->root, net_client_list,
01284                    0l, (long) BUFSIZE, False, XA_WINDOW, &type_ret,
01285                    &format_ret, &nitems_ret, &unused, &data_ret)
01286         == Success) {
01287         if (type_ret == XA_WINDOW && format_ret == 32) {
01288         Window *wins = (Window *) data_ret;
01289 
01290         qsort(wins, nitems_ret, sizeof(Window), wcmp);
01291 
01292         if (p->clients) {
01293             if (role == Client) {
01294             unsigned long new_index = 0, old_index = 0;
01295             unsigned long new_count = nitems_ret,
01296                       old_count = p->clients_count;
01297 
01298             while (old_index < old_count || new_index < new_count) {
01299                 if (old_index == old_count) {
01300                 addClient(wins[new_index++]);
01301                 } else if (new_index == new_count) {
01302                 removeClient(p->clients[old_index++]);
01303                 } else {
01304                 if (p->clients[old_index] <
01305                     wins[new_index]) {
01306                     removeClient(p->clients[old_index++]);
01307                 } else if (wins[new_index] <
01308                        p->clients[old_index]) {
01309                     addClient(wins[new_index++]);
01310                 } else {
01311                     new_index++;
01312                     old_index++;
01313                 }
01314                 }
01315             }
01316             }
01317 
01318             delete [] p->clients;
01319         } else {
01320 #ifdef    NETWMDEBUG
01321             fprintf(stderr, "NETRootInfo::update: client list null, creating\n");
01322 #endif
01323 
01324             unsigned long n;
01325             for (n = 0; n < nitems_ret; n++) {
01326             addClient(wins[n]);
01327             }
01328         }
01329 
01330         p->clients_count = nitems_ret;
01331         p->clients = nwindup(wins, p->clients_count);
01332         }
01333 
01334 #ifdef    NETWMDEBUG
01335         fprintf(stderr, "NETRootInfo::update: client list updated (%ld clients)\n",
01336             p->clients_count);
01337 #endif
01338         if ( data_ret )
01339         XFree(data_ret);
01340     }
01341     }
01342 
01343     if (dirty & KDESystemTrayWindows) {
01344     if (XGetWindowProperty(p->display, p->root, kde_net_system_tray_windows,
01345                    0l, (long) BUFSIZE, False, XA_WINDOW, &type_ret,
01346                    &format_ret, &nitems_ret, &unused, &data_ret)
01347         == Success) {
01348         if (type_ret == XA_WINDOW && format_ret == 32) {
01349         Window *wins = (Window *) data_ret;
01350 
01351         qsort(wins, nitems_ret, sizeof(Window), wcmp);
01352 
01353         if (p->kde_system_tray_windows) {
01354             if (role == Client) {
01355             unsigned long new_index = 0, new_count = nitems_ret;
01356             unsigned long old_index = 0,
01357                       old_count = p->kde_system_tray_windows_count;
01358 
01359             while(old_index < old_count || new_index < new_count) {
01360                 if (old_index == old_count) {
01361                 addSystemTrayWin(wins[new_index++]);
01362                 } else if (new_index == new_count) {
01363                 removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
01364                 } else {
01365                 if (p->kde_system_tray_windows[old_index] <
01366                     wins[new_index]) {
01367                     removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
01368                 } else if (wins[new_index] <
01369                        p->kde_system_tray_windows[old_index]) {
01370                     addSystemTrayWin(wins[new_index++]);
01371                 } else {
01372                     new_index++;
01373                     old_index++;
01374                 }
01375                 }
01376             }
01377             }
01378 
01379         } else {
01380             unsigned long n;
01381             for (n = 0; n < nitems_ret; n++) {
01382             addSystemTrayWin(wins[n]);
01383             }
01384         }
01385 
01386         p->kde_system_tray_windows_count = nitems_ret;
01387         if (p->kde_system_tray_windows)
01388             delete [] p->kde_system_tray_windows;
01389         p->kde_system_tray_windows =
01390             nwindup(wins, p->kde_system_tray_windows_count);
01391         }
01392 
01393         if ( data_ret )
01394         XFree(data_ret);
01395     }
01396     }
01397 
01398     if (dirty & ClientListStacking) {
01399     if (XGetWindowProperty(p->display, p->root, net_client_list_stacking,
01400                    0, (long) BUFSIZE, False, XA_WINDOW, &type_ret,
01401                    &format_ret, &nitems_ret, &unused, &data_ret)
01402         == Success) {
01403         if (type_ret == XA_WINDOW && format_ret == 32) {
01404         Window *wins = (Window *) data_ret;
01405 
01406         if (p->stacking) {
01407             delete [] p->stacking;
01408         }
01409 
01410         p->stacking_count = nitems_ret;
01411         p->stacking = nwindup(wins, p->stacking_count);
01412         }
01413 
01414 #ifdef    NETWMDEBUG
01415         fprintf(stderr,"NETRootInfo::update: client stacking updated (%ld clients)\n",
01416             p->stacking_count);
01417 #endif
01418 
01419         if ( data_ret )
01420         XFree(data_ret);
01421     }
01422     }
01423 
01424     if (dirty & NumberOfDesktops) {
01425     p->number_of_desktops = 0;
01426 
01427     if (XGetWindowProperty(p->display, p->root, net_number_of_desktops,
01428                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
01429                    &nitems_ret, &unused, &data_ret)
01430         == Success) {
01431         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
01432         p->number_of_desktops = *((long *) data_ret);
01433         }
01434 
01435 #ifdef    NETWMDEBUG
01436         fprintf(stderr, "NETRootInfo::update: number of desktops = %d\n",
01437             p->number_of_desktops);
01438 #endif
01439         if ( data_ret )
01440         XFree(data_ret);
01441     }
01442     }
01443 
01444     if (dirty & DesktopGeometry) {
01445     if (XGetWindowProperty(p->display, p->root, net_desktop_geometry,
01446                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
01447                    &nitems_ret, &unused, &data_ret)
01448         == Success) {
01449         if (type_ret == XA_CARDINAL && format_ret == 32 &&
01450         nitems_ret == 2) {
01451         long *data = (long *) data_ret;
01452 
01453         p->geometry.width  = data[0];
01454         p->geometry.height = data[1];
01455 
01456 #ifdef    NETWMDEBUG
01457         fprintf(stderr, "NETRootInfo::update: desktop geometry updated\n");
01458 #endif
01459         }
01460         if ( data_ret )
01461         XFree(data_ret);
01462     }
01463     } else {
01464     // insurance
01465     p->geometry = p->rootSize;
01466     }
01467 
01468     if (dirty & DesktopViewport) {
01469     if (XGetWindowProperty(p->display, p->root, net_desktop_viewport,
01470                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
01471                    &nitems_ret, &unused, &data_ret)
01472         == Success) {
01473         if (type_ret == XA_CARDINAL && format_ret == 32 &&
01474         nitems_ret == 2) {
01475         long *data = (long *) data_ret;
01476 
01477         int d, i, n;
01478         n = nitems_ret / 2;
01479         for (d = 0, i = 0; d < n; d++) {
01480             p->viewport[d].x = data[i++];
01481             p->viewport[d].y = data[i++];
01482         }
01483 
01484 #ifdef    NETWMDEBUG
01485         fprintf(stderr,
01486             "NETRootInfo::update: desktop viewport array updated (%d entries)\n",
01487             p->viewport.size());
01488 
01489         if (nitems_ret % 2 != 0) {
01490             fprintf(stderr,
01491                 "NETRootInfo::update(): desktop viewport array "
01492                 "size not a multipe of 2\n");
01493         }
01494 #endif
01495         }
01496         if ( data_ret )
01497         XFree(data_ret);
01498     }
01499     } else {
01500     int i;
01501     for (i = 0; i < p->viewport.size(); i++) {
01502         p->viewport[i].x = p->viewport[i].y = 0;
01503     }
01504     }
01505 
01506     if (dirty & CurrentDesktop) {
01507     p->current_desktop = 0;
01508     if (XGetWindowProperty(p->display, p->root, net_current_desktop,
01509                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
01510                    &nitems_ret, &unused, &data_ret)
01511         == Success) {
01512         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
01513         p->current_desktop = *((long *) data_ret) + 1;
01514         }
01515 
01516 #ifdef    NETWMDEBUG
01517         fprintf(stderr, "NETRootInfo::update: current desktop = %d\n",
01518             p->current_desktop);
01519 #endif
01520         if ( data_ret )
01521         XFree(data_ret);
01522     }
01523     }
01524 
01525     if (dirty & DesktopNames) {
01526     if (XGetWindowProperty(p->display, p->root, net_desktop_names,
01527                    0l, (long) BUFSIZE, False, UTF8_STRING, &type_ret,
01528                    &format_ret, &nitems_ret, &unused, &data_ret)
01529         == Success) {
01530         if (type_ret == UTF8_STRING && format_ret == 8) {
01531         const char *d = (const char *) data_ret;
01532         unsigned int s, n, index;
01533 
01534         for (s = 0, n = 0, index = 0; n < nitems_ret; n++) {
01535             if (d[n] == '\0') {
01536             if (p->desktop_names[index])
01537                 delete [] p->desktop_names[index];
01538             p->desktop_names[index++] = nstrndup((d + s), n - s + 1);
01539             s = n + 1;
01540             }
01541         }
01542         }
01543 
01544 #ifdef    NETWMDEBUG
01545         fprintf(stderr, "NETRootInfo::update: desktop names array updated (%d entries)\n",
01546             p->desktop_names.size());
01547 #endif
01548         if ( data_ret )
01549         XFree(data_ret);
01550     }
01551     }
01552 
01553     if (dirty & ActiveWindow) {
01554     if (XGetWindowProperty(p->display, p->root, net_active_window, 0l, 1l,
01555                    False, XA_WINDOW, &type_ret, &format_ret,
01556                    &nitems_ret, &unused, &data_ret)
01557         == Success) {
01558         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
01559         p->active = *((Window *) data_ret);
01560         }
01561 
01562 #ifdef    NETWMDEBUG
01563         fprintf(stderr, "NETRootInfo::update: active window = 0x%lx\n",
01564             p->active);
01565 #endif
01566         if ( data_ret )
01567         XFree(data_ret);
01568     }
01569     }
01570 
01571     if (dirty & WorkArea) {
01572     if (XGetWindowProperty(p->display, p->root, net_workarea, 0l,
01573                    (p->number_of_desktops * 4), False, XA_CARDINAL,
01574                    &type_ret, &format_ret, &nitems_ret, &unused,
01575                    &data_ret)
01576         == Success) {
01577         if (type_ret == XA_CARDINAL && format_ret == 32 &&
01578         nitems_ret == (unsigned) (p->number_of_desktops * 4)) {
01579         long *d = (long *) data_ret;
01580         int i, j;
01581         for (i = 0, j = 0; i < p->number_of_desktops; i++) {
01582             p->workarea[i].pos.x       = d[j++];
01583             p->workarea[i].pos.y       = d[j++];
01584             p->workarea[i].size.width  = d[j++];
01585             p->workarea[i].size.height = d[j++];
01586         }
01587         }
01588 
01589 #ifdef    NETWMDEBUG
01590         fprintf(stderr, "NETRootInfo::update: work area array updated (%d entries)\n",
01591             p->workarea.size());
01592 #endif
01593         if ( data_ret )
01594         XFree(data_ret);
01595     }
01596     }
01597 
01598 
01599     if (dirty & SupportingWMCheck) {
01600     if (XGetWindowProperty(p->display, p->root, net_supporting_wm_check,
01601                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
01602                    &nitems_ret, &unused, &data_ret)
01603         == Success) {
01604         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
01605         p->supportwindow = *((Window *) data_ret);
01606 
01607         unsigned char *name_ret;
01608         if (XGetWindowProperty(p->display, p->supportwindow,
01609                        net_wm_name, 0l, (long) BUFSIZE, False,
01610                        UTF8_STRING, &type_ret, &format_ret,
01611                        &nitems_ret, &unused, &name_ret)
01612             == Success) {
01613             if (type_ret == UTF8_STRING && format_ret == 8)
01614             p->name = nstrndup((const char *) name_ret, nitems_ret);
01615 
01616             if ( name_ret )
01617             XFree(name_ret);
01618         }
01619         }
01620 
01621 #ifdef    NETWMDEBUG
01622         fprintf(stderr,
01623             "NETRootInfo::update: supporting window manager = '%s'\n",
01624             p->name);
01625 #endif
01626         if ( data_ret )
01627         XFree(data_ret);
01628     }
01629     }
01630 
01631     if (dirty & VirtualRoots) {
01632     if (XGetWindowProperty(p->display, p->root, net_virtual_roots,
01633                    0, (long) BUFSIZE, False, XA_WINDOW, &type_ret,
01634                    &format_ret, &nitems_ret, &unused, &data_ret)
01635         == Success) {
01636         if (type_ret == XA_WINDOW && format_ret == 32) {
01637         Window *wins = (Window *) data_ret;
01638 
01639         if (p->virtual_roots) {
01640             delete [] p->virtual_roots;
01641         }
01642 
01643         p->virtual_roots_count = nitems_ret;
01644         p->virtual_roots = nwindup(wins, p->virtual_roots_count);
01645         }
01646 
01647 #ifdef    NETWMDEBUG
01648         fprintf(stderr, "NETRootInfo::updated: virtual roots updated (%ld windows)\n",
01649             p->virtual_roots_count);
01650 #endif
01651         if ( data_ret )
01652         XFree(data_ret);
01653     }
01654     }
01655 }
01656 
01657 
01658 Display *NETRootInfo::x11Display() const {
01659     return p->display;
01660 }
01661 
01662 
01663 Window NETRootInfo::rootWindow() const {
01664     return p->root;
01665 }
01666 
01667 
01668 Window NETRootInfo::supportWindow() const {
01669     return p->supportwindow;
01670 }
01671 
01672 
01673 const char *NETRootInfo::wmName() const {
01674     return p->name; }
01675 
01676 
01677 int NETRootInfo::screenNumber() const {
01678     return p->screen;
01679 }
01680 
01681 
01682 unsigned long NETRootInfo::supported() const {
01683     return p->protocols;
01684 }
01685 
01686 
01687 const Window *NETRootInfo::clientList() const {
01688     return p->clients;
01689 }
01690 
01691 
01692 int NETRootInfo::clientListCount() const {
01693     return p->clients_count;
01694 }
01695 
01696 
01697 const Window *NETRootInfo::clientListStacking() const {
01698     return p->stacking;
01699 }
01700 
01701 
01702 int NETRootInfo::clientListStackingCount() const {
01703     return p->stacking_count;
01704 }
01705 
01706 
01707 const Window *NETRootInfo::kdeSystemTrayWindows() const {
01708     return p->kde_system_tray_windows;
01709 }
01710 
01711 
01712 int NETRootInfo::kdeSystemTrayWindowsCount() const {
01713     return p->kde_system_tray_windows_count;
01714 }
01715 
01716 
01717 NETSize NETRootInfo::desktopGeometry(int) const {
01718     return p->geometry;
01719 }
01720 
01721 
01722 NETPoint NETRootInfo::desktopViewport(int desktop) const {
01723     if (desktop < 1) {
01724     NETPoint pt;
01725     return pt;
01726     }
01727 
01728     return p->viewport[desktop - 1];
01729 }
01730 
01731 
01732 NETRect NETRootInfo::workArea(int desktop) const {
01733     if (desktop < 1) {
01734     NETRect rt;
01735     return rt;
01736     }
01737 
01738     return p->workarea[desktop - 1];
01739 }
01740 
01741 
01742 const char *NETRootInfo::desktopName(int desktop) const {
01743     if (desktop < 1) {
01744     return 0;
01745     }
01746 
01747     return p->desktop_names[desktop - 1];
01748 }
01749 
01750 
01751 const Window *NETRootInfo::virtualRoots( ) const {
01752     return p->virtual_roots;
01753 }
01754 
01755 
01756 int NETRootInfo::virtualRootsCount() const {
01757     return p->virtual_roots_count;
01758 }
01759 
01760 
01761 int NETRootInfo::numberOfDesktops() const {
01762   // XXX rikkus: correct fix ?
01763     return p->number_of_desktops == 0 ? 1 : p->number_of_desktops;
01764 }
01765 
01766 
01767 int NETRootInfo::currentDesktop() const {
01768     return p->current_desktop;
01769 }
01770 
01771 
01772 Window NETRootInfo::activeWindow() const {
01773     return p->active;
01774 }
01775 
01776 
01777 // NETWinInfo stuffs
01778 
01779 const int NETWinInfo::OnAllDesktops = (int) -1;
01780 
01781 NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
01782                unsigned long properties, Role role)
01783 {
01784 
01785 #ifdef   NETWMDEBUG
01786     fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
01787         (role == WindowManager) ? "WindowManager" : "Client");
01788 #endif
01789 
01790     p = new NETWinInfoPrivate;
01791     p->ref = 1;
01792 
01793     p->display = display;
01794     p->window = window;
01795     p->root = rootWindow;
01796     p->mapping_state = Withdrawn;
01797     p->mapping_state_dirty = True;
01798     p->state = 0;
01799     p->type = Unknown;
01800     p->name = (char *) 0;
01801     p->visible_name = (char *) 0;
01802     p->icon_name = (char *) 0;
01803     p->visible_icon_name = (char *) 0;
01804     p->desktop = p->pid = p->handled_icons = 0;
01805 
01806     // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
01807     // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
01808     // p->frame_strut.bottom = 0;
01809 
01810     p->kde_system_tray_win_for = 0;
01811 
01812     p->properties = properties;
01813     p->icon_count = 0;
01814 
01815     this->role = role;
01816 
01817     if (! netwm_atoms_created) create_atoms(p->display);
01818 
01819     if (p->properties) update(p->properties);
01820 }
01821 
01822 
01823 NETWinInfo::NETWinInfo(const NETWinInfo &wininfo) {
01824     p = wininfo.p;
01825     p->ref++;
01826 }
01827 
01828 
01829 NETWinInfo::~NETWinInfo() {
01830     refdec_nwi(p);
01831 
01832     if (! p->ref) delete p;
01833 }
01834 
01835 
01836 void NETWinInfo::setIcon(NETIcon icon, Bool replace) {
01837     if (role != Client) return;
01838 
01839     int proplen, i, sz, j;
01840 
01841     if (replace) {
01842 
01843     for (i = 0; i < p->icons.size(); i++) {
01844         if (p->icons[i].data) delete [] p->icons[i].data;
01845         p->icons[i].data = 0;
01846         p->icons[i].size.width = 0;
01847         p->icons[i].size.height = 0;
01848     }
01849 
01850     p->icon_count = 0;
01851     }
01852 
01853     // assign icon
01854     p->icons[p->icon_count] = icon;
01855     p->icon_count++;
01856 
01857     // do a deep copy, we want to own the data
01858     NETIcon &ni = p->icons[p->icon_count - 1];
01859     sz = ni.size.width * ni.size.height;
01860     CARD32 *d = new CARD32[sz];
01861     ni.data = (unsigned char *) d;
01862     memcpy(d, icon.data, sz * sizeof(CARD32));
01863 
01864     // compute property length
01865     for (i = 0, proplen = 0; i < p->icon_count; i++) {
01866     proplen += 2 + (p->icons[i].size.width *
01867             p->icons[i].size.height);
01868     }
01869 
01870     CARD32 *d32;
01871     long *prop = new long[proplen], *pprop = prop;
01872     for (i = 0; i < p->icon_count; i++) {
01873     // copy size into property
01874         *pprop++ = p->icons[i].size.width;
01875     *pprop++ = p->icons[i].size.height;
01876 
01877     // copy data into property
01878     sz = (p->icons[i].size.width * p->icons[i].size.height);
01879     d32 = (CARD32 *) p->icons[i].data;
01880     for (j = 0; j < sz; j++) *pprop++ = *d32++;
01881     }
01882 
01883     XChangeProperty(p->display, p->window, net_wm_icon, XA_CARDINAL, 32,
01884             PropModeReplace, (unsigned char *) prop, proplen);
01885 
01886     delete [] prop;
01887 }
01888 
01889 
01890 void NETWinInfo::setIconGeometry(NETRect geometry) {
01891     if (role != Client) return;
01892 
01893     p->icon_geom = geometry;
01894 
01895     long data[4];
01896     data[0] = geometry.pos.x;
01897     data[1] = geometry.pos.y;
01898     data[2] = geometry.size.width;
01899     data[3] = geometry.size.height;
01900 
01901     XChangeProperty(p->display, p->window, net_wm_icon_geometry, XA_CARDINAL,
01902             32, PropModeReplace, (unsigned char *) data, 4);
01903 }
01904 
01905 
01906 void NETWinInfo::setStrut(NETStrut strut) {
01907     if (role != Client) return;
01908 
01909     p->strut = strut;
01910 
01911     long data[4];
01912     data[0] = strut.left;
01913     data[1] = strut.right;
01914     data[2] = strut.top;
01915     data[3] = strut.bottom;
01916 
01917     XChangeProperty(p->display, p->window, net_wm_strut, XA_CARDINAL, 32,
01918             PropModeReplace, (unsigned char *) data, 4);
01919 }
01920 
01921 
01922 void NETWinInfo::setState(unsigned long state, unsigned long mask) {
01923     if (p->mapping_state_dirty)
01924     update(XAWMState);
01925 
01926     if (role == Client && p->mapping_state != Withdrawn) {
01927 
01928 #ifdef NETWMDEBUG
01929         fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n",
01930                 state, mask);
01931 #endif // NETWMDEBUG
01932 
01933     XEvent e;
01934     e.xclient.type = ClientMessage;
01935     e.xclient.message_type = net_wm_state;
01936     e.xclient.display = p->display;
01937     e.xclient.window = p->window;
01938     e.xclient.format = 32;
01939     e.xclient.data.l[3] = 0l;
01940     e.xclient.data.l[4] = 0l;
01941 
01942     if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
01943         e.xclient.data.l[0] = (state & Modal) ? 1 : 0;
01944         e.xclient.data.l[1] = net_wm_state_modal;
01945         e.xclient.data.l[2] = 0l;
01946 
01947         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01948     }
01949 
01950     if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
01951         e.xclient.data.l[0] = (state & Sticky) ? 1 : 0;
01952         e.xclient.data.l[1] = net_wm_state_sticky;
01953         e.xclient.data.l[2] = 0l;
01954 
01955         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01956     }
01957 
01958     if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) {
01959 
01960         unsigned long wishstate = (p->state & ~mask) | (state & mask);
01961         if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) )
01962          && ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) {
01963         if ( (wishstate & Max) == Max ) {
01964             e.xclient.data.l[0] = 1;
01965             e.xclient.data.l[1] = net_wm_state_max_horiz;
01966             e.xclient.data.l[2] = net_wm_state_max_vert;
01967             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01968         } else if ( (wishstate & Max) == 0 ) {
01969             e.xclient.data.l[0] = 0;
01970             e.xclient.data.l[1] = net_wm_state_max_horiz;
01971             e.xclient.data.l[2] = net_wm_state_max_vert;
01972             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01973         } else {
01974             e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
01975             e.xclient.data.l[1] = net_wm_state_max_horiz;
01976             e.xclient.data.l[2] = 0;
01977             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01978             e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
01979             e.xclient.data.l[1] = net_wm_state_max_vert;
01980             e.xclient.data.l[2] = 0;
01981             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01982         }
01983         } else  if ( (wishstate & MaxVert) != (p->state & MaxVert) ) {
01984         e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
01985         e.xclient.data.l[1] = net_wm_state_max_vert;
01986         e.xclient.data.l[2] = 0;
01987         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01988         } else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) {
01989         e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
01990         e.xclient.data.l[1] = net_wm_state_max_horiz;
01991         e.xclient.data.l[2] = 0;
01992         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01993         }
01994     }
01995 
01996     if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
01997         e.xclient.data.l[0] = (state & Shaded) ? 1 : 0;
01998         e.xclient.data.l[1] = net_wm_state_shaded;
01999         e.xclient.data.l[2] = 0l;
02000 
02001         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02002     }
02003 
02004     if ((mask & SkipTaskbar) &&
02005         ((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
02006         e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0;
02007         e.xclient.data.l[1] = net_wm_state_skip_taskbar;
02008         e.xclient.data.l[2] = 0l;
02009 
02010         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02011     }
02012 
02013         if ((mask & SkipPager) &&
02014         ((p->state & SkipPager) != (state & SkipPager))) {
02015             e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0;
02016             e.xclient.data.l[1] = net_wm_state_skip_pager;
02017             e.xclient.data.l[2] = 0l;
02018 
02019             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02020         }
02021 
02022     if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) {
02023         e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0;
02024         e.xclient.data.l[1] = net_wm_state_stays_on_top;
02025         e.xclient.data.l[2] = 0l;
02026 
02027         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02028     }
02029     } else {
02030     p->state &= ~mask;
02031     p->state |= state;
02032 
02033     long data[8];
02034     int count = 0;
02035 
02036     // hints
02037     if (p->state & Modal) data[count++] = net_wm_state_modal;
02038     if (p->state & MaxVert) data[count++] = net_wm_state_max_vert;
02039     if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz;
02040     if (p->state & Shaded) data[count++] = net_wm_state_shaded;
02041 
02042     // policy
02043     if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top;
02044     if (p->state & Sticky) data[count++] = net_wm_state_sticky;
02045     if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar;
02046     if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager;
02047 
02048 #ifdef NETWMDEBUG
02049     fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
02050     for (int i = 0; i < count; i++)
02051         fprintf(stderr, "NETWinInfo::setState:   state %ld '%s'\n",
02052             data[i], XGetAtomName(p->display, (Atom) data[i]));
02053 #endif
02054 
02055     XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32,
02056             PropModeReplace, (unsigned char *) data, count);
02057     }
02058 }
02059 
02060 
02061 void NETWinInfo::setWindowType(WindowType type) {
02062     if (role != Client) return;
02063 
02064     int len;
02065     long data[2];
02066 
02067     switch (type) {
02068     case Override:
02069     // spec extension: override window type.  we must comply with the spec
02070     // and provide a fall back (normal seems best)
02071     data[0] = kde_net_wm_window_type_override;
02072     data[1] = net_wm_window_type_normal;
02073     len = 2;
02074     break;
02075 
02076     case  Dialog:
02077     data[0] = net_wm_window_type_dialog;
02078     data[1] = None;
02079     len = 1;
02080     break;
02081 
02082     case Menu:
02083     data[0] = net_wm_window_type_menu;
02084     data[1] = None;
02085     len = 1;
02086     break;
02087 
02088     case TopMenu:
02089     // spec extension: override window type.  we must comply with the spec
02090     // and provide a fall back (dock seems best)
02091     data[0] = kde_net_wm_window_type_topmenu;
02092     data[1] = net_wm_window_type_dock;
02093     len = 2;
02094     break;
02095 
02096     case Tool:
02097     data[0] = net_wm_window_type_toolbar;
02098     data[1] = None;
02099     len = 1;
02100     break;
02101 
02102     case Dock:
02103     data[0] = net_wm_window_type_dock;
02104     data[1] = None;
02105     len = 1;
02106     break;
02107 
02108     case Desktop:
02109     data[0] = net_wm_window_type_desktop;
02110     data[1] = None;
02111     len = 1;
02112     break;
02113 
02114     default:
02115     case Normal:
02116     data[0] = net_wm_window_type_normal;
02117     data[1] = None;
02118     len = 1;
02119     break;
02120     }
02121 
02122     XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32,
02123             PropModeReplace, (unsigned char *) &data, len);
02124 }
02125 
02126 
02127 void NETWinInfo::setName(const char *name) {
02128     if (role != Client) return;
02129 
02130     if (p->name) delete [] p->name;
02131     p->name = nstrdup(name);
02132     XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8,
02133             PropModeReplace, (unsigned char *) p->name,
02134             strlen(p->name));
02135 }
02136 
02137 
02138 void NETWinInfo::setVisibleName(const char *visibleName) {
02139     if (role != WindowManager) return;
02140 
02141     if (p->visible_name) delete [] p->visible_name;
02142     p->visible_name = nstrdup(visibleName);
02143     XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8,
02144             PropModeReplace, (unsigned char *) p->visible_name,
02145             strlen(p->visible_name));
02146 }
02147 
02148 
02149 void NETWinInfo::setIconName(const char *iconName) {
02150     if (role != Client) return;
02151 
02152     if (p->icon_name) delete [] p->icon_name;
02153     p->icon_name = nstrdup(iconName);
02154     XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8,
02155             PropModeReplace, (unsigned char *) p->icon_name,
02156             strlen(p->icon_name));
02157 }
02158 
02159 
02160 void NETWinInfo::setVisibleIconName(const char *visibleIconName) {
02161     if (role != WindowManager) return;
02162 
02163     if (p->visible_icon_name) delete [] p->visible_icon_name;
02164     p->visible_icon_name = nstrdup(visibleIconName);
02165     XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8,
02166             PropModeReplace, (unsigned char *) p->visible_icon_name,
02167             strlen(p->visible_icon_name));
02168 }
02169 
02170 
02171 void NETWinInfo::setDesktop(int desktop) {
02172     if (p->mapping_state_dirty)
02173     update(XAWMState);
02174 
02175     if (role == Client && p->mapping_state != Withdrawn) {
02176     // we only send a ClientMessage if we are 1) a client and 2) managed
02177 
02178     if ( desktop == 0 )
02179         return; // we can't do that while being managed
02180 
02181     XEvent e;
02182 
02183     e.xclient.type = ClientMessage;
02184     e.xclient.message_type = net_wm_desktop;
02185     e.xclient.display = p->display;
02186     e.xclient.window = p->window;
02187     e.xclient.format = 32;
02188     e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1;
02189     e.xclient.data.l[1] = 0l;
02190     e.xclient.data.l[2] = 0l;
02191     e.xclient.data.l[3] = 0l;
02192     e.xclient.data.l[4] = 0l;
02193 
02194     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02195     } else {
02196     // otherwise we just set or remove the property directly
02197     p->desktop = desktop;
02198     long d = desktop;
02199 
02200     if ( d != OnAllDesktops ) {
02201         if ( d == 0 ) {
02202         XDeleteProperty( p->display, p->window, net_wm_desktop );
02203         return;
02204         }
02205 
02206         d -= 1;
02207     }
02208 
02209     XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32,
02210             PropModeReplace, (unsigned char *) &d, 1);
02211     }
02212 }
02213 
02214 
02215 void NETWinInfo::setPid(int pid) {
02216     if (role != Client) return;
02217 
02218     p->pid = pid;
02219     long d = pid;
02220     XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32,
02221             PropModeReplace, (unsigned char *) &d, 1);
02222 }
02223 
02224 
02225 void NETWinInfo::setHandledIcons(Bool handled) {
02226     if (role != Client) return;
02227 
02228     p->handled_icons = handled;
02229     long d = handled;
02230     XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32,
02231             PropModeReplace, (unsigned char *) &d, 1);
02232 }
02233 
02234 
02235 void NETWinInfo::setKDESystemTrayWinFor(Window window) {
02236     if (role != Client) return;
02237 
02238     p->kde_system_tray_win_for = window;
02239     XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
02240             XA_WINDOW, 32, PropModeReplace,
02241             (unsigned char *) &(p->kde_system_tray_win_for), 1);
02242 }
02243 
02244 
02245 void NETWinInfo::setKDEFrameStrut(NETStrut strut) {
02246     if (role != WindowManager) return;
02247 
02248     p->frame_strut = strut;
02249 
02250     long d[4];
02251     d[0] = strut.left;
02252     d[1] = strut.right;
02253     d[2] = strut.top;
02254     d[3] = strut.bottom;
02255 
02256     XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32,
02257             PropModeReplace, (unsigned char *) d, 4);
02258 }
02259 
02260 
02261 void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) {
02262     if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
02263     Window unused;
02264     int x, y;
02265     unsigned int w, h, junk;
02266     XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk);
02267     XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused
02268                   );
02269 
02270     p->win_geom.pos.x = x;
02271     p->win_geom.pos.y = y;
02272 
02273     p->win_geom.size.width = w;
02274     p->win_geom.size.height = h;
02275     }
02276 
02277     window = p->win_geom;
02278 
02279     frame.pos.x = window.pos.x - p->frame_strut.left;
02280     frame.pos.y = window.pos.y - p->frame_strut.top;
02281     frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
02282     frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
02283 }
02284 
02285 
02286 NETIcon NETWinInfo::icon(int width, int height) const {
02287     NETIcon result;
02288 
02289     if ( !p->icons.size() ) {
02290     result.size.width = 0;
02291     result.size.height = 0;
02292     result.data = 0;
02293     return result;
02294     }
02295 
02296     result = p->icons[0];
02297 
02298     // find the icon that's closest in size to w x h...
02299     // return the first icon if w and h are -1
02300     if (width == height && height == -1) return result;
02301 
02302     int i;
02303     for (i = 0; i < p->icons.size(); i++) {
02304     if ((p->icons[i].size.width >= width &&
02305          p->icons[i].size.width < result.size.width) &&
02306         (p->icons[i].size.height >= height &&
02307          p->icons[i].size.height < result.size.height))
02308         result = p->icons[i];
02309     }
02310 
02311     return result;
02312 }
02313 
02314 
02315 unsigned long NETWinInfo::event(XEvent *event) {
02316     unsigned long dirty = 0;
02317 
02318     if (role == WindowManager && event->type == ClientMessage &&
02319     event->xclient.format == 32) {
02320 
02321 #ifdef NETWMDEBUG
02322         fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
02323 #endif // NETWMDEBUG
02324 
02325     if (event->xclient.message_type == net_wm_state) {
02326         dirty = WMState;
02327 
02328         // we need to generate a change mask
02329 
02330 #ifdef NETWMDEBUG
02331         fprintf(stderr,
02332             "NETWinInfo::event: state client message, getting new state/mask\n");
02333 #endif
02334 
02335         int i;
02336         long state = 0, mask = 0;
02337 
02338         for (i = 1; i < 3; i++) {
02339 #ifdef NETWMDEBUG
02340         fprintf(stderr, "NETWinInfo::event:  message %ld '%s'\n",
02341             event->xclient.data.l[i],
02342             XGetAtomName(p->display, (Atom) event->xclient.data.l[i]));
02343 #endif
02344 
02345         if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
02346             mask |= Modal;
02347         else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
02348             mask |= Sticky;
02349         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
02350             mask |= MaxVert;
02351         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
02352             mask |= MaxHoriz;
02353         else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
02354             mask |= Shaded;
02355         else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
02356             mask |= SkipTaskbar;
02357                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
02358             mask |= SkipPager;
02359         else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
02360             mask |= StaysOnTop;
02361         }
02362 
02363         // when removing, we just leave newstate == 0
02364         switch (event->xclient.data.l[0]) {
02365         case 1: // set
02366         // to set... the change state should be the same as the mask
02367         state = mask;
02368         break;
02369 
02370         case 2: // toggle
02371         // to toggle, we need to xor the current state with the new state
02372         state = (p->state & mask) ^ mask;
02373         break;
02374 
02375         default:
02376         // to clear state, the new state should stay zero
02377         ;
02378         }
02379 
02380 #ifdef NETWMDEBUG
02381         fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
02382             state, mask);
02383 #endif
02384 
02385         changeState(state, mask);
02386     } else if (event->xclient.message_type == net_wm_desktop) {
02387         dirty = WMDesktop;
02388 
02389         if( event->xclient.data.l[0] == OnAllDesktops )
02390         changeDesktop( OnAllDesktops );
02391         else
02392             changeDesktop(event->xclient.data.l[0] + 1);
02393     }
02394     }
02395 
02396     if (event->type == PropertyNotify) {
02397 
02398 #ifdef    NETWMDEBUG
02399     fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
02400 #endif
02401 
02402     XEvent pe = *event;
02403 
02404     Bool done = False;
02405     Bool compaction = False;
02406     while (! done) {
02407 
02408 #ifdef    NETWMDEBUG
02409         fprintf(stderr, "NETWinInfo::event: loop fire\n");
02410 #endif
02411 
02412         if (pe.xproperty.atom == net_wm_name)
02413         dirty |= WMName;
02414         else if (pe.xproperty.atom == net_wm_visible_name)
02415         dirty |= WMVisibleName;
02416         else if (pe.xproperty.atom == net_wm_window_type)
02417         dirty |=WMWindowType;
02418         else if (pe.xproperty.atom == net_wm_strut)
02419         dirty |= WMStrut;
02420         else if (pe.xproperty.atom == net_wm_icon_geometry)
02421         dirty |= WMIconGeometry;
02422         else if (pe.xproperty.atom == net_wm_icon)
02423         dirty |= WMIcon;
02424         else if (pe.xproperty.atom == xa_wm_state)
02425         dirty |= XAWMState;
02426         else if (pe.xproperty.atom == net_wm_state)
02427         dirty |= WMState;
02428         else if (pe.xproperty.atom == net_wm_desktop)
02429         dirty |= WMDesktop;
02430         else if (pe.xproperty.atom == kde_net_wm_frame_strut)
02431         dirty |= WMKDEFrameStrut;
02432         else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
02433         dirty |= WMKDESystemTrayWinFor;
02434         else {
02435 
02436 #ifdef    NETWMDEBUG
02437         fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
02438 #endif
02439 
02440         if ( compaction )
02441             XPutBackEvent(p->display, &pe);
02442         break;
02443         }
02444 
02445         if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
02446         compaction = True;
02447         else
02448         break;
02449     }
02450 
02451     update(dirty);
02452     } else if (event->type == ConfigureNotify) {
02453 
02454 #ifdef NETWMDEBUG
02455     fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
02456 #endif
02457 
02458     dirty |= WMGeometry;
02459 
02460     // update window geometry
02461     p->win_geom.pos.x = event->xconfigure.x;
02462     p->win_geom.pos.y = event->xconfigure.y;
02463     p->win_geom.size.width = event->xconfigure.width;
02464     p->win_geom.size.height = event->xconfigure.height;
02465     }
02466 
02467     return dirty;
02468 }
02469 
02470 
02471 void NETWinInfo::update(unsigned long dirty) {
02472     Atom type_ret;
02473     int format_ret;
02474     unsigned long nitems_ret, unused;
02475     unsigned char *data_ret;
02476 
02477     if (dirty & XAWMState) {
02478     if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
02479                    False, xa_wm_state, &type_ret, &format_ret,
02480                    &nitems_ret, &unused, &data_ret)
02481         == Success) {
02482         if (type_ret == xa_wm_state && format_ret == 32 &&
02483         nitems_ret == 1) {
02484         long *state = (long *) data_ret;
02485 
02486         switch(*state) {
02487             case IconicState:
02488             p->mapping_state = Iconic;
02489             break;
02490             case WithdrawnState:
02491             p->mapping_state = Withdrawn;
02492             break;
02493             case NormalState:
02494             default:
02495             p->mapping_state = Visible;
02496 
02497         }
02498 
02499         p->mapping_state_dirty = False;
02500         }
02501         if ( data_ret )
02502         XFree(data_ret);
02503     }
02504     }
02505 
02506     // we do this here because we *always* want to update WM_STATE
02507     dirty &= p->properties;
02508 
02509     if (dirty & WMState) {
02510     p->state = 0;
02511     if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
02512                    False, XA_ATOM, &type_ret, &format_ret,
02513                    &nitems_ret, &unused, &data_ret)
02514         == Success) {
02515         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
02516         // determine window state
02517 #ifdef NETWMDEBUG
02518         fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
02519             nitems_ret);
02520 #endif
02521 
02522         long *states = (long *) data_ret;
02523         unsigned long count;
02524 
02525         for (count = 0; count < nitems_ret; count++) {
02526 #ifdef NETWMDEBUG
02527             fprintf(stderr,
02528                 "NETWinInfo::update:   adding window state %ld '%s'\n",
02529                 states[count],
02530                 XGetAtomName(p->display, (Atom) states[count]));
02531 #endif
02532 
02533             if ((Atom) states[count] == net_wm_state_modal)
02534             p->state |= Modal;
02535             else if ((Atom) states[count] == net_wm_state_sticky)
02536             p->state |= Sticky;
02537             else if ((Atom) states[count] == net_wm_state_max_vert)
02538             p->state |= MaxVert;
02539             else if ((Atom) states[count] == net_wm_state_max_horiz)
02540             p->state |= MaxHoriz;
02541             else if ((Atom) states[count] == net_wm_state_shaded)
02542             p->state |= Shaded;
02543             else if ((Atom) states[count] == net_wm_state_skip_taskbar)
02544             p->state |= SkipTaskbar;
02545             else if ((Atom) states[count] == net_wm_state_skip_pager)
02546             p->state |= SkipPager;
02547             else if ((Atom) states[count] == net_wm_state_stays_on_top)
02548             p->state |= StaysOnTop;
02549         }
02550         }
02551         if ( data_ret )
02552         XFree(data_ret);
02553     }
02554     }
02555 
02556     if (dirty & WMDesktop) {
02557     p->desktop = 0;
02558     if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
02559                    False, XA_CARDINAL, &type_ret,
02560                    &format_ret, &nitems_ret,
02561                    &unused, &data_ret)
02562         == Success) {
02563         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02564         nitems_ret == 1) {
02565         p->desktop = *((long *) data_ret);
02566         if ((signed) p->desktop != OnAllDesktops)
02567             p->desktop++;
02568 
02569         if ( p->desktop == 0 )
02570             p->desktop = OnAllDesktops;
02571         }
02572         if ( data_ret )
02573         XFree(data_ret);
02574     }
02575     }
02576 
02577     if (dirty & WMName) {
02578     if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
02579                    (long) BUFSIZE, False, UTF8_STRING, &type_ret,
02580                    &format_ret, &nitems_ret, &unused, &data_ret)
02581         == Success) {
02582         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
02583         if (p->name) delete [] p->name;
02584         p->name = nstrndup((const char *) data_ret, nitems_ret);
02585         }
02586 
02587         if( data_ret )
02588         XFree(data_ret);
02589     }
02590     }
02591 
02592     if (dirty & WMVisibleName) {
02593     if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
02594                    (long) BUFSIZE, False, UTF8_STRING, &type_ret,
02595                    &format_ret, &nitems_ret, &unused, &data_ret)
02596         == Success) {
02597         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
02598         if (p->visible_name) delete [] p->visible_name;
02599         p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
02600         }
02601 
02602         if( data_ret )
02603         XFree(data_ret);
02604     }
02605     }
02606 
02607     if (dirty & WMIconName) {
02608 
02609     char* text_ret = 0;
02610     if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
02611                    (long) BUFSIZE, False, UTF8_STRING, &type_ret,
02612                    &format_ret, &nitems_ret, &unused, &data_ret)
02613         == Success) {
02614         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
02615         if (p->icon_name) delete [] p->icon_name;
02616         p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
02617         }
02618 
02619         if( data_ret )
02620         XFree(data_ret);
02621     }
02622 
02623     if ( !p->visible_icon_name &&  XGetIconName(p->display, p->window, &text_ret) ) {
02624         if (p->icon_name) delete [] p->icon_name;
02625         p->icon_name = strdup((const char *) text_ret);
02626 
02627         if( text_ret )
02628         XFree(text_ret);
02629     }
02630     }
02631 
02632     if (dirty & WMVisibleIconName)
02633     {
02634     char* text_ret = 0;
02635     if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
02636                    (long) BUFSIZE, False, UTF8_STRING, &type_ret,
02637                    &format_ret, &nitems_ret, &unused, &data_ret)
02638         == Success) {
02639         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
02640         if (p->visible_icon_name) delete [] p->visible_icon_name;
02641         p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
02642         }
02643 
02644         if( data_ret )
02645         XFree(data_ret);
02646     }
02647 
02648 
02649     if ( !p->visible_icon_name && XGetIconName(p->display, p->window, &text_ret) ) {
02650         if (p->visible_icon_name) delete [] p->visible_icon_name;
02651         p->visible_icon_name = strdup((const char *) text_ret);
02652 
02653         if( text_ret )
02654         XFree(text_ret);
02655     }
02656     }
02657 
02658     if (dirty & WMWindowType) {
02659     p->type = Unknown;
02660     if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
02661                    False, XA_ATOM, &type_ret, &format_ret,
02662                    &nitems_ret, &unused, &data_ret)
02663         == Success) {
02664         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
02665         // determine the window type
02666 #ifdef NETWMDEBUG
02667         fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
02668             nitems_ret);
02669 #endif
02670 
02671         unsigned long count = 0;
02672         long *types = (long *) data_ret;
02673 
02674         while (p->type == Unknown && count < nitems_ret) {
02675             // check the types for the types we know about... types[count] is
02676             // not known, p->type is unchanged (Unknown)
02677 
02678 #ifdef NETWMDEBUG
02679             fprintf(stderr,
02680                 "NETWinInfo::update:   examining window type %ld %s\n",
02681                 types[count],
02682                 XGetAtomName(p->display, (Atom) types[count]));
02683 #endif
02684 
02685             if ((Atom) types[count] == net_wm_window_type_normal)
02686             p->type = Normal;
02687             else if ((Atom) types[count] == net_wm_window_type_desktop)
02688             p->type = Desktop;
02689             else if ((Atom) types[count] == net_wm_window_type_dock)
02690             p->type = Dock;
02691             else if ((Atom) types[count] == net_wm_window_type_toolbar)
02692             p->type = Tool;
02693             else if ((Atom) types[count] == net_wm_window_type_menu)
02694             p->type = Menu;
02695             else if ((Atom) types[count] == net_wm_window_type_dialog)
02696             p->type = Dialog;
02697             else if ((Atom) types[count] == kde_net_wm_window_type_override)
02698             p->type = Override;
02699             else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
02700             p->type = TopMenu;
02701 
02702             count++;
02703         }
02704         }
02705 
02706         if ( data_ret )
02707         XFree(data_ret);
02708     }
02709     }
02710 
02711     if (dirty & WMStrut) {
02712     if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
02713                    False, XA_CARDINAL, &type_ret, &format_ret,
02714                    &nitems_ret, &unused, &data_ret)
02715         == Success) {
02716         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02717         nitems_ret == 4) {
02718         long *d = (long *) data_ret;
02719         p->strut.left   = d[0];
02720         p->strut.right  = d[1];
02721         p->strut.top    = d[2];
02722         p->strut.bottom = d[3];
02723         }
02724         if ( data_ret )
02725         XFree(data_ret);
02726     }
02727     }
02728 
02729     if (dirty & WMIconGeometry) {
02730     if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
02731                    False, XA_CARDINAL, &type_ret, &format_ret,
02732                    &nitems_ret, &unused, &data_ret)
02733         == Success) {
02734         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02735         nitems_ret == 4) {
02736         long *d = (long *) data_ret;
02737         p->icon_geom.pos.x       = d[0];
02738         p->icon_geom.pos.y       = d[1];
02739         p->icon_geom.size.width  = d[2];
02740         p->icon_geom.size.height = d[3];
02741         }
02742         if ( data_ret )
02743         XFree(data_ret);
02744     }
02745     }
02746 
02747     if (dirty & WMIcon) {
02748     readIcon(p);
02749     }
02750 
02751     if (dirty & WMKDESystemTrayWinFor) {
02752     p->kde_system_tray_win_for = 0;
02753     if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
02754                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
02755                    &nitems_ret, &unused, &data_ret)
02756         == Success) {
02757         if (type_ret == XA_WINDOW && format_ret == 32 &&
02758         nitems_ret == 1) {
02759         p->kde_system_tray_win_for = *((Window *) data_ret);
02760         if ( p->kde_system_tray_win_for == 0 )
02761             p->kde_system_tray_win_for = p->root;
02762         }
02763         if ( data_ret )
02764         XFree(data_ret);
02765         }
02766     }
02767 
02768     if (dirty & WMKDEFrameStrut) {
02769     if (XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
02770                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
02771                    &nitems_ret, &unused, &data_ret) == Success) {
02772         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
02773         long *d = (long *) data_ret;
02774 
02775         p->frame_strut.left   = d[0];
02776         p->frame_strut.right  = d[1];
02777         p->frame_strut.top    = d[2];
02778         p->frame_strut.bottom = d[3];
02779         }
02780         if ( data_ret )
02781         XFree(data_ret);
02782     }
02783     }
02784 
02785     if (dirty & WMPid) {
02786     p->pid = 0;
02787     if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
02788                    False, XA_CARDINAL, &type_ret, &format_ret,
02789                    &nitems_ret, &unused, &data_ret) == Success) {
02790         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
02791         p->pid = *((long *) data_ret);
02792         }
02793         if ( data_ret )
02794         XFree(data_ret);
02795     }
02796     }
02797 }
02798 
02799 
02800 NETRect NETWinInfo::iconGeometry() const {
02801     return p->icon_geom;
02802 }
02803 
02804 
02805 unsigned long NETWinInfo::state() const {
02806     return p->state;
02807 }
02808 
02809 
02810 NETStrut NETWinInfo::strut() const {
02811     return p->strut;
02812 }
02813 
02814 
02815 NET::WindowType NETWinInfo::windowType() const {
02816     return p->type;
02817 }
02818 
02819 
02820 const char *NETWinInfo::name() const {
02821     return p->name;
02822 }
02823 
02824 
02825 const char *NETWinInfo::visibleName() const {
02826     return p->visible_name;
02827 }
02828 
02829 
02830 const char *NETWinInfo::iconName() const {
02831     return p->icon_name;
02832 }
02833 
02834 
02835 const char *NETWinInfo::visibleIconName() const {
02836     return p->visible_icon_name;
02837 }
02838 
02839 
02840 int NETWinInfo::desktop() const {
02841     return p->desktop;
02842 }
02843 
02844 int NETWinInfo::pid() const {
02845     return p->pid;
02846 }
02847 
02848 
02849 Bool NETWinInfo::handledIcons() const {
02850     return p->handled_icons;
02851 }
02852 
02853 
02854 Window NETWinInfo::kdeSystemTrayWinFor() const {
02855     return p->kde_system_tray_win_for;
02856 }
02857 
02858 
02859 unsigned long NETWinInfo::properties() const {
02860     return p->properties;
02861 }
02862 
02863 
02864 NET::MappingState NETWinInfo::mappingState() const {
02865     return p->mapping_state;
02866 }
02867 
02868 void NETRootInfo::virtual_hook( int, void* )
02869 { /*BASE::virtual_hook( id, data );*/ }
02870 
02871 void NETWinInfo::virtual_hook( int, void* )
02872 { /*BASE::virtual_hook( id, data );*/ }
02873 
02874 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:20:43 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001