1 /*
2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4 *
5 * Copyright 2009 Nokia.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include <glib.h>
24
25 #include "event-source.h"
26
27 typedef struct _DisplaySource
28 {
29 GSource source;
30
31 Display *display;
32 GPollFD event_poll_fd;
33 } DisplaySource;
34
35 /*---------------------------------------------------------------------------*/
36
37 static void (*_spi_default_filter) (XEvent*, void*) = NULL;
38 static void* _spi_default_filter_data = NULL;
39
40 /*---------------------------------------------------------------------------*/
41
42 static gboolean
event_prepare(GSource * source,gint * timeout)43 event_prepare (GSource *source, gint *timeout)
44 {
45 Display *display = ((DisplaySource *)source)->display;
46 gboolean retval;
47
48 *timeout = -1;
49 retval = XPending (display);
50
51 return retval;
52 }
53
54 static gboolean
event_check(GSource * source)55 event_check (GSource *source)
56 {
57 DisplaySource *display_source = (DisplaySource*)source;
58 gboolean retval;
59
60 if (display_source->event_poll_fd.revents & G_IO_IN)
61 retval = XPending (display_source->display);
62 else
63 retval = FALSE;
64
65 return retval;
66 }
67
68 static gboolean
event_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)69 event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
70 {
71 Display *display = ((DisplaySource*)source)->display;
72 XEvent xevent;
73
74 /* TODO - Should this be "if (XPending (display))"?
75 * The effect of this might be to run other main loop functions
76 * before dispatching the next XEvent.
77 */
78 while (XPending (display))
79 {
80 XNextEvent (display, &xevent);
81
82 switch (xevent.type)
83 {
84 case KeyPress:
85 case KeyRelease:
86 break;
87 default:
88 if (XFilterEvent (&xevent, None))
89 continue;
90 }
91
92 if (_spi_default_filter)
93 {
94 _spi_default_filter (&xevent, _spi_default_filter_data);
95 }
96 }
97
98 return TRUE;
99 }
100
101 /*---------------------------------------------------------------------------*/
102
103 static GSourceFuncs event_funcs = {
104 event_prepare,
105 event_check,
106 event_dispatch,
107 NULL
108 };
109
110 static GSource *
display_source_new(Display * display)111 display_source_new (Display *display)
112 {
113 GSource *source = g_source_new (&event_funcs, sizeof (DisplaySource));
114 DisplaySource *display_source = (DisplaySource *) source;
115 g_source_set_name (source, "[at-spi2-core] display_source_funcs");
116
117 display_source->display = display;
118
119 return source;
120 }
121
122 /*---------------------------------------------------------------------------*/
123
124 static DisplaySource *spi_display_source = NULL;
125
126 void
spi_events_init(Display * display)127 spi_events_init (Display *display)
128 {
129 GSource *source;
130
131 int connection_number = ConnectionNumber (display);
132
133 source = display_source_new (display);
134 spi_display_source = (DisplaySource*) source;
135
136 g_source_set_priority (source, G_PRIORITY_DEFAULT);
137
138 spi_display_source->event_poll_fd.fd = connection_number;
139 spi_display_source->event_poll_fd.events = G_IO_IN;
140
141 g_source_add_poll (source, &spi_display_source->event_poll_fd);
142 g_source_set_can_recurse (source, TRUE);
143 g_source_attach (source, NULL);
144 }
145
146 void
spi_events_uninit()147 spi_events_uninit ()
148 {
149 if (spi_display_source)
150 {
151 g_source_destroy ((GSource *) spi_display_source);
152 g_source_unref ((GSource *) spi_display_source);
153 spi_display_source = NULL;
154 }
155 }
156
157 void
spi_set_events(long event_mask)158 spi_set_events (long event_mask)
159 {
160 long xevent_mask = StructureNotifyMask | PropertyChangeMask;
161 xevent_mask |= event_mask;
162
163 XSelectInput (spi_display_source->display,
164 DefaultRootWindow (spi_display_source->display),
165 xevent_mask);
166 }
167
168 void
spi_set_filter(void (* filter)(XEvent *,void *),void * data)169 spi_set_filter (void (*filter) (XEvent*, void*), void* data)
170 {
171 _spi_default_filter = filter;
172 _spi_default_filter_data = data;
173 }
174
175 /*END------------------------------------------------------------------------*/
176