kdecore Library API Documentation

netwm.cpp

00001 /* 00002 00003 Copyright (c) 2000 Troll Tech AS 00004 Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org> 00005 00006 Permission is hereby granted, free of charge, to any person obtaining a 00007 copy of this software and associated documentation files (the "Software"), 00008 to deal in the Software without restriction, including without limitation 00009 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00010 and/or sell copies of the Software, and to permit persons to whom the 00011 Software is furnished to do so, subject to the following conditions: 00012 00013 The above copyright notice and this permission notice shall be included in 00014 all copies or substantial portions of the Software. 00015 00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00019 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00021 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00022 DEALINGS IN THE SOFTWARE. 00023 00024 */ 00025 00026 //#define NETWMDEBUG 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 // UTF-8 string 00043 static Atom UTF8_STRING = 0; 00044 00045 // root window properties 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 // root window messages 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 // application window properties 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 // KDE extensions 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 // application protocols 00090 static Atom wm_protocols = 0; 00091 static Atom net_wm_ping = 0; 00092 00093 // application window types 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 // application window state 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 // allowed actions 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 // KDE extension that's not in the specs - Replaced by state_above now? 00130 static Atom net_wm_state_stays_on_top = 0; 00131 00132 // used to determine whether application window is managed or not 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_WM_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 // reset 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 // allocate buffers 00426 unsigned char *buffer = 0; 00427 unsigned long offset = 0; 00428 unsigned long buffer_offset = 0; 00429 unsigned long bufsize = 0; 00430 00431 // read data 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 // either we didn't get the property, or the property has less than 00442 // 3 elements in it 00443 // NOTE: 3 is the ABSOLUTE minimum: 00444 // width = 1, height = 1, length(data) = 1 (width * height) 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; // Some error occurred cq. property didn't exist. 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)); // allocate 2 elts and set to zero 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 // allocate space for the new data 00533 // open table has amortized O(1) access time 00534 // when N elements appended consecutively -- exa 00535 int newcapacity = 2*capacity > index+1 ? 2*capacity : index+1; // max 00536 // copy into new larger memory block using realloc 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) // at this point capacity>index 00542 sz = index + 1; 00543 00544 return d[index]; 00545 } 00546 00547 00548 // Construct a new NETRootInfo object. 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 // force support for Supported and SupportingWMCheck for window managers 00587 p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck ); 00588 p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients 00589 | WMPing; // or they can reply to this 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 // force support for Supported and SupportingWMCheck for window managers 00630 p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck ); 00631 p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients 00632 | WMPing; // or they can reply to this 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 // Copy an existing NETRootInfo object. 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 // Be gone with our NETRootInfo. 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; // these two actually don't 00780 p->client_properties[ STATES ] = 0; // make sense in client_properties 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 // allow setting desktop names even for non-existant desktops, see the spec, sect.3.7. 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 // Root window properties/messages 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 // Application window properties/messages 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 // Application window types 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 // KDE extensions 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 // Application window states 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 // Actions 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 // KDE specific extensions 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 // Application window properties/messages 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 // Application window types 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 // KDE extensions 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 // Application window states 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 // Actions 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 // KDE specific extensions 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 // assignment operator 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 ); // add elements above 01677 unsigned long& dirty = props[ PROTOCOLS ]; 01678 unsigned long& dirty2 = props[ PROTOCOLS2 ]; 01679 bool do_update = false; 01680 01681 Q_UNUSED( dirty2 ); // for now 01682 01683 // the window manager will be interested in client messages... no other 01684 // client should get these messages 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 // make sure there aren't unknown values 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 // private functions to update the data we keep 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 ); // for now 01915 01916 if (dirty & Supported ) { 01917 // only in Client mode 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; // set to (0,0) 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 // NETWinInfo stuffs 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 // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0; 02516 // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top = 02517 // p->frame_strut.bottom = 0; 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 // p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0; 02574 // p->frame_strut.left = p->frame_strut.right = p->frame_strut.top = 02575 // p->frame_strut.bottom = 0; 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 // assignment operator 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 // assign icon 02648 p->icons[p->icon_count] = icon; 02649 p->icon_count++; 02650 02651 // do a deep copy, we want to own the data 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 // compute property length 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 // copy size into property 02668 *pprop++ = p->icons[i].size.width; 02669 *pprop++ = p->icons[i].size.height; 02670 02671 // copy data into property 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 // setState() needs to know the current state, so read it even if not requested 02721 if( ( p->properties[ PROTOCOLS ] & WMState ) == 0 ) { 02722 p->properties[ PROTOCOLS ] |= WMState; 02723 unsigned long props[ PROPERTIES_SIZE ] = { WMState, 0 }; 02724 assert( PROPERTIES_SIZE == 2 ); // add elements above 02725 update( props ); 02726 p->properties[ PROTOCOLS ] &= ~WMState; 02727 } 02728 02729 if (role == Client && p->mapping_state != Withdrawn) { 02730 02731 #ifdef NETWMDEBUG 02732 fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n", 02733 state, mask); 02734 #endif // NETWMDEBUG 02735 02736 XEvent e; 02737 e.xclient.type = ClientMessage; 02738 e.xclient.message_type = net_wm_state; 02739 e.xclient.display = p->display; 02740 e.xclient.window = p->window; 02741 e.xclient.format = 32; 02742 e.xclient.data.l[3] = 0l; 02743 e.xclient.data.l[4] = 0l; 02744 02745 if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) { 02746 e.xclient.data.l[0] = (state & Modal) ? 1 : 0; 02747 e.xclient.data.l[1] = net_wm_state_modal; 02748 e.xclient.data.l[2] = 0l; 02749 02750 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02751 } 02752 02753 if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) { 02754 e.xclient.data.l[0] = (state & Sticky) ? 1 : 0; 02755 e.xclient.data.l[1] = net_wm_state_sticky; 02756 e.xclient.data.l[2] = 0l; 02757 02758 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02759 } 02760 02761 if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) { 02762 02763 unsigned long wishstate = (p->state & ~mask) | (state & mask); 02764 if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) 02765 && ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) { 02766 if ( (wishstate & Max) == Max ) { 02767 e.xclient.data.l[0] = 1; 02768 e.xclient.data.l[1] = net_wm_state_max_horiz; 02769 e.xclient.data.l[2] = net_wm_state_max_vert; 02770 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02771 } else if ( (wishstate & Max) == 0 ) { 02772 e.xclient.data.l[0] = 0; 02773 e.xclient.data.l[1] = net_wm_state_max_horiz; 02774 e.xclient.data.l[2] = net_wm_state_max_vert; 02775 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02776 } else { 02777 e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0; 02778 e.xclient.data.l[1] = net_wm_state_max_horiz; 02779 e.xclient.data.l[2] = 0; 02780 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02781 e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0; 02782 e.xclient.data.l[1] = net_wm_state_max_vert; 02783 e.xclient.data.l[2] = 0; 02784 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02785 } 02786 } else if ( (wishstate & MaxVert) != (p->state & MaxVert) ) { 02787 e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0; 02788 e.xclient.data.l[1] = net_wm_state_max_vert; 02789 e.xclient.data.l[2] = 0; 02790 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02791 } else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) { 02792 e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0; 02793 e.xclient.data.l[1] = net_wm_state_max_horiz; 02794 e.xclient.data.l[2] = 0; 02795 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02796 } 02797 } 02798 02799 if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) { 02800 e.xclient.data.l[0] = (state & Shaded) ? 1 : 0; 02801 e.xclient.data.l[1] = net_wm_state_shaded; 02802 e.xclient.data.l[2] = 0l; 02803 02804 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02805 } 02806 02807 if ((mask & SkipTaskbar) && 02808 ((p->state & SkipTaskbar) != (state & SkipTaskbar))) { 02809 e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0; 02810 e.xclient.data.l[1] = net_wm_state_skip_taskbar; 02811 e.xclient.data.l[2] = 0l; 02812 02813 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02814 } 02815 02816 if ((mask & SkipPager) && 02817 ((p->state & SkipPager) != (state & SkipPager))) { 02818 e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0; 02819 e.xclient.data.l[1] = net_wm_state_skip_pager; 02820 e.xclient.data.l[2] = 0l; 02821 02822 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02823 } 02824 02825 if ((mask & Hidden) && 02826 ((p->state & Hidden) != (state & Hidden))) { 02827 e.xclient.data.l[0] = (state & Hidden) ? 1 : 0; 02828 e.xclient.data.l[1] = net_wm_state_hidden; 02829 e.xclient.data.l[2] = 0l; 02830 02831 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02832 } 02833 02834 if ((mask & FullScreen) && 02835 ((p->state & FullScreen) != (state & FullScreen))) { 02836 e.xclient.data.l[0] = (state & FullScreen) ? 1 : 0; 02837 e.xclient.data.l[1] = net_wm_state_fullscreen; 02838 e.xclient.data.l[2] = 0l; 02839 02840 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02841 } 02842 02843 if ((mask & KeepAbove) && 02844 ((p->state & KeepAbove) != (state & KeepAbove))) { 02845 e.xclient.data.l[0] = (state & KeepAbove) ? 1 : 0; 02846 e.xclient.data.l[1] = net_wm_state_above; 02847 e.xclient.data.l[2] = 0l; 02848 02849 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02850 } 02851 02852 if ((mask & KeepBelow) && 02853 ((p->state & KeepBelow) != (state & KeepBelow))) { 02854 e.xclient.data.l[0] = (state & KeepBelow) ? 1 : 0; 02855 e.xclient.data.l[1] = net_wm_state_below; 02856 e.xclient.data.l[2] = 0l; 02857 02858 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02859 } 02860 02861 if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) { 02862 e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0; 02863 e.xclient.data.l[1] = net_wm_state_stays_on_top; 02864 e.xclient.data.l[2] = 0l; 02865 02866 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02867 } 02868 02869 if ((mask & DemandsAttention) && 02870 ((p->state & DemandsAttention) != (state & DemandsAttention))) { 02871 e.xclient.data.l[0] = (state & DemandsAttention) ? 1 : 0; 02872 e.xclient.data.l[1] = net_wm_state_demands_attention; 02873 e.xclient.data.l[2] = 0l; 02874 02875 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 02876 } 02877 02878 } else { 02879 p->state &= ~mask; 02880 p->state |= state; 02881 02882 long data[50]; 02883 int count = 0; 02884 02885 // hints 02886 if (p->state & Modal) data[count++] = net_wm_state_modal; 02887 if (p->state & MaxVert) data[count++] = net_wm_state_max_vert; 02888 if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz; 02889 if (p->state & Shaded) data[count++] = net_wm_state_shaded; 02890 if (p->state & Hidden) data[count++] = net_wm_state_hidden; 02891 if (p->state & FullScreen) data[count++] = net_wm_state_fullscreen; 02892 if (p->state & DemandsAttention) data[count++] = net_wm_state_demands_attention; 02893 02894 // policy 02895 if (p->state & KeepAbove) data[count++] = net_wm_state_above; 02896 if (p->state & KeepBelow) data[count++] = net_wm_state_below; 02897 if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top; 02898 if (p->state & Sticky) data[count++] = net_wm_state_sticky; 02899 if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar; 02900 if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager; 02901 02902 #ifdef NETWMDEBUG 02903 fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count); 02904 for (int i = 0; i < count; i++) { 02905 char* data_ret = XGetAtomName(p->display, (Atom) data[i]); 02906 fprintf(stderr, "NETWinInfo::setState: state %ld '%s'\n", 02907 data[i], data_ret); 02908 if ( data_ret ) 02909 XFree( data_ret ); 02910 } 02911 02912 #endif 02913 02914 XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32, 02915 PropModeReplace, (unsigned char *) data, count); 02916 } 02917 } 02918 02919 02920 void NETWinInfo::setWindowType(WindowType type) { 02921 if (role != Client) return; 02922 02923 int len; 02924 long data[2]; 02925 02926 switch (type) { 02927 case Override: 02928 // spec extension: override window type. we must comply with the spec 02929 // and provide a fall back (normal seems best) 02930 data[0] = kde_net_wm_window_type_override; 02931 data[1] = net_wm_window_type_normal; 02932 len = 2; 02933 break; 02934 02935 case Dialog: 02936 data[0] = net_wm_window_type_dialog; 02937 data[1] = None; 02938 len = 1; 02939 break; 02940 02941 case Menu: 02942 data[0] = net_wm_window_type_menu; 02943 data[1] = None; 02944 len = 1; 02945 break; 02946 02947 case TopMenu: 02948 // spec extension: override window type. we must comply with the spec 02949 // and provide a fall back (dock seems best) 02950 data[0] = kde_net_wm_window_type_topmenu; 02951 data[1] = net_wm_window_type_dock; 02952 len = 2; 02953 break; 02954 02955 case Tool: 02956 data[0] = net_wm_window_type_toolbar; 02957 data[1] = None; 02958 len = 1; 02959 break; 02960 02961 case Dock: 02962 data[0] = net_wm_window_type_dock; 02963 data[1] = None; 02964 len = 1; 02965 break; 02966 02967 case Desktop: 02968 data[0] = net_wm_window_type_desktop; 02969 data[1] = None; 02970 len = 1; 02971 break; 02972 02973 case Utility: 02974 data[0] = net_wm_window_type_utility; 02975 data[1] = net_wm_window_type_dialog; // fallback for old netwm version 02976 len = 2; 02977 break; 02978 02979 case Splash: 02980 data[0] = net_wm_window_type_splash; 02981 data[1] = net_wm_window_type_dock; // fallback (dock seems best) 02982 len = 2; 02983 break; 02984 02985 default: 02986 case Normal: 02987 data[0] = net_wm_window_type_normal; 02988 data[1] = None; 02989 len = 1; 02990 break; 02991 } 02992 02993 XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32, 02994 PropModeReplace, (unsigned char *) &data, len); 02995 } 02996 02997 02998 void NETWinInfo::setName(const char *name) { 02999 if (role != Client) return; 03000 03001 delete [] p->name; 03002 p->name = nstrdup(name); 03003 if( p->name[ 0 ] != '\0' ) 03004 XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8, 03005 PropModeReplace, (unsigned char *) p->name, 03006 strlen(p->name)); 03007 else 03008 XDeleteProperty(p->display, p->window, net_wm_name); 03009 } 03010 03011 03012 void NETWinInfo::setVisibleName(const char *visibleName) { 03013 if (role != WindowManager) return; 03014 03015 delete [] p->visible_name; 03016 p->visible_name = nstrdup(visibleName); 03017 if( p->visible_name[ 0 ] != '\0' ) 03018 XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8, 03019 PropModeReplace, (unsigned char *) p->visible_name, 03020 strlen(p->visible_name)); 03021 else 03022 XDeleteProperty(p->display, p->window, net_wm_visible_name); 03023 } 03024 03025 03026 void NETWinInfo::setIconName(const char *iconName) { 03027 if (role != Client) return; 03028 03029 delete [] p->icon_name; 03030 p->icon_name = nstrdup(iconName); 03031 if( p->icon_name[ 0 ] != '\0' ) 03032 XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8, 03033 PropModeReplace, (unsigned char *) p->icon_name, 03034 strlen(p->icon_name)); 03035 else 03036 XDeleteProperty(p->display, p->window, net_wm_icon_name); 03037 } 03038 03039 03040 void NETWinInfo::setVisibleIconName(const char *visibleIconName) { 03041 if (role != WindowManager) return; 03042 03043 delete [] p->visible_icon_name; 03044 p->visible_icon_name = nstrdup(visibleIconName); 03045 if( p->visible_icon_name[ 0 ] != '\0' ) 03046 XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8, 03047 PropModeReplace, (unsigned char *) p->visible_icon_name, 03048 strlen(p->visible_icon_name)); 03049 else 03050 XDeleteProperty(p->display, p->window, net_wm_visible_icon_name); 03051 } 03052 03053 03054 void NETWinInfo::setDesktop(int desktop) { 03055 if (p->mapping_state_dirty) 03056 updateWMState(); 03057 03058 if (role == Client && p->mapping_state != Withdrawn) { 03059 // we only send a ClientMessage if we are 1) a client and 2) managed 03060 03061 if ( desktop == 0 ) 03062 return; // we can't do that while being managed 03063 03064 XEvent e; 03065 03066 e.xclient.type = ClientMessage; 03067 e.xclient.message_type = net_wm_desktop; 03068 e.xclient.display = p->display; 03069 e.xclient.window = p->window; 03070 e.xclient.format = 32; 03071 e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1; 03072 e.xclient.data.l[1] = 0l; 03073 e.xclient.data.l[2] = 0l; 03074 e.xclient.data.l[3] = 0l; 03075 e.xclient.data.l[4] = 0l; 03076 03077 XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e); 03078 } else { 03079 // otherwise we just set or remove the property directly 03080 p->desktop = desktop; 03081 long d = desktop; 03082 03083 if ( d != OnAllDesktops ) { 03084 if ( d == 0 ) { 03085 XDeleteProperty( p->display, p->window, net_wm_desktop ); 03086 return; 03087 } 03088 03089 d -= 1; 03090 } 03091 03092 XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32, 03093 PropModeReplace, (unsigned char *) &d, 1); 03094 } 03095 } 03096 03097 03098 void NETWinInfo::setPid(int pid) { 03099 if (role != Client) return; 03100 03101 p->pid = pid; 03102 long d = pid; 03103 XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32, 03104 PropModeReplace, (unsigned char *) &d, 1); 03105 } 03106 03107 03108 void NETWinInfo::setHandledIcons(Bool handled) { 03109 if (role != Client) return; 03110 03111 p->handled_icons = handled; 03112 long d = handled; 03113 XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32, 03114 PropModeReplace, (unsigned char *) &d, 1); 03115 } 03116 03117 void NETWinInfo::setStartupId(const char* id) { 03118 if (role != Client) return; 03119 03120 delete[] p->startup_id; 03121 p->startup_id = nstrdup(id); 03122 XChangeProperty(p->display, p->window, net_startup_id, UTF8_STRING, 8, 03123 PropModeReplace, reinterpret_cast< unsigned char* >( p->startup_id ), 03124 strlen( p->startup_id )); 03125 } 03126 03127 void NETWinInfo::setAllowedActions( unsigned long actions ) { 03128 if( role != WindowManager ) 03129 return; 03130 long data[50]; 03131 int count = 0; 03132 03133 p->allowed_actions = actions; 03134 if (p->allowed_actions & ActionMove) data[count++] = net_wm_action_move; 03135 if (p->allowed_actions & ActionResize) data[count++] = net_wm_action_resize; 03136 if (p->allowed_actions & ActionMinimize) data[count++] = net_wm_action_minimize; 03137 if (p->allowed_actions & ActionShade) data[count++] = net_wm_action_shade; 03138 if (p->allowed_actions & ActionStick) data[count++] = net_wm_action_stick; 03139 if (p->allowed_actions & ActionMaxVert) data[count++] = net_wm_action_max_vert; 03140 if (p->allowed_actions & ActionMaxHoriz) data[count++] = net_wm_action_max_horiz; 03141 if (p->allowed_actions & ActionFullScreen) data[count++] = net_wm_action_fullscreen; 03142 if (p->allowed_actions & ActionChangeDesktop) data[count++] = net_wm_action_change_desk; 03143 if (p->allowed_actions & ActionClose) data[count++] = net_wm_action_close; 03144 03145 #ifdef NETWMDEBUG 03146 fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count); 03147 for (int i = 0; i < count; i++) { 03148 char* data_ret = XGetAtomName(p->display, (Atom) data[i]); 03149 fprintf(stderr, "NETWinInfo::setAllowedActions: action %ld '%s'\n", 03150 data[i], data_ret); 03151 if ( data_ret ) 03152 XFree(data_ret); 03153 } 03154 #endif 03155 03156 XChangeProperty(p->display, p->window, net_wm_allowed_actions, XA_ATOM, 32, 03157 PropModeReplace, (unsigned char *) data, count); 03158 } 03159 03160 void NETWinInfo::setKDESystemTrayWinFor(Window window) { 03161 if (role != Client) return; 03162 03163 p->kde_system_tray_win_for = window; 03164 XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for, 03165 XA_WINDOW, 32, PropModeReplace, 03166 (unsigned char *) &(p->kde_system_tray_win_for), 1); 03167 } 03168 03169 03170 void NETWinInfo::setKDEFrameStrut(NETStrut strut) { 03171 if (role != WindowManager) return; 03172 03173 p->frame_strut = strut; 03174 03175 long d[4]; 03176 d[0] = strut.left; 03177 d[1] = strut.right; 03178 d[2] = strut.top; 03179 d[3] = strut.bottom; 03180 03181 XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32, 03182 PropModeReplace, (unsigned char *) d, 4); 03183 } 03184 03185 03186 void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) { 03187 if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) { 03188 Window unused; 03189 int x, y; 03190 unsigned int w, h, junk; 03191 XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk); 03192 XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused 03193 ); 03194 03195 p->win_geom.pos.x = x; 03196 p->win_geom.pos.y = y; 03197 03198 p->win_geom.size.width = w; 03199 p->win_geom.size.height = h; 03200 } 03201 // TODO try to work also without _KDE_NET_WM_FRAME_STRUT 03202 window = p->win_geom; 03203 03204 frame.pos.x = window.pos.x - p->frame_strut.left; 03205 frame.pos.y = window.pos.y - p->frame_strut.top; 03206 frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right; 03207 frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom; 03208 } 03209 03210 03211 NETIcon NETWinInfo::icon(int width, int height) const { 03212 NETIcon result; 03213 03214 if ( !p->icon_count ) { 03215 result.size.width = 0; 03216 result.size.height = 0; 03217 result.data = 0; 03218 return result; 03219 } 03220 03221 result = p->icons[0]; 03222 03223 // find the icon that's closest in size to w x h... 03224 // return the first icon if w and h are -1 03225 if (width == height && height == -1) return result; 03226 03227 int i; 03228 for (i = 0; i < p->icons.size(); i++) { 03229 if ((p->icons[i].size.width >= width && 03230 p->icons[i].size.width < result.size.width) && 03231 (p->icons[i].size.height >= height && 03232 p->icons[i].size.height < result.size.height)) 03233 result = p->icons[i]; 03234 } 03235 03236 return result; 03237 } 03238 03239 void NETWinInfo::setUserTime( Time time ) { 03240 if (role != Client) return; 03241 03242 p->user_time = time; 03243 long d = time; 03244 XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32, 03245 PropModeReplace, (unsigned char *) &d, 1); 03246 } 03247 03248 03249 unsigned long NETWinInfo::event(XEvent *ev ) 03250 { 03251 unsigned long props[ 1 ]; 03252 event( ev, props, 1 ); 03253 return props[ 0 ]; 03254 } 03255 03256 void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) { 03257 unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 }; 03258 assert( PROPERTIES_SIZE == 2 ); // add elements above 03259 unsigned long& dirty = props[ PROTOCOLS ]; 03260 unsigned long& dirty2 = props[ PROTOCOLS2 ]; 03261 bool do_update = false; 03262 03263 if (role == WindowManager && event->type == ClientMessage && 03264 event->xclient.format == 32) { 03265 03266 #ifdef NETWMDEBUG 03267 fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n"); 03268 #endif // NETWMDEBUG 03269 03270 if (event->xclient.message_type == net_wm_state) { 03271 dirty = WMState; 03272 03273 // we need to generate a change mask 03274 03275 #ifdef NETWMDEBUG 03276 fprintf(stderr, 03277 "NETWinInfo::event: state client message, getting new state/mask\n"); 03278 #endif 03279 03280 int i; 03281 long state = 0, mask = 0; 03282 03283 for (i = 1; i < 3; i++) { 03284 #ifdef NETWMDEBUG 03285 char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]); 03286 fprintf(stderr, "NETWinInfo::event: message %ld '%s'\n", 03287 event->xclient.data.l[i], debug_txt ); 03288 if ( debug_txt ) 03289 XFree( debug_txt ); 03290 #endif 03291 03292 if ((Atom) event->xclient.data.l[i] == net_wm_state_modal) 03293 mask |= Modal; 03294 else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky) 03295 mask |= Sticky; 03296 else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert) 03297 mask |= MaxVert; 03298 else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz) 03299 mask |= MaxHoriz; 03300 else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded) 03301 mask |= Shaded; 03302 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar) 03303 mask |= SkipTaskbar; 03304 else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager) 03305 mask |= SkipPager; 03306 else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden) 03307 mask |= Hidden; 03308 else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen) 03309 mask |= FullScreen; 03310 else if ((Atom) event->xclient.data.l[i] == net_wm_state_above) 03311 mask |= KeepAbove; 03312 else if ((Atom) event->xclient.data.l[i] == net_wm_state_below) 03313 mask |= KeepBelow; 03314 else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention) 03315 mask |= DemandsAttention; 03316 else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top) 03317 mask |= StaysOnTop; 03318 } 03319 03320 // when removing, we just leave newstate == 0 03321 switch (event->xclient.data.l[0]) { 03322 case 1: // set 03323 // to set... the change state should be the same as the mask 03324 state = mask; 03325 break; 03326 03327 case 2: // toggle 03328 // to toggle, we need to xor the current state with the new state 03329 state = (p->state & mask) ^ mask; 03330 break; 03331 03332 default: 03333 // to clear state, the new state should stay zero 03334 ; 03335 } 03336 03337 #ifdef NETWMDEBUG 03338 fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n", 03339 state, mask); 03340 #endif 03341 03342 changeState(state, mask); 03343 } else if (event->xclient.message_type == net_wm_desktop) { 03344 dirty = WMDesktop; 03345 03346 if( event->xclient.data.l[0] == OnAllDesktops ) 03347 changeDesktop( OnAllDesktops ); 03348 else 03349 changeDesktop(event->xclient.data.l[0] + 1); 03350 } 03351 } 03352 03353 if (event->type == PropertyNotify) { 03354 03355 #ifdef NETWMDEBUG 03356 fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n"); 03357 #endif 03358 03359 XEvent pe = *event; 03360 03361 Bool done = False; 03362 Bool compaction = False; 03363 while (! done) { 03364 03365 #ifdef NETWMDEBUG 03366 fprintf(stderr, "NETWinInfo::event: loop fire\n"); 03367 #endif 03368 03369 if (pe.xproperty.atom == net_wm_name) 03370 dirty |= WMName; 03371 else if (pe.xproperty.atom == net_wm_visible_name) 03372 dirty |= WMVisibleName; 03373 else if (pe.xproperty.atom == net_wm_desktop) 03374 dirty |= WMDesktop; 03375 else if (pe.xproperty.atom == net_wm_window_type) 03376 dirty |=WMWindowType; 03377 else if (pe.xproperty.atom == net_wm_state) 03378 dirty |= WMState; 03379 else if (pe.xproperty.atom == net_wm_strut) 03380 dirty |= WMStrut; 03381 else if (pe.xproperty.atom == net_wm_icon_geometry) 03382 dirty |= WMIconGeometry; 03383 else if (pe.xproperty.atom == net_wm_icon) 03384 dirty |= WMIcon; 03385 else if (pe.xproperty.atom == net_wm_pid) 03386 dirty |= WMPid; 03387 else if (pe.xproperty.atom == net_wm_handled_icons) 03388 dirty |= WMHandledIcons; 03389 else if (pe.xproperty.atom == net_startup_id) 03390 dirty2 |= WM2StartupId; 03391 else if (pe.xproperty.atom == net_wm_allowed_actions) 03392 dirty2 |= WM2AllowedActions; 03393 else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for) 03394 dirty |= WMKDESystemTrayWinFor; 03395 else if (pe.xproperty.atom == xa_wm_state) 03396 dirty |= XAWMState; 03397 else if (pe.xproperty.atom == kde_net_wm_frame_strut) 03398 dirty |= WMKDEFrameStrut; 03399 else if (pe.xproperty.atom == net_wm_icon_name) 03400 dirty |= WMIconName; 03401 else if (pe.xproperty.atom == net_wm_visible_icon_name) 03402 dirty |= WMVisibleIconName; 03403 else if (pe.xproperty.atom == net_wm_user_time) 03404 dirty2 |= WM2UserTime; 03405 else if (pe.xproperty.atom == XA_WM_HINTS) 03406 dirty2 |= WM2GroupLeader; 03407 else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR) 03408 dirty2 |= WM2TransientFor; 03409 else { 03410 03411 #ifdef NETWMDEBUG 03412 fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n"); 03413 #endif 03414 03415 if ( compaction ) 03416 XPutBackEvent(p->display, &pe); 03417 break; 03418 } 03419 03420 if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) ) 03421 compaction = True; 03422 else 03423 break; 03424 } 03425 03426 do_update = true; 03427 } else if (event->type == ConfigureNotify) { 03428 03429 #ifdef NETWMDEBUG 03430 fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n"); 03431 #endif 03432 03433 dirty |= WMGeometry; 03434 03435 // update window geometry 03436 p->win_geom.pos.x = event->xconfigure.x; 03437 p->win_geom.pos.y = event->xconfigure.y; 03438 p->win_geom.size.width = event->xconfigure.width; 03439 p->win_geom.size.height = event->xconfigure.height; 03440 } 03441 03442 if( do_update ) 03443 update( props ); 03444 03445 if( properties_size > PROPERTIES_SIZE ) 03446 properties_size = PROPERTIES_SIZE; 03447 for( int i = 0; 03448 i < properties_size; 03449 ++i ) 03450 properties[ i ] = props[ i ]; 03451 } 03452 03453 void NETWinInfo::updateWMState() { 03454 unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 }; 03455 assert( PROPERTIES_SIZE == 2 ); // add elements above 03456 update( props ); 03457 } 03458 03459 void NETWinInfo::update(const unsigned long dirty_props[]) { 03460 Atom type_ret; 03461 int format_ret; 03462 unsigned long nitems_ret, unused; 03463 unsigned char *data_ret; 03464 unsigned long props[ PROPERTIES_SIZE ]; 03465 for( int i = 0; 03466 i < PROPERTIES_SIZE; 03467 ++i ) 03468 props[ i ] = dirty_props[ i ] & p->properties[ i ]; 03469 const unsigned long& dirty = props[ PROTOCOLS ]; 03470 const unsigned long& dirty2 = props[ PROTOCOLS2 ]; 03471 03472 // we *always* want to update WM_STATE if set in dirty_props 03473 if( dirty_props[ PROTOCOLS ] & XAWMState ) 03474 props[ PROTOCOLS ] |= XAWMState; 03475 03476 if (dirty & XAWMState) { 03477 p->mapping_state = Withdrawn; 03478 if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l, 03479 False, xa_wm_state, &type_ret, &format_ret, 03480 &nitems_ret, &unused, &data_ret) 03481 == Success) { 03482 if (type_ret == xa_wm_state && format_ret == 32 && 03483 nitems_ret == 1) { 03484 long *state = (long *) data_ret; 03485 03486 switch(*state) { 03487 case IconicState: 03488 p->mapping_state = Iconic; 03489 break; 03490 case NormalState: 03491 p->mapping_state = Visible; 03492 break; 03493 case WithdrawnState: 03494 default: 03495 p->mapping_state = Withdrawn; 03496 break; 03497 } 03498 03499 p->mapping_state_dirty = False; 03500 } 03501 if ( data_ret ) 03502 XFree(data_ret); 03503 } 03504 } 03505 03506 if (dirty & WMState) { 03507 p->state = 0; 03508 if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l, 03509 False, XA_ATOM, &type_ret, &format_ret, 03510 &nitems_ret, &unused, &data_ret) 03511 == Success) { 03512 if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) { 03513 // determine window state 03514 #ifdef NETWMDEBUG 03515 fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n", 03516 nitems_ret); 03517 #endif 03518 03519 long *states = (long *) data_ret; 03520 unsigned long count; 03521 03522 for (count = 0; count < nitems_ret; count++) { 03523 #ifdef NETWMDEBUG 03524 char* data_ret = XGetAtomName(p->display, (Atom) states[count]); 03525 fprintf(stderr, 03526 "NETWinInfo::update: adding window state %ld '%s'\n", 03527 states[count], data_ret ); 03528 if ( data_ret ) 03529 XFree( data_ret ); 03530 #endif 03531 03532 if ((Atom) states[count] == net_wm_state_modal) 03533 p->state |= Modal; 03534 else if ((Atom) states[count] == net_wm_state_sticky) 03535 p->state |= Sticky; 03536 else if ((Atom) states[count] == net_wm_state_max_vert) 03537 p->state |= MaxVert; 03538 else if ((Atom) states[count] == net_wm_state_max_horiz) 03539 p->state |= MaxHoriz; 03540 else if ((Atom) states[count] == net_wm_state_shaded) 03541 p->state |= Shaded; 03542 else if ((Atom) states[count] == net_wm_state_skip_taskbar) 03543 p->state |= SkipTaskbar; 03544 else if ((Atom) states[count] == net_wm_state_skip_pager) 03545 p->state |= SkipPager; 03546 else if ((Atom) states[count] == net_wm_state_hidden) 03547 p->state |= Hidden; 03548 else if ((Atom) states[count] == net_wm_state_fullscreen) 03549 p->state |= FullScreen; 03550 else if ((Atom) states[count] == net_wm_state_above) 03551 p->state |= KeepAbove; 03552 else if ((Atom) states[count] == net_wm_state_below) 03553 p->state |= KeepBelow; 03554 else if ((Atom) states[count] == net_wm_state_demands_attention) 03555 p->state |= DemandsAttention; 03556 else if ((Atom) states[count] == net_wm_state_stays_on_top) 03557 p->state |= StaysOnTop; 03558 } 03559 } 03560 if ( data_ret ) 03561 XFree(data_ret); 03562 } 03563 } 03564 03565 if (dirty & WMDesktop) { 03566 p->desktop = 0; 03567 if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l, 03568 False, XA_CARDINAL, &type_ret, 03569 &format_ret, &nitems_ret, 03570 &unused, &data_ret) 03571 == Success) { 03572 if (type_ret == XA_CARDINAL && format_ret == 32 && 03573 nitems_ret == 1) { 03574 p->desktop = *((long *) data_ret); 03575 if ((signed) p->desktop != OnAllDesktops) 03576 p->desktop++; 03577 03578 if ( p->desktop == 0 ) 03579 p->desktop = OnAllDesktops; 03580 } 03581 if ( data_ret ) 03582 XFree(data_ret); 03583 } 03584 } 03585 03586 if (dirty & WMName) { 03587 delete[] p->name; 03588 p->name = NULL; 03589 if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l, 03590 MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, 03591 &format_ret, &nitems_ret, &unused, &data_ret) 03592 == Success) { 03593 if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) { 03594 p->name = nstrndup((const char *) data_ret, nitems_ret); 03595 } 03596 03597 if( data_ret ) 03598 XFree(data_ret); 03599 } 03600 } 03601 03602 if (dirty & WMVisibleName) { 03603 delete[] p->visible_name; 03604 p->visible_name = NULL; 03605 if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l, 03606 MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, 03607 &format_ret, &nitems_ret, &unused, &data_ret) 03608 == Success) { 03609 if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) { 03610 p->visible_name = nstrndup((const char *) data_ret, nitems_ret); 03611 } 03612 03613 if( data_ret ) 03614 XFree(data_ret); 03615 } 03616 } 03617 03618 if (dirty & WMIconName) { 03619 delete[] p->icon_name; 03620 p->icon_name = NULL; 03621 if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l, 03622 MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, 03623 &format_ret, &nitems_ret, &unused, &data_ret) 03624 == Success) { 03625 if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) { 03626 p->icon_name = nstrndup((const char *) data_ret, nitems_ret); 03627 } 03628 03629 if( data_ret ) 03630 XFree(data_ret); 03631 } 03632 } 03633 03634 if (dirty & WMVisibleIconName) 03635 { 03636 delete[] p->visible_icon_name; 03637 p->visible_icon_name = NULL; 03638 if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l, 03639 MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, 03640 &format_ret, &nitems_ret, &unused, &data_ret) 03641 == Success) { 03642 if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) { 03643 p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret); 03644 } 03645 03646 if( data_ret ) 03647 XFree(data_ret); 03648 } 03649 } 03650 03651 if (dirty & WMWindowType) { 03652 p->types.reset(); 03653 p->types[ 0 ] = Unknown; 03654 p->has_net_support = false; 03655 if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l, 03656 False, XA_ATOM, &type_ret, &format_ret, 03657 &nitems_ret, &unused, &data_ret) 03658 == Success) { 03659 if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) { 03660 // determine the window type 03661 #ifdef NETWMDEBUG 03662 fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n", 03663 nitems_ret); 03664 #endif 03665 03666 p->has_net_support = true; 03667 03668 unsigned long count = 0; 03669 long *types = (long *) data_ret; 03670 int pos = 0; 03671 03672 while (count < nitems_ret) { 03673 // remember all window types we know 03674 #ifdef NETWMDEBUG 03675 char* debug_type = XGetAtomName(p->display, (Atom) types[count]); 03676 fprintf(stderr, 03677 "NETWinInfo::update: examining window type %ld %s\n", 03678 types[count], debug_type ); 03679 if ( debug_type ) 03680 XFree( debug_type ); 03681 #endif 03682 03683 if ((Atom) types[count] == net_wm_window_type_normal) 03684 p->types[ pos++ ] = Normal; 03685 else if ((Atom) types[count] == net_wm_window_type_desktop) 03686 p->types[ pos++ ] = Desktop; 03687 else if ((Atom) types[count] == net_wm_window_type_dock) 03688 p->types[ pos++ ] = Dock; 03689 else if ((Atom) types[count] == net_wm_window_type_toolbar) 03690 p->types[ pos++ ] = Tool; 03691 else if ((Atom) types[count] == net_wm_window_type_menu) 03692 p->types[ pos++ ] = Menu; 03693 else if ((Atom) types[count] == net_wm_window_type_dialog) 03694 p->types[ pos++ ] = Dialog; 03695 else if ((Atom) types[count] == net_wm_window_type_utility) 03696 p->types[ pos++ ] = Utility; 03697 else if ((Atom) types[count] == net_wm_window_type_splash) 03698 p->types[ pos++ ] = Splash; 03699 else if ((Atom) types[count] == kde_net_wm_window_type_override) 03700 p->types[ pos++ ] = Override; 03701 else if ((Atom) types[count] == kde_net_wm_window_type_topmenu) 03702 p->types[ pos++ ] = TopMenu; 03703 03704 count++; 03705 } 03706 } 03707 03708 if ( data_ret ) 03709 XFree(data_ret); 03710 } 03711 } 03712 03713 if (dirty & WMStrut) { 03714 p->strut = NETStrut(); 03715 if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l, 03716 False, XA_CARDINAL, &type_ret, &format_ret, 03717 &nitems_ret, &unused, &data_ret) 03718 == Success) { 03719 if (type_ret == XA_CARDINAL && format_ret == 32 && 03720 nitems_ret == 4) { 03721 long *d = (long *) data_ret; 03722 p->strut.left = d[0]; 03723 p->strut.right = d[1]; 03724 p->strut.top = d[2]; 03725 p->strut.bottom = d[3]; 03726 } 03727 if ( data_ret ) 03728 XFree(data_ret); 03729 } 03730 } 03731 03732 if (dirty & WMIconGeometry) { 03733 p->icon_geom = NETRect(); 03734 if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l, 03735 False, XA_CARDINAL, &type_ret, &format_ret, 03736 &nitems_ret, &unused, &data_ret) 03737 == Success) { 03738 if (type_ret == XA_CARDINAL && format_ret == 32 && 03739 nitems_ret == 4) { 03740 long *d = (long *) data_ret; 03741 p->icon_geom.pos.x = d[0]; 03742 p->icon_geom.pos.y = d[1]; 03743 p->icon_geom.size.width = d[2]; 03744 p->icon_geom.size.height = d[3]; 03745 } 03746 if ( data_ret ) 03747 XFree(data_ret); 03748 } 03749 } 03750 03751 if (dirty & WMIcon) { 03752 readIcon(p); 03753 } 03754 03755 if (dirty & WMKDESystemTrayWinFor) { 03756 p->kde_system_tray_win_for = 0; 03757 if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for, 03758 0l, 1l, False, XA_WINDOW, &type_ret, &format_ret, 03759 &nitems_ret, &unused, &data_ret) 03760 == Success) { 03761 if (type_ret == XA_WINDOW && format_ret == 32 && 03762 nitems_ret == 1) { 03763 p->kde_system_tray_win_for = *((Window *) data_ret); 03764 if ( p->kde_system_tray_win_for == 0 ) 03765 p->kde_system_tray_win_for = p->root; 03766 } 03767 if ( data_ret ) 03768 XFree(data_ret); 03769 } 03770 } 03771 03772 if (dirty & WMKDEFrameStrut) { 03773 p->frame_strut = NETStrut(); 03774 if (XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut, 03775 0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret, 03776 &nitems_ret, &unused, &data_ret) == Success) { 03777 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) { 03778 long *d = (long *) data_ret; 03779 03780 p->frame_strut.left = d[0]; 03781 p->frame_strut.right = d[1]; 03782 p->frame_strut.top = d[2]; 03783 p->frame_strut.bottom = d[3]; 03784 } 03785 if ( data_ret ) 03786 XFree(data_ret); 03787 } 03788 } 03789 03790 if (dirty & WMPid) { 03791 p->pid = 0; 03792 if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l, 03793 False, XA_CARDINAL, &type_ret, &format_ret, 03794 &nitems_ret, &unused, &data_ret) == Success) { 03795 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) { 03796 p->pid = *((long *) data_ret); 03797 } 03798 if ( data_ret ) 03799 XFree(data_ret); 03800 } 03801 } 03802 03803 if (dirty2 & WM2StartupId) 03804 { 03805 delete[] p->startup_id; 03806 p->startup_id = NULL; 03807 if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l, 03808 MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, 03809 &format_ret, &nitems_ret, &unused, &data_ret) 03810 == Success) { 03811 if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) { 03812 p->startup_id = nstrndup((const char *) data_ret, nitems_ret); 03813 } 03814 03815 if( data_ret ) 03816 XFree(data_ret); 03817 } 03818 } 03819 03820 if( dirty2 & WM2AllowedActions ) { 03821 p->allowed_actions = 0; 03822 if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l, 03823 False, XA_ATOM, &type_ret, &format_ret, 03824 &nitems_ret, &unused, &data_ret) 03825 == Success) { 03826 if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) { 03827 // determine actions 03828 #ifdef NETWMDEBUG 03829 fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n", 03830 nitems_ret); 03831 #endif 03832 03833 long *actions = (long *) data_ret; 03834 unsigned long count; 03835 03836 for (count = 0; count < nitems_ret; count++) { 03837 #ifdef NETWMDEBUG 03838 fprintf(stderr, 03839 "NETWinInfo::update: adding allowed action %ld '%s'\n", 03840 actions[count], 03841 XGetAtomName(p->display, (Atom) actions[count])); 03842 #endif 03843 03844 if ((Atom) actions[count] == net_wm_action_move) 03845 p->allowed_actions |= ActionMove; 03846 if ((Atom) actions[count] == net_wm_action_resize) 03847 p->allowed_actions |= ActionResize; 03848 if ((Atom) actions[count] == net_wm_action_minimize) 03849 p->allowed_actions |= ActionMinimize; 03850 if ((Atom) actions[count] == net_wm_action_shade) 03851 p->allowed_actions |= ActionShade; 03852 if ((Atom) actions[count] == net_wm_action_stick) 03853 p->allowed_actions |= ActionStick; 03854 if ((Atom) actions[count] == net_wm_action_max_vert) 03855 p->allowed_actions |= ActionMaxVert; 03856 if ((Atom) actions[count] == net_wm_action_max_horiz) 03857 p->allowed_actions |= ActionMaxHoriz; 03858 if ((Atom) actions[count] == net_wm_action_fullscreen) 03859 p->allowed_actions |= ActionFullScreen; 03860 if ((Atom) actions[count] == net_wm_action_change_desk) 03861 p->allowed_actions |= ActionChangeDesktop; 03862 if ((Atom) actions[count] == net_wm_action_close) 03863 p->allowed_actions |= ActionClose; 03864 } 03865 } 03866 if ( data_ret ) 03867 XFree(data_ret); 03868 } 03869 } 03870 03871 if (dirty2 & WM2UserTime) { 03872 p->user_time = -1U; 03873 if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l, 03874 False, XA_CARDINAL, &type_ret, &format_ret, 03875 &nitems_ret, &unused, &data_ret) == Success) { 03876 // don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it 03877 if (type_ret == XA_CARDINAL && format_ret == 32 /*&& nitems_ret == 1*/) { 03878 p->user_time = *((long *) data_ret); 03879 } 03880 if ( data_ret ) 03881 XFree(data_ret); 03882 } 03883 } 03884 03885 if (dirty2 & WM2TransientFor) { 03886 p->transient_for = None; 03887 XGetTransientForHint(p->display, p->window, &p->transient_for); 03888 } 03889 03890 if (dirty2 & WM2GroupLeader) { 03891 XWMHints *hints = XGetWMHints(p->display, p->window); 03892 p->window_group = None; 03893 if ( hints ) 03894 { 03895 if( hints->flags & WindowGroupHint ) 03896 p->window_group = hints->window_group; 03897 XFree( reinterpret_cast< char* >( hints )); 03898 } 03899 } 03900 03901 } 03902 03903 03904 NETRect NETWinInfo::iconGeometry() const { 03905 return p->icon_geom; 03906 } 03907 03908 03909 unsigned long NETWinInfo::state() const { 03910 return p->state; 03911 } 03912 03913 03914 NETStrut NETWinInfo::strut() const { 03915 return p->strut; 03916 } 03917 03918 NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const { 03919 for( int i = 0; 03920 i < p->types.size(); 03921 ++i ) { 03922 switch( p->types[ i ] ) { 03923 // return the type only if the application supports it 03924 #define CHECK_TYPE_MASK( type ) \ 03925 case type: \ 03926 if( supported_types & type##Mask ) \ 03927 return type; \ 03928 break; 03929 CHECK_TYPE_MASK( Normal ) 03930 CHECK_TYPE_MASK( Desktop ) 03931 CHECK_TYPE_MASK( Dock ) 03932 CHECK_TYPE_MASK( Toolbar ) 03933 CHECK_TYPE_MASK( Menu ) 03934 CHECK_TYPE_MASK( Dialog ) 03935 CHECK_TYPE_MASK( Override ) 03936 CHECK_TYPE_MASK( TopMenu ) 03937 CHECK_TYPE_MASK( Utility ) 03938 CHECK_TYPE_MASK( Splash ) 03939 #undef CHECK_TYPE_MASK 03940 default: 03941 break; 03942 } 03943 } 03944 return Unknown; 03945 } 03946 03947 NET::WindowType NETWinInfo::windowType() const { 03948 return p->types[ 0 ]; 03949 } 03950 03951 03952 const char *NETWinInfo::name() const { 03953 return p->name; 03954 } 03955 03956 03957 const char *NETWinInfo::visibleName() const { 03958 return p->visible_name; 03959 } 03960 03961 03962 const char *NETWinInfo::iconName() const { 03963 return p->icon_name; 03964 } 03965 03966 03967 const char *NETWinInfo::visibleIconName() const { 03968 return p->visible_icon_name; 03969 } 03970 03971 03972 int NETWinInfo::desktop() const { 03973 return p->desktop; 03974 } 03975 03976 int NETWinInfo::pid() const { 03977 return p->pid; 03978 } 03979 03980 Time NETWinInfo::userTime() const { 03981 return p->user_time; 03982 } 03983 03984 const char* NETWinInfo::startupId() const { 03985 return p->startup_id; 03986 } 03987 03988 unsigned long NETWinInfo::allowedActions() const { 03989 return p->allowed_actions; 03990 } 03991 03992 bool NETWinInfo::hasNETSupport() const { 03993 return p->has_net_support; 03994 } 03995 03996 Window NETWinInfo::transientFor() const { 03997 return p->transient_for; 03998 } 03999 04000 Window NETWinInfo::groupLeader() const { 04001 return p->window_group; 04002 } 04003 04004 Bool NETWinInfo::handledIcons() const { 04005 return p->handled_icons; 04006 } 04007 04008 04009 Window NETWinInfo::kdeSystemTrayWinFor() const { 04010 return p->kde_system_tray_win_for; 04011 } 04012 04013 const unsigned long* NETWinInfo::passedProperties() const { 04014 return p->properties; 04015 } 04016 04017 unsigned long NETWinInfo::properties() const { 04018 return p->properties[ PROTOCOLS ]; 04019 } 04020 04021 04022 NET::MappingState NETWinInfo::mappingState() const { 04023 return p->mapping_state; 04024 } 04025 04026 void NETRootInfo::virtual_hook( int, void* ) 04027 { /*BASE::virtual_hook( id, data );*/ } 04028 04029 void NETWinInfo::virtual_hook( int, void* ) 04030 { /*BASE::virtual_hook( id, data );*/ } 04031 04032 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 10 18:54:57 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003