cursor: Use enum for server set cursor names

This mainly prevents having to use strcmp() on every mouse move.
This commit is contained in:
Consolatis 2022-09-16 02:23:44 +02:00 committed by Johan Malm
parent f491942858
commit e30fce6c34
5 changed files with 110 additions and 76 deletions

View file

@ -66,9 +66,9 @@ struct cursor_context get_cursor_context(struct server *server);
/**
* cursor_set - set cursor icon
* @seat - current seat
* @cursor_name - name of cursor, for example "left_ptr" or "grab"
* @cursor - name of cursor, for example LAB_CURSOR_DEFAULT or LAB_CURSOR_GRAB
*/
void cursor_set(struct seat *seat, const char *cursor_name);
void cursor_set(struct seat *seat, enum lab_cursors cursor);
/**
* cursor_get_resize_edges - calculate resize edge based on cursor position
@ -84,6 +84,18 @@ void cursor_set(struct seat *seat, const char *cursor_name);
uint32_t cursor_get_resize_edges(struct wlr_cursor *cursor,
struct cursor_context *ctx);
/**
* cursor_get_from_edge - translate wlroots edge enum to lab_cursor enum
* @resize_edges - WLR_EDGE_ combination like WLR_EDGE_TOP | WLR_EDGE_RIGHT
*
* Returns LAB_CURSOR_DEFAULT on WLR_EDGE_NONE
* Returns the appropriate lab_cursors enum if @resize_edges
* is one of the 4 corners or one of the 4 edges.
*
* Asserts on invalid edge combinations like WLR_EDGE_LEFT | WLR_EDGE_RIGHT
*/
enum lab_cursors cursor_get_from_edge(uint32_t resize_edges);
/**
* cursor_update_focus - update cursor focus, may update the cursor icon
* @server - server

View file

@ -59,7 +59,6 @@
#define XCURSOR_DEFAULT "left_ptr"
#define XCURSOR_SIZE 24
#define XCURSOR_MOVE "grabbing"
enum input_mode {
LAB_INPUT_STATE_PASSTHROUGH = 0,
@ -80,13 +79,12 @@ struct seat {
struct server *server;
struct wlr_keyboard_group *keyboard_group;
bool cursor_requires_fallback;
/*
* Name of most recent server-side cursor image. Set by
* Enum of most recent server-side cursor image. Set by
* cursor_set(). Cleared when a client surface is entered
* (in that case the client is expected to set a cursor image).
* (in that case the client is expected to set its own cursor image).
*/
char *cursor_set_by_server;
enum lab_cursors server_cursor;
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_manager;

View file

