1 // XAtom.cc for Openbox
2 // Copyright (c) 2002 - 2002 Ben Jansens (xor at orodu.net)
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
22 #include "../config.h"
25 #include "blackbox.hh"
29 XAtom::XAtom(Blackbox
*bb
) {
30 _display
= bb
->getXDisplay();
32 // make sure asserts fire if there is a problem
33 memset(_atoms
, sizeof(_atoms
), 0);
35 _atoms
[utf8_string
] = create("UTF8_STRING");
38 _atoms
[blackbox_pid
] = create("_BLACKBOX_PID");
41 _atoms
[wm_colormap_windows
] = create("WM_COLORMAP_WINDOWS");
42 _atoms
[wm_protocols
] = create("WM_PROTOCOLS");
43 _atoms
[wm_state
] = create("WM_STATE");
44 _atoms
[wm_change_state
] = create("WM_CHANGE_STATE");
45 _atoms
[wm_delete_window
] = create("WM_DELETE_WINDOW");
46 _atoms
[wm_take_focus
] = create("WM_TAKE_FOCUS");
47 _atoms
[motif_wm_hints
] = create("_MOTIF_WM_HINTS");
48 _atoms
[blackbox_hints
] = create("_BLACKBOX_HINTS");
49 _atoms
[blackbox_attributes
] = create("_BLACKBOX_ATTRIBUTES");
50 _atoms
[blackbox_change_attributes
] = create("_BLACKBOX_CHANGE_ATTRIBUTES");
51 _atoms
[blackbox_structure_messages
] = create("_BLACKBOX_STRUCTURE_MESSAGES");
52 _atoms
[blackbox_notify_startup
] = create("_BLACKBOX_NOTIFY_STARTUP");
53 _atoms
[blackbox_notify_window_add
] = create("_BLACKBOX_NOTIFY_WINDOW_ADD");
54 _atoms
[blackbox_notify_window_del
] = create("_BLACKBOX_NOTIFY_WINDOW_DEL");
55 _atoms
[blackbox_notify_current_workspace
] =
56 create("_BLACKBOX_NOTIFY_CURRENT_WORKSPACE");
57 _atoms
[blackbox_notify_workspace_count
] =
58 create("_BLACKBOX_NOTIFY_WORKSPACE_COUNT");
59 _atoms
[blackbox_notify_window_focus
] =
60 create("_BLACKBOX_NOTIFY_WINDOW_FOCUS");
61 _atoms
[blackbox_notify_window_raise
] =
62 create("_BLACKBOX_NOTIFY_WINDOW_RAISE");
63 _atoms
[blackbox_notify_window_lower
] =
64 create("_BLACKBOX_NOTIFY_WINDOW_LOWER");
66 _atoms
[blackbox_change_workspace
] = create("_BLACKBOX_CHANGE_WORKSPACE");
67 _atoms
[blackbox_change_window_focus
] =
68 create("_BLACKBOX_CHANGE_WINDOW_FOCUS");
69 _atoms
[blackbox_cycle_window_focus
] = create("_BLACKBOX_CYCLE_WINDOW_FOCUS");
71 _atoms
[net_supported
] = create("_NET_SUPPORTED");
72 _atoms
[net_client_list
] = create("_NET_CLIENT_LIST");
73 _atoms
[net_client_list_stacking
] = create("_NET_CLIENT_LIST_STACKING");
74 _atoms
[net_number_of_desktops
] = create("_NET_NUMBER_OF_DESKTOPS");
75 _atoms
[net_desktop_geometry
] = create("_NET_DESKTOP_GEOMETRY");
76 _atoms
[net_desktop_viewport
] = create("_NET_DESKTOP_VIEWPORT");
77 _atoms
[net_current_desktop
] = create("_NET_CURRENT_DESKTOP");
78 _atoms
[net_desktop_names
] = create("_NET_DESKTOP_NAMES");
79 _atoms
[net_active_window
] = create("_NET_ACTIVE_WINDOW");
80 _atoms
[net_workarea
] = create("_NET_WORKAREA");
81 _atoms
[net_supporting_wm_check
] = create("_NET_SUPPORTING_WM_CHECK");
82 _atoms
[net_virtual_roots
] = create("_NET_VIRTUAL_ROOTS");
84 _atoms
[net_close_window
] = create("_NET_CLOSE_WINDOW");
85 _atoms
[net_wm_moveresize
] = create("_NET_WM_MOVERESIZE");
87 _atoms
[net_properties
] = create("_NET_PROPERTIES");
88 _atoms
[net_wm_name
] = create("_NET_WM_NAME");
89 _atoms
[net_wm_desktop
] = create("_NET_WM_DESKTOP");
90 _atoms
[net_wm_window_type
] = create("_NET_WM_WINDOW_TYPE");
91 _atoms
[net_wm_state
] = create("_NET_WM_STATE");
92 _atoms
[net_wm_strut
] = create("_NET_WM_STRUT");
93 _atoms
[net_wm_icon_geometry
] = create("_NET_WM_ICON_GEOMETRY");
94 _atoms
[net_wm_icon
] = create("_NET_WM_ICON");
95 _atoms
[net_wm_pid
] = create("_NET_WM_PID");
96 _atoms
[net_wm_handled_icons
] = create("_NET_WM_HANDLED_ICONS");
98 _atoms
[net_wm_ping
] = create("_NET_WM_PING");
103 * clean up the class' members
106 while (!_support_windows
.empty()) {
107 // make sure we aren't fucking with this somewhere
108 assert(_support_windows
.back() != None
);
109 XDestroyWindow(_display
, _support_windows
.back());
110 _support_windows
.pop_back();
116 * Returns an atom from the Xserver, creating it if necessary.
118 Atom
XAtom::create(const char *name
) const {
119 return XInternAtom(_display
, name
, False
);
124 * Sets which atoms are supported for NETWM, by Openbox, on the root window.
126 void XAtom::setSupported(const ScreenInfo
*screen
) {
127 Window root
= screen
->getRootWindow();
129 // create the netwm support window
130 Window w
= XCreateSimpleWindow(_display
, root
, 0, 0, 1, 1, 0, 0, 0);
132 _support_windows
.push_back(w
);
134 // set supporting window
135 setValue(root
, net_supporting_wm_check
, Type_Window
, w
);
137 //set properties on the supporting window
138 setValue(w
, net_wm_name
, Type_Utf8
, "Openbox");
139 setValue(w
, net_supporting_wm_check
, Type_Window
, w
);
142 // we don't support any yet..
146 _atoms
[net_supported
] // remove me later, cuz i dont think i belong
149 eraseValue(root
, net_supported
);
150 for (unsigned int i
= 0, num
= sizeof(supported
)/sizeof(Atom
); i
< num
; ++i
)
151 addValue(root
, net_supported
, Type_Atom
, supported
[i
]);
156 * Internal setValue used by all typed setValue functions.
157 * Sets a window property on a window, optionally appending to the existing
160 void XAtom::setValue(Window win
, AvailableAtoms atom
, Atom type
,
161 unsigned char* data
, int size
, int nelements
,
163 assert(atom
>= 0 && atom
< NUM_ATOMS
);
164 assert(win
!= None
); assert(type
!= None
);
165 assert(data
!= (unsigned char *) 0);
166 assert(size
== 8 || size
== 16 || size
== 32);
167 assert(nelements
> 0);
168 XChangeProperty(_display
, win
, _atoms
[atom
], type
, size
,
169 (append
? PropModeAppend
: PropModeReplace
),
175 * Set a 32-bit property value on a window.
177 void XAtom::setValue(Window win
, AvailableAtoms atom
, AtomType type
,
178 unsigned long value
) const {
181 case Type_Cardinal
: t
= XA_CARDINAL
; break;
182 case Type_Atom
: t
= XA_ATOM
; break;
183 case Type_Window
: t
= XA_WINDOW
; break;
184 case Type_Pixmap
: t
= XA_PIXMAP
; break;
185 default: assert(false); // unhandled AtomType
187 setValue(win
, atom
, t
, reinterpret_cast<unsigned char*>(&value
),
193 * Set a string property value on a window.
195 void XAtom::setValue(Window win
, AvailableAtoms atom
, StringType type
,
196 const std::string
&value
) const {
199 case Type_String
: t
= XA_STRING
; break;
200 case Type_Utf8
: t
= _atoms
[utf8_string
]; break;
201 default: assert(false); // unhandled StringType
203 setValue(win
, atom
, t
,
204 const_cast<unsigned char*>
205 (reinterpret_cast<const unsigned char*>(value
.c_str())),
206 8, value
.size(), false);
211 * Add elements to a 32-bit property value on a window.
213 void XAtom::addValue(Window win
, AvailableAtoms atom
, AtomType type
,
214 unsigned long value
) const {
217 case Type_Cardinal
: t
= XA_CARDINAL
; break;
218 case Type_Atom
: t
= XA_ATOM
; break;
219 case Type_Window
: t
= XA_WINDOW
; break;
220 case Type_Pixmap
: t
= XA_PIXMAP
; break;
221 default: assert(false); // unhandled Atom_Type
223 setValue(win
, atom
, t
, reinterpret_cast<unsigned char*>(&value
), 32, 1, true);
228 * Add characters to a string property value on a window.
230 void XAtom::addValue(Window win
, AvailableAtoms atom
, StringType type
,
231 const std::string
&value
) const {
234 case Type_String
: t
= XA_STRING
; break;
235 case Type_Utf8
: t
= _atoms
[utf8_string
]; break;
236 default: assert(false); // unhandled StringType
238 setValue(win
, atom
, t
,
239 const_cast<unsigned char*>
240 (reinterpret_cast<const unsigned char *>
242 8, value
.size(), true);
247 * Internal getValue function used by all of the typed getValue functions.
248 * Gets an property's value from a window.
249 * Returns true if the property was successfully retrieved; false if the
250 * property did not exist on the window, or has a different type/size format
251 * than the user tried to retrieve.
253 bool XAtom::getValue(Window win
, AvailableAtoms atom
, Atom type
,
254 unsigned long *nelements
, unsigned char **value
,
256 assert(atom
>= 0 && atom
< NUM_ATOMS
);
257 assert(win
!= None
); assert(type
!= None
);
258 assert(size
== 8 || size
== 16 || size
== 32);
259 unsigned char *c_val
; // value alloc'd with c malloc
262 unsigned long ret_bytes
;
263 XGetWindowProperty(_display
, win
, _atoms
[atom
], 0l, 1l, False
,
264 AnyPropertyType
, &ret_type
, &ret_size
, nelements
,
265 &ret_bytes
, &c_val
); // try get the first element
266 if (ret_type
== None
)
267 // the property does not exist on the window
269 if (ret_type
!= type
|| ret_size
!= size
) {
270 // wrong data in property
274 // the data is correct, now, is there more than 1 element?
275 if (ret_bytes
== 0) {
276 // we got the whole property's value
277 *value
= new unsigned char[*nelements
* size
/8 + 1];
278 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
282 // get the entire property since it is larger than one long
284 // the number of longs that need to be retreived to get the property's entire
285 // value. The last + 1 is the first long that we retrieved above.
286 const int remain
= (ret_bytes
- 1)/sizeof(long) + 1 + 1;
287 XGetWindowProperty(_display
, win
, _atoms
[atom
], 0l, remain
, False
, type
,
288 &ret_type
, &ret_size
, nelements
, &ret_bytes
, &c_val
);
289 assert(ret_bytes
== 0);
290 *value
= new unsigned char[*nelements
* size
/8 + 1];
291 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
298 * Gets a 32-bit property's value from a window.
300 bool XAtom::getValue(Window win
, AvailableAtoms atom
, AtomType type
,
301 unsigned long *nelements
,
302 unsigned long **value
) const {
305 case Type_Cardinal
: t
= XA_CARDINAL
; break;
306 case Type_Atom
: t
= XA_ATOM
; break;
307 case Type_Window
: t
= XA_WINDOW
; break;
308 case Type_Pixmap
: t
= XA_PIXMAP
; break;
309 default: assert(false); // unhandled Atom_Type
311 return getValue(win
, atom
, XA_CARDINAL
, nelements
,
312 reinterpret_cast<unsigned char **>(value
), 32);
317 * Gets an string property's value from a window.
319 bool XAtom::getValue(Window win
, AvailableAtoms atom
, StringType type
,
320 std::string
&value
) const {
323 case Type_String
: t
= XA_STRING
; break;
324 case Type_Utf8
: t
= _atoms
[utf8_string
]; break;
325 default: assert(false); // unhandled StringType
328 unsigned long nelements
;
329 bool ret
= getValue(win
, atom
, t
, &nelements
, &data
, 8);
331 value
= reinterpret_cast<char*>(data
);
337 * Removes a property entirely from a window.
339 void XAtom::eraseValue(Window win
, AvailableAtoms atom
) const {
340 XDeleteProperty(_display
, win
, _atoms
[atom
]);