1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gdkeventsource.h"
24 #include "gdkinternals.h"
28 static gboolean gdk_event_source_prepare (GSource *source,
30 static gboolean gdk_event_source_check (GSource *source);
31 static gboolean gdk_event_source_dispatch (GSource *source,
34 static void gdk_event_source_finalize (GSource *source);
36 #define HAS_FOCUS(toplevel) \
37 ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
39 struct _GdkEventSource
44 GPollFD event_poll_fd;
48 static GSourceFuncs event_funcs = {
49 gdk_event_source_prepare,
50 gdk_event_source_check,
51 gdk_event_source_dispatch,
52 gdk_event_source_finalize
55 static GList *event_sources = NULL;
58 gdk_event_apply_filters (XEvent *xevent,
63 GdkFilterReturn result;
69 GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
72 if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
74 tmp_list = tmp_list->next;
79 result = filter->function (xevent, event, filter->data);
81 /* get the next node after running the function since the
82 function may add or remove a next node */
84 tmp_list = tmp_list->next;
87 if (filter->ref_count == 0)
89 *filters = g_list_remove_link (*filters, node);
94 if (result != GDK_FILTER_CONTINUE)
98 return GDK_FILTER_CONTINUE;
102 gdk_event_source_get_filter_window (GdkEventSource *event_source,
107 window = gdk_window_lookup_for_display (event_source->display,
108 xevent->xany.window);
110 if (window && !GDK_IS_WINDOW (window))
117 handle_focus_change (GdkEventCrossing *event)
119 GdkToplevelX11 *toplevel;
120 gboolean focus_in, had_focus;
122 toplevel = _gdk_x11_window_get_toplevel (event->window);
123 focus_in = (event->type == GDK_ENTER_NOTIFY);
125 if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
128 toplevel->has_pointer = focus_in;
130 if (!event->focus || toplevel->has_focus_window)
133 had_focus = HAS_FOCUS (toplevel);
134 toplevel->has_pointer_focus = focus_in;
136 if (HAS_FOCUS (toplevel) != had_focus)
138 GdkEvent *focus_event;
140 focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
141 focus_event->focus_change.window = g_object_ref (event->window);
142 focus_event->focus_change.send_event = FALSE;
143 focus_event->focus_change.in = focus_in;
144 gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));
146 gdk_event_put (focus_event);
147 gdk_event_free (focus_event);
152 gdk_event_source_translate_event (GdkEventSource *event_source,
155 GdkEvent *event = gdk_event_new (GDK_NOTHING);
156 GList *list = event_source->translators;
157 GdkFilterReturn result;
158 GdkWindow *filter_window;
160 /* Run default filters */
161 if (_gdk_default_filters)
163 /* Apply global filters */
165 result = gdk_event_apply_filters (xevent, event,
166 &_gdk_default_filters);
168 if (result == GDK_FILTER_REMOVE)
170 gdk_event_free (event);
173 else if (result == GDK_FILTER_TRANSLATE)
177 filter_window = gdk_event_source_get_filter_window (event_source, xevent);
181 /* Apply per-window filters */
182 GdkFilterReturn result;
184 event->any.window = g_object_ref (filter_window);
186 if (filter_window->filters)
188 result = gdk_event_apply_filters (xevent, event,
189 &filter_window->filters);
191 if (result == GDK_FILTER_REMOVE)
193 gdk_event_free (event);
196 else if (result == GDK_FILTER_TRANSLATE)
201 gdk_event_free (event);
204 while (list && !event)
206 GdkEventTranslator *translator = list->data;
209 event = gdk_event_translator_translate (translator,
210 event_source->display,
215 (event->type == GDK_ENTER_NOTIFY ||
216 event->type == GDK_LEAVE_NOTIFY) &&
217 event->crossing.window != NULL)
219 /* Handle focusing (in the case where no window manager is running */
220 handle_focus_change (&event->crossing);
227 gdk_check_xpending (GdkDisplay *display)
229 return XPending (GDK_DISPLAY_XDISPLAY (display));
233 gdk_event_source_prepare (GSource *source,
236 GdkDisplay *display = ((GdkEventSource*) source)->display;
239 GDK_THREADS_ENTER ();
242 retval = (_gdk_event_queue_find_first (display) != NULL ||
243 gdk_check_xpending (display));
245 GDK_THREADS_LEAVE ();
251 gdk_event_source_check (GSource *source)
253 GdkEventSource *event_source = (GdkEventSource*) source;
256 GDK_THREADS_ENTER ();
258 if (event_source->event_poll_fd.revents & G_IO_IN)
259 retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
260 gdk_check_xpending (event_source->display));
264 GDK_THREADS_LEAVE ();
270 _gdk_events_queue (GdkDisplay *display)
274 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
275 GdkEventSource *event_source;
276 GdkDisplayX11 *display_x11;
278 display_x11 = GDK_DISPLAY_X11 (display);
279 event_source = (GdkEventSource *) display_x11->event_source;
281 while (!_gdk_event_queue_find_first (display) && XPending (xdisplay))
283 XNextEvent (xdisplay, &xevent);
291 if (XFilterEvent (&xevent, None))
295 event = gdk_event_source_translate_event (event_source, &xevent);
301 node = _gdk_event_queue_append (display, event);
302 _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
308 gdk_event_source_dispatch (GSource *source,
309 GSourceFunc callback,
312 GdkDisplay *display = ((GdkEventSource*) source)->display;
315 GDK_THREADS_ENTER ();
317 event = gdk_display_get_event (display);
321 _gdk_event_emit (event);
323 gdk_event_free (event);
326 GDK_THREADS_LEAVE ();
332 gdk_event_source_finalize (GSource *source)
334 GdkEventSource *event_source = (GdkEventSource *)source;
336 g_list_free (event_source->translators);
337 event_source->translators = NULL;
339 event_sources = g_list_remove (event_sources, source);
343 gdk_event_source_new (GdkDisplay *display)
346 GdkEventSource *event_source;
347 GdkDisplayX11 *display_x11;
348 int connection_number;
351 source = g_source_new (&event_funcs, sizeof (GdkEventSource));
352 name = g_strdup_printf ("GDK X11 Event source (%s)",
353 gdk_display_get_name (display));
354 g_source_set_name (source, name);
356 event_source = (GdkEventSource *) source;
357 event_source->display = display;
359 display_x11 = GDK_DISPLAY_X11 (display);
360 connection_number = ConnectionNumber (display_x11->xdisplay);
362 event_source->event_poll_fd.fd = connection_number;
363 event_source->event_poll_fd.events = G_IO_IN;
364 g_source_add_poll (source, &event_source->event_poll_fd);
366 g_source_set_priority (source, GDK_PRIORITY_EVENTS);
367 g_source_set_can_recurse (source, TRUE);
368 g_source_attach (source, NULL);
370 event_sources = g_list_prepend (event_sources, source);
376 gdk_event_source_add_translator (GdkEventSource *source,
377 GdkEventTranslator *translator)
379 g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
381 source->translators = g_list_append (source->translators, translator);
385 gdk_event_source_select_events (GdkEventSource *source,
387 GdkEventMask event_mask,
388 unsigned int extra_x_mask)
390 unsigned int xmask = extra_x_mask;
394 list = source->translators;
398 GdkEventTranslator *translator = list->data;
399 GdkEventMask translator_mask, mask;
401 translator_mask = gdk_event_translator_get_handled_events (translator);
402 mask = event_mask & translator_mask;
406 gdk_event_translator_select_window_events (translator, window, mask);
413 for (i = 0; i < _gdk_nenvent_masks; i++)
415 if (event_mask & (1 << (i + 1)))
416 xmask |= _gdk_event_mask_table[i];
419 XSelectInput (GDK_DISPLAY_XDISPLAY (source->display), window, xmask);
423 * gdk_events_pending:
425 * Checks if any events are ready to be processed for any display.
427 * Return value: %TRUE if any events are pending.
430 gdk_events_pending (void)
434 for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
436 GdkEventSource *tmp_source = tmp_list->data;
437 GdkDisplay *display = tmp_source->display;
439 if (_gdk_event_queue_find_first (display))
443 for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
445 GdkEventSource *tmp_source = tmp_list->data;
446 GdkDisplay *display = tmp_source->display;
448 if (gdk_check_xpending (display))