property.c revision ecce36be
1/*
2 * Copyright © 2008 Julien Danjou <julien@danjou.info>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Except as contained in this notice, the names of the authors or
24 * their institutions shall not be used in advertising or otherwise to
25 * promote the sale, use or other dealings in this Software without
26 * prior written authorization from the authors.
27 */
28
29#include <stdlib.h>
30#include <string.h>
31
32#include "xcb_property.h"
33
34xcb_get_property_cookie_t
35xcb_get_any_property(xcb_connection_t *c, uint8_t del, xcb_window_t window, xcb_atom_t name, uint32_t long_len)
36{
37    static const xcb_atom_t type = XCB_GET_PROPERTY_TYPE_ANY;
38
39    return xcb_get_property(c, del, window, name, type, 0, long_len);
40}
41
42xcb_get_property_cookie_t
43xcb_get_any_property_unchecked(xcb_connection_t *c,
44                                                             uint8_t del,
45                                                             xcb_window_t window,
46                                                             xcb_atom_t name,
47                                                             uint32_t long_len)
48{
49    return xcb_get_property_unchecked(c, del, window, name, XCB_GET_PROPERTY_TYPE_ANY, 0, long_len);
50}
51
52static int
53call_handler(xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_property_handler_t *h)
54{
55    xcb_get_property_reply_t *propr = 0;
56    int                     ret;
57
58    if(state != XCB_PROPERTY_DELETE)
59    {
60        xcb_get_property_cookie_t cookie = xcb_get_any_property(c, 0, window, atom, h->long_len);
61        propr = xcb_get_property_reply(c, cookie, 0);
62    }
63    ret = h->handler(h->data, c, state, window, atom, propr);
64    free(propr);
65    return ret;
66}
67
68int
69xcb_property_changed(xcb_property_handlers_t *prophs, uint8_t state, xcb_window_t window, xcb_atom_t atom)
70{
71    xcb_connection_t *c = xcb_event_get_xcb_connection(xcb_property_get_event_handlers(prophs));
72    xcb_property_handler_node_t *cur;
73
74    for(cur = prophs->head; cur; cur = cur->next)
75        if(cur->name == atom)
76            return call_handler(c, state, window, atom, &cur->h);
77
78    if(prophs->def.handler)
79        return call_handler(c, state, window, atom, &prophs->def);
80
81    return 0;
82}
83
84static int
85handle_property_notify_event(void *data, xcb_connection_t *c, xcb_property_notify_event_t *e)
86{
87    xcb_property_handlers_t *prophs = data;
88    uint8_t state = e->state;
89    xcb_window_t window = e->window;
90    xcb_atom_t atom = e->atom;
91
92    return xcb_property_changed(prophs, state, window, atom);
93}
94
95void
96xcb_property_handlers_init(xcb_property_handlers_t *prophs, xcb_event_handlers_t *evenths)
97{
98    memset(prophs, 0, sizeof(prophs));
99    prophs->evenths = evenths;
100    xcb_event_set_property_notify_handler(evenths, handle_property_notify_event, prophs);
101}
102
103void
104xcb_property_handlers_wipe(xcb_property_handlers_t *prophs)
105{
106    xcb_property_handler_node_t *node, *next;
107
108    for(node = prophs->head; node; node = next)
109    {
110            next = node->next;
111            free(node);
112    }
113}
114
115xcb_event_handlers_t *
116xcb_property_get_event_handlers(xcb_property_handlers_t *prophs)
117{
118    return prophs->evenths;
119}
120
121static inline void
122set_prop_handler(xcb_property_handler_t *cur, uint32_t long_len, xcb_generic_property_handler_t handler, void *data)
123{
124    cur->long_len = long_len;
125    cur->handler = handler;
126    cur->data = data;
127}
128
129uint8_t
130xcb_property_set_handler(xcb_property_handlers_t *prophs, xcb_atom_t name, uint32_t long_len, xcb_generic_property_handler_t handler, void *data)
131{
132    xcb_property_handler_node_t *cur = malloc(sizeof(xcb_property_handler_node_t));
133    if(!cur)
134        return 0;
135    cur->next = prophs->head;
136    cur->name = name;
137    set_prop_handler(&cur->h, long_len, handler, data);
138    prophs->head = cur;
139    return 1;
140}
141
142uint8_t
143xcb_property_set_default_handler(xcb_property_handlers_t *prophs, uint32_t long_len, xcb_generic_property_handler_t handler, void *data)
144{
145    set_prop_handler(&prophs->def, long_len, handler, data);
146    return 1;
147}
148