add getting of some root properties
[dana/openbox.git] / cwmcc / client_props.c
1 #include "cwmcc_internal.h"
2 #include "atom.h"
3 #include "prop.h"
4 #include "client_props.h"
5 #include "render/render.h"
6
7 #include <X11/Xutil.h>
8 #ifdef HAVE_STRING_H
9 #  include <string.h>
10 #endif
11
12 void cwmcc_client_get_protocols(Window win, Atom **protocols)
13 {
14     gulong num;
15
16     if (!prop_get_array32(win, CWMCC_ATOM(client, wm_protocols),
17                           CWMCC_ATOM(type, atom), protocols, &num)) {
18         g_warning("Failed to read WM_PROTOCOLS from 0x%lx", win);
19         *protocols = NULL;
20     }
21 }
22
23 void cwmcc_client_set_protocols(Window win, Atom *protocols)
24 {
25     gulong n;
26     Atom *a;
27
28     for (a = protocols, n = 0; *a; ++a, ++n);
29     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, wm_state),
30                     CWMCC_ATOM(type, atom), 32, PropModeReplace,
31                     (guchar*)protocols, n);
32 }
33
34 void cwmcc_client_get_wm_state(Window win, gulong *state)
35 {
36     if (!prop_get32(win, CWMCC_ATOM(client, wm_state),
37                     CWMCC_ATOM(client, wm_state), state)) {
38         g_warning("Failed to read WM_STATE from 0x%lx", win);
39         *state = NormalState;
40     }
41 }
42
43 void cwmcc_client_set_wm_state(Window win, gulong state)
44 {
45     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, wm_state),
46                     CWMCC_ATOM(client, wm_state), 32, PropModeReplace,
47                     (guchar*)&state, 1);
48 }
49
50 void cwmcc_client_get_name(Window win, char **name)
51 {
52     if (!prop_get_string_utf8(win, CWMCC_ATOM(client, net_wm_name), name))
53         if (!prop_get_string_locale(win, CWMCC_ATOM(client, wm_name), name)) {
54             g_warning("Failed to read a name from 0x%lx", win);
55             *name = g_strdup("Unnamed Window");
56         }
57 }
58
59 void cwmcc_client_set_name(Window win, char *name)
60 {
61     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, net_wm_name),
62                     CWMCC_ATOM(type, utf8), 32, PropModeReplace,
63                     (guchar*)name, strlen(name));
64 }
65
66 void cwmcc_client_get_icon_name(Window win, char **name)
67 {
68     if (!prop_get_string_utf8(win, CWMCC_ATOM(client, net_wm_icon_name), name))
69         if (!prop_get_string_locale(win,
70                                     CWMCC_ATOM(client, wm_icon_name), name)) {
71             g_warning("Failed to read an icon name from 0x%lx", win);
72             *name = g_strdup("Unnamed Window");
73         }
74 }
75
76 void cwmcc_client_set_icon_name(Window win, char *name)
77 {
78     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, net_wm_icon_name),
79                     CWMCC_ATOM(type, utf8), 32, PropModeReplace,
80                     (guchar*)name, strlen(name));
81 }
82
83 void cwmcc_client_get_class(Window win, char **class, char **name)
84 {
85     char **s;
86
87     if (!prop_get_strings_locale(win, CWMCC_ATOM(client, wm_class), &s)) {
88         g_warning("Failed to read WM_CLASS from 0x%lx", win);
89         *class = g_strdup("");
90         *name = g_strdup("");
91     } else {
92         if (!s[0]) {
93             g_warning("Failed to read class element of WM_CLASS from 0x%lx",
94                       win);
95             *class = g_strdup("");
96         } else
97             *class = g_strdup(s[0]);
98         if (!s[0] || !s[1]) {
99             g_warning("Failed to read name element of WM_CLASS from 0x%lx",
100                       win);
101             *name = g_strdup("");
102         } else
103             *name = g_strdup(s[1]);
104     }
105     g_strfreev(s);
106 }
107
108 void cwmcc_client_get_role(Window win, char **role)
109 {
110     if (!prop_get_string_locale(win,
111                                 CWMCC_ATOM(client, wm_window_role), role)) {
112         g_warning("Failed to read WM_WINDOW_ROLE from 0x%lx", win);
113         *role = g_strdup("");
114     }
115 }
116
117 void cwmcc_client_get_mwmhints(Window win, struct Cwmcc_MwmHints *hints)
118 {
119     gulong *l = NULL, num;
120
121     if (!prop_get_array32(win, CWMCC_ATOM(client, motif_wm_hints),
122                           CWMCC_ATOM(client, motif_wm_hints), &l, &num)) {
123         g_warning("Failed to read Motif WM Hints from 0x%lx", win);
124         hints->flags = 0;
125     } else if (num < 3) {
126         g_warning("Read incomplete Motif WM Hints from 0x%lx", win);
127         hints->flags = 0;
128     } else {
129         hints->flags = l[0];
130         hints->functions = l[1];
131         hints->decorations = l[2];
132     }
133     g_free(l);
134 }
135
136 void cwmcc_client_get_desktop(Window win, gulong *desk)
137 {
138     if (!prop_get32(win, CWMCC_ATOM(client, net_wm_desktop),
139                     CWMCC_ATOM(type, cardinal), desk)) {
140         g_warning("Failed to read NET_WM_DESKTOP from 0x%lx", win);
141         *desk = 0;
142     }
143 }
144
145 void cwmcc_client_set_desktop(Window win, gulong desk)
146 {
147     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, net_wm_desktop),
148                     CWMCC_ATOM(type, cardinal), 32, PropModeReplace,
149                     (guchar*)&desk, 1);
150 }
151
152 void cwmcc_client_get_type(Window win, gulong **types)
153 {
154     gulong num;
155
156     if (!prop_get_array32(win, CWMCC_ATOM(client, net_wm_window_type),
157                     CWMCC_ATOM(type, atom), types, &num)) {
158         g_warning("Failed to read NET_WM_WINDOW_TYPE from 0x%lx", win);
159         *types = g_new(Atom, 2);
160         (*types)[0] = CWMCC_ATOM(data, net_wm_window_type_normal);
161         (*types)[1] = 0;
162     }
163 }
164
165 void cwmcc_client_set_type(Window win, gulong *types)
166 {
167     gulong n;
168     gulong *t;
169
170     for (t = types, n = 0; *t; ++t, ++n);
171     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, wm_state),
172                     CWMCC_ATOM(type, atom), 32, PropModeReplace,
173                     (guchar*)types, n);
174 }
175
176 void cwmcc_client_get_state(Window win, gulong **states)
177 {
178     gulong num;
179
180     if (!prop_get_array32(win, CWMCC_ATOM(client, net_wm_state),
181                     CWMCC_ATOM(type, atom), states, &num)) {
182         g_warning("Failed to read NET_WM_STATE from 0x%lx", win);
183         *states = g_new(Atom, 1);
184         (*states)[0] = 0;
185     }
186 }
187
188 void cwmcc_client_set_state(Window win, gulong *states)
189 {
190     gulong n;
191     gulong *s;
192
193     for (s = states, n = 0; *s; ++s, ++n);
194     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, wm_state),
195                     CWMCC_ATOM(type, atom), 32, PropModeReplace,
196                     (guchar*)states, n);
197 }
198
199 void cwmcc_client_get_strut(Window win, int *l, int *t, int *r, int *b)
200 {
201     gulong *data = NULL, num;
202
203     if (!prop_get_array32(win, CWMCC_ATOM(client, net_wm_strut),
204                     CWMCC_ATOM(type, cardinal), &data, &num)) {
205         g_warning("Failed to read NET_WM_STRUT from 0x%lx", win);
206         *l = *t = *r = *b = 0;
207     } else if (num != 4) {
208         g_warning("Read invalid NET_WM_STRUT from 0x%lx", win);
209         *l = *t = *r = *b = 0;
210     } else {
211         *l = data[0];
212         *r = data[1];
213         *t = data[2];
214         *b = data[3];
215     }
216     g_free(data);
217 }
218
219 static void convert_pixmap_to_icon(Pixmap pix, Pixmap mask,
220                                    struct Cwmcc_Icon *icon)
221 {
222 /*
223     guint pw, ph, mw, mh, depth;
224     Window wjunk;
225     int ijunk;
226     guint uijunk;
227     guint x, y;
228
229     if (!XGetGeometry(cwmcc_display, pix, &wjunk, &ijunk, &ijunk, &pw, &ph,
230                       &uijunk, &depth)) {
231         g_message("Unable to read pixmap icon's geometry");
232         icon->width = icon->height = 0;
233         icon->data = NULL;
234         return;
235     }
236     if (!XGetGeometry(cwmcc_display, mask, &wjunk, &ijunk, &ijunk, &mw, &mh,
237                       &uijunk, &ujunk)) {
238         g_message("Unable to read pixmap icon's mask's geometry");
239         icon->width = icon->height = 0;
240         icon->data = NULL;
241         return;
242     }
243     if (pw != mw || ph !_ mh) {
244         g_warning("Pixmap icon's mask does not match icon's dimensions");
245         icon->width = icon->height = 0;
246         icon->data = NULL;
247         return;
248     }
249
250     for (y = 0; y < ph; ++y)
251         for (x = 0; x < pw; ++x) {
252         }
253 */
254     icon->width = icon->height = 0;
255     icon->data = NULL;
256 }
257
258 void cwmcc_client_get_icon(Window win, struct Cwmcc_Icon **icons)
259 {
260     gulong *data = NULL, num;
261     gulong w, h, i;
262     int j;
263     int nicons;
264
265     if (!prop_get_array32(win, CWMCC_ATOM(client, net_wm_icon),
266                           CWMCC_ATOM(type, cardinal), &data, &num)) {
267         g_warning("Failed to read NET_WM_ICON from 0x%lx", win);
268         *icons = NULL;
269         nicons = 0;
270     } else { 
271         /* figure out how many valid icons are in here */
272         i = 0;
273         nicons = 0;
274         while (num - i > 2) {
275             w = data[i++];
276             h = data[i++];
277             i += w * h;
278             if (i > num) break;
279             ++nicons;
280         }
281
282         *icons = g_new(struct Cwmcc_Icon, nicons + 1);
283         (*icons)[nicons].data = NULL;
284     
285         /* store the icons */
286         i = 0;
287         for (j = 0; j < nicons; ++j) {
288             w = (*icons)[j].width = data[i++];
289             h = (*icons)[j].height = data[i++];
290             (*icons)[j].data =
291                 g_memdup(&data[i], w * h * sizeof(gulong));
292             i += w * h;
293             g_assert(i <= num);
294         }
295     }
296     g_free(data);
297
298     data = NULL;
299     if (!prop_get_array32(win, CWMCC_ATOM(client, kwm_win_icon),
300                           CWMCC_ATOM(client, kwm_win_icon), &data, &num)) {
301         g_warning("Failed to read KWM_WIN_ICON from 0x%lx", win);
302     } else if (num != 2) {
303         g_warning("Read invalid KWM_WIN_ICON from 0x%lx", win);
304     } else {
305         Pixmap p, m;
306         struct Cwmcc_Icon icon;
307
308         p = data[0];
309         m = data[1];
310
311         convert_pixmap_to_icon(p, m, &icon);
312
313         if (icon.data) {
314             *icons = g_renew(struct Cwmcc_Icon, *icons, nicons + 2);
315             (*icons[nicons + 1]).data = NULL;
316             g_memmove(&(*icons)[nicons], &icon, sizeof(struct Cwmcc_Icon));
317         }
318     }
319     g_free(data);
320
321 }
322
323 void cwmcc_client_get_premax(Window win, int *x, int *y, int *w, int *h)
324 {
325     gulong *l = NULL, num;
326
327     if (!prop_get_array32(win, CWMCC_ATOM(client, openbox_premax),
328                     CWMCC_ATOM(type, cardinal), &l, &num)) {
329         g_warning("Failed to read OPENBOX_PREMAX from 0x%lx", win);
330         *x = *y = *w = *h = 0;
331     } else if (num != 4) {
332         g_warning("Read invalid OPENBOX_PREMAX from 0x%lx", win);
333         *x = *y = *w = *h = 0;
334     } else {
335         *x = l[0];
336         *y = l[1];
337         *w = l[2];
338         *h = l[3];
339     }
340     g_free(l);
341 }
342
343 void cwmcc_client_set_premax(Window win, int x, int y, int w, int h)
344 {
345     gulong l[4];
346
347     l[0] = x;
348     l[1] = y;
349     l[2] = w;
350     l[3] = h;
351     XChangeProperty(cwmcc_display, win, CWMCC_ATOM(client, openbox_premax),
352                     CWMCC_ATOM(type, cardinal), 32, PropModeReplace,
353                     (guchar*)l, 4);
354 }