add the xevent callback system to libobt in xevent.[ch]
[dana/openbox.git] / obt / xevent.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    obt/xevent.c for the Openbox window manager
4    Copyright (c) 2007        Dana Jansens
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "obt/xevent.h"
20 #include "obt/mainloop.h"
21
22 typedef struct _ObtXEventBinding ObtXEventBinding;
23
24 struct _ObtXEventHandler
25 {
26     gint ref;
27     ObtMainLoop *loop;
28
29     /* A hash table where the key is the window, and the value is the
30        ObtXEventBinding */
31     GHashTable *bindings[LASTEvent]; /* LASTEvent comes from X.h */
32 };
33
34 struct _ObtXEventBinding
35 {
36     Window win;
37     ObtXEventCallback func;
38     gpointer data;
39 };
40
41 static void xevent_handler(const XEvent *e, gpointer data);
42 static guint window_hash(Window *w) { return *w; }
43 static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
44
45 ObtXEventHandler* xevent_new()
46 {
47     ObtXEventHandler *h;
48     gint i;
49
50     h = g_new(ObtXEventHandler, 1);
51     h->ref = 1;
52     for (i = 0; i < LASTEvent; ++i)
53         h->bindings[i] = g_hash_table_new_full((GHashFunc)window_hash,
54                                                (GEqualFunc)window_comp,
55                                                NULL, g_free);
56     return h;
57 }
58
59 void xevent_ref(ObtXEventHandler *h)
60 {
61     ++h->ref;
62 }
63
64 void xevent_unref(ObtXEventHandler *h)
65 {
66     if (h && --h->ref == 0) {
67         if (h->loop)
68             obt_main_loop_x_remove(h->loop, xevent_handler);
69     }
70 }
71
72 void xevent_register(ObtXEventHandler *h, ObtMainLoop *loop)
73 {
74     h->loop = loop;
75     obt_main_loop_x_add(loop, xevent_handler, h, NULL);
76 }
77
78 void xevent_set_handler(ObtXEventHandler *h, gint type, Window win,
79                         ObtXEventCallback func, gpointer data)
80 {
81     ObtXEventBinding *b;
82
83     g_assert(type < LASTEvent);
84     g_assert(win);
85     g_assert(func);
86
87     b = g_new(ObtXEventBinding, 1);
88     b->win = win;
89     b->func = func;
90     b->data = data;
91     g_hash_table_replace(h->bindings[type], &b->win, b);
92 }
93
94 void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win)
95 {
96     g_assert(type < LASTEvent);
97     g_assert(win);
98
99     g_hash_table_remove(h->bindings[type], &win);
100 }
101
102 static void xevent_handler(const XEvent *e, gpointer data)
103 {
104     ObtXEventHandler *h;
105     ObtXEventBinding *b;
106
107     h = data;
108     b = g_hash_table_lookup(h->bindings[e->xany.type], &e->xany.window);
109     if (b) b->func(e, b->data);
110 }