#define _XOPEN_SOURCE 700 #include #include #include #include "sway/config.h" #include "log.h" struct input_config *new_input_config(const char* identifier) { struct input_config *input = calloc(1, sizeof(struct input_config)); if (!input) { wlr_log(WLR_DEBUG, "Unable to allocate input config"); return NULL; } wlr_log(WLR_DEBUG, "new_input_config(%s)", identifier); if (!(input->identifier = strdup(identifier))) { free(input); wlr_log(WLR_DEBUG, "Unable to allocate input config"); return NULL; } input->tap = INT_MIN; input->tap_button_map = INT_MIN; input->drag_lock = INT_MIN; input->dwt = INT_MIN; input->send_events = INT_MIN; input->click_method = INT_MIN; input->middle_emulation = INT_MIN; input->natural_scroll = INT_MIN; input->accel_profile = INT_MIN; input->pointer_accel = FLT_MIN; input->scroll_button = INT_MIN; input->scroll_method = INT_MIN; input->left_handed = INT_MIN; input->repeat_delay = INT_MIN; input->repeat_rate = INT_MIN; input->xkb_numlock = INT_MIN; input->xkb_capslock = INT_MIN; return input; } void merge_input_config(struct input_config *dst, struct input_config *src) { if (src->accel_profile != INT_MIN) { dst->accel_profile = src->accel_profile; } if (src->click_method != INT_MIN) { dst->click_method = src->click_method; } if (src->drag_lock != INT_MIN) { dst->drag_lock = src->drag_lock; } if (src->dwt != INT_MIN) { dst->dwt = src->dwt; } if (src->middle_emulation != INT_MIN) { dst->middle_emulation = src->middle_emulation; } if (src->natural_scroll != INT_MIN) { dst->natural_scroll = src->natural_scroll; } if (src->pointer_accel != FLT_MIN) { dst->pointer_accel = src->pointer_accel; } if (src->repeat_delay != INT_MIN) { dst->repeat_delay = src->repeat_delay; } if (src->repeat_rate != INT_MIN) { dst->repeat_rate = src->repeat_rate; } if (src->scroll_method != INT_MIN) { dst->scroll_method = src->scroll_method; } if (src->scroll_button != INT_MIN) { dst->scroll_button = src->scroll_button; } if (src->send_events != INT_MIN) { dst->send_events = src->send_events; } if (src->tap != INT_MIN) { dst->tap = src->tap; } if (src->tap_button_map != INT_MIN) { dst->tap_button_map = src->tap_button_map; } if (src->xkb_layout) { free(dst->xkb_layout); dst->xkb_layout = strdup(src->xkb_layout); } if (src->xkb_model) { free(dst->xkb_model); dst->xkb_model = strdup(src->xkb_model); } if (src->xkb_options) { free(dst->xkb_options); dst->xkb_options = strdup(src->xkb_options); } if (src->xkb_rules) { free(dst->xkb_rules); dst->xkb_rules = strdup(src->xkb_rules); } if (src->xkb_variant) { free(dst->xkb_variant); dst->xkb_variant = strdup(src->xkb_variant); } if (src->xkb_numlock != INT_MIN) { dst->xkb_numlock = src->xkb_numlock; } if (src->xkb_capslock != INT_MIN) { dst->xkb_capslock = src->xkb_capslock; } if (src->mapped_from_region) { free(dst->mapped_from_region); dst->mapped_from_region = malloc(sizeof(struct input_config_mapped_from_region)); memcpy(dst->mapped_from_region, src->mapped_from_region, sizeof(struct input_config_mapped_from_region)); } if (src->mapped_to_output) { free(dst->mapped_to_output); dst->mapped_to_output = strdup(src->mapped_to_output); } } static void merge_wildcard_on_all(struct input_config *wildcard) { for (int i = 0; i < config->input_configs->length; i++) { struct input_config *ic = config->input_configs->items[i]; if (strcmp(wildcard->identifier, ic->identifier) != 0) { wlr_log(WLR_DEBUG, "Merging input * config on %s", ic->identifier); merge_input_config(ic, wildcard); } } } struct input_config *store_input_config(struct input_config *ic) { bool wildcard = strcmp(ic->identifier, "*") == 0; if (wildcard) { merge_wildcard_on_all(ic); } int i = list_seq_find(config->input_configs, input_identifier_cmp, ic->identifier); if (i >= 0) { wlr_log(WLR_DEBUG, "Merging on top of existing input config"); struct input_config *current = config->input_configs->items[i]; merge_input_config(current, ic); free_input_config(ic); ic = current; } else if (!wildcard) { wlr_log(WLR_DEBUG, "Adding non-wildcard input config"); i = list_seq_find(config->input_configs, input_identifier_cmp, "*"); if (i >= 0) { wlr_log(WLR_DEBUG, "Merging on top of input * config"); struct input_config *current = new_input_config(ic->identifier); merge_input_config(current, config->input_configs->items[i]); merge_input_config(current, ic); free_input_config(ic); ic = current; } list_add(config->input_configs, ic); } else { // New wildcard config. Just add it wlr_log(WLR_DEBUG, "Adding input * config"); list_add(config->input_configs, ic); } wlr_log(WLR_DEBUG, "Config stored for input %s", ic->identifier); return ic; } void free_input_config(struct input_config *ic) { if (!ic) { return; } free(ic->identifier); free(ic->xkb_layout); free(ic->xkb_model); free(ic->xkb_options); free(ic->xkb_rules); free(ic->xkb_variant); free(ic->mapped_from_region); free(ic->mapped_to_output); free(ic); } int input_identifier_cmp(const void *item, const void *data) { const struct input_config *ic = item; const char *identifier = data; return strcmp(ic->identifier, identifier); }