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