diff --git a/include/sway/config.h b/include/sway/config.h index 473f723b..59f22ae2 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -181,6 +181,12 @@ struct seat_attachment_config { // TODO other things are configured here for some reason }; +enum seat_config_hide_cursor_when_typing { + HIDE_WHEN_TYPING_DEFAULT, // the default is currently disabled + HIDE_WHEN_TYPING_ENABLE, + HIDE_WHEN_TYPING_DISABLE, +}; + enum seat_config_allow_constrain { CONSTRAIN_DEFAULT, // the default is currently enabled CONSTRAIN_ENABLE, @@ -216,6 +222,7 @@ struct seat_config { int fallback; // -1 means not set list_t *attachments; // list of seat_attachment configs int hide_cursor_timeout; + enum seat_config_hide_cursor_when_typing hide_cursor_when_typing; enum seat_config_allow_constrain allow_constrain; enum seat_config_shortcuts_inhibit shortcuts_inhibit; enum seat_keyboard_grouping keyboard_grouping; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 4c130faf..ca3c6f4b 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -6,6 +6,7 @@ #include #include #include "sway/input/seat.h" +#include "config.h" #define SWAY_CURSOR_PRESSED_BUTTONS_CAP 32 @@ -68,6 +69,10 @@ struct sway_cursor { struct wl_event_source *hide_source; bool hidden; + // This field is just a cache of the field in seat_config in order to avoid + // costly seat_config lookups on every keypress. HIDE_WHEN_TYPING_DEFAULT + // indicates that there is no cached value. + enum seat_config_hide_cursor_when_typing hide_when_typing; size_t pressed_button_count; }; @@ -94,6 +99,7 @@ void cursor_handle_activity(struct sway_cursor *cursor, struct wlr_input_device *device); void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); +void cursor_notify_key_press(struct sway_cursor *cursor); void dispatch_cursor_button(struct sway_cursor *cursor, struct wlr_input_device *device, uint32_t time_msec, uint32_t button, diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c index 3bfce697..e09b82d9 100644 --- a/sway/commands/seat/hide_cursor.c +++ b/sway/commands/seat/hide_cursor.c @@ -3,26 +3,48 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" +#include "sway/server.h" #include "stringop.h" +#include "util.h" struct cmd_results *seat_cmd_hide_cursor(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "hide_cursor", EXPECTED_EQUAL_TO, 1))) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->handler_context.seat_config) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_MOST, 2))) { + return error; + } + struct seat_config *seat_config = config->handler_context.seat_config; + if (!seat_config) { return cmd_results_new(CMD_FAILURE, "No seat defined"); } - char *end; - int timeout = strtol(argv[0], &end, 10); - if (*end) { - return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + if (argc == 1) { + char *end; + int timeout = strtol(argv[0], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + } + if (timeout < 100 && timeout != 0) { + timeout = 100; + } + seat_config->hide_cursor_timeout = timeout; + } else { + if (strcmp(argv[0], "when-typing") != 0) { + return cmd_results_new(CMD_INVALID, + "Expected 'hide_cursor |when-typing [enable|disable]'"); + } + seat_config->hide_cursor_when_typing = parse_boolean(argv[1], true) ? + HIDE_WHEN_TYPING_ENABLE : HIDE_WHEN_TYPING_DISABLE; + + // Invalidate all the caches for this config + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + seat->cursor->hide_when_typing = HIDE_WHEN_TYPING_DEFAULT; + } } - if (timeout < 100 && timeout != 0) { - timeout = 100; - } - config->handler_context.seat_config->hide_cursor_timeout = timeout; return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config/seat.c b/sway/config/seat.c index e2702de5..84260aa3 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -29,6 +29,7 @@ struct seat_config *new_seat_config(const char* name) { return NULL; } seat->hide_cursor_timeout = -1; + seat->hide_cursor_when_typing = HIDE_WHEN_TYPING_DEFAULT; seat->allow_constrain = CONSTRAIN_DEFAULT; seat->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT; @@ -151,6 +152,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { dest->hide_cursor_timeout = source->hide_cursor_timeout; } + if (source->hide_cursor_when_typing != HIDE_WHEN_TYPING_DEFAULT) { + dest->hide_cursor_when_typing = source->hide_cursor_when_typing; + } + if (source->allow_constrain != CONSTRAIN_DEFAULT) { dest->allow_constrain = source->allow_constrain; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index e47410a5..b168afc5 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -253,6 +253,32 @@ int cursor_get_timeout(struct sway_cursor *cursor) { return timeout; } +void cursor_notify_key_press(struct sway_cursor *cursor) { + if (cursor->hidden) { + return; + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + // No cached value, need to lookup in the seat_config + const struct seat_config *seat_config = seat_get_config(cursor->seat); + if (!seat_config) { + seat_config = seat_get_config_by_name("*"); + if (!seat_config) { + return; + } + } + cursor->hide_when_typing = seat_config->hide_cursor_when_typing; + // The default is currently disabled + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + cursor->hide_when_typing = HIDE_WHEN_TYPING_DISABLE; + } + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_ENABLE) { + cursor_hide(cursor); + } +} + static enum sway_input_idle_source idle_source_from_device( struct wlr_input_device *device) { switch (device->type) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 541fc90d..ae30e83a 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -13,6 +13,7 @@ #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" #include "sway/ipc-server.h" #include "log.h" @@ -392,6 +393,10 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; + if (event->state == WLR_KEY_PRESSED) { + cursor_notify_key_press(seat->cursor); + } + // Identify new keycode, raw keysym(s), and translated keysym(s) struct key_info keyinfo; update_keyboard_state(keyboard, event->keycode, event->state, &keyinfo); diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index d8180c1c..dbf21d93 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -229,11 +229,16 @@ correct seat. Set this seat as the fallback seat. A fallback seat will attach any device not explicitly attached to another seat (similar to a "default" seat). -*seat* hide_cursor - Hides the cursor image after the specified _timeout_ (in milliseconds) - has elapsed with no activity on that cursor. A timeout of 0 (default) - disables hiding the cursor. The minimal timeout is 100 and any value less - than that (aside from 0), will be increased to 100. +*seat* hide_cursor |when-typing [enable|disable] + Hides the cursor image after the specified event occured. + + If _timeout_ is specified, then the cursor will be hidden after _timeout_ + (in milliseconds) has elapsed with no activity on the cursor. A timeout of 0 + (default) disables hiding the cursor. The minimal timeout is 100 and any + value less than that (aside from 0), will be increased to 100. + + If _when-typing_ is enabled, then the cursor will be hidden whenever a key + is pressed. *seat* idle_inhibit Sets the set of input event sources which can prevent the seat from