kdecore Library API Documentation

netwm.cpp

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