]> git.mdlowis.com Git - proto/labwc.git/commitdiff
ssd: fix resizing on border corners and add <resize><cornerRange>
authortokyo4j <hrak1529@gmail.com>
Sat, 1 Feb 2025 05:51:47 +0000 (14:51 +0900)
committerAndrew J. Hesford <ajh@sideband.org>
Tue, 4 Feb 2025 16:13:32 +0000 (11:13 -0500)
Eliminate corner extents and instead use cursor position to map SSD
borders and extents to corner contexts, with a size configurable by the
<resize><cornerRange> 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 <ajh@sideband.org>
docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
include/ssd.h
src/config/rcxml.c
src/desktop.c
src/ssd/ssd-extents.c
src/ssd/ssd.c
src/theme.c

index 23b5df3765cfa95f78ab00ace4ab2b8b5028dcd5..9be38e80b5deda1149801c41118b5e39cd3a350d 100644 (file)
@@ -576,6 +576,13 @@ extending outward from the snapped edge.
        outlined rectangle is shown to indicate the geometry of resized window.
        Default is yes.
 
+*<resize><cornerRange>*
+       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
 
 *<keyboard><numlock>* [on|off]
index 8ea2710bf276d516b5d04ef512309c1c999e37f2..31ddb6d769bcd5f891ccd6cb17ecaf924d640c71 100644 (file)
     <popupShow>Never</popupShow>
     <!-- Let client redraw its contents while resizing -->
     <drawContents>yes</drawContents>
+    <cornerRange>8</cornerRange>
   </resize>
 
   <focus>
index 208b73e0d005d430c411a6ccc29f32535d5b581c..0b9c0dc9a00b66df150f7447da1489ce2d6649d5 100644 (file)
@@ -151,6 +151,7 @@ struct rcxml {
 
        enum resize_indicator_mode resize_indicator;
        bool resize_draw_contents;
+       int resize_corner_range;
 
        struct {
                int popuptime;
index fe56be54c8a063d8818d4c0dc947c2fb84e04307..3c0231211ffcccbd13d0c7fc3da47c1da935039b 100644 (file)
@@ -5,6 +5,8 @@
 #include <wayland-server-core.h>
 #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);
index 0b606a2a78967d97de558ed4a915ce83d2e7acff..eebf695688ae5c814be402c3bf54fede2a4c5ac4 100644 (file)
@@ -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;
index 5a78bffa48fe2504d3914dfec199d7f74dedee92..e3380705043cd5ce4c0bb7ec71fc5f089dd402be 100644 (file)
@@ -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);
                                }
index 1a0ed3518b34d8f5221ffa11232ecaaf0e42b068..e88b58ead7631d93a5762430760f1a3b7fc17175 100644 (file)
@@ -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);
index 49f088b7f6464fe20246c1b8edb1a27a71d66c26..65416ca32d0b5a61714ec3bd248f83e9d16695f7 100644 (file)
@@ -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
index 511bc92326f29bebaa0f228e056b91f2051c8866..51468e020c5a7d434a9c6f8d1c8e76ee04eda3c4 100644 (file)
@@ -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) {