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