summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdk/wayland/gdkeventsource.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/gdk/wayland/gdkeventsource.c b/gdk/wayland/gdkeventsource.c
index f04281cb9a..a239cab046 100644
--- a/gdk/wayland/gdkeventsource.c
+++ b/gdk/wayland/gdkeventsource.c
@@ -28,6 +28,7 @@ typedef struct _GdkWaylandEventSource {
GPollFD pfd;
uint32_t mask;
GdkDisplay *display;
+ gboolean reading;
} GdkWaylandEventSource;
static gboolean
@@ -50,12 +51,20 @@ gdk_event_source_prepare (GSource *base,
if (_gdk_event_queue_find_first (source->display) != NULL)
return TRUE;
+ /* wl_display_prepare_read() needs to be balanced with either
+ * wl_display_read_events() or wl_display_cancel_read()
+ * (in gdk_event_source_check() */
+ if (source->reading)
+ return FALSE;
+
+ /* if prepare_read() returns non-zero, there are events to be dispatched */
+ if (wl_display_prepare_read (display->wl_display) != 0)
+ return TRUE;
+ source->reading = TRUE;
+
if (wl_display_flush (display->wl_display) < 0)
g_error ("Error flushing display: %s", g_strerror (errno));
- if (wl_display_dispatch_pending (display->wl_display) < 0)
- g_error ("Error dispatching display: %s", g_strerror (errno));
-
return FALSE;
}
@@ -63,9 +72,29 @@ static gboolean
gdk_event_source_check (GSource *base)
{
GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
+ GdkWaylandDisplay *display_wayland = (GdkWaylandDisplay *) source->display;
if (source->display->event_pause_count > 0)
- return _gdk_event_queue_find_first (source->display) != NULL;
+ {
+ if (source->reading)
+ wl_display_cancel_read (display_wayland->wl_display);
+ source->reading = FALSE;
+
+ return _gdk_event_queue_find_first (source->display) != NULL;
+ }
+
+ /* read the events from the wayland fd into their respective queues if we have data */
+ if (source->reading)
+ {
+ if (source->pfd.revents & G_IO_IN)
+ {
+ if (wl_display_read_events (display_wayland->wl_display) < 0)
+ g_error ("Error reading events from display: %s", g_strerror (errno));
+ }
+ else
+ wl_display_cancel_read (display_wayland->wl_display);
+ source->reading = FALSE;
+ }
return _gdk_event_queue_find_first (source->display) != NULL ||
source->pfd.revents;
@@ -97,8 +126,14 @@ gdk_event_source_dispatch (GSource *base,
}
static void
-gdk_event_source_finalize (GSource *source)
+gdk_event_source_finalize (GSource *base)
{
+ GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
+ GdkWaylandDisplay *display = (GdkWaylandDisplay *) source->display;
+
+ if (source->reading)
+ wl_display_cancel_read (display->wl_display);
+ source->reading = FALSE;
}
static GSourceFuncs wl_glib_source_funcs = {
@@ -157,14 +192,11 @@ _gdk_wayland_display_queue_events (GdkDisplay *display)
display_wayland = GDK_WAYLAND_DISPLAY (display);
source = (GdkWaylandEventSource *) display_wayland->event_source;
- if (source->pfd.revents & G_IO_IN)
+ if (wl_display_dispatch_pending (display_wayland->wl_display) < 0)
{
- if (wl_display_dispatch (display_wayland->wl_display) < 0)
- {
- g_warning ("Error %d (%s) dispatching to Wayland display.",
- errno, g_strerror (errno));
- exit (1);
- }
+ g_warning ("Error %d (%s) dispatching to Wayland display.",
+ errno, g_strerror (errno));
+ exit (1);
}
if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))