[gtk/matthiasc/surface-state-rework: 25/80] wayland: Communicate popup layout changes via GdkSurface::layout




commit 023cdb996093290a658ff91b85ff67b5af1e045b
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Nov 25 11:48:08 2020 +0100

    wayland: Communicate popup layout changes via GdkSurface::layout
    
    By moving popup layout emission to the layout phase, the current
    GdkPopup::poup-layout-changed signal has no value on its own as it'd be
    ignored by GtkPopover.
    
    Make the Wayland backend communicate the popup layout changes via the
    common signal; but leave the rest intact until other backends catch up.

 gdk/gdkpopup.c                   | 17 ++++++++++-------
 gdk/wayland/gdksurface-wayland.c | 39 ++++++++++++++++-----------------------
 gtk/gtkpopover.c                 | 21 ++++++++++++++++-----
 3 files changed, 42 insertions(+), 35 deletions(-)
---
diff --git a/gdk/gdkpopup.c b/gdk/gdkpopup.c
index 375a0fcb92..bcd8c8ed29 100644
--- a/gdk/gdkpopup.c
+++ b/gdk/gdkpopup.c
@@ -133,13 +133,16 @@ gdk_popup_default_init (GdkPopupInterface *iface)
  * If the popup was previously now showing, it will be showed,
  * otherwise it will change position according to @layout.
  *
- * After calling this function, the result of the layout can be queried
- * using gdk_popup_get_position_x(), gdk_popup_get_position_y(),
- * gdk_surface_get_width(), gdk_surface_get_height(),
- * gdk_popup_get_rect_anchor() and gdk_popup_get_surface_anchor().
+ * After calling this function, the result should be handled in response
+ * to the GdkSurface::layout signal being emitted. The resulting popup
+ * position can be queried using gdk_popup_get_position_x(),
+ * gdk_popup_get_position_y(), and the resulting size will be sent as
+ * parameters in the layout signal. Use gdk_popup_get_rect_anchor() and
+ * gdk_popup_get_surface_anchor() to get the resulting anchors.
  *
  * Presenting may have fail, for example if it was immediately
- * hidden if the @popup was set to autohide.
+ * hidden if the @popup was set to autohide. If presenting failed,
+ * GdkSurface::layout will not me emitted.
  *
  * Returns: %FALSE if it failed to be presented, otherwise %TRUE.
  */
@@ -164,7 +167,7 @@ gdk_popup_present (GdkPopup       *popup,
  * Gets the current popup surface anchor.
  *
  * The value returned may change after calling gdk_popup_present(),
- * or after the "popup-layout-changed" is emitted.
+ * or after the "GdkSurface::layout" signal is emitted.
  *
  * Returns: the current surface anchor value of @popup
  */
@@ -183,7 +186,7 @@ gdk_popup_get_surface_anchor (GdkPopup *popup)
  * Gets the current popup rectangle anchor.
  *
  * The value returned may change after calling gdk_popup_present(),
- * or after the "popup-layout-changed" is emitted.
+ * or after the "GdkSurface::layout" signal is emitted.
  *
  * Returns: the current rectangle anchor value of @popup
  */
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index e8b635fef0..04a7643b46 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -189,6 +189,10 @@ struct _GdkWaylandSurface
       gboolean should_constrain;
       gboolean size_is_fixed;
     } toplevel;
+    struct {
+      int x;
+      int y;
+    } popup;
     int configured_width;
     int configured_height;
     gboolean surface_geometry_dirty;
@@ -616,7 +620,6 @@ configure_popup_geometry (GdkSurface *surface)
                                    impl->next_layout.popup.y,
                                    impl->next_layout.configured_width,
                                    impl->next_layout.configured_height);
-  g_signal_emit_by_name (surface, "popup-layout");
 }
 
 static void
@@ -626,8 +629,10 @@ gdk_wayland_surface_compute_size (GdkSurface *surface)
 
   if (impl->next_layout.surface_geometry_dirty)
     {
-      g_warn_if_fail (GDK_IS_TOPLEVEL (impl));
-      configure_toplevel_geometry (surface);
+      if (GDK_IS_TOPLEVEL (impl))
+        configure_toplevel_geometry (surface);
+      else if (GDK_IS_POPUP (impl))
+        configure_popup_geometry (surface);
 
       impl->next_layout.surface_geometry_dirty = FALSE;
     }
