Skip to content

Commit

Permalink
Implement input type configs (#3784)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lolzballs authored and RedSoxFan committed Apr 14, 2019
1 parent 6737b90 commit bd37205
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 6 deletions.
2 changes: 2 additions & 0 deletions include/sway/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion sway/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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))))
Expand Down
39 changes: 36 additions & 3 deletions sway/config/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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");
Expand Down
47 changes: 46 additions & 1 deletion sway/input/input-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
17 changes: 16 additions & 1 deletion sway/sway-input.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -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 _\<identifier\>_ in the commands below.
in place of _\<identifier\>_ in the commands below. In addition, the settings
can be applied to a type of device, by using _type:\<input_type\>_ in place
of _\<identifier\>_.

Tip: If the configuration settings do not appear to be taking effect, you could
try using _\*_ instead of _\<identifier\>_. 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
Expand Down

0 comments on commit bd37205

Please sign in to comment.