1 IPC interface (interprocess communication)
2 ==========================================
3 Michael Stapelberg <michael+i3@stapelberg.de>
6 This document describes how to interface with i3 from a separate process. This
7 is useful for example to remote-control i3 (to write test cases for example) or
8 to get various information like the current workspaces to implement an external
11 The method of choice for IPC in our case is a unix socket because it has very
12 little overhead on both sides and is usually available without headaches in
13 most languages. In the default configuration file, the ipc-socket gets created
14 in +/tmp/i3-%u/ipc-socket.%p+ where +%u+ is your UNIX username and +%p+ is the
15 PID of i3. You can get the socketpath from i3 by calling +i3 --get-socketpath+.
17 All i3 utilities, like +i3-msg+ and +i3-input+ will read the +I3_SOCKET_PATH+
18 X11 property, stored on the X11 root window.
20 == Establishing a connection
22 To establish a connection, simply open the IPC socket. The following code
23 snippet illustrates this in Perl:
25 -------------------------------------------------------------
27 chomp(my $path = qx(i3 --get-socketpath));
28 my $sock = IO::Socket::UNIX->new(Peer => $path);
29 -------------------------------------------------------------
31 == Sending messages to i3
33 To send a message to i3, you have to format in the binary message format which
34 i3 expects. This format specifies a magic string in the beginning to ensure
35 the integrity of messages (to prevent follow-up errors). Following the magic
36 string comes the length of the payload of the message as 32-bit integer, and
37 the type of the message as 32-bit integer (the integers are not converted, so
38 they are in native byte order).
40 The magic string currently is "i3-ipc" and will only be changed when a change
41 in the IPC API is done which breaks compatibility (we hope that we don’t need
44 Currently implemented message types are the following:
47 The payload of the message is a command for i3 (like the commands you
48 can bind to keys in the configuration file) and will be executed
49 directly after receiving it.
51 Gets the current workspaces. The reply will be a JSON-encoded list of
52 workspaces (see the reply section).
54 Subscribes your connection to certain events. See <<events>> for a
55 description of this message and the concept of events.
57 Gets the current outputs. The reply will be a JSON-encoded list of outputs
58 (see the reply section).
60 Gets the layout tree. i3 uses a tree as data structure which includes
61 every container. The reply will be the JSON-encoded tree (see the reply
64 Gets a list of marks (identifiers for containers to easily jump to them
65 later). The reply will be a JSON-encoded list of window marks (see
68 Gets the configuration (as JSON map) of the workspace bar with the
69 given ID. If no ID is provided, an array with all configured bar IDs is
72 Gets the SHM log markers for the current position, the last wrap, the
73 SHM segment name and segment size. This is necessary for tools like
74 i3-dump-log which want to display the SHM log.
76 So, a typical message could look like this:
77 --------------------------------------------------
78 "i3-ipc" <message length> <message type> <payload>
79 --------------------------------------------------
82 ------------------------------------------------------------------------------
83 00000000 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex|
84 00000010 69 74 0a |it.|
85 ------------------------------------------------------------------------------
87 To generate and send such a message, you could use the following code in Perl:
88 ------------------------------------------------------------
89 sub format_ipc_command {
92 # Get the real byte count (vs. amount of characters)
93 { use bytes; $len = length($msg); }
94 return "i3-ipc" . pack("LL", $len, 0) . $msg;
97 $sock->write(format_ipc_command("exit"));
98 ------------------------------------------------------------------------------
100 == Receiving replies from i3
102 Replies from i3 usually consist of a simple string (the length of the string
103 is the message_length, so you can consider them length-prefixed) which in turn
104 contain the JSON serialization of a data structure. For example, the
105 GET_WORKSPACES message returns an array of workspaces (each workspace is a map
106 with certain attributes).
110 The reply format is identical to the normal message format. There also is
111 the magic string, then the message length, then the message type and the
114 The following reply types are implemented:
117 Confirmation/Error code for the COMMAND message.
119 Reply to the GET_WORKSPACES message.
121 Confirmation/Error code for the SUBSCRIBE message.
123 Reply to the GET_OUTPUTS message.
125 Reply to the GET_TREE message.
127 Reply to the GET_MARKS message.
129 Reply to the GET_BAR_CONFIG message.
131 Reply to the GET_LOG_MARKERS message.
135 The reply consists of a single serialized map. At the moment, the only
136 property is +success (bool)+, but this will be expanded in future versions.
145 The reply consists of a serialized list of workspaces. Each workspace has the
146 following properties:
149 The logical number of the workspace. Corresponds to the command
150 to switch to this workspace.
152 The name of this workspace (by default num+1), as changed by the
153 user. Encoded in UTF-8.
155 Whether this workspace is currently visible on an output (multiple
156 workspaces can be visible at the same time).
158 Whether this workspace currently has the focus (only one workspace
159 can have the focus at the same time).
161 Whether a window on this workspace has the "urgent" flag set.
163 The rectangle of this workspace (equals the rect of the output it
164 is on), consists of x, y, width, height.
166 The video output this workspace is on (LVDS1, VGA1, …).
204 The reply consists of a single serialized map. The only property is
205 +success (bool)+, indicating whether the subscription was successful (the
206 default) or whether a JSON parse error occurred.
213 === GET_OUTPUTS reply
215 The reply consists of a serialized list of outputs. Each output has the
216 following properties:
219 The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8.
221 Whether this output is currently active (has a valid mode).
222 current_workspace (integer)::
223 The current workspace which is visible on this output. +null+ if the
224 output is not active.
226 The rectangle of this output (equals the rect of the output it
227 is on), consists of x, y, width, height.
235 "current_workspace": 4,
246 "current_workspace": 1,
259 The reply consists of a serialized tree. Each node in the tree (representing
260 one container) has at least the properties listed below. While the nodes might
261 have more properties, please do not use any properties which are not documented
262 here. They are not yet finalized and will probably change!
265 The internal ID (actually a C pointer value) of this container. Do not
266 make any assumptions about it. You can use it to (re-)identify and
267 address containers when talking to i3.
269 The internal name of this container. For all containers which are part
270 of the tree structure down to the workspace contents, this is set to a
271 nice human-readable name of the container.
272 For all other containers, the content is not defined (yet).
274 Can be either "normal", "none" or "1pixel", dependending on the
275 container’s border style.
277 Can be either "default", "stacked", "tabbed", "dockarea" or "output".
278 Other values might be possible in the future, should we add new
280 orientation (string)::
281 Can be either "none" (for non-split containers), "horizontal" or
284 The percentage which this container takes in its parent. A value of
285 +null+ means that the percent property does not make sense for this
286 container, for example for the root container.
288 The absolute display coordinates for this container. Display
289 coordinates means that when you have two 1600x1200 monitors on a single
290 X11 Display (the standard way), the coordinates of the first window on
291 the second monitor are +{ "x": 1600, "y": 0, "width": 1600, "height":
294 The coordinates of the *actual client window* inside its container.
295 These coordinates are relative to the container and do not include the
296 window decoration (which is actually rendered on the parent container).
297 So, when using the +default+ layout, you will have a 2 pixel border on
298 each side, making the window_rect +{ "x": 2, "y": 0, "width": 632,
299 "height": 366 }+ (for example).
301 The original geometry the window specified when i3 mapped it. Used when
302 switching a window to floating mode, for example.
304 Whether this container (window or workspace) has the urgency hint set.
306 Whether this container is currently focused.
308 Please note that in the following example, I have left out some keys/values
309 which are not relevant for the type of the node. Otherwise, the example would
310 be by far too long (it already is quite long, despite showing only 1 window and
313 It is useful to have an overview of the structure before taking a look at the
327 -----------------------
354 "layout": "dockarea",
355 "orientation": "vertical",
378 "orientation": "horizontal",
385 "floating_nodes": [],
409 "name": "bottomdock",
410 "layout": "dockarea",
411 "orientation": "vertical",
438 ------------------------
442 The reply consists of a single array of strings for each container that has a
443 mark. The order of that array is undefined. If more than one container has the
444 same mark, it will be represented multiple times in the reply (the array
445 contents are not unique).
447 If no window has a mark the response will be the empty array [].
451 This can be used by third-party workspace bars (especially i3bar, but others
452 are free to implement compatible alternatives) to get the +bar+ block
453 configuration from i3.
455 Depending on the input, the reply is either:
458 An array of configured bar IDs
460 A JSON map containing the configuration for the specified bar.
462 Each bar configuration has the following properties:
465 The ID for this bar. Included in case you request multiple
466 configurations and want to differentiate the different replies.
468 Either +dock+ (the bar sets the dock window type) or +hide+ (the bar
469 does not show unless a specific key is pressed).
471 Either +bottom+ or +top+ at the moment.
472 status_command (string)::
473 Command which will be run to generate a statusline. Each line on stdout
474 of this command will be displayed in the bar. At the moment, no
475 formatting is supported.
477 The font to use for text on the bar.
478 workspace_buttons (boolean)::
479 Display workspace buttons or not? Defaults to true.
481 Should the bar enable verbose output for debugging? Defaults to false.
483 Contains key/value pairs of colors. Each value is a color code in hex,
484 formatted #rrggbb (like in HTML).
486 The following colors can be configured at the moment:
489 Background color of the bar.
491 Text color to be used for the statusline.
492 focused_workspace_text/focused_workspace_bg::
493 Text color/background color for a workspace button when the workspace
495 active_workspace_text/active_workspace_bg::
496 Text color/background color for a workspace button when the workspace
497 is active (visible) on some output, but the focus is on another one.
498 You can only tell this apart from the focused workspace when you are
499 using multiple monitors.
500 inactive_workspace_text/inactive_workspace_bg::
501 Text color/background color for a workspace button when the workspace
502 does not have focus and is not active (visible) on any output. This
503 will be the case for most workspaces.
504 urgent_workspace_text/urgent_workspace_bar::
505 Text color/background color for workspaces which contain at least one
506 window with the urgency hint set.
509 *Example of configured bars:*
514 *Example of bar configuration:*
519 "position": "bottom",
520 "status_command": "i3status",
521 "font": "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1",
522 "workspace_buttons": true,
525 "background": "#c0c0c0",
526 "statusline": "#00ff00",
527 "focused_workspace_text": "#ffffff",
528 "focused_workspace_bg": "#000000"
533 === LOG_MARKERS reply
535 Gets the SHM log markers for the current position, the last wrap, the
536 SHM segment name and segment size. This is necessary for tools like
537 i3-dump-log which want to display the SHM log.
539 The reply is a JSON map with the following entries:
542 The name of the SHM segment, will be of the format +/i3-log-<pid>+.
544 The size (in bytes) of the SHM segment. If this is 0, SHM logging is
546 offset_next_write (integer)::
547 The offset in the SHM segment at which the next write will happen.
548 Tools should start printing lines from here, since the bytes following
549 this offset are the oldest log lines. However, the first line might be
550 garbled, so it makes sense to skip all bytes until the first \0.
551 offset_last_wrap (integer)::
552 The offset in the SHM segment at which the last wrap occured. i3 only
553 stores entire messages in the SHM log, so it might waste a few bytes at
554 the end to be more efficient. Tools should not print content after the
558 -----------------------------
560 "offset_next_write":132839,
561 "offset_last_wrap":26214400,
562 "shmname":"/i3-log-3392",
565 -----------------------------
571 To get informed when certain things happen in i3, clients can subscribe to
572 events. Events consist of a name (like "workspace") and an event reply type
573 (like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format
574 as replies to specific commands. However, the highest bit of the message type
575 is set to 1 to indicate that this is an event reply instead of a normal reply.
577 Caveat: As soon as you subscribe to an event, it is not guaranteed any longer
578 that the requests to i3 are processed in order. This means, the following
579 situation can happen: You send a GET_WORKSPACES request but you receive a
580 "workspace" event before receiving the reply to GET_WORKSPACES. If your
581 program does not want to cope which such kinds of race conditions (an
582 event based library may not have a problem here), I suggest you create a
583 separate connection to receive events.
585 === Subscribing to events
587 By sending a message of type SUBSCRIBE with a JSON-encoded array as payload
588 you can register to an event.
591 ---------------------------------
593 payload: [ "workspace", "focus" ]
594 ---------------------------------
599 The numbers in parenthesis is the event type (keep in mind that you need to
600 strip the highest bit first).
603 Sent when the user switches to a different workspace, when a new
604 workspace is initialized or when a workspace is removed (because the
605 last client vanished).
607 Sent when RandR issues a change notification (of either screens,
608 outputs, CRTCs or output properties).
611 --------------------------------------------------------------------
612 # the appropriate 4 bytes read from the socket are stored in $input
614 # unpack a 32-bit unsigned integer
615 my $message_type = unpack("L", $input);
617 # check if the highest bit is 1
618 my $is_event = (($message_type >> 31) == 1);
621 my $event_type = ($message_type & 0x7F);
624 say "Received event of type $event_type";
626 --------------------------------------------------------------------
630 This event consists of a single serialized map containing a property
631 +change (string)+ which indicates the type of the change ("focus", "init",
635 ---------------------
636 { "change": "focus" }
637 ---------------------
641 This event consists of a single serialized map containing a property
642 +change (string)+ which indicates the type of the change (currently only
646 ---------------------------
647 { "change": "unspecified" }
648 ---------------------------
652 For some languages, libraries are available (so you don’t have to implement
653 all this on your own). This list names some (if you wrote one, please let me
657 i3 includes a headerfile +i3/ipc.h+ which provides you all constants.
658 However, there is no library yet.
660 http://github.com/badboy/i3-ipc
662 http://search.cpan.org/search?query=AnyEvent::I3
664 http://github.com/thepub/i3ipc