From e98406168def2762670a6818cb4dc66be61e7852 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 1 Feb 2025 14:51:47 +0900 Subject: [PATCH] ssd: fix resizing on border corners and add Co-authored-by: @ahesford The direction of resizing was determined based on the hovered ssd component (e.g. left border, top-left extent), but it caused problems when trying to start resizing by pressing the corners of the window border; the resizing direction was always unidirectional at bottom corners and resizing cannot be started by pressing top corners. This commit fixes this weirdness by determining resize directions only based on the window geometry and the cursor position. The corner extents are removed as they are not longer needed. This commit also adds which configures the range of corner resizing on the borders/extent. --- docs/labwc-config.5.scd | 6 ++++ docs/rc.xml.all | 1 + include/config/rcxml.h | 1 + include/ssd.h | 6 ++-- src/config/rcxml.c | 3 ++ src/desktop.c | 3 +- src/ssd/ssd-extents.c | 52 +++++----------------------- src/ssd/ssd.c | 76 +++++++++++++++++++++++++++++++++++------ 8 files changed, 89 insertions(+), 59 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 1c160a45..c274a0d2 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -576,6 +576,12 @@ 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 8. + ## KEYBOARD ** [on|off] diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 16f5c212..02a9be9e 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 9aa6c9ba..264326e6 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 0dfdc604..2193336c 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1220,6 +1220,8 @@ entry(xmlNode *node, char *nodename, char *content) } } else if (!strcasecmp(nodename, "drawContents.resize")) { set_bool(content, &rc.resize_draw_contents); + } else if (!strcasecmp(nodename, "cornerRange.resize")) { + rc.resize_corner_range = MAX(0, atoi(content)); } else if (!strcasecmp(nodename, "mouseEmulation.tablet")) { set_bool(content, &rc.tablet.force_mouse_emulation); } else if (!strcasecmp(nodename, "mapToOutput.tablet")) { @@ -1492,6 +1494,7 @@ rcxml_init(void) rc.resize_indicator = LAB_RESIZE_INDICATOR_NEVER; rc.resize_draw_contents = true; + rc.resize_corner_range = 8; 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: + case LAB_SSD_PART_TOP: 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.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..ae2c06de 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -74,8 +74,63 @@ ssd_max_extents(struct view *view) }; } +/* + * Returns a part type representing mouse contexts like 'Left' and 'TLCorner' + * based on the view geometry and cursor position + */ +static enum ssd_part_type +get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor) +{ + assert(ssd); + assert(cursor); + struct view *view = ssd->view; + + if (!view || !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_enabled && !view->fullscreen && !view->ssd_titlebar_hidden) { + 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)) { + 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; @@ -86,6 +141,15 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) return LAB_SSD_NONE; } + /* + * Detect some mouse context (e.g. 'Left', 'TLCorner') from cursor + * position, not from node->type + */ + enum ssd_part_type resizing_type = get_resizing_type(ssd, cursor); + if (resizing_type != LAB_SSD_NONE) { + return resizing_type; + } + const struct wl_list *part_list = NULL; struct wlr_scene_tree *grandparent = node->parent ? node->parent->node.parent : NULL; @@ -132,16 +196,6 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) 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); -} - uint32_t ssd_resize_edges(enum ssd_part_type type) {