From 8362e1889134eb66e98b5d65be5e7baa199a4983 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
Date: Mon, 12 Jun 2023 18:28:29 +0200
Subject: [PATCH] window: Clear resize_cursor on leave notify events

When the pointer leaves the window surface, gtk_window_capture_motion
will not be called anymore, so priv->resize_cursor may remain non-NULL
indefinitely without this.

If update_cursor is later called (via gtk_window_maybe_update_cursor) on
a virtual enter notify event (e.g. because the pointer entered a
descendant surface), it would previously re-set the window surface
cursor to priv->resize_cursor, which could result in the wrong cursor
shape being shown for descendant surfaces.

This affected mutter-x11-frames, see
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1557.

One could also say that if the pointer leaves the window surface, it's
trivially not over any window edge.

(cherry-picked from commit f8fd04402eaf500abc72d5529165068660bd6911)
---
 gtk/gtkwindow.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index cc1f37b80d..579251250f 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -1569,6 +1569,15 @@ gtk_window_capture_motion (GtkWidget *widget,
   gtk_window_maybe_update_cursor (window, widget, NULL);
 }
 
+static void
+gtk_window_capture_leave (GtkWidget *widget)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  g_clear_object (&priv->resize_cursor);
+}
+
 static void
 gtk_window_activate_default_activate (GtkWidget  *widget,
                                       const char *name,
@@ -1673,6 +1682,8 @@ gtk_window_init (GtkWindow *window)
                                               GTK_PHASE_CAPTURE);
   g_signal_connect_swapped (controller, "motion",
                             G_CALLBACK (gtk_window_capture_motion), window);
+  g_signal_connect_swapped (controller, "leave",
+                            G_CALLBACK (gtk_window_capture_leave), window);
   gtk_widget_add_controller (widget, controller);
 
   controller = gtk_event_controller_key_new ();