From d38f81999e2e277e29573a855120873803d26125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 25 Nov 2020 11:48:08 +0100 Subject: [PATCH] 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);