[gtk/popover-list-lockup] window: Defer focus setting until after paint




commit 4a76abffd4d62cbbb7b795008c86659a966cbf0d
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Apr 9 19:38:25 2021 -0400

    window: Defer focus setting until after paint
    
    Commit 3dbf5038fab8eb0d8c11 tried to defer focus changes
    until after rendering is done. But it failed to do so, since
    the toplevel ::render handler is still before rendering of
    popups that are attached to that toplevel. To do this
    properly, we need to do it in the AFTER_PAINT frame clock
    phase.
    
    Fixes: #3725

 gtk/gtkwindow.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 7b1eaa860d..99bb28feb6 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -371,6 +371,8 @@ static gboolean surface_render            (GdkSurface         *surface,
 static gboolean surface_event             (GdkSurface         *surface,
                                            GdkEvent           *event,
                                            GtkWidget          *widget);
+static void     after_paint               (GdkFrameClock      *clock,
+                                           GtkWindow          *window);
 
 static int gtk_window_focus              (GtkWidget        *widget,
                                           GtkDirectionType  direction);
@@ -4256,6 +4258,7 @@ gtk_window_realize (GtkWidget *widget)
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
   GdkSurface *surface;
+  GdkFrameClock *frame_clock;
 
   /* Create default title bar */
   if (!priv->client_decorated && gtk_window_should_use_csd (window))
@@ -4292,6 +4295,9 @@ gtk_window_realize (GtkWidget *widget)
   g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget);
   g_signal_connect (surface, "compute-size", G_CALLBACK (toplevel_compute_size), widget);
 
+  frame_clock = gdk_surface_get_frame_clock (surface);
+  g_signal_connect (frame_clock, "after-paint", G_CALLBACK (after_paint), widget);
+
   GTK_WIDGET_CLASS (gtk_window_parent_class)->realize (widget);
 
   gtk_root_start_layout (GTK_ROOT (window));
@@ -4363,6 +4369,7 @@ gtk_window_unrealize (GtkWidget *widget)
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
   GtkWindowGeometryInfo *info;
   GdkSurface *surface;
+  GdkFrameClock *frame_clock;
 
   gtk_native_unrealize (GTK_NATIVE (window));
 
@@ -4403,6 +4410,10 @@ gtk_window_unrealize (GtkWidget *widget)
   g_signal_handlers_disconnect_by_func (surface, surface_render, widget);
   g_signal_handlers_disconnect_by_func (surface, surface_event, widget);
 
+  frame_clock = gdk_surface_get_frame_clock (surface);
+
+  g_signal_handlers_disconnect_by_func (frame_clock, after_paint, widget);
+
   gtk_root_stop_layout (GTK_ROOT (window));
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
@@ -4677,14 +4688,18 @@ surface_render (GdkSurface     *surface,
                 cairo_region_t *region,
                 GtkWidget      *widget)
 {
-  GtkWindow *window = GTK_WINDOW (widget);
-
   gtk_widget_render (widget, surface, region);
-  maybe_unset_focus_and_default (window);
 
   return TRUE;
 }
 
+static void
+after_paint (GdkFrameClock *clock,
+             GtkWindow     *window)
+{
+  maybe_unset_focus_and_default (window);
+}
+
 static gboolean
 surface_event (GdkSurface *surface,
                GdkEvent   *event,
@@ -5129,6 +5144,16 @@ _gtk_window_unset_focus_and_default (GtkWindow *window,
   child = priv->default_widget;
   if (child && (child == widget || gtk_widget_is_ancestor (child, widget)))
     priv->unset_default = TRUE;
+
+  if ((priv->move_focus || priv->unset_default) &&
+      priv->surface != NULL)
+    {
+      GdkFrameClock *frame_clock;
+
+      frame_clock = gdk_surface_get_frame_clock (priv->surface);
+      gdk_frame_clock_request_phase (frame_clock,
+                                     GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
+    }
 }
 
 #undef INCLUDE_CSD_SIZE


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]