]> Dogcows Code - chaz/openbox/blob - otk/property.cc
Add the "obsetroot" tool. Use it to set the root background.
[chaz/openbox] / otk / property.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 #include "property.hh"
6 #include "display.hh"
7
8 extern "C" {
9 #include <X11/Xatom.h>
10 }
11
12 #include <algorithm>
13 #include <cassert>
14
15 namespace otk {
16
17 Atoms Property::atoms;
18
19 static Atom create(char *name) { return XInternAtom(**display, name, false); }
20
21 void Property::initialize()
22 {
23 assert(display);
24
25 // make sure asserts fire if there is a problem
26 memset(&atoms, 0, sizeof(Atoms));
27
28 atoms.cardinal = XA_CARDINAL;
29 atoms.window = XA_WINDOW;
30 atoms.pixmap = XA_PIXMAP;
31 atoms.atom = XA_ATOM;
32 atoms.string = XA_STRING;
33 atoms.utf8 = create("UTF8_STRING");
34
35 atoms.openbox_pid = create("_OPENBOX_PID");
36
37 atoms.wm_colormap_windows = create("WM_COLORMAP_WINDOWS");
38 atoms.wm_protocols = create("WM_PROTOCOLS");
39 atoms.wm_state = create("WM_STATE");
40 atoms.wm_change_state = create("WM_CHANGE_STATE");
41 atoms.wm_delete_window = create("WM_DELETE_WINDOW");
42 atoms.wm_take_focus = create("WM_TAKE_FOCUS");
43 atoms.wm_name = create("WM_NAME");
44 atoms.wm_icon_name = create("WM_ICON_NAME");
45 atoms.wm_class = create("WM_CLASS");
46 atoms.wm_window_role = create("WM_WINDOW_ROLE");
47 atoms.motif_wm_hints = create("_MOTIF_WM_HINTS");
48
49 atoms.openbox_show_root_menu = create("_OPENBOX_SHOW_ROOT_MENU");
50 atoms.openbox_show_workspace_menu = create("_OPENBOX_SHOW_WORKSPACE_MENU");
51
52 atoms.net_supported = create("_NET_SUPPORTED");
53 atoms.net_client_list = create("_NET_CLIENT_LIST");
54 atoms.net_client_list_stacking = create("_NET_CLIENT_LIST_STACKING");
55 atoms.net_number_of_desktops = create("_NET_NUMBER_OF_DESKTOPS");
56 atoms.net_desktop_geometry = create("_NET_DESKTOP_GEOMETRY");
57 atoms.net_desktop_viewport = create("_NET_DESKTOP_VIEWPORT");
58 atoms.net_current_desktop = create("_NET_CURRENT_DESKTOP");
59 atoms.net_desktop_names = create("_NET_DESKTOP_NAMES");
60 atoms.net_active_window = create("_NET_ACTIVE_WINDOW");
61 atoms.net_workarea = create("_NET_WORKAREA");
62 atoms.net_supporting_wm_check = create("_NET_SUPPORTING_WM_CHECK");
63 // atoms.net_virtual_roots = create("_NET_VIRTUAL_ROOTS");
64 atoms.net_desktop_layout = create("_NET_DESKTOP_LAYOUT");
65 atoms.net_showing_desktop = create("_NET_SHOWING_DESKTOP");
66
67 atoms.net_close_window = create("_NET_CLOSE_WINDOW");
68 atoms.net_wm_moveresize = create("_NET_WM_MOVERESIZE");
69
70 // atoms.net_properties = create("_NET_PROPERTIES");
71 atoms.net_wm_name = create("_NET_WM_NAME");
72 atoms.net_wm_visible_name = create("_NET_WM_VISIBLE_NAME");
73 atoms.net_wm_icon_name = create("_NET_WM_ICON_NAME");
74 atoms.net_wm_visible_icon_name = create("_NET_WM_VISIBLE_ICON_NAME");
75 atoms.net_wm_desktop = create("_NET_WM_DESKTOP");
76 atoms.net_wm_window_type = create("_NET_WM_WINDOW_TYPE");
77 atoms.net_wm_state = create("_NET_WM_STATE");
78 atoms.net_wm_strut = create("_NET_WM_STRUT");
79 // atoms.net_wm_icon_geometry = create("_NET_WM_ICON_GEOMETRY");
80 atoms.net_wm_icon = create("_NET_WM_ICON");
81 // atoms.net_wm_pid = create("_NET_WM_PID");
82 // atoms.net_wm_handled_icons = create("_NET_WM_HANDLED_ICONS");
83 atoms.net_wm_allowed_actions = create("_NET_WM_ALLOWED_ACTIONS");
84
85 // atoms.net_wm_ping = create("_NET_WM_PING");
86
87 atoms.net_wm_window_type_desktop = create("_NET_WM_WINDOW_TYPE_DESKTOP");
88 atoms.net_wm_window_type_dock = create("_NET_WM_WINDOW_TYPE_DOCK");
89 atoms.net_wm_window_type_toolbar = create("_NET_WM_WINDOW_TYPE_TOOLBAR");
90 atoms.net_wm_window_type_menu = create("_NET_WM_WINDOW_TYPE_MENU");
91 atoms.net_wm_window_type_utility = create("_NET_WM_WINDOW_TYPE_UTILITY");
92 atoms.net_wm_window_type_splash = create("_NET_WM_WINDOW_TYPE_SPLASH");
93 atoms.net_wm_window_type_dialog = create("_NET_WM_WINDOW_TYPE_DIALOG");
94 atoms.net_wm_window_type_normal = create("_NET_WM_WINDOW_TYPE_NORMAL");
95
96 atoms.net_wm_moveresize_size_topleft =
97 create("_NET_WM_MOVERESIZE_SIZE_TOPLEFT");
98 atoms.net_wm_moveresize_size_topright =
99 create("_NET_WM_MOVERESIZE_SIZE_TOPRIGHT");
100 atoms.net_wm_moveresize_size_bottomleft =
101 create("_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT");
102 atoms.net_wm_moveresize_size_bottomright =
103 create("_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT");
104 atoms.net_wm_moveresize_move =
105 create("_NET_WM_MOVERESIZE_MOVE");
106
107 atoms.net_wm_action_move = create("_NET_WM_ACTION_MOVE");
108 atoms.net_wm_action_resize = create("_NET_WM_ACTION_RESIZE");
109 atoms.net_wm_action_minimize = create("_NET_WM_ACTION_MINIMIZE");
110 atoms.net_wm_action_shade = create("_NET_WM_ACTION_SHADE");
111 atoms.net_wm_action_stick = create("_NET_WM_ACTION_STICK");
112 atoms.net_wm_action_maximize_horz = create("_NET_WM_ACTION_MAXIMIZE_HORZ");
113 atoms.net_wm_action_maximize_vert = create("_NET_WM_ACTION_MAXIMIZE_VERT");
114 atoms.net_wm_action_fullscreen = create("_NET_WM_ACTION_FULLSCREEN");
115 atoms.net_wm_action_change_desktop =
116 create("_NET_WM_ACTION_CHANGE_DESKTOP");
117 atoms.net_wm_action_close = create("_NET_WM_ACTION_CLOSE");
118
119 atoms.net_wm_state_modal = create("_NET_WM_STATE_MODAL");
120 atoms.net_wm_state_sticky = create("_NET_WM_STATE_STICKY");
121 atoms.net_wm_state_maximized_vert = create("_NET_WM_STATE_MAXIMIZED_VERT");
122 atoms.net_wm_state_maximized_horz = create("_NET_WM_STATE_MAXIMIZED_HORZ");
123 atoms.net_wm_state_shaded = create("_NET_WM_STATE_SHADED");
124 atoms.net_wm_state_skip_taskbar = create("_NET_WM_STATE_SKIP_TASKBAR");
125 atoms.net_wm_state_skip_pager = create("_NET_WM_STATE_SKIP_PAGER");
126 atoms.net_wm_state_hidden = create("_NET_WM_STATE_HIDDEN");
127 atoms.net_wm_state_fullscreen = create("_NET_WM_STATE_FULLSCREEN");
128 atoms.net_wm_state_above = create("_NET_WM_STATE_ABOVE");
129 atoms.net_wm_state_below = create("_NET_WM_STATE_BELOW");
130
131 atoms.kde_net_system_tray_windows = create("_KDE_NET_SYSTEM_TRAY_WINDOWS");
132 atoms.kde_net_wm_system_tray_window_for =
133 create("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR");
134 atoms.kde_net_wm_window_type_override =
135 create("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
136
137 atoms.rootpmapid = create("_XROOTPMAP_ID");
138 atoms.esetrootid = create("ESETROOT_PMAP_ID");
139
140 atoms.openbox_premax = create("_OPENBOX_PREMAX");
141 atoms.openbox_active_window = create("_OPENBOX_ACTIVE_WINDOW");
142 }
143
144 void Property::set(Window win, Atom atom, Atom type, unsigned char* data,
145 int size, int nelements, bool append)
146 {
147 assert(win != None); assert(atom != None); assert(type != None);
148 assert(nelements == 0 || (nelements > 0 && data != (unsigned char *) 0));
149 assert(size == 8 || size == 16 || size == 32);
150 XChangeProperty(**display, win, atom, type, size,
151 (append ? PropModeAppend : PropModeReplace),
152 data, nelements);
153 }
154
155 void Property::set(Window win, Atom atom, Atom type, unsigned long value)
156 {
157 set(win, atom, type, (unsigned char*) &value, 32, 1, false);
158 }
159
160 void Property::set(Window win, Atom atom, Atom type, unsigned long value[],
161 int elements)
162 {
163 set(win, atom, type, (unsigned char*) value, 32, elements, false);
164 }
165
166 void Property::set(Window win, Atom atom, StringType type,
167 const ustring &value)
168 {
169 Atom t;
170 switch (type) {
171 case ascii: t = atoms.string; assert(!value.utf8()); break;
172 case utf8: t = atoms.utf8; assert(value.utf8()); break;
173 default: assert(false); return; // unhandled StringType
174 }
175
176 // add 1 to the size to include the trailing null
177 set(win, atom, t, (unsigned char*) value.c_str(), 8, value.bytes() + 1,
178 false);
179 }
180
181 void Property::set(Window win, Atom atom, StringType type,
182 const StringVect &strings)
183 {
184 Atom t;
185 bool u; // utf8 encoded?
186 switch (type) {
187 case ascii: t = atoms.string; u = false; break;
188 case utf8: t = atoms.utf8; u = true; break;
189 default: assert(false); return; // unhandled StringType
190 }
191
192 ustring value(u);
193
194 StringVect::const_iterator it = strings.begin();
195 const StringVect::const_iterator end = strings.end();
196 for (; it != end; ++it) {
197 assert(it->utf8() == u); // the ustring is encoded correctly?
198 value += *it;
199 value += '\0';
200 }
201
202 // add 1 to the size to include the trailing null
203 set(win, atom, t, (unsigned char*)value.c_str(), 8,
204 value.bytes() + 1, false);
205 }
206
207 bool Property::get(Window win, Atom atom, Atom type, unsigned long *nelements,
208 unsigned char **value, int size)
209 {
210 assert(win != None); assert(atom != None); assert(type != None);
211 assert(size == 8 || size == 16 || size == 32);
212 assert(*nelements > 0);
213 unsigned char *c_val = 0; // value alloc'd in Xlib, must be XFree()d
214 Atom ret_type;
215 int ret_size;
216 unsigned long ret_bytes;
217 int result;
218 unsigned long maxread = *nelements;
219 bool ret = false;
220
221 // try get the first element
222 result = XGetWindowProperty(**display, win, atom, 0l, 1l,
223 false, AnyPropertyType, &ret_type, &ret_size,
224 nelements, &ret_bytes, &c_val);
225 ret = (result == Success && ret_type == type && ret_size == size &&
226 *nelements > 0);
227 if (ret) {
228 if (ret_bytes == 0 || maxread <= *nelements) {
229 // we got the whole property's value
230 *value = new unsigned char[*nelements * size/8 + 1];
231 memcpy(*value, c_val, *nelements * size/8 + 1);
232 } else {
233 // get the entire property since it is larger than one long
234 XFree(c_val);
235 // the number of longs that need to be retreived to get the property's
236 // entire value. The last + 1 is the first long that we retrieved above.
237 int remain = (ret_bytes - 1)/sizeof(long) + 1 + 1;
238 if (remain > size/8 * (signed)maxread) // dont get more than the max
239 remain = size/8 * (signed)maxread;
240 result = XGetWindowProperty(**display, win, atom, 0l,
241 remain, false, type, &ret_type, &ret_size,
242 nelements, &ret_bytes, &c_val);
243 ret = (result == Success && ret_type == type && ret_size == size &&
244 ret_bytes == 0);
245 /*
246 If the property has changed type/size, or has grown since our first
247 read of it, then stop here and try again. If it shrank, then this will
248 still work.
249 */
250 if (! ret)
251 return get(win, atom, type, &maxread, value, size);
252
253 *value = new unsigned char[*nelements * size/8 + 1];
254 memcpy(*value, c_val, *nelements * size/8 + 1);
255 }
256 }
257 if (c_val) XFree(c_val);
258 return ret;
259 }
260
261 bool Property::get(Window win, Atom atom, Atom type, unsigned long *nelements,
262 unsigned long **value)
263 {
264 return get(win, atom, type, nelements, (unsigned char**) value, 32);
265 }
266
267 bool Property::get(Window win, Atom atom, Atom type, unsigned long *value)
268 {
269 unsigned long *temp;
270 unsigned long num = 1;
271 if (! get(win, atom, type, &num, (unsigned char **) &temp, 32))
272 return false;
273 *value = temp[0];
274 delete [] temp;
275 return true;
276 }
277
278 bool Property::get(Window win, Atom atom, StringType type, ustring *value)
279 {
280 unsigned long n = 1;
281 StringVect s;
282
283 if (get(win, atom, type, &n, &s)) {
284 *value = s[0];
285 return true;
286 }
287 return false;
288 }
289
290 bool Property::get(Window win, Atom atom, StringType type,
291 unsigned long *nelements, StringVect *strings)
292 {
293 assert(*nelements > 0);
294
295 Atom t;
296 bool u; // utf8 encoded?
297 switch (type) {
298 case ascii: t = atoms.string; u = false; break;
299 case utf8: t = atoms.utf8; u = true; break;
300 default: assert(false); return false; // unhandled StringType
301 }
302
303 unsigned char *value;
304 unsigned long elements = (unsigned) -1;
305 if (!get(win, atom, t, &elements, &value, 8) || elements < 1)
306 return false;
307
308 std::string s((char*)value, elements);
309 delete [] value;
310
311 std::string::const_iterator it = s.begin(), end = s.end();
312 unsigned long num = 0;
313 while(num < *nelements) {
314 std::string::const_iterator tmp = it; // current string.begin()
315 it = std::find(tmp, end, '\0'); // look for null between tmp and end
316 strings->push_back(std::string(tmp, it)); // s[tmp:it)
317 strings->back().setUtf8(u);
318 ++num;
319 if (it == end) break;
320 ++it;
321 if (it == end) break;
322 }
323
324 *nelements = num;
325
326 return true;
327 }
328
329
330 /*
331 * Removes a property entirely from a window.
332 */
333 void Property::erase(Window win, Atom atom)
334 {
335 XDeleteProperty(**display, win, atom);
336 }
337
338 }
This page took 0.052212 seconds and 4 git commands to generate.