]> icculus.org git repositories - mikachu/openbox.git/blob - src/XAtom.cc
put webpage in the man page. Also, a couple fixes.
[mikachu/openbox.git] / src / XAtom.cc
1 // XAtom.cc for Openbox
2 // Copyright (c) 2002 - 2002 Ben Jansens (xor at orodu.net)
3 //
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:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
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.
21
22 #include "../config.h"
23
24 #include "XAtom.hh"
25 #include "blackbox.hh"
26 #include "Screen.hh"
27 #include "Util.hh"
28
29 XAtom::XAtom(Blackbox *bb) {
30   _display = bb->getXDisplay();
31
32   // make sure asserts fire if there is a problem
33   memset(_atoms, sizeof(_atoms), 0);
34
35   _atoms[utf8_string] = create("UTF8_STRING");
36   
37 #ifdef    HAVE_GETPID
38   _atoms[blackbox_pid] = create("_BLACKBOX_PID");
39 #endif // HAVE_GETPID
40
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");
65   
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");
70
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");
83
84   _atoms[net_close_window] = create("_NET_CLOSE_WINDOW");
85   _atoms[net_wm_moveresize] = create("_NET_WM_MOVERESIZE");
86
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");
97
98   _atoms[net_wm_ping] = create("_NET_WM_PING");
99 }
100
101
102 /*
103  * clean up the class' members
104  */
105 XAtom::~XAtom() {
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();
111   }
112 }
113
114
115 /*
116  * Returns an atom from the Xserver, creating it if necessary.
117  */
118 Atom XAtom::create(const char *name) const {
119   return XInternAtom(_display, name, False);
120 }
121
122
123 /*
124  * Sets which atoms are supported for NETWM, by Openbox, on the root window.
125  */
126 void XAtom::setSupported(const ScreenInfo *screen) {
127   Window root = screen->getRootWindow();
128
129   // create the netwm support window
130   Window w = XCreateSimpleWindow(_display, root, 0, 0, 1, 1, 0, 0, 0);
131   assert(w != None);
132   _support_windows.push_back(w);
133   
134   // set supporting window
135   setValue(root, net_supporting_wm_check, Type_Window, w);
136  
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);
140   
141   
142   // we don't support any yet..
143   // yes we do!
144
145   Atom supported[] = {
146     _atoms[net_supported]      // remove me later, cuz i dont think i belong
147   };
148
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]);
152 }
153   
154
155 /*
156  * Internal setValue used by all typed setValue functions.
157  * Sets a window property on a window, optionally appending to the existing
158  * value.
159  */
160 void XAtom::setValue(Window win, AvailableAtoms atom, Atom type,
161                      unsigned char* data, int size, int nelements,
162                      bool append) const {
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),
170                   data, nelements);                  
171 }
172
173
174 /*
175  * Set a 32-bit property value on a window.
176  */
177 void XAtom::setValue(Window win, AvailableAtoms atom, AtomType type,
178                      unsigned long value) const {
179   Atom t;
180   switch (type) {
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
186   }
187   setValue(win, atom, t, reinterpret_cast<unsigned char*>(&value),
188            32, 1, false);
189 }
190
191
192 /*
193  * Set a string property value on a window.
194  */
195 void XAtom::setValue(Window win, AvailableAtoms atom, StringType type,
196                      const std::string &value) const {
197   Atom t;
198   switch (type) {
199   case Type_String: t = XA_STRING;           break;
200   case Type_Utf8:   t = _atoms[utf8_string]; break;
201   default: assert(false); // unhandled StringType
202   }
203   setValue(win, atom, t,
204            const_cast<unsigned char*>
205            (reinterpret_cast<const unsigned char*>(value.c_str())),
206            8, value.size(), false);
207 }
208
209
210 /*
211  * Add elements to a 32-bit property value on a window.
212  */
213 void XAtom::addValue(Window win, AvailableAtoms atom, AtomType type,
214                      unsigned long value) const {
215   Atom t;
216   switch (type) {
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
222   }
223   setValue(win, atom, t, reinterpret_cast<unsigned char*>(&value), 32, 1, true);
224 }
225
226
227 /*
228  * Add characters to a string property value on a window.
229  */
230 void XAtom::addValue(Window win, AvailableAtoms atom, StringType type,
231                      const std::string &value) const {
232   Atom t;
233   switch (type) {
234   case Type_String: t = XA_STRING;           break;
235   case Type_Utf8:   t = _atoms[utf8_string]; break;
236   default: assert(false); // unhandled StringType
237   }
238   setValue(win, atom, t,
239            const_cast<unsigned char*>
240            (reinterpret_cast<const unsigned char *>
241             (value.c_str())),
242            8, value.size(), true);
243
244
245
246 /*
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.
252  */
253 bool XAtom::getValue(Window win, AvailableAtoms atom, Atom type,
254                      unsigned long *nelements, unsigned char **value,
255                      int size) const {
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
260   Atom ret_type;
261   int ret_size;
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
268     return false;
269   if (ret_type != type || ret_size != size) {
270     // wrong data in property
271     XFree(c_val);
272     return false;
273   }
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);
279     XFree(c_val);
280     return true;    
281   }
282   // get the entire property since it is larger than one long
283   free(c_val);
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);
292   XFree(c_val);
293   return true;    
294 }
295
296
297 /*
298  * Gets a 32-bit property's value from a window.
299  */
300 bool XAtom::getValue(Window win, AvailableAtoms atom, AtomType type,
301                          unsigned long *nelements,
302                          unsigned long **value) const {
303   Atom t;
304   switch (type) {
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
310   }
311   return getValue(win, atom, XA_CARDINAL, nelements,
312                   reinterpret_cast<unsigned char **>(value), 32);
313 }
314
315
316 /*
317  * Gets an string property's value from a window.
318  */
319 bool XAtom::getValue(Window win, AvailableAtoms atom, StringType type,
320                      std::string &value) const {
321   Atom t;
322   switch (type) {
323   case Type_String: t = XA_STRING;           break;
324   case Type_Utf8:   t = _atoms[utf8_string]; break;
325   default: assert(false); // unhandled StringType
326   }
327   unsigned char *data;
328   unsigned long nelements;
329   bool ret = getValue(win, atom, t, &nelements, &data, 8);
330   if (ret)
331     value = reinterpret_cast<char*>(data);
332   return ret;
333 }
334
335
336 /*
337  * Removes a property entirely from a window.
338  */
339 void XAtom::eraseValue(Window win, AvailableAtoms atom) const {
340   XDeleteProperty(_display, win, _atoms[atom]);
341 }