From 7727c9efbc105269befe06a5bb12d2019c52515e Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 5 Jan 2016 00:49:11 +0100 Subject: Detect bar modifier pressed/released --- include/input_state.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include') diff --git a/include/input_state.h b/include/input_state.h index a1f238e1..79e27d91 100644 --- a/include/input_state.h +++ b/include/input_state.h @@ -60,6 +60,12 @@ extern struct pointer_state { int mode; } pointer_state; +enum modifier_state { + MOD_STATE_UNCHANGED = 0, + MOD_STATE_PRESSED = 1, + MOD_STATE_RELEASED = 2 +}; + void pointer_position_set(struct wlc_origin *new_origin, bool force_focus); void center_pointer_on(swayc_t *view); @@ -75,5 +81,19 @@ void pointer_mode_reset(void); void input_init(void); +/** + * Check if state of mod changed from current state to new_state. + * + * Returns MOD_STATE_UNCHANGED if the state didn't change, MOD_STATE_PRESSED if + * the state changed to pressed and MOD_STATE_RELEASED if the state changed to + * released. + */ +uint32_t modifier_state_changed(uint32_t new_state, uint32_t mod); + +/** + * Update the current modifiers state to new_state. + */ +void modifiers_state_update(uint32_t new_state); + #endif -- cgit v1.2.3-54-g00ecf From c20c63b677c03b17441f0d135b5325e23d65f38d Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 5 Jan 2016 02:20:20 +0100 Subject: Send IPC modifier event on bar_modifier up/down Detects when a bar modifier key is pressed/released and sends a modifier IPC event to any listeners (usually swaybars). This way a swaybar can listen on the modifier event and hide/show the bar accordingly (not implemented yet) The modifier event looks like this: { "change": "pressed", // or released "modifier": "Mod4" } --- include/ipc-server.h | 6 ++++++ include/ipc.h | 1 + sway/commands.c | 2 +- sway/handlers.c | 17 ++++++++++------- sway/ipc-server.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/ipc-server.h b/include/ipc-server.h index 04975093..47026bfd 100644 --- a/include/ipc-server.h +++ b/include/ipc-server.h @@ -15,6 +15,12 @@ void ipc_event_barconfig_update(struct bar_config *bar); * Send IPC mode event to all listening clients */ void ipc_event_mode(const char *mode); +/** + * Sends an IPC modifier event to all listening clients. The modifier event + * includes a key 'change' with the value of state and a key 'modifier' with + * the name of that modifier. + */ +void ipc_event_modifier(uint32_t modifier, const char *state); const char *swayc_type_string(enum swayc_types type); #endif diff --git a/include/ipc.h b/include/ipc.h index e0b3b736..56593529 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -17,6 +17,7 @@ enum ipc_command_type { IPC_EVENT_WINDOW = (1 << 31 | 3), IPC_EVENT_BARCONFIG_UPDATE = (1 << 31 | 4), IPC_EVENT_BINDING = (1 << 31 | 5), + IPC_EVENT_MODIFIER = (1 << 31 | 6), IPC_SWAY_GET_PIXELS = 0x81 }; diff --git a/sway/commands.c b/sway/commands.c index 38019be5..f748a969 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1897,7 +1897,7 @@ static struct cmd_results *bar_cmd_modifier(int argc, char **argv) { bool is_mod = false; for (j = 0; j < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++j) { if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { - mod |= modifiers[j].mod; + mod = modifiers[j].mod; is_mod = true; break; } diff --git a/sway/handlers.c b/sway/handlers.c index 5e523468..4cbec0ab 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -20,6 +20,7 @@ #include "resize.h" #include "extensions.h" #include "criteria.h" +#include "ipc-server.h" // Event should be sent to client #define EVENT_PASSTHROUGH false @@ -392,13 +393,15 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier struct bar_config *bar; for (i = 0; i < config->bars->length; ++i) { bar = config->bars->items[i]; - switch (modifier_state_changed(modifiers->mods, bar->modifier)) { - case MOD_STATE_PRESSED: - sway_log(L_INFO, "pressed!!!"); - break; - case MOD_STATE_RELEASED: - sway_log(L_INFO, "released!!!"); - break; + if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { + switch (modifier_state_changed(modifiers->mods, bar->modifier)) { + case MOD_STATE_PRESSED: + ipc_event_modifier(bar->modifier, "pressed"); + break; + case MOD_STATE_RELEASED: + ipc_event_modifier(bar->modifier, "released"); + break; + } } } // update modifiers state diff --git a/sway/ipc-server.c b/sway/ipc-server.c index ed3977d5..da3d52e3 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -35,6 +35,22 @@ struct ipc_client { enum ipc_command_type subscribed_events; }; +static struct modifier_key { + char *name; + uint32_t mod; +} modifiers[] = { + { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, + { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, + { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, + { "Ctrl", WLC_BIT_MOD_CTRL }, + { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, + { "Alt", WLC_BIT_MOD_ALT }, + { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, + { "Mod3", WLC_BIT_MOD_MOD3 }, + { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, + { "Mod5", WLC_BIT_MOD_MOD5 }, +}; + struct sockaddr_un *ipc_user_sockaddr(void); int ipc_handle_connection(int fd, uint32_t mask, void *data); int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); @@ -295,6 +311,8 @@ void ipc_client_handle_command(struct ipc_client *client) { client->subscribed_events |= IPC_EVENT_BARCONFIG_UPDATE; } else if (strcmp(event_type, "mode") == 0) { client->subscribed_events |= IPC_EVENT_MODE; + } else if (strcmp(event_type, "modifier") == 0) { + client->subscribed_events |= IPC_EVENT_MODIFIER; } else { ipc_send_reply(client, "{\"success\": false}", 18); ipc_client_disconnect(client); @@ -617,3 +635,24 @@ void ipc_event_mode(const char *mode) { json_object_put(obj); // free } + +void ipc_event_modifier(uint32_t modifier, const char *state) { + json_object *obj = json_object_new_object(); + json_object_object_add(obj, "change", json_object_new_string(state)); + + const char *modifier_name = NULL; + int i; + for (i = 0; i < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++i) { + if (modifiers[i].mod == modifier) { + modifier_name = modifiers[i].name; + break; + } + } + + json_object_object_add(obj, "modifier", json_object_new_string(modifier_name)); + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_MODIFIER); + + json_object_put(obj); // free +} -- cgit v1.2.3-54-g00ecf From 95e0f44c73f2783541b180c9bd555f6b8abb7c0f Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 5 Jan 2016 18:07:43 +0100 Subject: Move modifier name table to common/util.c Lookup of modifier names is required in several places, thus it makes sense to move it to a general place. --- common/util.c | 38 ++++++++++++++++++++++++++++++++++++++ include/util.h | 18 ++++++++++++++++++ sway/commands.c | 52 +++++++++++----------------------------------------- sway/ipc-server.c | 27 ++------------------------- 4 files changed, 69 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/common/util.c b/common/util.c index ed6d033f..b5037d35 100644 --- a/common/util.c +++ b/common/util.c @@ -13,3 +13,41 @@ int numlen(int n) { if (n >= 10) return 2; return 1; } + +static struct modifier_key { + char *name; + uint32_t mod; +} modifiers[] = { + { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, + { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, + { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, + { "Ctrl", WLC_BIT_MOD_CTRL }, + { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, + { "Alt", WLC_BIT_MOD_ALT }, + { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, + { "Mod3", WLC_BIT_MOD_MOD3 }, + { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, + { "Mod5", WLC_BIT_MOD_MOD5 }, +}; + +uint32_t get_modifier_mask_by_name(const char *name) { + int i; + for (i = 0; i < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++i) { + if (strcasecmp(modifiers[i].name, name) == 0) { + return modifiers[i].mod; + } + } + + return 0; +} + +const char *get_modifier_name_by_mask(uint32_t modifier) { + int i; + for (i = 0; i < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++i) { + if (modifiers[i].mod == modifier) { + return modifiers[i].name; + } + } + + return NULL; +} diff --git a/include/util.h b/include/util.h index 9cb861dd..4bbb64c8 100644 --- a/include/util.h +++ b/include/util.h @@ -1,6 +1,10 @@ #ifndef _SWAY_UTIL_H #define _SWAY_UTIL_H +#include +#include +#include + /** * Wrap i into the range [0, max[ */ @@ -11,4 +15,18 @@ int wrap(int i, int max); */ int numlen(int n); +/** + * Get modifier mask from modifier name. + * + * Returns the modifer mask or 0 if the name isn't found. + */ +uint32_t get_modifier_mask_by_name(const char *name); + +/** + * Get modifier name from modifier mask. + * + * Returns the modifier name or NULL if it isn't found. + */ +const char *get_modifier_name_by_mask(uint32_t modifier); + #endif diff --git a/sway/commands.c b/sway/commands.c index f748a969..963d8f12 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -99,22 +99,6 @@ static sway_cmd bar_colors_cmd_urgent_workspace; swayc_t *sp_view; int sp_index = 0; -static struct modifier_key { - char *name; - uint32_t mod; -} modifiers[] = { - { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, - { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, - { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, - { "Ctrl", WLC_BIT_MOD_CTRL }, - { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, - { "Alt", WLC_BIT_MOD_ALT }, - { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, - { "Mod3", WLC_BIT_MOD_MOD3 }, - { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, - { "Mod5", WLC_BIT_MOD_MOD5 }, -}; - static char *bg_options[] = { "stretch", "center", @@ -187,16 +171,11 @@ static struct cmd_results *cmd_bindsym(int argc, char **argv) { list_t *split = split_string(argv[0], "+"); for (int i = 0; i < split->length; ++i) { // Check for a modifier key - int j; - bool is_mod = false; - for (j = 0; j < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++j) { - if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { - binding->modifiers |= modifiers[j].mod; - is_mod = true; - break; - } + uint32_t mod; + if ((mod = get_modifier_mask_by_name(split->items[i])) > 0) { + binding->modifiers |= mod; + continue; } - if (is_mod) continue; // Check for xkb key xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); if (!sym) { @@ -408,17 +387,13 @@ static struct cmd_results *cmd_floating_mod(int argc, char **argv) { if ((error = checkarg(argc, "floating_modifier", EXPECTED_AT_LEAST, 1))) { return error; } - int i, j; + int i; list_t *split = split_string(argv[0], "+"); config->floating_mod = 0; // set modifier keys for (i = 0; i < split->length; ++i) { - for (j = 0; j < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++j) { - if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { - config->floating_mod |= modifiers[j].mod; - } - } + config->floating_mod |= get_modifier_mask_by_name(split->items[i]); } free_flat_list(split); if (!config->floating_mod) { @@ -1893,16 +1868,11 @@ static struct cmd_results *bar_cmd_modifier(int argc, char **argv) { list_t *split = split_string(argv[0], "+"); for (int i = 0; i < split->length; ++i) { - int j; - bool is_mod = false; - for (j = 0; j < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++j) { - if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { - mod = modifiers[j].mod; - is_mod = true; - break; - } - } - if (!is_mod) { + uint32_t tmp_mod; + if ((tmp_mod = get_modifier_mask_by_name(split->items[i])) > 0) { + mod |= tmp_mod; + continue; + } else { free_flat_list(split); return cmd_results_new(CMD_INVALID, "modifier", "Unknown modifier '%s'", split->items[i]); } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index da3d52e3..a6598b84 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -19,6 +19,7 @@ #include "commands.h" #include "list.h" #include "stringop.h" +#include "util.h" static int ipc_socket = -1; static struct wlc_event_source *ipc_event_source = NULL; @@ -35,22 +36,6 @@ struct ipc_client { enum ipc_command_type subscribed_events; }; -static struct modifier_key { - char *name; - uint32_t mod; -} modifiers[] = { - { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, - { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, - { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, - { "Ctrl", WLC_BIT_MOD_CTRL }, - { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, - { "Alt", WLC_BIT_MOD_ALT }, - { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, - { "Mod3", WLC_BIT_MOD_MOD3 }, - { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, - { "Mod5", WLC_BIT_MOD_MOD5 }, -}; - struct sockaddr_un *ipc_user_sockaddr(void); int ipc_handle_connection(int fd, uint32_t mask, void *data); int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); @@ -640,15 +625,7 @@ void ipc_event_modifier(uint32_t modifier, const char *state) { json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(state)); - const char *modifier_name = NULL; - int i; - for (i = 0; i < (int)(sizeof(modifiers) / sizeof(struct modifier_key)); ++i) { - if (modifiers[i].mod == modifier) { - modifier_name = modifiers[i].name; - break; - } - } - + const char *modifier_name = get_modifier_name_by_mask(modifier); json_object_object_add(obj, "modifier", json_object_new_string(modifier_name)); const char *json_string = json_object_to_json_string(obj); -- cgit v1.2.3-54-g00ecf From 843e2ad2c140288733110691f7dc8252fbe4dc16 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 5 Jan 2016 23:18:59 +0100 Subject: Only send modifier event once for active modifiers This makes sure that a modifier event is only sent for active bar modifiers, and that it is only sent once for each of those modifiers. An active bar modifier is a modifier defined for a bar with `mode hide` and `hidden_state hide`. --- include/config.h | 6 ++++++ sway/commands.c | 6 ++++++ sway/config.c | 31 +++++++++++++++++++++++++++++++ sway/handlers.c | 23 +++++++++++------------ 4 files changed, 54 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/config.h b/include/config.h index a915fbed..5e1c39f3 100644 --- a/include/config.h +++ b/include/config.h @@ -135,6 +135,7 @@ struct sway_config { list_t *workspace_outputs; list_t *output_configs; list_t *criteria; + list_t *active_bar_modifiers; struct sway_mode *current_mode; struct bar_config *current_bar; uint32_t floating_mod; @@ -176,6 +177,11 @@ void merge_output_config(struct output_config *dst, struct output_config *src); void apply_output_config(struct output_config *oc, swayc_t *output); void free_output_config(struct output_config *oc); +/** + * Updates the list of active bar modifiers + */ +void update_active_bar_modifiers(void); + int workspace_output_cmp_workspace(const void *a, const void *b); int sway_binding_cmp(const void *a, const void *b); diff --git a/sway/commands.c b/sway/commands.c index 963d8f12..3a4079e4 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1751,6 +1751,9 @@ static struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) { } } + // active bar modifiers might have changed. + update_active_bar_modifiers(); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -1775,6 +1778,9 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode if (strcmp(old_mode, bar->mode) != 0) { if (!config->reading) { ipc_event_barconfig_update(bar); + + // active bar modifiers might have changed. + update_active_bar_modifiers(); } sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); } diff --git a/sway/config.c b/sway/config.c index 87b1342d..95d8f339 100644 --- a/sway/config.c +++ b/sway/config.c @@ -103,6 +103,8 @@ static void free_config(struct sway_config *config) { free_output_config(config->output_configs->items[i]); } list_free(config->output_configs); + + list_free(config->active_bar_modifiers); free(config); } @@ -145,6 +147,33 @@ static void config_defaults(struct sway_config *config) { config->edge_gaps = true; config->gaps_inner = 0; config->gaps_outer = 0; + + config->active_bar_modifiers = create_list(); +} + +static int compare_modifiers(const void *left, const void *right) { + uint32_t a = *(uint32_t *)left; + uint32_t b = *(uint32_t *)right; + + return a - b; +} + +void update_active_bar_modifiers() { + if (config->active_bar_modifiers->length > 0) { + list_free(config->active_bar_modifiers); + config->active_bar_modifiers = create_list(); + } + + struct bar_config *bar; + int i; + for (i = 0; i < config->bars->length; ++i) { + bar = config->bars->items[i]; + if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { + if (list_seq_find(config->active_bar_modifiers, compare_modifiers, &bar->modifier) < 0) { + list_add(config->active_bar_modifiers, &bar->modifier); + } + } + } } static char *get_config_path(void) { @@ -215,6 +244,8 @@ bool load_config(const char *file) { } fclose(f); + update_active_bar_modifiers(); + return config_load_success; } diff --git a/sway/handlers.c b/sway/handlers.c index 4cbec0ab..db3a0206 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -390,18 +390,17 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } // handle bar modifiers pressed/released - struct bar_config *bar; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { - switch (modifier_state_changed(modifiers->mods, bar->modifier)) { - case MOD_STATE_PRESSED: - ipc_event_modifier(bar->modifier, "pressed"); - break; - case MOD_STATE_RELEASED: - ipc_event_modifier(bar->modifier, "released"); - break; - } + uint32_t modifier; + for (i = 0; i < config->active_bar_modifiers->length; ++i) { + modifier = *(uint32_t *)config->active_bar_modifiers->items[i]; + + switch (modifier_state_changed(modifiers->mods, modifier)) { + case MOD_STATE_PRESSED: + ipc_event_modifier(modifier, "pressed"); + break; + case MOD_STATE_RELEASED: + ipc_event_modifier(modifier, "released"); + break; } } // update modifiers state -- cgit v1.2.3-54-g00ecf