]> Dogcows Code - chaz/openbox/blob - tools/obxprop/obxprop.c
Fix ordering so fallback for inactive osd to label works
[chaz/openbox] / tools / obxprop / obxprop.c
1 #include <X11/Xlib.h>
2 #include <X11/cursorfont.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <assert.h>
7 #include <glib.h>
8
9 gint fail(const gchar *s) {
10 if (s)
11 fprintf(stderr, "%s\n", s);
12 else
13 fprintf
14 (stderr,
15 "Usage: obxprop [OPTIONS]\n\n"
16 "Options:\n"
17 " --help Display this help and exit\n"
18 " --display DISPLAY Connect to this X display\n"
19 " --id ID Show the properties for this window\n"
20 " --root Show the properties for the root window\n");
21 return 1;
22 }
23
24 gint parse_hex(gchar *s) {
25 gint result = 0;
26 while (*s) {
27 gint add;
28 if (*s >= '0' && *s <='9')
29 add = *s-'0';
30 else if (*s >= 'A' && *s <='F')
31 add = *s-'A';
32 else if (*s >= 'a' && *s <='f')
33 add = *s-'a';
34 else
35 break;
36
37 result *= 16;
38 result += add;
39 }
40 return result;
41 }
42
43 Window find_client(Display *d, Window win)
44 {
45 Window r, *children;
46 guint n, i;
47 Atom state = XInternAtom(d, "WM_STATE", True);
48 Atom ret_type;
49 gint ret_format, res;
50 gulong ret_items, ret_bytesleft, *xdata;
51
52 XQueryTree(d, win, &r, &r, &children, &n);
53 for (i = 0; i < n; ++i) {
54 Window w = find_client(d, children[i]);
55 if (w) return w;
56 }
57
58 // try me
59 res = XGetWindowProperty(d, win, state, 0, 1,
60 False, state, &ret_type, &ret_format,
61 &ret_items, &ret_bytesleft,
62 (unsigned char**) &xdata);
63 XFree(xdata);
64 if (res != Success || ret_type == None || ret_items < 1)
65 return None;
66 return win; // found it!
67 }
68
69 static gboolean get_all(Display *d, Window win, Atom prop,
70 Atom *type, gint *size,
71 guchar **data, guint *num)
72 {
73 gboolean ret = FALSE;
74 gint res;
75 guchar *xdata = NULL;
76 gulong ret_items, bytes_left;
77
78 res = XGetWindowProperty(d, win, prop, 0l, G_MAXLONG,
79 FALSE, AnyPropertyType, type, size,
80 &ret_items, &bytes_left, &xdata);
81 if (res == Success) {
82 if (ret_items > 0) {
83 guint i;
84
85 *data = g_malloc(ret_items * (*size / 8));
86 for (i = 0; i < ret_items; ++i)
87 switch (*size) {
88 case 8:
89 (*data)[i] = xdata[i];
90 break;
91 case 16:
92 ((guint16*)*data)[i] = ((gushort*)xdata)[i];
93 break;
94 case 32:
95 ((guint32*)*data)[i] = ((gulong*)xdata)[i];
96 break;
97 default:
98 g_assert_not_reached(); /* unhandled size */
99 }
100 *num = ret_items;
101 ret = TRUE;
102 }
103 XFree(xdata);
104 }
105 return ret;
106 }
107
108 gchar *append_string(gchar *before, gchar *after, gboolean quote)
109 {
110 gchar *tmp;
111 const gchar *q = quote ? "\"" : "";
112 if (before)
113 tmp = g_strdup_printf("%s, %s%s%s", before, q, after, q);
114 else
115 tmp = g_strdup_printf("%s%s%s", q, after, q);
116 g_free(before);
117 return tmp;
118 }
119
120 gchar *append_int(gchar *before, guint after)
121 {
122 gchar *tmp;
123 if (before)
124 tmp = g_strdup_printf("%s, %u", before, after);
125 else
126 tmp = g_strdup_printf("%u", after);
127 g_free(before);
128 return tmp;
129 }
130
131 gchar* read_strings(gchar *val, guint n, gboolean utf8)
132 {
133 GSList *strs = NULL, *it;
134 gchar *ret, *p;
135 guint i;
136
137 p = val;
138 while (p < val + n) {
139 strs = g_slist_append(strs, g_strndup(p, n - (p - val)));
140 p += strlen(p) + 1; /* next string */
141 }
142
143 ret = NULL;
144 for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
145 char *data;
146
147 if (utf8) {
148 if (g_utf8_validate(it->data, -1, NULL))
149 data = g_strdup(it->data);
150 else
151 data = g_strdup("");
152 }
153 else
154 data = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL);
155
156 ret = append_string(ret, data, TRUE);
157 g_free(data);
158 }
159
160 while (strs) {
161 g_free(strs->data);
162 strs = g_slist_delete_link(strs, strs);
163 }
164 return ret;
165 }
166
167 gchar* read_atoms(Display *d, guchar *val, guint n)
168 {
169 gchar *ret;
170 guint i;
171
172 ret = NULL;
173 for (i = 0; i < n; ++i)
174 ret = append_string(ret, XGetAtomName(d, ((guint32*)val)[i]), FALSE);
175 return ret;
176 }
177
178 gchar* read_numbers(guchar *val, guint n, guint size)
179 {
180 gchar *ret;
181 guint i;
182
183 ret = NULL;
184 for (i = 0; i < n; ++i)
185 switch (size) {
186 case 8:
187 ret = append_int(ret, ((guint8*)val)[i]);
188 break;
189 case 16:
190 ret = append_int(ret, ((guint16*)val)[i]);
191 break;
192 case 32:
193 ret = append_int(ret, ((guint32*)val)[i]);
194 break;
195 default:
196 g_assert_not_reached(); /* unhandled size */
197 }
198
199 return ret;
200 }
201
202 gboolean read_prop(Display *d, Window w, Atom prop, const gchar **type, gchar **val)
203 {
204 guchar *ret;
205 guint nret;
206 gint size;
207 Atom ret_type;
208
209 ret = NULL;
210 if (get_all(d, w, prop, &ret_type, &size, &ret, &nret)) {
211 *type = XGetAtomName(d, ret_type);
212
213 if (strcmp(*type, "STRING") == 0)
214 *val = read_strings((gchar*)ret, nret, FALSE);
215 else if (strcmp(*type, "UTF8_STRING") == 0)
216 *val = read_strings((gchar*)ret, nret, TRUE);
217 else if (strcmp(*type, "ATOM") == 0) {
218 g_assert(size == 32);
219 *val = read_atoms(d, ret, nret);
220 }
221 else
222 *val = read_numbers(ret, nret, size);
223
224 g_free(ret);
225 return TRUE;
226 }
227 return FALSE;
228 }
229
230 void show_properties(Display *d, Window w)
231 {
232 Atom* props;
233 int i, n;
234
235 props = XListProperties(d, w, &n);
236
237 for (i = 0; i < n; ++i) {
238 const char *type;
239 char *name, *val;
240
241 name = XGetAtomName(d, props[i]);
242
243 if (read_prop(d, w, props[i], &type, &val)) {
244 g_print("%s(%s) = %s\n", name, type, val);
245 g_free(val);
246 }
247
248 XFree(name);
249 }
250
251 XFree(props);
252 }
253
254 int main(int argc, char **argv)
255 {
256 Display *d;
257 Window id, userid = None;
258 int i;
259 char *dname = NULL;
260 gboolean root = FALSE;
261
262 for (i = 1; i < argc; ++i) {
263 if (!strcmp(argv[i], "--help")) {
264 return fail(0);
265 }
266 else if (!strcmp(argv[i], "--root"))
267 root = TRUE;
268 else if (!strcmp(argv[i], "--id")) {
269 if (++i == argc)
270 return fail(0);
271 if (argv[i][0] == '0' && argv[i][1] == 'x') {
272 /* hex */
273 userid = parse_hex(argv[i]+2);
274 }
275 else {
276 /* decimal */
277 userid = atoi(argv[i]);
278 }
279 break;
280 }
281 else if (!strcmp(argv[i], "--display")) {
282 if (++i == argc)
283 return fail(0);
284 dname = argv[i];
285 }
286 }
287
288 d = XOpenDisplay(dname);
289 if (!d) {
290 return fail("Unable to find an X display. "
291 "Ensure you have permission to connect to the display.");
292 }
293
294 if (root)
295 userid = RootWindow(d, DefaultScreen(d));
296
297 if (userid == None) {
298 i = XGrabPointer(d, RootWindow(d, DefaultScreen(d)),
299 False, ButtonPressMask,
300 GrabModeAsync, GrabModeAsync,
301 None, XCreateFontCursor(d, XC_crosshair),
302 CurrentTime);
303 if (i != GrabSuccess)
304 return fail("Unable to grab the pointer device");
305 while (1) {
306 XEvent ev;
307
308 XNextEvent(d, &ev);
309 if (ev.type == ButtonPress) {
310 XUngrabPointer(d, CurrentTime);
311 userid = ev.xbutton.subwindow;
312 break;
313 }
314 }
315 }
316
317 id = find_client(d, userid);
318
319 if (id == None)
320 return fail("Unable to find window with the requested ID");
321
322 show_properties(d, id);
323
324 XCloseDisplay(d);
325
326 return 0;
327 }
This page took 0.049764 seconds and 4 git commands to generate.