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