introduced i3 command for changing the hidden state and the mode of i3bar

The hidden_state and mode of each i3bar instance can now be controlled from within i3.
Therefore, two new i3 command were introduced:
    _
    bar hidden_state show|hide|toggle [<bar_id>]

    show: always show the bar
    hide: normal hide mode
    toggle: toggle between show and hide (individually for each bar)
    _
    bar mode dock|hide|invisible|toggle [<bar_id>]

    hide,dock: like before
    invisible: always keep the bar hidden
    toggle: toggle between dock and hide (individually for each bar)

This patch introduces a hidden_state ("hidden_state hide|show") in the
barconfig, which indicates the current hidden_state of each i3bar
instance. It only affects the bar when in hide mode. Additionally, a new
invisible mode was introduced. In order to change the hidden_state or
mode of the bar from i3, a barconfig-update event was introduced, for
which a bar can subscribe and the bar then gets notified about the
currently set hidden_state and mode in its barconfig.

For convenience, an id field ("id <bar_id>") was added to the barconfig, where one can
set the desired id for the corresponding bar. If the id is not specified, i3 will
deterministically choose an id; otherwise, with the previous random approach for finding
a new id, which is actually not shared with i3bar, as it would determine its id on
startup, the event-subscription would be destroyed on reload. Still, this issue remains
when manually changing the bar_id in the config and then reloading.

fixes #833, #651
This commit is contained in:
haptix@web.de 2013-05-25 14:30:00 +02:00 committed by Michael Stapelberg
parent f0eba6d15c
commit e3913093b6
18 changed files with 470 additions and 58 deletions

View File

@ -626,6 +626,9 @@ mode (2)::
window (3)::
Sent when a client's window is successfully reparented (that is when i3
has finished fitting it into a container).
barconfig_update (4)::
Sent when the hidden_state or mode field in the barconfig of any bar
instance was updated.
*Example:*
--------------------------------------------------------------------
@ -723,6 +726,24 @@ window title as "urxvt").
}
---------------------------
=== barconfig_update event
This event consists of a single serialized map reporting on options from the
barconfig of the specified bar_id that were updated in i3. The map always
consists of a property +id (string)+, which specifies to which bar instance the
sent config update belongs, a property +hidden_state (string)+, which indicates
the hidden_state of an i3bar instance, and a property +mode (string)+, which
corresponds to the current mode.
*Example:*
---------------------------
{
"id": "bar-0",
"hidden_state": "hide"
"mode": "hide"
}
---------------------------
== See also (existing libraries)
[[libraries]]

View File

