00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #include <qwidget.h>
00029 #ifdef Q_WS_X11 //FIXME
00030 
00031 #include "netwm.h"
00032 
00033 #include <string.h>
00034 #include <stdio.h>
00035 #include <assert.h>
00036 #include <stdlib.h>
00037 
00038 #include <X11/Xmd.h>
00039 
00040 #include "netwm_p.h"
00041 
00042 
00043 static Atom UTF8_STRING = 0;
00044 
00045 
00046 static Atom net_supported            = 0;
00047 static Atom net_client_list          = 0;
00048 static Atom net_client_list_stacking = 0;
00049 static Atom net_desktop_geometry     = 0;
00050 static Atom net_desktop_viewport     = 0;
00051 static Atom net_current_desktop      = 0;
00052 static Atom net_desktop_names        = 0;
00053 static Atom net_number_of_desktops   = 0;
00054 static Atom net_active_window        = 0;
00055 static Atom net_workarea             = 0;
00056 static Atom net_supporting_wm_check  = 0;
00057 static Atom net_virtual_roots        = 0;
00058 
00059 
00060 static Atom net_close_window         = 0;
00061 static Atom net_restack_window         = 0;
00062 static Atom net_wm_moveresize        = 0;
00063 static Atom net_moveresize_window    = 0;
00064 
00065 
00066 static Atom net_wm_name              = 0;
00067 static Atom net_wm_visible_name      = 0;
00068 static Atom net_wm_icon_name         = 0;
00069 static Atom net_wm_visible_icon_name = 0;
00070 static Atom net_wm_desktop           = 0;
00071 static Atom net_wm_window_type       = 0;
00072 static Atom net_wm_state             = 0;
00073 static Atom net_wm_strut             = 0;
00074 static Atom net_wm_icon_geometry     = 0;
00075 static Atom net_wm_icon              = 0;
00076 static Atom net_wm_pid               = 0;
00077 static Atom net_wm_user_time         = 0;
00078 static Atom net_wm_handled_icons     = 0;
00079 static Atom net_startup_id           = 0;
00080 static Atom net_wm_allowed_actions   = 0;
00081 
00082 
00083 static Atom kde_net_system_tray_windows       = 0;
00084 static Atom kde_net_wm_system_tray_window_for = 0;
00085 static Atom kde_net_wm_frame_strut            = 0;
00086 static Atom kde_net_wm_window_type_override   = 0;
00087 static Atom kde_net_wm_window_type_topmenu    = 0;
00088 
00089 
00090 static Atom wm_protocols = 0;
00091 static Atom net_wm_ping = 0;
00092 
00093 
00094 static Atom net_wm_window_type_normal  = 0;
00095 static Atom net_wm_window_type_desktop = 0;
00096 static Atom net_wm_window_type_dock    = 0;
00097 static Atom net_wm_window_type_toolbar = 0;
00098 static Atom net_wm_window_type_menu    = 0;
00099 static Atom net_wm_window_type_dialog  = 0;
00100 static Atom net_wm_window_type_utility = 0;
00101 static Atom net_wm_window_type_splash  = 0;
00102 
00103 
00104 static Atom net_wm_state_modal        = 0;
00105 static Atom net_wm_state_sticky       = 0;
00106 static Atom net_wm_state_max_vert     = 0;
00107 static Atom net_wm_state_max_horiz    = 0;
00108 static Atom net_wm_state_shaded       = 0;
00109 static Atom net_wm_state_skip_taskbar = 0;
00110 static Atom net_wm_state_skip_pager   = 0;
00111 static Atom net_wm_state_hidden       = 0;
00112 static Atom net_wm_state_fullscreen   = 0;
00113 static Atom net_wm_state_above        = 0;
00114 static Atom net_wm_state_below        = 0;
00115 static Atom net_wm_state_demands_attention = 0;
00116 
00117 
00118 static Atom net_wm_action_move        = 0;
00119 static Atom net_wm_action_resize      = 0;
00120 static Atom net_wm_action_minimize    = 0;
00121 static Atom net_wm_action_shade       = 0;
00122 static Atom net_wm_action_stick       = 0;
00123 static Atom net_wm_action_max_vert    = 0;
00124 static Atom net_wm_action_max_horiz   = 0;
00125 static Atom net_wm_action_fullscreen  = 0;
00126 static Atom net_wm_action_change_desk = 0;
00127 static Atom net_wm_action_close       = 0;
00128 
00129 
00130 static Atom net_wm_state_stays_on_top = 0;
00131 
00132 
00133 static Atom xa_wm_state = 0;
00134 
00135 static Bool netwm_atoms_created      = False;
00136 const unsigned long netwm_sendevent_mask = (SubstructureRedirectMask|
00137                          SubstructureNotifyMask);
00138 
00139 
00140 const long MAX_PROP_SIZE = 100000;
00141 
00142 static char *nstrdup(const char *s1) {
00143     if (! s1) return (char *) 0;
00144 
00145     int l = strlen(s1) + 1;
00146     char *s2 = new char[l];
00147     strncpy(s2, s1, l);
00148     return s2;
00149 }
00150 
00151 
00152 static char *nstrndup(const char *s1, int l) {
00153     if (! s1 || l == 0) return (char *) 0;
00154 
00155     char *s2 = new char[l+1];
00156     strncpy(s2, s1, l);
00157     s2[l] = '\0';
00158     return s2;
00159 }
00160 
00161 
00162 static Window *nwindup(Window *w1, int n) {
00163     if (! w1 || n == 0) return (Window *) 0;
00164 
00165     Window *w2 = new Window[n];
00166     while (n--) w2[n] = w1[n];
00167     return w2;
00168 }
00169 
00170 
00171 static void refdec_nri(NETRootInfoPrivate *p) {
00172 
00173 #ifdef    NETWMDEBUG
00174     fprintf(stderr, "NET: decrementing NETRootInfoPrivate::ref (%d)\n", p->ref - 1);
00175 #endif
00176 
00177     if (! --p->ref) {
00178 
00179 #ifdef    NETWMDEBUG
00180     fprintf(stderr, "NET: \tno more references, deleting\n");
00181 #endif
00182 
00183     delete [] p->name;
00184     delete [] p->stacking;
00185     delete [] p->clients;
00186     delete [] p->virtual_roots;
00187     delete [] p->kde_system_tray_windows;
00188 
00189     int i;
00190     for (i = 0; i < p->desktop_names.size(); i++)
00191         delete [] p->desktop_names[i];
00192     }
00193 }
00194 
00195 
00196 static void refdec_nwi(NETWinInfoPrivate *p) {
00197 
00198 #ifdef    NETWMDEBUG
00199     fprintf(stderr, "NET: decrementing NETWinInfoPrivate::ref (%d)\n", p->ref - 1);
00200 #endif
00201 
00202     if (! --p->ref) {
00203 
00204 #ifdef    NETWMDEBUG
00205     fprintf(stderr, "NET: \tno more references, deleting\n");
00206 #endif
00207 
00208     delete [] p->name;
00209     delete [] p->visible_name;
00210     delete [] p->icon_name;
00211     delete [] p->visible_icon_name;
00212     delete [] p->startup_id;
00213 
00214     int i;
00215     for (i = 0; i < p->icons.size(); i++)
00216         delete [] p->icons[i].data;
00217     }
00218 }
00219 
00220 
00221 static int wcmp(const void *a, const void *b) {
00222     return *((Window *) a) - *((Window *) b);
00223 }
00224 
00225 
00226 static const int netAtomCount = 71;
00227 static void create_atoms(Display *d) {
00228     static const char * const names[netAtomCount] =
00229     {
00230     "UTF8_STRING",
00231         "_NET_SUPPORTED",
00232         "_NET_SUPPORTING_WM_CHECK",
00233         "_NET_CLIENT_LIST",
00234         "_NET_CLIENT_LIST_STACKING",
00235         "_NET_NUMBER_OF_DESKTOPS",
00236         "_NET_DESKTOP_GEOMETRY",
00237         "_NET_DESKTOP_VIEWPORT",
00238         "_NET_CURRENT_DESKTOP",
00239         "_NET_DESKTOP_NAMES",
00240         "_NET_ACTIVE_WINDOW",
00241         "_NET_WORKAREA",
00242         "_NET_VIRTUAL_ROOTS",
00243         "_NET_CLOSE_WINDOW",
00244             "_NET_RESTACK_WINDOW",
00245 
00246         "_NET_WM_MOVERESIZE",
00247             "_NET_MOVERESIZE_WINDOW",
00248         "_NET_WM_NAME",
00249         "_NET_WM_VISIBLE_NAME",
00250         "_NET_WM_ICON_NAME",
00251         "_NET_WM_VISIBLE_ICON_NAME",
00252         "_NET_WM_DESKTOP",
00253         "_NET_WM_WINDOW_TYPE",
00254         "_NET_WM_STATE",
00255         "_NET_WM_STRUT",
00256         "_NET_WM_ICON_GEOMETRY",
00257         "_NET_WM_ICON",
00258         "_NET_WM_PID",
00259         "_NET_WM_USER_TIME",
00260         "_NET_WM_HANDLED_ICONS",
00261             "_NET_STARTUP_ID",
00262             "_NET_AM_ALLOWED_ACTIONS",
00263         "_NET_WM_PING",
00264 
00265         "_NET_WM_WINDOW_TYPE_NORMAL",
00266         "_NET_WM_WINDOW_TYPE_DESKTOP",
00267         "_NET_WM_WINDOW_TYPE_DOCK",
00268         "_NET_WM_WINDOW_TYPE_TOOLBAR",
00269         "_NET_WM_WINDOW_TYPE_MENU",
00270         "_NET_WM_WINDOW_TYPE_DIALOG",
00271         "_NET_WM_WINDOW_TYPE_UTILITY",
00272         "_NET_WM_WINDOW_TYPE_SPLASH",
00273 
00274         "_NET_WM_STATE_MODAL",
00275         "_NET_WM_STATE_STICKY",
00276         "_NET_WM_STATE_MAXIMIZED_VERT",
00277         "_NET_WM_STATE_MAXIMIZED_HORZ",
00278         "_NET_WM_STATE_SHADED",
00279         "_NET_WM_STATE_SKIP_TASKBAR",
00280         "_NET_WM_STATE_SKIP_PAGER",
00281         "_NET_WM_STATE_HIDDEN",
00282         "_NET_WM_STATE_FULLSCREEN",
00283         "_NET_WM_STATE_ABOVE",
00284         "_NET_WM_STATE_BELOW",
00285         "_NET_WM_STATE_DEMANDS_ATTENTION",
00286 
00287             "_NET_WM_ACTION_MOVE",
00288             "_NET_WM_ACTION_RESIZE",
00289             "_NET_WM_ACTION_MINIMIZE",
00290             "_NET_WM_ACTION_SHADE",
00291             "_NET_WM_ACTION_STICK",
00292             "_NET_WM_ACTION_MAXIMIZE_VERT",
00293             "_NET_WM_ACTION_MAXIMIZE_HORZ",
00294             "_NET_WM_ACTION_FULLSCREEN",
00295             "_NET_WM_ACTION_CHANGE_DESKTOP",
00296             "_NET_WM_ACTION_CLOSE",
00297 
00298         "_NET_WM_STATE_STAYS_ON_TOP",
00299 
00300         "_KDE_NET_SYSTEM_TRAY_WINDOWS",
00301         "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
00302         "_KDE_NET_WM_FRAME_STRUT",
00303         "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE",
00304         "_KDE_NET_WM_WINDOW_TYPE_TOPMENU",
00305 
00306         "WM_STATE",
00307         "WM_PROTOCOLS"
00308         };
00309 
00310     Atom atoms[netAtomCount], *atomsp[netAtomCount] =
00311     {
00312     &UTF8_STRING,
00313         &net_supported,
00314         &net_supporting_wm_check,
00315         &net_client_list,
00316         &net_client_list_stacking,
00317         &net_number_of_desktops,
00318         &net_desktop_geometry,
00319         &net_desktop_viewport,
00320         &net_current_desktop,
00321         &net_desktop_names,
00322         &net_active_window,
00323         &net_workarea,
00324         &net_virtual_roots,
00325         &net_close_window,
00326             &net_restack_window,
00327 
00328         &net_wm_moveresize,
00329             &net_moveresize_window,
00330         &net_wm_name,
00331         &net_wm_visible_name,
00332         &net_wm_icon_name,
00333         &net_wm_visible_icon_name,
00334         &net_wm_desktop,
00335         &net_wm_window_type,
00336         &net_wm_state,
00337         &net_wm_strut,
00338         &net_wm_icon_geometry,
00339         &net_wm_icon,
00340         &net_wm_pid,
00341         &net_wm_user_time,
00342         &net_wm_handled_icons,
00343             &net_startup_id,
00344             &net_wm_allowed_actions,
00345         &net_wm_ping,
00346 
00347         &net_wm_window_type_normal,
00348         &net_wm_window_type_desktop,
00349         &net_wm_window_type_dock,
00350         &net_wm_window_type_toolbar,
00351         &net_wm_window_type_menu,
00352         &net_wm_window_type_dialog,
00353         &net_wm_window_type_utility,
00354         &net_wm_window_type_splash,
00355 
00356         &net_wm_state_modal,
00357         &net_wm_state_sticky,
00358         &net_wm_state_max_vert,
00359         &net_wm_state_max_horiz,
00360         &net_wm_state_shaded,
00361         &net_wm_state_skip_taskbar,
00362         &net_wm_state_skip_pager,
00363         &net_wm_state_hidden,
00364         &net_wm_state_fullscreen,
00365         &net_wm_state_above,
00366         &net_wm_state_below,
00367         &net_wm_state_demands_attention,
00368 
00369             &net_wm_action_move,
00370             &net_wm_action_resize,
00371             &net_wm_action_minimize,
00372             &net_wm_action_shade,
00373             &net_wm_action_stick,
00374             &net_wm_action_max_vert,
00375             &net_wm_action_max_horiz,
00376             &net_wm_action_fullscreen,
00377             &net_wm_action_change_desk,
00378             &net_wm_action_close,
00379 
00380         &net_wm_state_stays_on_top,
00381 
00382         &kde_net_system_tray_windows,
00383         &kde_net_wm_system_tray_window_for,
00384         &kde_net_wm_frame_strut,
00385         &kde_net_wm_window_type_override,
00386         &kde_net_wm_window_type_topmenu,
00387 
00388         &xa_wm_state,
00389         &wm_protocols
00390         };
00391 
00392     assert( !netwm_atoms_created );
00393 
00394     int i = netAtomCount;
00395     while (i--)
00396     atoms[i] = 0;
00397 
00398     XInternAtoms(d, (char **) names, netAtomCount, False, atoms);
00399 
00400     i = netAtomCount;
00401     while (i--)
00402     *atomsp[i] = atoms[i];
00403 
00404     netwm_atoms_created = True;
00405 }
00406 
00407 
00408 static void readIcon(NETWinInfoPrivate *p) {
00409 
00410 #ifdef    NETWMDEBUG
00411     fprintf(stderr, "NET: readIcon\n");
00412 #endif
00413 
00414     Atom type_ret;
00415     int format_ret;
00416     unsigned long nitems_ret = 0, after_ret = 0;
00417     unsigned char *data_ret = 0;
00418 
00419     
00420     for (int i = 0; i < p->icons.size(); i++)
00421         delete [] p->icons[i].data;
00422     p->icons.reset();
00423     p->icon_count = 0;
00424 
00425     
00426     unsigned char *buffer = 0;
00427     unsigned long offset = 0;
00428     unsigned long buffer_offset = 0;
00429     unsigned long bufsize = 0;
00430 
00431     
00432     do {
00433     if (XGetWindowProperty(p->display, p->window, net_wm_icon, offset,
00434                    MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret,
00435                    &format_ret, &nitems_ret, &after_ret, &data_ret)
00436         == Success) {
00437             if (!bufsize)
00438             {
00439                if (nitems_ret < 3 || type_ret != XA_CARDINAL ||
00440                   format_ret != 32) {
00441                   
00442                   
00443                   
00444                   
00445                   if ( data_ret )
00446                      XFree(data_ret);
00447                   return;
00448                }
00449 
00450                bufsize = nitems_ret * sizeof(long) + after_ret;
00451                buffer = (unsigned char *) malloc(bufsize);
00452             }
00453             else if (buffer_offset + nitems_ret*sizeof(long) > bufsize)
00454             {
00455 fprintf(stderr, "NETWM: Warning readIcon() needs buffer adjustment!\n");
00456                bufsize = buffer_offset + nitems_ret * sizeof(long) + after_ret;
00457                buffer = (unsigned char *) realloc(buffer, bufsize);
00458             }
00459         memcpy((buffer + buffer_offset), data_ret, nitems_ret * sizeof(long));
00460         buffer_offset += nitems_ret * sizeof(long);
00461         offset += nitems_ret;
00462 
00463         if ( data_ret )
00464         XFree(data_ret);
00465     } else {
00466             if (buffer)
00467                free(buffer);
00468         return; 
00469     }
00470     }
00471     while (after_ret > 0);
00472 
00473     CARD32 *data32;
00474     unsigned long i, j, k, sz, s;
00475     unsigned long *d = (unsigned long *) buffer;
00476     for (i = 0, j = 0; i < bufsize; i++) {
00477     p->icons[j].size.width = *d++;
00478     i += sizeof(long);
00479     p->icons[j].size.height = *d++;
00480     i += sizeof(long);
00481 
00482     sz = p->icons[j].size.width * p->icons[j].size.height;
00483     s = sz * sizeof(long);
00484 
00485     if ( i + s - 1 > bufsize ) {
00486         break;
00487     }
00488 
00489     delete [] p->icons[j].data;
00490     data32 = new CARD32[sz];
00491     p->icons[j].data = (unsigned char *) data32;
00492     for (k = 0; k < sz; k++, i += sizeof(long)) {
00493         *data32++ = (CARD32) *d++;
00494     }
00495     j++;
00496         p->icon_count++;
00497     }
00498 
00499 #ifdef    NETWMDEBUG
00500     fprintf(stderr, "NET: readIcon got %d icons\n", p->icon_count);
00501 #endif
00502 
00503     free(buffer);
00504 }
00505 
00506 
00507 template <class Z>
00508 NETRArray<Z>::NETRArray()
00509   : sz(0),  capacity(2)
00510 {
00511     d = (Z*) calloc(capacity, sizeof(Z)); 
00512 }
00513 
00514 
00515 template <class Z>
00516 NETRArray<Z>::~NETRArray() {
00517     free(d);
00518 }
00519 
00520 
00521 template <class Z>
00522 void NETRArray<Z>::reset() {
00523     sz = 0;
00524     capacity = 2;
00525     d = (Z*) realloc(d, sizeof(Z)*capacity);
00526     memset( (void*) d, 0, sizeof(Z)*capacity );
00527 }
00528 
00529 template <class Z>
00530 Z &NETRArray<Z>::operator[](int index) {
00531     if (index >= capacity) {
00532     
00533     
00534     
00535         int newcapacity = 2*capacity > index+1 ? 2*capacity : index+1; 
00536     
00537         d = (Z*) realloc(d, sizeof(Z)*newcapacity);
00538         memset( (void*) &d[capacity], 0, sizeof(Z)*(newcapacity-capacity) );
00539     capacity = newcapacity;
00540     }
00541     if (index >= sz)            
00542         sz = index + 1;
00543 
00544     return d[index];
00545 }
00546 
00547 
00548 
00549 
00550 NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
00551              const unsigned long properties[], int properties_size,
00552                          int screen, bool doActivate)
00553 {
00554 
00555 #ifdef    NETWMDEBUG
00556     fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
00557 #endif
00558 
00559     p = new NETRootInfoPrivate;
00560     p->ref = 1;
00561 
00562     p->display = display;
00563     p->name = nstrdup(wmName);
00564 
00565     if (screen != -1) {
00566     p->screen = screen;
00567     } else {
00568     p->screen = DefaultScreen(p->display);
00569     }
00570 
00571     p->root = RootWindow(p->display, p->screen);
00572     p->supportwindow = supportWindow;
00573     p->number_of_desktops = p->current_desktop = 0;
00574     p->active = None;
00575     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00576     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00577     p->kde_system_tray_windows = 0;
00578     p->kde_system_tray_windows_count = 0;
00579     setDefaultProperties();
00580     if( properties_size > PROPERTIES_SIZE ) {
00581         fprintf( stderr, "NETRootInfo::NETRootInfo(): properties array too large\n");
00582         properties_size = PROPERTIES_SIZE;
00583     }
00584     for( int i = 0; i < properties_size; ++i )
00585         p->properties[ i ] = properties[ i ];
00586     
00587     p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
00588     p->client_properties[ PROTOCOLS ] = DesktopNames 
00589                             | WMPing; 
00590     p->client_properties[ PROTOCOLS2 ] = 0;
00591 
00592     role = WindowManager;
00593 
00594     if (! netwm_atoms_created) create_atoms(p->display);
00595 
00596     if (doActivate) activate();
00597 }
00598 
00599 NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
00600              unsigned long properties, int screen, bool doActivate)
00601 {
00602 
00603 #ifdef    NETWMDEBUG
00604     fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
00605 #endif
00606 
00607     p = new NETRootInfoPrivate;
00608     p->ref = 1;
00609 
00610     p->display = display;
00611     p->name = nstrdup(wmName);
00612 
00613     if (screen != -1) {
00614     p->screen = screen;
00615     } else {
00616     p->screen = DefaultScreen(p->display);
00617     }
00618 
00619     p->root = RootWindow(p->display, p->screen);
00620     p->supportwindow = supportWindow;
00621     p->number_of_desktops = p->current_desktop = 0;
00622     p->active = None;
00623     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00624     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00625     p->kde_system_tray_windows = 0;
00626     p->kde_system_tray_windows_count = 0;
00627     setDefaultProperties();
00628     p->properties[ PROTOCOLS ] = properties;
00629     
00630     p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
00631     p->client_properties[ PROTOCOLS ] = DesktopNames 
00632                             | WMPing; 
00633     p->client_properties[ PROTOCOLS2 ] = 0;
00634 
00635     role = WindowManager;
00636 
00637     if (! netwm_atoms_created) create_atoms(p->display);
00638 
00639     if (doActivate) activate();
00640 }
00641 
00642 
00643 NETRootInfo::NETRootInfo(Display *display, const unsigned long properties[], int properties_size,
00644                          int screen, bool doActivate)
00645 {
00646 
00647 #ifdef    NETWMDEBUG
00648     fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
00649 #endif
00650 
00651     p = new NETRootInfoPrivate;
00652     p->ref = 1;
00653 
00654     p->name = 0;
00655 
00656     p->display = display;
00657 
00658     if (screen != -1) {
00659     p->screen = screen;
00660     } else {
00661     p->screen = DefaultScreen(p->display);
00662     }
00663 
00664     p->root = RootWindow(p->display, p->screen);
00665     p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
00666     p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
00667 
00668     p->supportwindow = None;
00669     p->number_of_desktops = p->current_desktop = 0;
00670     p->active = None;
00671     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00672     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00673     p->kde_system_tray_windows = 0;
00674     p->kde_system_tray_windows_count = 0;
00675     setDefaultProperties();
00676     if( properties_size > PROPERTIES_SIZE ) {
00677         fprintf( stderr, "NETWinInfo::NETWinInfo(): properties array too large\n");
00678         properties_size = PROPERTIES_SIZE;
00679     }
00680     for( int i = 0; i < properties_size; ++i )
00681         p->client_properties[ i ] = properties[ i ];
00682     for( int i = 0; i < PROPERTIES_SIZE; ++i )
00683         p->properties[ i ] = 0;
00684 
00685     role = Client;
00686 
00687     if (! netwm_atoms_created) create_atoms(p->display);
00688 
00689     if (doActivate) activate();
00690 }
00691 
00692 NETRootInfo::NETRootInfo(Display *display, unsigned long properties, int screen,
00693              bool doActivate)
00694 {
00695 
00696 #ifdef    NETWMDEBUG
00697     fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
00698 #endif
00699 
00700     p = new NETRootInfoPrivate;
00701     p->ref = 1;
00702 
00703     p->name = 0;
00704 
00705     p->display = display;
00706 
00707     if (screen != -1) {
00708     p->screen = screen;
00709     } else {
00710     p->screen = DefaultScreen(p->display);
00711     }
00712 
00713     p->root = RootWindow(p->display, p->screen);
00714     p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
00715     p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
00716 
00717     p->supportwindow = None;
00718     p->number_of_desktops = p->current_desktop = 0;
00719     p->active = None;
00720     p->clients = p->stacking = p->virtual_roots = (Window *) 0;
00721     p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
00722     p->kde_system_tray_windows = 0;
00723     p->kde_system_tray_windows_count = 0;
00724     setDefaultProperties();
00725     p->client_properties[ PROTOCOLS ] = properties;
00726     for( int i = 0; i < PROPERTIES_SIZE; ++i )
00727         p->properties[ i ] = 0;
00728 
00729     role = Client;
00730 
00731     if (! netwm_atoms_created) create_atoms(p->display);
00732 
00733     if (doActivate) activate();
00734 }
00735 
00736 
00737 NETRootInfo2::NETRootInfo2(Display *display, Window supportWindow, const char *wmName,
00738              unsigned long properties[], int properties_size,
00739                          int screen, bool doActivate)
00740     : NETRootInfo( display, supportWindow, wmName, properties, properties_size,
00741     screen, doActivate )
00742 {
00743 }
00744 
00745 
00746 
00747 NETRootInfo::NETRootInfo(const NETRootInfo &rootinfo) {
00748 
00749 #ifdef    NETWMDEBUG
00750     fprintf(stderr, "NETRootInfo::NETRootInfo: using copy constructor\n");
00751 #endif
00752 
00753     p = rootinfo.p;
00754     role = rootinfo.role;
00755 
00756     p->ref++;
00757 }
00758 
00759 
00760 
00761 
00762 NETRootInfo::~NETRootInfo() {
00763     refdec_nri(p);
00764 
00765     if (! p->ref) delete p;
00766 }
00767 
00768 
00769 void NETRootInfo::setDefaultProperties()
00770 {
00771     p->properties[ PROTOCOLS ] = Supported | SupportingWMCheck;
00772     p->properties[ WINDOW_TYPES ] = NormalMask | DesktopMask | DockMask
00773         | ToolbarMask | MenuMask | DialogMask;
00774     p->properties[ STATES ] = Modal | Sticky | MaxVert | MaxHoriz | Shaded
00775         | SkipTaskbar | StaysOnTop;
00776     p->properties[ PROTOCOLS2 ] = 0;
00777     p->properties[ ACTIONS ] = 0;
00778     p->client_properties[ PROTOCOLS ] = 0;
00779     p->client_properties[ WINDOW_TYPES ] = 0; 
00780     p->client_properties[ STATES ] = 0;       
00781     p->client_properties[ PROTOCOLS2 ] = 0;
00782     p->client_properties[ ACTIONS ] = 0;
00783 }
00784 
00785 void NETRootInfo::activate() {
00786     if (role == WindowManager) {
00787 
00788 #ifdef    NETWMDEBUG
00789     fprintf(stderr,
00790         "NETRootInfo::activate: setting supported properties on root\n");
00791 #endif
00792 
00793     setSupported();
00794     } else {
00795 
00796 #ifdef    NETWMDEBUG
00797     fprintf(stderr, "NETRootInfo::activate: updating client information\n");
00798 #endif
00799 
00800     update(p->client_properties);
00801     }
00802 }
00803 
00804 
00805 void NETRootInfo::setClientList(Window *windows, unsigned int count) {
00806     if (role != WindowManager) return;
00807 
00808     p->clients_count = count;
00809 
00810     delete [] p->clients;
00811     p->clients = nwindup(windows, count);
00812 
00813 #ifdef    NETWMDEBUG
00814     fprintf(stderr, "NETRootInfo::setClientList: setting list with %ld windows\n",
00815         p->clients_count);
00816 #endif
00817 
00818     XChangeProperty(p->display, p->root, net_client_list, XA_WINDOW, 32,
00819             PropModeReplace, (unsigned char *)p->clients,
00820             p->clients_count);
00821 }
00822 
00823 
00824 void NETRootInfo::setClientListStacking(Window *windows, unsigned int count) {
00825     if (role != WindowManager) return;
00826 
00827     p->stacking_count = count;
00828     delete [] p->stacking;
00829     p->stacking = nwindup(windows, count);
00830 
00831 #ifdef    NETWMDEBUG
00832     fprintf(stderr,
00833         "NETRootInfo::setClientListStacking: setting list with %ld windows\n",
00834         p->clients_count);
00835 #endif
00836 
00837     XChangeProperty(p->display, p->root, net_client_list_stacking, XA_WINDOW, 32,
00838             PropModeReplace, (unsigned char *) p->stacking,
00839             p->stacking_count);
00840 }
00841 
00842 
00843 void NETRootInfo::setKDESystemTrayWindows(Window *windows, unsigned int count) {
00844     if (role != WindowManager) return;
00845 
00846     p->kde_system_tray_windows_count = count;
00847     delete [] p->kde_system_tray_windows;
00848     p->kde_system_tray_windows = nwindup(windows, count);
00849 
00850 #ifdef    NETWMDEBUG
00851     fprintf(stderr,
00852         "NETRootInfo::setKDESystemTrayWindows: setting list with %ld windows\n",
00853         p->kde_system_tray_windows_count);
00854 #endif
00855 
00856     XChangeProperty(p->display, p->root, kde_net_system_tray_windows, XA_WINDOW, 32,
00857             PropModeReplace,
00858             (unsigned char *) p->kde_system_tray_windows,
00859             p->kde_system_tray_windows_count);
00860 }
00861 
00862 
00863 void NETRootInfo::setNumberOfDesktops(int numberOfDesktops) {
00864 
00865 #ifdef    NETWMDEBUG
00866     fprintf(stderr,
00867         "NETRootInfo::setNumberOfDesktops: setting desktop count to %d (%s)\n",
00868         numberOfDesktops, (role == WindowManager) ? "WM" : "Client");
00869 #endif
00870 
00871     if (role == WindowManager) {
00872     p->number_of_desktops = numberOfDesktops;
00873     long d = numberOfDesktops;
00874     XChangeProperty(p->display, p->root, net_number_of_desktops, XA_CARDINAL, 32,
00875             PropModeReplace, (unsigned char *) &d, 1);
00876     } else {
00877     XEvent e;
00878 
00879     e.xclient.type = ClientMessage;
00880     e.xclient.message_type = net_number_of_desktops;
00881     e.xclient.display = p->display;
00882     e.xclient.window = p->root;
00883     e.xclient.format = 32;
00884     e.xclient.data.l[0] = numberOfDesktops;
00885     e.xclient.data.l[1] = 0l;
00886     e.xclient.data.l[2] = 0l;
00887     e.xclient.data.l[3] = 0l;
00888     e.xclient.data.l[4] = 0l;
00889 
00890     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00891     }
00892 }
00893 
00894 
00895 void NETRootInfo::setCurrentDesktop(int desktop) {
00896 
00897 #ifdef    NETWMDEBUG
00898     fprintf(stderr,
00899         "NETRootInfo::setCurrentDesktop: setting current desktop = %d (%s)\n",
00900         desktop, (role == WindowManager) ? "WM" : "Client");
00901 #endif
00902 
00903     if (role == WindowManager) {
00904     p->current_desktop = desktop;
00905     long d = p->current_desktop - 1;
00906     XChangeProperty(p->display, p->root, net_current_desktop, XA_CARDINAL, 32,
00907             PropModeReplace, (unsigned char *) &d, 1);
00908     } else {
00909     XEvent e;
00910 
00911     e.xclient.type = ClientMessage;
00912     e.xclient.message_type = net_current_desktop;
00913     e.xclient.display = p->display;
00914     e.xclient.window = p->root;
00915     e.xclient.format = 32;
00916     e.xclient.data.l[0] = desktop - 1;
00917     e.xclient.data.l[1] = 0l;
00918     e.xclient.data.l[2] = 0l;
00919     e.xclient.data.l[3] = 0l;
00920     e.xclient.data.l[4] = 0l;
00921 
00922     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00923     }
00924 }
00925 
00926 
00927 void NETRootInfo::setDesktopName(int desktop, const char *desktopName) {
00928     
00929     if (desktop < 1) return;
00930 
00931     delete [] p->desktop_names[desktop - 1];
00932     p->desktop_names[desktop - 1] = nstrdup(desktopName);
00933 
00934     unsigned int i, proplen,
00935     num = ((p->number_of_desktops > p->desktop_names.size()) ?
00936            p->number_of_desktops : p->desktop_names.size());
00937     for (i = 0, proplen = 0; i < num; i++)
00938     proplen += (p->desktop_names[i] != 0 ? strlen(p->desktop_names[i])+1 : 1 );
00939 
00940     char *prop = new char[proplen], *propp = prop;
00941 
00942     for (i = 0; i < num; i++)
00943     if (p->desktop_names[i]) {
00944         strcpy(propp, p->desktop_names[i]);
00945         propp += strlen(p->desktop_names[i]) + 1;
00946     } else
00947         *propp++ = '\0';
00948 
00949 #ifdef    NETWMDEBUG
00950     fprintf(stderr,
00951         "NETRootInfo::setDesktopName(%d, '%s')\n"
00952         "NETRootInfo::setDesktopName: total property length = %d",
00953         desktop, desktopName, proplen);
00954 #endif
00955 
00956     XChangeProperty(p->display, p->root, net_desktop_names, UTF8_STRING, 8,
00957             PropModeReplace, (unsigned char *) prop, proplen);
00958 
00959     delete [] prop;
00960 }
00961 
00962 
00963 void NETRootInfo::setDesktopGeometry(int , const NETSize &geometry) {
00964 
00965 #ifdef    NETWMDEBUG
00966     fprintf(stderr, "NETRootInfo::setDesktopGeometry( -- , { %d, %d }) (%s)\n",
00967         geometry.width, geometry.height, (role == WindowManager) ? "WM" : "Client");
00968 #endif
00969 
00970     if (role == WindowManager) {
00971     p->geometry = geometry;
00972 
00973     long data[2];
00974     data[0] = p->geometry.width;
00975     data[1] = p->geometry.height;
00976 
00977     XChangeProperty(p->display, p->root, net_desktop_geometry, XA_CARDINAL, 32,
00978             PropModeReplace, (unsigned char *) data, 2);
00979     } else {
00980     XEvent e;
00981 
00982     e.xclient.type = ClientMessage;
00983     e.xclient.message_type = net_desktop_geometry;
00984     e.xclient.display = p->display;
00985     e.xclient.window = p->root;
00986     e.xclient.format = 32;
00987     e.xclient.data.l[0] = geometry.width;
00988     e.xclient.data.l[1] = geometry.height;
00989     e.xclient.data.l[2] = 0l;
00990     e.xclient.data.l[3] = 0l;
00991     e.xclient.data.l[4] = 0l;
00992 
00993     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
00994     }
00995 }
00996 
00997 
00998 void NETRootInfo::setDesktopViewport(int desktop, const NETPoint &viewport) {
00999 
01000 #ifdef    NETWMDEBUG
01001     fprintf(stderr, "NETRootInfo::setDesktopViewport(%d, { %d, %d }) (%s)\n",
01002         desktop, viewport.x, viewport.y, (role == WindowManager) ? "WM" : "Client");
01003 #endif
01004 
01005     if (desktop < 1) return;
01006 
01007     if (role == WindowManager) {
01008     p->viewport[desktop - 1] = viewport;
01009 
01010     int d, i, l;
01011     l = p->number_of_desktops * 2;
01012     long *data = new long[l];
01013     for (d = 0, i = 0; d < p->number_of_desktops; d++) {
01014         data[i++] = p->viewport[d].x;
01015         data[i++] = p->viewport[d].y;
01016     }
01017 
01018     XChangeProperty(p->display, p->root, net_desktop_viewport, XA_CARDINAL, 32,
01019             PropModeReplace, (unsigned char *) data, l);
01020 
01021     delete [] data;
01022     } else {
01023     XEvent e;
01024 
01025     e.xclient.type = ClientMessage;
01026     e.xclient.message_type = net_desktop_viewport;
01027     e.xclient.display = p->display;
01028     e.xclient.window = p->root;
01029     e.xclient.format = 32;
01030     e.xclient.data.l[0] = viewport.x;
01031     e.xclient.data.l[1] = viewport.y;
01032     e.xclient.data.l[2] = 0l;
01033     e.xclient.data.l[3] = 0l;
01034     e.xclient.data.l[4] = 0l;
01035 
01036     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01037     }
01038 }
01039 
01040 
01041 void NETRootInfo::setSupported() {
01042     if (role != WindowManager) {
01043 #ifdef    NETWMDEBUG
01044     fprintf(stderr, "NETRootInfo::setSupported - role != WindowManager\n");
01045 #endif
01046 
01047     return;
01048     }
01049 
01050     Atom atoms[netAtomCount];
01051     int pnum = 2;
01052 
01053     
01054     atoms[0] = net_supported;
01055     atoms[1] = net_supporting_wm_check;
01056 
01057     if (p->properties[ PROTOCOLS ] & ClientList)
01058     atoms[pnum++] = net_client_list;
01059 
01060     if (p->properties[ PROTOCOLS ] & ClientListStacking)
01061     atoms[pnum++] = net_client_list_stacking;
01062 
01063     if (p->properties[ PROTOCOLS ] & NumberOfDesktops)
01064     atoms[pnum++] = net_number_of_desktops;
01065 
01066     if (p->properties[ PROTOCOLS ] & DesktopGeometry)
01067     atoms[pnum++] = net_desktop_geometry;
01068 
01069     if (p->properties[ PROTOCOLS ] & DesktopViewport)
01070     atoms[pnum++] = net_desktop_viewport;
01071 
01072     if (p->properties[ PROTOCOLS ] & CurrentDesktop)
01073     atoms[pnum++] = net_current_desktop;
01074 
01075     if (p->properties[ PROTOCOLS ] & DesktopNames)
01076     atoms[pnum++] = net_desktop_names;
01077 
01078     if (p->properties[ PROTOCOLS ] & ActiveWindow)
01079     atoms[pnum++] = net_active_window;
01080 
01081     if (p->properties[ PROTOCOLS ] & WorkArea)
01082     atoms[pnum++] = net_workarea;
01083 
01084     if (p->properties[ PROTOCOLS ] & VirtualRoots)
01085     atoms[pnum++] = net_virtual_roots;
01086 
01087     if (p->properties[ PROTOCOLS ] & CloseWindow)
01088     atoms[pnum++] = net_close_window;
01089 
01090     if (p->properties[ PROTOCOLS2 ] & WM2RestackWindow)
01091     atoms[pnum++] = net_restack_window;
01092 
01093     
01094     if (p->properties[ PROTOCOLS ] & WMMoveResize)
01095     atoms[pnum++] = net_wm_moveresize;
01096 
01097     if (p->properties[ PROTOCOLS2 ] & WM2MoveResizeWindow)
01098     atoms[pnum++] = net_moveresize_window;
01099 
01100     if (p->properties[ PROTOCOLS ] & WMName)
01101     atoms[pnum++] = net_wm_name;
01102 
01103     if (p->properties[ PROTOCOLS ] & WMVisibleName)
01104     atoms[pnum++] = net_wm_visible_name;
01105 
01106     if (p->properties[ PROTOCOLS ] & WMIconName)
01107     atoms[pnum++] = net_wm_icon_name;
01108 
01109     if (p->properties[ PROTOCOLS ] & WMVisibleIconName)
01110     atoms[pnum++] = net_wm_visible_icon_name;
01111 
01112     if (p->properties[ PROTOCOLS ] & WMDesktop)
01113     atoms[pnum++] = net_wm_desktop;
01114 
01115     if (p->properties[ PROTOCOLS ] & WMWindowType) {
01116     atoms[pnum++] = net_wm_window_type;
01117 
01118     
01119         if (p->properties[ WINDOW_TYPES ] & NormalMask)
01120         atoms[pnum++] = net_wm_window_type_normal;
01121         if (p->properties[ WINDOW_TYPES ] & DesktopMask)
01122         atoms[pnum++] = net_wm_window_type_desktop;
01123         if (p->properties[ WINDOW_TYPES ] & DockMask)
01124             atoms[pnum++] = net_wm_window_type_dock;
01125         if (p->properties[ WINDOW_TYPES ] & ToolbarMask)
01126         atoms[pnum++] = net_wm_window_type_toolbar;
01127         if (p->properties[ WINDOW_TYPES ] & MenuMask)
01128         atoms[pnum++] = net_wm_window_type_menu;
01129         if (p->properties[ WINDOW_TYPES ] & DialogMask)
01130         atoms[pnum++] = net_wm_window_type_dialog;
01131         if (p->properties[ WINDOW_TYPES ] & UtilityMask)
01132         atoms[pnum++] = net_wm_window_type_utility;
01133         if (p->properties[ WINDOW_TYPES ] & SplashMask)
01134         atoms[pnum++] = net_wm_window_type_splash;
01135     
01136         if (p->properties[ WINDOW_TYPES ] & OverrideMask)
01137         atoms[pnum++] = kde_net_wm_window_type_override;
01138         if (p->properties[ WINDOW_TYPES ] & TopMenuMask)
01139         atoms[pnum++] = kde_net_wm_window_type_topmenu;
01140     }
01141 
01142     if (p->properties[ PROTOCOLS ] & WMState) {
01143     atoms[pnum++] = net_wm_state;
01144 
01145     
01146         if (p->properties[ STATES ] & Modal)
01147             atoms[pnum++] = net_wm_state_modal;
01148         if (p->properties[ STATES ] & Sticky)
01149         atoms[pnum++] = net_wm_state_sticky;
01150         if (p->properties[ STATES ] & MaxVert)
01151         atoms[pnum++] = net_wm_state_max_vert;
01152         if (p->properties[ STATES ] & MaxHoriz)
01153         atoms[pnum++] = net_wm_state_max_horiz;
01154         if (p->properties[ STATES ] & Shaded)
01155         atoms[pnum++] = net_wm_state_shaded;
01156         if (p->properties[ STATES ] & SkipTaskbar)
01157         atoms[pnum++] = net_wm_state_skip_taskbar;
01158         if (p->properties[ STATES ] & SkipPager)
01159         atoms[pnum++] = net_wm_state_skip_pager;
01160         if (p->properties[ STATES ] & Hidden)
01161         atoms[pnum++] = net_wm_state_hidden;
01162         if (p->properties[ STATES ] & FullScreen)
01163         atoms[pnum++] = net_wm_state_fullscreen;
01164         if (p->properties[ STATES ] & KeepAbove)
01165         atoms[pnum++] = net_wm_state_above;
01166         if (p->properties[ STATES ] & KeepBelow)
01167         atoms[pnum++] = net_wm_state_below;
01168         if (p->properties[ STATES ] & DemandsAttention)
01169         atoms[pnum++] = net_wm_state_demands_attention;
01170 
01171         if (p->properties[ STATES ] & StaysOnTop)
01172         atoms[pnum++] = net_wm_state_stays_on_top;
01173     }
01174 
01175     if (p->properties[ PROTOCOLS ] & WMStrut)
01176     atoms[pnum++] = net_wm_strut;
01177 
01178     if (p->properties[ PROTOCOLS ] & WMIconGeometry)
01179     atoms[pnum++] = net_wm_icon_geometry;
01180 
01181     if (p->properties[ PROTOCOLS ] & WMIcon)
01182     atoms[pnum++] = net_wm_icon;
01183 
01184     if (p->properties[ PROTOCOLS ] & WMPid)
01185     atoms[pnum++] = net_wm_pid;
01186 
01187     if (p->properties[ PROTOCOLS ] & WMHandledIcons)
01188     atoms[pnum++] = net_wm_handled_icons;
01189 
01190     if (p->properties[ PROTOCOLS ] & WMPing)
01191     atoms[pnum++] = net_wm_ping;
01192 
01193     if (p->properties[ PROTOCOLS2 ] & WM2UserTime)
01194     atoms[pnum++] = net_wm_user_time;
01195 
01196     if (p->properties[ PROTOCOLS2 ] & WM2StartupId)
01197     atoms[pnum++] = net_startup_id;
01198 
01199     if (p->properties[ PROTOCOLS2 ] & WM2AllowedActions) {
01200         atoms[pnum++] = net_wm_allowed_actions;
01201 
01202     
01203         if (p->properties[ ACTIONS ] & ActionMove)
01204             atoms[pnum++] = net_wm_action_move;
01205         if (p->properties[ ACTIONS ] & ActionResize)
01206             atoms[pnum++] = net_wm_action_resize;
01207         if (p->properties[ ACTIONS ] & ActionMinimize)
01208             atoms[pnum++] = net_wm_action_minimize;
01209         if (p->properties[ ACTIONS ] & ActionShade)
01210             atoms[pnum++] = net_wm_action_shade;
01211         if (p->properties[ ACTIONS ] & ActionStick)
01212             atoms[pnum++] = net_wm_action_stick;
01213         if (p->properties[ ACTIONS ] & ActionMaxVert)
01214             atoms[pnum++] = net_wm_action_max_vert;
01215         if (p->properties[ ACTIONS ] & ActionMaxHoriz)
01216             atoms[pnum++] = net_wm_action_max_horiz;
01217         if (p->properties[ ACTIONS ] & ActionFullScreen)
01218             atoms[pnum++] = net_wm_action_fullscreen;
01219         if (p->properties[ ACTIONS ] & ActionChangeDesktop)
01220             atoms[pnum++] = net_wm_action_change_desk;
01221         if (p->properties[ ACTIONS ] & ActionClose)
01222             atoms[pnum++] = net_wm_action_close;
01223     }
01224 
01225     
01226     if (p->properties[ PROTOCOLS ] & KDESystemTrayWindows)
01227     atoms[pnum++] = kde_net_system_tray_windows;
01228 
01229     if (p->properties[ PROTOCOLS ] & WMKDESystemTrayWinFor)
01230     atoms[pnum++] = kde_net_wm_system_tray_window_for;
01231 
01232     if (p->properties[ PROTOCOLS ] & WMKDEFrameStrut)
01233     atoms[pnum++] = kde_net_wm_frame_strut;
01234 
01235     XChangeProperty(p->display, p->root, net_supported, XA_ATOM, 32,
01236             PropModeReplace, (unsigned char *) atoms, pnum);
01237     XChangeProperty(p->display, p->root, net_supporting_wm_check, XA_WINDOW, 32,
01238             PropModeReplace, (unsigned char *) &(p->supportwindow), 1);
01239 
01240 #ifdef    NETWMDEBUG
01241     fprintf(stderr,
01242         "NETRootInfo::setSupported: _NET_SUPPORTING_WM_CHECK = 0x%lx on 0x%lx\n"
01243         "                         : _NET_WM_NAME = '%s' on 0x%lx\n",
01244         p->supportwindow, p->supportwindow, p->name, p->supportwindow);
01245 #endif
01246 
01247     XChangeProperty(p->display, p->supportwindow, net_supporting_wm_check,
01248             XA_WINDOW, 32, PropModeReplace,
01249             (unsigned char *) &(p->supportwindow), 1);
01250     XChangeProperty(p->display, p->supportwindow, net_wm_name, UTF8_STRING, 8,
01251             PropModeReplace, (unsigned char *) p->name,
01252             strlen(p->name));
01253 }
01254 
01255 void NETRootInfo::updateSupportedProperties( Atom atom )
01256 {
01257     if( atom == net_supported )
01258         p->properties[ PROTOCOLS ] |= Supported;
01259 
01260     else if( atom == net_supporting_wm_check )
01261         p->properties[ PROTOCOLS ] |= SupportingWMCheck;
01262 
01263     else if( atom == net_client_list )
01264         p->properties[ PROTOCOLS ] |= ClientList;
01265 
01266     else if( atom == net_client_list_stacking )
01267         p->properties[ PROTOCOLS ] |= ClientListStacking;
01268 
01269     else if( atom == net_number_of_desktops )
01270         p->properties[ PROTOCOLS ] |= NumberOfDesktops;
01271 
01272     else if( atom == net_desktop_geometry )
01273         p->properties[ PROTOCOLS ] |= DesktopGeometry;
01274 
01275     else if( atom == net_desktop_viewport )
01276         p->properties[ PROTOCOLS ] |= DesktopViewport;
01277 
01278     else if( atom == net_current_desktop )
01279         p->properties[ PROTOCOLS ] |= CurrentDesktop;
01280 
01281     else if( atom == net_desktop_names )
01282         p->properties[ PROTOCOLS ] |= DesktopNames;
01283 
01284     else if( atom == net_active_window )
01285         p->properties[ PROTOCOLS ] |= ActiveWindow;
01286 
01287     else if( atom == net_workarea )
01288         p->properties[ PROTOCOLS ] |= WorkArea;
01289 
01290     else if( atom == net_virtual_roots )
01291         p->properties[ PROTOCOLS ] |= VirtualRoots;
01292 
01293     else if( atom == net_close_window )
01294         p->properties[ PROTOCOLS ] |= CloseWindow;
01295 
01296     else if( atom == net_restack_window )
01297         p->properties[ PROTOCOLS2 ] |= WM2RestackWindow;
01298 
01299 
01300     
01301     else if( atom == net_wm_moveresize )
01302         p->properties[ PROTOCOLS ] |= WMMoveResize;
01303 
01304     else if( atom == net_moveresize_window )
01305         p->properties[ PROTOCOLS2 ] |= WM2MoveResizeWindow;
01306 
01307     else if( atom == net_wm_name )
01308         p->properties[ PROTOCOLS ] |= WMName;
01309 
01310     else if( atom == net_wm_visible_name )
01311         p->properties[ PROTOCOLS ] |= WMVisibleName;
01312 
01313     else if( atom == net_wm_icon_name )
01314         p->properties[ PROTOCOLS ] |= WMIconName;
01315 
01316     else if( atom == net_wm_visible_icon_name )
01317         p->properties[ PROTOCOLS ] |= WMVisibleIconName;
01318 
01319     else if( atom == net_wm_desktop )
01320         p->properties[ PROTOCOLS ] |= WMDesktop;
01321 
01322     else if( atom == net_wm_window_type )
01323         p->properties[ PROTOCOLS ] |= WMWindowType;
01324 
01325     
01326     else if( atom == net_wm_window_type_normal )
01327         p->properties[ WINDOW_TYPES ] |= NormalMask;
01328     else if( atom == net_wm_window_type_desktop )
01329         p->properties[ WINDOW_TYPES ] |= DesktopMask;
01330     else if( atom == net_wm_window_type_dock )
01331         p->properties[ WINDOW_TYPES ] |= DockMask;
01332     else if( atom == net_wm_window_type_toolbar )
01333         p->properties[ WINDOW_TYPES ] |= ToolbarMask;
01334     else if( atom == net_wm_window_type_menu )
01335         p->properties[ WINDOW_TYPES ] |= MenuMask;
01336     else if( atom == net_wm_window_type_dialog )
01337         p->properties[ WINDOW_TYPES ] |= DialogMask;
01338     else if( atom == net_wm_window_type_utility )
01339         p->properties[ WINDOW_TYPES ] |= UtilityMask;
01340     else if( atom == net_wm_window_type_splash )
01341         p->properties[ WINDOW_TYPES ] |= SplashMask;
01342     
01343     else if( atom == kde_net_wm_window_type_override )
01344         p->properties[ WINDOW_TYPES ] |= OverrideMask;
01345     else if( atom == kde_net_wm_window_type_topmenu )
01346         p->properties[ WINDOW_TYPES ] |= TopMenuMask;
01347 
01348     else if( atom == net_wm_state )
01349         p->properties[ PROTOCOLS ] |= WMState;
01350 
01351     
01352     else if( atom == net_wm_state_modal )
01353         p->properties[ STATES ] |= Modal;
01354     else if( atom == net_wm_state_sticky )
01355         p->properties[ STATES ] |= Sticky;
01356     else if( atom == net_wm_state_max_vert )
01357         p->properties[ STATES ] |= MaxVert;
01358     else if( atom == net_wm_state_max_horiz )
01359         p->properties[ STATES ] |= MaxHoriz;
01360     else if( atom == net_wm_state_shaded )
01361         p->properties[ STATES ] |= Shaded;
01362     else if( atom == net_wm_state_skip_taskbar )
01363         p->properties[ STATES ] |= SkipTaskbar;
01364     else if( atom == net_wm_state_skip_pager )
01365         p->properties[ STATES ] |= SkipPager;
01366     else if( atom == net_wm_state_hidden )
01367         p->properties[ STATES ] |= Hidden;
01368     else if( atom == net_wm_state_fullscreen )
01369         p->properties[ STATES ] |= FullScreen;
01370     else if( atom == net_wm_state_above )
01371         p->properties[ STATES ] |= KeepAbove;
01372     else if( atom == net_wm_state_below )
01373         p->properties[ STATES ] |= KeepBelow;
01374     else if( atom == net_wm_state_demands_attention )
01375         p->properties[ STATES ] |= DemandsAttention;
01376 
01377     else if( atom == net_wm_state_stays_on_top )
01378         p->properties[ STATES ] |= StaysOnTop;
01379 
01380     else if( atom == net_wm_strut )
01381         p->properties[ PROTOCOLS ] |= WMStrut;
01382 
01383     else if( atom == net_wm_icon_geometry )
01384         p->properties[ PROTOCOLS ] |= WMIconGeometry;
01385 
01386     else if( atom == net_wm_icon )
01387         p->properties[ PROTOCOLS ] |= WMIcon;
01388 
01389     else if( atom == net_wm_pid )
01390         p->properties[ PROTOCOLS ] |= WMPid;
01391 
01392     else if( atom == net_wm_handled_icons )
01393         p->properties[ PROTOCOLS ] |= WMHandledIcons;
01394 
01395     else if( atom == net_wm_ping )
01396         p->properties[ PROTOCOLS ] |= WMPing;
01397 
01398     else if( atom == net_wm_user_time )
01399         p->properties[ PROTOCOLS2 ] |= WM2UserTime;
01400 
01401     else if( atom == net_startup_id )
01402         p->properties[ PROTOCOLS2 ] |= WM2StartupId;
01403 
01404     else if( atom == net_wm_allowed_actions )
01405         p->properties[ PROTOCOLS2 ] |= WM2AllowedActions;
01406 
01407         
01408     else if( atom == net_wm_action_move )
01409         p->properties[ ACTIONS ] |= ActionMove;
01410     else if( atom == net_wm_action_resize )
01411         p->properties[ ACTIONS ] |= ActionResize;
01412     else if( atom == net_wm_action_minimize )
01413         p->properties[ ACTIONS ] |= ActionMinimize;
01414     else if( atom == net_wm_action_shade )
01415         p->properties[ ACTIONS ] |= ActionShade;
01416     else if( atom == net_wm_action_stick )
01417         p->properties[ ACTIONS ] |= ActionStick;
01418     else if( atom == net_wm_action_max_vert )
01419         p->properties[ ACTIONS ] |= ActionMaxVert;
01420     else if( atom == net_wm_action_max_horiz )
01421         p->properties[ ACTIONS ] |= ActionMaxHoriz;
01422     else if( atom == net_wm_action_fullscreen )
01423         p->properties[ ACTIONS ] |= ActionFullScreen;
01424     else if( atom == net_wm_action_change_desk )
01425         p->properties[ ACTIONS ] |= ActionChangeDesktop;
01426     else if( atom == net_wm_action_close )
01427         p->properties[ ACTIONS ] |= ActionClose;
01428 
01429     
01430     else if( atom == kde_net_system_tray_windows )
01431         p->properties[ PROTOCOLS ] |= KDESystemTrayWindows;
01432 
01433     else if( atom == kde_net_wm_system_tray_window_for )
01434         p->properties[ PROTOCOLS ] |= WMKDESystemTrayWinFor;
01435 
01436     else if( atom == kde_net_wm_frame_strut )
01437         p->properties[ PROTOCOLS ] |= WMKDEFrameStrut;
01438 }
01439 
01440 extern Time qt_x_user_time;
01441 void NETRootInfo::setActiveWindow(Window window) {
01442     setActiveWindow( window, FromUnknown, qt_x_user_time, None );
01443 }
01444 
01445 void NETRootInfo::setActiveWindow(Window window, NET::RequestSource src,
01446     Time timestamp, Window active_window ) {
01447 
01448 #ifdef    NETWMDEBUG
01449     fprintf(stderr, "NETRootInfo::setActiveWindow(0x%lx) (%s)\n",
01450             window, (role == WindowManager) ? "WM" : "Client");
01451 #endif
01452 
01453     if (role == WindowManager) {
01454     p->active = window;
01455     XChangeProperty(p->display, p->root, net_active_window, XA_WINDOW, 32,
01456             PropModeReplace, (unsigned char *) &(p->active), 1);
01457     } else {
01458     XEvent e;
01459 
01460     e.xclient.type = ClientMessage;
01461     e.xclient.message_type = net_active_window;
01462     e.xclient.display = p->display;
01463     e.xclient.window = window;
01464     e.xclient.format = 32;
01465     e.xclient.data.l[0] = src;
01466     e.xclient.data.l[1] = timestamp;
01467     e.xclient.data.l[2] = active_window;
01468     e.xclient.data.l[3] = 0l;
01469     e.xclient.data.l[4] = 0l;
01470 
01471     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01472     }
01473 }
01474 
01475 
01476 void NETRootInfo::setWorkArea(int desktop, const NETRect &workarea) {
01477 
01478 #ifdef    NETWMDEBUG
01479     fprintf(stderr, "NETRootInfo::setWorkArea(%d, { %d, %d, %d, %d }) (%s)\n",
01480         desktop, workarea.pos.x, workarea.pos.y, workarea.size.width, workarea.size.height,
01481         (role == WindowManager) ? "WM" : "Client");
01482 #endif
01483 
01484     if (role != WindowManager || desktop < 1) return;
01485 
01486     p->workarea[desktop - 1] = workarea;
01487 
01488     long *wa = new long[p->number_of_desktops * 4];
01489     int i, o;
01490     for (i = 0, o = 0; i < p->number_of_desktops; i++) {
01491     wa[o++] = p->workarea[i].pos.x;
01492     wa[o++] = p->workarea[i].pos.y;
01493     wa[o++] = p->workarea[i].size.width;
01494     wa[o++] = p->workarea[i].size.height;
01495     }
01496 
01497     XChangeProperty(p->display, p->root, net_workarea, XA_CARDINAL, 32,
01498             PropModeReplace, (unsigned char *) wa,
01499             p->number_of_desktops * 4);
01500 
01501     delete [] wa;
01502 }
01503 
01504 
01505 void NETRootInfo::setVirtualRoots(Window *windows, unsigned int count) {
01506     if (role != WindowManager) return;
01507 
01508     p->virtual_roots_count = count;
01509     p->virtual_roots = windows;
01510 
01511 #ifdef   NETWMDEBUG
01512     fprintf(stderr, "NETRootInfo::setVirtualRoots: setting list with %ld windows\n",
01513         p->virtual_roots_count);
01514 #endif
01515 
01516     XChangeProperty(p->display, p->root, net_virtual_roots, XA_WINDOW, 32,
01517             PropModeReplace, (unsigned char *) p->virtual_roots,
01518             p->virtual_roots_count);
01519 }
01520 
01521 
01522 void NETRootInfo::closeWindowRequest(Window window) {
01523 
01524 #ifdef    NETWMDEBUG
01525     fprintf(stderr, "NETRootInfo::closeWindowRequest: requesting close for 0x%lx\n",
01526         window);
01527 #endif
01528 
01529     XEvent e;
01530 
01531     e.xclient.type = ClientMessage;
01532     e.xclient.message_type = net_close_window;
01533     e.xclient.display = p->display;
01534     e.xclient.window = window;
01535     e.xclient.format = 32;
01536     e.xclient.data.l[0] = 0l;
01537     e.xclient.data.l[1] = 0l;
01538     e.xclient.data.l[2] = 0l;
01539     e.xclient.data.l[3] = 0l;
01540     e.xclient.data.l[4] = 0l;
01541 
01542     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01543 }
01544 
01545 
01546 void NETRootInfo::moveResizeRequest(Window window, int x_root, int y_root,
01547                     Direction direction)
01548 {
01549 
01550 #ifdef    NETWMDEBUG
01551     fprintf(stderr,
01552         "NETRootInfo::moveResizeRequest: requesting resize/move for 0x%lx (%d, %d, %d)\n",
01553         window, x_root, y_root, direction);
01554 #endif
01555 
01556     XEvent e;
01557 
01558     e.xclient.type = ClientMessage;
01559     e.xclient.message_type = net_wm_moveresize;
01560     e.xclient.display = p->display;
01561     e.xclient.window = window,
01562     e.xclient.format = 32;
01563     e.xclient.data.l[0] = x_root;
01564     e.xclient.data.l[1] = y_root;
01565     e.xclient.data.l[2] = direction;
01566     e.xclient.data.l[3] = 0l;
01567     e.xclient.data.l[4] = 0l;
01568 
01569     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01570 }
01571 
01572 void NETRootInfo::moveResizeWindowRequest(Window window, int flags, int x, int y, int width, int height )
01573 {
01574 
01575 #ifdef    NETWMDEBUG
01576     fprintf(stderr,
01577         "NETRootInfo::moveResizeWindowRequest: resizing/moving 0x%lx (%d, %d, %d, %d, %d)\n",
01578         window, flags, x, y, width, height);
01579 #endif
01580 
01581     XEvent e;
01582 
01583     e.xclient.type = ClientMessage;
01584     e.xclient.message_type = net_moveresize_window;
01585     e.xclient.display = p->display;
01586     e.xclient.window = window,
01587     e.xclient.format = 32;
01588     e.xclient.data.l[0] = flags;
01589     e.xclient.data.l[1] = x;
01590     e.xclient.data.l[2] = y;
01591     e.xclient.data.l[3] = width;
01592     e.xclient.data.l[4] = height;
01593 
01594     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01595 }
01596 
01597 void NETRootInfo::restackRequest(Window window, Window above, int detail)
01598 {
01599 #ifdef    NETWMDEBUG
01600     fprintf(stderr,
01601         "NETRootInfo::restackRequest: requesting restack for 0x%lx (%lx, %d)\n",
01602         window, above, detail);
01603 #endif
01604 
01605     XEvent e;
01606 
01607     e.xclient.type = ClientMessage;
01608     e.xclient.message_type = net_restack_window;
01609     e.xclient.display = p->display;
01610     e.xclient.window = window,
01611     e.xclient.format = 32;
01612     e.xclient.data.l[0] = FromTool;
01613     e.xclient.data.l[1] = above;
01614     e.xclient.data.l[2] = detail;
01615     e.xclient.data.l[3] = 0l;
01616     e.xclient.data.l[4] = 0l;
01617 
01618     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
01619 }
01620 
01621 void NETRootInfo2::sendPing( Window window, Time timestamp )
01622 {
01623     if (role != WindowManager) return;
01624 #ifdef   NETWMDEBUG
01625     fprintf(stderr, "NETRootInfo2::setPing: window 0x%lx, timestamp %lu\n",
01626     window, timestamp );
01627 #endif
01628     XEvent e;
01629     e.xclient.type = ClientMessage;
01630     e.xclient.message_type = wm_protocols;
01631     e.xclient.display = p->display;
01632     e.xclient.window = window,
01633     e.xclient.format = 32;
01634     e.xclient.data.l[0] = net_wm_ping;
01635     e.xclient.data.l[1] = timestamp;
01636     e.xclient.data.l[2] = window;
01637     e.xclient.data.l[3] = 0;
01638     e.xclient.data.l[4] = 0;
01639 
01640     XSendEvent(p->display, window, False, 0, &e);
01641 }
01642 
01643 
01644 
01645 
01646 
01647 const NETRootInfo &NETRootInfo::operator=(const NETRootInfo &rootinfo) {
01648 
01649 #ifdef   NETWMDEBUG
01650     fprintf(stderr, "NETRootInfo::operator=()\n");
01651 #endif
01652 
01653     if (p != rootinfo.p) {
01654     refdec_nri(p);
01655 
01656     if (! p->ref) delete p;
01657     }
01658 
01659     p = rootinfo.p;
01660     role = rootinfo.role;
01661     p->ref++;
01662 
01663     return *this;
01664 }
01665 
01666 unsigned long NETRootInfo::event(XEvent *ev )
01667 {
01668     unsigned long props[ 1 ];
01669     event( ev, props, 1 );
01670     return props[ 0 ];
01671 }
01672 
01673 void NETRootInfo::event(XEvent *event, unsigned long* properties, int properties_size )
01674 {
01675     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0, 0, 0, 0 };
01676     assert( PROPERTIES_SIZE == 5 ); 
01677     unsigned long& dirty = props[ PROTOCOLS ];
01678     unsigned long& dirty2 = props[ PROTOCOLS2 ];
01679     bool do_update = false;
01680 
01681     Q_UNUSED( dirty2 ); 
01682 
01683     
01684     
01685     if (role == WindowManager && event->type == ClientMessage &&
01686     event->xclient.format == 32) {
01687 #ifdef    NETWMDEBUG
01688     fprintf(stderr, "NETRootInfo::event: handling ClientMessage event\n");
01689 #endif
01690 
01691     if (event->xclient.message_type == net_number_of_desktops) {
01692         dirty = NumberOfDesktops;
01693 
01694 #ifdef   NETWMDEBUG
01695         fprintf(stderr, "NETRootInfo::event: changeNumberOfDesktops(%ld)\n",
01696             event->xclient.data.l[0]);
01697 #endif
01698 
01699         changeNumberOfDesktops(event->xclient.data.l[0]);
01700     } else if (event->xclient.message_type == net_desktop_geometry) {
01701         dirty = DesktopGeometry;
01702 
01703         NETSize sz;
01704         sz.width = event->xclient.data.l[0];
01705         sz.height = event->xclient.data.l[1];
01706 
01707 #ifdef    NETWMDEBUG
01708         fprintf(stderr, "NETRootInfo::event: changeDesktopGeometry( -- , { %d, %d })\n",
01709             sz.width, sz.height);
01710 #endif
01711 
01712         changeDesktopGeometry(~0, sz);
01713     } else if (event->xclient.message_type == net_desktop_viewport) {
01714         dirty = DesktopViewport;
01715 
01716         NETPoint pt;
01717         pt.x = event->xclient.data.l[0];
01718         pt.y = event->xclient.data.l[1];
01719 
01720 #ifdef   NETWMDEBUG
01721         fprintf(stderr, "NETRootInfo::event: changeDesktopViewport(%d, { %d, %d })\n",
01722             p->current_desktop, pt.x, pt.y);
01723 #endif
01724 
01725         changeDesktopViewport(p->current_desktop, pt);
01726     } else if (event->xclient.message_type == net_current_desktop) {
01727         dirty = CurrentDesktop;
01728 
01729 #ifdef   NETWMDEBUG
01730         fprintf(stderr, "NETRootInfo::event: changeCurrentDesktop(%ld)\n",
01731             event->xclient.data.l[0] + 1);
01732 #endif
01733 
01734         changeCurrentDesktop(event->xclient.data.l[0] + 1);
01735     } else if (event->xclient.message_type == net_active_window) {
01736         dirty = ActiveWindow;
01737 
01738 #ifdef    NETWMDEBUG
01739         fprintf(stderr, "NETRootInfo::event: changeActiveWindow(0x%lx)\n",
01740             event->xclient.window);
01741 #endif
01742 
01743         changeActiveWindow(event->xclient.window);
01744         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
01745             {
01746                 RequestSource src = FromUnknown;
01747                 Time timestamp = CurrentTime;
01748                 Window active_window = None;
01749                 
01750                 if( event->xclient.data.l[0] >= FromUnknown
01751                     && event->xclient.data.l[0] <= FromTool )
01752                     {
01753                     src = static_cast< RequestSource >( event->xclient.data.l[0] );
01754                     timestamp = event->xclient.data.l[1];
01755                     active_window = event->xclient.data.l[2];
01756                     }
01757         this2->changeActiveWindow( event->xclient.window, src, timestamp, active_window );
01758             }
01759     } else if (event->xclient.message_type == net_wm_moveresize) {
01760 
01761 #ifdef    NETWMDEBUG
01762         fprintf(stderr, "NETRootInfo::event: moveResize(%ld, %ld, %ld, %ld)\n",
01763             event->xclient.window,
01764             event->xclient.data.l[0],
01765             event->xclient.data.l[1],
01766             event->xclient.data.l[2]
01767             );
01768 #endif
01769 
01770         moveResize(event->xclient.window,
01771                event->xclient.data.l[0],
01772                event->xclient.data.l[1],
01773                event->xclient.data.l[2]);
01774     } else if (event->xclient.message_type == net_moveresize_window) {
01775 
01776 #ifdef    NETWMDEBUG
01777         fprintf(stderr, "NETRootInfo::event: moveResizeWindow(%ld, %ld, %ld, %ld, %ld, %ld)\n",
01778             event->xclient.window,
01779             event->xclient.data.l[0],
01780             event->xclient.data.l[1],
01781             event->xclient.data.l[2],
01782             event->xclient.data.l[3],
01783             event->xclient.data.l[4]
01784             );
01785 #endif
01786 
01787         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
01788             this2->moveResizeWindow(event->xclient.window,
01789                    event->xclient.data.l[0],
01790                    event->xclient.data.l[1],
01791                    event->xclient.data.l[2],
01792                    event->xclient.data.l[3],
01793                    event->xclient.data.l[4]);
01794     } else if (event->xclient.message_type == net_close_window) {
01795 
01796 #ifdef   NETWMDEBUG
01797         fprintf(stderr, "NETRootInfo::event: closeWindow(0x%lx)\n",
01798             event->xclient.window);
01799 #endif
01800 
01801         closeWindow(event->xclient.window);
01802     } else if (event->xclient.message_type == net_restack_window) {
01803 
01804 #ifdef   NETWMDEBUG
01805         fprintf(stderr, "NETRootInfo::event: restackWindow(0x%lx)\n",
01806             event->xclient.window);
01807 #endif
01808 
01809         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
01810             this2->restackWindow(event->xclient.window,
01811                     event->xclient.data.l[1], event->xclient.data.l[2]);
01812     } else if (event->xclient.message_type == wm_protocols
01813         && (Atom)event->xclient.data.l[ 0 ] == net_wm_ping) {
01814         dirty = WMPing;
01815 
01816 #ifdef   NETWMDEBUG
01817         fprintf(stderr, "NETRootInfo2::event: gotPing(0x%lx,%lu)\n",
01818         event->xclient.window, event->xclient.data.l[1]);
01819 #endif
01820         if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
01821         this2->gotPing( event->xclient.data.l[2], event->xclient.data.l[1]);
01822     }
01823     }
01824 
01825     if (event->type == PropertyNotify) {
01826 
01827 #ifdef    NETWMDEBUG
01828     fprintf(stderr, "NETRootInfo::event: handling PropertyNotify event\n");
01829 #endif
01830 
01831     XEvent pe = *event;
01832 
01833     Bool done = False;
01834     Bool compaction = False;
01835     while (! done) {
01836 
01837 #ifdef   NETWMDEBUG
01838         fprintf(stderr, "NETRootInfo::event: loop fire\n");
01839 #endif
01840 
01841         if (pe.xproperty.atom == net_client_list)
01842         dirty |= ClientList;
01843         else if (pe.xproperty.atom == net_client_list_stacking)
01844         dirty |= ClientListStacking;
01845         else if (pe.xproperty.atom == kde_net_system_tray_windows)
01846         dirty |= KDESystemTrayWindows;
01847         else if (pe.xproperty.atom == net_desktop_names)
01848         dirty |= DesktopNames;
01849         else if (pe.xproperty.atom == net_workarea)
01850         dirty |= WorkArea;
01851         else if (pe.xproperty.atom == net_number_of_desktops)
01852         dirty |= NumberOfDesktops;
01853         else if (pe.xproperty.atom == net_desktop_geometry)
01854         dirty |= DesktopGeometry;
01855         else if (pe.xproperty.atom == net_desktop_viewport)
01856         dirty |= DesktopViewport;
01857         else if (pe.xproperty.atom == net_current_desktop)
01858         dirty |= CurrentDesktop;
01859         else if (pe.xproperty.atom == net_active_window)
01860         dirty |= ActiveWindow;
01861         else {
01862 
01863 #ifdef    NETWMDEBUG
01864         fprintf(stderr, "NETRootInfo::event: putting back event and breaking\n");
01865 #endif
01866 
01867         if ( compaction )
01868             XPutBackEvent(p->display, &pe);
01869         break;
01870         }
01871 
01872         if (XCheckTypedWindowEvent(p->display, p->root, PropertyNotify, &pe) )
01873         compaction = True;
01874         else
01875         break;
01876     }
01877 
01878     do_update = true;
01879     }
01880 
01881     if( do_update )
01882         update( props );
01883 
01884 #ifdef   NETWMDEBUG
01885      fprintf(stderr, "NETRootInfo::event: handled events, returning dirty = 0x%lx, 0x%lx\n",
01886         dirty, dirty2);
01887 #endif
01888 
01889     if( properties_size > PROPERTIES_SIZE )
01890         properties_size = PROPERTIES_SIZE;
01891     for( int i = 0;
01892          i < properties_size;
01893          ++i )
01894         properties[ i ] = props[ i ];
01895 }
01896 
01897 
01898 
01899 
01900 void NETRootInfo::update( const unsigned long dirty_props[] )
01901 {
01902     Atom type_ret;
01903     int format_ret;
01904     unsigned char *data_ret;
01905     unsigned long nitems_ret, unused;
01906     unsigned long props[ PROPERTIES_SIZE ];
01907     for( int i = 0;
01908          i < PROPERTIES_SIZE;
01909          ++i )
01910         props[ i ] = dirty_props[ i ] & p->client_properties[ i ];
01911     const unsigned long& dirty = props[ PROTOCOLS ];
01912     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
01913 
01914     Q_UNUSED( dirty2 ); 
01915 
01916     if (dirty & Supported ) {
01917         
01918         for( int i = 0; i < PROPERTIES_SIZE; ++i )
01919             p->properties[ i ] = 0;
01920         if( XGetWindowProperty(p->display, p->root, net_supported,
01921                                0l, MAX_PROP_SIZE, False, XA_ATOM, &type_ret,
01922                                &format_ret, &nitems_ret, &unused, &data_ret)
01923             == Success ) {
01924             if( type_ret == XA_ATOM && format_ret == 32 ) {
01925                 Atom* atoms = (Atom*) data_ret;
01926                 for( unsigned int i = 0;
01927                      i < nitems_ret;
01928                      ++i )
01929                     updateSupportedProperties( atoms[ i ] );
01930             }
01931         if ( data_ret )
01932         XFree(data_ret);
01933         }
01934     }
01935 
01936     if (dirty & ClientList) {
01937         bool read_ok = false;
01938     if (XGetWindowProperty(p->display, p->root, net_client_list,
01939                    0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
01940                    &format_ret, &nitems_ret, &unused, &data_ret)
01941         == Success) {
01942         if (type_ret == XA_WINDOW && format_ret == 32) {
01943         Window *wins = (Window *) data_ret;
01944 
01945         qsort(wins, nitems_ret, sizeof(Window), wcmp);
01946 
01947         if (p->clients) {
01948             if (role == Client) {
01949             unsigned long new_index = 0, old_index = 0;
01950             unsigned long new_count = nitems_ret,
01951                       old_count = p->clients_count;
01952 
01953             while (old_index < old_count || new_index < new_count) {
01954                 if (old_index == old_count) {
01955                 addClient(wins[new_index++]);
01956                 } else if (new_index == new_count) {
01957                 removeClient(p->clients[old_index++]);
01958                 } else {
01959                 if (p->clients[old_index] <
01960                     wins[new_index]) {
01961                     removeClient(p->clients[old_index++]);
01962                 } else if (wins[new_index] <
01963                        p->clients[old_index]) {
01964                     addClient(wins[new_index++]);
01965                 } else {
01966                     new_index++;
01967                     old_index++;
01968                 }
01969                 }
01970             }
01971             }
01972 
01973             delete [] p->clients;
01974         } else {
01975 #ifdef    NETWMDEBUG
01976             fprintf(stderr, "NETRootInfo::update: client list null, creating\n");
01977 #endif
01978 
01979             unsigned long n;
01980             for (n = 0; n < nitems_ret; n++) {
01981             addClient(wins[n]);
01982             }
01983         }
01984 
01985         p->clients_count = nitems_ret;
01986         p->clients = nwindup(wins, p->clients_count);
01987                 read_ok = true;
01988         }
01989 
01990         if ( data_ret )
01991         XFree(data_ret);
01992     }
01993         if( !read_ok ) {
01994             for( unsigned int i = 0; i < p->clients_count; ++ i )
01995             removeClient(p->clients[i]);
01996             p->clients_count = 0;
01997             delete[] p->clients;
01998             p->clients = NULL;
01999         }
02000 
02001 #ifdef    NETWMDEBUG
02002     fprintf(stderr, "NETRootInfo::update: client list updated (%ld clients)\n",
02003         p->clients_count);
02004 #endif
02005     }
02006 
02007     if (dirty & KDESystemTrayWindows) {
02008         bool read_ok = false;
02009     if (XGetWindowProperty(p->display, p->root, kde_net_system_tray_windows,
02010                    0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
02011                    &format_ret, &nitems_ret, &unused, &data_ret)
02012         == Success) {
02013         if (type_ret == XA_WINDOW && format_ret == 32) {
02014         Window *wins = (Window *) data_ret;
02015 
02016         qsort(wins, nitems_ret, sizeof(Window), wcmp);
02017 
02018         if (p->kde_system_tray_windows) {
02019             if (role == Client) {
02020             unsigned long new_index = 0, new_count = nitems_ret;
02021             unsigned long old_index = 0,
02022                       old_count = p->kde_system_tray_windows_count;
02023 
02024             while(old_index < old_count || new_index < new_count) {
02025                 if (old_index == old_count) {
02026                 addSystemTrayWin(wins[new_index++]);
02027                 } else if (new_index == new_count) {
02028                 removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
02029                 } else {
02030                 if (p->kde_system_tray_windows[old_index] <
02031                     wins[new_index]) {
02032                     removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
02033                 } else if (wins[new_index] <
02034                        p->kde_system_tray_windows[old_index]) {
02035                     addSystemTrayWin(wins[new_index++]);
02036                 } else {
02037                     new_index++;
02038                     old_index++;
02039                 }
02040                 }
02041             }
02042             }
02043 
02044         } else {
02045             unsigned long n;
02046             for (n = 0; n < nitems_ret; n++) {
02047             addSystemTrayWin(wins[n]);
02048             }
02049         }
02050 
02051         p->kde_system_tray_windows_count = nitems_ret;
02052         delete [] p->kde_system_tray_windows;
02053         p->kde_system_tray_windows =
02054             nwindup(wins, p->kde_system_tray_windows_count);
02055                 read_ok = true;
02056         }
02057 
02058         if ( data_ret )
02059         XFree(data_ret);
02060     }
02061         if( !read_ok ) {
02062             for( unsigned int i = 0; i < p->kde_system_tray_windows_count; ++i )
02063                 removeSystemTrayWin(p->kde_system_tray_windows[i]);
02064             p->kde_system_tray_windows_count = 0;
02065         delete [] p->kde_system_tray_windows;
02066             p->kde_system_tray_windows = NULL;
02067         }
02068     }
02069 
02070     if (dirty & ClientListStacking) {
02071         p->stacking_count = 0;
02072         delete[] p->stacking;
02073         p->stacking = NULL;
02074     if (XGetWindowProperty(p->display, p->root, net_client_list_stacking,
02075                    0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
02076                    &format_ret, &nitems_ret, &unused, &data_ret)
02077         == Success) {
02078         if (type_ret == XA_WINDOW && format_ret == 32) {
02079         Window *wins = (Window *) data_ret;
02080 
02081         p->stacking_count = nitems_ret;
02082         p->stacking = nwindup(wins, p->stacking_count);
02083         }
02084 
02085 #ifdef    NETWMDEBUG
02086         fprintf(stderr,"NETRootInfo::update: client stacking updated (%ld clients)\n",
02087             p->stacking_count);
02088 #endif
02089 
02090         if ( data_ret )
02091         XFree(data_ret);
02092     }
02093     }
02094 
02095     if (dirty & NumberOfDesktops) {
02096     p->number_of_desktops = 0;
02097 
02098     if (XGetWindowProperty(p->display, p->root, net_number_of_desktops,
02099                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
02100                    &nitems_ret, &unused, &data_ret)
02101         == Success) {
02102         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
02103         p->number_of_desktops = *((long *) data_ret);
02104         }
02105 
02106 #ifdef    NETWMDEBUG
02107         fprintf(stderr, "NETRootInfo::update: number of desktops = %d\n",
02108             p->number_of_desktops);
02109 #endif
02110         if ( data_ret )
02111         XFree(data_ret);
02112     }
02113     }
02114 
02115     if (dirty & DesktopGeometry) {
02116         p->geometry = p->rootSize;
02117     if (XGetWindowProperty(p->display, p->root, net_desktop_geometry,
02118                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
02119                    &nitems_ret, &unused, &data_ret)
02120         == Success) {
02121         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02122         nitems_ret == 2) {
02123         long *data = (long *) data_ret;
02124 
02125         p->geometry.width  = data[0];
02126         p->geometry.height = data[1];
02127 
02128 #ifdef    NETWMDEBUG
02129         fprintf(stderr, "NETRootInfo::update: desktop geometry updated\n");
02130 #endif
02131         }
02132         if ( data_ret )
02133         XFree(data_ret);
02134     }
02135     }
02136 
02137     if (dirty & DesktopViewport) {
02138     for (int i = 0; i < p->viewport.size(); i++)
02139         p->viewport[i].x = p->viewport[i].y = 0;
02140     if (XGetWindowProperty(p->display, p->root, net_desktop_viewport,
02141                    0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
02142                    &nitems_ret, &unused, &data_ret)
02143         == Success) {
02144         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02145         nitems_ret == 2) {
02146         long *data = (long *) data_ret;
02147 
02148         int d, i, n;
02149         n = nitems_ret / 2;
02150         for (d = 0, i = 0; d < n; d++) {
02151             p->viewport[d].x = data[i++];
02152             p->viewport[d].y = data[i++];
02153         }
02154 
02155 #ifdef    NETWMDEBUG
02156         fprintf(stderr,
02157             "NETRootInfo::update: desktop viewport array updated (%d entries)\n",
02158             p->viewport.size());
02159 
02160         if (nitems_ret % 2 != 0) {
02161             fprintf(stderr,
02162                 "NETRootInfo::update(): desktop viewport array "
02163                 "size not a multiple of 2\n");
02164         }
02165 #endif
02166         }
02167         if ( data_ret )
02168         XFree(data_ret);
02169     }
02170     }
02171 
02172     if (dirty & CurrentDesktop) {
02173     p->current_desktop = 0;
02174     if (XGetWindowProperty(p->display, p->root, net_current_desktop,
02175                    0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
02176                    &nitems_ret, &unused, &data_ret)
02177         == Success) {
02178         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
02179         p->current_desktop = *((long *) data_ret) + 1;
02180         }
02181 
02182 #ifdef    NETWMDEBUG
02183         fprintf(stderr, "NETRootInfo::update: current desktop = %d\n",
02184             p->current_desktop);
02185 #endif
02186         if ( data_ret )
02187         XFree(data_ret);
02188     }
02189     }
02190 
02191     if (dirty & DesktopNames) {
02192         for( int i = 0; i < p->desktop_names.size(); ++i )
02193             delete[] p->desktop_names[ i ];
02194         p->desktop_names.reset();
02195     if (XGetWindowProperty(p->display, p->root, net_desktop_names,
02196                    0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
02197                    &format_ret, &nitems_ret, &unused, &data_ret)
02198         == Success) {
02199         if (type_ret == UTF8_STRING && format_ret == 8) {
02200         const char *d = (const char *) data_ret;
02201         unsigned int s, n, index;
02202 
02203         for (s = 0, n = 0, index = 0; n < nitems_ret; n++) {
02204             if (d[n] == '\0') {
02205             delete [] p->desktop_names[index];
02206             p->desktop_names[index++] = nstrndup((d + s), n - s + 1);
02207             s = n + 1;
02208             }
02209         }
02210         }
02211 
02212 #ifdef    NETWMDEBUG
02213         fprintf(stderr, "NETRootInfo::update: desktop names array updated (%d entries)\n",
02214             p->desktop_names.size());
02215 #endif
02216         if ( data_ret )
02217         XFree(data_ret);
02218     }
02219     }
02220 
02221     if (dirty & ActiveWindow) {
02222         p->active = None;
02223     if (XGetWindowProperty(p->display, p->root, net_active_window, 0l, 1l,
02224                    False, XA_WINDOW, &type_ret, &format_ret,
02225                    &nitems_ret, &unused, &data_ret)
02226         == Success) {
02227         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
02228         p->active = *((Window *) data_ret);
02229         }
02230 
02231 #ifdef    NETWMDEBUG
02232         fprintf(stderr, "NETRootInfo::update: active window = 0x%lx\n",
02233             p->active);
02234 #endif
02235         if ( data_ret )
02236         XFree(data_ret);
02237     }
02238     }
02239 
02240     if (dirty & WorkArea) {
02241         p->workarea.reset();
02242     if (XGetWindowProperty(p->display, p->root, net_workarea, 0l,
02243                    (p->number_of_desktops * 4), False, XA_CARDINAL,
02244                    &type_ret, &format_ret, &nitems_ret, &unused,
02245                    &data_ret)
02246         == Success) {
02247         if (type_ret == XA_CARDINAL && format_ret == 32 &&
02248         nitems_ret == (unsigned) (p->number_of_desktops * 4)) {
02249         long *d = (long *) data_ret;
02250         int i, j;
02251         for (i = 0, j = 0; i < p->number_of_desktops; i++) {
02252             p->workarea[i].pos.x       = d[j++];
02253             p->workarea[i].pos.y       = d[j++];
02254             p->workarea[i].size.width  = d[j++];
02255             p->workarea[i].size.height = d[j++];
02256         }
02257         }
02258 
02259 #ifdef    NETWMDEBUG
02260         fprintf(stderr, "NETRootInfo::update: work area array updated (%d entries)\n",
02261             p->workarea.size());
02262 #endif
02263         if ( data_ret )
02264         XFree(data_ret);
02265     }
02266     }
02267 
02268 
02269     if (dirty & SupportingWMCheck) {
02270         p->supportwindow = None;
02271         delete[] p->name;
02272         p->name = NULL;
02273     if (XGetWindowProperty(p->display, p->root, net_supporting_wm_check,
02274                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
02275                    &nitems_ret, &unused, &data_ret)
02276         == Success) {
02277         if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
02278         p->supportwindow = *((Window *) data_ret);
02279 
02280         unsigned char *name_ret;
02281         if (XGetWindowProperty(p->display, p->supportwindow,
02282                        net_wm_name, 0l, MAX_PROP_SIZE, False,
02283                        UTF8_STRING, &type_ret, &format_ret,
02284                        &nitems_ret, &unused, &name_ret)
02285             == Success) {
02286             if (type_ret == UTF8_STRING && format_ret == 8)
02287             p->name = nstrndup((const char *) name_ret, nitems_ret);
02288 
02289             if ( name_ret )
02290             XFree(name_ret);
02291         }
02292         }
02293 
02294 #ifdef    NETWMDEBUG
02295         fprintf(stderr,
02296             "NETRootInfo::update: supporting window manager = '%s'\n",
02297             p->name);
02298 #endif
02299         if ( data_ret )
02300         XFree(data_ret);
02301     }
02302     }
02303 
02304     if (dirty & VirtualRoots) {
02305         p->virtual_roots_count = 0;
02306         delete[] p->virtual_roots;
02307         p->virtual_roots = NULL;
02308     if (XGetWindowProperty(p->display, p->root, net_virtual_roots,
02309                    0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
02310                    &format_ret, &nitems_ret, &unused, &data_ret)
02311         == Success) {
02312         if (type_ret == XA_WINDOW && format_ret == 32) {
02313         Window *wins = (Window *) data_ret;
02314 
02315         p->virtual_roots_count = nitems_ret;
02316         p->virtual_roots = nwindup(wins, p->virtual_roots_count);
02317         }
02318 
02319 #ifdef    NETWMDEBUG
02320         fprintf(stderr, "NETRootInfo::updated: virtual roots updated (%ld windows)\n",
02321             p->virtual_roots_count);
02322 #endif
02323         if ( data_ret )
02324         XFree(data_ret);
02325     }
02326     }
02327 }
02328 
02329 
02330 Display *NETRootInfo::x11Display() const {
02331     return p->display;
02332 }
02333 
02334 
02335 Window NETRootInfo::rootWindow() const {
02336     return p->root;
02337 }
02338 
02339 
02340 Window NETRootInfo::supportWindow() const {
02341     return p->supportwindow;
02342 }
02343 
02344 
02345 const char *NETRootInfo::wmName() const {
02346     return p->name; }
02347 
02348 
02349 int NETRootInfo::screenNumber() const {
02350     return p->screen;
02351 }
02352 
02353 
02354 unsigned long NETRootInfo::supported() const {
02355     return role == WindowManager
02356         ? p->properties[ PROTOCOLS ]
02357         : p->client_properties[ PROTOCOLS ];
02358 }
02359 
02360 const unsigned long* NETRootInfo::supportedProperties() const {
02361     return p->properties;
02362 }
02363 
02364 const unsigned long* NETRootInfo::passedProperties() const {
02365     return role == WindowManager
02366         ? p->properties
02367         : p->client_properties;
02368 }
02369 
02370 bool NETRootInfo::isSupported( NET::Property property ) const {
02371     return p->properties[ PROTOCOLS ] & property;
02372 }
02373 
02374 bool NETRootInfo::isSupported( NET::Property2 property ) const {
02375     return p->properties[ PROTOCOLS2 ] & property;
02376 }
02377 
02378 bool NETRootInfo::isSupported( NET::WindowType type ) const {
02379     return p->properties[ WINDOW_TYPES ] & type;
02380 }
02381 
02382 bool NETRootInfo::isSupported( NET::State state ) const {
02383     return p->properties[ STATES ] & state;
02384 }
02385 
02386 bool NETRootInfo::isSupported( NET::Action action ) const {
02387     return p->properties[ ACTIONS ] & action;
02388 }
02389 
02390 const Window *NETRootInfo::clientList() const {
02391     return p->clients;
02392 }
02393 
02394 
02395 int NETRootInfo::clientListCount() const {
02396     return p->clients_count;
02397 }
02398 
02399 
02400 const Window *NETRootInfo::clientListStacking() const {
02401     return p->stacking;
02402 }
02403 
02404 
02405 int NETRootInfo::clientListStackingCount() const {
02406     return p->stacking_count;
02407 }
02408 
02409 
02410 const Window *NETRootInfo::kdeSystemTrayWindows() const {
02411     return p->kde_system_tray_windows;
02412 }
02413 
02414 
02415 int NETRootInfo::kdeSystemTrayWindowsCount() const {
02416     return p->kde_system_tray_windows_count;
02417 }
02418 
02419 
02420 NETSize NETRootInfo::desktopGeometry(int) const {
02421     return p->geometry.width != 0 ? p->geometry : p->rootSize;
02422 }
02423 
02424 
02425 NETPoint NETRootInfo::desktopViewport(int desktop) const {
02426     if (desktop < 1) {
02427     NETPoint pt; 
02428     return pt;
02429     }
02430 
02431     return p->viewport[desktop - 1];
02432 }
02433 
02434 
02435 NETRect NETRootInfo::workArea(int desktop) const {
02436     if (desktop < 1) {
02437     NETRect rt;
02438     return rt;
02439     }
02440 
02441     return p->workarea[desktop - 1];
02442 }
02443 
02444 
02445 const char *NETRootInfo::desktopName(int desktop) const {
02446     if (desktop < 1) {
02447     return 0;
02448     }
02449 
02450     return p->desktop_names[desktop - 1];
02451 }
02452 
02453 
02454 const Window *NETRootInfo::virtualRoots( ) const {
02455     return p->virtual_roots;
02456 }
02457 
02458 
02459 int NETRootInfo::virtualRootsCount() const {
02460     return p->virtual_roots_count;
02461 }
02462 
02463 
02464 int NETRootInfo::numberOfDesktops() const {
02465     return p->number_of_desktops == 0 ? 1 : p->number_of_desktops;
02466 }
02467 
02468 
02469 int NETRootInfo::currentDesktop() const {
02470     return p->current_desktop == 0 ? 1 : p->current_desktop;
02471 }
02472 
02473 
02474 Window NETRootInfo::activeWindow() const {
02475     return p->active;
02476 }
02477 
02478 
02479 
02480 
02481 const int NETWinInfo::OnAllDesktops = NET::OnAllDesktops;
02482 
02483 NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
02484                const unsigned long properties[], int properties_size,
02485                        Role role)
02486 {
02487 
02488 #ifdef   NETWMDEBUG
02489     fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
02490         (role == WindowManager) ? "WindowManager" : "Client");
02491 #endif
02492 
02493     p = new NETWinInfoPrivate;
02494     p->ref = 1;
02495 
02496     p->display = display;
02497     p->window = window;
02498     p->root = rootWindow;
02499     p->mapping_state = Withdrawn;
02500     p->mapping_state_dirty = True;
02501     p->state = 0;
02502     p->types[ 0 ] = Unknown;
02503     p->name = (char *) 0;
02504     p->visible_name = (char *) 0;
02505     p->icon_name = (char *) 0;
02506     p->visible_icon_name = (char *) 0;
02507     p->desktop = p->pid = p->handled_icons = 0;
02508     p->user_time = -1U;
02509     p->startup_id = NULL;
02510     p->transient_for = None;
02511     p->window_group = None;
02512     p->allowed_actions = 0;
02513     p->has_net_support = false;
02514 
02515     
02516     
02517     
02518 
02519     p->kde_system_tray_win_for = 0;
02520 
02521     for( int i = 0;
02522          i < PROPERTIES_SIZE;
02523          ++i )
02524         p->properties[ i ] = 0;
02525     if( properties_size > PROPERTIES_SIZE )
02526         properties_size = PROPERTIES_SIZE;
02527     for( int i = 0;
02528          i < properties_size;
02529          ++i )
02530         p->properties[ i ] = properties[ i ];
02531 
02532     p->icon_count = 0;
02533 
02534     this->role = role;
02535 
02536     if (! netwm_atoms_created) create_atoms(p->display);
02537 
02538     update(p->properties);
02539 }
02540 
02541 
02542 NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
02543                unsigned long properties, Role role)
02544 {
02545 
02546 #ifdef   NETWMDEBUG
02547     fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
02548         (role == WindowManager) ? "WindowManager" : "Client");
02549 #endif
02550 
02551     p = new NETWinInfoPrivate;
02552     p->ref = 1;
02553 
02554     p->display = display;
02555     p->window = window;
02556     p->root = rootWindow;
02557     p->mapping_state = Withdrawn;
02558     p->mapping_state_dirty = True;
02559     p->state = 0;
02560     p->types[ 0 ] = Unknown;
02561     p->name = (char *) 0;
02562     p->visible_name = (char *) 0;
02563     p->icon_name = (char *) 0;
02564     p->visible_icon_name = (char *) 0;
02565     p->desktop = p->pid = p->handled_icons = 0;
02566     p->user_time = -1U;
02567     p->startup_id = NULL;
02568     p->transient_for = None;
02569     p->window_group = None;
02570     p->allowed_actions = 0;
02571     p->has_net_support = false;
02572 
02573     
02574     
02575     
02576 
02577     p->kde_system_tray_win_for = 0;
02578 
02579     for( int i = 0;
02580          i < PROPERTIES_SIZE;
02581          ++i )
02582         p->properties[ i ] = 0;
02583     p->properties[ PROTOCOLS ] = properties;
02584 
02585     p->icon_count = 0;
02586 
02587     this->role = role;
02588 
02589     if (! netwm_atoms_created) create_atoms(p->display);
02590 
02591     update(p->properties);
02592 }
02593 
02594 
02595 NETWinInfo::NETWinInfo(const NETWinInfo &wininfo) {
02596     p = wininfo.p;
02597     p->ref++;
02598 }
02599 
02600 
02601 NETWinInfo::~NETWinInfo() {
02602     refdec_nwi(p);
02603 
02604     if (! p->ref) delete p;
02605 }
02606 
02607 
02608 
02609 
02610 const NETWinInfo &NETWinInfo::operator=(const NETWinInfo &wininfo) {
02611 
02612 #ifdef   NETWMDEBUG
02613     fprintf(stderr, "NETWinInfo::operator=()\n");
02614 #endif
02615 
02616     if (p != wininfo.p) {
02617     refdec_nwi(p);
02618 
02619     if (! p->ref) delete p;
02620     }
02621 
02622     p = wininfo.p;
02623     role = wininfo.role;
02624     p->ref++;
02625 
02626     return *this;
02627 }
02628 
02629 
02630 void NETWinInfo::setIcon(NETIcon icon, Bool replace) {
02631     if (role != Client) return;
02632 
02633     int proplen, i, sz, j;
02634 
02635     if (replace) {
02636 
02637     for (i = 0; i < p->icons.size(); i++) {
02638         delete [] p->icons[i].data;
02639         p->icons[i].data = 0;
02640         p->icons[i].size.width = 0;
02641         p->icons[i].size.height = 0;
02642     }
02643 
02644     p->icon_count = 0;
02645     }
02646 
02647     
02648     p->icons[p->icon_count] = icon;
02649     p->icon_count++;
02650 
02651     
02652     NETIcon &ni = p->icons[p->icon_count - 1];
02653     sz = ni.size.width * ni.size.height;
02654     CARD32 *d = new CARD32[sz];
02655     ni.data = (unsigned char *) d;
02656     memcpy(d, icon.data, sz * sizeof(CARD32));
02657 
02658     
02659     for (i = 0, proplen = 0; i < p->icon_count; i++) {
02660     proplen += 2 + (p->icons[i].size.width *
02661             p->icons[i].size.height);
02662     }
02663 
02664     CARD32 *d32;
02665     long *prop = new long[proplen], *pprop = prop;
02666     for (i = 0; i < p->icon_count; i++) {
02667     
02668         *pprop++ = p->icons[i].size.width;
02669     *pprop++ = p->icons[i].size.height;
02670 
02671     
02672     sz = (p->icons[i].size.width * p->icons[i].size.height);
02673     d32 = (CARD32 *) p->icons[i].data;
02674     for (j = 0; j < sz; j++) *pprop++ = *d32++;
02675     }
02676 
02677     XChangeProperty(p->display, p->window, net_wm_icon, XA_CARDINAL, 32,
02678             PropModeReplace, (unsigned char *) prop, proplen);
02679 
02680     delete [] prop;
02681 }
02682 
02683 
02684 void NETWinInfo::setIconGeometry(NETRect geometry) {
02685     if (role != Client) return;
02686 
02687     p->icon_geom = geometry;
02688 
02689     long data[4];
02690     data[0] = geometry.pos.x;
02691     data[1] = geometry.pos.y;
02692     data[2] = geometry.size.width;
02693     data[3] = geometry.size.height;
02694 
02695     XChangeProperty(p->display, p->window, net_wm_icon_geometry, XA_CARDINAL,
02696             32, PropModeReplace, (unsigned char *) data, 4);
02697 }
02698 
02699 
02700 void NETWinInfo::setStrut(NETStrut strut) {
02701     if (role != Client) return;
02702 
02703     p->strut = strut;
02704 
02705     long data[4];
02706     data[0] = strut.left;
02707     data[1] = strut.right;
02708     data[2] = strut.top;
02709     data[3] = strut.bottom;
02710 
02711     XChangeProperty(p->display, p->window, net_wm_strut, XA_CARDINAL, 32,
02712             PropModeReplace, (unsigned char *) data, 4);
02713 }
02714 
02715 
02716 void NETWinInfo::setState(unsigned long state, unsigned long mask) {
02717     if (p->mapping_state_dirty)
02718     updateWMState();
02719 
02720     if (role == Client && p->mapping_state != Withdrawn) {
02721 
02722 #ifdef NETWMDEBUG
02723         fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n",
02724                 state, mask);
02725 #endif // NETWMDEBUG
02726 
02727     XEvent e;
02728     e.xclient.type = ClientMessage;
02729     e.xclient.message_type = net_wm_state;
02730     e.xclient.display = p->display;
02731     e.xclient.window = p->window;
02732     e.xclient.format = 32;
02733     e.xclient.data.l[3] = 0l;
02734     e.xclient.data.l[4] = 0l;
02735 
02736     if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
02737         e.xclient.data.l[0] = (state & Modal) ? 1 : 0;
02738         e.xclient.data.l[1] = net_wm_state_modal;
02739         e.xclient.data.l[2] = 0l;
02740 
02741         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02742     }
02743 
02744     if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
02745         e.xclient.data.l[0] = (state & Sticky) ? 1 : 0;
02746         e.xclient.data.l[1] = net_wm_state_sticky;
02747         e.xclient.data.l[2] = 0l;
02748 
02749         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02750     }
02751 
02752     if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) {
02753 
02754         unsigned long wishstate = (p->state & ~mask) | (state & mask);
02755         if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) )
02756          && ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) {
02757         if ( (wishstate & Max) == Max ) {
02758             e.xclient.data.l[0] = 1;
02759             e.xclient.data.l[1] = net_wm_state_max_horiz;
02760             e.xclient.data.l[2] = net_wm_state_max_vert;
02761             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02762         } else if ( (wishstate & Max) == 0 ) {
02763             e.xclient.data.l[0] = 0;
02764             e.xclient.data.l[1] = net_wm_state_max_horiz;
02765             e.xclient.data.l[2] = net_wm_state_max_vert;
02766             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02767         } else {
02768             e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
02769             e.xclient.data.l[1] = net_wm_state_max_horiz;
02770             e.xclient.data.l[2] = 0;
02771             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02772             e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
02773             e.xclient.data.l[1] = net_wm_state_max_vert;
02774             e.xclient.data.l[2] = 0;
02775             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02776         }
02777         } else  if ( (wishstate & MaxVert) != (p->state & MaxVert) ) {
02778         e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
02779         e.xclient.data.l[1] = net_wm_state_max_vert;
02780         e.xclient.data.l[2] = 0;
02781         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02782         } else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) {
02783         e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
02784         e.xclient.data.l[1] = net_wm_state_max_horiz;
02785         e.xclient.data.l[2] = 0;
02786         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02787         }
02788     }
02789 
02790     if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
02791         e.xclient.data.l[0] = (state & Shaded) ? 1 : 0;
02792         e.xclient.data.l[1] = net_wm_state_shaded;
02793         e.xclient.data.l[2] = 0l;
02794 
02795         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02796     }
02797 
02798     if ((mask & SkipTaskbar) &&
02799         ((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
02800         e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0;
02801         e.xclient.data.l[1] = net_wm_state_skip_taskbar;
02802         e.xclient.data.l[2] = 0l;
02803 
02804         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02805     }
02806 
02807         if ((mask & SkipPager) &&
02808         ((p->state & SkipPager) != (state & SkipPager))) {
02809             e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0;
02810             e.xclient.data.l[1] = net_wm_state_skip_pager;
02811             e.xclient.data.l[2] = 0l;
02812 
02813             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02814         }
02815 
02816         if ((mask & Hidden) &&
02817         ((p->state & Hidden) != (state & Hidden))) {
02818             e.xclient.data.l[0] = (state & Hidden) ? 1 : 0;
02819             e.xclient.data.l[1] = net_wm_state_hidden;
02820             e.xclient.data.l[2] = 0l;
02821 
02822             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02823         }
02824 
02825         if ((mask & FullScreen) &&
02826         ((p->state & FullScreen) != (state & FullScreen))) {
02827             e.xclient.data.l[0] = (state & FullScreen) ? 1 : 0;
02828             e.xclient.data.l[1] = net_wm_state_fullscreen;
02829             e.xclient.data.l[2] = 0l;
02830 
02831             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02832         }
02833 
02834         if ((mask & KeepAbove) &&
02835         ((p->state & KeepAbove) != (state & KeepAbove))) {
02836             e.xclient.data.l[0] = (state & KeepAbove) ? 1 : 0;
02837             e.xclient.data.l[1] = net_wm_state_above;
02838             e.xclient.data.l[2] = 0l;
02839 
02840             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02841         }
02842 
02843         if ((mask & KeepBelow) &&
02844         ((p->state & KeepBelow) != (state & KeepBelow))) {
02845             e.xclient.data.l[0] = (state & KeepBelow) ? 1 : 0;
02846             e.xclient.data.l[1] = net_wm_state_below;
02847             e.xclient.data.l[2] = 0l;
02848 
02849             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02850         }
02851 
02852     if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) {
02853         e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0;
02854         e.xclient.data.l[1] = net_wm_state_stays_on_top;
02855         e.xclient.data.l[2] = 0l;
02856 
02857         XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02858     }
02859 
02860         if ((mask & DemandsAttention) &&
02861         ((p->state & DemandsAttention) != (state & DemandsAttention))) {
02862             e.xclient.data.l[0] = (state & DemandsAttention) ? 1 : 0;
02863             e.xclient.data.l[1] = net_wm_state_demands_attention;
02864             e.xclient.data.l[2] = 0l;
02865 
02866             XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
02867         }
02868 
02869     } else {
02870     p->state &= ~mask;
02871     p->state |= state;
02872 
02873     long data[50];
02874     int count = 0;
02875 
02876     
02877     if (p->state & Modal) data[count++] = net_wm_state_modal;
02878     if (p->state & MaxVert) data[count++] = net_wm_state_max_vert;
02879     if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz;
02880     if (p->state & Shaded) data[count++] = net_wm_state_shaded;
02881     if (p->state & Hidden) data[count++] = net_wm_state_hidden;
02882     if (p->state & FullScreen) data[count++] = net_wm_state_fullscreen;
02883     if (p->state & DemandsAttention) data[count++] = net_wm_state_demands_attention;
02884 
02885     
02886     if (p->state & KeepAbove) data[count++] = net_wm_state_above;
02887     if (p->state & KeepBelow) data[count++] = net_wm_state_below;
02888     if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top;
02889     if (p->state & Sticky) data[count++] = net_wm_state_sticky;
02890     if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar;
02891     if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager;
02892 
02893 #ifdef NETWMDEBUG
02894     fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
02895     for (int i = 0; i < count; i++) {
02896             char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
02897         fprintf(stderr, "NETWinInfo::setState:   state %ld '%s'\n",
02898             data[i], data_ret);
02899             if ( data_ret )
02900                 XFree( data_ret );
02901         }
02902 
02903 #endif
02904 
02905     XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32,
02906             PropModeReplace, (unsigned char *) data, count);
02907     }
02908 }
02909 
02910 
02911 void NETWinInfo::setWindowType(WindowType type) {
02912     if (role != Client) return;
02913 
02914     int len;
02915     long data[2];
02916 
02917     switch (type) {
02918     case Override:
02919     
02920     
02921     data[0] = kde_net_wm_window_type_override;
02922     data[1] = net_wm_window_type_normal;
02923     len = 2;
02924     break;
02925 
02926     case  Dialog:
02927     data[0] = net_wm_window_type_dialog;
02928     data[1] = None;
02929     len = 1;
02930     break;
02931 
02932     case Menu:
02933     data[0] = net_wm_window_type_menu;
02934     data[1] = None;
02935     len = 1;
02936     break;
02937 
02938     case TopMenu:
02939     
02940     
02941     data[0] = kde_net_wm_window_type_topmenu;
02942     data[1] = net_wm_window_type_dock;
02943     len = 2;
02944     break;
02945 
02946     case Tool:
02947     data[0] = net_wm_window_type_toolbar;
02948     data[1] = None;
02949     len = 1;
02950     break;
02951 
02952     case Dock:
02953     data[0] = net_wm_window_type_dock;
02954     data[1] = None;
02955     len = 1;
02956     break;
02957 
02958     case Desktop:
02959     data[0] = net_wm_window_type_desktop;
02960     data[1] = None;
02961     len = 1;
02962     break;
02963 
02964     case Utility:
02965     data[0] = net_wm_window_type_utility;
02966     data[1] = net_wm_window_type_dialog; 
02967     len = 2;
02968     break;
02969 
02970     case Splash:
02971     data[0] = net_wm_window_type_splash;
02972     data[1] = net_wm_window_type_dock; 
02973     len = 2;
02974     break;
02975 
02976     default:
02977     case Normal:
02978     data[0] = net_wm_window_type_normal;
02979     data[1] = None;
02980     len = 1;
02981     break;
02982     }
02983 
02984     XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32,
02985             PropModeReplace, (unsigned char *) &data, len);
02986 }
02987 
02988 
02989 void NETWinInfo::setName(const char *name) {
02990     if (role != Client) return;
02991 
02992     delete [] p->name;
02993     p->name = nstrdup(name);
02994     if( p->name[ 0 ] != '\0' )
02995         XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8,
02996             PropModeReplace, (unsigned char *) p->name,
02997             strlen(p->name));
02998     else
02999         XDeleteProperty(p->display, p->window, net_wm_name);
03000 }
03001 
03002 
03003 void NETWinInfo::setVisibleName(const char *visibleName) {
03004     if (role != WindowManager) return;
03005 
03006     delete [] p->visible_name;
03007     p->visible_name = nstrdup(visibleName);
03008     if( p->visible_name[ 0 ] != '\0' )
03009         XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8,
03010             PropModeReplace, (unsigned char *) p->visible_name,
03011             strlen(p->visible_name));
03012     else
03013         XDeleteProperty(p->display, p->window, net_wm_visible_name);
03014 }
03015 
03016 
03017 void NETWinInfo::setIconName(const char *iconName) {
03018     if (role != Client) return;
03019 
03020     delete [] p->icon_name;
03021     p->icon_name = nstrdup(iconName);
03022     if( p->icon_name[ 0 ] != '\0' )
03023         XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8,
03024             PropModeReplace, (unsigned char *) p->icon_name,
03025             strlen(p->icon_name));
03026     else
03027         XDeleteProperty(p->display, p->window, net_wm_icon_name);
03028 }
03029 
03030 
03031 void NETWinInfo::setVisibleIconName(const char *visibleIconName) {
03032     if (role != WindowManager) return;
03033 
03034     delete [] p->visible_icon_name;
03035     p->visible_icon_name = nstrdup(visibleIconName);
03036     if( p->visible_icon_name[ 0 ] != '\0' )
03037         XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8,
03038             PropModeReplace, (unsigned char *) p->visible_icon_name,
03039             strlen(p->visible_icon_name));
03040     else
03041         XDeleteProperty(p->display, p->window, net_wm_visible_icon_name);
03042 }
03043 
03044 
03045 void NETWinInfo::setDesktop(int desktop) {
03046     if (p->mapping_state_dirty)
03047     updateWMState();
03048 
03049     if (role == Client && p->mapping_state != Withdrawn) {
03050     
03051 
03052     if ( desktop == 0 )
03053         return; 
03054 
03055     XEvent e;
03056 
03057     e.xclient.type = ClientMessage;
03058     e.xclient.message_type = net_wm_desktop;
03059     e.xclient.display = p->display;
03060     e.xclient.window = p->window;
03061     e.xclient.format = 32;
03062     e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1;
03063     e.xclient.data.l[1] = 0l;
03064     e.xclient.data.l[2] = 0l;
03065     e.xclient.data.l[3] = 0l;
03066     e.xclient.data.l[4] = 0l;
03067 
03068     XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
03069     } else {
03070     
03071     p->desktop = desktop;
03072     long d = desktop;
03073 
03074     if ( d != OnAllDesktops ) {
03075         if ( d == 0 ) {
03076         XDeleteProperty( p->display, p->window, net_wm_desktop );
03077         return;
03078         }
03079 
03080         d -= 1;
03081     }
03082 
03083     XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32,
03084             PropModeReplace, (unsigned char *) &d, 1);
03085     }
03086 }
03087 
03088 
03089 void NETWinInfo::setPid(int pid) {
03090     if (role != Client) return;
03091 
03092     p->pid = pid;
03093     long d = pid;
03094     XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32,
03095             PropModeReplace, (unsigned char *) &d, 1);
03096 }
03097 
03098 
03099 void NETWinInfo::setHandledIcons(Bool handled) {
03100     if (role != Client) return;
03101 
03102     p->handled_icons = handled;
03103     long d = handled;
03104     XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32,
03105             PropModeReplace, (unsigned char *) &d, 1);
03106 }
03107 
03108 void NETWinInfo::setStartupId(const char* id) {
03109     if (role != Client) return;
03110 
03111     delete[] p->startup_id;
03112     p->startup_id = nstrdup(id);
03113     XChangeProperty(p->display, p->window, net_startup_id, UTF8_STRING, 8,
03114         PropModeReplace, reinterpret_cast< unsigned char* >( p->startup_id ),
03115         strlen( p->startup_id ));
03116 }
03117 
03118 void NETWinInfo::setAllowedActions( unsigned long actions ) {
03119     if( role != WindowManager )
03120         return;
03121     long data[50];
03122     int count = 0;
03123 
03124     p->allowed_actions = actions;
03125     if (p->allowed_actions & ActionMove) data[count++] = net_wm_action_move;
03126     if (p->allowed_actions & ActionResize) data[count++] = net_wm_action_resize;
03127     if (p->allowed_actions & ActionMinimize) data[count++] = net_wm_action_minimize;
03128     if (p->allowed_actions & ActionShade) data[count++] = net_wm_action_shade;
03129     if (p->allowed_actions & ActionStick) data[count++] = net_wm_action_stick;
03130     if (p->allowed_actions & ActionMaxVert) data[count++] = net_wm_action_max_vert;
03131     if (p->allowed_actions & ActionMaxHoriz) data[count++] = net_wm_action_max_horiz;
03132     if (p->allowed_actions & ActionFullScreen) data[count++] = net_wm_action_fullscreen;
03133     if (p->allowed_actions & ActionChangeDesktop) data[count++] = net_wm_action_change_desk;
03134     if (p->allowed_actions & ActionClose) data[count++] = net_wm_action_close;
03135 
03136 #ifdef NETWMDEBUG
03137     fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count);
03138     for (int i = 0; i < count; i++) {
03139         char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
03140         fprintf(stderr, "NETWinInfo::setAllowedActions:   action %ld '%s'\n",
03141         data[i], data_ret);
03142         if ( data_ret )
03143             XFree(data_ret);
03144     }
03145 #endif
03146 
03147     XChangeProperty(p->display, p->window, net_wm_allowed_actions, XA_ATOM, 32,
03148             PropModeReplace, (unsigned char *) data, count);
03149 }
03150 
03151 void NETWinInfo::setKDESystemTrayWinFor(Window window) {
03152     if (role != Client) return;
03153 
03154     p->kde_system_tray_win_for = window;
03155     XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
03156             XA_WINDOW, 32, PropModeReplace,
03157             (unsigned char *) &(p->kde_system_tray_win_for), 1);
03158 }
03159 
03160 
03161 void NETWinInfo::setKDEFrameStrut(NETStrut strut) {
03162     if (role != WindowManager) return;
03163 
03164     p->frame_strut = strut;
03165 
03166     long d[4];
03167     d[0] = strut.left;
03168     d[1] = strut.right;
03169     d[2] = strut.top;
03170     d[3] = strut.bottom;
03171 
03172     XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32,
03173             PropModeReplace, (unsigned char *) d, 4);
03174 }
03175 
03176 
03177 void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) {
03178     if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
03179     Window unused;
03180     int x, y;
03181     unsigned int w, h, junk;
03182     XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk);
03183     XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused
03184                   );
03185 
03186     p->win_geom.pos.x = x;
03187     p->win_geom.pos.y = y;
03188 
03189     p->win_geom.size.width = w;
03190     p->win_geom.size.height = h;
03191     }
03192 
03193     window = p->win_geom;
03194 
03195     frame.pos.x = window.pos.x - p->frame_strut.left;
03196     frame.pos.y = window.pos.y - p->frame_strut.top;
03197     frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
03198     frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
03199 }
03200 
03201 
03202 NETIcon NETWinInfo::icon(int width, int height) const {
03203     NETIcon result;
03204 
03205     if ( !p->icon_count ) {
03206     result.size.width = 0;
03207     result.size.height = 0;
03208     result.data = 0;
03209     return result;
03210     }
03211 
03212     result = p->icons[0];
03213 
03214     
03215     
03216     if (width == height && height == -1) return result;
03217 
03218     int i;
03219     for (i = 0; i < p->icons.size(); i++) {
03220     if ((p->icons[i].size.width >= width &&
03221          p->icons[i].size.width < result.size.width) &&
03222         (p->icons[i].size.height >= height &&
03223          p->icons[i].size.height < result.size.height))
03224         result = p->icons[i];
03225     }
03226 
03227     return result;
03228 }
03229 
03230 void NETWinInfo::setUserTime( Time time ) {
03231     if (role != Client) return;
03232 
03233     p->user_time = time;
03234     long d = time;
03235     XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32,
03236             PropModeReplace, (unsigned char *) &d, 1);
03237 }
03238 
03239 
03240 unsigned long NETWinInfo::event(XEvent *ev )
03241 {
03242     unsigned long props[ 1 ];
03243     event( ev, props, 1 );
03244     return props[ 0 ];
03245 }
03246 
03247 void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) {
03248     unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 };
03249     assert( PROPERTIES_SIZE == 2 ); 
03250     unsigned long& dirty = props[ PROTOCOLS ];
03251     unsigned long& dirty2 = props[ PROTOCOLS2 ];
03252     bool do_update = false;
03253 
03254     if (role == WindowManager && event->type == ClientMessage &&
03255     event->xclient.format == 32) {
03256 
03257 #ifdef NETWMDEBUG
03258         fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
03259 #endif // NETWMDEBUG
03260 
03261     if (event->xclient.message_type == net_wm_state) {
03262         dirty = WMState;
03263 
03264         
03265 
03266 #ifdef NETWMDEBUG
03267         fprintf(stderr,
03268             "NETWinInfo::event: state client message, getting new state/mask\n");
03269 #endif
03270 
03271         int i;
03272         long state = 0, mask = 0;
03273 
03274         for (i = 1; i < 3; i++) {
03275 #ifdef NETWMDEBUG
03276                 char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]);
03277         fprintf(stderr, "NETWinInfo::event:  message %ld '%s'\n",
03278             event->xclient.data.l[i], debug_txt );
03279                 if ( debug_txt )
03280                     XFree( debug_txt );
03281 #endif
03282 
03283         if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
03284             mask |= Modal;
03285         else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
03286             mask |= Sticky;
03287         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
03288             mask |= MaxVert;
03289         else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
03290             mask |= MaxHoriz;
03291         else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
03292             mask |= Shaded;
03293         else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
03294             mask |= SkipTaskbar;
03295                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
03296             mask |= SkipPager;
03297                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden)
03298             mask |= Hidden;
03299                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen)
03300             mask |= FullScreen;
03301                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_above)
03302             mask |= KeepAbove;
03303                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_below)
03304             mask |= KeepBelow;
03305                 else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention)
03306             mask |= DemandsAttention;
03307         else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
03308             mask |= StaysOnTop;
03309         }
03310 
03311         
03312         switch (event->xclient.data.l[0]) {
03313         case 1: 
03314         
03315         state = mask;
03316         break;
03317 
03318         case 2: 
03319         
03320         state = (p->state & mask) ^ mask;
03321         break;
03322 
03323         default:
03324         
03325         ;
03326         }
03327 
03328 #ifdef NETWMDEBUG
03329         fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
03330             state, mask);
03331 #endif
03332 
03333         changeState(state, mask);
03334     } else if (event->xclient.message_type == net_wm_desktop) {
03335         dirty = WMDesktop;
03336 
03337         if( event->xclient.data.l[0] == OnAllDesktops )
03338         changeDesktop( OnAllDesktops );
03339         else
03340             changeDesktop(event->xclient.data.l[0] + 1);
03341     }
03342     }
03343 
03344     if (event->type == PropertyNotify) {
03345 
03346 #ifdef    NETWMDEBUG
03347     fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
03348 #endif
03349 
03350     XEvent pe = *event;
03351 
03352     Bool done = False;
03353     Bool compaction = False;
03354     while (! done) {
03355 
03356 #ifdef    NETWMDEBUG
03357         fprintf(stderr, "NETWinInfo::event: loop fire\n");
03358 #endif
03359 
03360         if (pe.xproperty.atom == net_wm_name)
03361         dirty |= WMName;
03362         else if (pe.xproperty.atom == net_wm_visible_name)
03363         dirty |= WMVisibleName;
03364         else if (pe.xproperty.atom == net_wm_desktop)
03365         dirty |= WMDesktop;
03366         else if (pe.xproperty.atom == net_wm_window_type)
03367         dirty |=WMWindowType;
03368         else if (pe.xproperty.atom == net_wm_state)
03369         dirty |= WMState;
03370         else if (pe.xproperty.atom == net_wm_strut)
03371         dirty |= WMStrut;
03372         else if (pe.xproperty.atom == net_wm_icon_geometry)
03373         dirty |= WMIconGeometry;
03374         else if (pe.xproperty.atom == net_wm_icon)
03375         dirty |= WMIcon;
03376         else if (pe.xproperty.atom == net_wm_pid)
03377         dirty |= WMPid;
03378         else if (pe.xproperty.atom == net_wm_handled_icons)
03379         dirty |= WMHandledIcons;
03380         else if (pe.xproperty.atom == net_startup_id)
03381         dirty2 |= WM2StartupId;
03382         else if (pe.xproperty.atom == net_wm_allowed_actions)
03383         dirty2 |= WM2AllowedActions;
03384         else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
03385         dirty |= WMKDESystemTrayWinFor;
03386         else if (pe.xproperty.atom == xa_wm_state)
03387         dirty |= XAWMState;
03388         else if (pe.xproperty.atom == kde_net_wm_frame_strut)
03389         dirty |= WMKDEFrameStrut;
03390         else if (pe.xproperty.atom == net_wm_icon_name)
03391         dirty |= WMIconName;
03392         else if (pe.xproperty.atom == net_wm_visible_icon_name)
03393         dirty |= WMVisibleIconName;
03394         else if (pe.xproperty.atom == net_wm_user_time)
03395         dirty2 |= WM2UserTime;
03396             else if (pe.xproperty.atom == XA_WM_HINTS)
03397                 dirty2 |= WM2GroupLeader;
03398             else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR)
03399                 dirty2 |= WM2TransientFor;
03400         else {
03401 
03402 #ifdef    NETWMDEBUG
03403         fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
03404 #endif
03405 
03406         if ( compaction )
03407             XPutBackEvent(p->display, &pe);
03408         break;
03409         }
03410 
03411         if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
03412         compaction = True;
03413         else
03414         break;
03415     }
03416 
03417     do_update = true;
03418     } else if (event->type == ConfigureNotify) {
03419 
03420 #ifdef NETWMDEBUG
03421     fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
03422 #endif
03423 
03424     dirty |= WMGeometry;
03425 
03426     
03427     p->win_geom.pos.x = event->xconfigure.x;
03428     p->win_geom.pos.y = event->xconfigure.y;
03429     p->win_geom.size.width = event->xconfigure.width;
03430     p->win_geom.size.height = event->xconfigure.height;
03431     }
03432 
03433     if( do_update )
03434         update( props );
03435 
03436     if( properties_size > PROPERTIES_SIZE )
03437         properties_size = PROPERTIES_SIZE;
03438     for( int i = 0;
03439          i < properties_size;
03440          ++i )
03441         properties[ i ] = props[ i ];
03442 }
03443 
03444 void NETWinInfo::updateWMState() {
03445     unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 };
03446     assert( PROPERTIES_SIZE == 2 ); 
03447     update( props );
03448 }
03449 
03450 void NETWinInfo::update(const unsigned long dirty_props[]) {
03451     Atom type_ret;
03452     int format_ret;
03453     unsigned long nitems_ret, unused;
03454     unsigned char *data_ret;
03455     unsigned long props[ PROPERTIES_SIZE ];
03456     for( int i = 0;
03457          i < PROPERTIES_SIZE;
03458          ++i )
03459         props[ i ] = dirty_props[ i ] & p->properties[ i ];
03460     const unsigned long& dirty = props[ PROTOCOLS ];
03461     const unsigned long& dirty2 = props[ PROTOCOLS2 ];
03462 
03463     
03464     if( dirty_props[ PROTOCOLS ] & XAWMState )
03465         props[ PROTOCOLS ] |= XAWMState;
03466 
03467     if (dirty & XAWMState) {
03468         p->mapping_state = Withdrawn;
03469     if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
03470                    False, xa_wm_state, &type_ret, &format_ret,
03471                    &nitems_ret, &unused, &data_ret)
03472         == Success) {
03473         if (type_ret == xa_wm_state && format_ret == 32 &&
03474         nitems_ret == 1) {
03475         long *state = (long *) data_ret;
03476 
03477         switch(*state) {
03478             case IconicState:
03479             p->mapping_state = Iconic;
03480             break;
03481             case NormalState:
03482             p->mapping_state = Visible;
03483                         break;
03484             case WithdrawnState:
03485             default:
03486             p->mapping_state = Withdrawn;
03487             break;
03488         }
03489 
03490         p->mapping_state_dirty = False;
03491         }
03492         if ( data_ret )
03493         XFree(data_ret);
03494     }
03495     }
03496 
03497     if (dirty & WMState) {
03498     p->state = 0;
03499     if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
03500                    False, XA_ATOM, &type_ret, &format_ret,
03501                    &nitems_ret, &unused, &data_ret)
03502         == Success) {
03503         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03504         
03505 #ifdef NETWMDEBUG
03506         fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
03507             nitems_ret);
03508 #endif
03509 
03510         long *states = (long *) data_ret;
03511         unsigned long count;
03512 
03513         for (count = 0; count < nitems_ret; count++) {
03514 #ifdef NETWMDEBUG
03515                     char* data_ret = XGetAtomName(p->display, (Atom) states[count]);
03516             fprintf(stderr,
03517                 "NETWinInfo::update:   adding window state %ld '%s'\n",
03518                 states[count], data_ret );
03519                     if ( data_ret )
03520                         XFree( data_ret );
03521 #endif
03522 
03523             if ((Atom) states[count] == net_wm_state_modal)
03524             p->state |= Modal;
03525             else if ((Atom) states[count] == net_wm_state_sticky)
03526             p->state |= Sticky;
03527             else if ((Atom) states[count] == net_wm_state_max_vert)
03528             p->state |= MaxVert;
03529             else if ((Atom) states[count] == net_wm_state_max_horiz)
03530             p->state |= MaxHoriz;
03531             else if ((Atom) states[count] == net_wm_state_shaded)
03532             p->state |= Shaded;
03533             else if ((Atom) states[count] == net_wm_state_skip_taskbar)
03534             p->state |= SkipTaskbar;
03535             else if ((Atom) states[count] == net_wm_state_skip_pager)
03536             p->state |= SkipPager;
03537             else if ((Atom) states[count] == net_wm_state_hidden)
03538             p->state |= Hidden;
03539             else if ((Atom) states[count] == net_wm_state_fullscreen)
03540             p->state |= FullScreen;
03541             else if ((Atom) states[count] == net_wm_state_above)
03542             p->state |= KeepAbove;
03543             else if ((Atom) states[count] == net_wm_state_below)
03544             p->state |= KeepBelow;
03545             else if ((Atom) states[count] == net_wm_state_demands_attention)
03546             p->state |= DemandsAttention;
03547             else if ((Atom) states[count] == net_wm_state_stays_on_top)
03548             p->state |= StaysOnTop;
03549         }
03550         }
03551         if ( data_ret )
03552         XFree(data_ret);
03553     }
03554     }
03555 
03556     if (dirty & WMDesktop) {
03557     p->desktop = 0;
03558     if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
03559                    False, XA_CARDINAL, &type_ret,
03560                    &format_ret, &nitems_ret,
03561                    &unused, &data_ret)
03562         == Success) {
03563         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03564         nitems_ret == 1) {
03565         p->desktop = *((long *) data_ret);
03566         if ((signed) p->desktop != OnAllDesktops)
03567             p->desktop++;
03568 
03569         if ( p->desktop == 0 )
03570             p->desktop = OnAllDesktops;
03571         }
03572         if ( data_ret )
03573         XFree(data_ret);
03574     }
03575     }
03576 
03577     if (dirty & WMName) {
03578         delete[] p->name;
03579         p->name = NULL;
03580     if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
03581                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03582                    &format_ret, &nitems_ret, &unused, &data_ret)
03583         == Success) {
03584         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03585         p->name = nstrndup((const char *) data_ret, nitems_ret);
03586         }
03587 
03588         if( data_ret )
03589         XFree(data_ret);
03590     }
03591     }
03592 
03593     if (dirty & WMVisibleName) {
03594         delete[] p->visible_name;
03595         p->visible_name = NULL;
03596     if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
03597                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03598                    &format_ret, &nitems_ret, &unused, &data_ret)
03599         == Success) {
03600         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03601         p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
03602         }
03603 
03604         if( data_ret )
03605         XFree(data_ret);
03606     }
03607     }
03608 
03609     if (dirty & WMIconName) {
03610         delete[] p->icon_name;
03611         p->icon_name = NULL;
03612     if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
03613                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03614                    &format_ret, &nitems_ret, &unused, &data_ret)
03615         == Success) {
03616         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03617         p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
03618         }
03619 
03620         if( data_ret )
03621         XFree(data_ret);
03622     }
03623     }
03624 
03625     if (dirty & WMVisibleIconName)
03626     {
03627         delete[] p->visible_icon_name;
03628         p->visible_icon_name = NULL;
03629     if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
03630                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03631                    &format_ret, &nitems_ret, &unused, &data_ret)
03632         == Success) {
03633         if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
03634         p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
03635         }
03636 
03637         if( data_ret )
03638         XFree(data_ret);
03639     }
03640     }
03641 
03642     if (dirty & WMWindowType) {
03643     p->types.reset();
03644     p->types[ 0 ] = Unknown;
03645         p->has_net_support = false;
03646     if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
03647                    False, XA_ATOM, &type_ret, &format_ret,
03648                    &nitems_ret, &unused, &data_ret)
03649         == Success) {
03650         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03651         
03652 #ifdef NETWMDEBUG
03653         fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
03654             nitems_ret);
03655 #endif
03656 
03657                 p->has_net_support = true;
03658 
03659         unsigned long count = 0;
03660         long *types = (long *) data_ret;
03661         int pos = 0;
03662 
03663         while (count < nitems_ret) {
03664             
03665 #ifdef NETWMDEBUG
03666                     char* debug_type = XGetAtomName(p->display, (Atom) types[count]);
03667             fprintf(stderr,
03668                 "NETWinInfo::update:   examining window type %ld %s\n",
03669                 types[count], debug_type );
03670                     if ( debug_type )
03671                         XFree( debug_type );
03672 #endif
03673 
03674             if ((Atom) types[count] == net_wm_window_type_normal)
03675             p->types[ pos++ ] = Normal;
03676             else if ((Atom) types[count] == net_wm_window_type_desktop)
03677             p->types[ pos++ ] = Desktop;
03678             else if ((Atom) types[count] == net_wm_window_type_dock)
03679             p->types[ pos++ ] = Dock;
03680             else if ((Atom) types[count] == net_wm_window_type_toolbar)
03681             p->types[ pos++ ] = Tool;
03682             else if ((Atom) types[count] == net_wm_window_type_menu)
03683             p->types[ pos++ ] = Menu;
03684             else if ((Atom) types[count] == net_wm_window_type_dialog)
03685             p->types[ pos++ ] = Dialog;
03686             else if ((Atom) types[count] == net_wm_window_type_utility)
03687             p->types[ pos++ ] = Utility;
03688             else if ((Atom) types[count] == net_wm_window_type_splash)
03689             p->types[ pos++ ] = Splash;
03690             else if ((Atom) types[count] == kde_net_wm_window_type_override)
03691             p->types[ pos++ ] = Override;
03692             else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
03693             p->types[ pos++ ] = TopMenu;
03694 
03695             count++;
03696         }
03697         }
03698 
03699         if ( data_ret )
03700         XFree(data_ret);
03701     }
03702     }
03703 
03704     if (dirty & WMStrut) {
03705         p->strut = NETStrut();
03706     if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
03707                    False, XA_CARDINAL, &type_ret, &format_ret,
03708                    &nitems_ret, &unused, &data_ret)
03709         == Success) {
03710         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03711         nitems_ret == 4) {
03712         long *d = (long *) data_ret;
03713         p->strut.left   = d[0];
03714         p->strut.right  = d[1];
03715         p->strut.top    = d[2];
03716         p->strut.bottom = d[3];
03717         }
03718         if ( data_ret )
03719         XFree(data_ret);
03720     }
03721     }
03722 
03723     if (dirty & WMIconGeometry) {
03724         p->icon_geom = NETRect();
03725     if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
03726                    False, XA_CARDINAL, &type_ret, &format_ret,
03727                    &nitems_ret, &unused, &data_ret)
03728         == Success) {
03729         if (type_ret == XA_CARDINAL && format_ret == 32 &&
03730         nitems_ret == 4) {
03731         long *d = (long *) data_ret;
03732         p->icon_geom.pos.x       = d[0];
03733         p->icon_geom.pos.y       = d[1];
03734         p->icon_geom.size.width  = d[2];
03735         p->icon_geom.size.height = d[3];
03736         }
03737         if ( data_ret )
03738         XFree(data_ret);
03739     }
03740     }
03741 
03742     if (dirty & WMIcon) {
03743     readIcon(p);
03744     }
03745 
03746     if (dirty & WMKDESystemTrayWinFor) {
03747     p->kde_system_tray_win_for = 0;
03748     if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
03749                    0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
03750                    &nitems_ret, &unused, &data_ret)
03751         == Success) {
03752         if (type_ret == XA_WINDOW && format_ret == 32 &&
03753         nitems_ret == 1) {
03754         p->kde_system_tray_win_for = *((Window *) data_ret);
03755         if ( p->kde_system_tray_win_for == 0 )
03756             p->kde_system_tray_win_for = p->root;
03757         }
03758         if ( data_ret )
03759         XFree(data_ret);
03760         }
03761     }
03762 
03763     if (dirty & WMKDEFrameStrut) {
03764         p->frame_strut = NETStrut();
03765     if (XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
03766                    0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
03767                    &nitems_ret, &unused, &data_ret) == Success) {
03768         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
03769         long *d = (long *) data_ret;
03770 
03771         p->frame_strut.left   = d[0];
03772         p->frame_strut.right  = d[1];
03773         p->frame_strut.top    = d[2];
03774         p->frame_strut.bottom = d[3];
03775         }
03776         if ( data_ret )
03777         XFree(data_ret);
03778     }
03779     }
03780 
03781     if (dirty & WMPid) {
03782     p->pid = 0;
03783     if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
03784                    False, XA_CARDINAL, &type_ret, &format_ret,
03785                    &nitems_ret, &unused, &data_ret) == Success) {
03786         if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
03787         p->pid = *((long *) data_ret);
03788         }
03789         if ( data_ret )
03790         XFree(data_ret);
03791     }
03792     }
03793 
03794     if (dirty2 & WM2StartupId)
03795     {
03796         delete[] p->startup_id;
03797         p->startup_id = NULL;
03798     if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l,
03799                    MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
03800                    &format_ret, &nitems_ret, &unused, &data_ret)
03801         == Success) {
03802         if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
03803         p->startup_id = nstrndup((const char *) data_ret, nitems_ret);
03804         }
03805 
03806         if( data_ret )
03807         XFree(data_ret);
03808     }
03809     }
03810 
03811     if( dirty2 & WM2AllowedActions ) {
03812         p->allowed_actions = 0;
03813     if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l,
03814                    False, XA_ATOM, &type_ret, &format_ret,
03815                    &nitems_ret, &unused, &data_ret)
03816         == Success) {
03817         if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
03818         
03819 #ifdef NETWMDEBUG
03820         fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n",
03821             nitems_ret);
03822 #endif
03823 
03824         long *actions = (long *) data_ret;
03825         unsigned long count;
03826 
03827         for (count = 0; count < nitems_ret; count++) {
03828 #ifdef NETWMDEBUG
03829             fprintf(stderr,
03830                 "NETWinInfo::update:   adding allowed action %ld '%s'\n",
03831                 actions[count],
03832                 XGetAtomName(p->display, (Atom) actions[count]));
03833 #endif
03834 
03835             if ((Atom) actions[count] == net_wm_action_move)
03836             p->allowed_actions |= ActionMove;
03837             if ((Atom) actions[count] == net_wm_action_resize)
03838             p->allowed_actions |= ActionResize;
03839             if ((Atom) actions[count] == net_wm_action_minimize)
03840             p->allowed_actions |= ActionMinimize;
03841             if ((Atom) actions[count] == net_wm_action_shade)
03842             p->allowed_actions |= ActionShade;
03843             if ((Atom) actions[count] == net_wm_action_stick)
03844             p->allowed_actions |= ActionStick;
03845             if ((Atom) actions[count] == net_wm_action_max_vert)
03846             p->allowed_actions |= ActionMaxVert;
03847             if ((Atom) actions[count] == net_wm_action_max_horiz)
03848             p->allowed_actions |= ActionMaxHoriz;
03849             if ((Atom) actions[count] == net_wm_action_fullscreen)
03850             p->allowed_actions |= ActionFullScreen;
03851             if ((Atom) actions[count] == net_wm_action_change_desk)
03852             p->allowed_actions |= ActionChangeDesktop;
03853             if ((Atom) actions[count] == net_wm_action_close)
03854             p->allowed_actions |= ActionClose;
03855         }
03856         }
03857         if ( data_ret )
03858         XFree(data_ret);
03859     }
03860     }
03861 
03862     if (dirty2 & WM2UserTime) {
03863     p->user_time = -1U;
03864     if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l,
03865                    False, XA_CARDINAL, &type_ret, &format_ret,
03866                    &nitems_ret, &unused, &data_ret) == Success) {
03867             
03868         if (type_ret == XA_CARDINAL && format_ret == 32 ) {
03869         p->user_time = *((long *) data_ret);
03870         }
03871         if ( data_ret )
03872         XFree(data_ret);
03873     }
03874     }
03875 
03876     if (dirty2 & WM2TransientFor) {
03877     p->transient_for = None;
03878         XGetTransientForHint(p->display, p->window, &p->transient_for);
03879     }
03880 
03881     if (dirty2 & WM2GroupLeader) {
03882         XWMHints *hints = XGetWMHints(p->display, p->window);
03883         p->window_group = None;
03884         if ( hints )
03885         {
03886             if( hints->flags & WindowGroupHint )
03887                 p->window_group = hints->window_group;
03888             XFree( reinterpret_cast< char* >( hints ));
03889         }
03890     }
03891 
03892 }
03893 
03894 
03895 NETRect NETWinInfo::iconGeometry() const {
03896     return p->icon_geom;
03897 }
03898 
03899 
03900 unsigned long NETWinInfo::state() const {
03901     return p->state;
03902 }
03903 
03904 
03905 NETStrut NETWinInfo::strut() const {
03906     return p->strut;
03907 }
03908 
03909 NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const {
03910     for( int i = 0;
03911      i < p->types.size();
03912      ++i ) {
03913     switch( p->types[ i ] ) {
03914     
03915 #define CHECK_TYPE_MASK( type ) \
03916         case type: \
03917         if( supported_types & type##Mask ) \
03918             return type; \
03919         break;
03920         CHECK_TYPE_MASK( Normal )
03921         CHECK_TYPE_MASK( Desktop )
03922         CHECK_TYPE_MASK( Dock )
03923         CHECK_TYPE_MASK( Toolbar )
03924         CHECK_TYPE_MASK( Menu )
03925         CHECK_TYPE_MASK( Dialog )
03926         CHECK_TYPE_MASK( Override )
03927         CHECK_TYPE_MASK( TopMenu )
03928         CHECK_TYPE_MASK( Utility )
03929         CHECK_TYPE_MASK( Splash )
03930 #undef CHECK_TYPE_MASK
03931         default:
03932         break;
03933     }
03934     }
03935     return Unknown;
03936 }
03937 
03938 NET::WindowType NETWinInfo::windowType() const {
03939     return p->types[ 0 ];
03940 }
03941 
03942 
03943 const char *NETWinInfo::name() const {
03944     return p->name;
03945 }
03946 
03947 
03948 const char *NETWinInfo::visibleName() const {
03949     return p->visible_name;
03950 }
03951 
03952 
03953 const char *NETWinInfo::iconName() const {
03954     return p->icon_name;
03955 }
03956 
03957 
03958 const char *NETWinInfo::visibleIconName() const {
03959     return p->visible_icon_name;
03960 }
03961 
03962 
03963 int NETWinInfo::desktop() const {
03964     return p->desktop;
03965 }
03966 
03967 int NETWinInfo::pid() const {
03968     return p->pid;
03969 }
03970 
03971 Time NETWinInfo::userTime() const {
03972     return p->user_time;
03973 }
03974 
03975 const char* NETWinInfo::startupId() const {
03976     return p->startup_id;
03977 }
03978 
03979 unsigned long NETWinInfo::allowedActions() const {
03980     return p->allowed_actions;
03981 }
03982 
03983 bool NETWinInfo::hasNETSupport() const {
03984     return p->has_net_support;
03985 }
03986 
03987 Window NETWinInfo::transientFor() const {
03988     return p->transient_for;
03989 }
03990 
03991 Window NETWinInfo::groupLeader() const {
03992     return p->window_group;
03993 }
03994 
03995 Bool NETWinInfo::handledIcons() const {
03996     return p->handled_icons;
03997 }
03998 
03999 
04000 Window NETWinInfo::kdeSystemTrayWinFor() const {
04001     return p->kde_system_tray_win_for;
04002 }
04003 
04004 const unsigned long* NETWinInfo::passedProperties() const {
04005     return p->properties;
04006 }
04007 
04008 unsigned long NETWinInfo::properties() const {
04009     return p->properties[ PROTOCOLS ];
04010 }
04011 
04012 
04013 NET::MappingState NETWinInfo::mappingState() const {
04014     return p->mapping_state;
04015 }
04016 
04017 void NETRootInfo::virtual_hook( int, void* )
04018 {  }
04019 
04020 void NETWinInfo::virtual_hook( int, void* )
04021 {  }
04022 
04023 #endif