icccm.c revision ecce36be
1ecce36beSmrg/*
2ecce36beSmrg * Copyright © 2008 Arnaud Fontaine <arnau@debian.org>
3ecce36beSmrg * Copyright © 2007-2008 Vincent Torri <vtorri@univ-evry.fr>
4ecce36beSmrg *
5ecce36beSmrg * Permission is hereby granted, free of charge, to any person
6ecce36beSmrg * obtaining a copy of this software and associated documentation
7ecce36beSmrg * files (the "Software"), to deal in the Software without
8ecce36beSmrg * restriction, including without limitation the rights to use, copy,
9ecce36beSmrg * modify, merge, publish, distribute, sublicense, and/or sell copies
10ecce36beSmrg * of the Software, and to permit persons to whom the Software is
11ecce36beSmrg * furnished to do so, subject to the following conditions:
12ecce36beSmrg *
13ecce36beSmrg * The above copyright notice and this permission notice shall be
14ecce36beSmrg * included in all copies or substantial portions of the Software.
15ecce36beSmrg *
16ecce36beSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17ecce36beSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18ecce36beSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19ecce36beSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
20ecce36beSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21ecce36beSmrg * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22ecce36beSmrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23ecce36beSmrg *
24ecce36beSmrg * Except as contained in this notice, the names of the authors or
25ecce36beSmrg * their institutions shall not be used in advertising or otherwise to
26ecce36beSmrg * promote the sale, use or other dealings in this Software without
27ecce36beSmrg * prior written authorization from the authors.
28ecce36beSmrg */
29ecce36beSmrg
30ecce36beSmrg#include <stdlib.h>
31ecce36beSmrg#include <limits.h>
32ecce36beSmrg#include <string.h>
33ecce36beSmrg
34ecce36beSmrg#include "xcb_icccm.h"
35ecce36beSmrg#include "xcb_atom.h"
36ecce36beSmrg
37ecce36beSmrgxcb_get_property_cookie_t
38ecce36beSmrgxcb_get_text_property(xcb_connection_t *c,
39ecce36beSmrg                      xcb_window_t window,
40ecce36beSmrg                      xcb_atom_t property)
41ecce36beSmrg{
42ecce36beSmrg  return xcb_get_any_property(c, 0, window, property, UINT_MAX);
43ecce36beSmrg}
44ecce36beSmrg
45ecce36beSmrgxcb_get_property_cookie_t
46ecce36beSmrgxcb_get_text_property_unchecked(xcb_connection_t *c,
47ecce36beSmrg                                xcb_window_t window,
48ecce36beSmrg                                xcb_atom_t property)
49ecce36beSmrg{
50ecce36beSmrg  return xcb_get_any_property_unchecked(c, 0, window, property, UINT_MAX);
51ecce36beSmrg}
52ecce36beSmrg
53ecce36beSmrguint8_t
54ecce36beSmrgxcb_get_text_property_reply(xcb_connection_t *c,
55ecce36beSmrg                            xcb_get_property_cookie_t cookie,
56ecce36beSmrg                            xcb_get_text_property_reply_t *prop,
57ecce36beSmrg                            xcb_generic_error_t **e)
58ecce36beSmrg{
59ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
60ecce36beSmrg
61ecce36beSmrg  if(!reply)
62ecce36beSmrg    return 0;
63ecce36beSmrg
64ecce36beSmrg  prop->_reply = reply;
65ecce36beSmrg  prop->encoding = prop->_reply->type;
66ecce36beSmrg  prop->format = prop->_reply->format;
67ecce36beSmrg  prop->name_len = xcb_get_property_value_length(prop->_reply);
68ecce36beSmrg  prop->name = xcb_get_property_value(prop->_reply);
69ecce36beSmrg
70ecce36beSmrg  return 1;
71ecce36beSmrg}
72ecce36beSmrg
73ecce36beSmrgvoid
74ecce36beSmrgxcb_get_text_property_reply_wipe(xcb_get_text_property_reply_t *prop)
75ecce36beSmrg{
76ecce36beSmrg  free(prop->_reply);
77ecce36beSmrg}
78ecce36beSmrg
79ecce36beSmrg/* WM_NAME */
80ecce36beSmrg
81ecce36beSmrgvoid
82ecce36beSmrgxcb_set_wm_name_checked(xcb_connection_t *c, xcb_window_t window,
83ecce36beSmrg                        xcb_atom_t encoding, uint32_t name_len,
84ecce36beSmrg                        const char *name)
85ecce36beSmrg{
86ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_NAME,
87ecce36beSmrg                              encoding, 8, name_len, name);
88ecce36beSmrg}
89ecce36beSmrg
90ecce36beSmrgvoid
91ecce36beSmrgxcb_set_wm_name(xcb_connection_t *c, xcb_window_t window, xcb_atom_t encoding,
92ecce36beSmrg                uint32_t name_len, const char *name)
93ecce36beSmrg{
94ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_NAME, encoding, 8,
95ecce36beSmrg                      name_len, name);
96ecce36beSmrg}
97ecce36beSmrg
98ecce36beSmrgxcb_get_property_cookie_t
99ecce36beSmrgxcb_get_wm_name(xcb_connection_t *c,
100ecce36beSmrg                xcb_window_t window)
101ecce36beSmrg{
102ecce36beSmrg  return xcb_get_text_property(c, window, WM_NAME);
103ecce36beSmrg}
104ecce36beSmrg
105ecce36beSmrgxcb_get_property_cookie_t
106ecce36beSmrgxcb_get_wm_name_unchecked(xcb_connection_t *c,
107ecce36beSmrg                          xcb_window_t window)
108ecce36beSmrg{
109ecce36beSmrg  return xcb_get_text_property_unchecked(c, window, WM_NAME);
110ecce36beSmrg}
111ecce36beSmrg
112ecce36beSmrguint8_t
113ecce36beSmrgxcb_get_wm_name_reply(xcb_connection_t *c,
114ecce36beSmrg                      xcb_get_property_cookie_t cookie,
115ecce36beSmrg                      xcb_get_text_property_reply_t *prop,
116ecce36beSmrg                      xcb_generic_error_t **e)
117ecce36beSmrg{
118ecce36beSmrg  return xcb_get_text_property_reply(c, cookie, prop, e);
119ecce36beSmrg}
120ecce36beSmrg
121ecce36beSmrgvoid
122ecce36beSmrgxcb_watch_wm_name(xcb_property_handlers_t *prophs, uint32_t long_len,
123ecce36beSmrg                  xcb_generic_property_handler_t handler, void *data)
124ecce36beSmrg{
125ecce36beSmrg  xcb_property_set_handler(prophs, WM_NAME, long_len, handler, data);
126ecce36beSmrg}
127ecce36beSmrg
128ecce36beSmrg/* WM_ICON_NAME */
129ecce36beSmrg
130ecce36beSmrgvoid
131ecce36beSmrgxcb_set_wm_icon_name_checked(xcb_connection_t *c, xcb_window_t window,
132ecce36beSmrg                             xcb_atom_t encoding, uint32_t name_len,
133ecce36beSmrg                             const char *name)
134ecce36beSmrg{
135ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_ICON_NAME,
136ecce36beSmrg                              encoding, 8, name_len, name);
137ecce36beSmrg}
138ecce36beSmrg
139ecce36beSmrgvoid
140ecce36beSmrgxcb_set_wm_icon_name(xcb_connection_t *c, xcb_window_t window,
141ecce36beSmrg                     xcb_atom_t encoding, uint32_t name_len, const char *name)
142ecce36beSmrg{
143ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_ICON_NAME, encoding,
144ecce36beSmrg                      8, name_len, name);
145ecce36beSmrg}
146ecce36beSmrg
147ecce36beSmrgxcb_get_property_cookie_t
148ecce36beSmrgxcb_get_wm_icon_name(xcb_connection_t *c,
149ecce36beSmrg                     xcb_window_t window)
150ecce36beSmrg{
151ecce36beSmrg  return xcb_get_text_property(c, window, WM_ICON_NAME);
152ecce36beSmrg}
153ecce36beSmrg
154ecce36beSmrgxcb_get_property_cookie_t
155ecce36beSmrgxcb_get_wm_icon_name_unchecked(xcb_connection_t *c,
156ecce36beSmrg                               xcb_window_t window)
157ecce36beSmrg{
158ecce36beSmrg  return xcb_get_text_property_unchecked(c, window, WM_ICON_NAME);
159ecce36beSmrg}
160ecce36beSmrg
161ecce36beSmrguint8_t
162ecce36beSmrgxcb_get_wm_icon_name_reply(xcb_connection_t *c,
163ecce36beSmrg                           xcb_get_property_cookie_t cookie,
164ecce36beSmrg                           xcb_get_text_property_reply_t *prop,
165ecce36beSmrg                           xcb_generic_error_t **e)
166ecce36beSmrg{
167ecce36beSmrg  return xcb_get_text_property_reply(c, cookie, prop, e);
168ecce36beSmrg}
169ecce36beSmrg
170ecce36beSmrgvoid
171ecce36beSmrgxcb_watch_wm_icon_name(xcb_property_handlers_t *prophs, uint32_t long_len,
172ecce36beSmrg                       xcb_generic_property_handler_t handler, void *data)
173ecce36beSmrg{
174ecce36beSmrg  xcb_property_set_handler(prophs, WM_ICON_NAME, long_len, handler, data);
175ecce36beSmrg}
176ecce36beSmrg
177ecce36beSmrg/* WM_CLIENT_MACHINE */
178ecce36beSmrg
179ecce36beSmrgvoid
180ecce36beSmrgxcb_set_wm_client_machine_checked(xcb_connection_t *c, xcb_window_t window,
181ecce36beSmrg                                  xcb_atom_t encoding, uint32_t name_len,
182ecce36beSmrg                                  const char *name)
183ecce36beSmrg{
184ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window,
185ecce36beSmrg                              WM_CLIENT_MACHINE, encoding, 8, name_len, name);
186ecce36beSmrg}
187ecce36beSmrg
188ecce36beSmrgvoid
189ecce36beSmrgxcb_set_wm_client_machine(xcb_connection_t *c, xcb_window_t window,
190ecce36beSmrg                          xcb_atom_t encoding, uint32_t name_len,
191ecce36beSmrg                          const char *name)
192ecce36beSmrg{
193ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_CLIENT_MACHINE,
194ecce36beSmrg                      encoding, 8, name_len, name);
195ecce36beSmrg}
196ecce36beSmrg
197ecce36beSmrgxcb_get_property_cookie_t
198ecce36beSmrgxcb_get_wm_client_machine(xcb_connection_t *c,
199ecce36beSmrg                          xcb_window_t window)
200ecce36beSmrg{
201ecce36beSmrg  return xcb_get_text_property(c, window, WM_CLIENT_MACHINE);
202ecce36beSmrg}
203ecce36beSmrg
204ecce36beSmrgxcb_get_property_cookie_t
205ecce36beSmrgxcb_get_wm_client_machine_unchecked(xcb_connection_t *c,
206ecce36beSmrg                                    xcb_window_t window)
207ecce36beSmrg{
208ecce36beSmrg  return xcb_get_text_property_unchecked(c, window, WM_CLIENT_MACHINE);
209ecce36beSmrg}
210ecce36beSmrg
211ecce36beSmrguint8_t
212ecce36beSmrgxcb_get_wm_client_machine_reply(xcb_connection_t *c,
213ecce36beSmrg                                xcb_get_property_cookie_t cookie,
214ecce36beSmrg                                xcb_get_text_property_reply_t *prop,
215ecce36beSmrg                                xcb_generic_error_t **e)
216ecce36beSmrg{
217ecce36beSmrg  return xcb_get_text_property_reply(c, cookie, prop, e);
218ecce36beSmrg}
219ecce36beSmrg
220ecce36beSmrgvoid
221ecce36beSmrgxcb_watch_wm_client_machine(xcb_property_handlers_t *prophs, uint32_t long_len,
222ecce36beSmrg                            xcb_generic_property_handler_t handler, void *data)
223ecce36beSmrg{
224ecce36beSmrg  xcb_property_set_handler(prophs, WM_CLIENT_MACHINE, long_len, handler, data);
225ecce36beSmrg}
226ecce36beSmrg
227ecce36beSmrg/* WM_CLASS */
228ecce36beSmrg
229ecce36beSmrgxcb_get_property_cookie_t
230ecce36beSmrgxcb_get_wm_class(xcb_connection_t *c, xcb_window_t window)
231ecce36beSmrg{
232ecce36beSmrg  return xcb_get_property(c, 0, window, WM_CLASS, STRING, 0L, 2048L);
233ecce36beSmrg}
234ecce36beSmrg
235ecce36beSmrgxcb_get_property_cookie_t
236ecce36beSmrgxcb_get_wm_class_unchecked(xcb_connection_t *c, xcb_window_t window)
237ecce36beSmrg{
238ecce36beSmrg  return xcb_get_property_unchecked(c, 0, window, WM_CLASS, STRING, 0L, 2048L);
239ecce36beSmrg}
240ecce36beSmrg
241ecce36beSmrguint8_t
242ecce36beSmrgxcb_get_wm_class_from_reply(xcb_get_wm_class_reply_t *prop,
243ecce36beSmrg                            xcb_get_property_reply_t *reply)
244ecce36beSmrg{
245ecce36beSmrg  if(!reply || reply->type != STRING || reply->format != 8)
246ecce36beSmrg    return 0;
247ecce36beSmrg
248ecce36beSmrg  prop->_reply = reply;
249ecce36beSmrg  prop->instance_name = (char *) xcb_get_property_value(prop->_reply);
250ecce36beSmrg
251ecce36beSmrg  int name_len = strlen(prop->instance_name);
252ecce36beSmrg  if(name_len == xcb_get_property_value_length(prop->_reply))
253ecce36beSmrg    name_len--;
254ecce36beSmrg
255ecce36beSmrg  prop->class_name = prop->instance_name + name_len + 1;
256ecce36beSmrg
257ecce36beSmrg  return 1;
258ecce36beSmrg}
259ecce36beSmrg
260ecce36beSmrguint8_t
261ecce36beSmrgxcb_get_wm_class_reply(xcb_connection_t *c, xcb_get_property_cookie_t cookie,
262ecce36beSmrg                       xcb_get_wm_class_reply_t *prop, xcb_generic_error_t **e)
263ecce36beSmrg{
264ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
265ecce36beSmrg  uint8_t ret = xcb_get_wm_class_from_reply(prop, reply);
266ecce36beSmrg  /* if reply parsing failed, free the reply to avoid mem leak */
267ecce36beSmrg  if(!ret)
268ecce36beSmrg      free(reply);
269ecce36beSmrg  return ret;
270ecce36beSmrg}
271ecce36beSmrg
272ecce36beSmrgvoid
273ecce36beSmrgxcb_get_wm_class_reply_wipe(xcb_get_wm_class_reply_t *prop)
274ecce36beSmrg{
275ecce36beSmrg  free(prop->_reply);
276ecce36beSmrg}
277ecce36beSmrg
278ecce36beSmrg/* WM_TRANSIENT_FOR */
279ecce36beSmrg
280ecce36beSmrgxcb_get_property_cookie_t
281ecce36beSmrgxcb_get_wm_transient_for(xcb_connection_t *c, xcb_window_t window)
282ecce36beSmrg{
283ecce36beSmrg  return xcb_get_property(c, 0, window, WM_TRANSIENT_FOR, WINDOW, 0, 1);
284ecce36beSmrg}
285ecce36beSmrg
286ecce36beSmrgxcb_get_property_cookie_t
287ecce36beSmrgxcb_get_wm_transient_for_unchecked(xcb_connection_t *c, xcb_window_t window)
288ecce36beSmrg{
289ecce36beSmrg  return xcb_get_property_unchecked(c, 0, window, WM_TRANSIENT_FOR, WINDOW, 0, 1);
290ecce36beSmrg}
291ecce36beSmrg
292ecce36beSmrguint8_t
293ecce36beSmrgxcb_get_wm_transient_for_from_reply(xcb_window_t *prop,
294ecce36beSmrg                                    xcb_get_property_reply_t *reply)
295ecce36beSmrg{
296ecce36beSmrg  if(!reply || reply->type != WINDOW || reply->format != 32 || !reply->length)
297ecce36beSmrg    return 0;
298ecce36beSmrg
299ecce36beSmrg  *prop = *((xcb_window_t *) xcb_get_property_value(reply));
300ecce36beSmrg
301ecce36beSmrg  return 1;
302ecce36beSmrg}
303ecce36beSmrg
304ecce36beSmrguint8_t
305ecce36beSmrgxcb_get_wm_transient_for_reply(xcb_connection_t *c,
306ecce36beSmrg                               xcb_get_property_cookie_t cookie,
307ecce36beSmrg                               xcb_window_t *prop,
308ecce36beSmrg                               xcb_generic_error_t **e)
309ecce36beSmrg{
310ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
311ecce36beSmrg  uint8_t ret = xcb_get_wm_transient_for_from_reply(prop, reply);
312ecce36beSmrg  free(reply);
313ecce36beSmrg  return ret;
314ecce36beSmrg}
315ecce36beSmrg
316ecce36beSmrg/* WM_SIZE_HINTS */
317ecce36beSmrg
318ecce36beSmrgvoid
319ecce36beSmrgxcb_size_hints_set_position(xcb_size_hints_t *hints, int user_specified,
320ecce36beSmrg                            int32_t x, int32_t y)
321ecce36beSmrg{
322ecce36beSmrg  hints->flags &= ~(XCB_SIZE_HINT_US_POSITION | XCB_SIZE_HINT_P_POSITION);
323ecce36beSmrg  if (user_specified)
324ecce36beSmrg    hints->flags |= XCB_SIZE_HINT_US_POSITION;
325ecce36beSmrg  else
326ecce36beSmrg    hints->flags |= XCB_SIZE_HINT_P_POSITION;
327ecce36beSmrg  hints->x = x;
328ecce36beSmrg  hints->y = y;
329ecce36beSmrg}
330ecce36beSmrg
331ecce36beSmrgvoid
332ecce36beSmrgxcb_size_hints_set_size(xcb_size_hints_t *hints, int user_specified,
333ecce36beSmrg                         int32_t width, int32_t height)
334ecce36beSmrg{
335ecce36beSmrg  hints->flags &= ~(XCB_SIZE_HINT_US_SIZE | XCB_SIZE_HINT_P_SIZE);
336ecce36beSmrg  if (user_specified)
337ecce36beSmrg    hints->flags |= XCB_SIZE_HINT_US_SIZE;
338ecce36beSmrg  else
339ecce36beSmrg    hints->flags |= XCB_SIZE_HINT_P_SIZE;
340ecce36beSmrg  hints->width = width;
341ecce36beSmrg  hints->height = height;
342ecce36beSmrg}
343ecce36beSmrg
344ecce36beSmrgvoid
345ecce36beSmrgxcb_size_hints_set_min_size(xcb_size_hints_t *hints, int32_t min_width,
346ecce36beSmrg                            int32_t min_height)
347ecce36beSmrg{
348ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_P_MIN_SIZE;
349ecce36beSmrg  hints->min_width = min_width;
350ecce36beSmrg  hints->min_height = min_height;
351ecce36beSmrg}
352ecce36beSmrg
353ecce36beSmrgvoid
354ecce36beSmrgxcb_size_hints_set_max_size(xcb_size_hints_t *hints, int32_t max_width,
355ecce36beSmrg                            int32_t max_height)
356ecce36beSmrg{
357ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_P_MAX_SIZE;
358ecce36beSmrg  hints->max_width = max_width;
359ecce36beSmrg  hints->max_height = max_height;
360ecce36beSmrg}
361ecce36beSmrg
362ecce36beSmrgvoid
363ecce36beSmrgxcb_size_hints_set_resize_inc(xcb_size_hints_t *hints, int32_t width_inc,
364ecce36beSmrg                              int32_t height_inc)
365ecce36beSmrg{
366ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_P_RESIZE_INC;
367ecce36beSmrg  hints->width_inc = width_inc;
368ecce36beSmrg  hints->height_inc = height_inc;
369ecce36beSmrg}
370ecce36beSmrg
371ecce36beSmrgvoid
372ecce36beSmrgxcb_size_hints_set_aspect(xcb_size_hints_t *hints, int32_t min_aspect_num,
373ecce36beSmrg                          int32_t min_aspect_den, int32_t max_aspect_num,
374ecce36beSmrg                          int32_t max_aspect_den)
375ecce36beSmrg{
376ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_P_ASPECT;
377ecce36beSmrg  hints->min_aspect_num = min_aspect_num;
378ecce36beSmrg  hints->min_aspect_den = min_aspect_den;
379ecce36beSmrg  hints->max_aspect_num = max_aspect_num;
380ecce36beSmrg  hints->max_aspect_den = max_aspect_den;
381ecce36beSmrg}
382ecce36beSmrg
383ecce36beSmrgvoid
384ecce36beSmrgxcb_size_hints_set_base_size(xcb_size_hints_t *hints, int32_t base_width,
385ecce36beSmrg                             int32_t base_height)
386ecce36beSmrg{
387ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_BASE_SIZE;
388ecce36beSmrg  hints->base_width = base_width;
389ecce36beSmrg  hints->base_height = base_height;
390ecce36beSmrg}
391ecce36beSmrg
392ecce36beSmrgvoid
393ecce36beSmrgxcb_size_hints_set_win_gravity(xcb_size_hints_t *hints, xcb_gravity_t win_gravity)
394ecce36beSmrg{
395ecce36beSmrg  hints->flags |= XCB_SIZE_HINT_P_WIN_GRAVITY;
396ecce36beSmrg  hints->win_gravity = win_gravity;
397ecce36beSmrg}
398ecce36beSmrg
399ecce36beSmrgvoid
400ecce36beSmrgxcb_set_wm_size_hints_checked(xcb_connection_t *c, xcb_window_t window,
401ecce36beSmrg                              xcb_atom_t property, xcb_size_hints_t *hints)
402ecce36beSmrg{
403ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, property,
404ecce36beSmrg                              WM_SIZE_HINTS, 32, sizeof(*hints) >> 2, hints);
405ecce36beSmrg}
406ecce36beSmrg
407ecce36beSmrgvoid
408ecce36beSmrgxcb_set_wm_size_hints(xcb_connection_t *c, xcb_window_t window,
409ecce36beSmrg                      xcb_atom_t property, xcb_size_hints_t *hints)
410ecce36beSmrg{
411ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, property,
412ecce36beSmrg                      WM_SIZE_HINTS, 32, sizeof(*hints) >> 2, hints);
413ecce36beSmrg}
414ecce36beSmrg
415ecce36beSmrgxcb_get_property_cookie_t
416ecce36beSmrgxcb_get_wm_size_hints(xcb_connection_t *c, xcb_window_t window,
417ecce36beSmrg                      xcb_atom_t property)
418ecce36beSmrg{
419ecce36beSmrg  /* NumPropSizeElements = 18 (ICCCM version 1). */
420ecce36beSmrg  return xcb_get_property(c, 0, window, property, WM_SIZE_HINTS, 0L, 18);
421ecce36beSmrg}
422ecce36beSmrg
423ecce36beSmrgxcb_get_property_cookie_t
424ecce36beSmrgxcb_get_wm_size_hints_unchecked(xcb_connection_t *c, xcb_window_t window,
425ecce36beSmrg                                xcb_atom_t property)
426ecce36beSmrg{
427ecce36beSmrg  return xcb_get_property_unchecked(c, 0, window, property, WM_SIZE_HINTS,
428ecce36beSmrg                                    0L, 18);
429ecce36beSmrg}
430ecce36beSmrg
431ecce36beSmrguint8_t
432ecce36beSmrgxcb_get_wm_size_hints_from_reply(xcb_size_hints_t *hints, xcb_get_property_reply_t *reply)
433ecce36beSmrg{
434ecce36beSmrg  uint32_t flags;
435ecce36beSmrg
436ecce36beSmrg  if(!reply)
437ecce36beSmrg    return 0;
438ecce36beSmrg
439ecce36beSmrg  int length = xcb_get_property_value_length(reply) / (reply->format / 8);
440ecce36beSmrg
441ecce36beSmrg  if (!(reply->type == WM_SIZE_HINTS &&
442ecce36beSmrg        (reply->format == 8  || reply->format == 16 ||
443ecce36beSmrg         reply->format == 32) &&
444ecce36beSmrg        /* OldNumPropSizeElements = 15 (pre-ICCCM) */
445ecce36beSmrg        length >= 15))
446ecce36beSmrg    return 0;
447ecce36beSmrg
448ecce36beSmrg  memcpy(hints, (xcb_size_hints_t *) xcb_get_property_value (reply),
449ecce36beSmrg         length * reply->format >> 3);
450ecce36beSmrg
451ecce36beSmrg  flags = (XCB_SIZE_HINT_US_POSITION | XCB_SIZE_HINT_US_SIZE |
452ecce36beSmrg           XCB_SIZE_HINT_P_POSITION | XCB_SIZE_HINT_P_SIZE |
453ecce36beSmrg           XCB_SIZE_HINT_P_MIN_SIZE | XCB_SIZE_HINT_P_MAX_SIZE |
454ecce36beSmrg           XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_P_ASPECT);
455ecce36beSmrg
456ecce36beSmrg  /* NumPropSizeElements = 18 (ICCCM version 1) */
457ecce36beSmrg  if(length >= 18)
458ecce36beSmrg    flags |= (XCB_SIZE_HINT_BASE_SIZE | XCB_SIZE_HINT_P_WIN_GRAVITY);
459ecce36beSmrg  else
460ecce36beSmrg  {
461ecce36beSmrg    hints->base_width = 0;
462ecce36beSmrg    hints->base_height = 0;
463ecce36beSmrg    hints->win_gravity = 0;
464ecce36beSmrg  }
465ecce36beSmrg  /* get rid of unwanted bits */
466ecce36beSmrg  hints->flags &= flags;
467ecce36beSmrg
468ecce36beSmrg  return 1;
469ecce36beSmrg}
470ecce36beSmrg
471ecce36beSmrguint8_t
472ecce36beSmrgxcb_get_wm_size_hints_reply(xcb_connection_t *c, xcb_get_property_cookie_t cookie,
473ecce36beSmrg                            xcb_size_hints_t *hints, xcb_generic_error_t **e)
474ecce36beSmrg{
475ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
476ecce36beSmrg  uint8_t ret = xcb_get_wm_size_hints_from_reply(hints, reply);
477ecce36beSmrg  free(reply);
478ecce36beSmrg  return ret;
479ecce36beSmrg}
480ecce36beSmrg
481ecce36beSmrg/* WM_NORMAL_HINTS */
482ecce36beSmrg
483ecce36beSmrgvoid
484ecce36beSmrgxcb_set_wm_normal_hints_checked(xcb_connection_t *c, xcb_window_t window,
485ecce36beSmrg                                xcb_size_hints_t *hints)
486ecce36beSmrg{
487ecce36beSmrg  xcb_set_wm_size_hints_checked(c, window, WM_NORMAL_HINTS, hints);
488ecce36beSmrg}
489ecce36beSmrg
490ecce36beSmrgvoid
491ecce36beSmrgxcb_set_wm_normal_hints(xcb_connection_t *c, xcb_window_t window,
492ecce36beSmrg                        xcb_size_hints_t *hints)
493ecce36beSmrg{
494ecce36beSmrg  xcb_set_wm_size_hints(c, window, WM_NORMAL_HINTS, hints);
495ecce36beSmrg}
496ecce36beSmrg
497ecce36beSmrgxcb_get_property_cookie_t
498ecce36beSmrgxcb_get_wm_normal_hints(xcb_connection_t *c, xcb_window_t window)
499ecce36beSmrg{
500ecce36beSmrg  return xcb_get_wm_size_hints(c, window, WM_NORMAL_HINTS);
501ecce36beSmrg}
502ecce36beSmrg
503ecce36beSmrgxcb_get_property_cookie_t
504ecce36beSmrgxcb_get_wm_normal_hints_unchecked(xcb_connection_t *c, xcb_window_t window)
505ecce36beSmrg{
506ecce36beSmrg  return xcb_get_wm_size_hints_unchecked(c, window, WM_NORMAL_HINTS);
507ecce36beSmrg}
508ecce36beSmrg
509ecce36beSmrguint8_t
510ecce36beSmrgxcb_get_wm_normal_hints_reply(xcb_connection_t *c,
511ecce36beSmrg                              xcb_get_property_cookie_t cookie,
512ecce36beSmrg                              xcb_size_hints_t *hints,
513ecce36beSmrg                              xcb_generic_error_t **e)
514ecce36beSmrg{
515ecce36beSmrg  return xcb_get_wm_size_hints_reply(c, cookie, hints, e);
516ecce36beSmrg}
517ecce36beSmrg
518ecce36beSmrg/* WM_HINTS */
519ecce36beSmrg
520ecce36beSmrguint32_t
521ecce36beSmrgxcb_wm_hints_get_urgency(xcb_wm_hints_t *hints)
522ecce36beSmrg{
523ecce36beSmrg  return (hints->flags & XCB_WM_HINT_X_URGENCY);
524ecce36beSmrg}
525ecce36beSmrg
526ecce36beSmrgvoid
527ecce36beSmrgxcb_wm_hints_set_input(xcb_wm_hints_t *hints, uint8_t input)
528ecce36beSmrg{
529ecce36beSmrg  hints->input = input;
530ecce36beSmrg  hints->flags |= XCB_WM_HINT_INPUT;
531ecce36beSmrg}
532ecce36beSmrg
533ecce36beSmrgvoid
534ecce36beSmrgxcb_wm_hints_set_iconic(xcb_wm_hints_t *hints)
535ecce36beSmrg{
536ecce36beSmrg  hints->initial_state = XCB_WM_STATE_ICONIC;
537ecce36beSmrg  hints->flags |= XCB_WM_HINT_STATE;
538ecce36beSmrg}
539ecce36beSmrg
540ecce36beSmrgvoid
541ecce36beSmrgxcb_wm_hints_set_normal(xcb_wm_hints_t *hints)
542ecce36beSmrg{
543ecce36beSmrg  hints->initial_state = XCB_WM_STATE_NORMAL;
544ecce36beSmrg  hints->flags |= XCB_WM_HINT_STATE;
545ecce36beSmrg}
546ecce36beSmrg
547ecce36beSmrgvoid
548ecce36beSmrgxcb_wm_hints_set_withdrawn(xcb_wm_hints_t *hints)
549ecce36beSmrg{
550ecce36beSmrg  hints->initial_state = XCB_WM_STATE_WITHDRAWN;
551ecce36beSmrg  hints->flags |= XCB_WM_HINT_STATE;
552ecce36beSmrg}
553ecce36beSmrg
554ecce36beSmrgvoid
555ecce36beSmrgxcb_wm_hints_set_none(xcb_wm_hints_t *hints)
556ecce36beSmrg{
557ecce36beSmrg  hints->flags &= ~XCB_WM_HINT_STATE;
558ecce36beSmrg}
559ecce36beSmrg
560ecce36beSmrgvoid
561ecce36beSmrgxcb_wm_hints_set_icon_pixmap(xcb_wm_hints_t *hints, xcb_pixmap_t icon_pixmap)
562ecce36beSmrg{
563ecce36beSmrg  hints->icon_pixmap = icon_pixmap;
564ecce36beSmrg  hints->flags |= XCB_WM_HINT_ICON_PIXMAP;
565ecce36beSmrg}
566ecce36beSmrg
567ecce36beSmrgvoid
568ecce36beSmrgxcb_wm_hints_set_icon_mask(xcb_wm_hints_t *hints, xcb_pixmap_t icon_mask)
569ecce36beSmrg{
570ecce36beSmrg  hints->icon_mask = icon_mask;
571ecce36beSmrg  hints->flags |= XCB_WM_HINT_ICON_MASK;
572ecce36beSmrg}
573ecce36beSmrg
574ecce36beSmrgvoid
575ecce36beSmrgxcb_wm_hints_set_icon_window(xcb_wm_hints_t *hints, xcb_window_t icon_window)
576ecce36beSmrg{
577ecce36beSmrg  hints->icon_window = icon_window;
578ecce36beSmrg  hints->flags |= XCB_WM_HINT_ICON_WINDOW;
579ecce36beSmrg}
580ecce36beSmrg
581ecce36beSmrgvoid
582ecce36beSmrgxcb_wm_hints_set_window_group(xcb_wm_hints_t *hints, xcb_window_t window_group)
583ecce36beSmrg{
584ecce36beSmrg  hints->window_group = window_group;
585ecce36beSmrg  hints->flags |= XCB_WM_HINT_WINDOW_GROUP;
586ecce36beSmrg}
587ecce36beSmrg
588ecce36beSmrgvoid
589ecce36beSmrgxcb_wm_hints_set_urgency(xcb_wm_hints_t *hints)
590ecce36beSmrg{
591ecce36beSmrg  hints->flags |= XCB_WM_HINT_X_URGENCY;
592ecce36beSmrg}
593ecce36beSmrg
594ecce36beSmrgvoid
595ecce36beSmrgxcb_set_wm_hints_checked(xcb_connection_t *c, xcb_window_t window,
596ecce36beSmrg                         xcb_wm_hints_t *hints)
597ecce36beSmrg{
598ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_HINTS,
599ecce36beSmrg                              WM_HINTS, 32, sizeof(*hints) >> 2, hints);
600ecce36beSmrg}
601ecce36beSmrg
602ecce36beSmrgvoid
603ecce36beSmrgxcb_set_wm_hints(xcb_connection_t *c, xcb_window_t window,
604ecce36beSmrg                 xcb_wm_hints_t *hints)
605ecce36beSmrg{
606ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_HINTS, WM_HINTS, 32,
607ecce36beSmrg                      sizeof(*hints) >> 2, hints);
608ecce36beSmrg}
609ecce36beSmrg
610ecce36beSmrgxcb_get_property_cookie_t
611ecce36beSmrgxcb_get_wm_hints(xcb_connection_t *c,
612ecce36beSmrg                 xcb_window_t window)
613ecce36beSmrg{
614ecce36beSmrg  return xcb_get_property(c, 0, window, WM_HINTS, WM_HINTS, 0L,
615ecce36beSmrg                          XCB_NUM_WM_HINTS_ELEMENTS);
616ecce36beSmrg}
617ecce36beSmrg
618ecce36beSmrgxcb_get_property_cookie_t
619ecce36beSmrgxcb_get_wm_hints_unchecked(xcb_connection_t *c,
620ecce36beSmrg                           xcb_window_t window)
621ecce36beSmrg{
622ecce36beSmrg  return xcb_get_property_unchecked(c, 0, window, WM_HINTS, WM_HINTS, 0L,
623ecce36beSmrg                                    XCB_NUM_WM_HINTS_ELEMENTS);
624ecce36beSmrg}
625ecce36beSmrg
626ecce36beSmrguint8_t
627ecce36beSmrgxcb_get_wm_hints_from_reply(xcb_wm_hints_t *hints,
628ecce36beSmrg                            xcb_get_property_reply_t *reply)
629ecce36beSmrg{
630ecce36beSmrg  if(!reply)
631ecce36beSmrg    return 0;
632ecce36beSmrg
633ecce36beSmrg  int length = xcb_get_property_value_length(reply);
634ecce36beSmrg  int num_elem = length / (reply->format / 8);
635ecce36beSmrg
636ecce36beSmrg  if (reply->type != WM_HINTS
637ecce36beSmrg      || reply->format != 32
638ecce36beSmrg      || num_elem < XCB_NUM_WM_HINTS_ELEMENTS - 1)
639ecce36beSmrg    return 0;
640ecce36beSmrg
641ecce36beSmrg  memcpy(hints, (xcb_size_hints_t *) xcb_get_property_value(reply), length);
642ecce36beSmrg
643ecce36beSmrg  if(num_elem < XCB_NUM_WM_HINTS_ELEMENTS)
644ecce36beSmrg    hints->window_group = XCB_NONE;
645ecce36beSmrg
646ecce36beSmrg  return 1;
647ecce36beSmrg}
648ecce36beSmrg
649ecce36beSmrguint8_t
650ecce36beSmrgxcb_get_wm_hints_reply(xcb_connection_t *c,
651ecce36beSmrg                       xcb_get_property_cookie_t cookie,
652ecce36beSmrg                       xcb_wm_hints_t *hints,
653ecce36beSmrg                       xcb_generic_error_t **e)
654ecce36beSmrg{
655ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
656ecce36beSmrg  int ret = xcb_get_wm_hints_from_reply(hints, reply);
657ecce36beSmrg  free(reply);
658ecce36beSmrg  return ret;
659ecce36beSmrg}
660ecce36beSmrg
661ecce36beSmrg/* WM_PROTOCOLS */
662ecce36beSmrg
663ecce36beSmrgvoid
664ecce36beSmrgxcb_set_wm_protocols_checked(xcb_connection_t *c, xcb_atom_t wm_protocols,
665ecce36beSmrg                             xcb_window_t window, uint32_t list_len,
666ecce36beSmrg                             xcb_atom_t *list)
667ecce36beSmrg{
668ecce36beSmrg  xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, wm_protocols,
669ecce36beSmrg                              ATOM, 32, list_len, list);
670ecce36beSmrg}
671ecce36beSmrg
672ecce36beSmrgvoid
673ecce36beSmrgxcb_set_wm_protocols(xcb_connection_t *c, xcb_atom_t wm_protocols,
674ecce36beSmrg                     xcb_window_t window, uint32_t list_len, xcb_atom_t *list)
675ecce36beSmrg{
676ecce36beSmrg  xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, wm_protocols, ATOM, 32,
677ecce36beSmrg                      list_len, list);
678ecce36beSmrg}
679ecce36beSmrg
680ecce36beSmrgxcb_get_property_cookie_t
681ecce36beSmrgxcb_get_wm_protocols(xcb_connection_t *c, xcb_window_t window,
682ecce36beSmrg                     xcb_atom_t wm_protocol_atom)
683ecce36beSmrg{
684ecce36beSmrg  return xcb_get_property(c, 0, window, wm_protocol_atom, ATOM, 0, UINT_MAX);
685ecce36beSmrg}
686ecce36beSmrg
687ecce36beSmrgxcb_get_property_cookie_t
688ecce36beSmrgxcb_get_wm_protocols_unchecked(xcb_connection_t *c,
689ecce36beSmrg                               xcb_window_t window,
690ecce36beSmrg                               xcb_atom_t wm_protocol_atom)
691ecce36beSmrg{
692ecce36beSmrg  return xcb_get_property_unchecked(c, 0, window, wm_protocol_atom, ATOM, 0,
693ecce36beSmrg                                    UINT_MAX);
694ecce36beSmrg}
695ecce36beSmrg
696ecce36beSmrguint8_t
697ecce36beSmrgxcb_get_wm_protocols_from_reply(xcb_get_property_reply_t *reply, xcb_get_wm_protocols_reply_t *protocols)
698ecce36beSmrg{
699ecce36beSmrg  if(!reply || reply->type != ATOM || reply->format != 32)
700ecce36beSmrg    return 0;
701ecce36beSmrg
702ecce36beSmrg  protocols->_reply = reply;
703ecce36beSmrg  protocols->atoms_len = xcb_get_property_value_length(protocols->_reply) /  (reply->format / 8);
704ecce36beSmrg  protocols->atoms = (xcb_atom_t *) xcb_get_property_value(protocols->_reply);
705ecce36beSmrg
706ecce36beSmrg  return 1;
707ecce36beSmrg}
708ecce36beSmrg
709ecce36beSmrguint8_t
710ecce36beSmrgxcb_get_wm_protocols_reply(xcb_connection_t *c,
711ecce36beSmrg                           xcb_get_property_cookie_t cookie,
712ecce36beSmrg                           xcb_get_wm_protocols_reply_t *protocols,
713ecce36beSmrg                           xcb_generic_error_t **e)
714ecce36beSmrg{
715ecce36beSmrg  xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e);
716ecce36beSmrg  uint8_t ret = xcb_get_wm_protocols_from_reply(reply, protocols);
717ecce36beSmrg  if(!ret)
718ecce36beSmrg      free(reply);
719ecce36beSmrg  return ret;
720ecce36beSmrg}
721ecce36beSmrg
722ecce36beSmrgvoid
723ecce36beSmrgxcb_get_wm_protocols_reply_wipe(xcb_get_wm_protocols_reply_t *protocols)
724ecce36beSmrg{
725ecce36beSmrg  free(protocols->_reply);
726ecce36beSmrg}
727