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