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
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:*
--------------------------------------------------------------------
}
---------------------------
+=== 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]]
=== 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>
----------------
----------------
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
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
} position_t;
typedef struct config_t {
- int hide_on_modifier;
int modifier;
position_t position;
int verbose;
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;
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;
}
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;
+
+ /* 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();
+ }
-/* Data-structure to easily call the reply-handlers later */
+ 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,
};
/*
*/
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\" ]");
}
}
*
*/
void hide_bars(void) {
- if (!config.hide_on_modifier) {
+ if ((config.hide_on_modifier == M_DOCK) || (config.hidden_state == S_SHOW)) {
return;
}
*
*/
void unhide_bars(void) {
- if (!config.hide_on_modifier) {
+ if (config.hide_on_modifier != M_HIDE) {
return;
}
}
/*
- * 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;
}
}
+/*
+ * 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.
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
/* 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);
}
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);
}
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,
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 (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(pm_cookie, "Could not create pixmap")) {
+
+ 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);
}
}
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();
}
*/
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
/* just ignore the popup, that is, don’t map it */
PDF_IGNORE = 2,
} popup_during_fullscreen;
+
+ /* The number of currently parsed barconfigs */
+ int number_barconfigs;
};
/**
* 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 {
*/
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.
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);
/* 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
'nop' -> NOP
'scratchpad' -> SCRATCHPAD
'mode' -> MODE
+ 'bar' -> BAR
state CRITERIA:
ctype = 'class' -> CRITERION
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)
'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
-> 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
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);
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();
+}
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,
}
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) {
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(¤t_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)
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) {
################################################################################
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');
$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