1 IPC interface (interprocess communication)
2 ==========================================
3 Michael Stapelberg <michael@i3wm.org>
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.XXXXXX/ipc-socket.%p+ where +%u+ is your UNIX username, +%p+ is
15 the PID of i3 and XXXXXX is a string of random characters from the portable
16 filename character set (see mkdtemp(3)). You can get the socketpath from i3 by
17 calling +i3 --get-socketpath+.
19 All i3 utilities, like +i3-msg+ and +i3-input+ will read the +I3_SOCKET_PATH+
20 X11 property, stored on the X11 root window.
23 .Use an existing library!
24 There are existing libraries for many languages. You can have a look at
25 <<libraries>> or search the web if your language of choice is not mentioned.
26 Usually, it is not necessary to implement low-level communication with i3
29 == Establishing a connection
31 To establish a connection, simply open the IPC socket. The following code
32 snippet illustrates this in Perl:
34 -------------------------------------------------------------
36 chomp(my $path = qx(i3 --get-socketpath));
37 my $sock = IO::Socket::UNIX->new(Peer => $path);
38 -------------------------------------------------------------
40 == Sending messages to i3
42 To send a message to i3, you have to format in the binary message format which
43 i3 expects. This format specifies a magic string in the beginning to ensure
44 the integrity of messages (to prevent follow-up errors). Following the magic
45 string comes the length of the payload of the message as 32-bit integer, and
46 the type of the message as 32-bit integer (the integers are not converted, so
47 they are in native byte order).
49 The magic string currently is "i3-ipc" and will only be changed when a change
50 in the IPC API is done which breaks compatibility (we hope that we don’t need
53 .Currently implemented message types
54 [options="header",cols="^10%,^20%,^20%,^50%"]
55 |======================================================
56 | Type (numeric) | Type (name) | Reply type | Purpose
57 | 0 | +RUN_COMMAND+ | <<_command_reply,COMMAND>> | Run the payload as an i3 command (like the commands you can bind to keys).
58 | 1 | +GET_WORKSPACES+ | <<_workspaces_reply,WORKSPACES>> | Get the list of current workspaces.
59 | 2 | +SUBSCRIBE+ | <<_subscribe_reply,SUBSCRIBE>> | Subscribe this IPC connection to the event types specified in the message payload. See <<events>>.
60 | 3 | +GET_OUTPUTS+ | <<_outputs_reply,OUTPUTS>> | Get the list of current outputs.
61 | 4 | +GET_TREE+ | <<_tree_reply,TREE>> | Get the i3 layout tree.
62 | 5 | +GET_MARKS+ | <<_marks_reply,MARKS>> | Gets the names of all currently set marks.
63 | 6 | +GET_BAR_CONFIG+ | <<_bar_config_reply,BAR_CONFIG>> | Gets the specified bar configuration or the names of all bar configurations if payload is empty.
64 | 7 | +GET_VERSION+ | <<_version_reply,VERSION>> | Gets the i3 version.
65 | 8 | +GET_BINDING_MODES+ | <<_binding_modes_reply,BINDING_MODES>> | Gets the names of all currently configured binding modes.
66 | 9 | +GET_CONFIG+ | <<_config_reply,CONFIG>> | Returns the last loaded i3 config.
67 |======================================================
69 So, a typical message could look like this:
70 --------------------------------------------------
71 "i3-ipc" <message length> <message type> <payload>
72 --------------------------------------------------
75 ------------------------------------------------------------------------------
76 00000000 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex|
78 ------------------------------------------------------------------------------
80 To generate and send such a message, you could use the following code in Perl:
81 ------------------------------------------------------------
82 sub format_ipc_command {
85 # Get the real byte count (vs. amount of characters)
86 { use bytes; $len = length($msg); }
87 return "i3-ipc" . pack("LL", $len, 0) . $msg;
90 $sock->write(format_ipc_command("exit"));
91 ------------------------------------------------------------------------------
93 == Receiving replies from i3
95 Replies from i3 usually consist of a simple string (the length of the string
96 is the message_length, so you can consider them length-prefixed) which in turn
97 contain the JSON serialization of a data structure. For example, the
98 GET_WORKSPACES message returns an array of workspaces (each workspace is a map
99 with certain attributes).
103 The reply format is identical to the normal message format. There also is
104 the magic string, then the message length, then the message type and the
107 The following reply types are implemented:
110 Confirmation/Error code for the RUN_COMMAND message.
112 Reply to the GET_WORKSPACES message.
114 Confirmation/Error code for the SUBSCRIBE message.
116 Reply to the GET_OUTPUTS message.
118 Reply to the GET_TREE message.
120 Reply to the GET_MARKS message.
122 Reply to the GET_BAR_CONFIG message.
124 Reply to the GET_VERSION message.
126 Reply to the GET_BINDING_MODES message.
128 Reply to the GET_CONFIG message.
133 The reply consists of a list of serialized maps for each command that was
134 parsed. Each has the property +success (bool)+ and may also include a
135 human-readable error message in the property +error (string)+.
139 [{ "success": true }]
142 [[_workspaces_reply]]
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. For named workspaces, this will be -1.
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, …).
205 The reply consists of a single serialized map. The only property is
206 +success (bool)+, indicating whether the subscription was successful (the
207 default) or whether a JSON parse error occurred.
217 The reply consists of a serialized list of outputs. Each output has the
218 following properties:
221 The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8.
223 Whether this output is currently active (has a valid mode).
225 Whether this output is currently the primary output.
226 current_workspace (string)::
227 The name of the current workspace that is visible on this output. +null+ if
228 the output is not active.
230 The rectangle of this output (equals the rect of the output it
231 is on), consists of x, y, width, height.
239 "current_workspace": "4",
250 "current_workspace": "1",
264 The reply consists of a serialized tree. Each node in the tree (representing
265 one container) has at least the properties listed below. While the nodes might
266 have more properties, please do not use any properties which are not documented
267 here. They are not yet finalized and will probably change!
270 The internal ID (actually a C pointer value) of this container. Do not
271 make any assumptions about it. You can use it to (re-)identify and
272 address containers when talking to i3.
274 The internal name of this container. For all containers which are part
275 of the tree structure down to the workspace contents, this is set to a
276 nice human-readable name of the container.
277 For containers that have an X11 window, the content is the title
278 (_NET_WM_NAME property) of that window.
279 For all other containers, the content is not defined (yet).
281 Type of this container. Can be one of "root", "output", "con",
282 "floating_con", "workspace" or "dockarea".
284 Can be either "normal", "none" or "pixel", depending on the
285 container’s border style.
286 current_border_width (integer)::
287 Number of pixels of the border width.
289 Can be either "splith", "splitv", "stacked", "tabbed", "dockarea" or
291 Other values might be possible in the future, should we add new
293 orientation (string)::
294 Can be either "none" (for non-split containers), "horizontal" or
296 THIS FIELD IS OBSOLETE. It is still present, but your code should not
297 use it. Instead, rely on the layout field.
299 The percentage which this container takes in its parent. A value of
300 +null+ means that the percent property does not make sense for this
301 container, for example for the root container.
303 The absolute display coordinates for this container. Display
304 coordinates means that when you have two 1600x1200 monitors on a single
305 X11 Display (the standard way), the coordinates of the first window on
306 the second monitor are +{ "x": 1600, "y": 0, "width": 1600, "height":
309 The coordinates of the *actual client window* inside its container.
310 These coordinates are relative to the container and do not include the
311 window decoration (which is actually rendered on the parent container).
312 So, when using the +default+ layout, you will have a 2 pixel border on
313 each side, making the window_rect +{ "x": 2, "y": 0, "width": 632,
314 "height": 366 }+ (for example).
316 The coordinates of the *window decoration* inside its container. These
317 coordinates are relative to the container and do not include the actual
320 The original geometry the window specified when i3 mapped it. Used when
321 switching a window to floating mode, for example.
323 The X11 window ID of the *actual client window* inside this container.
324 This field is set to null for split containers or otherwise empty
325 containers. This ID corresponds to what xwininfo(1) and other
326 X11-related tools display (usually in hex).
328 Whether this container (window, split container, floating container or
329 workspace) has the urgency hint set, directly or indirectly. All parent
330 containers up until the workspace container will be marked urgent if they
331 have at least one urgent child.
333 Whether this container is currently focused.
334 focus (array of integer)::
335 List of child node IDs (see +nodes+, +floating_nodes+ and +id+) in focus
336 order. Traversing the tree by following the first entry in this array
337 will result in eventually reaching the one node with +focused+ set to
339 nodes (array of node)::
340 The tiling (i.e. non-floating) child containers of this node.
341 floating_nodes (array of node)::
342 The floating child containers of this node. Only non-empty on nodes with
345 Please note that in the following example, I have left out some keys/values
346 which are not relevant for the type of the node. Otherwise, the example would
347 be by far too long (it already is quite long, despite showing only 1 window and
350 It is useful to have an overview of the structure before taking a look at the
364 -----------------------
391 "layout": "dockarea",
392 "orientation": "vertical",
415 "orientation": "horizontal",
422 "floating_nodes": [],
446 "name": "bottomdock",
447 "layout": "dockarea",
448 "orientation": "vertical",
475 ------------------------
480 The reply consists of a single array of strings for each container that has a
481 mark. A mark can only be set on one container, so the array is unique.
482 The order of that array is undefined.
484 If no window has a mark the response will be the empty array [].
486 [[_bar_config_reply]]
489 This can be used by third-party workspace bars (especially i3bar, but others
490 are free to implement compatible alternatives) to get the +bar+ block
491 configuration from i3.
493 Depending on the input, the reply is either:
496 An array of configured bar IDs
498 A JSON map containing the configuration for the specified bar.
500 Each bar configuration has the following properties:
503 The ID for this bar. Included in case you request multiple
504 configurations and want to differentiate the different replies.
506 Either +dock+ (the bar sets the dock window type) or +hide+ (the bar
507 does not show unless a specific key is pressed).
509 Either +bottom+ or +top+ at the moment.
510 status_command (string)::
511 Command which will be run to generate a statusline. Each line on stdout
512 of this command will be displayed in the bar. At the moment, no
513 formatting is supported.
515 The font to use for text on the bar.
516 workspace_buttons (boolean)::
517 Display workspace buttons or not? Defaults to true.
518 binding_mode_indicator (boolean)::
519 Display the mode indicator or not? Defaults to true.
521 Should the bar enable verbose output for debugging? Defaults to false.
523 Contains key/value pairs of colors. Each value is a color code in hex,
524 formatted #rrggbb (like in HTML).
526 The following colors can be configured at the moment:
529 Background color of the bar.
531 Text color to be used for the statusline.
533 Text color to be used for the separator.
535 Background color of the bar on the currently focused monitor output.
537 Text color to be used for the statusline on the currently focused
540 Text color to be used for the separator on the currently focused
542 focused_workspace_text/focused_workspace_bg/focused_workspace_border::
543 Text/background/border color for a workspace button when the workspace
545 active_workspace_text/active_workspace_bg/active_workspace_border::
546 Text/background/border color for a workspace button when the workspace
547 is active (visible) on some output, but the focus is on another one.
548 You can only tell this apart from the focused workspace when you are
549 using multiple monitors.
550 inactive_workspace_text/inactive_workspace_bg/inactive_workspace_border::
551 Text/background/border color for a workspace button when the workspace
552 does not have focus and is not active (visible) on any output. This
553 will be the case for most workspaces.
554 urgent_workspace_text/urgent_workspace_bg/urgent_workspace_border::
555 Text/background/border color for workspaces which contain at least one
556 window with the urgency hint set.
557 binding_mode_text/binding_mode_bg/binding_mode_border::
558 Text/background/border color for the binding mode indicator.
561 *Example of configured bars:*
566 *Example of bar configuration:*
571 "position": "bottom",
572 "status_command": "i3status",
573 "font": "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1",
574 "workspace_buttons": true,
575 "binding_mode_indicator": true,
578 "background": "#c0c0c0",
579 "statusline": "#00ff00",
580 "focused_workspace_text": "#ffffff",
581 "focused_workspace_bg": "#000000"
589 The reply consists of a single JSON dictionary with the following keys:
592 The major version of i3, such as +4+.
594 The minor version of i3, such as +2+. Changes in the IPC interface (new
595 features) will only occur with new minor (or major) releases. However,
596 bugfixes might be introduced in patch releases, too.
598 The patch version of i3, such as +1+ (when the complete version is
599 +4.2.1+). For versions such as +4.2+, patch will be set to +0+.
600 human_readable (string)::
601 A human-readable version of i3 containing the precise git version,
602 build date and branch name. When you need to display the i3 version to
603 your users, use the human-readable version whenever possible (since
604 this is what +i3 --version+ displays, too).
605 loaded_config_file_name (string)::
606 The current config path.
611 "human_readable" : "4.2-169-gf80b877 (2012-08-05, branch \"next\")",
612 "loaded_config_file_name" : "/home/hwangcc23/.i3/config",
619 [[_binding_modes_reply]]
620 === BINDING_MODES reply
622 The reply consists of an array of all currently configured binding modes.
625 ---------------------
626 ["default", "resize"]
627 ---------------------
632 The config reply is a map which currently only contains the "config" member,
633 which is a string containing the config file as loaded by i3 most recently.
637 { "config": "font pango:monospace 8\nbindsym Mod4+q exit\n" }
645 To get informed when certain things happen in i3, clients can subscribe to
646 events. Events consist of a name (like "workspace") and an event reply type
647 (like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format
648 as replies to specific commands. However, the highest bit of the message type
649 is set to 1 to indicate that this is an event reply instead of a normal reply.
651 Caveat: As soon as you subscribe to an event, it is not guaranteed any longer
652 that the requests to i3 are processed in order. This means, the following
653 situation can happen: You send a GET_WORKSPACES request but you receive a
654 "workspace" event before receiving the reply to GET_WORKSPACES. If your
655 program does not want to cope which such kinds of race conditions (an
656 event based library may not have a problem here), I suggest you create a
657 separate connection to receive events.
659 === Subscribing to events
661 By sending a message of type SUBSCRIBE with a JSON-encoded array as payload
662 you can register to an event.
665 ---------------------------------
667 payload: [ "workspace", "output" ]
668 ---------------------------------
673 The numbers in parenthesis is the event type (keep in mind that you need to
674 strip the highest bit first).
677 Sent when the user switches to a different workspace, when a new
678 workspace is initialized or when a workspace is removed (because the
679 last client vanished).
681 Sent when RandR issues a change notification (of either screens,
682 outputs, CRTCs or output properties).
684 Sent whenever i3 changes its binding mode.
686 Sent when a client's window is successfully reparented (that is when i3
687 has finished fitting it into a container), when a window received input
688 focus or when certain properties of the window have changed.
689 barconfig_update (4)::
690 Sent when the hidden_state or mode field in the barconfig of any bar
691 instance was updated and when the config is reloaded.
693 Sent when a configured command binding is triggered with the keyboard or
696 Sent when the ipc shuts down because of a restart or exit by user command
699 --------------------------------------------------------------------
700 # the appropriate 4 bytes read from the socket are stored in $input
702 # unpack a 32-bit unsigned integer
703 my $message_type = unpack("L", $input);
705 # check if the highest bit is 1
706 my $is_event = (($message_type >> 31) == 1);
709 my $event_type = ($message_type & 0x7F);
712 say "Received event of type $event_type";
714 --------------------------------------------------------------------
718 This event consists of a single serialized map containing a property
719 +change (string)+ which indicates the type of the change ("focus", "init",
720 "empty", "urgent", "reload", "rename", "restored", "move"). A
721 +current (object)+ property will be present with the affected workspace
722 whenever the type of event affects a workspace (otherwise, it will be +null).
724 When the change is "focus", an +old (object)+ property will be present with the
725 previous workspace. When the first switch occurs (when i3 focuses the
726 workspace visible at the beginning) there is no previous workspace, and the
727 +old+ property will be set to +null+. Also note that if the previous is empty
728 it will get destroyed when switching, but will still be present in the "old"
732 ---------------------
746 ---------------------
750 This event consists of a single serialized map containing a property
751 +change (string)+ which indicates the type of the change (currently only
755 ---------------------------
756 { "change": "unspecified" }
757 ---------------------------
761 This event consists of a single serialized map containing a property
762 +change (string)+ which holds the name of current mode in use. The name
763 is the same as specified in config when creating a mode. The default
764 mode is simply named default. It contains a second property, +pango_markup+, which
765 defines whether pango markup shall be used for displaying this mode.
768 ---------------------------
773 ---------------------------
777 This event consists of a single serialized map containing a property
778 +change (string)+ which indicates the type of the change
780 * +new+ – the window has become managed by i3
781 * +close+ – the window has closed
782 * +focus+ – the window has received input focus
783 * +title+ – the window's title has changed
784 * +fullscreen_mode+ – the window has entered or exited fullscreen mode
785 * +move+ – the window has changed its position in the tree
786 * +floating+ – the window has transitioned to or from floating
787 * +urgent+ – the window has become urgent or lost its urgent status
788 * +mark+ – a mark has been added to or removed from the window
790 Additionally a +container (object)+ field will be present, which consists
791 of the window's parent container. Be aware that for the "new" event, the
792 container will hold the initial name of the newly reparented window (e.g.
793 if you run urxvt with a shell that changes the title, you will still at
794 this point get the window title as "urxvt").
797 ---------------------------
806 ---------------------------
808 === barconfig_update event
810 This event consists of a single serialized map reporting on options from the
811 barconfig of the specified bar_id that were updated in i3. This event is the
812 same as a +GET_BAR_CONFIG+ reply for the bar with the given id.
816 This event consists of a single serialized map reporting on the details of a
817 binding that ran a command because of user input. The +change (string)+ field
818 indicates what sort of binding event was triggered (right now it will always be
819 +"run"+ but may be expanded in the future).
821 The +binding (object)+ field contains details about the binding that was run:
824 The i3 command that is configured to run for this binding.
825 event_state_mask (array of strings)::
826 The group and modifier keys that were configured with this binding.
827 input_code (integer)::
828 If the binding was configured with +bindcode+, this will be the key code
829 that was given for the binding. If the binding is a mouse binding, it will be
830 the number of the mouse button that was pressed. Otherwise it will be 0.
831 symbol (string or null)::
832 If this is a keyboard binding that was configured with +bindsym+, this
833 field will contain the given symbol. Otherwise it will be +null+.
834 input_type (string)::
835 This will be +"keyboard"+ or +"mouse"+ depending on whether or not this was
836 a keyboard or a mouse binding.
839 ---------------------------
844 "event_state_mask": [
850 "input_type": "keyboard"
853 ---------------------------
857 This event is triggered when the connection to the ipc is about to shutdown
858 because of a user action such as a +restart+ or +exit+ command. The +change
859 (string)+ field indicates why the ipc is shutting down. It can be either
860 +"restart"+ or +"exit"+.
863 ---------------------------
867 ---------------------------
869 == See also (existing libraries)
873 For some languages, libraries are available (so you don’t have to implement
874 all this on your own). This list names some (if you wrote one, please let me
878 * i3 includes a headerfile +i3/ipc.h+ which provides you all constants.
879 * https://github.com/acrisci/i3ipc-glib
881 * https://github.com/drmgc/i3ipcpp
883 * https://github.com/mdirkse/i3ipc-go
885 * https://github.com/acrisci/i3ipc-gjs
887 * https://github.com/acrisci/i3ipc-lua
889 * https://metacpan.org/module/AnyEvent::I3
891 * https://github.com/acrisci/i3ipc-python
892 * https://github.com/whitelynx/i3ipc (not maintained)
893 * https://github.com/ziberna/i3-py (not maintained)
895 * https://github.com/veelenga/i3ipc-ruby
896 * https://github.com/badboy/i3-ipc (not maintained)
898 * https://github.com/tmerr/i3ipc-rs
900 * https://github.com/Armael/ocaml-i3ipc
902 == Appendix A: Detecting byte order in memory-safe languages
904 Some programming languages such as Go don’t offer a way to serialize data in the
905 native byte order of the machine they’re running on without resorting to tricks
906 involving the +unsafe+ package.
908 The following technique can be used (and will not be broken by changes to i3) to
909 detect the byte order i3 is using:
911 1. The byte order dependent fields of an IPC message are message type and
914 * The message type +RUN_COMMAND+ (0) is the same in big and little endian, so
915 we can use it in either byte order to elicit a reply from i3.
917 * The payload length 65536 + 256 (+0x00 01 01 00+) is the same in big and
918 little endian, and also small enough to not worry about memory allocations
919 of that size. We must use payloads of length 65536 + 256 in every message
920 we send, so that i3 will be able to read the entire message regardless of
921 the byte order it uses.
923 2. Send a big endian encoded message of type +SUBSCRIBE+ (2) with payload `[]`
924 followed by 65536 + 256 - 2 +SPACE+ (ASCII 0x20) bytes.
926 * If i3 is running in big endian, this message is treated as a noop,
927 resulting in a +SUBSCRIBE+ reply with payload `{"success":true}`
928 footnote:[A small payload is important: that way, we circumvent dealing
929 with UNIX domain socket buffer sizes, whose size depends on the
930 implementation/operating system. Exhausting such a buffer results in an i3
931 deadlock unless you concurrently read and write, which — depending on the
932 programming language — makes the technique much more complicated.].
934 * If i3 is running in little endian, this message is read in its entirety due
935 to the byte order independent payload length, then
936 https://github.com/i3/i3/blob/d726d09d496577d1c337a4b97486f2c9fbc914f1/src/ipc.c#L1188[silently
937 discarded] due to the unknown message type.
939 3. Send a byte order independent message, i.e. type +RUN_COMMAND+ (0) with
940 payload +nop byte order detection. padding:+, padded to 65536 + 256 bytes
941 with +a+ (ASCII 0x61) bytes. i3 will reply to this message with a reply of
944 * The human-readable prefix is in there to not confuse readers of the i3 log.
946 * This messages serves as a synchronization primitive so that we know whether
947 i3 discarded the +SUBSCRIBE+ message or didn’t answer it yet.
949 4. Receive a message header from i3, decoding the message type as big endian.
951 * If the message’s reply type is +COMMAND+ (0), i3 is running in little
952 endian (because the +SUBSCRIBE+ message was discarded). Decode the message
953 payload length as little endian, receive the message payload.
955 * If the message’s reply type is anything else, i3 is running in big endian
956 (because our big endian encoded +SUBSCRIBE+ message was answered). Decode
957 the message payload length in big endian, receive the message
958 payload. Then, receive the pending +COMMAND+ message reply in big endian.
960 5. From here on out, send/receive all messages using the detected byte order.