don't include "cvs" in the version (not using cvs anymore :D)
[blackbox.git] / lib / EWMH.cc
blob7a30d5ff2d1f4a0c494abaae15dfa4f5b864c137
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:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
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.
25 #include "EWMH.hh"
27 #include <X11/Xatom.h>
28 #include <X11/Xlib.h>
30 #include <stdio.h>
33 bt::EWMH::EWMH(const Display &_display)
34 : display(_display)
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 }
110 static const int AtomCount =
111 sizeof(refs) / (sizeof(const char *) + sizeof(Atom *));
112 char *names[AtomCount];
113 Atom atoms[AtomCount];
115 for (int i = 0; i < AtomCount; ++i)
116 names[i] = const_cast<char *>(refs[i].name);
118 XInternAtoms(display.XDisplay(), names, AtomCount, false, atoms);
120 for (int i = 0; i < AtomCount; ++i)
121 *refs[i].atom = atoms[i];
125 // root window properties
127 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);
134 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);
140 atoms.reserve(nitems);
141 atoms.assign(values, values + nitems);
143 XFree(data);
146 return (!atoms.empty());
150 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());
156 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);
162 windows.reserve(nitems);
163 windows.assign(values, values + nitems);
165 XFree(data);
168 return (!windows.empty());
172 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());
179 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);
187 windows.reserve(nitems);
188 windows.assign(values, values + nitems);
190 XFree(data);
193 return (!windows.empty());
197 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);
204 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)));
211 XFree(data);
212 return true;
214 return false;
218 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);
228 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);
237 *width = static_cast<unsigned int>(values[0]);
238 *height = static_cast<unsigned int>(values[1]);
240 XFree(data);
241 return true;
244 return false;
248 void bt::EWMH::setDesktopViewport(Window target, int x, int y) const {
249 const unsigned long viewport[] =
250 { static_cast<long>(x), static_cast<long>(y) };
251 setProperty(target, XA_CARDINAL, net_desktop_viewport,
252 reinterpret_cast<const unsigned char *>(viewport), 2);
256 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);
263 *x = static_cast<int>(values[0]);
264 *y = static_cast<int>(values[1]);
266 XFree(data);
267 return true;
270 return false;
274 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);
281 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);
288 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)));
294 XFree(data);
295 return true;
297 return false;
301 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
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';
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());
319 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
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;
336 XFree(data);
339 return (!names.empty());
343 void bt::EWMH::setActiveWindow(Window target, Window data) const {
344 setProperty(target, XA_WINDOW, net_active_window,
345 reinterpret_cast<unsigned char *>(&data), 1);
349 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);
355 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));
360 XFree(data);
361 return true;
363 return false;
367 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());
373 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);
379 windows.reserve(nitems);
380 windows.assign(values, values + nitems);
382 XFree(data);
385 return (!windows.empty());
389 // application properties
391 void bt::EWMH::setWMName(Window target, const bt::ustring &name) const {
392 if (!hasUnicode())
393 return; // cannot convert UTF-32 to UTF-8
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());
403 bool bt::EWMH::readWMName(Window target, bt::ustring &name) const {
404 if (!hasUnicode())
405 return false; // cannot convert UTF-8 to UTF-32
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);
415 return (!name.empty());
419 void bt::EWMH::setWMVisibleName(Window target,
420 const bt::ustring &name) const {
421 if (!hasUnicode())
422 return; // cannot convert UTF-32 to UTF-8
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());
432 bool bt::EWMH::readWMIconName(Window target, bt::ustring &name) const {
433 if (!hasUnicode())
434 return false; // cannot convert UTF-8 to UTF-32
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);
444 return (!name.empty());
448 void bt::EWMH::setWMVisibleIconName(Window target,
449 const bt::ustring &name) const {
450 if (!hasUnicode())
451 return; // cannot convert UTF-32 to UTF-8
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());
461 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);
468 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)));
474 XFree(data);
475 return true;
477 return false;
481 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);
487 types.reserve(nitems);
488 types.assign(values, values + nitems);
490 XFree(data);
493 return (!types.empty());
497 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());
503 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);
509 states.reserve(nitems);
510 states.assign(values, values + nitems);
512 XFree(data);
515 return (!states.empty());
519 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());
525 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;
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;
538 unsigned long* const values = reinterpret_cast<unsigned long*>(data);
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]);
545 XFree(data);
547 return true;
551 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;
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;
564 unsigned long * const values = reinterpret_cast<unsigned long *>(data);
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]);
579 XFree(data);
581 return true;
585 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);
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]);
599 XFree(data);
600 return true;
603 return false;
607 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)));
613 XFree(data);
614 return true;
616 return false;
620 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));
625 XFree(data);
626 return true;
628 return false;
632 // utility
634 void bt::EWMH::removeProperty(Window target, Atom atom) const {
635 XDeleteProperty(display.XDisplay(), target, atom);
639 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);
647 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;
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;
660 return true;
664 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;
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;
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;
689 *count = nitems;
690 return true;
694 bool bt::EWMH::isSupportedWMWindowType(Atom atom) const {
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.
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);