@@ -1538,18 +1543,20 @@ gdk_wayland_surface_configure_popup (GdkSurface *surface)
   width = impl->pending.popup.width;
   height = impl->pending.popup.height;
 
-  gdk_wayland_surface_resize (surface, width, height, impl->scale);
+  x += surface->parent->shadow_left;
+  y += surface->parent->shadow_top;
 
   update_popup_layout_state (surface,
                              x, y,
                              width, height,
                              impl->popup.layout);
 
-  if (!impl->pending.popup.has_repositioned_token &&
-      !impl->pending.is_initial_configure)
-    g_signal_emit_by_name (surface, "popup-layout-changed");
-
-  gdk_surface_invalidate_rect (surface, NULL);
+  impl->next_layout.popup.x = x;
+  impl->next_layout.popup.y = y;
+  impl->next_layout.configured_width = width;
+  impl->next_layout.configured_height = height;
+  impl->next_layout.surface_geometry_dirty = TRUE;
+  gdk_surface_request_layout (surface);
 }
 
 static void
@@ -2316,26 +2323,12 @@ update_popup_layout_state (GdkSurface     *surface,
                            int             height,
                            GdkPopupLayout *layout)
 {
-  int surface_x, surface_y;
-  int surface_width, surface_height;
   GdkRectangle best_rect;
   GdkRectangle flipped_rect;
   GdkGravity rect_anchor;
   GdkGravity surface_anchor;
   GdkAnchorHints anchor_hints;
 
-  x += surface->parent->shadow_left;
-  y += surface->parent->shadow_top;
-
-  surface_x = x;
-  surface_y = y;
-  surface_width = width + surface->shadow_left + surface->shadow_right;
-  surface_height = height + surface->shadow_top + surface->shadow_bottom;
-
-  gdk_wayland_surface_move_resize (surface,
-                                   surface_x, surface_y,
-                                   surface_width, surface_height);
-
   rect_anchor = gdk_popup_layout_get_rect_anchor (layout);
   surface_anchor = gdk_popup_layout_get_surface_anchor (layout);
   anchor_hints = gdk_popup_layout_get_anchor_hints (layout);
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 504dcd6cc1..252797599c 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -419,11 +419,6 @@ update_popover_layout (GtkPopover     *popover,
       g_clear_pointer (&priv->arrow_render_node, gsk_render_node_unref);
     }
 
-  gtk_widget_allocate (GTK_WIDGET (popover),
-                       gdk_surface_get_width (priv->surface),
-                       gdk_surface_get_height (priv->surface),
-                       -1, NULL);
-
   gtk_widget_queue_draw (GTK_WIDGET (popover));
 }
 
@@ -771,6 +766,20 @@ popup_layout_changed (GdkSurface *surface,
   update_popover_layout (popover, gdk_popup_layout_ref (priv->layout));
 }
 
+static void
+surface_layout (GdkSurface *surface,
+                int         width,
+                int         height,
+                GtkWidget  *widget)
+{
+  GtkPopover *popover = GTK_POPOVER (widget);
+  GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+  update_popover_layout (popover, gdk_popup_layout_ref (priv->layout));
+  if (_gtk_widget_get_alloc_needed (widget))
+    gtk_widget_allocate (widget, width, height, -1, NULL);
+}
+
 static void
 gtk_popover_activate_default (GtkPopover *popover)
 {
@@ -891,6 +900,7 @@ gtk_popover_realize (GtkWidget *widget)
   g_signal_connect (priv->surface, "render", G_CALLBACK (surface_render), widget);
   g_signal_connect (priv->surface, "event", G_CALLBACK (surface_event), widget);
   g_signal_connect (priv->surface, "popup-layout-changed", G_CALLBACK (popup_layout_changed), widget);
+  g_signal_connect (priv->surface, "layout", G_CALLBACK (surface_layout), widget);
 
   GTK_WIDGET_CLASS (gtk_popover_parent_class)->realize (widget);
 
@@ -913,6 +923,7 @@ gtk_popover_unrealize (GtkWidget *widget)
   g_signal_handlers_disconnect_by_func (priv->surface, surface_render, widget);
   g_signal_handlers_disconnect_by_func (priv->surface, surface_event, widget);
   g_signal_handlers_disconnect_by_func (priv->surface, popup_layout_changed, widget);
+  g_signal_handlers_disconnect_by_func (priv->surface, surface_layout, widget);
   gdk_surface_set_widget (priv->surface, NULL);
   gdk_surface_destroy (priv->surface);
   g_clear_object (&priv->surface);


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