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