X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=docs%2Fipc;h=e44ffd7ce20f2c38230bef3e137e02f73a22ea0e;hb=bd7a5ee48a4e6acba2a885508f0b26c6f4d963c3;hp=75ea9179d3e6de7d0105a0d33b1e8f94b257f2a0;hpb=39415fe16d96099015487827a763bc63c047dabe;p=i3%2Fi3 diff --git a/docs/ipc b/docs/ipc index 75ea9179..e44ffd7c 100644 --- a/docs/ipc +++ b/docs/ipc @@ -1,7 +1,7 @@ IPC interface (interprocess communication) ========================================== Michael Stapelberg -October 2014 +September 2017 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 @@ -63,6 +63,9 @@ to do that). | 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. | 7 | +GET_VERSION+ | <<_version_reply,VERSION>> | Gets the i3 version. | 8 | +GET_BINDING_MODES+ | <<_binding_modes_reply,BINDING_MODES>> | Gets the names of all currently configured binding modes. +| 9 | +GET_CONFIG+ | <<_config_reply,CONFIG>> | Returns the last loaded i3 config. +| 10 | +SEND_TICK+ | <<_tick_reply,TICK>> | Sends a tick event with the specified payload. +| 11 | +SYNC+ | <<_sync_reply,SYNC>> | Sends an i3 sync event with the specified random value to the specified window. |====================================================== So, a typical message could look like this: @@ -123,6 +126,10 @@ VERSION (7):: Reply to the GET_VERSION message. BINDING_MODES (8):: Reply to the GET_BINDING_MODES message. +GET_CONFIG (9):: + Reply to the GET_CONFIG message. +TICK (10):: + Reply to the SEND_TICK message. [[_command_reply]] === COMMAND reply @@ -321,6 +328,8 @@ window (integer):: This field is set to null for split containers or otherwise empty containers. This ID corresponds to what xwininfo(1) and other X11-related tools display (usually in hex). +window_properties (map):: + X11 window properties title, instance, class, window_role and transient_for. urgent (bool):: Whether this container (window, split container, floating container or workspace) has the urgency hint set, directly or indirectly. All parent @@ -416,6 +425,12 @@ JSON dump: "width": 1280, "height": 782 }, + "window_properties": { + "class": "Evince", + "instance": "evince", + "title": "Properties", + "transient_for": 52428808 + }, "floating_nodes": [], "nodes": [ @@ -623,6 +638,43 @@ The reply consists of an array of all currently configured binding modes. ["default", "resize"] --------------------- +[[_config_reply]] +=== CONFIG reply + +The config reply is a map which currently only contains the "config" member, +which is a string containing the config file as loaded by i3 most recently. + +*Example:* +------------------- +{ "config": "font pango:monospace 8\nbindsym Mod4+q exit\n" } +------------------- + +[[_tick_reply]] +=== TICK reply + +The reply is a map containing the "success" member. After the reply was +received, the tick event has been written to all IPC connections which subscribe +to tick events. UNIX sockets are usually buffered, but you can be certain that +once you receive the tick event you just triggered, you must have received all +events generated prior to the +SEND_TICK+ message (happened-before relation). + +*Example:* +------------------- +{ "success": true } +------------------- + +[[_sync_reply]] +=== SYNC reply + +The reply is a map containing the "success" member. After the reply was +received, the https://i3wm.org/docs/testsuite.html#i3_sync[i3 sync message] was +responded to. + +*Example:* +------------------- +{ "success": true } +------------------- + == Events [[events]] @@ -679,6 +731,10 @@ binding (5):: mouse shutdown (6):: Sent when the ipc shuts down because of a restart or exit by user command +tick (7):: + Sent when the ipc client subscribes to the tick event (with +"first": + true+) or when any ipc client sends a SEND_TICK message (with +"first": + false+). *Example:* -------------------------------------------------------------------- @@ -851,6 +907,27 @@ because of a user action such as a +restart+ or +exit+ command. The +change } --------------------------- +=== tick event + +This event is triggered by a subscription to tick events or by a +SEND_TICK+ +message. + +*Example (upon subscription):* +-------------------------------------------------------------------------------- +{ + "first": true, + "payload": "" +} +-------------------------------------------------------------------------------- + +*Example (upon +SEND_TICK+ with a payload of +arbitrary string+):* +-------------------------------------------------------------------------------- +{ + "first": false, + "payload": "arbitrary string" +} +-------------------------------------------------------------------------------- + == See also (existing libraries) [[libraries]] @@ -866,6 +943,7 @@ C++:: * https://github.com/drmgc/i3ipcpp Go:: * https://github.com/mdirkse/i3ipc-go + * https://github.com/i3/go-i3 JavaScript:: * https://github.com/acrisci/i3ipc-gjs Lua:: @@ -883,3 +961,66 @@ Rust:: * https://github.com/tmerr/i3ipc-rs OCaml:: * https://github.com/Armael/ocaml-i3ipc + +== Appendix A: Detecting byte order in memory-safe languages + +Some programming languages such as Go don’t offer a way to serialize data in the +native byte order of the machine they’re running on without resorting to tricks +involving the +unsafe+ package. + +The following technique can be used (and will not be broken by changes to i3) to +detect the byte order i3 is using: + +1. The byte order dependent fields of an IPC message are message type and + payload length. + + * The message type +RUN_COMMAND+ (0) is the same in big and little endian, so + we can use it in either byte order to elicit a reply from i3. + + * The payload length 65536 + 256 (+0x00 01 01 00+) is the same in big and + little endian, and also small enough to not worry about memory allocations + of that size. We must use payloads of length 65536 + 256 in every message + we send, so that i3 will be able to read the entire message regardless of + the byte order it uses. + +2. Send a big endian encoded message of type +SUBSCRIBE+ (2) with payload `[]` + followed by 65536 + 256 - 2 +SPACE+ (ASCII 0x20) bytes. + + * If i3 is running in big endian, this message is treated as a noop, + resulting in a +SUBSCRIBE+ reply with payload `{"success":true}` + footnote:[A small payload is important: that way, we circumvent dealing + with UNIX domain socket buffer sizes, whose size depends on the + implementation/operating system. Exhausting such a buffer results in an i3 + deadlock unless you concurrently read and write, which — depending on the + programming language — makes the technique much more complicated.]. + + * If i3 is running in little endian, this message is read in its entirety due + to the byte order independent payload length, then + https://github.com/i3/i3/blob/d726d09d496577d1c337a4b97486f2c9fbc914f1/src/ipc.c#L1188[silently + discarded] due to the unknown message type. + +3. Send a byte order independent message, i.e. type +RUN_COMMAND+ (0) with + payload +nop byte order detection. padding:+, padded to 65536 + 256 bytes + with +a+ (ASCII 0x61) bytes. i3 will reply to this message with a reply of + type +COMMAND+ (0). + + * The human-readable prefix is in there to not confuse readers of the i3 log. + + * This messages serves as a synchronization primitive so that we know whether + i3 discarded the +SUBSCRIBE+ message or didn’t answer it yet. + +4. Receive a message header from i3, decoding the message type as big endian. + + * If the message’s reply type is +COMMAND+ (0), i3 is running in little + endian (because the +SUBSCRIBE+ message was discarded). Decode the message + payload length as little endian, receive the message payload. + + * If the message’s reply type is anything else, i3 is running in big endian + (because our big endian encoded +SUBSCRIBE+ message was answered). Decode + the message payload length in big endian, receive the message + payload. Then, receive the pending +COMMAND+ message reply in big endian. + +5. From here on out, send/receive all messages using the detected byte order. + +Find an example implementation of this technique in +https://github.com/i3/go-i3/blob/master/byteorder.go