]> git.sur5r.net Git - i3/i3/blobdiff - docs/ipc
Merge branch 'fix-baf'
[i3/i3] / docs / ipc
index 35a5fa036914aca8318576ca6933f4a121300b25..fc46590e0777d8973a5771e061c861631604a1a4 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -1,7 +1,7 @@
 IPC interface (interprocess communication)
 ==========================================
 Michael Stapelberg <michael+i3@stapelberg.de>
-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
@@ -10,9 +10,12 @@ workspace bar.
 
 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, no ipc-socket path is
-specified and thus no socket is created. The standard path (which +i3-msg+ and
-+i3-input+ use) is +/tmp/i3-ipc.sock+.
+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. 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.
 
 == Establishing a connection
 
@@ -21,17 +24,18 @@ 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
 
 To send a message to i3, you have to format in the binary message format which
 i3 expects. This format specifies a magic string in the beginning to ensure
-the integrity of messages (to prevent follow-up errors). Afterwards follows
-the length of the payload of the message as 32-bit integer and the type of
-the message as 32-bit integer (the integers are not converted, so they are
-in native byte order).
+the integrity of messages (to prevent follow-up errors). Following the magic
+string comes the length of the payload of the message as 32-bit integer, and
+the type of the message as 32-bit integer (the integers are not converted, so
+they are in native byte order).
 
 The magic string currently is "i3-ipc" and will only be changed when a change
 in the IPC API is done which breaks compatibility (we hope that we don’t need
@@ -52,6 +56,18 @@ SUBSCRIBE (2)::
 GET_OUTPUTS (3)::
        Gets the current outputs. The reply will be a JSON-encoded list of outputs
        (see the reply section).
+GET_TREE (4)::
+       Gets the layout tree. i3 uses a tree as data structure which includes
+       every container. The reply will be the JSON-encoded tree (see the reply
+       section).
+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:
 --------------------------------------------------
@@ -75,11 +91,11 @@ sub format_ipc_command {
 }
 
 $sock->write(format_ipc_command("exit"));
-------------------------------------------------------------
+------------------------------------------------------------------------------
 
 == Receiving replies from i3
 
-Replies of i3 usually consist of a simple string (the length of the string
+Replies from i3 usually consist of a simple string (the length of the string
 is the message_length, so you can consider them length-prefixed) which in turn
 contain the JSON serialization of a data structure. For example, the
 GET_WORKSPACES message returns an array of workspaces (each workspace is a map
@@ -101,6 +117,12 @@ SUBSCRIBE (2)::
        Confirmation/Error code for the SUBSCRIBE message.
 GET_OUTPUTS (3)::
        Reply to the GET_OUTPUTS message.
+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
 
@@ -226,6 +248,282 @@ rect (map)::
 ]
 -------------------
 
+=== GET_TREE reply
+
+The reply consists of a serialized tree. Each node in the tree (representing
+one container) has at least the properties listed below. While the nodes might
+have more properties, please do not use any properties which are not documented
+here. They are not yet finalized and will probably change!
+
+id (integer)::
+       The internal ID (actually a C pointer value) of this container. Do not
+       make any assumptions about it. You can use it to (re-)identify and
+       address containers when talking to i3.
+name (string)::
+       The internal name of this container. For all containers which are part
+       of the tree structure down to the workspace contents, this is set to a
+       nice human-readable name of the container.
+       For all other containers, the content is not defined (yet).
+border (string)::
+       Can be either "normal", "none" or "1pixel", dependending on the
+       container’s border style.
+layout (string)::
+       Can be either "default", "stacked", "tabbed", "dockarea" or "output".
+       Other values might be possible in the future, should we add new
+       layouts.
+orientation (string)::
+       Can be either "none" (for non-split containers), "horizontal" or
+       "vertical".
+percent (float)::
+       The percentage which this container takes in its parent. A value of
+       +null+ means that the percent property does not make sense for this
+       container, for example for the root container.
+rect (map)::
+       The absolute display coordinates for this container. Display
+       coordinates means that when you have two 1600x1200 monitors on a single
+       X11 Display (the standard way), the coordinates of the first window on
+       the second monitor are +{ "x": 1600, "y": 0, "width": 1600, "height":
+       1200 }+.
+window_rect (map)::
+       The coordinates of the *actual client window* inside its container.
+       These coordinates are relative to the container and do not include the
+       window decoration (which is actually rendered on the parent container).
+       So, when using the +default+ layout, you will have a 2 pixel border on
+       each side, making the window_rect +{ "x": 2, "y": 0, "width": 632,
+       "height": 366 }+ (for example).
+geometry (map)::
+       The original geometry the window specified when i3 mapped it. Used when
+       switching a window to floating mode, for example.
+urgent (bool)::
+       Whether this container (window or workspace) has the urgency hint set.
+focused (bool)::
+       Whether this container is currently focused.
+
+Please note that in the following example, I have left out some keys/values
+which are not relevant for the type of the node. Otherwise, the example would
+be by far too long (it already is quite long, despite showing only 1 window and
+one dock window).
+
+It is useful to have an overview of the structure before taking a look at the
+JSON dump:
+
+* root
+** LVDS1
+*** topdock
+*** content
+**** workspace 1
+***** window 1
+*** bottomdock
+**** dock window 1
+** VGA1
+
+*Example:*
+-----------------------
+{
+ "id": 6875648,
+ "name": "root",
+ "rect": {
+   "x": 0,
+   "y": 0,
+   "width": 1280,
+   "height": 800
+ },
+ "nodes": [
+
+   {
+    "id": 6878320,
+    "name": "LVDS1",
+    "layout": "output",
+    "rect": {
+      "x": 0,
+      "y": 0,
+      "width": 1280,
+      "height": 800
+    },
+    "nodes": [
+
+      {
+       "id": 6878784,
+       "name": "topdock",
+       "layout": "dockarea",
+       "orientation": "vertical",
+       "rect": {
+         "x": 0,
+        "y": 0,
+        "width": 1280,
+        "height": 0
+       },
+      },
+
+      {
+       "id": 6879344,
+       "name": "content",
+       "rect": {
+         "x": 0,
+        "y": 0,
+        "width": 1280,
+        "height": 782
+       },
+       "nodes": [
+
+         {
+          "id": 6880464,
+         "name": "1",
+         "orientation": "horizontal",
+         "rect": {
+            "x": 0,
+           "y": 0,
+           "width": 1280,
+           "height": 782
+         },
+         "floating_nodes": [],
+         "nodes": [
+
+            {
+             "id": 6929968,
+            "name": "#aa0000",
+            "border": "normal",
+            "percent": 1,
+            "rect": {
+               "x": 0,
+              "y": 18,
+              "width": 1280,
+              "height": 782
+            }
+           }
+
+         ]
+        }
+
+       ]
+      },
+
+      {
+       "id": 6880208,
+       "name": "bottomdock",
+       "layout": "dockarea",
+       "orientation": "vertical",
+       "rect": {
+         "x": 0,
+        "y": 782,
+        "width": 1280,
+        "height": 18
+       },
+       "nodes": [
+
+         {
+          "id": 6931312,
+         "name": "#00aa00",
+         "percent": 1,
+         "rect": {
+            "x": 0,
+           "y": 782,
+           "width": 1280,
+           "height": 18
+         }
+        }
+
+       ]
+      }
+    ]
+   }
+ ]
+}
+------------------------
+
+=== GET_MARKS reply
+
+The reply consists of a single array of strings for each container that has a
+mark. The order of that array is undefined. If more than one container has the
+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 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
 
 [[events]]
@@ -233,15 +531,16 @@ rect (map)::
 To get informed when certain things happen in i3, clients can subscribe to
 events. Events consist of a name (like "workspace") and an event reply type
 (like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format
-as replies to specific commands.
+as replies to specific commands. However, the highest bit of the message type
+is set to 1 to indicate that this is an event reply instead of a normal reply.
 
 Caveat: As soon as you subscribe to an event, it is not guaranteed any longer
 that the requests to i3 are processed in order. This means, the following
 situation can happen: You send a GET_WORKSPACES request but you receive a
 "workspace" event before receiving the reply to GET_WORKSPACES. If your
 program does not want to cope which such kinds of race conditions (an
-event based library may not have a problem here), I advise to create a separate
-connection to receive events.
+event based library may not have a problem here), I suggest you create a
+separate connection to receive events.
 
 === Subscribing to events
 
@@ -254,24 +553,60 @@ type: SUBSCRIBE
 payload: [ "workspace", "focus" ]
 ---------------------------------
 
+
 === Available events
 
-workspace::
+The numbers in parenthesis is the event type (keep in mind that you need to
+strip the highest bit first).
+
+workspace (0)::
        Sent when the user switches to a different workspace, when a new
        workspace is initialized or when a workspace is removed (because the
        last client vanished).
+output (1)::
+       Sent when RandR issues a change notification (of either screens,
+       outputs, CRTCs or output properties).
+
+*Example:*
+--------------------------------------------------------------------
+# the appropriate 4 bytes read from the socket are stored in $input
+
+# unpack a 32-bit unsigned integer
+my $message_type = unpack("L", $input);
+
+# check if the highest bit is 1
+my $is_event = (($message_type >> 31) == 1);
+
+# use the other bits
+my $event_type = ($message_type & 0x7F);
+
+if ($is_event) {
+  say "Received event of type $event_type";
+}
+--------------------------------------------------------------------
 
 === workspace event
 
 This event consists of a single serialized map containing a property
 +change (string)+ which indicates the type of the change ("focus", "init",
-"empty").
+"empty", "urgent").
 
 *Example:*
 ---------------------
 { "change": "focus" }
 ---------------------
 
+=== output event
+
+This event consists of a single serialized map containing a property
++change (string)+ which indicates the type of the change (currently only
+"unspecified").
+
+*Example:*
+---------------------------
+{ "change": "unspecified" }
+---------------------------
+
 == See also
 
 For some languages, libraries are available (so you don’t have to implement
@@ -285,3 +620,5 @@ Ruby::
        http://github.com/badboy/i3-ipc
 Perl::
        http://search.cpan.org/search?query=AnyEvent::I3
+Python::
+       http://github.com/thepub/i3ipc