netwm.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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

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