From bd3720585e91ae0dfcc4be30149ae4f8f5218174 Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Mon, 25 Mar 2019 22:05:49 -0400 Subject: [PATCH] Implement input type configs (#3784) Add support for configurations that apply to a type of inputs (i.e. natural scrolling on all touchpads). A type config is differentiated by a `type:` prefix followed by the type it corresponds to. When new devices appear, the device config is merged on top of its type config (if it exists). New type configs are applied on top of existing configs. --- include/sway/config.h | 2 ++ sway/config.c | 10 +++++++- sway/config/input.c | 39 ++++++++++++++++++++++++++++--- sway/input/input-manager.c | 47 +++++++++++++++++++++++++++++++++++++- sway/sway-input.5.scd | 17 +++++++++++++- 5 files changed, 109 insertions(+), 6 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index fe06fb9d..86410544 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -105,6 +105,7 @@ struct input_config_mapped_from_region { */ struct input_config { char *identifier; + const char *input_type; int accel_profile; int click_method; @@ -418,6 +419,7 @@ struct sway_config { list_t *workspace_configs; list_t *output_configs; list_t *input_configs; + list_t *input_type_configs; list_t *seat_configs; list_t *criteria; list_t *no_focus; diff --git a/sway/config.c b/sway/config.c index 4944ec02..e14ea83a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -113,6 +113,12 @@ void free_config(struct sway_config *config) { } list_free(config->input_configs); } + if (config->input_type_configs) { + for (int i = 0; i < config->input_type_configs->length; i++) { + free_input_config(config->input_type_configs->items[i]); + } + list_free(config->input_type_configs); + } if (config->seat_configs) { for (int i = 0; i < config->seat_configs->length; i++) { free_seat_config(config->seat_configs->items[i]); @@ -189,10 +195,12 @@ static void config_defaults(struct sway_config *config) { if (!(config->workspace_configs = create_list())) goto cleanup; if (!(config->criteria = create_list())) goto cleanup; if (!(config->no_focus = create_list())) goto cleanup; - if (!(config->input_configs = create_list())) goto cleanup; if (!(config->seat_configs = create_list())) goto cleanup; if (!(config->output_configs = create_list())) goto cleanup; + if (!(config->input_type_configs = create_list())) goto cleanup; + if (!(config->input_configs = create_list())) goto cleanup; + if (!(config->cmd_queue = create_list())) goto cleanup; if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) diff --git a/sway/config/input.c b/sway/config/input.c index 63c28635..aa581431 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -18,6 +18,7 @@ struct input_config *new_input_config(const char* identifier) { return NULL; } + input->input_type = NULL; input->tap = INT_MIN; input->tap_button_map = INT_MIN; input->drag = INT_MIN; @@ -140,6 +141,30 @@ static void merge_wildcard_on_all(struct input_config *wildcard) { merge_input_config(ic, wildcard); } } + + for (int i = 0; i < config->input_type_configs->length; i++) { + struct input_config *ic = config->input_type_configs->items[i]; + if (strcmp(wildcard->identifier, ic->identifier) != 0) { + sway_log(SWAY_DEBUG, "Merging input * config on %s", ic->identifier); + merge_input_config(ic, wildcard); + } + } +} + +static void merge_type_on_existing(struct input_config *type_wildcard) { + for (int i = 0; i < config->input_configs->length; i++) { + struct input_config *ic = config->input_configs->items[i]; + if (ic->input_type == NULL) { + continue; + } + + if (strcmp(ic->input_type, type_wildcard->identifier + 5) == 0) { + sway_log(SWAY_DEBUG, "Merging %s top of %s", + type_wildcard->identifier, + ic->identifier); + merge_input_config(ic, type_wildcard); + } + } } struct input_config *store_input_config(struct input_config *ic) { @@ -148,11 +173,19 @@ struct input_config *store_input_config(struct input_config *ic) { merge_wildcard_on_all(ic); } - int i = list_seq_find(config->input_configs, input_identifier_cmp, + list_t *config_list = NULL; + if (strncmp(ic->identifier, "type:", 5) == 0) { + config_list = config->input_type_configs; + merge_type_on_existing(ic); + } else { + config_list = config->input_configs; + } + + int i = list_seq_find(config_list, input_identifier_cmp, ic->identifier); if (i >= 0) { sway_log(SWAY_DEBUG, "Merging on top of existing input config"); - struct input_config *current = config->input_configs->items[i]; + struct input_config *current = config_list->items[i]; merge_input_config(current, ic); free_input_config(ic); ic = current; @@ -167,7 +200,7 @@ struct input_config *store_input_config(struct input_config *ic) { free_input_config(ic); ic = current; } - list_add(config->input_configs, ic); + list_add(config_list, ic); } else { // New wildcard config. Just add it sway_log(SWAY_DEBUG, "Adding input * config"); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 0c5254bd..a2a1e274 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -105,6 +105,37 @@ const char *input_device_get_type(struct sway_input_device *device) { return "unknown"; } +static void apply_input_type_config(struct sway_input_device *input_device) { + const char *device_type = input_device_get_type(input_device); + struct input_config *type_config = NULL; + for (int i = 0; i < config->input_type_configs->length; i++) { + struct input_config *ic = config->input_type_configs->items[i]; + if (strcmp(ic->identifier + 5, device_type) == 0) { + type_config = ic; + break; + } + } + if (type_config == NULL) { + return; + } + + for (int i = 0; i < config->input_configs->length; i++) { + struct input_config *ic = config->input_configs->items[i]; + if (strcmp(input_device->identifier, ic->identifier) == 0) { + struct input_config *current = new_input_config(ic->identifier); + merge_input_config(current, type_config); + merge_input_config(current, ic); + + current->input_type = device_type; + config->input_configs->items[i] = current; + free_input_config(ic); + ic = NULL; + + break; + } + } +} + static struct sway_input_device *input_sway_device_from_wlr( struct wlr_input_device *device) { struct sway_input_device *input_device = NULL; @@ -541,6 +572,8 @@ static void handle_new_input(struct wl_listener *listener, void *data) { sway_log(SWAY_DEBUG, "adding device: '%s'", input_device->identifier); + apply_input_type_config(input_device); + if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER || input_device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { input_manager_libinput_config_pointer(input_device); @@ -693,9 +726,13 @@ void input_manager_set_focus(struct sway_node *node) { void input_manager_apply_input_config(struct input_config *input_config) { struct sway_input_device *input_device = NULL; bool wildcard = strcmp(input_config->identifier, "*") == 0; + bool type_wildcard = strncmp(input_config->identifier, "type:", 5) == 0; wl_list_for_each(input_device, &server.input->devices, link) { + bool type_matches = type_wildcard && + strcmp(input_device_get_type(input_device), input_config->identifier + 5) == 0; if (strcmp(input_device->identifier, input_config->identifier) == 0 - || wildcard) { + || wildcard + || type_matches) { if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER || input_device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { input_manager_libinput_config_pointer(input_device); @@ -829,5 +866,13 @@ struct input_config *input_device_get_config(struct sway_input_device *device) { } } + const char *device_type = input_device_get_type(device); + for (int i = 0; i < config->input_type_configs->length; ++i) { + input_config = config->input_type_configs->items[i]; + if (strcmp(input_config->identifier + 5, device_type) == 0) { + return input_config; + } + } + return wildcard_config; } diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 1a8062fb..efd3d1af 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -9,13 +9,28 @@ sway-input - input configuration file and commands Sway allows for configuration of devices within the sway configuration file. To obtain a list of available device identifiers, run *swaymsg -t get_inputs*. Settings can also be applied to all input devices by using the wildcard, _\*_, -in place of _\_ in the commands below. +in place of _\_ in the commands below. In addition, the settings +can be applied to a type of device, by using _type:\_ in place +of _\_. Tip: If the configuration settings do not appear to be taking effect, you could try using _\*_ instead of _\_. If it works with the wildcard, try using a different identifier from *swaymsg -t get_inputs* until you find the correct input device. +Current available input types are: + +- touchpad +- pointer +- keyboard +- touch +- tablet_tool +- tablet_pad +- switch + +Note: The type configurations are applied as the devices appear and get applied +on top of the existing device configurations. + # INPUT COMMANDS ## KEYBOARD CONFIGURATION