From d44c8b2e7f61c76bfc45afb11d81af5b8f6ad536 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 12 Jan 2025 14:14:46 -0500 Subject: [PATCH 1/2] Add a rounded rect helper Add a function to find out if a point is in a corner box. --- gsk/gskroundedrect.c | 44 +++++++++++++++++++++++++++++++++++++ gsk/gskroundedrectprivate.h | 4 ++++ 2 files changed, 48 insertions(+) diff --git a/gsk/gskroundedrect.c b/gsk/gskroundedrect.c index f66dadf8e0e..e852e014a1b 100644 --- a/gsk/gskroundedrect.c +++ b/gsk/gskroundedrect.c @@ -1075,3 +1075,47 @@ gsk_rounded_rect_get_largest_cover (const GskRoundedRect *self, *result = high; } +/*< private > + * gsk_rounded_rect_corner_box_contains_point: + * @self: a rounded rectangle + * @corner: the corner + * @point: the point + * + * Returns whether @point is inside the rectangle defining + * the quarter ellipses of the given corner. + * + * Returns: true if @point is inside the @corner's box + */ +gboolean +gsk_rounded_rect_corner_box_contains_point (const GskRoundedRect *self, + GskCorner corner, + const graphene_point_t *point) +{ + graphene_rect_t rect; + + graphene_size_init_from_size (&rect.size, &self->corner[corner]); + + switch (corner) + { + case GSK_CORNER_TOP_LEFT: + rect.origin.x = self->bounds.origin.x; + rect.origin.y = self->bounds.origin.y; + break; + case GSK_CORNER_TOP_RIGHT: + rect.origin.x = self->bounds.origin.x + self->bounds.size.width - self->corner[corner].width; + rect.origin.y = self->bounds.origin.y; + break; + case GSK_CORNER_BOTTOM_RIGHT: + rect.origin.x = self->bounds.origin.x + self->bounds.size.width - self->corner[corner].width; + rect.origin.y = self->bounds.origin.y + self->bounds.size.height - self->corner[corner].height; + break; + case GSK_CORNER_BOTTOM_LEFT: + rect.origin.x = self->bounds.origin.x; + rect.origin.y = self->bounds.origin.y + self->bounds.size.height - self->corner[corner].height; + break; + default: + g_assert_not_reached (); + } + + return graphene_rect_contains_point (&rect, point); +} diff --git a/gsk/gskroundedrectprivate.h b/gsk/gskroundedrectprivate.h index e83e1aed1c8..d9f5f56cce3 100644 --- a/gsk/gskroundedrectprivate.h +++ b/gsk/gskroundedrectprivate.h @@ -75,6 +75,10 @@ GskRoundedRectIntersection gsk_rounded_rect_intersection (const GskRoun const GskRoundedRect *b, GskRoundedRect *result); +gboolean gsk_rounded_rect_corner_box_contains_point (const GskRoundedRect *self, + GskCorner corner, + const graphene_point_t *point); + G_END_DECLS -- GitLab From 589c319335b2a211d69149db295c4fd53c43f677 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 12 Jan 2025 14:15:40 -0500 Subject: [PATCH 2/2] window: Handle resize corners better With large corner radiuses, it becomes very noticable that there is a dead area between the corner circle and rectangle. We have the rounded rect, and the code to check, so lets do better. --- gtk/gtkwindow.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 38d288fe30a..0be15aff600 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -70,6 +70,8 @@ #include "gdk/gdktextureprivate.h" #include "gdk/gdktoplevelprivate.h" +#include "gsk/gskroundedrectprivate.h" + #include #include #include @@ -1440,6 +1442,9 @@ get_edge_for_coordinates (GtkWindow *window, GtkCssBoxes css_boxes; const graphene_rect_t *border_rect; float left, top; + const GskRoundedRect *border; + graphene_point_t p; + int resize_handle_size; #define edge_or_minus_one(edge) ((supports_edge_constraints && (priv->edge_constraints & constraints_for_edge (edge)) != constraints_for_edge (edge)) ? -1 : edge) @@ -1455,8 +1460,16 @@ get_edge_for_coordinates (GtkWindow *window, return -1; gtk_css_boxes_init (&css_boxes, GTK_WIDGET (window)); + border = gtk_css_boxes_get_content_box (&css_boxes); border_rect = gtk_css_boxes_get_content_rect (&css_boxes); + resize_handle_size = RESIZE_HANDLE_CORNER_SIZE; + for (int i = 0 ; i < 4; i++) + { + resize_handle_size = MAX (resize_handle_size, border->corner[i].width); + resize_handle_size = MAX (resize_handle_size, border->corner[i].height); + } + get_box_border (gtk_css_node_get_style (gtk_widget_get_css_node (GTK_WIDGET (window))), &handle_size); @@ -1478,10 +1491,10 @@ get_edge_for_coordinates (GtkWindow *window, if (x < left && x >= left - handle_size.left) { - if (y < top + RESIZE_HANDLE_CORNER_SIZE && y >= top - handle_size.top) + if (y < top + resize_handle_size && y >= top - handle_size.top) return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_WEST); - if (y > top + border_rect->size.height - RESIZE_HANDLE_CORNER_SIZE && + if (y > top + border_rect->size.height - resize_handle_size && y <= top + border_rect->size.height + handle_size.bottom) return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_WEST); @@ -1490,10 +1503,10 @@ get_edge_for_coordinates (GtkWindow *window, else if (x > left + border_rect->size.width && x <= left + border_rect->size.width + handle_size.right) { - if (y < top + RESIZE_HANDLE_CORNER_SIZE && y >= top - handle_size.top) + if (y < top + resize_handle_size && y >= top - handle_size.top) return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_EAST); - if (y > top + border_rect->size.height - RESIZE_HANDLE_CORNER_SIZE && + if (y > top + border_rect->size.height - resize_handle_size && y <= top + border_rect->size.height + handle_size.bottom) return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_EAST); @@ -1501,10 +1514,10 @@ get_edge_for_coordinates (GtkWindow *window, } else if (y < top && y >= top - handle_size.top) { - if (x < left + RESIZE_HANDLE_CORNER_SIZE && x >= left - handle_size.left) + if (x < left + resize_handle_size && x >= left - handle_size.left) return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_WEST); - if (x > left + border_rect->size.width - RESIZE_HANDLE_CORNER_SIZE && + if (x > left + border_rect->size.width - resize_handle_size && x <= left + border_rect->size.width + handle_size.right) return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_EAST); @@ -1513,16 +1526,32 @@ get_edge_for_coordinates (GtkWindow *window, else if (y > top + border_rect->size.height && y <= top + border_rect->size.height + handle_size.bottom) { - if (x < left + RESIZE_HANDLE_CORNER_SIZE && x >= left - handle_size.left) + if (x < left + resize_handle_size && x >= left - handle_size.left) return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_WEST); - if (x > left + border_rect->size.width - RESIZE_HANDLE_CORNER_SIZE && + if (x > left + border_rect->size.width - resize_handle_size && x <= left + border_rect->size.width + handle_size.right) return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_EAST); return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH); } + p = GRAPHENE_POINT_INIT (x,y ); + if (!gsk_rounded_rect_contains_point (border, &p)) + { + if (gsk_rounded_rect_corner_box_contains_point (border, GSK_CORNER_TOP_LEFT, &p)) + return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_WEST); + + if (gsk_rounded_rect_corner_box_contains_point (border, GSK_CORNER_TOP_RIGHT, &p)) + return edge_or_minus_one (GDK_SURFACE_EDGE_NORTH_EAST); + + if (gsk_rounded_rect_corner_box_contains_point (border, GSK_CORNER_BOTTOM_RIGHT, &p)) + return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_EAST); + + if (gsk_rounded_rect_corner_box_contains_point (border, GSK_CORNER_BOTTOM_LEFT, &p)) + return edge_or_minus_one (GDK_SURFACE_EDGE_SOUTH_WEST); + } + return -1; } -- GitLab