wayland: Fix corner cases in positioning
authorMatthias Clasen <mclasen@redhat.com>
Wed, 29 Mar 2023 00:23:38 +0000 (20:23 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Wed, 29 Mar 2023 00:37:54 +0000 (20:37 -0400)
We were not handling some cases correctly.
This was making the dropdown in the gtk-demo
image-scaling demo appear in the top left
corner.

gdk/wayland/gdkpopup-wayland.c

index 44f1e46083cc6d7e3bdca8e7cbc98e58150f72db..4b150d1d309de6c3fb4b5324e21f1b32b8199199 100644 (file)
@@ -747,11 +747,7 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
   GdkRectangle geometry;
   uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
-  const GdkRectangle *anchor_rect;
-  int anchor_rect_x, anchor_rect_y;
-  int anchor_rect_x2, anchor_rect_y2;
-  int real_anchor_rect_x, real_anchor_rect_y;
-  int anchor_rect_width, anchor_rect_height;
+  GdkRectangle anchor_rect;
   int rect_anchor_dx;
   int rect_anchor_dy;
   GdkGravity rect_anchor;
@@ -777,36 +773,23 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
 
   gdk_wayland_surface_get_window_geometry (surface->parent, &parent_geometry);
 
-  anchor_rect = gdk_popup_layout_get_anchor_rect (layout);
+  anchor_rect = *gdk_popup_layout_get_anchor_rect (layout);
 
   /* Wayland protocol requires that the anchor rect is specified
    * wrt. to the parent geometry, and that it is non-empty and
    * contained in the parent geometry.
    */
-  anchor_rect_x = anchor_rect->x - parent_geometry.x;
-  anchor_rect_y = anchor_rect->y - parent_geometry.y;
-  anchor_rect_x2 = anchor_rect_x + anchor_rect->width;
-  anchor_rect_y2 = anchor_rect_y + anchor_rect->height;
-
-  anchor_rect_x = CLAMP (anchor_rect_x, 0, parent_geometry.width - 1);
-  anchor_rect_y = CLAMP (anchor_rect_y, 0, parent_geometry.height - 1);
-  anchor_rect_x2 = CLAMP (anchor_rect_x, 0, parent_geometry.width - 1);
-  anchor_rect_y2 = CLAMP (anchor_rect_y, 0, parent_geometry.height - 1);
-
-  if (anchor_rect_x2 <= anchor_rect_x || anchor_rect_y2 <= anchor_rect_y)
+  if (!gdk_rectangle_intersect (&parent_geometry, &anchor_rect, &anchor_rect))
     {
-      /* Somebody gave a bad anchor rect. Just make something up */
-      real_anchor_rect_x = 0;
-      real_anchor_rect_y = 0;
-      anchor_rect_width = 1;
-      anchor_rect_height = 1;
+      anchor_rect.x = 0;
+      anchor_rect.y = 0;
+      anchor_rect.width = 1;
+      anchor_rect.height = 1;
     }
   else
     {
-      real_anchor_rect_x = anchor_rect_x;
-      real_anchor_rect_y = anchor_rect_y;
-      anchor_rect_width = anchor_rect_x2 - anchor_rect_x;
-      anchor_rect_height = anchor_rect_y2 - anchor_rect_y;
+      anchor_rect.x -= parent_geometry.x;
+      anchor_rect.y -= parent_geometry.y;
     }
 
   gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy);
@@ -828,10 +811,10 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
 
         xdg_positioner_set_size (positioner, geometry.width, geometry.height);
         xdg_positioner_set_anchor_rect (positioner,
-                                        real_anchor_rect_x,
-                                        real_anchor_rect_y,
-                                        anchor_rect_width,
-                                        anchor_rect_height);
+                                        anchor_rect.x,
+                                        anchor_rect.y,
+                                        anchor_rect.width,
+                                        anchor_rect.height);
         xdg_positioner_set_offset (positioner, rect_anchor_dx, rect_anchor_dy);
 
         anchor = rect_anchor_to_anchor (rect_anchor);
@@ -882,10 +865,10 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
 
         zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
         zxdg_positioner_v6_set_anchor_rect (positioner,
-                                            real_anchor_rect_x,
-                                            real_anchor_rect_y,
-                                            anchor_rect_width,
-                                            anchor_rect_height);
+                                            anchor_rect.x,
+                                            anchor_rect.y,
+                                            anchor_rect.width,
+                                            anchor_rect.height);
         zxdg_positioner_v6_set_offset (positioner,
                                        rect_anchor_dx,
                                        rect_anchor_dy);