From 9eb255d5faad2151b91401bc7c451a191e43a2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 23 May 2015 16:48:29 -0400 Subject: [PATCH] Ensure format of dumped bindings for i3bar is compatible with i3 bindings. fixes #1695 --- i3bar/include/config.h | 10 +++---- i3bar/src/config.c | 66 ++++++++++++++++++++++++++++------------- i3bar/src/xcb.c | 8 ++--- include/config.h | 10 +++---- src/config_directives.c | 34 ++++++++++++--------- src/ipc.c | 25 +++++++++++----- 6 files changed, 96 insertions(+), 57 deletions(-) diff --git a/i3bar/include/config.h b/i3bar/include/config.h index 90c7c02b..d0291917 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -22,16 +22,16 @@ typedef enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } bar_display_mode_t; -typedef struct mouse_command_t { - int button; +typedef struct binding_t { + int input_code; char *command; - TAILQ_ENTRY(mouse_command_t) commands; -} mouse_command_t; + TAILQ_ENTRY(binding_t) bindings; +} binding_t; typedef struct config_t { int modifier; - TAILQ_HEAD(mouse_commands_head, mouse_command_t) mouse_commands; + TAILQ_HEAD(bindings_head, binding_t) bindings; position_t position; int verbose; struct xcb_color_strings_t colors; diff --git a/i3bar/src/config.c b/i3bar/src/config.c index 423dbc69..a59dd5c1 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -20,7 +20,7 @@ #include "common.h" static char *cur_key; -static bool parsing_mouse_commands; +static bool parsing_bindings; /* * Parse a key. @@ -35,14 +35,14 @@ static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t strncpy(cur_key, (const char *)keyVal, keyLen); cur_key[keyLen] = '\0'; - if (strcmp(cur_key, "mouse_commands") == 0) - parsing_mouse_commands = true; + if (strcmp(cur_key, "bindings") == 0) + parsing_bindings = true; return 1; } -static int config_end_map_cb(void *params_) { - parsing_mouse_commands = false; +static int config_end_array_cb(void *params_) { + parsing_bindings = false; return 1; } @@ -72,23 +72,25 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len if (!strcmp(cur_key, "id") || !strcmp(cur_key, "socket_path")) return 1; - if (parsing_mouse_commands) { - int button = atoi(cur_key + sizeof("button") - 1); - - mouse_command_t *current; - TAILQ_FOREACH(current, &(config.mouse_commands), commands) { - if (current->button == button) { - FREE(current->command); - sasprintf(&(current->command), "%.*s", len, val); - return 1; + if (parsing_bindings) { + if (strcmp(cur_key, "command") == 0) { + binding_t *binding = TAILQ_LAST(&(config.bindings), bindings_head); + if (binding == NULL) { + ELOG("There is no binding to put the current command onto. This is a bug in i3.\n"); + return 0; } + + if (binding->command != NULL) { + ELOG("The binding for input_code = %d already has a command. This is a bug in i3.\n", binding->input_code); + return 0; + } + + sasprintf(&(binding->command), "%.*s", len, val); + return 1; } - mouse_command_t *command = scalloc(sizeof(mouse_command_t)); - command->button = button; - sasprintf(&(command->command), "%.*s", len, val); - TAILQ_INSERT_TAIL(&(config.mouse_commands), command, commands); - return 1; + ELOG("Unknown key \"%s\" while parsing bar bindings.\n", cur_key); + return 0; } if (!strcmp(cur_key, "mode")) { @@ -268,12 +270,34 @@ static int config_boolean_cb(void *params_, int val) { return 0; } +/* + * Parse an integer value + * + */ +static int config_integer_cb(void *params_, long long val) { + if (parsing_bindings) { + if (strcmp(cur_key, "input_code") == 0) { + binding_t *binding = scalloc(sizeof(binding_t)); + binding->input_code = val; + TAILQ_INSERT_TAIL(&(config.bindings), binding, bindings); + + return 1; + } + + ELOG("Unknown key \"%s\" while parsing bar bindings.\n", cur_key); + return 0; + } + + return 0; +} + /* A datastructure to pass all these callbacks to yajl */ static yajl_callbacks outputs_callbacks = { .yajl_null = config_null_cb, .yajl_boolean = config_boolean_cb, + .yajl_integer = config_integer_cb, .yajl_string = config_string_cb, - .yajl_end_map = config_end_map_cb, + .yajl_end_array = config_end_array_cb, .yajl_map_key = config_map_key_cb, }; @@ -286,7 +310,7 @@ void parse_config_json(char *json) { yajl_status state; handle = yajl_alloc(&outputs_callbacks, NULL, NULL); - TAILQ_INIT(&(config.mouse_commands)); + TAILQ_INIT(&(config.bindings)); state = yajl_parse(handle, (const unsigned char *)json, strlen(json)); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 56c31def..365ea366 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -470,12 +470,12 @@ void handle_button(xcb_button_press_event_t *event) { /* If a custom command was specified for this mouse button, it overrides * the default behavior. */ - mouse_command_t *command; - TAILQ_FOREACH(command, &(config.mouse_commands), commands) { - if (command->button != event->detail) + binding_t *binding; + TAILQ_FOREACH(binding, &(config.bindings), bindings) { + if (binding->input_code != event->detail) continue; - i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, command->command); + i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, binding->command); return; } diff --git a/include/config.h b/include/config.h index 3955fc79..9e881cc3 100644 --- a/include/config.h +++ b/include/config.h @@ -281,7 +281,7 @@ struct Barconfig { M_MOD5 = 7 } modifier; - TAILQ_HEAD(mouse_commands_head, Mousecommand) mouse_commands; + TAILQ_HEAD(bar_bindings_head, Barbinding) bar_bindings; /** Bar position (bottom by default). */ enum { P_BOTTOM = 0, @@ -352,14 +352,14 @@ struct Barconfig { * clicking on the non-statusline part of i3bar. * */ -struct Mousecommand { - /** The button for this command (e.g., "button1") */ - char *button; +struct Barbinding { + /** The button to be used (e.g., 1 for "button1"). */ + int input_code; /** The command which is to be executed for this button. */ char *command; - TAILQ_ENTRY(Mousecommand) commands; + TAILQ_ENTRY(Barbinding) bindings; }; /** diff --git a/src/config_directives.c b/src/config_directives.c index 182f2e35..cf72a4db 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -530,38 +530,44 @@ CFGFUN(bar_modifier, const char *modifier) { current_bar.modifier = M_SHIFT; } -static void bar_configure_mouse_command(const char *button, const char *command) { - if (strncasecmp(button, "button", sizeof("button") - 1) != 0) { - ELOG("unknown button \"%s\" for mouse command, ignoring.\n", button); +static void bar_configure_binding(const char *button, const char *command) { + if (strncasecmp(button, "button", strlen("button")) != 0) { + ELOG("Bindings for a bar can only be mouse bindings, not \"%s\", ignoring.\n", button); return; } - struct Mousecommand *current; - TAILQ_FOREACH(current, &(current_bar.mouse_commands), commands) { - if (strcasecmp(current->button, button) == 0) { + int input_code = atoi(button + strlen("button")); + if (input_code < 1) { + ELOG("Button \"%s\" does not seem to be in format 'buttonX'.\n", button); + return; + } + + struct Barbinding *current; + TAILQ_FOREACH(current, &(current_bar.bar_bindings), bindings) { + if (current->input_code == input_code) { ELOG("command for button %s was already specified, ignoring.\n", button); return; } } - struct Mousecommand *new_command = scalloc(sizeof(struct Mousecommand)); - new_command->button = sstrdup(button); - new_command->command = sstrdup(command); - TAILQ_INSERT_TAIL(&(current_bar.mouse_commands), new_command, commands); + struct Barbinding *new_binding = scalloc(sizeof(struct Barbinding)); + new_binding->input_code = input_code; + new_binding->command = sstrdup(command); + TAILQ_INSERT_TAIL(&(current_bar.bar_bindings), new_binding, bindings); } CFGFUN(bar_wheel_up_cmd, const char *command) { ELOG("'wheel_up_cmd' is deprecated. Please us 'bindsym button4 %s' instead.\n", command); - bar_configure_mouse_command("button4", command); + bar_configure_binding("button4", command); } CFGFUN(bar_wheel_down_cmd, const char *command) { ELOG("'wheel_down_cmd' is deprecated. Please us 'bindsym button5 %s' instead.\n", command); - bar_configure_mouse_command("button5", command); + bar_configure_binding("button5", command); } CFGFUN(bar_bindsym, const char *button, const char *command) { - bar_configure_mouse_command(button, command); + bar_configure_binding(button, command); } CFGFUN(bar_position, const char *position) { @@ -636,7 +642,7 @@ CFGFUN(bar_strip_workspace_numbers, const char *value) { } CFGFUN(bar_start) { - TAILQ_INIT(&(current_bar.mouse_commands)); + TAILQ_INIT(&(current_bar.bar_bindings)); } CFGFUN(bar_finish) { diff --git a/src/ipc.c b/src/ipc.c index fa028834..be600978 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -469,17 +469,26 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(map_close); } -static void dump_mouse_commands(yajl_gen gen, Barconfig *config) { - ystr("mouse_commands"); - y(map_open); +static void dump_bar_bindings(yajl_gen gen, Barconfig *config) { + if (TAILQ_EMPTY(&(config->bar_bindings))) + return; - struct Mousecommand *current; - TAILQ_FOREACH(current, &(config->mouse_commands), commands) { - ystr(current->button); + ystr("bindings"); + y(array_open); + + struct Barbinding *current; + TAILQ_FOREACH(current, &(config->bar_bindings), bindings) { + y(map_open); + + ystr("input_code"); + y(integer, current->input_code); + ystr("command"); ystr(current->command); + + y(map_close); } - y(map_close); + y(array_close); } static void dump_bar_config(yajl_gen gen, Barconfig *config) { @@ -562,7 +571,7 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) { break; } - dump_mouse_commands(gen, config); + dump_bar_bindings(gen, config); ystr("position"); if (config->position == P_BOTTOM)