@ -996,20 +996,39 @@ bar {
=== Display mode
You can have i3bar either be visible permanently at one edge of the screen
(+dock+ mode) or make it show up when you press your modifier key (+hide+
You can either have i3bar be visible permanently at one edge of the screen
(+dock+ mode) or make it show up when you press your modifier key (+hide+ mode).
It is also possible to force i3bar to always stay hidden (+invisible+
mode). The modifier key can be configured using the +modifier+ option.
The mode option can be changed during runtime through the +bar mode+ command.
On reload the mode will be reverted to its configured value.
The hide mode maximizes screen space that can be used for actual windows. Also,
i3bar sends the +SIGSTOP+ and +SIGCONT+ signals to the statusline process to
save battery power.
The default is dock mode; in hide mode, the default modifier is Mod4 (usually
the windows key).
Invisible mode allows to permanently maximize screen space, as the bar is never
shown. Thus, you can configure i3bar to not disturb you by popping up because
of an urgency hint or because the modifier key is pressed.
In order to control whether i3bar is hidden or shown in hide mode, there exists
the hidden_state option, which has no effect in dock mode or invisible mode. It
indicates the current hidden_state of the bar: (1) The bar acts like in normal
hide mode, it is hidden and is only unhidden in case of urgency hints or by
pressing the modifier key (+hide+ state), or (2) it is drawn on top of the
currently visible workspace (+show+ state).
Like the mode, the hidden_state can also be controlled through i3, this can be
done by using the +bar hidden_state+ command.
The default mode is dock mode; in hide mode, the default modifier is Mod4 (usually
the windows key). The default value for the hidden_state is hide.
*Syntax*:
----------------
mode <dock|hide>
mode <dock|hide|invisible>
hidden_state <hide|show>
modifier <Modifier>
----------------
@ -1017,12 +1036,31 @@ modifier <Modifier>
----------------
bar {
mode hide
hidden_state hide
modifier Mod1
}
----------------
Available modifiers are Mod1-Mod5, Shift, Control (see +xmodmap(1)+).
=== Bar ID
Specifies the bar ID for the configured bar instance. If this option is missing,
the ID is set to 'bar-x', where x corresponds to the position of the embedding
bar block in the config file ('bar-0', 'bar-1', ...).
*Syntax*:
---------------------
id <bar_id>
---------------------
*Example*:
---------------------
bar {
id bar-1
}
---------------------
[[i3bar_position]]
=== Position
@ -1775,6 +1813,38 @@ bindsym $mod+minus scratchpad show
bindsym mod4+s [title="^Sup ::"] scratchpad show
------------------------------------------------
=== i3bar control
There are two options in the configuration of each i3bar instance that can be
changed during runtime by invoking a command through i3. The commands +bar
hidden_state+ and +bar mode+ allow setting the current hidden_state
respectively mode option of each bar. It is also possible to toggle between
hide state and show state as well as between dock mode and hide mode. Each
i3bar instance can be controlled individually by specifying a bar_id, if none
is given, the command is executed for all bar instances.
*Syntax*:
---------------
bar hidden_state hide|show|toggle [<bar_id>]
bar mode dock|hide|invisible|toggle [<bar_id>]
---------------
*Examples*:
------------------------------------------------
# Toggle between hide state and show state
bindsym $mod+m bar hidden_state toggle
# Toggle between dock mode and hide mode
bindsym $mod+n bar mode toggle
# Set the bar instance with id 'bar-1' to switch to hide mode
bindsym $mod+b bar mode hide bar-1
# Set the bar instance with id 'bar-1' to always stay hidden
bindsym $mod+Shift+b bar mode invisible bar-1
------------------------------------------------
[[multi_monitor]]
== Multiple monitors

View File

@ -19,7 +19,6 @@ typedef enum {
} position_t;
typedef struct config_t {
int hide_on_modifier;
int modifier;
position_t position;
int verbose;
@ -31,6 +30,12 @@ typedef struct config_t {
char *tray_output;
int num_outputs;
char **outputs;
/* Bar display mode (hide unless modifier is pressed or show in dock mode or always hide in invisible mode) */
enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } hide_on_modifier;
/* The current hidden_state of the bar, which indicates whether it is hidden or shown */
enum { S_HIDE = 0, S_SHOW = 1 } hidden_state;
} config_t;
config_t config;

View File

@ -73,7 +73,15 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in
if (!strcmp(cur_key, "mode")) {
DLOG("mode = %.*s, len = %d\n", len, val, len);
config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")));
config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "dock", strlen("dock")) ? M_DOCK
: (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? M_HIDE
: M_INVISIBLE));
return 1;
}
if (!strcmp(cur_key, "hidden_state")) {
DLOG("hidden_state = %.*s, len = %d\n", len, val, len);
config.hidden_state = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? S_HIDE : S_SHOW);
return 1;
}

View File

@ -149,12 +149,37 @@ void got_mode_event(char *event) {
draw_bars(false);
}
/*
* Called, when a barconfig_update event arrives (i.e. i3 changed the bar hidden_state or mode)
*
*/
void got_bar_config_update(char *event) {
/* check whether this affect this bar instance by checking the bar_id */
char *expected_id;
sasprintf(&expected_id, "\"id\":\"%s\"", config.bar_id);
char *found_id = strstr(event, expected_id);
FREE(expected_id);
if (found_id == NULL)
return;
/* Data-structure to easily call the reply-handlers later */
/* update the configuration with the received settings */
DLOG("Received bar config update \"%s\"\n", event);
int old_mode = config.hide_on_modifier;
parse_config_json(event);
if (old_mode != config.hide_on_modifier) {
reconfig_windows();
}
draw_bars(false);
}
/* Data-structure to easily call the event-handlers later */
handler_t event_handlers[] = {
&got_workspace_event,
&got_output_event,
&got_mode_event
&got_mode_event,
NULL,
&got_bar_config_update,
};
/*
@ -310,8 +335,8 @@ void destroy_connection(void) {
*/
void subscribe_events(void) {
if (config.disable_ws) {
i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"output\", \"mode\" ]");
i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"output\", \"mode\", \"barconfig_update\" ]");
} else {
i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"workspace\", \"output\", \"mode\" ]");
i3_send_msg(I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[ \"workspace\", \"output\", \"mode\", \"barconfig_update\" ]");
}
}

