summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2016-01-18 14:05:00 +0100
committerCarlos Garnacho <carlosg@gnome.org>2016-01-19 00:00:06 +0100
commitbe016ad7454f446f8b28cedb3412cd8fe636dd19 (patch)
treecbbfb19ea16b59479e40f7f6c3aa3a93e2edbc62
parent9038313a1a736ff125131e4398477ac355fe7554 (diff)
downloadgtk+-be016ad7454f446f8b28cedb3412cd8fe636dd19.tar.gz
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.
-rw-r--r--gdk/wayland/gdkdevice-wayland.c33
1 files 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)
{