From: tokyo4j Date: Sat, 1 Feb 2025 05:51:47 +0000 (+0900) Subject: ssd: fix resizing on border corners and add X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=950337b89505b61c75c18332b8dce943ceea1971;p=proto%2Flabwc.git ssd: fix resizing on border corners and add Eliminate corner extents and instead use cursor position to map SSD borders and extents to corner contexts, with a size configurable by the parameter. This simplifies extent handling, eliminates bugs in the detection of corner context, and allows users to expand corner targets if they wish. Co-authored-by: Andrew J. Hesford --- diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 23b5df37..9be38e80 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -576,6 +576,13 @@ extending outward from the snapped edge. outlined rectangle is shown to indicate the geometry of resized window. Default is yes. +** + The size of corner regions to which the 'TLCorner', 'TRCorner', + 'BLCorner' and 'RLCorner' mousebind contexts apply, as well as the size + of the border region for which mouse resizing will apply both + horizontally and vertically rather than one or the other. Default is + half the titlebar height. + ## KEYBOARD ** [on|off] diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 8ea2710b..31ddb6d7 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -131,6 +131,7 @@ Never yes + 8 diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 208b73e0..0b9c0dc9 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -151,6 +151,7 @@ struct rcxml { enum resize_indicator_mode resize_indicator; bool resize_draw_contents; + int resize_corner_range; struct { int popuptime; diff --git a/include/ssd.h b/include/ssd.h index fe56be54..3c023121 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -5,6 +5,8 @@ #include #include "common/border.h" +struct wlr_cursor; + #define SSD_EXTENDED_AREA 8 /* @@ -107,10 +109,8 @@ enum ssd_part_type ssd_button_get_type(const struct ssd_button *button); struct view *ssd_button_get_view(const struct ssd_button *button); /* Public SSD helpers */ -enum ssd_part_type ssd_at(const struct ssd *ssd, - struct wlr_scene *scene, double lx, double ly); enum ssd_part_type ssd_get_part_type(const struct ssd *ssd, - struct wlr_scene_node *node); + struct wlr_scene_node *node, struct wlr_cursor *cursor); uint32_t ssd_resize_edges(enum ssd_part_type type); bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate); enum ssd_mode ssd_mode_parse(const char *mode); diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 0b606a2a..eebf6956 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1223,6 +1223,8 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) } } else if (!strcasecmp(nodename, "drawContents.resize")) { set_bool(content, &rc.resize_draw_contents); + } else if (!strcasecmp(nodename, "cornerRange.resize")) { + rc.resize_corner_range = atoi(content); } else if (!strcasecmp(nodename, "mouseEmulation.tablet")) { set_bool(content, &rc.tablet.force_mouse_emulation); } else if (!strcasecmp(nodename, "mapToOutput.tablet")) { @@ -1498,6 +1500,7 @@ rcxml_init(void) rc.resize_indicator = LAB_RESIZE_INDICATOR_NEVER; rc.resize_draw_contents = true; + rc.resize_corner_range = -1; rc.workspace_config.popuptime = INT_MIN; rc.workspace_config.min_nr_workspaces = 1; diff --git a/src/desktop.c b/src/desktop.c index 5a78bffa..e3380705 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -278,7 +278,8 @@ get_cursor_context(struct server *server) case LAB_NODE_DESC_VIEW: case LAB_NODE_DESC_XDG_POPUP: ret.view = desc->data; - ret.type = ssd_get_part_type(ret.view->ssd, ret.node); + ret.type = ssd_get_part_type( + ret.view->ssd, ret.node, cursor); if (ret.type == LAB_SSD_CLIENT) { ret.surface = lab_wlr_surface_from_node(ret.node); } diff --git a/src/ssd/ssd-extents.c b/src/ssd/ssd-extents.c index 1a0ed351..e88b58ea 100644 --- a/src/ssd/ssd-extents.c +++ b/src/ssd/ssd-extents.c @@ -37,17 +37,10 @@ ssd_extents_create(struct ssd *ssd) -(theme->border_width + extended_area), -(ssd->titlebar.height + theme->border_width + extended_area)); - /* Top */ - add_extent(part_list, LAB_SSD_PART_CORNER_TOP_LEFT, parent); add_extent(part_list, LAB_SSD_PART_TOP, parent); - add_extent(part_list, LAB_SSD_PART_CORNER_TOP_RIGHT, parent); - /* Sides */ add_extent(part_list, LAB_SSD_PART_LEFT, parent); add_extent(part_list, LAB_SSD_PART_RIGHT, parent); - /* Bottom */ - add_extent(part_list, LAB_SSD_PART_CORNER_BOTTOM_LEFT, parent); add_extent(part_list, LAB_SSD_PART_BOTTOM, parent); - add_extent(part_list, LAB_SSD_PART_CORNER_BOTTOM_RIGHT, parent); /* Initial manual update to keep X11 applications happy */ ssd_extents_update(ssd); @@ -76,11 +69,6 @@ ssd_extents_update(struct ssd *ssd) int full_height = height + theme->border_width * 2 + ssd->titlebar.height; int full_width = width + 2 * theme->border_width; int extended_area = SSD_EXTENDED_AREA; - int corner_width = ssd_get_corner_width(); - int corner_size = extended_area + theme->border_width + - MIN(corner_width, width) / 2; - int side_width = full_width + extended_area * 2 - corner_size * 2; - int side_height = full_height + extended_area * 2 - corner_size * 2; struct wlr_box part_box; struct wlr_box result_box; @@ -120,54 +108,30 @@ ssd_extents_update(struct ssd *ssd) wl_list_for_each(part, &ssd->extents.parts, link) { rect = wlr_scene_rect_from_node(part->node); switch (part->type) { - case LAB_SSD_PART_CORNER_TOP_LEFT: - target.x = 0; - target.y = 0; - target.width = corner_size; - target.height = corner_size; - break; case LAB_SSD_PART_TOP: - target.x = corner_size; + target.x = 0; target.y = 0; - target.width = side_width; + target.width = full_width + extended_area * 2; target.height = extended_area; break; - case LAB_SSD_PART_CORNER_TOP_RIGHT: - target.x = corner_size + side_width; - target.y = 0; - target.width = corner_size; - target.height = corner_size; - break; case LAB_SSD_PART_LEFT: target.x = 0; - target.y = corner_size; + target.y = extended_area; target.width = extended_area; - target.height = side_height; + target.height = full_height; break; case LAB_SSD_PART_RIGHT: target.x = extended_area + full_width; - target.y = corner_size; + target.y = extended_area; target.width = extended_area; - target.height = side_height; - break; - case LAB_SSD_PART_CORNER_BOTTOM_LEFT: - target.x = 0; - target.y = corner_size + side_height; - target.width = corner_size; - target.height = corner_size; + target.height = full_height; break; case LAB_SSD_PART_BOTTOM: - target.x = corner_size; + target.x = 0; target.y = extended_area + full_height; - target.width = side_width; + target.width = full_width + extended_area * 2; target.height = extended_area; break; - case LAB_SSD_PART_CORNER_BOTTOM_RIGHT: - target.x = corner_size + side_width; - target.y = corner_size + side_height; - target.width = corner_size; - target.height = corner_size; - break; default: /* not reached */ assert(false); diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index 49f088b7..65416ca3 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -74,8 +74,69 @@ ssd_max_extents(struct view *view) }; } +/* + * Resizing and mouse contexts like 'Left', 'TLCorner', etc. in the vicinity of + * SSD borders, titlebars and extents can have effective "corner regions" that + * behave differently from single-edge contexts. + * + * Corner regions are active whenever the cursor is within a prescribed size + * (generally rc.resize_corner_range, but clipped to view size) of the view + * bounds, so check the cursor against the view here. + */ +static enum ssd_part_type +get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor) +{ + struct view *view = ssd ? ssd->view : NULL; + if (!view || !cursor || !view->ssd_enabled || view->fullscreen) { + return LAB_SSD_NONE; + } + + struct wlr_box view_box = view->current; + view_box.height = view_effective_height(view, /* use_pending */ false); + + if (!view->ssd_titlebar_hidden) { + /* If the titlebar is visible, consider it part of the view */ + int titlebar_height = view->server->theme->titlebar_height; + view_box.y -= titlebar_height; + view_box.height += titlebar_height; + } + + if (wlr_box_contains_point(&view_box, cursor->x, cursor->y)) { + /* A cursor in bounds of the view is never in an SSD context */ + return LAB_SSD_NONE; + } + + int corner_height = MAX(0, MIN(rc.resize_corner_range, view_box.height / 2)); + int corner_width = MAX(0, MIN(rc.resize_corner_range, view_box.width / 2)); + bool left = cursor->x < view_box.x + corner_width; + bool right = cursor->x > view_box.x + view_box.width - corner_width; + bool top = cursor->y < view_box.y + corner_height; + bool bottom = cursor->y > view_box.y + view_box.height - corner_height; + + if (top && left) { + return LAB_SSD_PART_CORNER_TOP_LEFT; + } else if (top && right) { + return LAB_SSD_PART_CORNER_TOP_RIGHT; + } else if (bottom && left) { + return LAB_SSD_PART_CORNER_BOTTOM_LEFT; + } else if (bottom && right) { + return LAB_SSD_PART_CORNER_BOTTOM_RIGHT; + } else if (top) { + return LAB_SSD_PART_TOP; + } else if (bottom) { + return LAB_SSD_PART_BOTTOM; + } else if (left) { + return LAB_SSD_PART_LEFT; + } else if (right) { + return LAB_SSD_PART_RIGHT; + } + + return LAB_SSD_NONE; +} + enum ssd_part_type -ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) +ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node, + struct wlr_cursor *cursor) { if (!node) { return LAB_SSD_NONE; @@ -121,25 +182,25 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) part_list = &ssd->border.inactive.parts; } + enum ssd_part_type part_type = LAB_SSD_NONE; + if (part_list) { struct ssd_part *part; wl_list_for_each(part, part_list, link) { if (node == part->node) { - return part->type; + part_type = part->type; + break; } } } - return LAB_SSD_NONE; -} -enum ssd_part_type -ssd_at(const struct ssd *ssd, struct wlr_scene *scene, double lx, double ly) -{ - assert(scene); - double sx, sy; - struct wlr_scene_node *node = wlr_scene_node_at( - &scene->tree.node, lx, ly, &sx, &sy); - return ssd_get_part_type(ssd, node); + if (part_type == LAB_SSD_NONE) { + return part_type; + } + + /* Perform cursor-based context checks */ + enum ssd_part_type resizing_type = get_resizing_type(ssd, cursor); + return resizing_type != LAB_SSD_NONE ? resizing_type : part_type; } uint32_t diff --git a/src/theme.c b/src/theme.c index 511bc923..51468e02 100644 --- a/src/theme.c +++ b/src/theme.c @@ -1388,6 +1388,10 @@ post_processing(struct theme *theme) rc.corner_radius = theme->titlebar_height - 1; } + if (rc.resize_corner_range < 0) { + rc.resize_corner_range = theme->titlebar_height / 2; + } + int min_button_hover_radius = MIN(theme->window_button_width, theme->window_button_height) / 2; if (theme->window_button_hover_bg_corner_radius > min_button_hover_radius) {