From 7deb23c727da85e20004f123e237e677431377e8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 23 Apr 2014 19:49:50 +0200 Subject: [PATCH] add docs/layout-saving MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Feedback on this new document is very much appreciated, please don’t hesitate to state anything that is hard to understand/could be improved. --- docs/docs.mk | 3 +- docs/layout-saving | 233 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 docs/layout-saving diff --git a/docs/docs.mk b/docs/docs.mk index 8a522cce..050df97d 100644 --- a/docs/docs.mk +++ b/docs/docs.mk @@ -14,7 +14,8 @@ ASCIIDOC_TOC_TARGETS = \ docs/multi-monitor.html \ docs/wsbar.html \ docs/testsuite.html \ - docs/i3bar-protocol.html + docs/i3bar-protocol.html \ + docs/layout-saving.html ASCIIDOC_TARGETS = \ $(ASCIIDOC_TOC_TARGETS) \ diff --git a/docs/layout-saving b/docs/layout-saving new file mode 100644 index 00000000..2b798df5 --- /dev/null +++ b/docs/layout-saving @@ -0,0 +1,233 @@ +Layout saving in i3 +=================== +Michael Stapelberg +April 2014 + +Layout saving/restoring is a feature that was introduced in i3 v4.8. + +Layout saving/restoring allows you to load a JSON layout file so that you can +have a base layout to start working with after powering on your computer. +Dynamic use-cases also come to mind: if you frequently (but not always!) need a +grid layout of terminals with ping/traceroute commands to diagnose network +issues, you can easily automate opening these windows in just the right layout. + +== Saving the layout + +You can save the layout of either a single workspace or an entire output (e.g. +LVDS1). Of course, you can repeat this step multiple times if you want to +save/restore multiple workspaces/outputs. + ++i3-save-tree(1)+ is a tool to save the layout. It will print a JSON +representation of i3’s internal layout data structures to stdout. Typically, +you may want to take a quick look at the output, then save it to a file and +tweak it a little bit: + +--------------------------------------------------- +i3-save-tree --workspace 1 > ~/.i3/workspace-1.json +--------------------------------------------------- + +Please note that the output of +i3-save-tree(1)+ is *NOT useful* until you +manually modify it — you need to tell i3 how to match/distinguish windows (for +example based on their WM_CLASS, title, etc.). By default, all the different +window properties are included in the output, but commented out. This is partly +to avoid relying on heuristics and partly to make you aware how i3 works so +that you can easily solve layout restoring problems. + +How to modify the file manually is described in <>. + +== Restoring the layout + +After restoring the example layout from <>, i3 will open +placeholder windows for all the windows that were specified in the layout file. +You can recognize the placeholder windows by the watch symbol +footnote:[Depending on the font you are using, a placeholder symbol may show up +instead of the watch symbol.] in the center of the window, and by the swallow +criteria specification at the top of the window: + +image:layout-saving-1.png["Restored layout",width=400,link="layout-saving-1.png"] + +When an application opens a window that matches the specified swallow criteria, +it will be placed in the corresponding placeholder window. We say it gets +*swallowed* by the placeholder container, hence the term. + +Note: Swallowing windows into unsatisfied placeholder windows takes precedence +over +link:http://i3wm.org/docs/userguide.html#_automatically_putting_clients_on_specific_workspaces[assignment +rules]. For example, if you assign all Emacs windows to workspace 1 in your i3 +configuration file, but there is a placeholder window on workspace 2 which +matches Emacs as well, your newly started Emacs window will end up in the +placeholder window on workspace 2. + +The placeholder windows are just regular windows, so feel free to move them +around or close them, for example. + +=== append_layout command + +The +append_layout+ command is used to load a layout file into i3. It accepts a +path (relative to i3’s current working directory or absolute) to a JSON file. + +*Syntax*: +-------------------------------------------------------------------------------- +append_layout +-------------------------------------------------------------------------------- + +*Examples*: +-------------------------------------------------------------------------------- +# From a terminal or script: +i3-msg "workspace 1; append_layout /home/michael/.i3/workspace-1.json" + +# In your i3 configuration file, you can autostart i3-msg like this: +# (Note that those lines will quickly become long, so typically you would store +# them in a script with proper indentation.) +exec --no-startup-id "i3-msg 'workspace 1; append_layout /home/michael/.i3/workspace-1.json'" +-------------------------------------------------------------------------------- + +== Editing layout files + +[[EditingLayoutFiles]] + +=== Anatomy of a layout file + +Here is an example layout file that we’ll discuss: + +-------------------------------------------------------------------------------- +{ + // splitv split container with 2 children + "layout": "splitv", + "percent": 0.4, + "type": "con", + "nodes": [ + { + "border": "none", + "name": "irssi", + "percent": 0.5, + "type": "con", + "swallows": [ + { + "class": "^URxvt$", + "instance": "^irssi$" + } + ] + }, + { + // stacked split container with 2 children + "layout": "stacked", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "name": "notmuch", + "percent": 0.5, + "type": "con", + "swallows": [ + { + "class": "^Emacs$", + "instance": "^notmuch$" + } + ] + }, + { + "name": "midna: ~", + "percent": 0.5, + "type": "con" + } + ] + } + ] +} + +{ + // stacked split container with 1 children + "layout": "stacked", + "percent": 0.6, + "type": "con", + "nodes": [ + { + "name": "chrome", + "type": "con", + "swallows": [ + { + "class": "^Google-chrome$" + } + ] + } + ] +} +-------------------------------------------------------------------------------- + +In this layout, the screen is divided into two columns. In the left column, +which covers 40% of the screen, there is a terminal emulator running irssi on +the top, and a stacked split container with an Emacs window and a terminal +emulator on the bottom. In the right column, there is a stacked container with +a Chrome window: + +image:layout-saving-1.png["Restored layout",width=400,link="layout-saving-1.png"] + +The structure of this JSON file looks a lot like the +TREE+ reply, see +http://build.i3wm.org/docs/ipc.html#_tree_reply for documentation on that. Some +properties are excluded because they are not relevant when restoring a layout. + +Most importantly, look at the "swallows" section of each window. This is where +you need to be more or less specific. As an example, remember the section about +the Emacs window: + +-------------------------------------------------------------------------------- +"swallows": [ + { + "class": "^Emacs$", + "instance": "^notmuch$" + } +] +-------------------------------------------------------------------------------- + +Here you can see that i3 will require both the class and the instance to match. +Therefore, if you just start Emacs via dmenu, it will not get swallowed by that +container. Only if you start Emacs with the proper instance name (+emacs24 +--name notmuch+), it will get swallowed. + +You can match on "class", "instance", "window_role" and "title". All values are +case-sensitive regular expressions (PCRE). Use +xprop(1)+ and click into a +window to see its properties: + +-------------------------------------------------------------------------------- +$ xprop +WM_WINDOW_ROLE(STRING) = "gimp-toolbox-color-dialog" +WM_CLASS(STRING) = "gimp-2.8", "Gimp-2.8" +_NET_WM_NAME(UTF8_STRING) = "Change Foreground Color" +-------------------------------------------------------------------------------- + +The first part of +WM_CLASS+ is the "instance" (gimp-2.8 in this case), the +second part is the "class" (Gimp-2.8 in this case). "title" matches against ++_NET_WM_NAME+ and "window_role" matches against +WM_WINDOW_ROLE+. + +In general, you should try to be as specific as possible in your swallow +criteria. Try to use criteria that match one window and only one window, to +have a reliable startup procedure. + +If you specify multiple swallow criteria, the placeholder will be replaced by +the window which matches any of the criteria. As an example: + +-------------------------------------------------------------------------------- +// Matches either Emacs or Gvim, whichever one is started first. +"swallows": [ + {"class": "^Emacs$"}, + {"class": "^Gvim$"} +] +-------------------------------------------------------------------------------- + +=== JSON standard non-compliance + +A layout file as generated by +i3-save-tree(1)+ is not strictly valid JSON: + +1. Layout files contain multiple “JSON documents” on the top level, whereas the + JSON standard only allows precisely one “document” (array or hash). + +2. Layout files contain comments which are not standardized, but understood by + many parsers. + +Both deviations from the JSON standard are to make manual editing by humans +easier. In case you are writing a more elaborate tool for manipulating these +layouts, you can either use a JSON parser that supports these deviations (for +example libyajl), transform the layout file to a JSON-conforming file, or +link:http://cr.i3wm.org/[submit a patch] to make +i3-save-tree(1)+ optionally +output standard-conforming JSON. -- 2.39.5