Ensure format of dumped bindings for i3bar is compatible with i3 bindings.
fixes #1695
This commit is contained in:
parent
f0ac9629b9
commit
9eb255d5fa
|
@ -22,16 +22,16 @@ typedef enum { M_DOCK = 0,
|
||||||
M_HIDE = 1,
|
M_HIDE = 1,
|
||||||
M_INVISIBLE = 2 } bar_display_mode_t;
|
M_INVISIBLE = 2 } bar_display_mode_t;
|
||||||
|
|
||||||
typedef struct mouse_command_t {
|
typedef struct binding_t {
|
||||||
int button;
|
int input_code;
|
||||||
char *command;
|
char *command;
|
||||||
|
|
||||||
TAILQ_ENTRY(mouse_command_t) commands;
|
TAILQ_ENTRY(binding_t) bindings;
|
||||||
} mouse_command_t;
|
} binding_t;
|
||||||
|
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
int modifier;
|
int modifier;
|
||||||
TAILQ_HEAD(mouse_commands_head, mouse_command_t) mouse_commands;
|
TAILQ_HEAD(bindings_head, binding_t) bindings;
|
||||||
position_t position;
|
position_t position;
|
||||||
int verbose;
|
int verbose;
|
||||||
struct xcb_color_strings_t colors;
|
struct xcb_color_strings_t colors;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
static char *cur_key;
|
static char *cur_key;
|
||||||
static bool parsing_mouse_commands;
|
static bool parsing_bindings;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a key.
|
* 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);
|
strncpy(cur_key, (const char *)keyVal, keyLen);
|
||||||
cur_key[keyLen] = '\0';
|
cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
if (strcmp(cur_key, "mouse_commands") == 0)
|
if (strcmp(cur_key, "bindings") == 0)
|
||||||
parsing_mouse_commands = true;
|
parsing_bindings = true;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_end_map_cb(void *params_) {
|
static int config_end_array_cb(void *params_) {
|
||||||
parsing_mouse_commands = false;
|
parsing_bindings = false;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,25 +72,27 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
||||||
if (!strcmp(cur_key, "id") || !strcmp(cur_key, "socket_path"))
|
if (!strcmp(cur_key, "id") || !strcmp(cur_key, "socket_path"))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (parsing_mouse_commands) {
|
if (parsing_bindings) {
|
||||||
int button = atoi(cur_key + sizeof("button") - 1);
|
if (strcmp(cur_key, "command") == 0) {
|
||||||
|
binding_t *binding = TAILQ_LAST(&(config.bindings), bindings_head);
|
||||||
mouse_command_t *current;
|
if (binding == NULL) {
|
||||||
TAILQ_FOREACH(current, &(config.mouse_commands), commands) {
|
ELOG("There is no binding to put the current command onto. This is a bug in i3.\n");
|
||||||
if (current->button == button) {
|
return 0;
|
||||||
FREE(current->command);
|
|
||||||
sasprintf(&(current->command), "%.*s", len, val);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_command_t *command = scalloc(sizeof(mouse_command_t));
|
if (binding->command != NULL) {
|
||||||
command->button = button;
|
ELOG("The binding for input_code = %d already has a command. This is a bug in i3.\n", binding->input_code);
|
||||||
sasprintf(&(command->command), "%.*s", len, val);
|
return 0;
|
||||||
TAILQ_INSERT_TAIL(&(config.mouse_commands), command, commands);
|
}
|
||||||
|
|
||||||
|
sasprintf(&(binding->command), "%.*s", len, val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ELOG("Unknown key \"%s\" while parsing bar bindings.\n", cur_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "mode")) {
|
if (!strcmp(cur_key, "mode")) {
|
||||||
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
||||||
config.hide_on_modifier = (len == 4 && !strncmp((const char *)val, "dock", strlen("dock")) ? M_DOCK
|
config.hide_on_modifier = (len == 4 && !strncmp((const char *)val, "dock", strlen("dock")) ? M_DOCK
|
||||||
|
@ -268,12 +270,34 @@ static int config_boolean_cb(void *params_, int val) {
|
||||||
return 0;
|
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 */
|
/* A datastructure to pass all these callbacks to yajl */
|
||||||
static yajl_callbacks outputs_callbacks = {
|
static yajl_callbacks outputs_callbacks = {
|
||||||
.yajl_null = config_null_cb,
|
.yajl_null = config_null_cb,
|
||||||
.yajl_boolean = config_boolean_cb,
|
.yajl_boolean = config_boolean_cb,
|
||||||
|
.yajl_integer = config_integer_cb,
|
||||||
.yajl_string = config_string_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,
|
.yajl_map_key = config_map_key_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -286,7 +310,7 @@ void parse_config_json(char *json) {
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
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));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
|
|
|
@ -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
|
/* If a custom command was specified for this mouse button, it overrides
|
||||||
* the default behavior. */
|
* the default behavior. */
|
||||||
mouse_command_t *command;
|
binding_t *binding;
|
||||||
TAILQ_FOREACH(command, &(config.mouse_commands), commands) {
|
TAILQ_FOREACH(binding, &(config.bindings), bindings) {
|
||||||
if (command->button != event->detail)
|
if (binding->input_code != event->detail)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, command->command);
|
i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, binding->command);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,7 @@ struct Barconfig {
|
||||||
M_MOD5 = 7
|
M_MOD5 = 7
|
||||||
} modifier;
|
} modifier;
|
||||||
|
|
||||||
TAILQ_HEAD(mouse_commands_head, Mousecommand) mouse_commands;
|
TAILQ_HEAD(bar_bindings_head, Barbinding) bar_bindings;
|
||||||
|
|
||||||
/** Bar position (bottom by default). */
|
/** Bar position (bottom by default). */
|
||||||
enum { P_BOTTOM = 0,
|
enum { P_BOTTOM = 0,
|
||||||
|
@ -352,14 +352,14 @@ struct Barconfig {
|
||||||
* clicking on the non-statusline part of i3bar.
|
* clicking on the non-statusline part of i3bar.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Mousecommand {
|
struct Barbinding {
|
||||||
/** The button for this command (e.g., "button1") */
|
/** The button to be used (e.g., 1 for "button1"). */
|
||||||
char *button;
|
int input_code;
|
||||||
|
|
||||||
/** The command which is to be executed for this button. */
|
/** The command which is to be executed for this button. */
|
||||||
char *command;
|
char *command;
|
||||||
|
|
||||||
TAILQ_ENTRY(Mousecommand) commands;
|
TAILQ_ENTRY(Barbinding) bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -530,38 +530,44 @@ CFGFUN(bar_modifier, const char *modifier) {
|
||||||
current_bar.modifier = M_SHIFT;
|
current_bar.modifier = M_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bar_configure_mouse_command(const char *button, const char *command) {
|
static void bar_configure_binding(const char *button, const char *command) {
|
||||||
if (strncasecmp(button, "button", sizeof("button") - 1) != 0) {
|
if (strncasecmp(button, "button", strlen("button")) != 0) {
|
||||||
ELOG("unknown button \"%s\" for mouse command, ignoring.\n", button);
|
ELOG("Bindings for a bar can only be mouse bindings, not \"%s\", ignoring.\n", button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Mousecommand *current;
|
int input_code = atoi(button + strlen("button"));
|
||||||
TAILQ_FOREACH(current, &(current_bar.mouse_commands), commands) {
|
if (input_code < 1) {
|
||||||
if (strcasecmp(current->button, button) == 0) {
|
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);
|
ELOG("command for button %s was already specified, ignoring.\n", button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Mousecommand *new_command = scalloc(sizeof(struct Mousecommand));
|
struct Barbinding *new_binding = scalloc(sizeof(struct Barbinding));
|
||||||
new_command->button = sstrdup(button);
|
new_binding->input_code = input_code;
|
||||||
new_command->command = sstrdup(command);
|
new_binding->command = sstrdup(command);
|
||||||
TAILQ_INSERT_TAIL(&(current_bar.mouse_commands), new_command, commands);
|
TAILQ_INSERT_TAIL(&(current_bar.bar_bindings), new_binding, bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_wheel_up_cmd, const char *command) {
|
CFGFUN(bar_wheel_up_cmd, const char *command) {
|
||||||
ELOG("'wheel_up_cmd' is deprecated. Please us 'bindsym button4 %s' instead.\n", 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) {
|
CFGFUN(bar_wheel_down_cmd, const char *command) {
|
||||||
ELOG("'wheel_down_cmd' is deprecated. Please us 'bindsym button5 %s' instead.\n", 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) {
|
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) {
|
CFGFUN(bar_position, const char *position) {
|
||||||
|
@ -636,7 +642,7 @@ CFGFUN(bar_strip_workspace_numbers, const char *value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_start) {
|
CFGFUN(bar_start) {
|
||||||
TAILQ_INIT(&(current_bar.mouse_commands));
|
TAILQ_INIT(&(current_bar.bar_bindings));
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_finish) {
|
CFGFUN(bar_finish) {
|
||||||
|
|
23
src/ipc.c
23
src/ipc.c
|
@ -469,19 +469,28 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
||||||
y(map_close);
|
y(map_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_mouse_commands(yajl_gen gen, Barconfig *config) {
|
static void dump_bar_bindings(yajl_gen gen, Barconfig *config) {
|
||||||
ystr("mouse_commands");
|
if (TAILQ_EMPTY(&(config->bar_bindings)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ystr("bindings");
|
||||||
|
y(array_open);
|
||||||
|
|
||||||
|
struct Barbinding *current;
|
||||||
|
TAILQ_FOREACH(current, &(config->bar_bindings), bindings) {
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
struct Mousecommand *current;
|
ystr("input_code");
|
||||||
TAILQ_FOREACH(current, &(config->mouse_commands), commands) {
|
y(integer, current->input_code);
|
||||||
ystr(current->button);
|
ystr("command");
|
||||||
ystr(current->command);
|
ystr(current->command);
|
||||||
}
|
|
||||||
|
|
||||||
y(map_close);
|
y(map_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
y(array_close);
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
|
@ -562,7 +571,7 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_mouse_commands(gen, config);
|
dump_bar_bindings(gen, config);
|
||||||
|
|
||||||
ystr("position");
|
ystr("position");
|
||||||
if (config->position == P_BOTTOM)
|
if (config->position == P_BOTTOM)
|
||||||
|
|
Loading…
Reference in New Issue