diff options
-rw-r--r-- | gdk/wayland/gdkeventsource.c | 56 |
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)) |