]> git.sur5r.net Git - i3/i3.github.io/blob - docs/layout-saving.html
add the 4.8 release
[i3/i3.github.io] / docs / layout-saving.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
2     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
4 <head>\r
5 <link rel="icon" type="image/png" href="/favicon.png">\r
6 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
7 <meta name="generator" content="AsciiDoc 8.6.9" />\r
8 <title>i3: Layout saving in i3</title>\r
9 <link rel="stylesheet" href="/css/style.css" type="text/css" />\r
10 <link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
11 <script type="text/javascript">\r
12 /*<![CDATA[*/\r
13 document.addEventListener("DOMContentLoaded", function(){asciidoc.footnotes(); asciidoc.toc(2);}, false);\r
14 /*]]>*/\r
15 </script>\r
16 <script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
17 </head>\r
18 <body class="article">\r
19 \r
20         <div id="main">\r
21             <a href="/"><h1 id="title">i3 - improved tiling WM</h1></a>\r
22                         <ul id="nav">\r
23                                 <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
24                                 <li><a href="/screenshots">Screens</a></li>\r
25                                 <li><a href="/contact">Contact</a></li>\r
26                                 <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
27                         </ul>\r
28         <br style="clear: both">\r
29 <div id="content">\r
30 <div id="header">\r
31 <h1>Layout saving in i3</h1>\r
32 <span id="author">Michael Stapelberg</span><br />\r
33 <span id="email"><tt>&lt;<a href="mailto:michael@i3wm.org">michael@i3wm.org</a>&gt;</tt></span><br />\r
34 <span id="revdate">April 2014</span>\r
35 <div id="toc">
36   <div id="toctitle">Table of Contents</div>
37   <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
38 </div>\r
39 </div>\r
40 <div id="preamble">\r
41 <div class="sectionbody">\r
42 <div class="paragraph"><p>Layout saving/restoring is a feature that was introduced in i3 v4.8.</p></div>\r
43 <div class="paragraph"><p>Layout saving/restoring allows you to load a JSON layout file so that you can\r
44 have a base layout to start working with after powering on your computer.\r
45 Dynamic use-cases also come to mind: if you frequently (but not always!) need a\r
46 grid layout of terminals with ping/traceroute commands to diagnose network\r
47 issues, you can easily automate opening these windows in just the right layout.</p></div>\r
48 </div>\r
49 </div>\r
50 <div class="sect1">\r
51 <h2 id="_saving_the_layout">1. Saving the layout</h2>\r
52 <div class="sectionbody">\r
53 <div class="paragraph"><p>You can save the layout of either a single workspace or an entire output (e.g.\r
54 LVDS1). Of course, you can repeat this step multiple times if you want to\r
55 save/restore multiple workspaces/outputs.</p></div>\r
56 <div class="paragraph"><p><tt>i3-save-tree(1)</tt> is a tool to save the layout. It will print a JSON\r
57 representation of i3’s internal layout data structures to stdout. Typically,\r
58 you may want to take a quick look at the output, then save it to a file and\r
59 tweak it a little bit:</p></div>\r
60 <div class="listingblock">\r
61 <div class="content">\r
62 <pre><tt>i3-save-tree --workspace 1 &gt; ~/.i3/workspace-1.json</tt></pre>\r
63 </div></div>\r
64 <div class="paragraph"><p>Please note that the output of <tt>i3-save-tree(1)</tt> is <strong>NOT useful</strong> until you\r
65 manually modify it — you need to tell i3 how to match/distinguish windows (for\r
66 example based on their WM_CLASS, title, etc.). By default, all the different\r
67 window properties are included in the output, but commented out. This is partly\r
68 to avoid relying on heuristics and partly to make you aware how i3 works so\r
69 that you can easily solve layout restoring problems.</p></div>\r
70 <div class="paragraph"><p>How to modify the file manually is described in <a href="#EditingLayoutFiles">[EditingLayoutFiles]</a>.</p></div>\r
71 </div>\r
72 </div>\r
73 <div class="sect1">\r
74 <h2 id="_restoring_the_layout">2. Restoring the layout</h2>\r
75 <div class="sectionbody">\r
76 <div class="paragraph"><p>After restoring the example layout from <a href="#EditingLayoutFiles">[EditingLayoutFiles]</a>, i3 will open\r
77 placeholder windows for all the windows that were specified in the layout file.\r
78 You can recognize the placeholder windows by the watch symbol\r
79 <span class="footnote"><br />[Depending on the font you are using, a placeholder symbol may show up\r
80 instead of the watch symbol.]<br /></span> in the center of the window, and by the swallow\r
81 criteria specification at the top of the window:</p></div>\r
82 <div class="paragraph"><p><span class="image">\r
83 <a class="image" href="layout-saving-1.png">\r
84 <img src="layout-saving-1.png" alt="Restored layout" width="400" />\r
85 </a>\r
86 </span></p></div>\r
87 <div class="paragraph"><p>When an application opens a window that matches the specified swallow criteria,\r
88 it will be placed in the corresponding placeholder window. We say it gets\r
89 <strong>swallowed</strong> by the placeholder container, hence the term.</p></div>\r
90 <div class="paragraph"><p>Note: Swallowing windows into unsatisfied placeholder windows takes precedence\r
91 over\r
92 <a href="http://i3wm.org/docs/userguide.html#_automatically_putting_clients_on_specific_workspaces">assignment\r
93 rules</a>. For example, if you assign all Emacs windows to workspace 1 in your i3\r
94 configuration file, but there is a placeholder window on workspace 2 which\r
95 matches Emacs as well, your newly started Emacs window will end up in the\r
96 placeholder window on workspace 2.</p></div>\r
97 <div class="paragraph"><p>The placeholder windows are just regular windows, so feel free to move them\r
98 around or close them, for example.</p></div>\r
99 <div class="sect2">\r
100 <h3 id="_append_layout_command">2.1. append_layout command</h3>\r
101 <div class="paragraph"><p>The <tt>append_layout</tt> command is used to load a layout file into i3. It accepts a\r
102 path (relative to i3’s current working directory or absolute) to a JSON file.</p></div>\r
103 <div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
104 <div class="listingblock">\r
105 <div class="content">\r
106 <pre><tt>append_layout &lt;path&gt;</tt></pre>\r
107 </div></div>\r
108 <div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
109 <div class="listingblock">\r
110 <div class="content">\r
111 <pre><tt># From a terminal or script:\r
112 i3-msg "workspace 1; append_layout /home/michael/.i3/workspace-1.json"\r
113 \r
114 # In your i3 configuration file, you can autostart i3-msg like this:\r
115 # (Note that those lines will quickly become long, so typically you would store\r
116 #  them in a script with proper indentation.)\r
117 exec --no-startup-id "i3-msg 'workspace 1; append_layout /home/michael/.i3/workspace-1.json'"</tt></pre>\r
118 </div></div>\r
119 </div>\r
120 </div>\r
121 </div>\r
122 <div class="sect1">\r
123 <h2 id="_editing_layout_files">3. Editing layout files</h2>\r
124 <div class="sectionbody">\r
125 <div class="sect2">\r
126 <h3 id="EditingLayoutFiles">3.1. Anatomy of a layout file</h3>\r
127 <div class="paragraph"><p>Here is an example layout file that we’ll discuss:</p></div>\r
128 <div class="listingblock">\r
129 <div class="content">\r
130 <pre><tt>{\r
131     // splitv split container with 2 children\r
132     "layout": "splitv",\r
133     "percent": 0.4,\r
134     "type": "con",\r
135     "nodes": [\r
136         {\r
137             "border": "none",\r
138             "name": "irssi",\r
139             "percent": 0.5,\r
140             "type": "con",\r
141             "swallows": [\r
142                 {\r
143                     "class": "^URxvt$",\r
144                     "instance": "^irssi$"\r
145                 }\r
146             ]\r
147         },\r
148         {\r
149             // stacked split container with 2 children\r
150             "layout": "stacked",\r
151             "percent": 0.5,\r
152             "type": "con",\r
153             "nodes": [\r
154                 {\r
155                     "name": "notmuch",\r
156                     "percent": 0.5,\r
157                     "type": "con",\r
158                     "swallows": [\r
159                         {\r
160                             "class": "^Emacs$",\r
161                             "instance": "^notmuch$"\r
162                         }\r
163                     ]\r
164                 },\r
165                 {\r
166                     "name": "midna: ~",\r
167                     "percent": 0.5,\r
168                     "type": "con"\r
169                 }\r
170             ]\r
171         }\r
172     ]\r
173 }\r
174 \r
175 {\r
176     // stacked split container with 1 children\r
177     "layout": "stacked",\r
178     "percent": 0.6,\r
179     "type": "con",\r
180     "nodes": [\r
181         {\r
182             "name": "chrome",\r
183             "type": "con",\r
184             "swallows": [\r
185                 {\r
186                     "class": "^Google-chrome$"\r
187                 }\r
188             ]\r
189         }\r
190     ]\r
191 }</tt></pre>\r
192 </div></div>\r
193 <div class="paragraph"><p>In this layout, the screen is divided into two columns. In the left column,\r
194 which covers 40% of the screen, there is a terminal emulator running irssi on\r
195 the top, and a stacked split container with an Emacs window and a terminal\r
196 emulator on the bottom. In the right column, there is a stacked container with\r
197 a Chrome window:</p></div>\r
198 <div class="paragraph"><p><span class="image">\r
199 <a class="image" href="layout-saving-1.png">\r
200 <img src="layout-saving-1.png" alt="Restored layout" width="400" />\r
201 </a>\r
202 </span></p></div>\r
203 <div class="paragraph"><p>The structure of this JSON file looks a lot like the <tt>TREE</tt> reply, see\r
204 <a href="http://build.i3wm.org/docs/ipc.html#_tree_reply">http://build.i3wm.org/docs/ipc.html#_tree_reply</a> for documentation on that. Some\r
205 properties are excluded because they are not relevant when restoring a layout.</p></div>\r
206 <div class="paragraph"><p>Most importantly, look at the "swallows" section of each window. This is where\r
207 you need to be more or less specific. As an example, remember the section about\r
208 the Emacs window:</p></div>\r
209 <div class="listingblock">\r
210 <div class="content">\r
211 <pre><tt>"swallows": [\r
212     {\r
213         "class": "^Emacs$",\r
214         "instance": "^notmuch$"\r
215     }\r
216 ]</tt></pre>\r
217 </div></div>\r
218 <div class="paragraph"><p>Here you can see that i3 will require both the class and the instance to match.\r
219 Therefore, if you just start Emacs via dmenu, it will not get swallowed by that\r
220 container. Only if you start Emacs with the proper instance name (<tt>emacs24\r
221 --name notmuch</tt>), it will get swallowed.</p></div>\r
222 <div class="paragraph"><p>You can match on "class", "instance", "window_role" and "title". All values are\r
223 case-sensitive regular expressions (PCRE). Use <tt>xprop(1)</tt> and click into a\r
224 window to see its properties:</p></div>\r
225 <div class="listingblock">\r
226 <div class="content">\r
227 <pre><tt>$ xprop\r
228 WM_WINDOW_ROLE(STRING) = "gimp-toolbox-color-dialog"\r
229 WM_CLASS(STRING) = "gimp-2.8", "Gimp-2.8"\r
230 _NET_WM_NAME(UTF8_STRING) = "Change Foreground Color"</tt></pre>\r
231 </div></div>\r
232 <div class="paragraph"><p>The first part of <tt>WM_CLASS</tt> is the "instance" (gimp-2.8 in this case), the\r
233 second part is the "class" (Gimp-2.8 in this case). "title" matches against\r
234 <tt>_NET_WM_NAME</tt> and "window_role" matches against <tt>WM_WINDOW_ROLE</tt>.</p></div>\r
235 <div class="paragraph"><p>In general, you should try to be as specific as possible in your swallow\r
236 criteria. Try to use criteria that match one window and only one window, to\r
237 have a reliable startup procedure.</p></div>\r
238 <div class="paragraph"><p>If you specify multiple swallow criteria, the placeholder will be replaced by\r
239 the window which matches any of the criteria. As an example:</p></div>\r
240 <div class="listingblock">\r
241 <div class="content">\r
242 <pre><tt>// Matches either Emacs or Gvim, whichever one is started first.\r
243 "swallows": [\r
244     {"class": "^Emacs$"},\r
245     {"class": "^Gvim$"}\r
246 ]</tt></pre>\r
247 </div></div>\r
248 </div>\r
249 <div class="sect2">\r
250 <h3 id="_json_standard_non_compliance">3.2. JSON standard non-compliance</h3>\r
251 <div class="paragraph"><p>A layout file as generated by <tt>i3-save-tree(1)</tt> is not strictly valid JSON:</p></div>\r
252 <div class="olist arabic"><ol class="arabic">\r
253 <li>\r
254 <p>\r
255 Layout files contain multiple “JSON documents” on the top level, whereas the\r
256    JSON standard only allows precisely one “document” (array or hash).\r
257 </p>\r
258 </li>\r
259 <li>\r
260 <p>\r
261 Layout files contain comments which are not standardized, but understood by\r
262    many parsers.\r
263 </p>\r
264 </li>\r
265 </ol></div>\r
266 <div class="paragraph"><p>Both deviations from the JSON standard are to make manual editing by humans\r
267 easier. In case you are writing a more elaborate tool for manipulating these\r
268 layouts, you can either use a JSON parser that supports these deviations (for\r
269 example libyajl), transform the layout file to a JSON-conforming file, or\r
270 <a href="http://cr.i3wm.org/">submit a patch</a> to make <tt>i3-save-tree(1)</tt> optionally\r
271 output standard-conforming JSON.</p></div>\r
272 </div>\r
273 </div>\r
274 </div>\r
275 </div>\r
276 <div id="footnotes"><hr /></div>\r
277 <div id="footer" lang="de">\r
278 © 2009-2011 Michael Stapelberg, <a href="/impress.html">Impressum</a>\r
279 </div>\r
280 </body>\r
281 </html>\r