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