1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
3 // Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
25 // Methods, ideas, implementations taken from Openbox's XAtom class *sigh*
29 #include "Netclient.h"
31 Netclient::Netclient (const bt::Display
&display
)
32 : bt::EWMH(display
), _display(display
)
39 Netclient::~Netclient ()
43 void Netclient::init_icccm(void) {
45 "WM_COLORMAP_WINDOWS",
56 XInternAtoms(_display
.XDisplay(), atoms
, 9, False
, atoms_return
);
57 xa_wm_colormap_windows
= atoms_return
[0];
58 xa_wm_protocols
= atoms_return
[1];
59 xa_wm_name
= atoms_return
[2];
60 xa_wm_state
= atoms_return
[3];
61 xa_wm_class
= atoms_return
[4];
62 xa_wm_change_state
= atoms_return
[5];
63 xa_wm_delete_window
= atoms_return
[6];
64 xa_wm_take_focus
= atoms_return
[7];
65 motif_wm_hints
= atoms_return
[8];
69 void Netclient::init_extras(void) {
71 "_OPENBOX_SHOW_ROOT_MENU",
72 "_OPENBOX_SHOW_WORKSPACE_MENU",
73 "ENLIGHTENMENT_DESKTOP",
77 XInternAtoms(_display
.XDisplay(), atoms
, 2, False
, atoms_return
);
78 openbox_show_root_menu
= atoms_return
[0];
79 openbox_show_workspace_menu
= atoms_return
[1];
80 enlightenment_desktop
= atoms_return
[2];
81 net_virtual_roots
= atoms_return
[3];
85 void Netclient::init_blackbox(void) {
88 "_BLACKBOX_ATTRIBUTES",
89 "_BLACKBOX_CHANGE_ATTRIBUTES"
92 XInternAtoms(_display
.XDisplay(), atoms
, 3, False
, atoms_return
);
93 blackbox_hints
= atoms_return
[0];
94 blackbox_attributes
= atoms_return
[1];
95 blackbox_change_attributes
= atoms_return
[2];
99 std::string
Netclient::getWindowTitle(Window win
) const
102 std::string _title
= "";
105 if (! getValue(win
, wmName(), utf8
, _title
)) {
107 getValue(win
, XA_WM_NAME
, ansi
, _title
);
116 unsigned int Netclient::getDesktop(Window win
) const {
117 unsigned long _desktop
= 0ul;
119 if (! getValue(win
, wmDesktop(), XA_CARDINAL
, _desktop
))
122 return static_cast<unsigned int>(_desktop
);
126 * Internal getValue function used by all of the typed getValue functions.
127 * Gets an property's value from a window.
128 * Returns True if the property was successfully retrieved; False if the
129 * property did not exist on the window, or has a different type/size format
130 * than the user tried to retrieve.
132 bool Netclient::getValue(Window win
, Atom atom
, Atom type
,
133 unsigned long &nelements
, unsigned char **value
,
135 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
136 assert(size
== 8 || size
== 16 || size
== 32);
137 assert(nelements
> 0);
138 unsigned char *c_val
= 0; // value alloc'd in Xlib, must be XFree()d
141 unsigned long ret_bytes
;
143 unsigned long maxread
= nelements
;
146 // try get the first element
147 result
= XGetWindowProperty(_display
.XDisplay(), win
, atom
, 0l, 1l, False
,
148 AnyPropertyType
, &ret_type
, &ret_size
,
149 &nelements
, &ret_bytes
, &c_val
);
150 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
153 if (ret_bytes
== 0 || maxread
<= nelements
) {
154 // we got the whole property's value
155 *value
= new unsigned char[nelements
* size
/8 + 1];
156 memcpy(*value
, c_val
, nelements
* size
/8 + 1);
158 // get the entire property since it is larger than one long
160 // the number of longs that need to be retreived to get the property's
161 // entire value. The last + 1 is the first long that we retrieved above.
162 int remain
= (ret_bytes
- 1)/sizeof(long) + 1 + 1;
163 if (remain
> size
/8 * (signed)maxread
) // dont get more than the max
164 remain
= size
/8 * (signed)maxread
;
165 result
= XGetWindowProperty(_display
.XDisplay(), win
, atom
, 0l, remain
, False
, type
,
166 &ret_type
, &ret_size
, &nelements
, &ret_bytes
,
168 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
171 If the property has changed type/size, or has grown since our first
172 read of it, then stop here and try again. If it shrank, then this will
176 return getValue(win
, atom
, type
, maxread
, value
, size
);
178 *value
= new unsigned char[nelements
* size
/8 + 1];
179 memcpy(*value
, c_val
, nelements
* size
/8 + 1);
182 if (c_val
) XFree(c_val
);
188 * Gets a 32-bit property's value from a window.
190 bool Netclient::getValue(Window win
, Atom atom
, Atom type
,
191 unsigned long &nelements
,
192 unsigned long **value
) const {
193 return getValue(win
, atom
, type
, nelements
,
194 reinterpret_cast<unsigned char **>(value
), 32);
199 * Gets a single 32-bit property's value from a window.
201 bool Netclient::getValue(Window win
, Atom atom
, Atom type
,
202 unsigned long &value
) const {
204 unsigned long num
= 1;
205 if (! getValue(win
, atom
, type
, num
,
206 reinterpret_cast<unsigned char **>(&temp
), 32))
216 * Gets an string property's value from a window.
218 bool Netclient::getValue(Window win
, Atom atom
, StringType type
,
219 std::string
&value
) const {
222 if (getValue(win
, atom
, type
, n
, s
)) {
230 bool Netclient::getValue(Window win
, Atom atom
, StringType type
,
231 unsigned long &nelements
, StringVect
&strings
) const {
232 assert(win
!= None
); assert(atom
!= None
);
233 assert(nelements
> 0);
237 case ansi
: t
= XA_STRING
; break;
238 case utf8
: t
= utf8String(); break;
239 default: assert(False
); return False
; // unhandled StringType
242 unsigned char *value
;
243 unsigned long elements
= (unsigned) -1;
244 if (!getValue(win
, atom
, t
, elements
, &value
, 8) || elements
< 1)
247 std::string
s(reinterpret_cast<char *>(value
), elements
);
250 std::string::const_iterator it
= s
.begin(), end
= s
.end();
251 unsigned long num
= 0;
252 while(num
< nelements
) {
253 std::string::const_iterator tmp
= it
; // current string.begin()
254 it
= std::find(tmp
, end
, '\0'); // look for null between tmp and end
255 strings
.push_back(std::string(tmp
, it
)); // s[tmp:it)
257 if (it
== end
) break;
259 if (it
== end
) break;
269 * Removes a property entirely from a window.
271 void Netclient::eraseValue(Window win
, Atom atom
) const {
272 XDeleteProperty(_display
.XDisplay(), win
, atom
);
276 void Netclient::sendClientMessage(Window target
, Atom type
, Window about
,
277 long data
, long data1
, long data2
,
278 long data3
, long data4
) const {
279 assert(target
!= None
);
282 e
.xclient
.type
= ClientMessage
;
283 e
.xclient
.format
= 32;
284 e
.xclient
.message_type
= type
;
285 e
.xclient
.window
= about
;
286 e
.xclient
.data
.l
[0] = data
;
287 e
.xclient
.data
.l
[1] = data1
;
288 e
.xclient
.data
.l
[2] = data2
;
289 e
.xclient
.data
.l
[3] = data3
;
290 e
.xclient
.data
.l
[4] = data4
;
292 XSendEvent(_display
.XDisplay(), target
, False
,
293 SubstructureRedirectMask
| SubstructureNotifyMask
,
297 bool Netclient::isAtomSupported(Window win
, Atom atom
) const {
299 bool supported
= False
;
301 bt::EWMH::AtomList atoms
;
303 if (readSupported(win
, atoms
) && atoms
.size() > 0) {
304 if (std::find(atoms
.begin(), atoms
.end(), atom
) != atoms
.end()) {
312 Window
* Netclient::getNetVirtualRootList(Window win
) {
316 unsigned long nitems_ret
, unused
;
317 unsigned char *data_ret
;
318 Window
*winsReturn
= 0;
320 int e
= XGetWindowProperty(_display
.XDisplay(), win
, xaNetVirtualRoots(),
321 0, 0, False
, XA_WINDOW
, &type_ret
,
322 &format_ret
, &nitems_ret
, &unused
, &data_ret
);
324 if (e
== Success
&& type_ret
== XA_WINDOW
&& format_ret
== 32) {
325 Window
*wins
= (Window
*) data_ret
;
327 winsReturn
= new Window
[nitems_ret
];
328 while (nitems_ret
--) winsReturn
[nitems_ret
] = wins
[nitems_ret
];