diff --git a/docs/ipc b/docs/ipc index 4093ffce..db1ef681 100644 --- a/docs/ipc +++ b/docs/ipc @@ -1,7 +1,7 @@ IPC interface (interprocess communication) ========================================== Michael Stapelberg -March 2010 +October 2011 This document describes how to interface with i3 from a separate process. This is useful for example to remote-control i3 (to write test cases for example) or @@ -12,7 +12,7 @@ The method of choice for IPC in our case is a unix socket because it has very little overhead on both sides and is usually available without headaches in most languages. In the default configuration file, the ipc-socket gets created in +/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the -PID of i3. +PID of i3. You can get the socketpath from i3 by calling +i3 --get-socketpath+. All i3 utilities, like +i3-msg+ and +i3-input+ will read the +I3_SOCKET_PATH+ X11 property, stored on the X11 root window. @@ -24,7 +24,8 @@ snippet illustrates this in Perl: ------------------------------------------------------------- use IO::Socket::UNIX; -my $sock = IO::Socket::UNIX->new(Peer => '/tmp/i3-ipc.sock'); +chomp(my $path = qx(i3 --get-socketpath)); +my $sock = IO::Socket::UNIX->new(Peer => $path); ------------------------------------------------------------- == Sending messages to i3 @@ -63,6 +64,10 @@ GET_MARKS (5):: Gets a list of marks (identifiers for containers to easily jump to them later). The reply will be a JSON-encoded list of window marks (see reply section). +GET_BAR_CONFIG (6):: + Gets the configuration (as JSON map) of the workspace bar with the + given ID. If no ID is provided, an array with all configured bar IDs is + returned instead. So, a typical message could look like this: -------------------------------------------------- @@ -116,6 +121,8 @@ GET_TREE (4):: Reply to the GET_TREE message. GET_MARKS (5):: Reply to the GET_MARKS message. +GET_BAR_CONFIG (6):: + Reply to the GET_BAR_CONFIG message. === COMMAND reply @@ -422,7 +429,7 @@ JSON dump: } ] } - +------------------------ === GET_MARKS reply @@ -432,8 +439,90 @@ same mark, it will be represented multiple times in the reply (the array contents are not unique). If no window has a mark the response will be the empty array []. ------------------------- +=== GET_BAR_CONFIG reply + +This can be used by third-party workspace bars (especially i3bar, but others +are free to implement compatible alternatives) to get the +bar+ block +configuration from i3. + +Depending on the input, the reply is either: + +empty input:: + An array of configured bar IDs +Bar ID:: + A JSON map containing the configuration for the specified bar. + +Each bar configuration has the following properties: + +id (string):: + The ID for this bar. Included in case you request multiple + configurations and want to differentiate the different replies. +mode (string):: + Either +dock+ (the bar sets the dock window type) or +hide+ (the bar + does not show unless a specific key is pressed). +position (string):: + Either +bottom+ or +top+ at the moment. +status_command (string):: + Command which will be run to generate a statusline. Each line on stdout + of this command will be displayed in the bar. At the moment, no + formatting is supported. +font (string):: + The font to use for text on the bar. +workspace_buttons (boolean):: + Display workspace buttons or not? Defaults to true. +verbose (boolean):: + Should the bar enable verbose output for debugging? Defaults to false. +colors (map):: + Contains key/value pairs of colors. Each value is a color code in hex, + formatted rrggbb (like used in HTML). + +The following colors can be configured at the moment: + +background:: + Background color of the bar. +statusline:: + Text color to be used for the statusline. +focused_workspace_text/focused_workspace_bg:: + Text color/background color for a workspace button when the workspace + has focus. +active_workspace_text/active_workspace_bg:: + Text color/background color for a workspace button when the workspace + is active (visible) on some output, but the focus is on another one. + You can only tell this apart from the focused workspace when you are + using multiple monitors. +inactive_workspace_text/inactive_workspace_bg:: + Text color/background color for a workspace button when the workspace + does not have focus and is not active (visible) on any output. This + will be the case for most workspaces. +urgent_workspace_text/urgent_workspace_bar:: + Text color/background color for workspaces which contain at least one + window with the urgency hint set. + + +*Example of configured bars:* +-------------- +["bar-bxuqzf"] +-------------- + +*Example of bar configuration:* +-------------- +{ + "id": "bar-bxuqzf", + "mode": "dock", + "position": "bottom", + "status_command": "i3status", + "font": "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1", + "workspace_buttons": true, + "verbose": false, + "colors": { + "background": "c0c0c0", + "statusline": "00ff00", + "focused_workspace_text": "ffffff", + "focused_workspace_bg": "000000" + } +} +-------------- == Events diff --git a/docs/userguide b/docs/userguide index e12d8b6e..135c6bae 100644 --- a/docs/userguide +++ b/docs/userguide @@ -547,7 +547,7 @@ exec_always command *Examples*: -------------------------------- -exec i3status | i3bar -d +exec chromium exec_always ~/my_script.sh -------------------------------- @@ -756,6 +756,226 @@ workspace_auto_back_and_forth workspace_auto_back_and_forth yes --------------------------------- +== Configuring i3bar + +The bar at the bottom of your monitor is drawn by a separate process called +i3bar. Having this part of "the i3 user interface" in a separate process has +several advantages: + +1. It is a modular approach. If you don’t need a workspace bar at all, or if + you prefer a different one (dzen2, xmobar, maybe even gnome-panel?), you can + just remove the i3bar configuration and start your favorite bar instead. +2. It follows the UNIX philosophy of "Make each program do one thing well". + While i3 manages your windows well, i3bar is good at displaying a bar on + each monitor (unless you configure it otherwise). +3. It leads to two separate, clean codebases. If you want to understand i3, you + don’t need to bother with the details of i3bar and vice versa. + +That said, i3bar is configured in the same configuration file as i3. This is +because it is tightly coupled with i3 (in contrary to i3lock or i3status which +are useful for people using other window managers). Therefore, it makes no +sense to use a different configuration place when we already have a good +configuration infrastructure in place. + +Configuring your workspace bar starts with opening a +bar+ block. You can have +multiple bar blocks to use different settings for different outputs (monitors): + +*Example*: +--------------------------- +bar { + status_command i3status +} +--------------------------- + +=== Statusline command + +i3bar can run a program and display every line of its +stdout+ output on the +right hand side of the bar. This is useful to display system information like +your current IP address, battery status or date/time. + +The specified command will be passed to +sh -c+, so you can use globbing and +have to have correct quoting etc. + +*Syntax*: +---------------------- +status_command command +---------------------- + +*Example*: +------------------------------------------------- +status_command i3status --config ~/.i3status.conf +------------------------------------------------- + +=== 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+ +mode). + +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. + +*Syntax*: +---------------- +mode +---------------- + +*Example*: +---------------- +mode hide +---------------- + +=== Position + +This option determines in which edge of the screen i3bar should show up. + +The default is bottom. + +*Syntax*: +--------------------- +position +--------------------- + +*Example*: +--------------------- +position top +--------------------- + +=== Output(s) + +You can restrict i3bar to one or more outputs (monitors). The default is to +handle all outputs. Restricting the outputs is useful for using different +options for different outputs by using multiple 'bar' blocks. + +*Syntax*: +--------------- +output +--------------- + +*Example*: +------------------------------- +# big monitor: everything +bar { + output HDMI2 + status_command i3status +} + +# laptop monitor: bright colors and i3status with less modules. +bar { + output LVDS1 + status_command i3status --config ~/.i3status-small.conf + colors { + background #000000 + statusline #ffffff + } +} +------------------------------- + +=== Tray output + +i3bar by default provides a system tray area where programs such as +NetworkManager, VLC, Pidgin, etc. can place little icons. + +You can configure on which output (monitor) the icons should be displayed or +you can turn off the functionality entirely. + +*Syntax*: +------------------------- +tray_output +------------------------- + +*Example*: +------------------------- +# disable system tray +tray_output none + +# show tray icons on the big monitor +tray_output HDMI2 +------------------------- + +=== Font + +Specifies the font (again, X core font, not Xft, just like in i3) to be used in +the bar. + +*Syntax*: +--------------------- +font +--------------------- + +*Example*: +-------------------------------------------------------------- +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +-------------------------------------------------------------- + +=== Workspace buttons + +Specifies whether workspace buttons should be shown or not. This is useful if +you want to display a statusline-only bar containing additional information. + +The default is to show workspace buttons. + +*Syntax*: +-------------------------- +workspace_buttons +-------------------------- + +*Example*: +-------------------- +workspace_buttons no +-------------------- + +=== Colors + +As with i3, colors are in HTML hex format (#rrggbb). The following colors can +be configured at the moment: + +background:: + Background color of the bar. +statusline:: + Text color to be used for the statusline. +focused_workspace_text/focused_workspace_bg:: + Text color/background color for a workspace button when the workspace + has focus. +active_workspace_text/active_workspace_bg:: + Text color/background color for a workspace button when the workspace + is active (visible) on some output, but the focus is on another one. + You can only tell this apart from the focused workspace when you are + using multiple monitors. +inactive_workspace_text/inactive_workspace_bg:: + Text color/background color for a workspace button when the workspace + does not have focus and is not active (visible) on any output. This + will be the case for most workspaces. +urgent_workspace_text/urgent_workspace_bar:: + Text color/background color for workspaces which contain at least one + window with the urgency hint set. + +*Syntax*: +---------------------------------------- +colors { + background + statusline + + colorclass +} +---------------------------------------- + +*Example*: +-------------------------------------- +colors { + background #000000 + statusline #ffffff + + focused_workspace #ffffff #285577 + active_workspace #888888 #222222 + inactive_workspace #888888 #222222 + urgent_workspace #ffffff #900000 +} +-------------------------------------- + == List of commands Commands are what you bind to specific keypresses. You can also issue commands diff --git a/i3-migrate-config-to-v4 b/i3-migrate-config-to-v4 index 4dd4418f..4f4d0134 100755 --- a/i3-migrate-config-to-v4 +++ b/i3-migrate-config-to-v4 @@ -358,6 +358,8 @@ sub convert_command { # add an i3bar invocation automatically if no 'workspace_bar no' was found if ($workspace_bar) { print "\n"; - print "# XXX: Automatically added a call to i3bar to provide a workspace bar\n"; - print "exec i3status | i3bar -d\n"; + print "# XXX: Automatically added a bar configuration\n"; + print "bar {\n"; + print " status_command i3status\n"; + print "}\n"; } diff --git a/i3-msg/main.c b/i3-msg/main.c index 5bc35b88..13cf0ccb 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -74,9 +74,11 @@ int main(int argc, char *argv[]) { message_type = I3_IPC_MESSAGE_TYPE_GET_TREE; else if (strcasecmp(optarg, "get_marks") == 0) message_type = I3_IPC_MESSAGE_TYPE_GET_MARKS; + else if (strcasecmp(optarg, "get_bar_config") == 0) + message_type = I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG; else { printf("Unknown message type\n"); - printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks\n"); + printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config\n"); exit(EXIT_FAILURE); } } else if (o == 'q') { diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index d0d7e77a..254aedfb 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -45,6 +45,14 @@ static int font_height; static char *prompt = "Please do not run this program."; static button_t *buttons; static int buttoncnt; + +/* Result of get_colorpixel() for the various colors. */ +static uint32_t color_background; /* background of the bar */ +static uint32_t color_button_background; /* background for buttons */ +static uint32_t color_border; /* color of the button border */ +static uint32_t color_border_bottom; /* color of the bottom border */ +static uint32_t color_text; /* color of the text */ + xcb_window_t root; /* @@ -118,16 +126,14 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve * */ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { - printf("expose!\n"); - /* re-draw the background */ - xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#900000")); + xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, color_background); xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect); /* restore font color */ uint32_t values[3]; - values[0] = get_colorpixel(conn, "#FFFFFF"); - values[1] = get_colorpixel(conn, "#900000"); + values[0] = color_text; + values[1] = color_background; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, values); xcb_image_text_8(conn, strlen(prompt), pixmap, pixmap_gc, 4 + 4/* X */, font_height + 2 + 4 /* Y = baseline of font */, prompt); @@ -136,14 +142,14 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { int line_width = 4; int w = 20; int y = rect.width; - values[0] = get_colorpixel(conn, "#680a0a"); + values[0] = color_button_background; values[1] = line_width; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); xcb_rectangle_t close = { y - w - (2 * line_width), 0, w + (2 * line_width), rect.height }; xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); - xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#d92424")); + xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, color_border); xcb_point_t points[] = { { y - w - (2 * line_width), line_width / 2 }, { y - (line_width / 2), line_width / 2 }, @@ -153,8 +159,8 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { }; xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points); - values[0] = get_colorpixel(conn, "#ffffff"); - values[1] = get_colorpixel(conn, "#680a0a"); + values[0] = color_text; + values[1] = color_button_background; values[2] = 1; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH, values); xcb_image_text_8(conn, strlen("x"), pixmap, pixmap_gc, y - w - line_width + (w / 2) - 4/* X */, @@ -167,13 +173,13 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { line_width = 1; for (int c = 0; c < buttoncnt; c++) { /* TODO: make w = text extents of the label */ - w = 90; + w = 100; y -= 30; - xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#680a0a")); + xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, color_button_background); close = (xcb_rectangle_t){ y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6 }; xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); - xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#d92424")); + xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FOREGROUND, color_border); buttons[c].x = y - w - (2 * line_width); buttons[c].width = w; xcb_point_t points2[] = { @@ -185,8 +191,8 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { }; xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2); - values[0] = get_colorpixel(conn, "#ffffff"); - values[1] = get_colorpixel(conn, "#680a0a"); + values[0] = color_text; + values[1] = color_button_background; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, values); xcb_image_text_8(conn, strlen(buttons[c].label), pixmap, pixmap_gc, y - w - line_width + 6/* X */, font_height + 2 + 3/* Y = baseline of font */, buttons[c].label); @@ -196,7 +202,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* border line at the bottom */ line_width = 2; - values[0] = get_colorpixel(conn, "#470909"); + values[0] = color_border_bottom; values[1] = line_width; xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); xcb_point_t bottom[] = { @@ -216,6 +222,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { int main(int argc, char *argv[]) { char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; int o, option_index = 0; + enum { TYPE_ERROR = 0, TYPE_WARNING = 1 } bar_type = TYPE_ERROR; static struct option long_options[] = { {"version", no_argument, 0, 'v'}, @@ -223,10 +230,11 @@ int main(int argc, char *argv[]) { {"button", required_argument, 0, 'b'}, {"help", no_argument, 0, 'h'}, {"message", no_argument, 0, 'm'}, + {"type", required_argument, 0, 't'}, {0, 0, 0, 0} }; - char *options_string = "b:f:m:vh"; + char *options_string = "b:f:m:t:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { @@ -240,6 +248,9 @@ int main(int argc, char *argv[]) { case 'm': prompt = strdup(optarg); break; + case 't': + bar_type = (strcasecmp(optarg, "warning") == 0 ? TYPE_WARNING : TYPE_ERROR); + break; case 'h': printf("i3-nagbar " I3_VERSION "\n"); printf("i3-nagbar [-m ] [-b