1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // EWMH.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24
25 #include "EWMH.hh"
26
27 #include <X11/Xatom.h>
28 #include <X11/Xlib.h>
29
30 #include <stdio.h>
31
32
EWMH(const Display & _display)33 bt::EWMH::EWMH(const Display &_display)
34 : display(_display)
35 {
36 const struct AtomRef {
37 const char *name;
38 Atom *atom;
39 } refs[] = {
40 { "UTF8_STRING", &utf8_string },
41 { "_NET_SUPPORTED", &net_supported },
42 { "_NET_CLIENT_LIST", &net_client_list },
43 { "_NET_CLIENT_LIST_STACKING", &net_client_list_stacking },
44 { "_NET_NUMBER_OF_DESKTOPS", &net_number_of_desktops },
45 { "_NET_DESKTOP_GEOMETRY", &net_desktop_geometry },
46 { "_NET_DESKTOP_VIEWPORT", &net_desktop_viewport },
47 { "_NET_CURRENT_DESKTOP", &net_current_desktop },
48 { "_NET_DESKTOP_NAMES", &net_desktop_names },
49 { "_NET_ACTIVE_WINDOW", &net_active_window },
50 { "_NET_WORKAREA", &net_workarea },
51 { "_NET_SUPPORTING_WM_CHECK", &net_supporting_wm_check },
52 { "_NET_VIRTUAL_ROOTS", &net_virtual_roots },
53 { "_NET_DESKTOP_LAYOUT", &net_desktop_layout },
54 { "_NET_SHOWING_DESKTOP", &net_showing_desktop },
55 { "_NET_CLOSE_WINDOW", &net_close_window },
56 { "_NET_MOVERESIZE_WINDOW", &net_moveresize_window },
57 { "_NET_WM_MOVERESIZE", &net_wm_moveresize },
58 { "_NET_RESTACK_WINDOW", &net_restack_window },
59 { "_NET_REQUEST_FRAME_EXTENTS", &net_request_frame_extents },
60 { "_NET_WM_NAME", &net_wm_name },
61 { "_NET_WM_VISIBLE_NAME", &net_wm_visible_name },
62 { "_NET_WM_ICON_NAME", &net_wm_icon_name },
63 { "_NET_WM_VISIBLE_ICON_NAME", &net_wm_visible_icon_name },
64 { "_NET_WM_DESKTOP", &net_wm_desktop },
65 { "_NET_WM_WINDOW_TYPE", &net_wm_window_type },
66 { "_NET_WM_WINDOW_TYPE_DESKTOP", &net_wm_window_type_desktop },
67 { "_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock },
68 { "_NET_WM_WINDOW_TYPE_TOOLBAR", &net_wm_window_type_toolbar },
69 { "_NET_WM_WINDOW_TYPE_MENU", &net_wm_window_type_menu },
70 { "_NET_WM_WINDOW_TYPE_UTILITY", &net_wm_window_type_utility },
71 { "_NET_WM_WINDOW_TYPE_SPLASH", &net_wm_window_type_splash },
72 { "_NET_WM_WINDOW_TYPE_DIALOG", &net_wm_window_type_dialog },
73 { "_NET_WM_WINDOW_TYPE_NORMAL", &net_wm_window_type_normal },
74 { "_NET_WM_STATE", &net_wm_state },
75 { "_NET_WM_STATE_MODAL", &net_wm_state_modal },
76 { "_NET_WM_STATE_STICKY", &net_wm_state_sticky },
77 { "_NET_WM_STATE_MAXIMIZED_VERT", &net_wm_state_maximized_vert },
78 { "_NET_WM_STATE_MAXIMIZED_HORZ", &net_wm_state_maximized_horz },
79 { "_NET_WM_STATE_SHADED", &net_wm_state_shaded },
80 { "_NET_WM_STATE_SKIP_TASKBAR", &net_wm_state_skip_taskbar },
81 { "_NET_WM_STATE_SKIP_PAGER", &net_wm_state_skip_pager },
82 { "_NET_WM_STATE_HIDDEN", &net_wm_state_hidden },
83 { "_NET_WM_STATE_FULLSCREEN", &net_wm_state_fullscreen },
84 { "_NET_WM_STATE_ABOVE", &net_wm_state_above },
85 { "_NET_WM_STATE_BELOW", &net_wm_state_below },
86 { "_NET_WM_STATE_DEMANDS_ATTENTION", &net_wm_state_demands_attention },
87 { "_NET_WM_ALLOWED_ACTIONS", &net_wm_allowed_actions },
88 { "_NET_WM_ACTION_MOVE", &net_wm_action_move },
89 { "_NET_WM_ACTION_RESIZE", &net_wm_action_resize },
90 { "_NET_WM_ACTION_MINIMIZE", &net_wm_action_minimize },
91 { "_NET_WM_ACTION_SHADE", &net_wm_action_shade },
92 { "_NET_WM_ACTION_STICK", &net_wm_action_stick },
93 { "_NET_WM_ACTION_MAXIMIZE_HORZ", &net_wm_action_maximize_horz },
94 { "_NET_WM_ACTION_MAXIMIZE_VERT", &net_wm_action_maximize_vert },
95 { "_NET_WM_ACTION_FULLSCREEN", &net_wm_action_fullscreen },
96 { "_NET_WM_ACTION_CHANGE_DESKTOP", &net_wm_action_change_desktop },
97 { "_NET_WM_ACTION_CLOSE", &net_wm_action_close },
98 { "_NET_WM_STRUT", &net_wm_strut },
99 { "_NET_WM_STRUT_PARTIAL", &net_wm_strut_partial },
100 { "_NET_WM_ICON_GEOMETRY", &net_wm_icon_geometry },
101 { "_NET_WM_ICON", &net_wm_icon },
102 { "_NET_WM_PID", &net_wm_pid },
103 { "_NET_WM_HANDLED_ICONS", &net_wm_handled_icons },
104 { "_NET_WM_USER_TIME", &net_wm_user_time },
105 { "_NET_FRAME_EXTENTS", &net_frame_extents },
106 { "_NET_WM_PING", &net_wm_ping },
107 { "_NET_WM_SYNC_REQUEST", &net_wm_sync_request }
108 };
109
110 static const int AtomCount =
111 sizeof(refs) / (sizeof(const char *) + sizeof(Atom *));
112 char *names[AtomCount];
113 Atom atoms[AtomCount];
114
115 for (int i = 0; i < AtomCount; ++i)
116 names[i] = const_cast<char *>(refs[i].name);
117
118 XInternAtoms(display.XDisplay(), names, AtomCount, false, atoms);
119
120 for (int i = 0; i < AtomCount; ++i)
121 *refs[i].atom = atoms[i];
122 }
123
124
125 // root window properties
126
setSupported(Window target,Atom atoms[],unsigned int count) const127 void bt::EWMH::setSupported(Window target, Atom atoms[],
128 unsigned int count) const {
129 setProperty(target, XA_ATOM, net_supported,
130 reinterpret_cast<unsigned char *>(atoms), count);
131 }
132
133
readSupported(Window target,AtomList & atoms) const134 bool bt::EWMH::readSupported(Window target, AtomList& atoms) const {
135 unsigned char* data = 0;
136 unsigned long nitems;
137 if (getListProperty(target, XA_ATOM, net_supported, &data, &nitems)) {
138 Atom* values = reinterpret_cast<Atom*>(data);
139
140 atoms.reserve(nitems);
141 atoms.assign(values, values + nitems);
142
143 XFree(data);
144 }
145
146 return (!atoms.empty());
147 }
148
149
setClientList(Window target,WindowList & windows) const150 void bt::EWMH::setClientList(Window target, WindowList& windows) const {
151 setProperty(target, XA_WINDOW, net_client_list,
152 reinterpret_cast<unsigned char *>(&windows[0]), windows.size());
153 }
154
155
readClientList(Window target,WindowList & windows) const156 bool bt::EWMH::readClientList(Window target, WindowList& windows) const {
157 unsigned char* data = 0;
158 unsigned long nitems;
159 if (getListProperty(target, XA_WINDOW, net_client_list, &data, &nitems)) {
160 Window* values = reinterpret_cast<Window*>(data);
161
162 windows.reserve(nitems);
163 windows.assign(values, values + nitems);
164
165 XFree(data);
166 }
167
168 return (!windows.empty());
169 }
170
171
setClientListStacking(Window target,WindowList & windows) const172 void bt::EWMH::setClientListStacking(Window target,
173 WindowList& windows) const {
174 setProperty(target, XA_WINDOW, net_client_list_stacking,
175 reinterpret_cast<unsigned char *>(&windows[0]), windows.size());
176 }
177
178
readClientListStacking(Window target,WindowList & windows) const179 bool bt::EWMH::readClientListStacking(Window target,
180 WindowList& windows) const {
181 unsigned char* data = 0;
182 unsigned long nitems;
183 if (getListProperty(target, XA_WINDOW, net_client_list_stacking,
184 &data, &nitems)) {
185 Window* values = reinterpret_cast<Window*>(data);
186
187 windows.reserve(nitems);
188 windows.assign(values, values + nitems);
189
190 XFree(data);
191 }
192
193 return (!windows.empty());
194 }
195
196
setNumberOfDesktops(Window target,unsigned int number) const197 void bt::EWMH::setNumberOfDesktops(Window target, unsigned int number) const {
198 const unsigned long x = number;
199 setProperty(target, XA_CARDINAL, net_number_of_desktops,
200 reinterpret_cast<const unsigned char *>(&x), 1);
201 }
202
203
readNumberOfDesktops(Window target,unsigned int * number) const204 bool bt::EWMH::readNumberOfDesktops(Window target,
205 unsigned int* number) const {
206 unsigned char* data = 0;
207 if (getProperty(target, XA_CARDINAL, net_number_of_desktops, &data)) {
208 *number =
209 static_cast<unsigned int>(*(reinterpret_cast<unsigned long *>(data)));
210
211 XFree(data);
212 return true;
213 }
214 return false;
215 }
216
217
setDesktopGeometry(Window target,unsigned int width,unsigned int height) const218 void bt::EWMH::setDesktopGeometry(Window target,
219 unsigned int width,
220 unsigned int height) const {
221 const unsigned long geometry[] =
222 { static_cast<unsigned long>(width), static_cast<unsigned long> (height) };
223 setProperty(target, XA_CARDINAL, net_desktop_geometry,
224 reinterpret_cast<const unsigned char *>(geometry), 2);
225 }
226
227
readDesktopGeometry(Window target,unsigned int * width,unsigned int * height) const228 bool bt::EWMH::readDesktopGeometry(Window target,
229 unsigned int* width,
230 unsigned int* height) const {
231 unsigned char* data = 0;
232 unsigned long nitems;
233 if (getListProperty(target, XA_CARDINAL, net_desktop_geometry,
234 &data, &nitems) && nitems == 2) {
235 unsigned long *values = reinterpret_cast<unsigned long *>(data);
236
237 *width = static_cast<unsigned int>(values[0]);
238 *height = static_cast<unsigned int>(values[1]);
239
240 XFree(data);
241 return true;
242 }
243
244 return false;
245 }
246
247
setDesktopViewport(Window target,int x,int y) const248 void bt::EWMH::setDesktopViewport(Window target, int x, int y) const {
249 const unsigned long viewport[] =
250 { static_cast<unsigned long>(x), static_cast<unsigned long>(y) };
251 setProperty(target, XA_CARDINAL, net_desktop_viewport,
252 reinterpret_cast<const unsigned char *>(viewport), 2);
253 }
254
255
readDesktopViewport(Window target,int * x,int * y) const256 bool bt::EWMH::readDesktopViewport(Window target, int *x, int *y) const {
257 unsigned char* data = 0;
258 unsigned long nitems;
259 if (getListProperty(target, XA_CARDINAL, net_desktop_viewport,
260 &data, &nitems) && nitems == 2) {
261 const long * const values = reinterpret_cast<long *>(data);
262
263 *x = static_cast<int>(values[0]);
264 *y = static_cast<int>(values[1]);
265
266 XFree(data);
267 return true;
268 }
269
270 return false;
271 }
272
273
setWorkarea(Window target,unsigned long workareas[],unsigned int count) const274 void bt::EWMH::setWorkarea(Window target, unsigned long workareas[],
275 unsigned int count) const {
276 setProperty(target, XA_CARDINAL, net_workarea,
277 reinterpret_cast<unsigned char *>(workareas), count * 4);
278 }
279
280
setCurrentDesktop(Window target,unsigned int number) const281 void bt::EWMH::setCurrentDesktop(Window target, unsigned int number) const {
282 const unsigned long x = static_cast<unsigned long>(number);
283 setProperty(target, XA_CARDINAL, net_current_desktop,
284 reinterpret_cast<const unsigned char *>(&x), 1);
285 }
286
287
readCurrentDesktop(Window target,unsigned int * number) const288 bool bt::EWMH::readCurrentDesktop(Window target, unsigned int* number) const {
289 unsigned char* data = 0;
290 if (getProperty(target, XA_CARDINAL, net_current_desktop, &data)) {
291 *number =
292 static_cast<unsigned int>(*(reinterpret_cast<unsigned long *>(data)));
293
294 XFree(data);
295 return true;
296 }
297 return false;
298 }
299
300
setDesktopNames(Window target,const std::vector<bt::ustring> & names) const301 void bt::EWMH::setDesktopNames(Window target,
302 const std::vector<bt::ustring> &names) const {
303 if (!hasUnicode())
304 return; // cannot convert UTF-32 to UTF-8
305
306 std::string s;
307 std::vector<bt::ustring>::const_iterator it = names.begin();
308 const std::vector<bt::ustring>::const_iterator end = names.end();
309 for (; it != end; ++it)
310 s += toUtf8(*it) + '\0';
311
312 XChangeProperty(display.XDisplay(), target, net_desktop_names, utf8_string,
313 8, PropModeReplace,
314 reinterpret_cast<const unsigned char *>(s.c_str()),
315 s.length());
316 }
317
318
readDesktopNames(Window target,std::vector<bt::ustring> & names) const319 bool bt::EWMH::readDesktopNames(Window target,
320 std::vector<bt::ustring> &names) const {
321 if (!hasUnicode())
322 return false; // cannot convert UTF-8 to UTF-32
323
324 unsigned char *data = 0;
325 unsigned long nitems;
326 if (getListProperty(target, utf8_string, net_desktop_names,
327 &data, &nitems) && nitems > 0) {
328 char *tmp = reinterpret_cast<char *>(data);
329 for (unsigned int i = 0; i < nitems; ++i) {
330 if (data[i] == '\0') {
331 const std::string str(tmp, reinterpret_cast<char *>(data) + i);
332 names.push_back(toUtf32(str));
333 tmp = reinterpret_cast<char *>(data) + i + 1;
334 }
335 }
336 XFree(data);
337 }
338
339 return (!names.empty());
340 }
341
342
setActiveWindow(Window target,Window data) const343 void bt::EWMH::setActiveWindow(Window target, Window data) const {
344 setProperty(target, XA_WINDOW, net_active_window,
345 reinterpret_cast<unsigned char *>(&data), 1);
346 }
347
348
setSupportingWMCheck(Window target,Window data) const349 void bt::EWMH::setSupportingWMCheck(Window target, Window data) const {
350 setProperty(target, XA_WINDOW, net_supporting_wm_check,
351 reinterpret_cast<unsigned char *>(&data), 1);
352 }
353
354
readSupportingWMCheck(Window target,Window * window) const355 bool bt::EWMH::readSupportingWMCheck(Window target, Window* window) const {
356 unsigned char* data = 0;
357 if (getProperty(target, XA_WINDOW, net_supporting_wm_check, &data)) {
358 *window = * (reinterpret_cast<Window*>(data));
359
360 XFree(data);
361 return true;
362 }
363 return false;
364 }
365
366
setVirtualRoots(Window target,WindowList & windows) const367 void bt::EWMH::setVirtualRoots(Window target, WindowList &windows) const {
368 setProperty(target, XA_WINDOW, net_virtual_roots,
369 reinterpret_cast<unsigned char *>(&windows[0]), windows.size());
370 }
371
372
readVirtualRoots(Window target,WindowList & windows) const373 bool bt::EWMH::readVirtualRoots(Window target, WindowList &windows) const {
374 unsigned char* data = 0;
375 unsigned long nitems;
376 if (getListProperty(target, XA_WINDOW, net_virtual_roots, &data, &nitems)) {
377 Window* values = reinterpret_cast<Window*>(data);
378
379 windows.reserve(nitems);
380 windows.assign(values, values + nitems);
381
382 XFree(data);
383 }
384
385 return (!windows.empty());
386 }
387
388
389 // application properties
390
setWMName(Window target,const bt::ustring & name) const391 void bt::EWMH::setWMName(Window target, const bt::ustring &name) const {
392 if (!hasUnicode())
393 return; // cannot convert UTF-32 to UTF-8
394
395 const std::string utf8 = toUtf8(name);
396 XChangeProperty(display.XDisplay(), target, net_wm_name, utf8_string,
397 8, PropModeReplace,
398 reinterpret_cast<const unsigned char *>(utf8.c_str()),
399 utf8.length());
400 }
401
402
readWMName(Window target,bt::ustring & name) const403 bool bt::EWMH::readWMName(Window target, bt::ustring &name) const {
404 if (!hasUnicode())
405 return false; // cannot convert UTF-8 to UTF-32
406
407 unsigned char* data = 0;
408 unsigned long nitems;
409 if (getListProperty(target, utf8_string, net_wm_name,
410 &data, &nitems) && nitems > 0) {
411 name = toUtf32(reinterpret_cast<char*>(data));
412 XFree(data);
413 }
414
415 return (!name.empty());
416 }
417
418
setWMVisibleName(Window target,const bt::ustring & name) const419 void bt::EWMH::setWMVisibleName(Window target,
420 const bt::ustring &name) const {
421 if (!hasUnicode())
422 return; // cannot convert UTF-32 to UTF-8
423
424 const std::string utf8 = toUtf8(name);
425 XChangeProperty(display.XDisplay(), target, net_wm_visible_name, utf8_string,
426 8, PropModeReplace,
427 reinterpret_cast<const unsigned char *>(utf8.c_str()),
428 utf8.length());
429 }
430
431
readWMIconName(Window target,bt::ustring & name) const432 bool bt::EWMH::readWMIconName(Window target, bt::ustring &name) const {
433 if (!hasUnicode())
434 return false; // cannot convert UTF-8 to UTF-32
435
436 unsigned char* data = 0;
437 unsigned long nitems;
438 if (getListProperty(target, utf8_string, net_wm_icon_name,
439 &data, &nitems) && nitems > 0) {
440 name = toUtf32(reinterpret_cast<char*>(data));
441 XFree(data);
442 }
443
444 return (!name.empty());
445 }
446
447
setWMVisibleIconName(Window target,const bt::ustring & name) const448 void bt::EWMH::setWMVisibleIconName(Window target,
449 const bt::ustring &name) const {
450 if (!hasUnicode())
451 return; // cannot convert UTF-32 to UTF-8
452
453 const std::string utf8 = toUtf8(name);
454 XChangeProperty(display.XDisplay(), target, net_wm_visible_icon_name, utf8_string,
455 8, PropModeReplace,
456 reinterpret_cast<const unsigned char *>(utf8.c_str()),
457 utf8.length());
458 }
459
460
setWMDesktop(Window target,unsigned int desktop) const461 void bt::EWMH::setWMDesktop(Window target, unsigned int desktop) const {
462 const unsigned long x = desktop;
463 setProperty(target, XA_CARDINAL, net_wm_desktop,
464 reinterpret_cast<const unsigned char *>(&x), 1);
465 }
466
467
readWMDesktop(Window target,unsigned int & desktop) const468 bool bt::EWMH::readWMDesktop(Window target, unsigned int& desktop) const {
469 unsigned char* data = 0;
470 if (getProperty(target, XA_CARDINAL, net_wm_desktop, &data)) {
471 desktop =
472 static_cast<unsigned int>(*(reinterpret_cast<unsigned long *>(data)));
473
474 XFree(data);
475 return true;
476 }
477 return false;
478 }
479
480
readWMWindowType(Window target,AtomList & types) const481 bool bt::EWMH::readWMWindowType(Window target, AtomList& types) const {
482 unsigned char* data = 0;
483 unsigned long nitems;
484 if (getListProperty(target, XA_ATOM, net_wm_window_type, &data, &nitems)) {
485 Atom* values = reinterpret_cast<Atom*>(data);
486
487 types.reserve(nitems);
488 types.assign(values, values + nitems);
489
490 XFree(data);
491 }
492
493 return (!types.empty());
494 }
495
496
setWMState(Window target,AtomList & atoms) const497 void bt::EWMH::setWMState(Window target, AtomList& atoms) const {
498 setProperty(target, XA_ATOM, net_wm_state,
499 reinterpret_cast<unsigned char *>(&(atoms[0])), atoms.size());
500 }
501
502
readWMState(Window target,AtomList & states) const503 bool bt::EWMH::readWMState(Window target, AtomList& states) const {
504 unsigned char* data = 0;
505 unsigned long nitems;
506 if (getListProperty(target, XA_ATOM, net_wm_state, &data, &nitems)) {
507 Atom* values = reinterpret_cast<Atom*>(data);
508
509 states.reserve(nitems);
510 states.assign(values, values + nitems);
511
512 XFree(data);
513 }
514
515 return (!states.empty());
516 }
517
518
setWMAllowedActions(Window target,AtomList & atoms) const519 void bt::EWMH::setWMAllowedActions(Window target, AtomList& atoms) const {
520 setProperty(target, XA_ATOM, net_wm_allowed_actions,
521 reinterpret_cast<unsigned char *>(&(atoms[0])), atoms.size());
522 }
523
524
readWMStrut(Window target,Strut * strut) const525 bool bt::EWMH::readWMStrut(Window target, Strut* strut) const {
526 Atom atom_return;
527 int size;
528 unsigned long nitems, bytes_left;
529 unsigned char *data;
530
531 int ret = XGetWindowProperty(display.XDisplay(), target, net_wm_strut,
532 0l, 4l, false,
533 XA_CARDINAL, &atom_return, &size,
534 &nitems, &bytes_left, &data);
535 if (ret != Success || nitems < 4)
536 return false;
537
538 unsigned long* const values = reinterpret_cast<unsigned long*>(data);
539
540 strut->left = static_cast<unsigned int>(values[0]);
541 strut->right = static_cast<unsigned int>(values[1]);
542 strut->top = static_cast<unsigned int>(values[2]);
543 strut->bottom = static_cast<unsigned int>(values[3]);
544
545 XFree(data);
546
547 return true;
548 }
549
550
readWMStrutPartial(Window target,StrutPartial * strut) const551 bool bt::EWMH::readWMStrutPartial(Window target, StrutPartial* strut) const {
552 Atom atom_return;
553 int size;
554 unsigned long nitems, bytes_left;
555 unsigned char *data;
556
557 int ret = XGetWindowProperty(display.XDisplay(), target, net_wm_strut_partial,
558 0l, 12l, false,
559 XA_CARDINAL, &atom_return, &size,
560 &nitems, &bytes_left, &data);
561 if (ret != Success || nitems < 4)
562 return false;
563
564 unsigned long * const values = reinterpret_cast<unsigned long *>(data);
565
566 strut->left = static_cast<unsigned int>(values[0]);
567 strut->right = static_cast<unsigned int>(values[1]);
568 strut->top = static_cast<unsigned int>(values[2]);
569 strut->bottom = static_cast<unsigned int>(values[3]);
570 strut->left_start = static_cast<unsigned int>(values[4]);
571 strut->left_end = static_cast<unsigned int>(values[5]);
572 strut->right_start = static_cast<unsigned int>(values[6]);
573 strut->right_end = static_cast<unsigned int>(values[7]);
574 strut->top_start = static_cast<unsigned int>(values[8]);
575 strut->top_end = static_cast<unsigned int>(values[9]);
576 strut->bottom_start = static_cast<unsigned int>(values[10]);
577 strut->bottom_end = static_cast<unsigned int>(values[11]);
578
579 XFree(data);
580
581 return true;
582 }
583
584
readWMIconGeometry(Window target,int & x,int & y,unsigned int & width,unsigned int & height) const585 bool bt::EWMH::readWMIconGeometry(Window target, int &x, int &y,
586 unsigned int &width,
587 unsigned int &height) const {
588 unsigned char *data = 0;
589 unsigned long nitems;
590 if (getListProperty(target, XA_CARDINAL, net_wm_icon_geometry,
591 &data, &nitems) && nitems == 4) {
592 unsigned long *values = reinterpret_cast<unsigned long *>(data);
593
594 x = static_cast<int>(values[0]);
595 y = static_cast<int>(values[1]);
596 width = static_cast<unsigned int>(values[2]);
597 height = static_cast<unsigned int>(values[3]);
598
599 XFree(data);
600 return true;
601 }
602
603 return false;
604 }
605
606
readWMPid(Window target,unsigned int & pid) const607 bool bt::EWMH::readWMPid(Window target, unsigned int &pid) const {
608 unsigned char* data = 0;
609 if (getProperty(target, XA_CARDINAL, net_wm_pid, &data)) {
610 pid =
611 static_cast<unsigned int>(*(reinterpret_cast<unsigned long *>(data)));
612
613 XFree(data);
614 return true;
615 }
616 return false;
617 }
618
619
readWMUserTime(Window target,Time & user_time) const620 bool bt::EWMH::readWMUserTime(Window target, Time &user_time) const {
621 unsigned char* data = 0;
622 if (getProperty(target, XA_CARDINAL, net_wm_user_time, &data)) {
623 user_time = *(reinterpret_cast<unsigned long *>(data));
624
625 XFree(data);
626 return true;
627 }
628 return false;
629 }
630
631
632 // utility
633
removeProperty(Window target,Atom atom) const634 void bt::EWMH::removeProperty(Window target, Atom atom) const {
635 XDeleteProperty(display.XDisplay(), target, atom);
636 }
637
638
setProperty(Window target,Atom type,Atom property,const unsigned char * data,unsigned long count) const639 void bt::EWMH::setProperty(Window target, Atom type, Atom property,
640 const unsigned char *data,
641 unsigned long count) const {
642 XChangeProperty(display.XDisplay(), target, property, type,
643 32, PropModeReplace, data, count);
644 }
645
646
getProperty(Window target,Atom type,Atom property,unsigned char ** data) const647 bool bt::EWMH::getProperty(Window target, Atom type, Atom property,
648 unsigned char** data) const {
649 Atom atom_return;
650 int size;
651 unsigned long nitems, bytes_left;
652
653 int ret = XGetWindowProperty(display.XDisplay(), target, property,
654 0l, 1l, false,
655 type, &atom_return, &size,
656 &nitems, &bytes_left, data);
657 if (ret != Success || nitems != 1)
658 return false;
659
660 return true;
661 }
662
663
getListProperty(Window target,Atom type,Atom property,unsigned char ** data,unsigned long * count) const664 bool bt::EWMH::getListProperty(Window target, Atom type, Atom property,
665 unsigned char** data,
666 unsigned long* count) const {
667 Atom atom_return;
668 int size;
669 unsigned long nitems, bytes_left;
670
671 int ret = XGetWindowProperty(display.XDisplay(), target, property,
672 0l, 1l, false,
673 type, &atom_return, &size,
674 &nitems, &bytes_left, data);
675 if (ret != Success || nitems < 1)
676 return false;
677
678 if (bytes_left != 0) {
679 XFree(*data);
680 unsigned long remain = ((size / 8) * nitems) + bytes_left;
681 ret = XGetWindowProperty(display.XDisplay(), target,
682 property, 0l, remain, false,
683 type, &atom_return, &size,
684 &nitems, &bytes_left, data);
685 if (ret != Success)
686 return false;
687 }
688
689 *count = nitems;
690 return true;
691 }
692
693
isSupportedWMWindowType(Atom atom) const694 bool bt::EWMH::isSupportedWMWindowType(Atom atom) const {
695 /*
696 the implementation looks silly I know. You are probably thinking
697 "why not just do:
698 return (atom > net_wm_window_type && atom <= net_wm_window_type_normal)?".
699 Well the problem is it assumes the atoms were created in a contiguous
700 range. This happens to be true if we created them but could be false if we
701 were started after some EWMH app which allocated the windows in an odd
702 order. So the following is guaranteed to work even if it looks silly and
703 requires more effort to maintain.
704 */
705 return (atom == net_wm_window_type_desktop ||
706 atom == net_wm_window_type_dock ||
707 atom == net_wm_window_type_toolbar ||
708 atom == net_wm_window_type_menu ||
709 atom == net_wm_window_type_utility ||
710 atom == net_wm_window_type_splash ||
711 atom == net_wm_window_type_dialog ||
712 atom == net_wm_window_type_normal);
713 }
714