Merge pull request #2001 from Airblader/feature-multiple-tray-output
Allow multiple tray_output directives.
This commit is contained in:
commit
bb7a36e0c7
|
@ -1369,6 +1369,11 @@ NetworkManager, VLC, Pidgin, etc. can place little icons.
|
||||||
You can configure on which output (monitor) the icons should be displayed or
|
You can configure on which output (monitor) the icons should be displayed or
|
||||||
you can turn off the functionality entirely.
|
you can turn off the functionality entirely.
|
||||||
|
|
||||||
|
You can use mutliple +tray_output+ directives in your config to specify a list
|
||||||
|
of outputs on which you want the tray to appear. The first available output in
|
||||||
|
that list as defined by the order of the directives will be used for the tray
|
||||||
|
output.
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
---------------------------------
|
---------------------------------
|
||||||
tray_output none|primary|<output>
|
tray_output none|primary|<output>
|
||||||
|
|
|
@ -29,6 +29,12 @@ typedef struct binding_t {
|
||||||
TAILQ_ENTRY(binding_t) bindings;
|
TAILQ_ENTRY(binding_t) bindings;
|
||||||
} binding_t;
|
} binding_t;
|
||||||
|
|
||||||
|
typedef struct tray_output_t {
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(tray_output_t) tray_outputs;
|
||||||
|
} tray_output_t;
|
||||||
|
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
int modifier;
|
int modifier;
|
||||||
TAILQ_HEAD(bindings_head, binding_t) bindings;
|
TAILQ_HEAD(bindings_head, binding_t) bindings;
|
||||||
|
@ -42,7 +48,7 @@ typedef struct config_t {
|
||||||
char *command;
|
char *command;
|
||||||
char *fontname;
|
char *fontname;
|
||||||
i3String *separator_symbol;
|
i3String *separator_symbol;
|
||||||
char *tray_output;
|
TAILQ_HEAD(tray_outputs_head, tray_output_t) tray_outputs;
|
||||||
int tray_padding;
|
int tray_padding;
|
||||||
int num_outputs;
|
int num_outputs;
|
||||||
char **outputs;
|
char **outputs;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
static char *cur_key;
|
static char *cur_key;
|
||||||
static bool parsing_bindings;
|
static bool parsing_bindings;
|
||||||
|
static bool parsing_tray_outputs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a key.
|
* Parse a key.
|
||||||
|
@ -32,14 +33,20 @@ static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t
|
||||||
FREE(cur_key);
|
FREE(cur_key);
|
||||||
sasprintf(&(cur_key), "%.*s", keyLen, keyVal);
|
sasprintf(&(cur_key), "%.*s", keyLen, keyVal);
|
||||||
|
|
||||||
if (strcmp(cur_key, "bindings") == 0)
|
if (strcmp(cur_key, "bindings") == 0) {
|
||||||
parsing_bindings = true;
|
parsing_bindings = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cur_key, "tray_outputs") == 0) {
|
||||||
|
parsing_tray_outputs = true;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_end_array_cb(void *params_) {
|
static int config_end_array_cb(void *params_) {
|
||||||
parsing_bindings = false;
|
parsing_bindings = false;
|
||||||
|
parsing_tray_outputs = false;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +97,14 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parsing_tray_outputs) {
|
||||||
|
DLOG("Adding tray_output = %.*s to the list.\n", len, val);
|
||||||
|
tray_output_t *tray_output = scalloc(1, sizeof(tray_output_t));
|
||||||
|
sasprintf(&(tray_output->output), "%.*s", len, val);
|
||||||
|
TAILQ_INSERT_TAIL(&(config.tray_outputs), tray_output, tray_outputs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -195,10 +210,13 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We keep the old single tray_output working for users who only restart i3bar
|
||||||
|
* after updating. */
|
||||||
if (!strcmp(cur_key, "tray_output")) {
|
if (!strcmp(cur_key, "tray_output")) {
|
||||||
DLOG("tray_output %.*s\n", len, val);
|
DLOG("Found deprecated key tray_output %.*s.\n", len, val);
|
||||||
FREE(config.tray_output);
|
tray_output_t *tray_output = scalloc(1, sizeof(tray_output_t));
|
||||||
sasprintf(&config.tray_output, "%.*s", len, val);
|
sasprintf(&(tray_output->output), "%.*s", len, val);
|
||||||
|
TAILQ_INSERT_TAIL(&(config.tray_outputs), tray_output, tray_outputs);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,6 +335,7 @@ void parse_config_json(char *json) {
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
||||||
|
|
||||||
TAILQ_INIT(&(config.bindings));
|
TAILQ_INIT(&(config.bindings));
|
||||||
|
TAILQ_INIT(&(config.tray_outputs));
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
|
|
|
@ -728,25 +728,50 @@ static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG("X window %08x requested docking\n", client);
|
DLOG("X window %08x requested docking\n", client);
|
||||||
i3_output *walk, *output = NULL;
|
i3_output *output = NULL;
|
||||||
|
i3_output *walk = NULL;
|
||||||
|
tray_output_t *tray_output = NULL;
|
||||||
|
/* We need to iterate through the tray_output assignments first in
|
||||||
|
* order to prioritize them. Otherwise, if this bar manages two
|
||||||
|
* outputs and both are assigned as tray_output as well, the first
|
||||||
|
* output in our list would receive the tray rather than the first
|
||||||
|
* one defined via tray_output. */
|
||||||
|
TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) {
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH(walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
if (config.tray_output) {
|
|
||||||
if ((strcasecmp(walk->name, config.tray_output) != 0) &&
|
|
||||||
(!walk->primary || strcasecmp("primary", config.tray_output) != 0))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG("using output %s\n", walk->name);
|
if (strcasecmp(walk->name, tray_output->output) == 0) {
|
||||||
|
DLOG("Found tray_output assignment for output %s.\n", walk->name);
|
||||||
output = walk;
|
output = walk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (walk->primary && strcasecmp("primary", tray_output->output) == 0) {
|
||||||
|
DLOG("Found tray_output assignment on primary output %s.\n", walk->name);
|
||||||
|
output = walk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we found an output, we're done. */
|
||||||
|
if (output != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether any "tray_output primary" was defined for this bar. */
|
||||||
|
bool contains_primary = false;
|
||||||
|
TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) {
|
||||||
|
if (strcasecmp("primary", tray_output->output) == 0) {
|
||||||
|
contains_primary = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* In case of tray_output == primary and there is no primary output
|
/* In case of tray_output == primary and there is no primary output
|
||||||
* configured, we fall back to the first available output. */
|
* configured, we fall back to the first available output. We do the
|
||||||
if (output == NULL &&
|
* same if no tray_output was specified. */
|
||||||
config.tray_output &&
|
if (output == NULL && (contains_primary || TAILQ_EMPTY(&(config.tray_outputs)))) {
|
||||||
strcasecmp("primary", config.tray_output) == 0) {
|
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH(walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1707,20 +1732,37 @@ void reconfig_windows(bool redraw_bars) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *tray_output = (config.tray_output ? config.tray_output : SLIST_FIRST(outputs)->name);
|
/* Unless "tray_output none" was specified, we need to initialize the tray. */
|
||||||
if (!tray_configured && strcasecmp(tray_output, "none") != 0) {
|
const char *first = (TAILQ_EMPTY(&(config.tray_outputs))) ? SLIST_FIRST(outputs)->name : TAILQ_FIRST(&(config.tray_outputs))->output;
|
||||||
/* Configuration sanity check: ensure this i3bar instance handles the output on
|
if (!tray_configured && strcasecmp(first, "none") != 0) {
|
||||||
* which the tray should appear (e.g. don’t initialize a tray if tray_output ==
|
/* We do a sanity check here to ensure that this i3bar instance actually handles
|
||||||
* VGA-1 but output == [HDMI-1]).
|
* the output on which the tray should appear. For example,
|
||||||
*/
|
* consider tray_output == [VGA-1], but output == [HDMI-1]. */
|
||||||
|
|
||||||
|
/* If no tray_output was specified, we go ahead and initialize the tray as
|
||||||
|
* we will be using the first available output. */
|
||||||
|
if (TAILQ_EMPTY(&(config.tray_outputs)))
|
||||||
|
init_tray();
|
||||||
|
|
||||||
|
/* If one or more tray_output assignments were specified, we ensure that at least one of
|
||||||
|
* them is actually an output managed by this instance. */
|
||||||
|
tray_output_t *tray_output;
|
||||||
|
TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) {
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
|
bool found = false;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH(output, outputs, slist) {
|
||||||
if (strcasecmp(output->name, tray_output) == 0 ||
|
if (strcasecmp(output->name, tray_output->output) == 0 ||
|
||||||
(strcasecmp(tray_output, "primary") == 0 && output->primary)) {
|
(strcasecmp(tray_output->output, "primary") == 0 && output->primary)) {
|
||||||
|
found = true;
|
||||||
init_tray();
|
init_tray();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
tray_configured = true;
|
tray_configured = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -248,9 +248,10 @@ struct Barconfig {
|
||||||
* simplicity (since we store just strings). */
|
* simplicity (since we store just strings). */
|
||||||
char **outputs;
|
char **outputs;
|
||||||
|
|
||||||
/** Output on which the tray should be shown. The special value of 'no'
|
/* List of outputs on which the tray is allowed to be shown, in order.
|
||||||
* disables the tray (it’s enabled by default). */
|
* The special value "none" disables it (per default, it will be shown) and
|
||||||
char *tray_output;
|
* the special value "primary" enabled it on the primary output. */
|
||||||
|
TAILQ_HEAD(tray_outputs_head, tray_output_t) tray_outputs;
|
||||||
|
|
||||||
/* Padding around the tray icons. */
|
/* Padding around the tray icons. */
|
||||||
int tray_padding;
|
int tray_padding;
|
||||||
|
@ -366,6 +367,12 @@ struct Barbinding {
|
||||||
TAILQ_ENTRY(Barbinding) bindings;
|
TAILQ_ENTRY(Barbinding) bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tray_output_t {
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(tray_output_t) tray_outputs;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the configuration file to use (either the one specified by
|
* Finds the configuration file to use (either the one specified by
|
||||||
* override_configpath), the user’s one or the system default) and calls
|
* override_configpath), the user’s one or the system default) and calls
|
||||||
|
|
28
src/config.c
28
src/config.c
|
@ -75,20 +75,20 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
ungrab_all_keys(conn);
|
ungrab_all_keys(conn);
|
||||||
|
|
||||||
struct Mode *mode;
|
struct Mode *mode;
|
||||||
Binding *bind;
|
|
||||||
while (!SLIST_EMPTY(&modes)) {
|
while (!SLIST_EMPTY(&modes)) {
|
||||||
mode = SLIST_FIRST(&modes);
|
mode = SLIST_FIRST(&modes);
|
||||||
FREE(mode->name);
|
FREE(mode->name);
|
||||||
|
|
||||||
/* Clear the old binding list */
|
/* Clear the old binding list */
|
||||||
bindings = mode->bindings;
|
while (!TAILQ_EMPTY(mode->bindings)) {
|
||||||
while (!TAILQ_EMPTY(bindings)) {
|
Binding *bind = TAILQ_FIRST(mode->bindings);
|
||||||
bind = TAILQ_FIRST(bindings);
|
TAILQ_REMOVE(mode->bindings, bind, bindings);
|
||||||
TAILQ_REMOVE(bindings, bind, bindings);
|
|
||||||
binding_free(bind);
|
binding_free(bind);
|
||||||
}
|
}
|
||||||
FREE(bindings);
|
FREE(mode->bindings);
|
||||||
|
|
||||||
SLIST_REMOVE(&modes, mode, Mode, modes);
|
SLIST_REMOVE(&modes, mode, Mode, modes);
|
||||||
|
FREE(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Assignment *assign;
|
struct Assignment *assign;
|
||||||
|
@ -110,8 +110,22 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
FREE(barconfig->id);
|
FREE(barconfig->id);
|
||||||
for (int c = 0; c < barconfig->num_outputs; c++)
|
for (int c = 0; c < barconfig->num_outputs; c++)
|
||||||
free(barconfig->outputs[c]);
|
free(barconfig->outputs[c]);
|
||||||
|
|
||||||
|
while (!TAILQ_EMPTY(&(barconfig->bar_bindings))) {
|
||||||
|
struct Barbinding *binding = TAILQ_FIRST(&(barconfig->bar_bindings));
|
||||||
|
FREE(binding->command);
|
||||||
|
TAILQ_REMOVE(&(barconfig->bar_bindings), binding, bindings);
|
||||||
|
FREE(binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!TAILQ_EMPTY(&(barconfig->tray_outputs))) {
|
||||||
|
struct tray_output_t *tray_output = TAILQ_FIRST(&(barconfig->tray_outputs));
|
||||||
|
FREE(tray_output->output);
|
||||||
|
TAILQ_REMOVE(&(barconfig->tray_outputs), tray_output, tray_outputs);
|
||||||
|
FREE(tray_output);
|
||||||
|
}
|
||||||
|
|
||||||
FREE(barconfig->outputs);
|
FREE(barconfig->outputs);
|
||||||
FREE(barconfig->tray_output);
|
|
||||||
FREE(barconfig->socket_path);
|
FREE(barconfig->socket_path);
|
||||||
FREE(barconfig->status_command);
|
FREE(barconfig->status_command);
|
||||||
FREE(barconfig->i3bar_command);
|
FREE(barconfig->i3bar_command);
|
||||||
|
|
|
@ -399,57 +399,57 @@ CFGFUN(no_focus) {
|
||||||
* Bar configuration (i3bar)
|
* Bar configuration (i3bar)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static Barconfig current_bar;
|
static Barconfig *current_bar;
|
||||||
|
|
||||||
CFGFUN(bar_font, const char *font) {
|
CFGFUN(bar_font, const char *font) {
|
||||||
FREE(current_bar.font);
|
FREE(current_bar->font);
|
||||||
current_bar.font = sstrdup(font);
|
current_bar->font = sstrdup(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_separator_symbol, const char *separator) {
|
CFGFUN(bar_separator_symbol, const char *separator) {
|
||||||
FREE(current_bar.separator_symbol);
|
FREE(current_bar->separator_symbol);
|
||||||
current_bar.separator_symbol = sstrdup(separator);
|
current_bar->separator_symbol = sstrdup(separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_mode, const char *mode) {
|
CFGFUN(bar_mode, const char *mode) {
|
||||||
current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
|
current_bar->mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_hidden_state, const char *hidden_state) {
|
CFGFUN(bar_hidden_state, const char *hidden_state) {
|
||||||
current_bar.hidden_state = (strcmp(hidden_state, "hide") == 0 ? S_HIDE : S_SHOW);
|
current_bar->hidden_state = (strcmp(hidden_state, "hide") == 0 ? S_HIDE : S_SHOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_id, const char *bar_id) {
|
CFGFUN(bar_id, const char *bar_id) {
|
||||||
current_bar.id = sstrdup(bar_id);
|
current_bar->id = sstrdup(bar_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_output, const char *output) {
|
CFGFUN(bar_output, const char *output) {
|
||||||
int new_outputs = current_bar.num_outputs + 1;
|
int new_outputs = current_bar->num_outputs + 1;
|
||||||
current_bar.outputs = srealloc(current_bar.outputs, sizeof(char *) * new_outputs);
|
current_bar->outputs = srealloc(current_bar->outputs, sizeof(char *) * new_outputs);
|
||||||
current_bar.outputs[current_bar.num_outputs] = sstrdup(output);
|
current_bar->outputs[current_bar->num_outputs] = sstrdup(output);
|
||||||
current_bar.num_outputs = new_outputs;
|
current_bar->num_outputs = new_outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_verbose, const char *verbose) {
|
CFGFUN(bar_verbose, const char *verbose) {
|
||||||
current_bar.verbose = eval_boolstr(verbose);
|
current_bar->verbose = eval_boolstr(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_modifier, const char *modifier) {
|
CFGFUN(bar_modifier, const char *modifier) {
|
||||||
if (strcmp(modifier, "Mod1") == 0)
|
if (strcmp(modifier, "Mod1") == 0)
|
||||||
current_bar.modifier = M_MOD1;
|
current_bar->modifier = M_MOD1;
|
||||||
else if (strcmp(modifier, "Mod2") == 0)
|
else if (strcmp(modifier, "Mod2") == 0)
|
||||||
current_bar.modifier = M_MOD2;
|
current_bar->modifier = M_MOD2;
|
||||||
else if (strcmp(modifier, "Mod3") == 0)
|
else if (strcmp(modifier, "Mod3") == 0)
|
||||||
current_bar.modifier = M_MOD3;
|
current_bar->modifier = M_MOD3;
|
||||||
else if (strcmp(modifier, "Mod4") == 0)
|
else if (strcmp(modifier, "Mod4") == 0)
|
||||||
current_bar.modifier = M_MOD4;
|
current_bar->modifier = M_MOD4;
|
||||||
else if (strcmp(modifier, "Mod5") == 0)
|
else if (strcmp(modifier, "Mod5") == 0)
|
||||||
current_bar.modifier = M_MOD5;
|
current_bar->modifier = M_MOD5;
|
||||||
else if (strcmp(modifier, "Control") == 0 ||
|
else if (strcmp(modifier, "Control") == 0 ||
|
||||||
strcmp(modifier, "Ctrl") == 0)
|
strcmp(modifier, "Ctrl") == 0)
|
||||||
current_bar.modifier = M_CONTROL;
|
current_bar->modifier = M_CONTROL;
|
||||||
else if (strcmp(modifier, "Shift") == 0)
|
else if (strcmp(modifier, "Shift") == 0)
|
||||||
current_bar.modifier = M_SHIFT;
|
current_bar->modifier = M_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bar_configure_binding(const char *button, const char *command) {
|
static void bar_configure_binding(const char *button, const char *command) {
|
||||||
|
@ -465,7 +465,7 @@ static void bar_configure_binding(const char *button, const char *command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Barbinding *current;
|
struct Barbinding *current;
|
||||||
TAILQ_FOREACH(current, &(current_bar.bar_bindings), bindings) {
|
TAILQ_FOREACH(current, &(current_bar->bar_bindings), bindings) {
|
||||||
if (current->input_code == input_code) {
|
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;
|
||||||
|
@ -475,7 +475,7 @@ static void bar_configure_binding(const char *button, const char *command) {
|
||||||
struct Barbinding *new_binding = scalloc(1, sizeof(struct Barbinding));
|
struct Barbinding *new_binding = scalloc(1, sizeof(struct Barbinding));
|
||||||
new_binding->input_code = input_code;
|
new_binding->input_code = input_code;
|
||||||
new_binding->command = sstrdup(command);
|
new_binding->command = sstrdup(command);
|
||||||
TAILQ_INSERT_TAIL(&(current_bar.bar_bindings), new_binding, bindings);
|
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) {
|
||||||
|
@ -493,12 +493,12 @@ CFGFUN(bar_bindsym, const char *button, const char *command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_position, const char *position) {
|
CFGFUN(bar_position, const char *position) {
|
||||||
current_bar.position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM);
|
current_bar->position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_i3bar_command, const char *i3bar_command) {
|
CFGFUN(bar_i3bar_command, const char *i3bar_command) {
|
||||||
FREE(current_bar.i3bar_command);
|
FREE(current_bar->i3bar_command);
|
||||||
current_bar.i3bar_command = sstrdup(i3bar_command);
|
current_bar->i3bar_command = sstrdup(i3bar_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
|
CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
|
||||||
|
@ -507,13 +507,13 @@ CFGFUN(bar_color, const char *colorclass, const char *border, const char *backgr
|
||||||
if (strcmp(colorclass, #classname) == 0) { \
|
if (strcmp(colorclass, #classname) == 0) { \
|
||||||
if (text != NULL) { \
|
if (text != NULL) { \
|
||||||
/* New syntax: border, background, text */ \
|
/* New syntax: border, background, text */ \
|
||||||
current_bar.colors.classname##_border = sstrdup(border); \
|
current_bar->colors.classname##_border = sstrdup(border); \
|
||||||
current_bar.colors.classname##_bg = sstrdup(background); \
|
current_bar->colors.classname##_bg = sstrdup(background); \
|
||||||
current_bar.colors.classname##_text = sstrdup(text); \
|
current_bar->colors.classname##_text = sstrdup(text); \
|
||||||
} else { \
|
} else { \
|
||||||
/* Old syntax: text, background */ \
|
/* Old syntax: text, background */ \
|
||||||
current_bar.colors.classname##_bg = sstrdup(background); \
|
current_bar->colors.classname##_bg = sstrdup(background); \
|
||||||
current_bar.colors.classname##_text = sstrdup(border); \
|
current_bar->colors.classname##_text = sstrdup(border); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -528,73 +528,72 @@ CFGFUN(bar_color, const char *colorclass, const char *border, const char *backgr
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_socket_path, const char *socket_path) {
|
CFGFUN(bar_socket_path, const char *socket_path) {
|
||||||
FREE(current_bar.socket_path);
|
FREE(current_bar->socket_path);
|
||||||
current_bar.socket_path = sstrdup(socket_path);
|
current_bar->socket_path = sstrdup(socket_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_tray_output, const char *output) {
|
CFGFUN(bar_tray_output, const char *output) {
|
||||||
FREE(current_bar.tray_output);
|
struct tray_output_t *tray_output = scalloc(1, sizeof(struct tray_output_t));
|
||||||
current_bar.tray_output = sstrdup(output);
|
tray_output->output = sstrdup(output);
|
||||||
|
TAILQ_INSERT_TAIL(&(current_bar->tray_outputs), tray_output, tray_outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_tray_padding, const long padding_px) {
|
CFGFUN(bar_tray_padding, const long padding_px) {
|
||||||
current_bar.tray_padding = padding_px;
|
current_bar->tray_padding = padding_px;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_color_single, const char *colorclass, const char *color) {
|
CFGFUN(bar_color_single, const char *colorclass, const char *color) {
|
||||||
if (strcmp(colorclass, "background") == 0)
|
if (strcmp(colorclass, "background") == 0)
|
||||||
current_bar.colors.background = sstrdup(color);
|
current_bar->colors.background = sstrdup(color);
|
||||||
else if (strcmp(colorclass, "separator") == 0)
|
else if (strcmp(colorclass, "separator") == 0)
|
||||||
current_bar.colors.separator = sstrdup(color);
|
current_bar->colors.separator = sstrdup(color);
|
||||||
else if (strcmp(colorclass, "statusline") == 0)
|
else if (strcmp(colorclass, "statusline") == 0)
|
||||||
current_bar.colors.statusline = sstrdup(color);
|
current_bar->colors.statusline = sstrdup(color);
|
||||||
else if (strcmp(colorclass, "focused_background") == 0)
|
else if (strcmp(colorclass, "focused_background") == 0)
|
||||||
current_bar.colors.focused_background = sstrdup(color);
|
current_bar->colors.focused_background = sstrdup(color);
|
||||||
else if (strcmp(colorclass, "focused_separator") == 0)
|
else if (strcmp(colorclass, "focused_separator") == 0)
|
||||||
current_bar.colors.focused_separator = sstrdup(color);
|
current_bar->colors.focused_separator = sstrdup(color);
|
||||||
else
|
else
|
||||||
current_bar.colors.focused_statusline = sstrdup(color);
|
current_bar->colors.focused_statusline = sstrdup(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_status_command, const char *command) {
|
CFGFUN(bar_status_command, const char *command) {
|
||||||
FREE(current_bar.status_command);
|
FREE(current_bar->status_command);
|
||||||
current_bar.status_command = sstrdup(command);
|
current_bar->status_command = sstrdup(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_binding_mode_indicator, const char *value) {
|
CFGFUN(bar_binding_mode_indicator, const char *value) {
|
||||||
current_bar.hide_binding_mode_indicator = !eval_boolstr(value);
|
current_bar->hide_binding_mode_indicator = !eval_boolstr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_workspace_buttons, const char *value) {
|
CFGFUN(bar_workspace_buttons, const char *value) {
|
||||||
current_bar.hide_workspace_buttons = !eval_boolstr(value);
|
current_bar->hide_workspace_buttons = !eval_boolstr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_strip_workspace_numbers, const char *value) {
|
CFGFUN(bar_strip_workspace_numbers, const char *value) {
|
||||||
current_bar.strip_workspace_numbers = eval_boolstr(value);
|
current_bar->strip_workspace_numbers = eval_boolstr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_start) {
|
CFGFUN(bar_start) {
|
||||||
TAILQ_INIT(&(current_bar.bar_bindings));
|
current_bar = scalloc(1, sizeof(struct Barconfig));
|
||||||
current_bar.tray_padding = 2;
|
TAILQ_INIT(&(current_bar->bar_bindings));
|
||||||
|
TAILQ_INIT(&(current_bar->tray_outputs));
|
||||||
|
current_bar->tray_padding = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFGFUN(bar_finish) {
|
CFGFUN(bar_finish) {
|
||||||
DLOG("\t new bar configuration finished, saving.\n");
|
DLOG("\t new bar configuration finished, saving.\n");
|
||||||
/* Generate a unique ID for this bar if not already configured */
|
/* Generate a unique ID for this bar if not already configured */
|
||||||
if (!current_bar.id)
|
if (current_bar->id == NULL)
|
||||||
sasprintf(¤t_bar.id, "bar-%d", config.number_barconfigs);
|
sasprintf(¤t_bar->id, "bar-%d", config.number_barconfigs);
|
||||||
|
|
||||||
config.number_barconfigs++;
|
config.number_barconfigs++;
|
||||||
|
|
||||||
/* If no font was explicitly set, we use the i3 font as default */
|
/* If no font was explicitly set, we use the i3 font as default */
|
||||||
if (!current_bar.font && font_pattern)
|
if (current_bar->font == NULL && font_pattern != NULL)
|
||||||
current_bar.font = sstrdup(font_pattern);
|
current_bar->font = sstrdup(font_pattern);
|
||||||
|
|
||||||
/* Copy the current (static) structure into a dynamically allocated
|
TAILQ_INSERT_TAIL(&barconfigs, current_bar, configs);
|
||||||
* one, then cleanup our static one. */
|
/* Simply reset the pointer, but don't free the resources. */
|
||||||
Barconfig *bar_config = scalloc(1, sizeof(Barconfig));
|
current_bar = NULL;
|
||||||
memcpy(bar_config, ¤t_bar, sizeof(Barconfig));
|
|
||||||
TAILQ_INSERT_TAIL(&barconfigs, bar_config, configs);
|
|
||||||
|
|
||||||
memset(¤t_bar, '\0', sizeof(Barconfig));
|
|
||||||
}
|
}
|
||||||
|
|
14
src/ipc.c
14
src/ipc.c
|
@ -551,6 +551,18 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
y(array_close);
|
y(array_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!TAILQ_EMPTY(&(config->tray_outputs))) {
|
||||||
|
ystr("tray_outputs");
|
||||||
|
y(array_open);
|
||||||
|
|
||||||
|
struct tray_output_t *tray_output;
|
||||||
|
TAILQ_FOREACH(tray_output, &(config->tray_outputs), tray_outputs) {
|
||||||
|
ystr(tray_output->output);
|
||||||
|
}
|
||||||
|
|
||||||
|
y(array_close);
|
||||||
|
}
|
||||||
|
|
||||||
#define YSTR_IF_SET(name) \
|
#define YSTR_IF_SET(name) \
|
||||||
do { \
|
do { \
|
||||||
if (config->name) { \
|
if (config->name) { \
|
||||||
|
@ -559,8 +571,6 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
YSTR_IF_SET(tray_output);
|
|
||||||
|
|
||||||
ystr("tray_padding");
|
ystr("tray_padding");
|
||||||
y(integer, config->tray_padding);
|
y(integer, config->tray_padding);
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ ok(!$bar_config->{binding_mode_indicator}, 'mode indicator disabled');
|
||||||
is($bar_config->{mode}, 'dock', 'dock mode');
|
is($bar_config->{mode}, 'dock', 'dock mode');
|
||||||
is($bar_config->{position}, 'top', 'position top');
|
is($bar_config->{position}, 'top', 'position top');
|
||||||
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok');
|
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok');
|
||||||
is($bar_config->{tray_output}, 'HDMI2', 'tray_output ok');
|
is_deeply($bar_config->{tray_outputs}, [ 'LVDS1', 'HDMI2' ], 'tray_output ok');
|
||||||
is($bar_config->{tray_padding}, 0, 'tray_padding ok');
|
is($bar_config->{tray_padding}, 0, 'tray_padding ok');
|
||||||
is($bar_config->{font}, 'Terminus', 'font ok');
|
is($bar_config->{font}, 'Terminus', 'font ok');
|
||||||
is($bar_config->{socket_path}, '/tmp/foobar', 'socket_path ok');
|
is($bar_config->{socket_path}, '/tmp/foobar', 'socket_path ok');
|
||||||
|
@ -294,7 +294,7 @@ ok($bar_config->{binding_mode_indicator}, 'mode indicator enabled');
|
||||||
is($bar_config->{mode}, 'dock', 'dock mode');
|
is($bar_config->{mode}, 'dock', 'dock mode');
|
||||||
is($bar_config->{position}, 'top', 'position top');
|
is($bar_config->{position}, 'top', 'position top');
|
||||||
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok');
|
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok');
|
||||||
is($bar_config->{tray_output}, 'HDMI2', 'tray_output ok');
|
is_deeply($bar_config->{tray_outputs}, [ 'LVDS1', 'HDMI2' ], 'tray_output ok');
|
||||||
is($bar_config->{font}, 'Terminus', 'font ok');
|
is($bar_config->{font}, 'Terminus', 'font ok');
|
||||||
is($bar_config->{socket_path}, '/tmp/foobar', 'socket_path ok');
|
is($bar_config->{socket_path}, '/tmp/foobar', 'socket_path ok');
|
||||||
is_deeply($bar_config->{colors},
|
is_deeply($bar_config->{colors},
|
||||||
|
|
Loading…
Reference in New Issue