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;
71 tmp_list = tmp_list->next;
72 result = filter->function (xevent, event, filter->data);
74 if (result != GDK_FILTER_CONTINUE)
78 return GDK_FILTER_CONTINUE;
82 gdk_event_source_get_filter_window (GdkEventSource *event_source,
87 window = gdk_window_lookup_for_display (event_source->display,
90 if (window && !GDK_IS_WINDOW (window))
97 handle_focus_change (GdkEventCrossing *event)
99 GdkToplevelX11 *toplevel;
100 gboolean focus_in, had_focus;
102 toplevel = _gdk_x11_window_get_toplevel (event->window);
103 focus_in = (event->type == GDK_ENTER_NOTIFY);
105 if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
108 toplevel->has_pointer = focus_in;
110 if (!event->focus || toplevel->has_focus_window)
113 had_focus = HAS_FOCUS (toplevel);
114 toplevel->has_pointer_focus = focus_in;
116 if (HAS_FOCUS (toplevel) != had_focus)
118 GdkEvent *focus_event;
120 focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
121 focus_event->focus_change.window = g_object_ref (event->window);
122 focus_event->focus_change.send_event = FALSE;
123 focus_event->focus_change.in = focus_in;
124 gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));
126 gdk_event_put (focus_event);
127 gdk_event_free (focus_event);
132 gdk_event_source_translate_event (GdkEventSource *event_source,
135 GdkEvent *event = gdk_event_new (GDK_NOTHING);
136 GList *list = event_source->translators;
137 GdkFilterReturn result;
138 GdkWindow *filter_window;
140 /* Run default filters */
141 if (_gdk_default_filters)
143 /* Apply global filters */
145 result = gdk_event_apply_filters (xevent, event,
146 _gdk_default_filters);
148 if (result == GDK_FILTER_REMOVE)
150 gdk_event_free (event);
153 else if (result == GDK_FILTER_TRANSLATE)
157 filter_window = gdk_event_source_get_filter_window (event_source, xevent);
161 /* Apply per-window filters */
162 GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
163 GdkFilterReturn result;
165 event->any.window = g_object_ref (filter_window);
167 if (filter_private->filters)
169 result = gdk_event_apply_filters (xevent, event,
170 filter_private->filters);
172 if (result == GDK_FILTER_REMOVE)
174 gdk_event_free (event);
177 else if (result == GDK_FILTER_TRANSLATE)
182 gdk_event_free (event);
185 while (list && !event)
187 GdkEventTranslator *translator = list->data;
190 event = gdk_event_translator_translate (translator,
191 event_source->display,
196 (event->type == GDK_ENTER_NOTIFY ||
197 event->type == GDK_LEAVE_NOTIFY) &&
198 event->crossing.window != NULL)
200 /* Handle focusing (in the case where no window manager is running */
201 handle_focus_change (&event->crossing);
208 gdk_check_xpending (GdkDisplay *display)
210 return XPending (GDK_DISPLAY_XDISPLAY (display));
214 gdk_event_source_prepare (GSource *source,
217 GdkDisplay *display = ((GdkEventSource*) source)->display;
220 GDK_THREADS_ENTER ();
223 retval = (_gdk_event_queue_find_first (display) != NULL ||
224 gdk_check_xpending (display));
226 GDK_THREADS_LEAVE ();
232 gdk_event_source_check (GSource *source)
234 GdkEventSource *event_source = (GdkEventSource*) source;
237 GDK_THREADS_ENTER ();
239 if (event_source->event_poll_fd.revents & G_IO_IN)
240 retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
241 gdk_check_xpending (event_source->display));
245 GDK_THREADS_LEAVE ();
251 _gdk_events_queue (GdkDisplay *display)
255 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
256 GdkEventSource *event_source;
257 GdkDisplayX11 *display_x11;
259 display_x11 = GDK_DISPLAY_X11 (display);
260 event_source = (GdkEventSource *) display_x11->event_source;
262 while (!_gdk_event_queue_find_first (display) && XPending (xdisplay))
264 XNextEvent (xdisplay, &xevent);
272 if (XFilterEvent (&xevent, None))
276 event = gdk_event_source_translate_event (event_source, &xevent);
282 node = _gdk_event_queue_append (display, event);
283 _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
289 gdk_event_source_dispatch (GSource *source,
290 GSourceFunc callback,
293 GdkDisplay *display = ((GdkEventSource*) source)->display;
296 GDK_THREADS_ENTER ();
298 event = gdk_display_get_event (display);
303 (*_gdk_event_func) (event, _gdk_event_data);
305 gdk_event_free (event);
308 GDK_THREADS_LEAVE ();
314 gdk_event_source_finalize (GSource *source)
316 GdkEventSource *event_source = (GdkEventSource *)source;
318 g_list_free (event_source->translators);
319 event_source->translators = NULL;
321 event_sources = g_list_remove (event_sources, source);
325 gdk_event_source_new (GdkDisplay *display)
328 GdkEventSource *event_source;
329 GdkDisplayX11 *display_x11;
330 int connection_number;
333 source = g_source_new (&event_funcs, sizeof (GdkEventSource));
334 name = g_strdup_printf ("GDK X11 Event source (%s)",
335 gdk_display_get_name (display));
336 g_source_set_name (source, name);
338 event_source = (GdkEventSource *) source;
339 event_source->display = display;
341 display_x11 = GDK_DISPLAY_X11 (display);
342 connection_number = ConnectionNumber (display_x11->xdisplay);
344 event_source->event_poll_fd.fd = connection_number;
345 event_source->event_poll_fd.events = G_IO_IN;
346 g_source_add_poll (source, &event_source->event_poll_fd);
348 g_source_set_priority (source, GDK_PRIORITY_EVENTS);
349 g_source_set_can_recurse (source, TRUE);
350 g_source_attach (source, NULL);
352 event_sources = g_list_prepend (event_sources, source);
358 gdk_event_source_add_translator (GdkEventSource *source,
359 GdkEventTranslator *translator)
361 g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
363 source->translators = g_list_append (source->translators, translator);
367 gdk_event_source_select_events (GdkEventSource *source,
369 GdkEventMask event_mask,
370 unsigned int extra_x_mask)
372 unsigned int xmask = extra_x_mask;
376 list = source->translators;
380 GdkEventTranslator *translator = list->data;
381 GdkEventMask translator_mask, mask;
383 translator_mask = gdk_event_translator_get_handled_events (translator);
384 mask = event_mask & translator_mask;
388 gdk_event_translator_select_window_events (translator, window, mask);
395 for (i = 0; i < _gdk_nenvent_masks; i++)
397 if (event_mask & (1 << (i + 1)))
398 xmask |= _gdk_event_mask_table[i];
401 XSelectInput (GDK_DISPLAY_XDISPLAY (source->display), window, xmask);
405 * gdk_events_pending:
407 * Checks if any events are ready to be processed for any display.
409 * Return value: %TRUE if any events are pending.
412 gdk_events_pending (void)
416 for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
418 GdkEventSource *tmp_source = tmp_list->data;
419 GdkDisplay *display = tmp_source->display;
421 if (_gdk_event_queue_find_first (display))
425 for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
427 GdkEventSource *tmp_source = tmp_list->data;
428 GdkDisplay *display = tmp_source->display;
430 if (gdk_check_xpending (display))