@ -12,28 +12,84 @@
#include "ssd.h"
#include "config/mousebind.h"
#include "common/scene-helpers.h"
#include "common/zfree.h"
static const struct cursor_alias {
const char *name, *alias;
} cursor_aliases[] = {
{ "default", "left_ptr" },
{ "text", "xterm" },
{ "grab", "grabbing" },
{ "pointer", "hand1" },
{ "wait", "watch" },
{ "all-scroll", "grabbing" },
/* Resize edges */
{ "nw-resize", "top_left_corner" },
{ "n-resize", "top_side" },
{ "ne-resize", "top_right_corner" },
{ "e-resize", "right_side" },
{ "se-resize", "bottom_right_corner" },
{ "s-resize", "bottom_side" },
{ "sw-resize", "bottom_left_corner" },
{ "w-resize", "left_side" },
static const char **cursor_names = NULL;
/* Usual cursor names */
static const char *cursors_xdg[] = {
NULL,
"default",
"grab",
"nw-resize",
"n-resize",
"ne-resize",
"e-resize",
"se-resize",
"s-resize",
"sw-resize",
"w-resize"
};
/* XCursor fallbacks */
static const char *cursors_x11[] = {
NULL,
"left_ptr",
"grabbing",
"top_left_corner",
"top_side",
"top_right_corner",
"right_side",
"bottom_right_corner",
"bottom_side",
"bottom_left_corner",
"left_side"
};
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
static_assert(
ARRAY_SIZE(cursors_xdg) == LAB_CURSOR_COUNT,
"XDG cursor names are out ot sync");
static_assert(
ARRAY_SIZE(cursors_x11) == LAB_CURSOR_COUNT,
"X11 cursor names are out ot sync");
#undef ARRAY_SIZE
enum lab_cursors
cursor_get_from_edge(uint32_t resize_edges)
{
switch (resize_edges) {
case WLR_EDGE_NONE:
return LAB_CURSOR_DEFAULT;
case WLR_EDGE_TOP | WLR_EDGE_LEFT:
return LAB_CURSOR_RESIZE_NW;
case WLR_EDGE_TOP:
return LAB_CURSOR_RESIZE_N;
case WLR_EDGE_TOP | WLR_EDGE_RIGHT:
return LAB_CURSOR_RESIZE_NE;
case WLR_EDGE_RIGHT:
return LAB_CURSOR_RESIZE_E;
case WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT:
return LAB_CURSOR_RESIZE_SE;
case WLR_EDGE_BOTTOM:
return LAB_CURSOR_RESIZE_S;
case WLR_EDGE_BOTTOM | WLR_EDGE_LEFT:
return LAB_CURSOR_RESIZE_SW;
case WLR_EDGE_LEFT:
return LAB_CURSOR_RESIZE_W;
default:
wlr_log(WLR_ERROR,
"Failed to resolve wlroots edge %u to cursor name", resize_edges);
assert(false);
}
}
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)
{
@ -185,52 +241,19 @@ process_cursor_resize(struct server *server, uint32_t time)
view_move_resize(view, new_view_geo);
}
static const char *
cursor_name_fallback(struct wlr_xcursor_manager *manager, const char *name)
{
if (wlr_xcursor_manager_get_xcursor(manager, name, 1)) {
return name;
}
for (size_t i = 0; i < sizeof(cursor_aliases) / sizeof(cursor_aliases[0]); i++) {
if (!strcmp(cursor_aliases[i].name, name)) {
return cursor_aliases[i].alias;
}
}
return name;
}
void
cursor_set(struct seat *seat, const char *cursor_name)
cursor_set(struct seat *seat, enum lab_cursors cursor)
{
/*
* Required until wlroots MR !3651 is merged.
* Once that happened, the whole commit can be reverted.
*/
if (seat->cursor_requires_fallback) {
cursor_name = cursor_name_fallback(seat->xcursor_manager, cursor_name);
}
assert(cursor > LAB_CURSOR_CLIENT && cursor < LAB_CURSOR_COUNT);
/* Prevent setting the same cursor image twice */
if (seat->cursor_set_by_server && !strcmp(cursor_name,
seat->cursor_set_by_server)) {
if (seat->server_cursor == cursor) {
return;
}
wlr_xcursor_manager_set_cursor_image(
seat->xcursor_manager, cursor_name, seat->cursor);
zfree(seat->cursor_set_by_server);
seat->cursor_set_by_server = strdup(cursor_name);
}
static void
set_server_cursor(struct seat *seat, enum ssd_part_type view_area)
{
uint32_t resize_edges = ssd_resize_edges(view_area);
if (resize_edges) {
cursor_set(seat, wlr_xcursor_get_resize_name(resize_edges));
} else {
cursor_set(seat, XCURSOR_DEFAULT);
}
seat->xcursor_manager, cursor_names[cursor], seat->cursor);
seat->server_cursor = cursor;
}
bool
@ -346,7 +369,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
* in response to the enter event.
*/
if (ctx->surface != wlr_seat->pointer_state.focused_surface
|| seat->cursor_set_by_server) {
|| seat->server_cursor != LAB_CURSOR_CLIENT) {
/*
* Enter the surface if necessary. Usually we
* prevent re-entering an already focused
@ -361,7 +384,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
wlr_seat_pointer_notify_clear_focus(wlr_seat);
wlr_seat_pointer_notify_enter(wlr_seat, ctx->surface,
ctx->sx, ctx->sy);
zfree(seat->cursor_set_by_server);
seat->server_cursor = LAB_CURSOR_CLIENT;
}
if (cursor_has_moved) {
wlr_seat_pointer_notify_motion(wlr_seat, time_msec,
@ -374,7 +397,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
* set the cursor image ourselves.
*/
wlr_seat_pointer_notify_clear_focus(wlr_seat);
set_server_cursor(seat, ctx->type);
cursor_set(seat, cursor_get_from_ssd(ctx->type));
}
}
@ -411,7 +434,7 @@ process_cursor_motion(struct server *server, uint32_t time)
if (ctx.type == LAB_SSD_MENU) {
menu_process_cursor_motion(ctx.node);
set_server_cursor(seat, ctx.type);
cursor_set(&server->seat, LAB_CURSOR_DEFAULT);
return;
}
@ -983,11 +1006,13 @@ cursor_init(struct seat *seat)
seat->xcursor_manager = wlr_xcursor_manager_create(xcursor_theme, size);
wlr_xcursor_manager_load(seat->xcursor_manager, 1);
/* Check if we need to run every cursor_set() through translation */
if (strcmp("grab", cursor_name_fallback(seat->xcursor_manager, "grab"))) {
seat->cursor_requires_fallback = true;
if (wlr_xcursor_manager_get_xcursor(seat->xcursor_manager,
cursors_xdg[LAB_CURSOR_DEFAULT], 1)) {
cursor_names = cursors_xdg;
} else {
wlr_log(WLR_INFO,
"Cursor theme is missing cursor names, using fallbacks");
"Cursor theme is missing cursor names, using fallback");
cursor_names = cursors_x11;
}
seat->cursor_motion.notify = cursor_motion;

View file

@ -84,10 +84,10 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
switch (mode) {
case LAB_INPUT_STATE_MOVE:
cursor_set(&server->seat, "grab");
cursor_set(&server->seat, LAB_CURSOR_GRAB);
break;
case LAB_INPUT_STATE_RESIZE:
cursor_set(&server->seat, wlr_xcursor_get_resize_name(edges));
cursor_set(&server->seat, cursor_get_from_edge(edges));
break;
default:
break;

View file

@ -141,9 +141,8 @@ ssd_resize_edges(enum ssd_part_type type)
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
return WLR_EDGE_BOTTOM | WLR_EDGE_LEFT;
default:
break;
return WLR_EDGE_NONE;
}
return 0;
}
void