ssd: eliminate corner extents and correct corner behavior

This commit is contained in:
Andrew J. Hesford 2025-01-29 10:58:44 -05:00
parent 9a473f1848
commit 11c70c716d
9 changed files with 93 additions and 82 deletions

View file

@ -512,6 +512,12 @@ extending outward from the snapped edge.
*<theme><cornerRadius>*
The radius of server side decoration top corners. Default is 8.
*<theme><cornerSize>*
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.
*<theme><keepBorder>* [yes|no]
Even when disabling server side decorations via ToggleDecorations,
keep a small border (and resize area) around the window. Default is yes.

View file

@ -36,6 +36,7 @@
<showTitle>yes</showTitle>
</titlebar>
<cornerRadius>8</cornerRadius>
<cornerSize>8</cornerSize>
<keepBorder>yes</keepBorder>
<dropShadows>no</dropShadows>
<font place="ActiveWindow">

View file

@ -88,6 +88,7 @@ struct rcxml {
struct wl_list title_buttons_left;
struct wl_list title_buttons_right;
int corner_radius;
int corner_size;
bool show_title;
bool title_layout_loaded;
bool ssd_keep_border;

View file

@ -3,6 +3,9 @@
#define LABWC_SSD_H
#include <wayland-server-core.h>
#include <wlr/types/wlr_cursor.h>
#include "action.h"
#include "common/border.h"
#define SSD_EXTENDED_AREA 8
@ -111,8 +114,9 @@ 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);
uint32_t ssd_resize_edges(enum ssd_part_type type);
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
uint32_t ssd_resize_edges(struct cursor_context *ctx, struct wlr_cursor *cursor);
bool ssd_part_contains(enum ssd_part_type candidate,
struct cursor_context *ctx, struct wlr_cursor *cursor);
enum ssd_mode ssd_mode_parse(const char *mode);
/* TODO: clean up / update */

View file

