popover: Try to not exceed monitor bounds

When the natural size of the popover exceeds
the monitor width, clamp it to fit on screen.

This gives the Emoji chooser a chance to
work on phone screens.

Fixes: #3307
This commit is contained in:
Matthias Clasen 2020-12-21 22:46:52 -05:00
parent 2ea4574caf
commit 4857829aaa

View File

@ -360,7 +360,9 @@ did_flip_vertically (GdkGravity original_gravity,
static void static void
update_popover_layout (GtkPopover *popover, update_popover_layout (GtkPopover *popover,
GdkPopupLayout *layout) GdkPopupLayout *layout,
int width,
int height)
{ {
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
GdkRectangle final_rect; GdkRectangle final_rect;
@ -413,7 +415,9 @@ update_popover_layout (GtkPopover *popover,
break; break;
} }
if (priv->final_position != position) if (priv->final_position != position ||
priv->final_rect.width != width ||
priv->final_rect.height != height)
{ {
gtk_widget_queue_allocate (GTK_WIDGET (popover)); gtk_widget_queue_allocate (GTK_WIDGET (popover));
g_clear_pointer (&priv->arrow_render_node, gsk_render_node_unref); g_clear_pointer (&priv->arrow_render_node, gsk_render_node_unref);
@ -545,9 +549,9 @@ create_popup_layout (GtkPopover *popover)
g_assert_not_reached (); g_assert_not_reached ();
} }
layout = gdk_popup_layout_new (&rect, anchor_hints |= GDK_ANCHOR_RESIZE;
parent_anchor,
surface_anchor); layout = gdk_popup_layout_new (&rect, parent_anchor, surface_anchor);
gdk_popup_layout_set_anchor_hints (layout, anchor_hints); gdk_popup_layout_set_anchor_hints (layout, anchor_hints);
if (priv->x_offset || priv->y_offset) if (priv->x_offset || priv->y_offset)
@ -560,17 +564,17 @@ static gboolean
present_popup (GtkPopover *popover) present_popup (GtkPopover *popover)
{ {
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
GtkRequisition req; GtkRequisition nat;
GdkPopupLayout *layout; GdkPopupLayout *layout;
layout = create_popup_layout (popover); layout = create_popup_layout (popover);
gtk_widget_get_preferred_size (GTK_WIDGET (popover), NULL, &req); gtk_widget_get_preferred_size (GTK_WIDGET (popover), NULL, &nat);
if (gdk_popup_present (GDK_POPUP (priv->surface), if (gdk_popup_present (GDK_POPUP (priv->surface),
MAX (req.width, 1), nat.width, nat.height,
MAX (req.height, 1),
layout)) layout))
{ {
update_popover_layout (popover, layout); update_popover_layout (popover, layout, nat.width, nat.height);
return TRUE; return TRUE;
} }
@ -631,7 +635,7 @@ gtk_popover_native_layout (GtkNative *native,
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
GtkWidget *widget = GTK_WIDGET (popover); GtkWidget *widget = GTK_WIDGET (popover);
update_popover_layout (popover, gdk_popup_layout_ref (priv->layout)); update_popover_layout (popover, gdk_popup_layout_ref (priv->layout), width, height);
if (gtk_widget_needs_allocate (widget)) if (gtk_widget_needs_allocate (widget))
{ {