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