@ -682,8 +682,7 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
x = extent.x;
y = view->current.y;
/* Push the client menu underneath the button */
if (is_client_menu && ssd_part_contains(
LAB_SSD_BUTTON, ctx->type)) {
if (is_client_menu && ssd_part_contains(LAB_SSD_BUTTON, ctx, NULL)) {
assert(ctx->node);
int lx, ly;
wlr_scene_node_coords(ctx->node, &lx, &ly);

View file

@ -1081,6 +1081,8 @@ entry(xmlNode *node, char *nodename, char *content)
rc.show_title = parse_bool(content, true);
} else if (!strcmp(nodename, "cornerradius.theme")) {
rc.corner_radius = atoi(content);
} else if (!strcmp(nodename, "cornersize.theme")) {
rc.corner_size = MAX(0, atoi(content));
} else if (!strcasecmp(nodename, "keepBorder.theme")) {
set_bool(content, &rc.ssd_keep_border);
} else if (!strcasecmp(nodename, "dropShadows.theme")) {
@ -1429,6 +1431,7 @@ rcxml_init(void)
rc.title_layout_loaded = false;
rc.ssd_keep_border = true;
rc.corner_radius = 8;
rc.corner_size = 8;
rc.shadows_enabled = false;
rc.gap = 0;

View file

@ -103,13 +103,6 @@ cursor_get_from_edge(uint32_t resize_edges)
return LAB_CURSOR_DEFAULT;
}
static enum lab_cursors
cursor_get_from_ssd(enum ssd_part_type view_area)
{
uint32_t resize_edges = ssd_resize_edges(view_area);
return cursor_get_from_edge(resize_edges);
}
static struct wlr_surface *
get_toplevel(struct wlr_surface *surface)
{
@ -546,7 +539,9 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
*/
wlr_seat_pointer_notify_clear_focus(wlr_seat);
if (!seat->drag.active) {
enum lab_cursors cursor = cursor_get_from_ssd(ctx->type);
uint32_t resize_edge =
ssd_resize_edges(ctx, server->seat.cursor);
enum lab_cursors cursor = cursor_get_from_edge(resize_edge);
if (ctx->view && ctx->view->shaded && cursor > LAB_CURSOR_GRAB) {
/* Prevent resize cursor on borders for shaded SSD */
cursor = LAB_CURSOR_DEFAULT;
@ -560,7 +555,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
uint32_t
cursor_get_resize_edges(struct wlr_cursor *cursor, struct cursor_context *ctx)
{
uint32_t resize_edges = ssd_resize_edges(ctx->type);
uint32_t resize_edges = ssd_resize_edges(ctx, cursor);
if (ctx->view && !resize_edges) {
struct wlr_box box = ctx->view->current;
resize_edges |=
@ -898,7 +893,7 @@ handle_release_mousebinding(struct server *server,
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
wl_list_for_each(mousebind, &rc.mousebinds, link) {
if (ssd_part_contains(mousebind->context, ctx->type)
if (ssd_part_contains(mousebind->context, ctx, server->seat.cursor)
&& mousebind->button == button
&& modifiers == mousebind->modifiers) {
switch (mousebind->mouse_event) {
@ -965,7 +960,7 @@ handle_press_mousebinding(struct server *server, struct cursor_context *ctx,
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
wl_list_for_each(mousebind, &rc.mousebinds, link) {
if (ssd_part_contains(mousebind->context, ctx->type)
if (ssd_part_contains(mousebind->context, ctx, server->seat.cursor)
&& mousebind->button == button
&& modifiers == mousebind->modifiers) {
switch (mousebind->mouse_event) {
@ -1325,7 +1320,7 @@ handle_cursor_axis(struct server *server, struct cursor_context *ctx,
}
wl_list_for_each(mousebind, &rc.mousebinds, link) {
if (ssd_part_contains(mousebind->context, ctx->type)
if (ssd_part_contains(mousebind->context, ctx, server->seat.cursor)
&& mousebind->direction == direction
&& modifiers == mousebind->modifiers
&& mousebind->mouse_event == MOUSE_ACTION_SCROLL) {

View 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:
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);

View file

@ -143,20 +143,30 @@ ssd_at(const struct ssd *ssd, struct wlr_scene *scene, double lx, double ly)
}
uint32_t
ssd_resize_edges(enum ssd_part_type type)
ssd_resize_edges(struct cursor_context *ctx, struct wlr_cursor *cursor)
{
switch (type) {
assert(ctx);
struct view *view = ctx->view;
uint32_t edge = WLR_EDGE_NONE;
switch (ctx->type) {
case LAB_SSD_PART_TOP:
return WLR_EDGE_TOP;
edge = WLR_EDGE_TOP;
break;
case LAB_SSD_PART_RIGHT:
return WLR_EDGE_RIGHT;
edge = WLR_EDGE_RIGHT;
break;
case LAB_SSD_PART_BOTTOM:
return WLR_EDGE_BOTTOM;
edge = WLR_EDGE_BOTTOM;
break;
case LAB_SSD_PART_LEFT:
return WLR_EDGE_LEFT;
edge = WLR_EDGE_LEFT;
break;
case LAB_SSD_PART_CORNER_TOP_LEFT:
case LAB_SSD_PART_TITLEBAR_CORNER_LEFT:
return WLR_EDGE_TOP | WLR_EDGE_LEFT;
case LAB_SSD_PART_CORNER_TOP_RIGHT:
case LAB_SSD_PART_TITLEBAR_CORNER_RIGHT:
return WLR_EDGE_RIGHT | WLR_EDGE_TOP;
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
return WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT;
@ -165,6 +175,32 @@ ssd_resize_edges(enum ssd_part_type type)
default:
return WLR_EDGE_NONE;
}
if (!view || !cursor || !view->ssd) {
return edge;
}
if (edge == WLR_EDGE_BOTTOM || edge == WLR_EDGE_TOP) {
int width = view->current.width;
int corner_size = MAX(0, MIN(rc.corner_size, width / 2));
if (cursor->x < view->current.x + corner_size) {
edge |= WLR_EDGE_LEFT;
} else if (cursor->x > view->current.x + width - corner_size) {
edge |= WLR_EDGE_RIGHT;
}
} else if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
int height = view_effective_height(view, /* use_pending */ false);
int corner_size = MAX(0, MIN(rc.corner_size, height / 2));
if (cursor->y < view->current.y + corner_size) {
edge |= WLR_EDGE_TOP;
} else if (cursor->y > view->current.y + height - corner_size) {
edge |= WLR_EDGE_BOTTOM;
}
}
return edge;
}
struct ssd *
@ -305,8 +341,11 @@ ssd_destroy(struct ssd *ssd)
}
bool
ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate)
ssd_part_contains(enum ssd_part_type whole,
struct cursor_context *ctx, struct wlr_cursor *cursor)
{
assert(ctx);
enum ssd_part_type candidate = ctx->type;
if (whole == candidate || whole == LAB_SSD_ALL) {
return true;
}
@ -327,22 +366,21 @@ ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate)
return candidate >= LAB_SSD_BUTTON_CLOSE
&& candidate <= LAB_SSD_CLIENT;
}
if (whole == LAB_SSD_PART_TOP) {
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT
|| candidate == LAB_SSD_PART_CORNER_TOP_RIGHT;
}
if (whole == LAB_SSD_PART_RIGHT) {
return candidate == LAB_SSD_PART_CORNER_TOP_RIGHT
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT;
}
if (whole == LAB_SSD_PART_BOTTOM) {
return candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
}
if (whole == LAB_SSD_PART_LEFT) {
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
/* Perform corner tests if necessary */
switch (whole) {
case LAB_SSD_PART_CORNER_TOP_LEFT:
return ssd_resize_edges(ctx, cursor) == (WLR_EDGE_TOP | WLR_EDGE_LEFT);
case LAB_SSD_PART_CORNER_TOP_RIGHT:
return ssd_resize_edges(ctx, cursor) == (WLR_EDGE_TOP | WLR_EDGE_RIGHT);
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
return ssd_resize_edges(ctx, cursor) == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT);
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
return ssd_resize_edges(ctx, cursor) == (WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT);
default:
break;
}
return false;
}