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