mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
ssd: fix resizing on border corners and add <resize><cornerRange>
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>
This commit is contained in:
parent
9ad6e3c68c
commit
950337b895
9 changed files with 102 additions and 60 deletions
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@
|
|||
<popupShow>Never</popupShow>
|
||||
<!-- Let client redraw its contents while resizing -->
|
||||
<drawContents>yes</drawContents>
|
||||
<cornerRange>8</cornerRange>
|
||||
</resize>
|
||||
|
||||
<focus>
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ struct rcxml {
|
|||
|
||||
enum resize_indicator_mode resize_indicator;
|
||||
bool resize_draw_contents;
|
||||
int resize_corner_range;
|
||||
|
||||
struct {
|
||||
int popuptime;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue