diff options
Diffstat (limited to 'gdk/wayland/gdkeventsource.c')
-rw-r--r-- | gdk/wayland/gdkeventsource.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/gdk/wayland/gdkeventsource.c b/gdk/wayland/gdkeventsource.c new file mode 100644 index 0000000000..12c9118201 --- /dev/null +++ b/gdk/wayland/gdkeventsource.c @@ -0,0 +1,167 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gdkeventsource.h" +#include "gdkinternals.h" + +typedef struct _GdkWaylandEventSource { + GSource source; + GPollFD pfd; + uint32_t mask; + GdkDisplay *display; +} GdkWaylandEventSource; + +static GList *event_sources = NULL; + +static gboolean +gdk_event_source_prepare(GSource *base, gint *timeout) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + GdkDisplayWayland *display = (GdkDisplayWayland *) source->display; + + *timeout = -1; + + /* We have to add/remove the GPollFD if we want to update our + * poll event mask dynamically. Instead, let's just flush all + * write on idle instead, which is what this amounts to. */ + + if (_gdk_event_queue_find_first (source->display) != NULL) + return TRUE; + + while (source->mask & WL_DISPLAY_WRITABLE) + wl_display_iterate(display->wl_display, WL_DISPLAY_WRITABLE); + + return FALSE; +} + +static gboolean +gdk_event_source_check(GSource *base) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + + return _gdk_event_queue_find_first (source->display) != NULL || + source->pfd.revents; +} + +static gboolean +gdk_event_source_dispatch(GSource *base, + GSourceFunc callback, + gpointer data) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + GdkDisplay *display = source->display; + GdkEvent *event; + + GDK_THREADS_ENTER (); + + event = gdk_display_get_event (display); + + if (event) + { + _gdk_event_emit (event); + + gdk_event_free (event); + } + + GDK_THREADS_LEAVE (); + + return TRUE; +} + +static void +gdk_event_source_finalize (GSource *source) +{ + event_sources = g_list_remove (event_sources, source); +} + +static GSourceFuncs wl_glib_source_funcs = { + gdk_event_source_prepare, + gdk_event_source_check, + gdk_event_source_dispatch, + gdk_event_source_finalize +}; + +static int +gdk_event_source_update(uint32_t mask, void *data) +{ + GdkWaylandEventSource *source = data; + + source->mask = mask; + + return 0; +} + +void +_gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event) +{ + GList *node; + static int serial; + + node = _gdk_event_queue_append (display, event); + _gdk_windowing_got_event (display, node, event, serial++); +} + +GSource * +_gdk_wayland_display_event_source_new (GdkDisplay *display) +{ + GSource *source; + GdkWaylandEventSource *wl_source; + GdkDisplayWayland *display_wayland; + char *name; + + source = g_source_new (&wl_glib_source_funcs, + sizeof (GdkWaylandEventSource)); + name = g_strdup_printf ("GDK Wayland Event source (%s)", "display name"); + g_source_set_name (source, name); + g_free (name); + wl_source = (GdkWaylandEventSource *) source; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + wl_source->display = display; + wl_source->pfd.fd = wl_display_get_fd(display_wayland->wl_display, + gdk_event_source_update, source); + wl_source->pfd.events = G_IO_IN | G_IO_ERR; + g_source_add_poll(source, &wl_source->pfd); + + g_source_set_priority (source, GDK_PRIORITY_EVENTS); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); + + event_sources = g_list_prepend (event_sources, source); + + return source; +} + +void +_gdk_wayland_display_queue_events (GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland; + GdkWaylandEventSource *source; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + source = (GdkWaylandEventSource *) display_wayland->event_source; + + if (source->pfd.revents) + { + wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE); + source->pfd.revents = 0; + } +} |