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