From 5b1d96234d5f84c8757aac160673998f9d8be16f Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 18 Jan 2016 14:05:00 +0100 Subject: [PATCH] wayland: Set weak reference on the current grab window If the grab window is destroyed the grab will be implicitly removed, although we won't get GdkSeat:ungrab called in order to clear our internal window<->seat relation entirely. Setting a weak ref will nullify the pointer we keep on the seat to the window, avoiding the expected crashes. --- gdk/wayland/gdkdevice-wayland.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index cf98849931..b8f92fef68 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -2614,6 +2614,27 @@ gdk_wayland_seat_get_capabilities (GdkSeat *seat) return caps; } +static void +gdk_wayland_seat_set_grab_window (GdkWaylandSeat *seat, + GdkWindow *window) +{ + if (seat->pointer_grab_window) + { + _gdk_wayland_window_set_grab_seat (seat->pointer_grab_window, NULL); + g_object_remove_weak_pointer (G_OBJECT (seat->pointer_grab_window), + (gpointer *) &seat->pointer_grab_window); + seat->pointer_grab_window = NULL; + } + + if (window) + { + seat->pointer_grab_window = window; + g_object_add_weak_pointer (G_OBJECT (window), + (gpointer *) &seat->pointer_grab_window); + _gdk_wayland_window_set_grab_seat (window, GDK_SEAT (seat)); + } +} + static GdkGrabStatus gdk_wayland_seat_grab (GdkSeat *seat, GdkWindow *window, @@ -2646,16 +2667,15 @@ gdk_wayland_seat_grab (GdkSeat *seat, if (native == NULL || GDK_WINDOW_DESTROYED (native)) return GDK_GRAB_NOT_VIEWABLE; - wayland_seat->pointer_grab_window = window; + gdk_wayland_seat_set_grab_window (wayland_seat, window); wayland_seat->pointer_grab_time = evtime; - _gdk_wayland_window_set_grab_seat (window, seat); if (prepare_func) (prepare_func) (seat, window, prepare_func_data); if (!gdk_window_is_visible (window)) { - _gdk_wayland_window_set_grab_seat (window, NULL); + gdk_wayland_seat_set_grab_window (wayland_seat, NULL); g_critical ("Window %p has not been made visible in GdkSeatGrabPrepareFunc", window); return GDK_GRAB_NOT_VIEWABLE; @@ -2740,12 +2760,7 @@ gdk_wayland_seat_ungrab (GdkSeat *seat) g_clear_object (&wayland_seat->grab_cursor); - if (wayland_seat->pointer_grab_window) - { - _gdk_wayland_window_set_grab_seat (wayland_seat->pointer_grab_window, - NULL); - wayland_seat->pointer_grab_window = NULL; - } + gdk_wayland_seat_set_grab_window (wayland_seat, NULL); if (wayland_seat->master_pointer) {