View File

@ -198,7 +198,7 @@ void refresh_statusline(void) {
*
*/
void hide_bars(void) {
if (!config.hide_on_modifier) {
if ((config.hide_on_modifier == M_DOCK) || (config.hidden_state == S_SHOW)) {
return;
}
@ -217,7 +217,7 @@ void hide_bars(void) {
*
*/
void unhide_bars(void) {
if (!config.hide_on_modifier) {
if (config.hide_on_modifier != M_HIDE) {
return;
}
@ -988,25 +988,13 @@ char *init_xcb_early() {
}
/*
* Initialization which depends on 'config' being usable. Called after the
* configuration has arrived.
* Register for xkb keyevents. To grab modifiers without blocking other applications from receiving key-events
* involving that modifier, we sadly have to use xkb which is not yet fully supported
* in xcb.
*
*/
void init_xcb_late(char *fontname) {
if (fontname == NULL)
fontname = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1";
/* Load the font */
font = load_font(fontname, true);
set_font(&font);
DLOG("Calculated Font-height: %d\n", font.height);
xcb_flush(xcb_connection);
/* To grab modifiers without blocking other applications from receiving key-events
* involving that modifier, we sadly have to use xkb which is not yet fully supported
* in xcb */
if (config.hide_on_modifier) {
void register_xkb_keyevents() {
if (xkb_dpy == NULL) {
int xkb_major, xkb_minor, xkb_errbase, xkb_err;
xkb_major = XkbMajorVersion;
xkb_minor = XkbMinorVersion;
@ -1046,6 +1034,39 @@ void init_xcb_late(char *fontname) {
}
}
/*
* Deregister from xkb keyevents.
*
*/
void deregister_xkb_keyevents() {
if (xkb_dpy != NULL) {
ev_io_stop (main_loop, xkb_io);
close(xkb_io->fd);
FREE(xkb_io);
FREE(xkb_dpy);
}
}
/*
* Initialization which depends on 'config' being usable. Called after the
* configuration has arrived.
*
*/
void init_xcb_late(char *fontname) {
if (fontname == NULL)
fontname = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1";
/* Load the font */
font = load_font(fontname, true);
set_font(&font);
DLOG("Calculated Font-height: %d\n", font.height);
xcb_flush(xcb_connection);
if (config.hide_on_modifier == M_HIDE)
register_xkb_keyevents();
}
/*
* Inform clients waiting for a new _NET_SYSTEM_TRAY that we took the
* selection.
@ -1368,8 +1389,8 @@ void reconfig_windows(void) {
mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
/* Black background */
values[0] = colors.bar_bg;
/* If hide_on_modifier is set, i3 is not supposed to manage our bar-windows */
values[1] = config.hide_on_modifier;
/* If hide_on_modifier is set to hide or invisible mode, i3 is not supposed to manage our bar-windows */
values[1] = (config.hide_on_modifier == M_DOCK ? 0 : 1);
/* We enable the following EventMask fields:
* EXPOSURE, to get expose events (we have to re-draw then)
* SUBSTRUCTURE_REDIRECT, to get ConfigureRequests when the tray
@ -1490,7 +1511,7 @@ void reconfig_windows(void) {
/* We finally map the bar (display it on screen), unless the modifier-switch is on */
xcb_void_cookie_t map_cookie;
if (!config.hide_on_modifier) {
if (config.hide_on_modifier == M_DOCK) {
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
}
@ -1501,7 +1522,7 @@ void reconfig_windows(void) {
xcb_request_failed(name_cookie, "Could not set WM_NAME") ||
xcb_request_failed(strut_cookie, "Could not set strut") ||
xcb_request_failed(gc_cookie, "Could not create graphical context") ||
(!config.hide_on_modifier && xcb_request_failed(map_cookie, "Could not map window"))) {
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
exit(EXIT_FAILURE);
}
@ -1533,6 +1554,14 @@ void reconfig_windows(void) {
mask,
values);
mask = XCB_CW_OVERRIDE_REDIRECT;
values[0] = (config.hide_on_modifier == M_DOCK ? 0 : 1);
DLOG("Changing Window attribute override_redirect for output %s to %d\n", walk->name, values[0]);
xcb_void_cookie_t chg_cookie = xcb_change_window_attributes(xcb_connection,
walk->bar,
mask,
values);
DLOG("Recreating buffer for output %s\n", walk->name);
xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection,
root_screen->root_depth,
@ -1541,10 +1570,27 @@ void reconfig_windows(void) {
walk->rect.w,
walk->rect.h);
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window")) {
exit(EXIT_FAILURE);
/* Unmap the window, and draw it again when in dock mode */
xcb_void_cookie_t umap_cookie = xcb_unmap_window_checked(xcb_connection, walk->bar);
xcb_void_cookie_t map_cookie;
if (config.hide_on_modifier == M_DOCK) {
cont_child();
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
}
if (xcb_request_failed(pm_cookie, "Could not create pixmap")) {
if (config.hide_on_modifier == M_HIDE) {
/* Switching to hide mode, register for keyevents */
register_xkb_keyevents();
} else {
/* Switching to dock/invisible mode, deregister from keyevents */
deregister_xkb_keyevents();
}
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") ||
xcb_request_failed(chg_cookie, "Could not change window") ||
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
xcb_request_failed(umap_cookie, "Could not unmap window") ||
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
exit(EXIT_FAILURE);
}
}
@ -1718,11 +1764,14 @@ void draw_bars(bool unhide) {
i = 1;
}
/* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */
bool should_unhide = (config.hidden_state == S_SHOW || (unhide && config.hidden_state == S_HIDE));
bool should_hide = (config.hide_on_modifier == M_INVISIBLE);
if (!mod_pressed) {
if (unhide) {
/* The urgent-hint should get noticed, so we unhide the bars shortly */
if ((unhide || should_unhide) && !should_hide) {
unhide_bars();
} else if (walks_away) {
} else if (walks_away || should_hide) {
FREE(last_urgent_ws);
hide_bars();
}

View File

@ -265,4 +265,10 @@ void cmd_scratchpad_show(I3_CMD);
*/
void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name);
/**
* Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
*
*/
void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id);
#endif

View File

@ -199,6 +199,9 @@ struct Config {
/* just ignore the popup, that is, dont map it */
PDF_IGNORE = 2,
} popup_during_fullscreen;
/* The number of currently parsed barconfigs */
int number_barconfigs;
};
/**
@ -226,8 +229,11 @@ struct Barconfig {
* root window! */
char *socket_path;
/** Bar display mode (hide unless modifier is pressed or show in dock mode) */
enum { M_DOCK = 0, M_HIDE = 1 } mode;
/** Bar display mode (hide unless modifier is pressed or show in dock mode or always hide in invisible mode) */
enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } mode;
/* The current hidden_state of the bar, which indicates whether it is hidden or shown */
enum { S_HIDE = 0, S_SHOW = 1 } hidden_state;
/** Bar modifier (to show bar when in hide mode). */
enum {
@ -323,6 +329,12 @@ void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch);
*/
void switch_mode(const char *new_mode);
/**
* Sends the current bar configuration as an event to all barconfig_update listeners.
* This update mechnism currently only includes the hidden_state and the mode in the config.
*
*/void update_barconfig();
/**
* Returns a pointer to the Binding with the specified modifiers and keycode
* or NULL if no such binding exists.

View File

@ -62,6 +62,8 @@ CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *ke
CFGFUN(bar_font, const char *font);
CFGFUN(bar_mode, const char *mode);
CFGFUN(bar_hidden_state, const char *hidden_state);
CFGFUN(bar_id, const char *bar_id);
CFGFUN(bar_output, const char *output);
CFGFUN(bar_verbose, const char *verbose);
CFGFUN(bar_modifier, const char *modifier);

View File

@ -99,4 +99,7 @@ typedef struct i3_ipc_header {
/* The window event will be triggered upon window changes */
#define I3_IPC_EVENT_WINDOW (I3_IPC_EVENT_MASK | 3)
/** Bar config update will be triggered to update the bar config */
#define I3_IPC_EVENT_BARCONFIG_UPDATE (I3_IPC_EVENT_MASK | 4)
#endif

View File

@ -35,6 +35,7 @@ state INITIAL:
'nop' -> NOP
'scratchpad' -> SCRATCHPAD
'mode' -> MODE
'bar' -> BAR
state CRITERIA:
ctype = 'class' -> CRITERION
@ -319,3 +320,24 @@ state NOP:
state SCRATCHPAD:
'show'
-> call cmd_scratchpad_show()
# bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]
state BAR:
bar_type = 'hidden_state'
-> BAR_HIDDEN_STATE
bar_type = 'mode'
-> BAR_MODE
state BAR_HIDDEN_STATE:
bar_value = 'hide', 'show', 'toggle'
-> BAR_W_ID
state BAR_MODE:
bar_value = 'dock', 'hide', 'invisible', 'toggle'
-> BAR_W_ID
state BAR_W_ID:
bar_id = word
->
end
-> call cmd_bar($bar_type, $bar_value, $bar_id)

View File

@ -349,6 +349,8 @@ state BAR:
'status_command' -> BAR_STATUS_COMMAND
'socket_path' -> BAR_SOCKET_PATH
'mode' -> BAR_MODE
'hidden_state' -> BAR_HIDDEN_STATE
'id' -> BAR_ID
'modifier' -> BAR_MODIFIER
'position' -> BAR_POSITION
'output' -> BAR_OUTPUT
@ -378,9 +380,17 @@ state BAR_SOCKET_PATH:
-> call cfg_bar_socket_path($path); BAR
state BAR_MODE:
mode = 'dock', 'hide'
mode = 'dock', 'hide', 'invisible'
-> call cfg_bar_mode($mode); BAR
state BAR_HIDDEN_STATE:
hidden_state = 'hide', 'show'
-> call cfg_bar_hidden_state($hidden_state); BAR
state BAR_ID:
bar_id = word
-> call cfg_bar_id($bar_id); BAR
state BAR_MODIFIER:
modifier = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Control', 'Ctrl', 'Shift'
-> call cfg_bar_modifier($modifier); BAR

View File

@ -1632,6 +1632,8 @@ void cmd_reload(I3_CMD) {
x_set_i3_atoms();
/* Send an IPC event just in case the ws names have changed */
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}");
/* Send an update event for the barconfig just in case it has changed */
update_barconfig();
// XXX: default reply for now, make this a better reply
ysuccess(true);
@ -1915,3 +1917,113 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"rename\"}");
}
/*
* Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
*
*/
bool cmd_bar_mode(char *bar_mode, char *bar_id) {
int mode;
bool toggle = false;
if (strcmp(bar_mode, "dock") == 0)
mode = M_DOCK;
else if (strcmp(bar_mode, "hide") == 0)
mode = M_HIDE;
else if (strcmp(bar_mode, "invisible") == 0)
mode = M_INVISIBLE;
else if (strcmp(bar_mode, "toggle") == 0)
toggle = true;
else {
ELOG("Unknown bar mode \"%s\", this is a mismatch between code and parser spec.\n", bar_mode);
return false;
}
bool changed_sth = false;
Barconfig *current = NULL;
TAILQ_FOREACH(current, &barconfigs, configs) {
if (bar_id && strcmp(current->id, bar_id) != 0)
continue;
if (toggle)
mode = (current->mode + 1) % 2;
DLOG("Changing bar mode of bar_id '%s' to '%s (%d)'\n", current->id, bar_mode, mode);
current->mode = mode;
changed_sth = true;
if (bar_id)
break;
}
if (bar_id && !changed_sth) {
DLOG("Changing bar mode of bar_id %s failed, bar_id not found.\n", bar_id);
return false;
}
return true;
}
/*
* Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
*
*/
bool cmd_bar_hidden_state(char *bar_hidden_state, char *bar_id) {
int hidden_state;
bool toggle = false;
if (strcmp(bar_hidden_state, "hide") == 0)
hidden_state = S_HIDE;
else if (strcmp(bar_hidden_state, "show") == 0)
hidden_state = S_SHOW;
else if (strcmp(bar_hidden_state, "toggle") == 0)
toggle = true;
else {
ELOG("Unknown bar state \"%s\", this is a mismatch between code and parser spec.\n", bar_hidden_state);
return false;
}
bool changed_sth = false;
Barconfig *current = NULL;
TAILQ_FOREACH(current, &barconfigs, configs) {
if (bar_id && strcmp(current->id, bar_id) != 0)
continue;
if (toggle)
hidden_state = (current->hidden_state + 1) % 2;
DLOG("Changing bar hidden_state of bar_id '%s' to '%s (%d)'\n", current->id, bar_hidden_state, hidden_state);
current->hidden_state = hidden_state;
changed_sth = true;
if (bar_id)
break;
}
if (bar_id && !changed_sth) {
DLOG("Changing bar hidden_state of bar_id %s failed, bar_id not found.\n", bar_id);
return false;
}
return true;
}
/*
* Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
*
*/
void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) {
bool ret;
if (strcmp(bar_type, "mode") == 0)
ret = cmd_bar_mode(bar_value, bar_id);
else if (strcmp(bar_type, "hidden_state") == 0)
ret = cmd_bar_hidden_state(bar_value, bar_id);
else {
ELOG("Unknown bar option type \"%s\", this is a mismatch between code and parser spec.\n", bar_type);
ret = false;
}
ysuccess(ret);
if (!ret)
return;
update_barconfig();
}

View File

@ -210,6 +210,49 @@ void switch_mode(const char *new_mode) {
ELOG("ERROR: Mode not found\n");
}
/*
* Sends the current bar configuration as an event to all barconfig_update listeners.
* This update mechnism currently only includes the hidden_state and the mode in the config.
*
*/
void update_barconfig() {
Barconfig *current;
TAILQ_FOREACH(current, &barconfigs, configs) {
/* Build json message */
char *hidden_state;
switch (current->hidden_state) {
case S_SHOW:
hidden_state ="show";
break;
case S_HIDE:
default:
hidden_state = "hide";
break;
}
char *mode;
switch (current->mode) {
case M_HIDE:
mode ="hide";
break;
case M_INVISIBLE:
mode ="invisible";
break;
case M_DOCK:
default:
mode = "dock";
break;
}
/* Send an event to all barconfig listeners*/
char *event_msg;
sasprintf(&event_msg, "{ \"id\":\"%s\", \"hidden_state\":\"%s\", \"mode\":\"%s\" }", current->id, hidden_state, mode);
ipc_send_event("barconfig_update", I3_IPC_EVENT_BARCONFIG_UPDATE, event_msg);
FREE(event_msg);
}
}
/*
* Get the path of the first configuration file found. If override_configpath
* is specified, that path is returned and saved for further calls. Otherwise,

View File

@ -452,7 +452,15 @@ CFGFUN(bar_font, const char *font) {
}
CFGFUN(bar_mode, const char *mode) {
current_bar.mode = (strcmp(mode, "hide") == 0 ? M_HIDE : M_DOCK);
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) {
current_bar.hidden_state = (strcmp(hidden_state, "hide") == 0 ? S_HIDE : S_SHOW);
}
CFGFUN(bar_id, const char *bar_id) {
current_bar.id = sstrdup(bar_id);
}
CFGFUN(bar_output, const char *output) {
@ -548,15 +556,11 @@ CFGFUN(bar_workspace_buttons, const char *value) {
CFGFUN(bar_finish) {
DLOG("\t new bar configuration finished, saving.\n");
/* Generate a unique ID for this bar */
current_bar.id = sstrdup("bar-XXXXXX");
/* This works similar to mktemp in that it replaces the last six X with
* random letters, but without the restriction that the given buffer
* has to contain a valid path name. */
char *x = current_bar.id + strlen("bar-");
while (*x != '\0') {
*(x++) = (rand() % 26) + 'a';
}
/* Generate a unique ID for this bar if not already configured */
if (!current_bar.id)
sasprintf(&current_bar.id, "bar-%d", config.number_barconfigs);
config.number_barconfigs++;
/* If no font was explicitly set, we use the i3 font as default */
if (!current_bar.font && font_pattern)

View File

@ -621,9 +621,29 @@ IPC_HANDLER(get_bar_config) {
YSTR_IF_SET(socket_path);
ystr("mode");
if (config->mode == M_HIDE)
ystr("hide");
else ystr("dock");
switch (config->mode) {
case M_HIDE:
ystr("hide");
break;
case M_INVISIBLE:
ystr("invisible");
break;
case M_DOCK:
default:
ystr("dock");
break;
}
ystr("hidden_state");
switch (config->hidden_state) {
case S_SHOW:
ystr("show");
break;
case S_HIDE:
default:
ystr("hide");
break;
}
ystr("modifier");
switch (config->modifier) {

View File

@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"),
################################################################################
is(parser_calls('unknown_literal'),
"ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode'\n" .
"ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" .
"ERROR: Your command: unknown_literal\n" .
"ERROR: ^^^^^^^^^^^^^^^",
'error for unknown literal ok');

View File

@ -627,7 +627,7 @@ EOT
$expected = <<'EOT';
cfg_bar_output(LVDS-1)
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'modifier', 'position', 'output', 'tray_output', 'font', 'workspace_buttons', 'verbose', 'colors', '}'
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'workspace_buttons', 'verbose', 'colors', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1