Add AC_PREREQ to configure.ac; slight reformat of AS_HELP_STRING
[bbkeys.git] / src / Netclient.cpp
blob3306f305b15cdf27beea754c40cc081d3ed37ff7
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // -- Netclient.cpp --
3 // Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
4 //
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.
23 // E_O_H_VR
25 // Methods, ideas, implementations taken from Openbox's XAtom class *sigh*
27 #include <string.h>
29 #include "Netclient.h"
31 Netclient::Netclient (const bt::Display &display)
32 : bt::EWMH(display), _display(display)
34 init_icccm();
35 init_extras();
36 init_blackbox();
39 Netclient::~Netclient ()
43 void Netclient::init_icccm(void) {
44 char* atoms[9] = {
45 "WM_COLORMAP_WINDOWS",
46 "WM_PROTOCOLS",
47 "WM_NAME",
48 "WM_STATE",
49 "WM_CLASS",
50 "WM_CHANGE_STATE",
51 "WM_DELETE_WINDOW",
52 "WM_TAKE_FOCUS",
53 "_MOTIF_WM_HINTS"
55 Atom atoms_return[9];
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) {
70 char* atoms[4] = {
71 "_OPENBOX_SHOW_ROOT_MENU",
72 "_OPENBOX_SHOW_WORKSPACE_MENU",
73 "ENLIGHTENMENT_DESKTOP",
74 "_NET_VIRTUAL_ROOTS"
76 Atom atoms_return[4];
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) {
86 char* atoms[3] = {
87 "_BLACKBOX_HINTS",
88 "_BLACKBOX_ATTRIBUTES",
89 "_BLACKBOX_CHANGE_ATTRIBUTES"
91 Atom atoms_return[3];
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 = "";
104 // try ewmh
105 if (! getValue(win, wmName(), utf8, _title)) {
106 // try old x stuff
107 getValue(win, XA_WM_NAME, ansi, _title);
110 if (_title.empty())
111 _title = "Unnamed";
113 return _title;
116 unsigned int Netclient::getDesktop(Window win) const {
117 unsigned long _desktop = 0ul;
119 if (! getValue(win, wmDesktop(), XA_CARDINAL, _desktop))
120 _desktop = 0ul;
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,
134 int size) const {
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
139 Atom ret_type;
140 int ret_size;
141 unsigned long ret_bytes;
142 int result;
143 unsigned long maxread = nelements;
144 bool ret = False;
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 &&
151 nelements > 0);
152 if (ret) {
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);
157 } else {
158 // get the entire property since it is larger than one long
159 XFree(c_val);
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,
167 &c_val);
168 ret = (result == Success && ret_type == type && ret_size == size &&
169 ret_bytes == 0);
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
173 still work.
175 if (! ret)
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);
183 return ret;
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 {
203 unsigned long *temp;
204 unsigned long num = 1;
205 if (! getValue(win, atom, type, num,
206 reinterpret_cast<unsigned char **>(&temp), 32))
207 return False;
209 value = temp[0];
210 delete [] temp;
211 return True;
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 {
220 unsigned long n = 1;
221 StringVect s;
222 if (getValue(win, atom, type, n, s)) {
223 value = s[0];
224 return True;
226 return False;
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);
235 Atom t;
236 switch (type) {
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)
245 return False;
247 std::string s(reinterpret_cast<char *>(value), elements);
248 delete [] value;
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)
256 ++num;
257 if (it == end) break;
258 ++it;
259 if (it == end) break;
262 nelements = num;
264 return True;
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);
281 XEvent e;
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,
294 &e);
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()) {
305 supported = True;
309 return supported;
312 Window * Netclient::getNetVirtualRootList(Window win) {
314 Atom type_ret;
315 int format_ret;
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];
331 if ( data_ret )
332 XFree(data_ret);
334 return winsReturn;