cursor: implement <menu><ignoreButtonReleasePeriod>

Addresses UX degradation introduced by commit 1d3ed457.

This prevents clicks with small movement with the intention of opening
the menu from unexpectedly closing the menu or selecting a menu item.
This commit is contained in:
tokyo4j 2024-04-26 09:03:17 +09:00 committed by Hiroaki Yamamoto
parent 96d5d80be2
commit 4b6efb7307
5 changed files with 47 additions and 6 deletions

View file

@ -891,6 +891,24 @@ situation.
can be caused by *<margin>* settings or exclusive layer-shell clients can be caused by *<margin>* settings or exclusive layer-shell clients
such as panels. such as panels.
## MENU
```
<menu>
<ignoreButtonReleasePeriod>250</ignoreButtonReleasePeriod>
</menu>
```
*<menu><ignoreButtonReleasePeriod>*
How long (in milliseconds) the initial button release event is ignored
for. The reason for this logic and behaviour is to avoid a fast
press-move-release sequence indended to just open the menu resulting in
the closure of the menu or the selection of (typically the first) menu
item. This behaviour only affects the first button-release. It is not
anticipated that most users will want to change this, but the config
option has been exposed for unusual use-cases. It is equivalent to
Openbox's `<hideDelay>`. Default is 250 ms.
## ENVIRONMENT VARIABLES ## ENVIRONMENT VARIABLES
*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme *XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme

View file

@ -586,4 +586,7 @@
</windowRules> </windowRules>
--> -->
<menu>
<ignoreButtonReleasePeriod>250</ignoreButtonReleasePeriod>
</menu>
</labwc_config> </labwc_config>

View file

@ -137,6 +137,9 @@ struct rcxml {
} window_switcher; } window_switcher;
struct wl_list window_rules; /* struct window_rule.link */ struct wl_list window_rules; /* struct window_rule.link */
/* Menu */
unsigned int menu_ignore_button_release_period;
}; };
extern struct rcxml rc; extern struct rcxml rc;

View file

@ -1034,6 +1034,8 @@ entry(xmlNode *node, char *nodename, char *content)
} else { } else {
wlr_log(WLR_ERROR, "Missing 'button' argument for tablet button mapping"); wlr_log(WLR_ERROR, "Missing 'button' argument for tablet button mapping");
} }
} else if (!strcasecmp(nodename, "ignoreButtonReleasePeriod.menu")) {
rc.menu_ignore_button_release_period = atoi(content);
} }
} }
@ -1238,6 +1240,8 @@ rcxml_init(void)
rc.workspace_config.popuptime = INT_MIN; rc.workspace_config.popuptime = INT_MIN;
rc.workspace_config.min_nr_workspaces = 1; rc.workspace_config.min_nr_workspaces = 1;
rc.menu_ignore_button_release_period = 250;
} }
static void static void

View file

@ -929,6 +929,8 @@ handle_press_mousebinding(struct server *server, struct cursor_context *ctx,
return consumed_by_frame_context; return consumed_by_frame_context;
} }
static uint32_t press_msec;
static void static void
cursor_button_press(struct seat *seat, uint32_t button, cursor_button_press(struct seat *seat, uint32_t button,
enum wlr_button_state button_state, uint32_t time_msec) enum wlr_button_state button_state, uint32_t time_msec)
@ -936,6 +938,9 @@ cursor_button_press(struct seat *seat, uint32_t button,
struct server *server = seat->server; struct server *server = seat->server;
struct cursor_context ctx = get_cursor_context(server); struct cursor_context ctx = get_cursor_context(server);
/* Used on next button release to check if it can close menu or select menu item */
press_msec = time_msec;
/* Determine closest resize edges in case action is Resize */ /* Determine closest resize edges in case action is Resize */
uint32_t resize_edges = cursor_get_resize_edges(seat->cursor, &ctx); uint32_t resize_edges = cursor_get_resize_edges(seat->cursor, &ctx);
@ -946,6 +951,11 @@ cursor_button_press(struct seat *seat, uint32_t button,
} }
if (server->input_mode == LAB_INPUT_STATE_MENU) { if (server->input_mode == LAB_INPUT_STATE_MENU) {
/*
* If menu was already opened on press, set a very small value
* so subsequent release always closes menu or selects menu item.
*/
press_msec = 0;
return; return;
} }
@ -1011,12 +1021,15 @@ cursor_button_release(struct seat *seat, uint32_t button,
seat_reset_pressed(seat); seat_reset_pressed(seat);
if (server->input_mode == LAB_INPUT_STATE_MENU) { if (server->input_mode == LAB_INPUT_STATE_MENU) {
if (ctx.type == LAB_SSD_MENU) { /* TODO: take into account overflow of time_msec */
menu_call_selected_actions(server); if (time_msec - press_msec > rc.menu_ignore_button_release_period) {
} else { if (ctx.type == LAB_SSD_MENU) {
menu_close_root(server); menu_call_selected_actions(server);
cursor_update_common(server, &ctx, time_msec, } else {
/*cursor_has_moved*/ false); menu_close_root(server);
cursor_update_common(server, &ctx, time_msec,
/*cursor_has_moved*/ false);
}
} }
return; return;
} }