--- /dev/null
+
+all: hacking-howto.html debugging.html userguide.html ipc.html multi-monitor.html wsbar.html tree-migrating.html
+
+hacking-howto.html: hacking-howto
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+debugging.html: debugging
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -n $<
+
+userguide.html: userguide
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+tree-migrating.html: tree-migrating
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+ipc.html: ipc
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+multi-monitor.html: multi-monitor
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+wsbar.html: wsbar
+ asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $<
+
+clean:
+ rm -f */*.{aux,log,toc,bm,pdf,dvi}
+ rm -f *.log *.html
--- /dev/null
+#\r
+# xhtml11.conf\r
+#\r
+# Asciidoc configuration file.\r
+# xhtml11 backend, generates XHTML 1.1 conformant markup.\r
+#\r
+\r
+[miscellaneous]\r
+outfilesuffix=.html\r
+\r
+[attributes]\r
+basebackend=html\r
+basebackend-html=\r
+basebackend-xhtml11=\r
+\r
+[replacements2]\r
+# Line break.\r
+(?m)^(.*)\s\+$=\1<br />\r
+\r
+[replacements]\r
+ifdef::asciidoc7compatible[]\r
+# Superscripts.\r
+\^(.+?)\^=<sup>\1</sup>\r
+# Subscripts.\r
+~(.+?)~=<sub>\1</sub>\r
+endif::asciidoc7compatible[]\r
+\r
+[ruler-blockmacro]\r
+<hr />\r
+\r
+[pagebreak-blockmacro]\r
+<div style="page-break-after:always"></div>\r
+\r
+[blockdef-pass]\r
+asciimath-style=template="asciimathblock",subs=[]\r
+latexmath-style=template="latexmathblock",subs=[]\r
+\r
+[macros]\r
+# math macros.\r
+# Special characters are escaped in HTML math markup.\r
+(?su)[\\]?(?P<name>asciimath|latexmath):(?P<subslist>\S*?)\[(?P<passtext>.*?)(?<!\\)\]=[specialcharacters]\r
+(?u)^(?P<name>asciimath|latexmath)::(?P<subslist>\S*?)(\[(?P<passtext>.*?)\])$=#[specialcharacters]\r
+\r
+[asciimath-inlinemacro]\r
+`{passtext}`\r
+\r
+[asciimath-blockmacro]\r
+<div class="mathblock{role? {role}}"{id? id="{id}"}>\r
+<div class="content">\r
+<div class="title">{title}</div>\r
+`{passtext}`\r
+</div></div>\r
+\r
+[asciimathblock]\r
+<div class="mathblock{role? {role}}"{id? id="{id}"}>\r
+<div class="content">\r
+<div class="title">{title}</div>\r
+`|`\r
+</div></div>\r
+\r
+[latexmath-inlinemacro]\r
+{passtext}\r
+\r
+[latexmath-blockmacro]\r
+<div class="mathblock{role? {role}}"{id? id="{id}"}>\r
+<div class="content">\r
+<div class="title">{title}</div>\r
+{passtext}\r
+</div></div>\r
+\r
+[latexmathblock]\r
+<div class="mathblock{role? {role}}"{id? id="{id}"}>\r
+<div class="content">\r
+<div class="title">{title}</div>\r
+|\r
+</div></div>\r
+\r
+[image-inlinemacro]\r
+<span class="image{role? {role}}">\r
+<a class="image" href="{link}">\r
+{data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} />\r
+{data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} src="data:image/{eval:os.path.splitext('{target}')[1][1:]};base64,\r
+{data-uri#}{sys3:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join("{indir={outdir}}","{imagesdir=}","{target}")}"}" />\r
+{link#}</a>\r
+</span>\r
+\r
+[image-blockmacro]\r
+<div class="imageblock{style? {style}}{role? {role}}"{id? id="{id}"}{align? style="text-align:{align};"}{float? style="float:{float};"}>\r
+<div class="content">\r
+<a class="image" href="{link}">\r
+{data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} />\r
+{data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} src="data:image/{eval:os.path.splitext('{target}')[1][1:]};base64,\r
+{data-uri#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join("{indir={outdir}}","{imagesdir=}","{target}")}"}" />\r
+{link#}</a>\r
+</div>\r
+<div class="title">{caption={figure-caption} {counter:figure-number}. }{title}</div>\r
+</div>\r
+\r
+[unfloat-blockmacro]\r
+<div style="clear:both;"></div>\r
+\r
+[indexterm-inlinemacro]\r
+# Index term.\r
+{empty}\r
+\r
+[indexterm2-inlinemacro]\r
+# Index term.\r
+# Single entry index term that is visible in the primary text flow.\r
+{1}\r
+\r
+[footnote-inlinemacro]\r
+# footnote:[<text>].\r
+<span class="footnote"><br />[{0}]<br /></span>\r
+\r
+[footnoteref-inlinemacro]\r
+# footnoteref:[<id>], create reference to footnote.\r
+{2%}<span class="footnoteref"><br /><a href="#_footnote_{1}">[{1}]</a><br /></span>\r
+# footnoteref:[<id>,<text>], create footnote with ID.\r
+{2#}<span class="footnote" id="_footnote_{1}"><br />[{2}]<br /></span>\r
+\r
+[callout-inlinemacro]\r
+ifndef::icons[]\r
+<b><{index}></b>\r
+endif::icons[]\r
+ifdef::icons[]\r
+ifndef::data-uri[]\r
+<img src="{icon={iconsdir}/callouts/{index}.png}" alt="{index}" />\r
+endif::data-uri[]\r
+ifdef::data-uri[]\r
+<img alt="{index}" src="data:image/png;base64,\r
+{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join("{indir={outdir}}","{icon={iconsdir}/callouts/{index}.png}")}"}" />\r
+endif::data-uri[]\r
+endif::icons[]\r
+\r
+# Comment line macros.\r
+[comment-inlinemacro]\r
+{showcomments#}<br /><span class="comment">{passtext}</span><br />\r
+\r
+[comment-blockmacro]\r
+{showcomments#}<p><span class="comment">{passtext}</span></p>\r
+\r
+[literal-inlinemacro]\r
+# Inline literal.\r
+<tt>{passtext}</tt>\r
+\r
+# List tags.\r
+[listtags-bulleted]\r
+list=<div class="ulist{style? {style}}{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ul>|</ul></div>\r
+item=<li>|</li>\r
+text=<p>|</p>\r
+\r
+[listtags-numbered]\r
+# The start attribute is not valid XHTML 1.1 but all browsers support it.\r
+list=<div class="olist{style? {style}}{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol class="{style}"{start? start="{start}"}>|</ol></div>\r
+item=<li>|</li>\r
+text=<p>|</p>\r
+\r
+[listtags-labeled]\r
+list=<div class="dlist{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<dl>|</dl></div>\r
+entry=\r
+label=\r
+term=<dt class="hdlist1{strong-option? strong}">|</dt>\r
+item=<dd>|</dd>\r
+text=<p>|</p>\r
+\r
+[listtags-horizontal]\r
+list=<div class="hdlist{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<table>{labelwidth?<col width="{labelwidth}%" />}{itemwidth?<col width="{itemwidth}%" />}|</table></div>\r
+label=<td class="hdlist1{strong-option? strong}">|</td>\r
+term=|<br />\r
+entry=<tr>|</tr>\r
+item=<td class="hdlist2">|</td>\r
+text=<p style="margin-top: 0;">|</p>\r
+\r
+[listtags-qanda]\r
+list=<div class="qlist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol>|</ol></div>\r
+entry=<li>|</li>\r
+label=\r
+term=<p><em>|</em></p>\r
+item=\r
+text=<p>|</p>\r
+\r
+[listtags-callout]\r
+ifndef::icons[]\r
+list=<div class="colist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol>|</ol></div>\r
+item=<li>|</li>\r
+text=<p>|</p>\r
+endif::icons[]\r
+ifdef::icons[]\r
+list=<div class="colist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<table>|</table></div>\r
+ifndef::data-uri[]\r
+item=<tr><td><img src="{iconsdir}/callouts/{listindex}.png" alt="{listindex}" /></td><td>|</td></tr>\r
+endif::data-uri[]\r
+ifdef::data-uri[]\r
+item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join("{indir={outdir}}","{icon={iconsdir}/callouts/{listindex}.png}")}"}" /></td><td>|</td></tr>\r
+endif::data-uri[]\r
+text=|\r
+endif::icons[]\r
+\r
+[listtags-glossary]\r
+list=<div class="dlist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<dl>|</dl></div>\r
+label=\r
+entry=\r
+term=<dt>|</dt>\r
+item=<dd>|</dd>\r
+text=<p>|</p>\r
+\r
+[listtags-bibliography]\r
+list=<div class="ulist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ul>|</ul></div>\r
+item=<li>|</li>\r
+text=<p>|</p>\r
+\r
+[tags]\r
+# Quoted text.\r
+emphasis=<em>{1?<span class="{1}">}|{1?</span>}</em>\r
+strong=<strong>{1?<span class="{1}">}|{1?</span>}</strong>\r
+monospaced=<tt>{1?<span class="{1}">}|{1?</span>}</tt>\r
+singlequoted={lsquo}{1?<span class="{1}">}|{1?</span>}{rsquo}\r
+doublequoted={ldquo}{1?<span class="{1}">}|{1?</span>}{rdquo}\r
+unquoted={1?<span class="{1}">}|{1?</span>}\r
+superscript=<sup>{1?<span class="{1}">}|{1?</span>}</sup>\r
+subscript=<sub>{1?<span class="{1}">}|{1?</span>}</sub>\r
+\r
+ifdef::deprecated-quotes[]\r
+# Override with deprecated quote attributes.\r
+emphasis={role?<span class="{role}">}<em{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</em>{role?</span>}\r
+strong={role?<span class="{role}">}<strong{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</strong>{role?</span>}\r
+monospaced={role?<span class="{role}">}<tt{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</tt>{role?</span>}\r
+singlequoted={role?<span class="{role}">}{1,2,3?<span style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?">}{amp}#8216;|{amp}#8217;{1,2,3?</span>}{role?</span>}\r
+doublequoted={role?<span class="{role}">}{1,2,3?<span style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?">}{amp}#8220;|{amp}#8221;{1,2,3?</span>}{role?</span>}\r
+unquoted={role?<span class="{role}">}{1,2,3?<span style="{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}">}|{1,2,3?</span>}{role?</span>}\r
+superscript={role?<span class="{role}">}<sup{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</sup>{role?</span>}\r
+subscript={role?<span class="{role}">}<sub{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</sub>{role?</span>}\r
+endif::deprecated-quotes[]\r
+\r
+# Inline macros\r
+[http-inlinemacro]\r
+<a href="{name}:{target}">{0={name}:{target}}</a>\r
+[https-inlinemacro]\r
+<a href="{name}:{target}">{0={name}:{target}}</a>\r
+[ftp-inlinemacro]\r
+<a href="{name}:{target}">{0={name}:{target}}</a>\r
+[file-inlinemacro]\r
+<a href="{name}:{target}">{0={name}:{target}}</a>\r
+[irc-inlinemacro]\r
+<a href="{name}:{target}">{0={name}:{target}}</a>\r
+[mailto-inlinemacro]\r
+<a href="mailto:{target}">{0={target}}</a>\r
+[link-inlinemacro]\r
+<a href="{target}">{0={target}}</a>\r
+[callto-inlinemacro]\r
+<a href="{name}:{target}">{0={target}}</a>\r
+# anchor:id[text]\r
+[anchor-inlinemacro]\r
+<a id="{target}"></a>\r
+# [[id,text]]\r
+[anchor2-inlinemacro]\r
+<a id="{1}"></a>\r
+# [[[id]]]\r
+[anchor3-inlinemacro]\r
+<a id="{1}"></a>[{1}]\r
+# xref:id[text]\r
+[xref-inlinemacro]\r
+<a href="#{target}">{0=[{target}]}</a>\r
+# <<id,text>>\r
+[xref2-inlinemacro]\r
+<a href="#{1}">{2=[{1}]}</a>\r
+\r
+# Special word substitution.\r
+[emphasizedwords]\r
+<em>{words}</em>\r
+[monospacedwords]\r
+<tt>{words}</tt>\r
+[strongwords]\r
+<strong>{words}</strong>\r
+\r
+# Paragraph substitution.\r
+[paragraph]\r
+<div class="paragraph{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<p>\r
+|\r
+</p></div>\r
+\r
+[admonitionparagraph]\r
+template::[admonitionblock]\r
+\r
+# Delimited blocks.\r
+[listingblock]\r
+<div class="listingblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{caption=}{title}</div>\r
+<div class="content">\r
+<pre><tt>\r
+|\r
+</tt></pre>\r
+</div></div>\r
+\r
+[literalblock]\r
+<div class="literalblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{title}</div>\r
+<div class="content">\r
+<pre><tt>\r
+|\r
+</tt></pre>\r
+</div></div>\r
+\r
+[sidebarblock]\r
+<div class="sidebarblock{role? {role}}"{id? id="{id}"}>\r
+<div class="content">\r
+<div class="title">{title}</div>\r
+|\r
+</div></div>\r
+\r
+[openblock]\r
+<div class="openblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{title}</div>\r
+<div class="content">\r
+|\r
+</div></div>\r
+\r
+[partintroblock]\r
+template::[openblock]\r
+\r
+[abstractblock]\r
+template::[quoteblock]\r
+\r
+[quoteblock]\r
+<div class="quoteblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{title}</div>\r
+<div class="content">\r
+|\r
+</div>\r
+<div class="attribution">\r
+<em>{citetitle}</em>{attribution?<br />}\r
+— {attribution}\r
+</div></div>\r
+\r
+[verseblock]\r
+<div class="verseblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{title}</div>\r
+<pre class="content">\r
+|\r
+</pre>\r
+<div class="attribution">\r
+<em>{citetitle}</em>{attribution?<br />}\r
+— {attribution}\r
+</div></div>\r
+\r
+[exampleblock]\r
+<div class="exampleblock{role? {role}}"{id? id="{id}"}>\r
+<div class="title">{caption={example-caption} {counter:example-number}. }{title}</div>\r
+<div class="content">\r
+|\r
+</div></div>\r
+\r
+[admonitionblock]\r
+<div class="admonitionblock{role? {role}}"{id? id="{id}"}>\r
+<table><tr>\r
+<td class="icon">\r
+{data-uri%}{icons#}<img src="{icon={iconsdir}/{name}.png}" alt="{caption}" />\r
+{data-uri#}{icons#}<img alt="{caption}" src="data:image/png;base64,\r
+{data-uri#}{icons#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join("{indir={outdir}}","{icon={iconsdir}/{name}.png}")}"}" />\r
+{icons%}<div class="title">{caption}</div>\r
+</td>\r
+<td class="content">\r
+<div class="title">{title}</div>\r
+|\r
+</td>\r
+</tr></table>\r
+</div>\r
+\r
+# Tables.\r
+[tabletags-default]\r
+colspec=<col{autowidth-option! width="{colpcwidth}%"} />\r
+bodyrow=<tr>|</tr>\r
+headdata=<th {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }align="{halign}" valign="{valign}">|</th>\r
+bodydata=<td {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }align="{halign}" valign="{valign}">|</td>\r
+paragraph=<p class="table">|</p>\r
+\r
+[tabletags-header]\r
+paragraph=<p class="table header">|</p>\r
+\r
+[tabletags-emphasis]\r
+paragraph=<p class="table"><em>|</em></p>\r
+\r
+[tabletags-strong]\r
+paragraph=<p class="table"><strong>|</strong></p>\r
+\r
+[tabletags-monospaced]\r
+paragraph=<p class="table"><tt>|</tt></p>\r
+\r
+[tabletags-verse]\r
+bodydata=<td {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }align="{halign}" valign="{valign}"><div class="verse">|</div></td>\r
+paragraph=\r
+\r
+[tabletags-literal]\r
+bodydata=<td {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }align="{halign}" valign="{valign}"><div class="literal"><pre><tt>|</tt></pre></div></td>\r
+paragraph=\r
+\r
+[tabletags-asciidoc]\r
+bodydata=<td {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }align="{halign}" valign="{valign}"><div>|</div></td>\r
+paragraph=\r
+\r
+[table]\r
+<div class="tableblock{role? {role}}"{id? id="{id}"}>\r
+<table rules="{grid=all}"\r
+style="margin-left:{align@left:0}{align@center|right:auto}; margin-right:{align@left|center:auto}{align@right:0};"\r
+style="float:{float};"\r
+{autowidth-option%}width="{tablepcwidth}%"\r
+{autowidth-option#}{width#width="{tablepcwidth}%"}\r
+frame="{frame%border}"\r
+frame="{frame@topbot:hsides}{frame@all:border}{frame@none:void}{frame@sides:vsides}"\r
+cellspacing="0" cellpadding="4">\r
+<caption class="title">{caption={table-caption} {counter:table-number}. }{title}</caption>\r
+{colspecs}\r
+{headrows#}<thead>\r
+{headrows}\r
+{headrows#}</thead>\r
+{footrows#}<tfoot>\r
+{footrows}\r
+{footrows#}</tfoot>\r
+<tbody>\r
+{bodyrows}\r
+</tbody>\r
+</table>\r
+</div>\r
+\r
+#--------------------------------------------------------------------\r
+# Deprecated old table definitions.\r
+#\r
+\r
+[miscellaneous]\r
+# Screen width in pixels.\r
+pagewidth=800\r
+pageunits=\r
+\r
+[old_tabledef-default]\r
+template=old_table\r
+colspec=<col width="{colwidth}{pageunits}" />\r
+bodyrow=<tr>|</tr>\r
+headdata=<th align="{colalign}">|</th>\r
+footdata=<td align="{colalign}">|</td>\r
+bodydata=<td align="{colalign}">|</td>\r
+\r
+[old_table]\r
+<div class="tableblock"{id? id="{id}"}>\r
+<table rules="{grid=none}"\r
+frame="{frame%hsides}"\r
+frame="{frame@topbot:hsides}{frame@all:border}{frame@none:void}{frame@sides:vsides}"\r
+cellspacing="0" cellpadding="4">\r
+<caption class="title">{caption={table-caption}}{title}</caption>\r
+{colspecs}\r
+{headrows#}<thead>\r
+{headrows}\r
+{headrows#}</thead>\r
+{footrows#}<tfoot>\r
+{footrows}\r
+{footrows#}</tfoot>\r
+<tbody valign="top">\r
+{bodyrows}\r
+</tbody>\r
+</table>\r
+</div>\r
+\r
+# End of deprecated old table definitions.\r
+#--------------------------------------------------------------------\r
+\r
+[floatingtitle]\r
+<h{level@0:1}{level@1:2}{level@2:3}{level@3:4}{level@4:5}{id? id="{id}"} class="float">{title}</h{level@0:1}{level@1:2}{level@2:3}{level@3:4}{level@4:5}>\r
+\r
+[preamble]\r
+# Untitled elements between header and first section title.\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+|\r
+</div>\r
+</div>\r
+\r
+# Document sections.\r
+[sect0]\r
+<h1{id? id="{id}"}>{title}</h1>\r
+|\r
+\r
+[sect1]\r
+<div class="sect1{style? {style}}{role? {role}}">\r
+<h2{id? id="{id}"}>{numbered?{sectnum} }{title}</h2>\r
+<div class="sectionbody">\r
+|\r
+</div>\r
+</div>\r
+\r
+[sect2]\r
+<div class="sect2{style? {style}}{role? {role}}">\r
+<h3{id? id="{id}"}>{numbered?{sectnum} }{title}</h3>\r
+|\r
+</div>\r
+\r
+[sect3]\r
+<div class="sect3{style? {style}}{role? {role}}">\r
+<h4{id? id="{id}"}>{numbered?{sectnum} }{title}</h4>\r
+|\r
+</div>\r
+\r
+[sect4]\r
+<div class="sect4{style? {style}}{role? {role}}">\r
+<h5{id? id="{id}"}>{title}</h5>\r
+|\r
+</div>\r
+\r
+[appendix]\r
+<div class="sect1{style? {style}}{role? {role}}">\r
+<h2{id? id="{id}"}>{numbered?{sectnum} }{appendix-caption} {counter:appendix-number:A}: {title}</h2>\r
+<div class="sectionbody">\r
+|\r
+</div>\r
+</div>\r
+\r
+[toc]\r
+<div id="toc">\r
+ <div id="toctitle">{toc-title}</div>\r
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>\r
+</div>\r
+\r
+[header]\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{lang=en}">\r
+<head>\r
+<meta http-equiv="Content-Type" content="{quirks=application/xhtml+xml}{quirks?text/html}; charset={encoding}" />\r
+<meta name="generator" content="AsciiDoc {asciidoc-version}" />\r
+<meta name="description" content="{description}" />\r
+<meta name="keywords" content="{keywords}" />\r
+<title>i3: {title}</title>\r
+{title%}<title>i3: {doctitle=}</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+ifdef::linkcss[]\r
+<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}.css" type="text/css" />\r
+{doctype-manpage}<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}-manpage.css" type="text/css" />\r
+ifdef::quirks[]\r
+<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}-quirks.css" type="text/css" />\r
+endif::quirks[]\r
+<link rel="stylesheet" href="{stylesdir=.}/{stylesheet}" type="text/css" />\r
+ifdef::pygments[<link rel="stylesheet" href="{stylesdir=.}/pygments.css" type="text/css" />]\r
+endif::linkcss[]\r
+ifndef::linkcss[]\r
+<style type="text/css">\r
+include1::{stylesdir=./stylesheets}/{theme={backend}}.css[]\r
+ifdef::doctype-manpage[]\r
+include1::{stylesdir=./stylesheets}/{theme={backend}}-manpage.css[]\r
+endif::doctype-manpage[]\r
+ifdef::quirks[]\r
+include1::{stylesdir=./stylesheets}/{theme={backend}}-quirks.css[]\r
+endif::quirks[]\r
+include1::{stylesheet}[]\r
+ifdef::pygments[]\r
+include1::{stylesdir=./stylesheets}/pygments.css[]\r
+endif::pygments[]\r
+</style>\r
+endif::linkcss[]\r
+ifndef::disable-javascript[]\r
+ifdef::linkcss[]\r
+<script type="text/javascript">\r
+# Escape as CDATA to pass validators.\r
+/*<![CDATA[*/\r
+window.onload = function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="{scriptsdir=.}/asciidoc-xhtml11.js"></script>\r
+endif::linkcss[]\r
+ifndef::linkcss[]\r
+<script type="text/javascript">\r
+# Escape as CDATA to pass validators.\r
+/*<![CDATA[*/\r
+window.onload = function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}\r
+include1::{scriptsdir=./javascripts}/asciidoc-xhtml11.js[]\r
+/*]]>*/\r
+</script>\r
+endif::linkcss[]\r
+endif::disable-javascript[]\r
+ifdef::asciimath[]\r
+ifdef::linkcss[]\r
+<script type="text/javascript" src="{scriptsdir=.}/ASCIIMathML.js"></script>\r
+endif::linkcss[]\r
+ifndef::linkcss[]\r
+<script type="text/javascript">\r
+# Escape as CDATA to pass validators.\r
+/*<![CDATA[*/\r
+include1::{scriptsdir=./javascripts}/ASCIIMathML.js[]\r
+/*]]>*/\r
+</script>\r
+endif::linkcss[]\r
+endif::asciimath[]\r
+ifdef::latexmath[]\r
+ifdef::linkcss[]\r
+<script type="text/javascript" src="{scriptsdir=.}/LaTeXMathML.js"></script>\r
+endif::linkcss[]\r
+ifndef::linkcss[]\r
+<script type="text/javascript">\r
+# Escape as CDATA to pass validators.\r
+/*<![CDATA[*/\r
+include1::{scriptsdir=./javascripts}/LaTeXMathML.js[]\r
+/*]]>*/\r
+</script>\r
+endif::linkcss[]\r
+endif::latexmath[]\r
+{docinfo1,docinfo2#}{include:{docdir}/docinfo.html}\r
+{docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.html}\r
+</head>\r
+<body class="{doctype}"{max-width? style="max-width:{max-width}"}>\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+# Article, book header.\r
+ifndef::doctype-manpage[]\r
+<div id="header">\r
+ifndef::notitle[<h1>{doctitle}</h1>]\r
+ifdef::doctitle[]\r
+<span id="author">{author}</span><br />\r
+<span id="email"><tt><<a href="mailto:{email}">{email}</a>></tt></span><br />\r
+<span id="revnumber">version {revnumber}{revdate?,}</span>\r
+<span id="revdate">{revdate}</span>\r
+<br /><span id="revremark">{revremark}</span>\r
+endif::doctitle[]\r
+ifdef::toc[{template:toc}]\r
+</div>\r
+endif::doctype-manpage[]\r
+# Man page header.\r
+ifdef::doctype-manpage[]\r
+<div id="header">\r
+<h1>\r
+{doctitle} Manual Page\r
+</h1>\r
+ifdef::toc[{template:toc}]\r
+<h2>{manname-title}</h2>\r
+<div class="sectionbody">\r
+<p>{manname} -\r
+ {manpurpose}\r
+</p>\r
+</div>\r
+</div>\r
+endif::doctype-manpage[]\r
+\r
+[footer]\r
+</div>\r
+{disable-javascript%<div id="footnotes"><hr /></div>}\r
+<div id="footer">\r
+<div id="footer-text">\r
+template::[footer-text]\r
+</div>\r
+ifdef::badges[]\r
+<div id="footer-badges">\r
+ifndef::icons[]\r
+Valid <a href="http://validator.w3.org/check?uri=referer">XHTML</a>\r
+and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>.\r
+endif::icons[]\r
+ifdef::icons[]\r
+<a href="http://validator.w3.org/check?uri=referer">\r
+ <img style="border:0;width:88px;height:31px"\r
+ src="http://www.w3.org/Icons/valid-xhtml11-blue"\r
+ alt="Valid XHTML 1.1" height="31" width="88" />\r
+</a>\r
+<a href="http://jigsaw.w3.org/css-validator/">\r
+ <img style="border:0;width:88px;height:31px"\r
+ src="http://jigsaw.w3.org/css-validator/images/vcss-blue"\r
+ alt="Valid CSS!" />\r
+</a>\r
+<a href="http://www.mozilla.org/products/firefox/">\r
+ <img style="border:none; width:110px; height:32px;"\r
+ src="http://www.spreadfirefox.com/community/images/affiliates/Buttons/110x32/safer.gif"\r
+ alt="Get Firefox!" />\r
+</a>\r
+endif::icons[]\r
+</div>\r
+endif::badges[]\r
+</div>\r
+</body>\r
+</html>\r
+\r
+ifdef::doctype-manpage[]\r
+[synopsis]\r
+template::[sect1]\r
+endif::doctype-manpage[]\r
+\r
+ifdef::quirks[]\r
+include::{backend}-quirks.conf[]\r
+endif::quirks[]\r
--- /dev/null
+Debugging i3: How To
+====================
+Michael Stapelberg <michael+i3@stapelberg.de>
+March 2010
+
+This document describes how to debug i3 suitably for sending us useful bug
+reports, even if you have no clue of C programming.
+
+First of all: Thank you for being interested in debugging i3. It really means
+something to us to get your bug fixed. If you have any questions about the
+debugging and/or need further help, do not hesitate to contact us!
+
+== Enabling logging
+
+i3 spits out much information onto stdout, if told so. To have a clearly
+defined place where log files will be saved, you should redirect stdout and
+stderr in xsession. While you’re at it, putting each run of i3 in a separate
+log file with date/time in it is a good idea to not get confused about the
+different log files later on.
+
+--------------------------------------------------------------------
+exec /usr/bin/i3 -V -d all >/home/michael/i3/i3log-$(date +'%F-%k-%M-%S') 2>&1
+--------------------------------------------------------------------
+
+== Enabling core dumps
+
+When i3 crashes, often you have the chance of getting a 'core dump' (an image
+of the memory of the i3 process which can be loaded into a debugger). To get a
+core dump, you have to make sure that the user limit for core dump files is set
+high enough. Many systems ship with a default value which even forbids core
+dumps completely. To disable the limit completely and thus enable core dumps,
+use the following command (in your .xsession, before starting i3):
+
+-------------------
+ulimit -c unlimited
+-------------------
+
+Furthermore, to easily recognize core dumps and allow multiple of them, you
+should set a custom core dump filename pattern, using a command like the
+following:
+
+---------------------------------------------
+sudo sysctl -w kernel.core_pattern=core.%e.%p
+---------------------------------------------
+
+This will generate files which have the executable’s file name (%e) and the
+process id (%p) in it. You can save this setting across reboots using
++/etc/sysctl.conf+.
+
+== Compiling with debug symbols
+
+To actually get useful core dumps, you should make sure that your version of i3
+is compiled with debug symbols, that is, that they are not stripped during the
+build process. You can check whether your executable contains symbols by
+issuing the following command:
+
+----------------
+file $(which i3)
+----------------
+
+You should get an output like this:
+------------------------------------------------------------------------------
+/usr/bin/i3: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
+linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
+------------------------------------------------------------------------------
+
+Notice the +not stripped+, which is the important part. If you have a version
+which is stripped, please have a look if your distribution provides debug
+symbols (package +i3-wm-dbg+ on Debian for example) or if you can turn off
+stripping. If nothing helps, please build i3 from source.
+
+== Generating a backtrace
+
+Once you have made sure that your i3 is compiled with debug symbols and that
+core dumps are enabled, you can start making sense out of the core dumps.
+
+Because the core dump depends on the original executable (and its debug
+symbols), please do this as soon as you encounter the problem. If you
+re-compile i3, your core dump might be useless afterwards.
+
+Please install +gdb+, a debugger for C. No worries, you don’t need to learn it
+now. Start gdb using the following command (replacing the actual name of the
+core dump of course):
+
+----------------------------
+gdb $(which i3) core.i3.3849
+----------------------------
+
+Then, generate a backtrace using:
+
+--------------
+backtrace full
+--------------
+
+== Sending bug reports/debugging on IRC
+
+When sending bug reports, please paste the relevant part of the log (if in
+doubt, please send us rather too much information than too less) and the whole
+backtrace (if there was a core dump).
+
+When debugging with us in IRC, be prepared to use a so called nopaste service
+such as http://nopaste.info or http://pastebin.com because pasting large
+amounts of text in IRC sometimes leads to incomplete lines (servers have line
+length limitations) or flood kicks.
--- /dev/null
+Hacking i3: How To
+==================
+Michael Stapelberg <michael+i3@stapelberg.de>
+December 2009
+
+This document is intended to be the first thing you read before looking and/or
+touching i3’s source code. It should contain all important information to help
+you understand why things are like they are. If it does not mention something
+you find necessary, please do not hesitate to contact me.
+
+== Window Managers
+
+A window manager is not necessarily needed to run X, but it is usually used in
+combination with X to facilitate some things. The window manager's job is to
+take care of the placement of windows, to provide the user with some mechanisms
+to change the position/size of windows and to communicate with clients to a
+certain extent (for example handle fullscreen requests of clients such as
+MPlayer).
+
+There are no different contexts in which X11 clients run, so a window manager
+is just another client, like all other X11 applications. However, it handles
+some events which normal clients usually don’t handle.
+
+In the case of i3, the tasks (and order of them) are the following:
+
+. Grab the key bindings (events will be sent upon keypress/keyrelease)
+. Iterate through all existing windows (if the window manager is not started as
+ the first client of X) and manage them (reparent them, create window
+ decorations, etc.)
+. When new windows are created, manage them
+. Handle the client’s `_WM_STATE` property, but only the `_WM_STATE_FULLSCREEN`
+. Handle the client’s `WM_NAME` property
+. Handle the client’s size hints to display them proportionally
+. Handle the client’s urgency hint
+. Handle enter notifications (focus follows mouse)
+. Handle button (as in mouse buttons) presses for focus/raise on click
+. Handle expose events to re-draw own windows such as decorations
+. React to the user’s commands: Change focus, Move windows, Switch workspaces,
+ Change the layout mode of a container (default/stacking/tabbed), start a new
+ application, restart the window manager
+
+In the following chapters, each of these tasks and their implementation details
+will be discussed.
+
+=== Tiling window managers
+
+Traditionally, there are two approaches to managing windows: The most common
+one nowadays is floating, which means the user can freely move/resize the
+windows. The other approach is called tiling, which means that your window
+manager distributes windows to use as much space as possible while not
+overlapping each other.
+
+The idea behind tiling is that you should not need to waste your time
+moving/resizing windows while you usually want to get some work done. After
+all, most users sooner or later tend to lay out their windows in a way which
+corresponds to tiling or stacking mode in i3. Therefore, why not let i3 do this
+for you? Certainly, it’s faster than you could ever do it.
+
+The problem with most tiling window managers is that they are too unflexible.
+In my opinion, a window manager is just another tool, and similar to vim which
+can edit all kinds of text files (like source code, HTML, …) and is not limited
+to a specific file type, a window manager should not limit itself to a certain
+layout (like dwm, awesome, …) but provide mechanisms for you to easily create
+the layout you need at the moment.
+
+=== The layout table
+
+To accomplish flexible layouts, we decided to simply use a table. The table
+grows and shrinks as you need it. Each cell holds a container which then holds
+windows (see picture below). You can use different layouts for each container
+(default layout and stacking layout).
+
+So, when you open a terminal and immediately open another one, they reside in
+the same container, in default layout. The layout table has exactly one column,
+one row and therefore one cell. When you move one of the terminals to the
+right, the table needs to grow. It will be expanded to two columns and one row.
+This enables you to have different layouts for each container. The table then
+looks like this:
+
+[width="15%",cols="^,^"]
+|========
+| T1 | T2
+|========
+
+When moving terminal 2 to the bottom, the table will be expanded again.
+
+[width="15%",cols="^,^"]
+|========
+| T1 |
+| | T2
+|========
+
+You can really think of the layout table like a traditional HTML table, if
+you’ve ever designed one. Especially col- and rowspan work similarly. Below,
+you see an example of colspan=2 for the first container (which has T1 as
+window).
+
+[width="15%",cols="^asciidoc"]
+|========
+| T1
+|
+[cols="^,^",frame="none"]
+!========
+! T2 ! T3
+!========
+|========
+
+Furthermore, you can freely resize table cells.
+
+== Files
+
+include/data.h::
+Contains data definitions used by nearly all files. You really need to read
+this first.
+
+include/*.h::
+Contains forward definitions for all public functions, as well as
+doxygen-compatible comments (so if you want to get a bit more of the big
+picture, either browse all header files or use doxygen if you prefer that).
+
+src/cfgparse.l::
+Contains the lexer for i3’s configuration file, written for +flex(1)+.
+
+src/cfgparse.y::
+Contains the parser for i3’s configuration file, written for +bison(1)+.
+
+src/click.c::
+Contains all functions which handle mouse button clicks (right mouse button
+clicks initiate resizing and thus are relatively complex).
+
+src/client.c::
+Contains all functions which are specific to a certain client (make it
+fullscreen, see if its class/name matches a pattern, kill it, …).
+
+src/commands.c::
+Parsing commands and actually executing them (focusing, moving, …).
+
+src/config.c::
+Parses the configuration file.
+
+src/debug.c::
+Contains debugging functions to print unhandled X events.
+
+src/floating.c::
+Contains functions for floating mode (mostly resizing/dragging).
+
+src/handlers.c::
+Contains all handlers for all kinds of X events (new window title, new hints,
+unmapping, key presses, button presses, …).
+
+src/ipc.c::
+Contains code for the IPC interface.
+
+src/layout.c::
+Renders your layout (screens, workspaces, containers).
+
+src/mainx.c::
+Initializes the window manager.
+
+src/manage.c::
+Looks at existing or new windows and decides whether to manage them. If so, it
+reparents the window and inserts it into our data structures.
+
+src/resize.c::
+Contains the functions to resize columns/rows in the table.
+
+src/table.c::
+Manages the most important internal data structure, the design table.
+
+src/util.c::
+Contains useful functions which are not really dependant on anything.
+
+src/workspace.c::
+Contains all functions related to workspaces (displaying, hiding, renaming…)
+
+src/xcb.c::
+Contains wrappers to use xcb more easily.
+
+src/xinerama.c::
+(Re-)initializes the available screens and converts them to virtual screens
+(see below).
+
+== Data structures
+
+See include/data.h for documented data structures. The most important ones are
+explained right here.
+
+image:bigpicture.png[The Big Picture]
+
+So, the hierarchy is:
+
+. *Virtual screens* (Screen 0 in this example)
+. *Workspaces* (Workspace 1 in this example)
+. *Table* (There can only be one table per Workspace)
+. *Container* (left and right in this example)
+. *Client* (The two clients in the left container)
+
+=== Virtual screens
+
+A virtual screen (type `i3Screen`) is generated from the connected screens
+obtained through Xinerama. The difference to the raw Xinerama monitors as seen
+when using +xrandr(1)+ is that it falls back to the lowest common resolution of
+the logical screens.
+
+For example, if your notebook has 1280x800 and you connect a video projector
+with 1024x768, set up in clone mode (+xrandr \--output VGA \--mode 1024x768
+\--same-as LVDS+), i3 will have one virtual screen.
+
+However, if you configure it using +xrandr \--output VGA \--mode 1024x768
+\--right-of LVDS+, i3 will generate two virtual screens. For each virtual
+screen, a new workspace will be assigned. New workspaces are created on the
+screen you are currently on.
+
+=== Workspace
+
+A workspace is identified by its number. Basically, you could think of
+workspaces as different desks in your office, if you like the desktop
+methaphor. They just contain different sets of windows and are completely
+separate of each other. Other window managers also call this ``Virtual
+desktops''.
+
+=== The layout table
+
+Each workspace has a table, which is just a two-dimensional dynamic array
+containing Containers (see below). This table grows and shrinks as you need it
+(by moving windows to the right you can create a new column in the table, by
+moving them to the bottom you create a new row).
+
+=== Container
+
+A container is the content of a table’s cell. It holds an arbitrary amount of
+windows and has a specific layout (default layout, stack layout or tabbed
+layout). Containers can consume multiple table cells by modifying their
+colspan/rowspan attribute.
+
+=== Client
+
+A client is x11-speak for a window.
+
+== List/queue macros
+
+i3 makes heavy use of the list macros defined in BSD operating systems. To
+ensure that the operating system on which i3 is compiled has all the expected
+features, i3 comes with `include/queue.h`. On BSD systems, you can use man
+`queue(3)`. On Linux, you have to use google (or read the source).
+
+The lists used are `SLIST` (single linked lists), `CIRCLEQ` (circular
+queues) and TAILQ (tail queues). Usually, only forward traversal is necessary,
+so an `SLIST` works fine. If inserting elements at arbitrary positions or at
+the end of a list is necessary, a `TAILQ` is used instead. However, for the
+windows inside a container, a `CIRCLEQ` is necessary to go from the currently
+selected window to the window above/below.
+
+== Naming conventions
+
+There is a row of standard variables used in many events. The following names
+should be chosen for those:
+
+ * ``conn'' is the xcb_connection_t
+ * ``event'' is the event of the particular type
+ * ``container'' names a container
+ * ``client'' names a client, for example when using a +CIRCLEQ_FOREACH+
+
+== Startup (src/mainx.c, main())
+
+ * Establish the xcb connection
+ * Check for XKB extension on the separate X connection
+ * Check for Xinerama screens
+ * Grab the keycodes for which bindings exist
+ * Manage all existing windows
+ * Enter the event loop
+
+== Keybindings
+
+=== Grabbing the bindings
+
+Grabbing the bindings is quite straight-forward. You pass X your combination of
+modifiers and the keycode you want to grab and whether you want to grab them
+actively or passively. Most bindings (everything except for bindings using
+Mode_switch) are grabbed passively, that is, just the window manager gets the
+event and cannot replay it.
+
+We need to grab bindings that use Mode_switch actively because of a bug in X.
+When the window manager receives the keypress/keyrelease event for an actively
+grabbed keycode, it has to decide what to do with this event: It can either
+replay it so that other applications get it or it can prevent other
+applications from receiving it.
+
+So, why do we need to grab keycodes actively? Because X does not set the
+state-property of keypress/keyrelease events properly. The Mode_switch bit is
+not set and we need to get it using XkbGetState. This means we cannot pass X
+our combination of modifiers containing Mode_switch when grabbing the key and
+therefore need to grab the keycode itself without any modifiers. This means,
+if you bind Mode_switch + keycode 38 ("a"), i3 will grab keycode 38 ("a") and
+check on each press of "a" if the Mode_switch bit is set using XKB. If yes, it
+will handle the event, if not, it will replay the event.
+
+=== Handling a keypress
+
+As mentioned in "Grabbing the bindings", upon a keypress event, i3 first gets
+the correct state.
+
+Then, it looks through all bindings and gets the one which matches the received
+event.
+
+The bound command is parsed directly in command mode.
+
+== Manage windows (src/mainx.c, manage_window() and reparent_window())
+
+`manage_window()` does some checks to decide whether the window should be
+managed at all:
+
+ * Windows have to be mapped, that is, visible on screen
+ * The override_redirect must not be set. Windows with override_redirect shall
+ not be managed by a window manager
+
+Afterwards, i3 gets the intial geometry and reparents the window (see
+`reparent_window()`) if it wasn’t already managed.
+
+Reparenting means that for each window which is reparented, a new window,
+slightly larger than the original one, is created. The original window is then
+reparented to the bigger one (called "frame").
+
+After reparenting, the window type (`_NET_WM_WINDOW_TYPE`) is checked to see
+whether this window is a dock (`_NET_WM_WINDOW_TYPE_DOCK`), like dzen2 for
+example. Docks are handled differently, they don’t have decorations and are not
+assigned to a specific container. Instead, they are positioned at the bottom
+of the screen. To get the height which needsd to be reserved for the window,
+the `_NET_WM_STRUT_PARTIAL` property is used.
+
+Furthermore, the list of assignments (to other workspaces, which may be on
+other screens) is checked. If the window matches one of the user’s criteria,
+it may either be put in floating mode or moved to a different workspace. If the
+target workspace is not visible, the window will not be mapped.
+
+== What happens when an application is started?
+
+i3 does not care for applications. All it notices is when new windows are
+mapped (see `src/handlers.c`, `handle_map_request()`). The window is then
+reparented (see section "Manage windows").
+
+After reparenting the window, `render_layout()` is called which renders the
+internal layout table. The new window has been placed in the currently focused
+container and therefore the new window and the old windows (if any) need to be
+moved/resized so that the currently active layout (default/stacking/tabbed mode)
+is rendered correctly. To move/resize windows, a window is ``configured'' in
+X11-speak.
+
+Some applications, such as MPlayer obviously assume the window manager is
+stupid and try to configure their windows by themselves. This generates an
+event called configurerequest. i3 handles these events and tells the window the
+size it had before the configurerequest (with the exception of not yet mapped
+windows, which get configured like they want to, and floating windows, which
+can reconfigure themselves).
+
+== _NET_WM_STATE
+
+Only the _NET_WM_STATE_FULLSCREEN atom is handled. It calls
+``toggle_fullscreen()'' for the specific client which just configures the
+client to use the whole screen on which it currently is. Also, it is set as
+fullscreen_client for the i3Screen.
+
+== WM_NAME
+
+When the WM_NAME property of a window changes, its decoration (containing the
+title) is re-rendered. Note that WM_NAME is in COMPOUND_TEXT encoding which is
+totally uncommon and cumbersome. Therefore, the _NET_WM_NAME atom will be used
+if present.
+
+== _NET_WM_NAME
+
+Like WM_NAME, this atom contains the title of a window. However, _NET_WM_NAME
+is encoded in UTF-8. i3 will recode it to UCS-2 in order to be able to pass it
+to X. Using an appropriate font (ISO-10646), you can see most special
+characters (every special character contained in your font).
+
+== Size hints
+
+Size hints specify the minimum/maximum size for a given window as well as its
+aspect ratio. This is important for clients like mplayer, who only set the
+aspect ratio and resize their window to be as small as possible (but only with
+some video outputs, for example in Xv, while when using x11, mplayer does the
+necessary centering for itself).
+
+So, when an aspect ratio was specified, i3 adjusts the height of the window
+until the size maintains the correct aspect ratio. For the code to do this, see
+src/layout.c, function resize_client().
+
+== Rendering (src/layout.c, render_layout() and render_container())
+
+There are several entry points to rendering: `render_layout()`,
+`render_workspace()` and `render_container()`. The former one calls
+`render_workspace()` for every screen, which in turn will call
+`render_container()` for every container inside its layout table. Therefore, if
+you need to render only a single container, for example because a window was
+removed, added or changed its title, you should directly call
+render_container().
+
+Rendering consists of two steps: In the first one, in `render_workspace()`, each
+container gets its position (screen offset + offset in the table) and size
+(container's width times colspan/rowspan). Then, `render_container()` is called,
+which takes different approaches, depending on the mode the container is in:
+
+=== Common parts
+
+On the frame (the window which was created around the client’s window for the
+decorations), a black rectangle is drawn as a background for windows like
+MPlayer, which do not completely fit into the frame.
+
+=== Default mode
+
+Each clients gets the container’s width and an equal amount of height.
+
+=== Stack mode
+
+In stack mode, a window containing the decorations of all windows inside the
+container is placed at the top. The currently focused window is then given the
+whole remaining space.
+
+=== Tabbed mode
+
+Tabbed mode is like stack mode, except that the window decorations are drawn
+in one single line at the top of the container.
+
+=== Window decorations
+
+The window decorations consist of a rectangle in the appropriate color (depends
+on whether this window is the currently focused one, the last focused one in a
+not focused container or not focused at all) forming the background.
+Afterwards, two lighter lines are drawn and the last step is drawing the
+window’s title (see WM_NAME) onto it.
+
+=== Fullscreen windows
+
+For fullscreen windows, the `rect` (x, y, width, height) is not changed to
+allow the client to easily go back to its previous position. Instead,
+fullscreen windows are skipped when rendering.
+
+=== Resizing containers
+
+By clicking and dragging the border of a container, you can resize the whole
+column (respectively row) which this container is in. This is necessary to keep
+the table layout working and consistent.
+
+The resizing works similarly to the resizing of floating windows or movement of
+floating windows:
+
+* A new, invisible window with the size of the root window is created
+ (+grabwin+)
+* Another window, 2px width and as high as your screen (or vice versa for
+ horizontal resizing) is created. Its background color is the border color and
+ it is only there to inform the user how big the container will be (it
+ creates the impression of dragging the border out of the container).
+* The +drag_pointer+ function of +src/floating.c+ is called to grab the pointer
+ and enter its own event loop which will pass all events (expose events) but
+ motion notify events. This function then calls the specified callback
+ (+resize_callback+) which does some boundary checking and moves the helper
+ window. As soon as the mouse button is released, this loop will be
+ terminated.
+* The new width_factor for each involved column (respectively row) will be
+ calculated.
+
+== User commands / commandmode (src/commands.c)
+
+Like in vim, you can control i3 using commands. They are intended to be a
+powerful alternative to lots of shortcuts, because they can be combined. There
+are a few special commands, which are the following:
+
+exec <command>::
+Starts the given command by passing it to `/bin/sh`.
+
+restart::
+Restarts i3 by executing `argv[0]` (the path with which you started i3) without
+forking.
+
+w::
+"With". This is used to select a bunch of windows. Currently, only selecting
+the whole container in which the window is in, is supported by specifying "w".
+
+f, s, d::
+Toggle fullscreen, stacking, default mode for the current window/container.
+
+The other commands are to be combined with a direction. The directions are h,
+j, k and l, like in vim (h = left, j = down, k = up, l = right). When you just
+specify the direction keys, i3 will move the focus in that direction. You can
+provide "m" or "s" before the direction to move a window respectively or snap.
+
+== Gotchas
+
+* Forgetting to call `xcb_flush(conn);` after sending a request. This usually
+ leads to code which looks like it works fine but which does not work under
+ certain conditions.
+
+== Using git / sending patches
+
+For a short introduction into using git, see
+http://www.spheredev.org/wiki/Git_for_the_lazy or, for more documentation, see
+http://git-scm.com/documentation
+
+When you want to send a patch because you fixed a bug or implemented a cool
+feature (please talk to us before working on features to see whether they are
+maybe already implemented, not possible for some some reason, or don’t fit
+into the concept), please use git to create a patchfile.
+
+First of all, update your working copy to the latest version of the master
+branch:
+
+--------
+git pull
+--------
+
+Afterwards, make the necessary changes for your bugfix/feature. Then, review
+the changes using +git diff+ (you might want to enable colors in the diff using
++git config diff.color auto+). When you are definitely done, use +git commit
+-a+ to commit all changes you’ve made.
+
+Then, use the following command to generate a patchfile which we can directly
+apply to the branch, preserving your commit message and name:
+
+-----------------------
+git format-patch origin
+-----------------------
+
+Just send us the generated file via email.
--- /dev/null
+IPC interface (interprocess communication)
+==========================================
+Michael Stapelberg <michael+i3@stapelberg.de>
+March 2010
+
+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
+to get various information like the current workspaces to implement an external
+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 +~/.i3/ipc.sock+.
+
+== Establishing a connection
+
+To establish a connection, simply open the IPC socket. The following code
+snippet illustrates this in Perl:
+
+-------------------------------------------------------------
+use IO::Socket::UNIX;
+my $sock = IO::Socket::UNIX->new(Peer => '~/.i3/ipc.sock');
+-------------------------------------------------------------
+
+== 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). 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
+to do that).
+
+Currently implemented message types are the following:
+
+COMMAND (0)::
+ The payload of the message is a command for i3 (like the commands you
+ can bind to keys in the configuration file) and will be executed
+ directly after receiving it. There is no reply to this message.
+GET_WORKSPACES (1)::
+ Gets the current workspaces. The reply will be a JSON-encoded list of
+ workspaces (see the reply section).
+SUBSCRIBE (2)::
+ Subscribes your connection to certain events. See <<events>> for a
+ description of this message and the concept of events.
+GET_OUTPUTS (3)::
+ Gets the current outputs. The reply will be a JSON-encoded list of outputs
+ (see the reply section).
+
+So, a typical message could look like this:
+--------------------------------------------------
+"i3-ipc" <message length> <message type> <payload>
+--------------------------------------------------
+
+Or, as a hexdump:
+------------------------------------------------------------------------------
+00000000 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex|
+00000010 69 74 0a |it.|
+------------------------------------------------------------------------------
+
+To generate and send such a message, you could use the following code in Perl:
+------------------------------------------------------------
+sub format_ipc_command {
+ my ($msg) = @_;
+ my $len;
+ # Get the real byte count (vs. amount of characters)
+ { use bytes; $len = length($msg); }
+ return "i3-ipc" . pack("LL", $len, 0) . $msg;
+}
+
+$sock->write(format_ipc_command("exit"));
+------------------------------------------------------------------------------
+
+== Receiving replies from i3
+
+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
+with certain attributes).
+
+=== Reply format
+
+The reply format is identical to the normal message format. There also is
+the magic string, then the message length, then the message type and the
+payload.
+
+The following reply types are implemented:
+
+COMMAND (0)::
+ Confirmation/Error code for the COMMAND message.
+GET_WORKSPACES (1)::
+ Reply to the GET_WORKSPACES message.
+SUBSCRIBE (2)::
+ Confirmation/Error code for the SUBSCRIBE message.
+GET_OUTPUTS (3)::
+ Reply to the GET_OUTPUTS message.
+
+=== COMMAND reply
+
+The reply consists of a single serialized map. At the moment, the only
+property is +success (bool)+, but this will be expanded in future versions.
+
+*Example:*
+-------------------
+{ "success": true }
+-------------------
+
+=== GET_WORKSPACES reply
+
+The reply consists of a serialized list of workspaces. Each workspace has the
+following properties:
+
+num (integer)::
+ The logical number of the workspace. Corresponds to the command
+ to switch to this workspace.
+name (string)::
+ The name of this workspace (by default num+1), as changed by the
+ user. Encoded in UTF-8.
+visible (boolean)::
+ Whether this workspace is currently visible on an output (multiple
+ workspaces can be visible at the same time).
+focused (boolean)::
+ Whether this workspace currently has the focus (only one workspace
+ can have the focus at the same time).
+urgent (boolean)::
+ Whether a window on this workspace has the "urgent" flag set.
+rect (map)::
+ The rectangle of this workspace (equals the rect of the output it
+ is on), consists of x, y, width, height.
+output (string)::
+ The video output this workspace is on (LVDS1, VGA1, …).
+
+*Example:*
+-------------------
+[
+ {
+ "num": 0,
+ "name": "1",
+ "visible": true,
+ "focused": true,
+ "urgent": false,
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "width": 1280,
+ "height": 800
+ },
+ "output": "LVDS1"
+ },
+ {
+ "num": 1,
+ "name": "2",
+ "visible": false,
+ "focused": false,
+ "urgent": false,
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "width": 1280,
+ "height": 800
+ },
+ "output": "LVDS1"
+ }
+]
+-------------------
+
+=== SUBSCRIBE reply
+
+The reply consists of a single serialized map. The only property is
++success (bool)+, indicating whether the subscription was successful (the
+default) or whether a JSON parse error occurred.
+
+*Example:*
+-------------------
+{ "success": true }
+-------------------
+
+=== GET_OUTPUTS reply
+
+The reply consists of a serialized list of outputs. Each output has the
+following properties:
+
+name (string)::
+ The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8.
+active (boolean)::
+ Whether this output is currently active (has a valid mode).
+current_workspace (integer)::
+ The current workspace which is visible on this output. +null+ if the
+ output is not active.
+rect (map)::
+ The rectangle of this output (equals the rect of the output it
+ is on), consists of x, y, width, height.
+
+*Example:*
+-------------------
+[
+ {
+ "name": "LVDS1",
+ "active": true,
+ "current_workspace": 4,
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "width": 1280,
+ "height": 800
+ }
+ },
+ {
+ "name": "VGA1",
+ "active": true,
+ "current_workspace": 1,
+ "rect": {
+ "x": 1280,
+ "y": 0,
+ "width": 1280,
+ "height": 1024
+ },
+ }
+]
+-------------------
+
+== Events
+
+[[events]]
+
+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. 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 suggest you create a
+separate connection to receive events.
+
+=== Subscribing to events
+
+By sending a message of type SUBSCRIBE with a JSON-encoded array as payload
+you can register to an event.
+
+*Example:*
+---------------------------------
+type: SUBSCRIBE
+payload: [ "workspace", "focus" ]
+---------------------------------
+
+
+=== Available events
+
+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", "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
+all this on your own). This list names some (if you wrote one, please let me
+know):
+
+C::
+ i3 includes a headerfile +i3/ipc.h+ which provides you all constants.
+ However, there is no library yet.
+Ruby::
+ http://github.com/badboy/i3-ipc
+Perl::
+ http://search.cpan.org/search?query=AnyEvent::I3
+Python::
+ http://github.com/thepub/i3ipc
--- /dev/null
+The multi-monitor situation
+===========================
+Michael Stapelberg <michael+i3@stapelberg.de>
+March 2010
+
+…or: oh no, I have an nVidia graphics card!
+
+== The quick fix
+
+If you are using the nVidia binary graphics driver (also known as 'blob')
+you need to use the +--force-xinerama+ flag (in your .xsession) when starting
+i3, like so:
+
+.Example:
+----------------------------------------------
+exec i3 --force-xinerama -V >>~/.i3/i3log 2>&1
+----------------------------------------------
+
+== The explanation
+
+Starting with version 3.ε, i3 uses the RandR (Rotate and Resize) API instead
+of Xinerama. The reason for this, is that RandR provides more information
+about your outputs and connected screens than Xinerama does. To be specific,
+the code which handled on-the-fly screen reconfiguration (meaning without
+restarting the X server) was a very messy heuristic and most of the time did
+not work correctly -- that is just not possible with the little information
+Xinerama offers (just a list of screen resolutions, no identifiers for the
+screens or any additional information). Xinerama simply was not designed
+for dynamic configuration.
+
+So RandR came along, as a more powerful alternative (RandR 1.2 to be specific).
+It offers all of Xinerama’s possibilities and lots more. Using the RandR API
+made our code much more robust and clean. Also, you can now reliably assign
+workspaces to output names instead of some rather unreliable screen identifier
+(position inside the list of screens, which could change, and so on…).
+
+As RandR has been around for about three years as of this writing, it seemed
+like a very good idea to us, and it still is a very good one. What we did not
+expect, however, was the nVidia binary driver. It still does not support RandR
+(as of March 2010), even though nVidia has announced that it will support RandR
+eventually. What does this mean for you, if you are stuck with the binary
+driver for some reason (say the free drivers don’t work with your card)? First
+of all, you are stuck with TwinView and cannot use +xrandr+. While this ruins
+the user experience, the more grave problem is that the nVidia driver not only
+does not support dynamic configuration using RandR, it also does not expose
+correct multi-monitor information via the RandR API. So, in some setups, i3
+will not find any screens; in others, it will find one large screen which
+actually contains both of your physical screens (but it will not know that
+these are two screens).
+
+For this very reason, we decided to implement the following workaround: As
+long as the nVidia driver does not support RandR, an option called
++--force-xinerama+ is available in i3. This option gets the list of screens
+*once* when starting, and never updates it. As the nVidia driver cannot do
+dynamic configuration anyways, this is not a big deal.
+
+== See also
+
+For more information on how to use multi-monitor setups, see the i3 User’s
+Guide.
--- /dev/null
+Tree branch: Migrating
+======================
+Michael Stapelberg <michael+i3@stapelberg.de>
+November 2010
+
+== Introduction
+
+The tree branch (referring to a branch of i3 in the git repository) is the new
+version of i3. Due to the very deep changes and heavy refactoring of the source
+source, we decided to develop it in a seperate branch (instead of using the
+next/master-branch system like before).
+
+== Current status
+
+Currently, the code is mostly working. Some of the i3 core developers have been
+using the tree branch version for a few weeks now. So, if you are eager to try
+out the new features and help us find bugs, give it a try!
+
+At the same time, a word of warning is appropriate: This version of i3 might
+crash unexpectedly, so please be careful with important data (do not work for
+two days without saving…).
+
+== Getting the latest tree branch version
+
+Check out the latest version:
+---------------------------------------------
+$ git clone -b tree git://code.stapelberg.de/i3
+---------------------------------------------
+
+Then build and install it (has the same dependencies as the latest stable i3
+version):
+-----------------------------
+$ cd i3
+$ make
+$ sudo cp i3 /usr/bin/i3-tree
+-----------------------------
+
+…and execute +i3-tree+ instead of +i3+ in your Xsession.
+
+*IMPORTANT:* Please note that configuration file compatibility is not yet done.
+So, make sure you use/customize the provided +i3.config+ file.
+
+== Tree
+
+The most important change and reason for the name is that i3 stores all
+information about the X11 outputs, workspaces and layout of the windows on them
+in a tree. The root node is the X11 root window, followed by the X11 outputs,
+then workspaces and finally the windows themselve. In previous versions of i3
+we had multiple lists (of outputs, workspaces) and a table for each workspace.
+That approach turned out to be complicated to use (snapping), understand and
+implement.
+
+=== The tree consists of Containers
+
+The building blocks of our tree are so called +Containers+. A +Container+ can
+host a window (meaning an X11 window, one that you can actually see and use,
+like a browser). Alternatively, it could contain one or more +Containers+. A
+simple example is the workspace: When you start i3 with a single monitor, a
+single workspace and you open two terminal windows, you will end up with a tree
+like this:
+
+image::tree-layout2.png["layout2",float="right"]
+image::tree-shot4.png["shot4",title="Two terminals on standard workspace"]
+
+=== Orientation and Split Containers
+
+[[OrientationSplit]]
+
+It is only natural to use so-called +Split Containers+ in order to build a
+layout when using a tree as data structure. In i3, every +Container+ has an
+orientation (horizontal, vertical or unspecified). So, in our example with the
+workspace, the default orientation of the workspace +Container+ is horizontal
+(most monitors are widescreen nowadays). If you change the orientation to
+vertical (+Alt+v+ in the default config) and *then* open two terminals, i3 will
+configure your windows like this:
+
+image::tree-shot2.png["shot2",title="Vertical Workspace Orientation"]
+
+An interesting new feature of the tree branch is the ability to split anything:
+Let’s assume you have two terminals on a workspace (with horizontal
+orientation), focus is on the right terminal. Now you want to open another
+terminal window below the current one. If you would just open a new terminal
+window, it would show up to the right due to the horizontal workspace
+orientation. Instead, press +Alt+v+ to create a +Vertical Split Container+ (to
+open a +Horizontal Split Container+, use +Alt+h+). Now you can open a new
+terminal and it will open below the current one:
+
+image::tree-layout1.png["Layout",float="right"]
+image::tree-shot1.png["shot",title="Vertical Split Container"]
+
+unfloat::[]
+
+You probably guessed it already: There is no limit on how deep your hierarchy
+of splits can be.
+
+=== Level up
+
+Let’s stay with our example from above. We have a terminal on the left and two
+vertically split terminals on the right, focus is on the bottom right one. When
+you open a new terminal, it will open below the current one.
+
+So, how can you open a new terminal window to the *right* of the current one?
+The solution is to use +level up+, which will focus the +Parent Container+ of
+the current +Container+. In this case, you would focus the +Vertical Split
+Container+ which is *inside* the horizontally oriented workspace. Thus, now new
+windows will be opened to the right of the +Vertical Split Container+:
+
+image::tree-shot3.png["shot3",title="Level Up, then open new terminal"]
+
+== Commands
+
+The authoritive reference for commands is +src/cmdparse.y+. You can also find
+most commands in +i3.config+. Here comes a short overview over the important
+commands:
+
+=== Manipulating layout
+
+-------------------------------
+layout <default|stacked|tabbed>
+-------------------------------
+
+=== Changing Focus
+
+--------------------------
+next <horizontal|vertical>
+prev <horizontal|vertical>
+--------------------------
+
+.Examples:
+-------------------------
+bindsym Mod1+Left prev h
+bindsym Mod1+Right next h
+bindsym Mod1+Down next v
+bindsym Mod1+Up prev v
+-------------------------
+
+=== Moving
+
+-----------------------------------------
+move <before|after> <horizontal|vertical>
+-----------------------------------------
+
+.Examples:
+-----------------------------------------
+bindsym Mod1+Shift+Left move before h
+bindsym Mod1+Shift+Right move after h
+bindsym Mod1+Shift+Down move before v
+bindsym Mod1+Shift+Up move after v
+-----------------------------------------
+
+=== Changing workspace
+
+---------------------------
+workspace <name>
+---------------------------
+
+.Examples:
+---------------------------
+bindsym Mod1+1 workspace 1
+bindsym Mod1+2 workspace 2
+…
+---------------------------
+
+=== Moving Containers to workspaces
+
+---------------------
+move workspace <name>
+---------------------
+
+-------------------------------------
+bindsym Mod1+Shift+1 move workspace 1
+bindsym Mod1+Shift+2 move workspace 2
+…
+-------------------------------------
+
+=== Changing border style
+
+---------------------------
+border <normal|none|1pixel>
+---------------------------
+
+=== Changing container mode
+
+-----------------------------
+mode <tiling|floating|toggle>
+-----------------------------
+
+== The rest
+
+What is not mentioned here explicitly is either unchanged and can be read in
+the http://i3.zekjur.net/docs/userguide.html[i3 User’s Guide] or it is not yet
+implemented.
--- /dev/null
+i3 User’s Guide
+===============
+Michael Stapelberg <michael+i3@stapelberg.de>
+March 2010
+
+This document contains all the information you need to configure and use the i3
+window manager. If it does not, please contact me on IRC, Jabber or E-Mail and
+I’ll help you out.
+
+== Default keybindings
+
+For the "too long; didn’t read" people, here is an overview of the default
+keybindings (click to see the full size image):
+
+*Keys to use with Mod1 (alt):*
+
+image:keyboard-layer1.png["Keys to use with Mod1 (alt)",width=600,link="keyboard-layer1.png"]
+
+*Keys to use with Shift+Mod1:*
+
+image:keyboard-layer2.png["Keys to use with Shift+Mod1",width=600,link="keyboard-layer2.png"]
+
+As i3 uses keycodes in the default configuration, it does not matter which
+keyboard layout you actually use. The key positions are what matters (of course
+you can also use keysymbols, see <<keybindings>>).
+
+The red keys are the modifiers you need to press (by default), the blue keys
+are your homerow.
+
+== Using i3
+
+=== Opening terminals and moving around
+
+One very basic operation is opening a new terminal. By default, the keybinding
+for this is Mod1+Enter, that is Alt+Enter in the default configuration. By
+pressing Mod1+Enter, a new terminal will be opened. It will fill the whole
+space available on your screen.
+
+image:single_terminal.png[Single terminal]
+
+It is important to keep in mind that i3 uses a table to manage your windows. At
+the moment, you have exactly one column and one row which leaves you with one
+cell. In this cell there is a container, which is where your new terminal is
+opened.
+
+If you now open another terminal, you still have only one cell. However, the
+container in that cell holds both of your terminals. So, a container is just a
+group of clients with a specific layout. Containers can be resized by adjusting
+the size of the cell that holds them.
+
+image:two_terminals.png[Two terminals]
+
+To move the focus between the two terminals, you use the direction keys which
+you may know from the editor +vi+. However, in i3, your homerow is used for
+these keys (in +vi+, the keys are shifted to the left by one for compatibility
+with most keyboard layouts). Therefore, +Mod1+J+ is left, +Mod1+K+ is down,
++Mod1+L+ is up and `Mod1+;` is right. So, to switch between the terminals,
+use +Mod1+K+ or +Mod1+L+.
+
+To create a new row/column (and a new cell), you can simply move a terminal (or
+any other window) in the direction you want to expand your table. So, let’s
+expand the table to the right by pressing `Mod1+Shift+;`.
+
+image:two_columns.png[Two columns]
+
+=== Changing container modes
+
+A container can have the following modes:
+
+default::
+Windows are sized so that every window gets an equal amount of space in the
+container.
+stacking::
+Only the focused window in the container is displayed. You get a list of
+windows at the top of the container.
+tabbed::
+The same principle as +stacking+, but the list of windows at the top is only
+a single line which is vertically split.
+
+To switch modes, press +Mod1+e+ for default, +Mod1+h+ for stacking and
++Mod1+w+ for tabbed.
+
+image:modes.png[Container modes]
+
+=== Toggling fullscreen mode for a window
+
+To display a window fullscreen or to go out of fullscreen mode again, press
++Mod1+f+.
+
+There is also a global fullscreen mode in i3 in which the client will use all
+available outputs. To use it, or to get out of it again, press +Mod1+Shift+f+.
+
+=== Opening other applications
+
+Aside from opening applications from a terminal, you can also use the handy
++dmenu+ which is opened by pressing +Mod1+v+ by default. Just type the name
+(or a part of it) of the application which you want to open. The application
+typed has to be in your +$PATH+ for this to work.
+
+Additionally, if you have applications you open very frequently, you can
+create a keybinding for starting the application directly. See the section
+"Configuring i3" for details.
+
+=== Closing windows
+
+If an application does not provide a mechanism for closing (most applications
+provide a menu, the escape key or a shortcut like +Control+W+ to close), you
+can press +Mod1+Shift+q+ to kill a window. For applications which support
+the WM_DELETE protocol, this will correctly close the application (saving
+any modifications or doing other cleanup). If the application doesn’t support
+the WM_DELETE protocol your X server will kill the window and the behaviour
+depends on the application.
+
+=== Using workspaces
+
+Workspaces are an easy way to group a set of windows. By default, you are on
+the first workspace, as the bar on the bottom left indicates. To switch to
+another workspace, press +Mod1+num+ where +num+ is the number of the workspace
+you want to use. If the workspace does not exist yet, it will be created.
+
+A common paradigm is to put the web browser on one workspace, communication
+applications (+mutt+, +irssi+, ...) on another one, and the ones with which you
+work, on the third one. Of course, there is no need to follow this approach.
+
+If you have multiple screens, a workspace will be created on each screen at
+startup. If you open a new workspace, it will be bound to the screen you
+created it on. When you switch to a workspace on another screen, i3 will set
+focus to that screen.
+
+=== Moving windows to workspaces
+
+To move a window to another workspace, simply press +Mod1+Shift+num+ where
++num+ is (like when switching workspaces) the number of the target workspace.
+Similarly to switching workspaces, the target workspace will be created if
+it does not yet exist.
+
+=== Resizing columns/rows
+
+To resize columns or rows, just grab the border between the two columns/rows
+and move it to the wanted size. Please keep in mind that each cell of the table
+holds a +container+ and thus you cannot horizontally resize single windows. If
+you need applications with different horizontal sizes, place them in seperate
+cells one above the other.
+
+See <<resizingconfig>> for how to configure i3 to be able to resize
+columns/rows with your keyboard.
+
+=== Restarting i3 inplace
+
+To restart i3 inplace (and thus get into a clean state if there is a bug, or
+to upgrade to a newer version of i3) you can use +Mod1+Shift+r+. Be aware,
+though, that this kills your current layout and all the windows you have opened
+will be put in a default container in only one cell. Saving layouts will be
+implemented in a later version.
+
+=== Exiting i3
+
+To cleanly exit i3 without killing your X server, you can use +Mod1+Shift+e+.
+
+=== Snapping
+
+Snapping is a mechanism to increase/decrease the colspan/rowspan of a container.
+Colspan/rowspan is the number of columns/rows a specific cell of the table
+consumes. This is easier explained by giving an example, so take the following
+layout:
+
+image:snapping.png[Snapping example]
+
+To use the full size of your screen, you can now snap container 3 downwards
+by pressing +Mod1+Control+k+ (or snap container 2 rightwards).
+
+=== Floating
+
+Floating mode is the opposite of tiling mode. The position and size of a window
+are not managed by i3, but by you. Using this mode violates the tiling
+paradigm but can be useful for some corner cases like "Save as" dialog
+windows, or toolbar windows (GIMP or similar).
+
+You can enable floating mode for a window by pressing +Mod1+Shift+Space+. By
+dragging the window’s titlebar with your mouse you can move the window
+around. By grabbing the borders and moving them you can resize the window. You
+can also do that by using the <<floating_modifier>>.
+
+For resizing floating windows with your keyboard, see <<resizingconfig>>.
+
+Floating windows are always on top of tiling windows.
+
+== Configuring i3
+
+This is where the real fun begins ;-). Most things are very dependant on your
+ideal working environment so we can’t make reasonable defaults for them.
+
+While not using a programming language for the configuration, i3 stays
+quite flexible in regards to the things you usually want your window manager
+to do.
+
+For example, you can configure bindings to jump to specific windows,
+you can set specific applications to start on specific workspaces, you can
+automatically start applications, you can change the colors of i3, and you
+can bind your keys to do useful things.
+
+To change the configuration of i3, copy +/etc/i3/config+ to +\~/.i3/config+
+(or +~/.config/i3/config+ if you like the XDG directory scheme) and edit it
+with a text editor.
+
+=== Comments
+
+It is possible and recommended to use comments in your configuration file to
+properly document your setup for later reference. Comments are started with
+a # and can only be used at the beginning of a line:
+
+*Examples*:
+-------------------
+# This is a comment
+-------------------
+
+=== Fonts
+
+i3 uses X core fonts (not Xft) for rendering window titles and the internal
+workspace bar. You can use +xfontsel(1)+ to generate such a font description.
+To see special characters (Unicode), you need to use a font which supports
+the ISO-10646 encoding.
+
+*Syntax*:
+------------------------------
+font <X core font description>
+------------------------------
+
+*Examples*:
+--------------------------------------------------------------
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+--------------------------------------------------------------
+
+[[keybindings]]
+
+=== Keyboard bindings
+
+A keyboard binding makes i3 execute a command (see below) upon pressing a
+specific key. i3 allows you to bind either on keycodes or on keysyms (you can
+also mix your bindings, though i3 will not protect you from overlapping ones).
+
+* A keysym (key symbol) is a description for a specific symbol, like "a"
+ or "b", but also more strange ones like "underscore" instead of "_". These
+ are the ones you use in Xmodmap to remap your keys. To get the current
+ mapping of your keys, use +xmodmap -pke+.
+
+* Keycodes do not need to have a symbol assigned (handy for some hotkeys
+ on some notebooks) and they will not change their meaning as you switch to a
+ different keyboard layout (when using +xmodmap+).
+
+My recommendation is: If you often switch keyboard layouts but you want to keep
+your bindings in the same physical location on the keyboard, use keycodes.
+If you don’t switch layouts, and want a clean and simple config file, use
+keysyms.
+
+*Syntax*:
+----------------------------------
+bindsym [Modifiers+]keysym command
+bind [Modifiers+]keycode command
+----------------------------------
+
+*Examples*:
+--------------------------------
+# Fullscreen
+bindsym Mod1+f f
+
+# Restart
+bindsym Mod1+Shift+r restart
+
+# Notebook-specific hotkeys
+bind 214 exec /home/michael/toggle_beamer.sh
+--------------------------------
+
+Available Modifiers:
+
+Mod1-Mod5, Shift, Control::
+Standard modifiers, see +xmodmap(1)+
+
+Mode_switch::
+Unlike other window managers, i3 can use Mode_switch as a modifier. This allows
+you to remap capslock (for example) to Mode_switch and use it for both: typing
+umlauts or special characters 'and' having some comfortably reachable key
+bindings. For example, when typing, capslock+1 or capslock+2 for switching
+workspaces is totally convenient. Try it :-).
+
+[[floating_modifier]]
+
+=== The floating modifier
+
+To move floating windows with your mouse, you can either grab their titlebar
+or configure the so called floating modifier which you can then press and
+click anywhere in the window itself to move it. The most common setup is to
+use the same key you use for managing windows (Mod1 for example). Then
+you can press Mod1, click into a window using your left mouse button, and drag
+it to the position you want.
+
+When holding the floating modifier, you can resize a floating window by
+pressing the right mouse button on it and moving around while holding it. If
+you hold the shift button as well, the resize will be proportional.
+
+*Syntax*:
+--------------------------------
+floating_modifier <Modifiers>
+--------------------------------
+
+*Examples*:
+--------------------------------
+floating_modifier Mod1
+--------------------------------
+
+=== Layout mode for new containers
+
+This option determines in which mode new containers will start. See also
+<<stack-limit>>.
+
+*Syntax*:
+---------------------------------------------
+new_container <default|stacking|tabbed>
+new_container stack-limit <cols|rows> <value>
+---------------------------------------------
+
+*Examples*:
+---------------------
+new_container tabbed
+---------------------
+
+=== Border style for new windows
+
+This option determines which border style new windows will have.
+
+*Syntax*:
+---------------------------------------------
+new_window <bp|bn|bb>
+---------------------------------------------
+
+*Examples*:
+---------------------
+new_window bp
+---------------------
+
+=== Variables
+
+As you learned in the section about keyboard bindings, you will have
+to configure lots of bindings containing modifier keys. If you want to save
+yourself some typing and be able to change the modifier you use later,
+variables can be handy.
+
+*Syntax*:
+--------------
+set name value
+--------------
+
+*Examples*:
+------------------------
+set $m Mod1
+bindsym $m+Shift+r restart
+------------------------
+
+Variables are directly replaced in the file when parsing. There is no fancy
+handling and there are absolutely no plans to change this. If you need a more
+dynamic configuration you should create a little script which generates a
+configuration file and run it before starting i3 (for example in your
++.xsession+ file).
+
+=== Automatically putting clients on specific workspaces
+
+[[assign_workspace]]
+
+It is recommended that you match on window classes wherever possible because
+some applications first create their window, and then worry about setting the
+correct title. Firefox with Vimperator comes to mind. The window starts up
+being named Firefox, and only when Vimperator is loaded does the title change.
+As i3 will get the title as soon as the application maps the window (mapping
+means actually displaying it on the screen), you’d need to have to match on
+'Firefox' in this case.
+
+You can prefix or suffix workspaces with a `~` to specify that matching clients
+should be put into floating mode. If you specify only a `~`, the client will
+not be put onto any workspace, but will be set floating on the current one.
+
+*Syntax*:
+------------------------------------------------------------
+assign ["]window class[/window title]["] [→] [~ | workspace]
+------------------------------------------------------------
+
+*Examples*:
+----------------------
+assign urxvt 2
+assign urxvt → 2
+assign "urxvt" → 2
+assign "urxvt/VIM" → 3
+assign "gecko" → ~4
+assign "xv/MPlayer" → ~
+----------------------
+
+Note that the arrow is not required, it just looks good :-). If you decide to
+use it, it has to be a UTF-8 encoded arrow, not "->" or something like that.
+
+=== Automatically starting applications on i3 startup
+
+By using the +exec+ keyword outside a keybinding, you can configure which
+commands will be performed by i3 on initial startup (not when restarting i3
+in-place however). These commands will be run in order.
+
+*Syntax*:
+------------
+exec command
+------------
+
+*Examples*:
+--------------------------------
+exec sudo i3status | dzen2 -dock
+--------------------------------
+
+[[workspace_screen]]
+
+=== Automatically putting workspaces on specific screens
+
+If you assign clients to workspaces, it might be handy to put the
+workspaces on specific screens. Also, the assignment of workspaces to screens
+will determine which workspace i3 uses for a new screen when adding screens
+or when starting (e.g., by default it will use 1 for the first screen, 2 for
+the second screen and so on).
+
+*Syntax*:
+----------------------------------
+workspace <number> output <output>
+----------------------------------
+
+The 'output' is the name of the RandR output you attach your screen to. On a
+laptop, you might have VGA1 and LVDS1 as output names. You can see the
+available outputs by running +xrandr --current+.
+
+*Examples*:
+---------------------------
+workspace 1 output LVDS1
+workspace 5 output VGA1
+---------------------------
+
+=== Named workspaces
+
+If you always have a certain arrangement of workspaces, you might want to give
+them names (of course UTF-8 is supported):
+
+*Syntax*:
+---------------------------------------
+workspace <number> <name>
+workspace <number> output <output> name
+---------------------------------------
+
+For more details about the 'output' part of this command, see above.
+
+*Examples*:
+--------------------------
+workspace 1 www
+workspace 2 work
+workspace 3 i ♥ workspaces
+--------------------------
+
+=== Changing colors
+
+You can change all colors which i3 uses to draw the window decorations and the
+bottom bar.
+
+*Syntax*:
+--------------------------------------------
+colorclass border background text
+--------------------------------------------
+
+Where colorclass can be one of:
+
+client.focused::
+ A client which currently has the focus.
+client.focused_inactive::
+ A client which is the focused one of its container, but it does not have
+ the focus at the moment.
+client.unfocused::
+ A client which is not the focused one of its container.
+client.urgent::
+ A client which has its urgency hint activated.
+bar.focused::
+ The current workspace in the bottom bar.
+bar.unfocused::
+ All other workspaces in the bottom bar.
+bar.urgent::
+ A workspace which has at least one client with an activated urgency hint.
+
+You can also specify the color to be used to paint the background of the client
+windows. This color will be used to paint the window on top of which the client
+will be rendered.
+
+*Syntax*:
+-----------------------
+client.background color
+-----------------------
+
+Only clients that do not cover the whole area of this window expose the color
+used to paint it. If you use a color other than black for your terminals, you
+most likely want to set the client background color to the same color as your
+terminal program's background color to avoid black gaps between the rendered
+area of the termianal and the i3 border.
+
+Colors are in HTML hex format (#rrggbb), see the following example:
+
+*Examples*:
+--------------------------------------
+# class border backgr. text
+client.focused #2F343A #900000 #FFFFFF
+--------------------------------------
+
+Note that for the window decorations, the color around the child window is the
+background color, and the border color is only the two thin lines at the top of
+the window.
+
+=== Interprocess communication
+
+i3 uses unix sockets to provide an IPC interface. This allows third-party
+programs to get information from i3, such as the current workspaces
+(to display a workspace bar), and to control i3.
+
+To enable it, you have to configure a path where the unix socket will be
+stored. The default path is +~/.i3/ipc.sock+.
+
+*Examples*:
+----------------------------
+ipc-socket ~/.i3/ipc.sock
+----------------------------
+
+You can then use the +i3-msg+ application to perform any command listed in
+the next section.
+
+=== Disable focus follows mouse
+
+If you have a setup where your mouse usually is in your way (like a touchpad
+on your laptop which you do not want to disable completely), you might want
+to disable 'focus follows mouse' and control focus only by using your keyboard.
+The mouse will still be useful inside the currently active window (for example
+to click on links in your browser window).
+
+*Syntax*:
+----------------------------
+focus_follows_mouse <yes|no>
+----------------------------
+
+*Examples*:
+----------------------
+focus_follows_mouse no
+----------------------
+
+=== Internal workspace bar
+
+The internal workspace bar (the thing at the bottom of your screen) is very
+simple -- it does not provide a way to display custom text and it does not
+offer advanced customization features. This is intended because we do not
+want to duplicate functionality of tools like +dzen2+, +xmobar+ and so on
+(they render bars, we manage windows). Instead, there is an option which will
+turn off the internal bar completely, so that you can use a separate program to
+display it (see +i3-wsbar+, a sample implementation of such a program):
+
+*Syntax*:
+----------------------
+workspace_bar <yes|no>
+----------------------
+
+*Examples*:
+----------------
+workspace_bar no
+----------------
+
+== List of commands
+
+=== Manipulating layout
+
+To change the layout of the current container to stacking, use +s+, for default
+use +d+ and for tabbed, use +T+. To make the current client (!) fullscreen,
+use +f+, to make it span all outputs, use +fg+, to make it floating (or
+tiling again) use +t+:
+
+*Examples*:
+--------------
+bindsym Mod1+s s
+bindsym Mod1+l d
+bindsym Mod1+w T
+
+# Toggle fullscreen
+bindsym Mod1+f f
+
+# Toggle global fullscreen
+bindsym Mod1+Shift+f fg
+
+# Toggle floating/tiling
+bindsym Mod1+t t
+--------------
+
+=== Focusing/Moving/Snapping clients/containers/screens
+
+To change the focus, use one of the +h+, +j+, +k+ and +l+ commands, meaning
+left, down, up, right (respectively). To focus a container, prefix it with
++wc+. To focus a screen, prefix it with +ws+.
+
+The same principle applies for moving and snapping: just prefix the command
+with +m+ when moving and with +s+ when snapping:
+
+*Examples*:
+----------------------
+# Focus clients on the left, bottom, top, right:
+bindsym Mod1+j h
+bindsym Mod1+k j
+bindsym Mod1+j k
+bindsym Mod1+semicolon l
+
+# Move client to the left, bottom, top, right:
+bindsym Mod1+j mh
+bindsym Mod1+k mj
+bindsym Mod1+j mk
+bindsym Mod1+semicolon ml
+
+# Snap client to the left, bottom, top, right:
+bindsym Mod1+j sh
+bindsym Mod1+k sj
+bindsym Mod1+j sk
+bindsym Mod1+semicolon sl
+
+# Focus container on the left, bottom, top, right:
+bindsym Mod3+j wch
+…
+----------------------
+
+=== Changing workspaces/moving clients to workspaces
+
+To change to a specific workspace, the command is just the number of the
+workspace, e.g. +1+ or +3+. To move the current client to a specific workspace,
+prefix the number with an +m+.
+
+You can also switch to the next and previous workspace with the commands +nw+
+and +pw+, which is handy, for example, if you have workspace 1, 3, 4 and 9 and
+you want to cycle through them with a single key combination.
+
+*Examples*:
+-------------------------
+bindsym Mod1+1 1
+bindsym Mod1+2 2
+...
+
+bindsym Mod1+Shift+1 m1
+bindsym Mod1+Shift+2 m2
+...
+
+bindsym Mod1+o nw
+bindsym Mod1+p pw
+-------------------------
+
+[[resizingconfig]]
+
+=== Resizing columns/rows
+
+If you want to resize columns/rows using your keyboard, you can use the
++resize+ command, I recommend using it inside a so called +mode+:
+
+.Example: Configuration file, defining a mode for resizing
+----------------------------------------------------------------------
+mode "resize" {
+ # These bindings trigger as soon as you enter the resize mode
+
+ # They resize the border in the direction you pressed, e.g.
+ # when pressing left, the window is resized so that it has
+ # more space on its left
+
+ bindsym n resize left -10
+ bindsym Shift+n resize left +10
+
+ bindsym r resize bottom +10
+ bindsym Shift+r resize bottom -10
+
+ bindsym t resize top -10
+ bindsym Shift+t resize top +10
+
+ bindsym d resize right +10
+ bindsym Shift+d resize right -10
+
+ bind 36 mode default
+}
+
+# Enter resize mode
+bindsym Mod1+r mode resize
+----------------------------------------------------------------------
+
+=== Jumping to specific windows
+
+Often when in a multi-monitor environment, you want to quickly jump to a
+specific window. For example, while working on workspace 3 you may want to
+jump to your mail client to email your boss that you’ve achieved some
+important goal. Instead of figuring out how to navigate to your mailclient,
+it would be more convenient to have a shortcut.
+
+*Syntax*:
+----------------------------------------------------
+jump ["]window class[/window title]["]
+jump workspace [ column row ]
+----------------------------------------------------
+
+You can either use the same matching algorithm as in the +assign+ command
+(see above) or you can specify the position of the client if you always use
+the same layout.
+
+*Examples*:
+--------------------------------------
+# Get me to the next open VIM instance
+bindsym Mod1+a jump "urxvt/VIM"
+--------------------------------------
+
+=== VIM-like marks (mark/goto)
+
+[[vim_like_marks]]
+
+This feature is like the jump feature: It allows you to directly jump to a
+specific window (this means switching to the appropriate workspace and setting
+focus to the windows). However, you can directly mark a specific window with
+an arbitrary label and use it afterwards. You do not need to ensure that your
+windows have unique classes or titles, and you do not need to change your
+configuration file.
+
+As the command needs to include the label with which you want to mark the
+window, you cannot simply bind it to a key. +i3-input+ is a tool created
+for this purpose: It lets you input a command and sends the command to i3. It
+can also prefix this command and display a custom prompt for the input dialog.
+
+*Syntax*:
+-----------------
+mark <identifier>
+goto <identifier>
+-----------------
+
+*Examples*:
+---------------------------------------
+# Read 1 character and mark the current window with this character
+bindsym Mod1+m exec i3-input -p 'mark ' -l 1 -P 'Mark: '
+
+# Read 1 character and go to the window with the character
+bindsym Mod1+g exec i3-input -p 'goto ' -l 1 -P 'Goto: '
+---------------------------------------
+
+Alternatively, if you do not want to mess with +i3-input+, you could create
+seperate bindings for a specific set of labels and then only use those labels.
+
+=== Traveling the focus stack
+
+This mechanism can be thought of as the opposite of the +jump+ command.
+It travels the focus stack and jumps to the window which had focus previously.
+
+*Syntax*:
+--------------
+focus [number] | floating | tiling | ft
+--------------
+
+Where +number+ by default is 1 meaning that the next client in the focus stack
+will be selected.
+
+The special values have the following meaning:
+
+floating::
+ The next floating window is selected.
+tiling::
+ The next tiling window is selected.
+ft::
+ If the current window is floating, the next tiling window will be
+ selected; and vice-versa.
+
+=== Changing border style
+
+To change the border of the current client, you can use +bn+ to use the normal
+border (including window title), +bp+ to use a 1-pixel border (no window title)
+and +bb+ to make the client borderless. There is also +bt+ which will toggle
+the different border styles.
+
+*Examples*:
+------------------
+bindsym Mod1+t bn
+bindsym Mod1+y bp
+bindsym Mod1+u bb
+------------------
+
+[[stack-limit]]
+
+=== Changing the stack-limit of a container
+
+If you have a single container with a lot of windows inside it (say, more than
+10), the default layout of a stacking container can get a little unhandy.
+Depending on your screen’s size, you might end up seeing only half of the
+titlebars for each window in the container.
+
+Using the +stack-limit+ command, you can limit the number of rows or columns
+in a stacking container. i3 will create columns or rows (depending on what
+you limited) automatically as needed.
+
+*Syntax*:
+--------------------------------
+stack-limit <cols|rows> <value>
+--------------------------------
+
+*Examples*:
+-------------------
+# I always want to have two window titles in one line
+stack-limit cols 2
+
+# Not more than 5 rows in this stacking container
+stack-limit rows 5
+-------------------
+
+image:stacklimit.png[Container limited to two columns]
+
+=== Reloading/Restarting/Exiting
+
+You can make i3 reload its configuration file with +reload+. You can also
+restart i3 inplace with the +restart+ command to get it out of some weird state
+(if that should ever happen) or to perform an upgrade without having to restart
+your X session. However, your layout is not preserved at the moment, meaning
+that all open windows will end up in a single container in default layout
+after the restart. To exit i3 properly, you can use the +exit+ command,
+however you don’t need to (simply killing your X session is fine as well).
+
+*Examples*:
+----------------------------
+bindsym Mod1+Shift+r restart
+bindsym Mod1+Shift+w reload
+bindsym Mod1+Shift+e exit
+----------------------------
+
+[[multi_monitor]]
+
+== Multiple monitors
+
+As you can see in the goal list on the website, i3 was specifically developed
+with support for multiple monitors in mind. This section will explain how to
+handle multiple monitors.
+
+When you have only one monitor, things are simple. You usually start with
+workspace 1 on your monitor and open new ones as you need them.
+
+When you have more than one monitor, each monitor will get an initial
+workspace. The first monitor gets 1, the second gets 2 and a possible third
+would get 3. When you switch to a workspace on a different monitor, i3 will
+switch to that monitor and then switch to the workspace. This way, you don’t
+need shortcuts to switch to a specific monitor, and you don’t need to remember
+where you put which workspace. New workspaces will be opened on the currently
+active monitor. It is not possible to have a monitor without a workspace.
+
+The idea of making workspaces global is based on the observation that most
+users have a very limited set of workspaces on their additional monitors.
+They are often used for a specific task (browser, shell) or for monitoring
+several things (mail, IRC, syslog, …). Thus, using one workspace on one monitor
+and "the rest" on the other monitors often makes sense. However, as you can
+create an unlimited number of workspaces in i3 and tie them to specific
+screens, you can have the "traditional" approach of having X workspaces per
+screen by changing your configuration (using modes, for example).
+
+=== Configuring your monitors
+
+To help you get going if you have never used multiple monitors before, here is
+a short overview of the xrandr options which will probably be of interest to
+you. It is always useful to get an overview of the current screen configuration.
+Just run "xrandr" and you will get an output like the following:
+-------------------------------------------------------------------------------
+$ xrandr
+Screen 0: minimum 320 x 200, current 1280 x 800, maximum 8192 x 8192
+VGA1 disconnected (normal left inverted right x axis y axis)
+LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 261mm x 163mm
+ 1280x800 60.0*+ 50.0
+ 1024x768 85.0 75.0 70.1 60.0
+ 832x624 74.6
+ 800x600 85.1 72.2 75.0 60.3 56.2
+ 640x480 85.0 72.8 75.0 59.9
+ 720x400 85.0
+ 640x400 85.1
+ 640x350 85.1
+--------------------------------------------------------------------------------------
+
+Several things are important here: You can see that +LVDS1+ is connected (of
+course, it is the internal flat panel) but +VGA1+ is not. If you have a monitor
+connected to one of the ports but xrandr still says "disconnected", you should
+check your cable, monitor or graphics driver.
+
+The maximum resolution you can see at the end of the first line is the maximum
+combined resolution of your monitors. By default, it is usually too low and has
+to be increased by editing +/etc/X11/xorg.conf+.
+
+So, say you connected VGA1 and want to use it as an additional screen:
+-------------------------------------------
+xrandr --output VGA1 --auto --left-of LVDS1
+-------------------------------------------
+This command makes xrandr try to find the native resolution of the device
+connected to +VGA1+ and configures it to the left of your internal flat panel.
+When running "xrandr" again, the output looks like this:
+-------------------------------------------------------------------------------
+$ xrandr
+Screen 0: minimum 320 x 200, current 2560 x 1024, maximum 8192 x 8192
+VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm
+ 1280x1024 60.0*+ 75.0
+ 1280x960 60.0
+ 1152x864 75.0
+ 1024x768 75.1 70.1 60.0
+ 832x624 74.6
+ 800x600 72.2 75.0 60.3 56.2
+ 640x480 72.8 75.0 66.7 60.0
+ 720x400 70.1
+LVDS1 connected 1280x800+1280+0 (normal left inverted right x axis y axis) 261mm x 163mm
+ 1280x800 60.0*+ 50.0
+ 1024x768 85.0 75.0 70.1 60.0
+ 832x624 74.6
+ 800x600 85.1 72.2 75.0 60.3 56.2
+ 640x480 85.0 72.8 75.0 59.9
+ 720x400 85.0
+ 640x400 85.1
+ 640x350 85.1
+-------------------------------------------------------------------------------
+Please note that i3 uses exactly the same API as xrandr does, so it will see
+only what you can see in xrandr.
+
+See also <<presentations>> for more examples of multi-monitor setups.
+
+=== Interesting configuration for multi-monitor environments
+
+There are several things to configure in i3 which may be interesting if you
+have more than one monitor:
+
+1. You can specify which workspace should be put on which screen. This
+ allows you to have a different set of workspaces when starting than just
+ 1 for the first monitor, 2 for the second and so on. See
+ <<workspace_screen>>.
+2. If you want some applications to generally open on the bigger screen
+ (MPlayer, Firefox, …), you can assign them to a specific workspace, see
+ <<assign_workspace>>.
+3. If you have many workspaces on many monitors, it might get hard to keep
+ track of which window you put where. Thus, you can use vim-like marks to
+ quickly switch between windows. See <<vim_like_marks>>.
+
+== i3 and the rest of your software world
+
+=== Displaying a status line
+
+A very common thing amongst users of exotic window managers is a status line at
+some corner of the screen. It is an often superior replacement to the widget
+approach you have in the task bar of a traditional desktop environment.
+
+If you don’t already have your favorite way of generating such a status line
+(self-written scripts, conky, …), then i3status is the recommended tool for
+this task. It was written in C with the goal of using as few syscalls as
+possible to reduce the time your CPU is woken up from sleep states.
+
+Regardless of which application you use to generate the status line, you
+want to make sure that the application does one of the following things:
+
+1. Register as a dock window using EWMH hints. This will make i3 position the
+ window above the workspace bar but below every other client. This is the
+ recommended way, but in case of dzen2, for example, you need to check out
+ the source of dzen2 from subversion, as the -dock option is not present
+ in the released versions.
+2. Overlay the internal workspace bar. This method will not waste any space
+ on the workspace bar, however, it is rather hackish. Just configure
+ the output window to be over the workspace bar (say -x 200 and -y 780 if
+ your screen is 800 px height).
+
+The planned solution for this problem is to make the workspace bar optional
+and switch to a third party application completely (dzen2 for example)
+which will then contain the workspace bar.
+
+=== Giving presentations (multi-monitor)
+
+When giving a presentation, you typically want the audience to see what you see
+on your screen and then go through a series of slides (if the presentation is
+simple). For more complex presentations, you might want to have some notes
+which only you can see on your screen, while the audience can only see the
+slides.
+
+[[presentations]]
+==== Case 1: everybody gets the same output
+This is the simple case. You connect your computer to the video projector,
+turn on both (computer and video projector) and configure your X server to
+clone the internal flat panel of your computer to the video output:
+-----------------------------------------------------
+xrandr --output VGA1 --mode 1024x768 --same-as LVDS1
+-----------------------------------------------------
+i3 will then use the lowest common subset of screen resolutions, the rest of
+your screen will be left untouched (it will show the X background). So, in
+our example, this would be 1024x768 (my notebook has 1280x800).
+
+==== Case 2: you can see more than your audience
+This case is a bit harder. First of all, you should configure the VGA output
+somewhere near your internal flat panel, say right of it:
+-----------------------------------------------------
+xrandr --output VGA1 --mode 1024x768 --right-of LVDS1
+-----------------------------------------------------
+Now, i3 will put a new workspace (depending on your settings) on the new screen
+and you are in multi-monitor mode (see <<multi_monitor>>).
+
+Because i3 is not a compositing window manager, there is no ability to
+display a window on two screens at the same time. Instead, your presentation
+software needs to do this job (that is, open a window on each screen).
--- /dev/null
+External workspace bars
+=======================
+Michael Stapelberg <michael+i3@stapelberg.de>
+May 2010
+
+This document describes why the internal workspace bar is minimal and how an
+external workspace bar can be used. It explains the concepts using +i3-wsbar+
+as the reference implementation.
+
+== Internal and external bars
+
+The internal workspace bar of i3 is meant to be a reasonable default so that
+you can use i3 without having too much hassle when setting it up. It is quite
+simple and intended to stay this way. So, there is no way to display your own
+information in this bar (unlike dwm, wmii, awesome, …).
+
+We chose not to implement such a mechanism because that would be duplicating
+already existing functionality of tools such as dzen2, xmobar and similar.
+Instead, you should disable the internal bar and use an external workspace bar
+(which communicates with i3 through its IPC interface).
+
+== dock mode
+
+You typically want to see the same workspace bar on every workspace on a
+specific screen. Also, you don’t want to place the workspace bar somewhere
+in your layout by hand. This is where dock mode comes in: When a program sets
+the appropriate hint (_NET_WM_WINDOW_TYPE_DOCK), it will be managed in dock
+mode by i3. That means it will be placed at the bottom of the screen (while
+other edges of the screen are possible in the NetWM standard, this is not yet
+implemented in i3), it will not overlap any other window and it will be on
+every workspace for the specific screen it was placed on initially.
+
+== The IPC interface
+
+In the context of using an external workspace bar, the IPC interface needs to
+provide the bar program with the current workspaces and output (as in VGA-1,
+LVDS-1, …) configuration. In the other direction, the program has to be able
+to switch to specific workspaces.
+
+By default, the IPC interface is enabled and places its UNIX socket in
++~/.i3/ipc.sock+.
+
+To learn more about the protocol which is used for IPC, see +docs/ipc+.
+
+== Output changes (on-the-fly)
+
+i3 implements the RandR API and can handle changing outputs quite well. So, an
+external workspace bar implementation needs to make sure that when you change
+the resolution of any of your screens (or enable/disable an output), the bars
+will be adjusted properly.
+
+== i3-wsbar, the reference implementation
+
+Please keep in mind that +i3-wsbar+ is just a reference implementation. It is
+shipped with i3 to have a reasonable default. Thus, +i3-wsbar+ is designed to
+work well with dzen2 and there are no plans to make it more generic.
+
+=== The big picture
+
+The most common reason to use an external workspace bar is to integrate system
+information such as what +i3status+ provides into the workspace bar (to save
+screen space). So, we have +i3status+ or a similar program, which only provides
+text output (formatted in some way). To display this text nicely on the screen,
+there are programs such as dzen2, xmobar and similar. We will stick to dzen2
+from here on. So, we have the output of i3status, which needs to go into dzen2
+somehow. But we also want to display the list of workspaces. +i3-wsbar+ takes
+input on stdin, combines it with a formatted workspace list and pipes it to
+dzen2.
+
+Please note that +i3-wsbar+ does not print its output to stdout. Instead, it
+launches the dzen2 instances on its own. This is necessary to handle changes
+in the available outputs (to place a new dzen2 on a new screen for example).
+
+image:wsbar.png["Overview",link="wsbar.png"]
+
+=== Running i3-wsbar
+
+The most simple usage of i3-wsbar looks like this:
+-------------------------------
+i3-wsbar -c "dzen2 -x %x -dock"
+-------------------------------
+
+The +%x+ in the command name will be replaced by the X position of the output
+for which this workspace bar is running. i3 will automatically place the
+workspace bar on the correct output when dzen2 is started in dock mode. The
+bar which you will see should look exactly like the internal bar of i3.
+
+To actually get a benefit, you want to give +i3-wsbar+ some input:
+------------------------------------------
+i3status | i3-wsbar -c "dzen2 -x %x -dock"
+------------------------------------------
+
+It is recommended to place the above command in your i3 configuration file
+to start it automatically with i3.
--- /dev/null
+a {
+ color: #3ec2ff;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: #3ec2ff;
+}
+
+strong {
+ font-weight: bold;
+ color: #3ec2ff;
+}
+
+tt {
+ font-family: 'Droid Sans Mono', sans-serif;
+ font-size: inherit;
+ color: #3ec2ff;
+}
+
+div.listingblock tt {
+ color: black;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+}
+
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+/*ul > li { color: #aaa; }*/
+/*ul > li > * { color: black; }*/
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revnumber, span#revdate, span#revremark {
+}
+
+div#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #777777;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #3ec2ff;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: #3ec2ff;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+ border: 3px solid #3ec2ff;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #3ec2ff;
+}
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toc {
+ margin-bottom: 2.5em;
+}
+
+div#toctitle {
+ color: #3ec2ff;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+@font-face {
+ font-family: 'Droid Sans Mono';
+ font-style: normal;
+ font-weight: normal;
+ src: local('Droid Sans Mono'), local('DroidSansMono'), url('/fonts/DroidSansMono.ttf') format('truetype');
+}
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: Debugging i3: How To</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes();}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>Debugging i3: How To</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">March 2010</span>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This document describes how to debug i3 suitably for sending us useful bug\r
+reports, even if you have no clue of C programming.</p></div>\r
+<div class="paragraph"><p>First of all: Thank you for being interested in debugging i3. It really means\r
+something to us to get your bug fixed. If you have any questions about the\r
+debugging and/or need further help, do not hesitate to contact us!</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_enabling_logging">1. Enabling logging</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>i3 spits out much information onto stdout, if told so. To have a clearly\r
+defined place where log files will be saved, you should redirect stdout and\r
+stderr in xsession. While you’re at it, putting each run of i3 in a separate\r
+log file with date/time in it is a good idea to not get confused about the\r
+different log files later on.</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>exec /usr/bin/i3 -V -d all >/home/michael/i3/i3log-$(date +'%F-%k-%M-%S') 2>&1</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_enabling_core_dumps">2. Enabling core dumps</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>When i3 crashes, often you have the chance of getting a <em>core dump</em> (an image\r
+of the memory of the i3 process which can be loaded into a debugger). To get a\r
+core dump, you have to make sure that the user limit for core dump files is set\r
+high enough. Many systems ship with a default value which even forbids core\r
+dumps completely. To disable the limit completely and thus enable core dumps,\r
+use the following command (in your .xsession, before starting i3):</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>ulimit -c unlimited</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Furthermore, to easily recognize core dumps and allow multiple of them, you\r
+should set a custom core dump filename pattern, using a command like the\r
+following:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>sudo sysctl -w kernel.core_pattern=core.%e.%p</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This will generate files which have the executable’s file name (%e) and the\r
+process id (%p) in it. You can save this setting across reboots using\r
+<tt>/etc/sysctl.conf</tt>.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_compiling_with_debug_symbols">3. Compiling with debug symbols</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>To actually get useful core dumps, you should make sure that your version of i3\r
+is compiled with debug symbols, that is, that they are not stripped during the\r
+build process. You can check whether your executable contains symbols by\r
+issuing the following command:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>file $(which i3)</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>You should get an output like this:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>/usr/bin/i3: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically\r
+linked (uses shared libs), for GNU/Linux 2.6.18, not stripped</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Notice the <tt>not stripped</tt>, which is the important part. If you have a version\r
+which is stripped, please have a look if your distribution provides debug\r
+symbols (package <tt>i3-wm-dbg</tt> on Debian for example) or if you can turn off\r
+stripping. If nothing helps, please build i3 from source.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_generating_a_backtrace">4. Generating a backtrace</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Once you have made sure that your i3 is compiled with debug symbols and that\r
+core dumps are enabled, you can start making sense out of the core dumps.</p></div>\r
+<div class="paragraph"><p>Because the core dump depends on the original executable (and its debug\r
+symbols), please do this as soon as you encounter the problem. If you\r
+re-compile i3, your core dump might be useless afterwards.</p></div>\r
+<div class="paragraph"><p>Please install <tt>gdb</tt>, a debugger for C. No worries, you don’t need to learn it\r
+now. Start gdb using the following command (replacing the actual name of the\r
+core dump of course):</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>gdb $(which i3) core.i3.3849</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Then, generate a backtrace using:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>backtrace full</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_sending_bug_reports_debugging_on_irc">5. Sending bug reports/debugging on IRC</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>When sending bug reports, please paste the relevant part of the log (if in\r
+doubt, please send us rather too much information than too less) and the whole\r
+backtrace (if there was a core dump).</p></div>\r
+<div class="paragraph"><p>When debugging with us in IRC, be prepared to use a so called nopaste service\r
+such as <a href="http://nopaste.info">http://nopaste.info</a> or <a href="http://pastebin.com">http://pastebin.com</a> because pasting large\r
+amounts of text in IRC sometimes leads to incomplete lines (servers have line\r
+length limitations) or flood kicks.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:28:10 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: Hacking i3: How To</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>Hacking i3: How To</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">December 2009</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This document is intended to be the first thing you read before looking and/or\r
+touching i3’s source code. It should contain all important information to help\r
+you understand why things are like they are. If it does not mention something\r
+you find necessary, please do not hesitate to contact me.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_window_managers">1. Window Managers</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>A window manager is not necessarily needed to run X, but it is usually used in\r
+combination with X to facilitate some things. The window manager’s job is to\r
+take care of the placement of windows, to provide the user with some mechanisms\r
+to change the position/size of windows and to communicate with clients to a\r
+certain extent (for example handle fullscreen requests of clients such as\r
+MPlayer).</p></div>\r
+<div class="paragraph"><p>There are no different contexts in which X11 clients run, so a window manager\r
+is just another client, like all other X11 applications. However, it handles\r
+some events which normal clients usually don’t handle.</p></div>\r
+<div class="paragraph"><p>In the case of i3, the tasks (and order of them) are the following:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Grab the key bindings (events will be sent upon keypress/keyrelease)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Iterate through all existing windows (if the window manager is not started as\r
+ the first client of X) and manage them (reparent them, create window\r
+ decorations, etc.)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+When new windows are created, manage them\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle the client’s <tt>_WM_STATE</tt> property, but only the <tt>_WM_STATE_FULLSCREEN</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle the client’s <tt>WM_NAME</tt> property\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle the client’s size hints to display them proportionally\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle the client’s urgency hint\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle enter notifications (focus follows mouse)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle button (as in mouse buttons) presses for focus/raise on click\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Handle expose events to re-draw own windows such as decorations\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+React to the user’s commands: Change focus, Move windows, Switch workspaces,\r
+ Change the layout mode of a container (default/stacking/tabbed), start a new\r
+ application, restart the window manager\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p>In the following chapters, each of these tasks and their implementation details\r
+will be discussed.</p></div>\r
+<div class="sect2">\r
+<h3 id="_tiling_window_managers">1.1. Tiling window managers</h3>\r
+<div class="paragraph"><p>Traditionally, there are two approaches to managing windows: The most common\r
+one nowadays is floating, which means the user can freely move/resize the\r
+windows. The other approach is called tiling, which means that your window\r
+manager distributes windows to use as much space as possible while not\r
+overlapping each other.</p></div>\r
+<div class="paragraph"><p>The idea behind tiling is that you should not need to waste your time\r
+moving/resizing windows while you usually want to get some work done. After\r
+all, most users sooner or later tend to lay out their windows in a way which\r
+corresponds to tiling or stacking mode in i3. Therefore, why not let i3 do this\r
+for you? Certainly, it’s faster than you could ever do it.</p></div>\r
+<div class="paragraph"><p>The problem with most tiling window managers is that they are too unflexible.\r
+In my opinion, a window manager is just another tool, and similar to vim which\r
+can edit all kinds of text files (like source code, HTML, …) and is not limited\r
+to a specific file type, a window manager should not limit itself to a certain\r
+layout (like dwm, awesome, …) but provide mechanisms for you to easily create\r
+the layout you need at the moment.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_the_layout_table">1.2. The layout table</h3>\r
+<div class="paragraph"><p>To accomplish flexible layouts, we decided to simply use a table. The table\r
+grows and shrinks as you need it. Each cell holds a container which then holds\r
+windows (see picture below). You can use different layouts for each container\r
+(default layout and stacking layout).</p></div>\r
+<div class="paragraph"><p>So, when you open a terminal and immediately open another one, they reside in\r
+the same container, in default layout. The layout table has exactly one column,\r
+one row and therefore one cell. When you move one of the terminals to the\r
+right, the table needs to grow. It will be expanded to two columns and one row.\r
+This enables you to have different layouts for each container. The table then\r
+looks like this:</p></div>\r
+<div class="tableblock">\r
+<table rules="all"\r
+width="15%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<col width="50%" />\r
+<col width="50%" />\r
+<tbody>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">T1</p></td>\r
+<td align="center" valign="top"><p class="table">T2</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>When moving terminal 2 to the bottom, the table will be expanded again.</p></div>\r
+<div class="tableblock">\r
+<table rules="all"\r
+width="15%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<col width="50%" />\r
+<col width="50%" />\r
+<tbody>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">T1</p></td>\r
+<td align="center" valign="top"><p class="table"></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center" valign="top"><p class="table"></p></td>\r
+<td align="center" valign="top"><p class="table">T2</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>You can really think of the layout table like a traditional HTML table, if\r
+you’ve ever designed one. Especially col- and rowspan work similarly. Below,\r
+you see an example of colspan=2 for the first container (which has T1 as\r
+window).</p></div>\r
+<div class="tableblock">\r
+<table rules="all"\r
+width="15%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<col width="100%" />\r
+<tbody>\r
+<tr>\r
+<td align="center" valign="top"><div><div class="literalblock">\r
+<div class="content">\r
+<pre><tt>T1</tt></pre>\r
+</div></div></div></td>\r
+</tr>\r
+<tr>\r
+<td align="center" valign="top"><div><div class="tableblock">\r
+<table rules="all"\r
+width="100%"\r
+frame="void"\r
+cellspacing="0" cellpadding="4">\r
+<col width="50%" />\r
+<col width="50%" />\r
+<tbody>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">T2</p></td>\r
+<td align="center" valign="top"><p class="table">T3</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div></div></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>Furthermore, you can freely resize table cells.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_files">2. Files</h2>\r
+<div class="sectionbody">\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+include/data.h\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains data definitions used by nearly all files. You really need to read\r
+this first.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+include/*.h\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains forward definitions for all public functions, as well as\r
+doxygen-compatible comments (so if you want to get a bit more of the big\r
+picture, either browse all header files or use doxygen if you prefer that).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/cfgparse.l\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains the lexer for i3’s configuration file, written for <tt>flex(1)</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/cfgparse.y\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains the parser for i3’s configuration file, written for <tt>bison(1)</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/click.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all functions which handle mouse button clicks (right mouse button\r
+clicks initiate resizing and thus are relatively complex).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/client.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all functions which are specific to a certain client (make it\r
+fullscreen, see if its class/name matches a pattern, kill it, …).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/commands.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Parsing commands and actually executing them (focusing, moving, …).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/config.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Parses the configuration file.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/debug.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains debugging functions to print unhandled X events.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/floating.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains functions for floating mode (mostly resizing/dragging).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/handlers.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all handlers for all kinds of X events (new window title, new hints,\r
+unmapping, key presses, button presses, …).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/ipc.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains code for the IPC interface.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/layout.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Renders your layout (screens, workspaces, containers).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/mainx.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Initializes the window manager.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/manage.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Looks at existing or new windows and decides whether to manage them. If so, it\r
+reparents the window and inserts it into our data structures.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/resize.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains the functions to resize columns/rows in the table.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/table.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Manages the most important internal data structure, the design table.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/util.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains useful functions which are not really dependant on anything.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/workspace.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all functions related to workspaces (displaying, hiding, renaming…)\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/xcb.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains wrappers to use xcb more easily.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/xinerama.c\r
+</dt>\r
+<dd>\r
+<p>\r
+(Re-)initializes the available screens and converts them to virtual screens\r
+(see below).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_data_structures">3. Data structures</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>See include/data.h for documented data structures. The most important ones are\r
+explained right here.</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="bigpicture.png" alt="The Big Picture" />\r
+</span></p></div>\r
+<div class="paragraph"><p>So, the hierarchy is:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+<strong>Virtual screens</strong> (Screen 0 in this example)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Workspaces</strong> (Workspace 1 in this example)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Table</strong> (There can only be one table per Workspace)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Container</strong> (left and right in this example)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Client</strong> (The two clients in the left container)\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="sect2">\r
+<h3 id="_virtual_screens">3.1. Virtual screens</h3>\r
+<div class="paragraph"><p>A virtual screen (type <tt>i3Screen</tt>) is generated from the connected screens\r
+obtained through Xinerama. The difference to the raw Xinerama monitors as seen\r
+when using <tt>xrandr(1)</tt> is that it falls back to the lowest common resolution of\r
+the logical screens.</p></div>\r
+<div class="paragraph"><p>For example, if your notebook has 1280x800 and you connect a video projector\r
+with 1024x768, set up in clone mode (<tt>xrandr --output VGA --mode 1024x768\r
+--same-as LVDS</tt>), i3 will have one virtual screen.</p></div>\r
+<div class="paragraph"><p>However, if you configure it using <tt>xrandr --output VGA --mode 1024x768\r
+--right-of LVDS</tt>, i3 will generate two virtual screens. For each virtual\r
+screen, a new workspace will be assigned. New workspaces are created on the\r
+screen you are currently on.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_workspace">3.2. Workspace</h3>\r
+<div class="paragraph"><p>A workspace is identified by its number. Basically, you could think of\r
+workspaces as different desks in your office, if you like the desktop\r
+methaphor. They just contain different sets of windows and are completely\r
+separate of each other. Other window managers also call this “Virtual\r
+desktops”.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_the_layout_table_2">3.3. The layout table</h3>\r
+<div class="paragraph"><p>Each workspace has a table, which is just a two-dimensional dynamic array\r
+containing Containers (see below). This table grows and shrinks as you need it\r
+(by moving windows to the right you can create a new column in the table, by\r
+moving them to the bottom you create a new row).</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_container">3.4. Container</h3>\r
+<div class="paragraph"><p>A container is the content of a table’s cell. It holds an arbitrary amount of\r
+windows and has a specific layout (default layout, stack layout or tabbed\r
+layout). Containers can consume multiple table cells by modifying their\r
+colspan/rowspan attribute.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_client">3.5. Client</h3>\r
+<div class="paragraph"><p>A client is x11-speak for a window.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_list_queue_macros">4. List/queue macros</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>i3 makes heavy use of the list macros defined in BSD operating systems. To\r
+ensure that the operating system on which i3 is compiled has all the expected\r
+features, i3 comes with <tt>include/queue.h</tt>. On BSD systems, you can use man\r
+<tt>queue(3)</tt>. On Linux, you have to use google (or read the source).</p></div>\r
+<div class="paragraph"><p>The lists used are <tt>SLIST</tt> (single linked lists), <tt>CIRCLEQ</tt> (circular\r
+queues) and TAILQ (tail queues). Usually, only forward traversal is necessary,\r
+so an <tt>SLIST</tt> works fine. If inserting elements at arbitrary positions or at\r
+the end of a list is necessary, a <tt>TAILQ</tt> is used instead. However, for the\r
+windows inside a container, a <tt>CIRCLEQ</tt> is necessary to go from the currently\r
+selected window to the window above/below.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_naming_conventions">5. Naming conventions</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>There is a row of standard variables used in many events. The following names\r
+should be chosen for those:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+“conn” is the xcb_connection_t\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+“event” is the event of the particular type\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+“container” names a container\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+“client” names a client, for example when using a <tt>CIRCLEQ_FOREACH</tt>\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_startup_src_mainx_c_main">6. Startup (src/mainx.c, main())</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Establish the xcb connection\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Check for XKB extension on the separate X connection\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Check for Xinerama screens\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Grab the keycodes for which bindings exist\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Manage all existing windows\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Enter the event loop\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_keybindings">7. Keybindings</h2>\r
+<div class="sectionbody">\r
+<div class="sect2">\r
+<h3 id="_grabbing_the_bindings">7.1. Grabbing the bindings</h3>\r
+<div class="paragraph"><p>Grabbing the bindings is quite straight-forward. You pass X your combination of\r
+modifiers and the keycode you want to grab and whether you want to grab them\r
+actively or passively. Most bindings (everything except for bindings using\r
+Mode_switch) are grabbed passively, that is, just the window manager gets the\r
+event and cannot replay it.</p></div>\r
+<div class="paragraph"><p>We need to grab bindings that use Mode_switch actively because of a bug in X.\r
+When the window manager receives the keypress/keyrelease event for an actively\r
+grabbed keycode, it has to decide what to do with this event: It can either\r
+replay it so that other applications get it or it can prevent other\r
+applications from receiving it.</p></div>\r
+<div class="paragraph"><p>So, why do we need to grab keycodes actively? Because X does not set the\r
+state-property of keypress/keyrelease events properly. The Mode_switch bit is\r
+not set and we need to get it using XkbGetState. This means we cannot pass X\r
+our combination of modifiers containing Mode_switch when grabbing the key and\r
+therefore need to grab the keycode itself without any modifiers. This means,\r
+if you bind Mode_switch + keycode 38 ("a"), i3 will grab keycode 38 ("a") and\r
+check on each press of "a" if the Mode_switch bit is set using XKB. If yes, it\r
+will handle the event, if not, it will replay the event.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_handling_a_keypress">7.2. Handling a keypress</h3>\r
+<div class="paragraph"><p>As mentioned in "Grabbing the bindings", upon a keypress event, i3 first gets\r
+the correct state.</p></div>\r
+<div class="paragraph"><p>Then, it looks through all bindings and gets the one which matches the received\r
+event.</p></div>\r
+<div class="paragraph"><p>The bound command is parsed directly in command mode.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_manage_windows_src_mainx_c_manage_window_and_reparent_window">8. Manage windows (src/mainx.c, manage_window() and reparent_window())</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p><tt>manage_window()</tt> does some checks to decide whether the window should be\r
+managed at all:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Windows have to be mapped, that is, visible on screen\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The override_redirect must not be set. Windows with override_redirect shall\r
+ not be managed by a window manager\r
+</p>\r
+</li>\r
+</ul></div>\r
+<div class="paragraph"><p>Afterwards, i3 gets the intial geometry and reparents the window (see\r
+<tt>reparent_window()</tt>) if it wasn’t already managed.</p></div>\r
+<div class="paragraph"><p>Reparenting means that for each window which is reparented, a new window,\r
+slightly larger than the original one, is created. The original window is then\r
+reparented to the bigger one (called "frame").</p></div>\r
+<div class="paragraph"><p>After reparenting, the window type (<tt>_NET_WM_WINDOW_TYPE</tt>) is checked to see\r
+whether this window is a dock (<tt>_NET_WM_WINDOW_TYPE_DOCK</tt>), like dzen2 for\r
+example. Docks are handled differently, they don’t have decorations and are not\r
+assigned to a specific container. Instead, they are positioned at the bottom\r
+of the screen. To get the height which needsd to be reserved for the window,\r
+the <tt>_NET_WM_STRUT_PARTIAL</tt> property is used.</p></div>\r
+<div class="paragraph"><p>Furthermore, the list of assignments (to other workspaces, which may be on\r
+other screens) is checked. If the window matches one of the user’s criteria,\r
+it may either be put in floating mode or moved to a different workspace. If the\r
+target workspace is not visible, the window will not be mapped.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_what_happens_when_an_application_is_started">9. What happens when an application is started?</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>i3 does not care for applications. All it notices is when new windows are\r
+mapped (see <tt>src/handlers.c</tt>, <tt>handle_map_request()</tt>). The window is then\r
+reparented (see section "Manage windows").</p></div>\r
+<div class="paragraph"><p>After reparenting the window, <tt>render_layout()</tt> is called which renders the\r
+internal layout table. The new window has been placed in the currently focused\r
+container and therefore the new window and the old windows (if any) need to be\r
+moved/resized so that the currently active layout (default/stacking/tabbed mode)\r
+is rendered correctly. To move/resize windows, a window is “configured” in\r
+X11-speak.</p></div>\r
+<div class="paragraph"><p>Some applications, such as MPlayer obviously assume the window manager is\r
+stupid and try to configure their windows by themselves. This generates an\r
+event called configurerequest. i3 handles these events and tells the window the\r
+size it had before the configurerequest (with the exception of not yet mapped\r
+windows, which get configured like they want to, and floating windows, which\r
+can reconfigure themselves).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_net_wm_state">10. _NET_WM_STATE</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Only the _NET_WM_STATE_FULLSCREEN atom is handled. It calls\r
+“toggle_fullscreen()” for the specific client which just configures the\r
+client to use the whole screen on which it currently is. Also, it is set as\r
+fullscreen_client for the i3Screen.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_wm_name">11. WM_NAME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>When the WM_NAME property of a window changes, its decoration (containing the\r
+title) is re-rendered. Note that WM_NAME is in COMPOUND_TEXT encoding which is\r
+totally uncommon and cumbersome. Therefore, the _NET_WM_NAME atom will be used\r
+if present.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_net_wm_name">12. _NET_WM_NAME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Like WM_NAME, this atom contains the title of a window. However, _NET_WM_NAME\r
+is encoded in UTF-8. i3 will recode it to UCS-2 in order to be able to pass it\r
+to X. Using an appropriate font (ISO-10646), you can see most special\r
+characters (every special character contained in your font).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_size_hints">13. Size hints</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Size hints specify the minimum/maximum size for a given window as well as its\r
+aspect ratio. This is important for clients like mplayer, who only set the\r
+aspect ratio and resize their window to be as small as possible (but only with\r
+some video outputs, for example in Xv, while when using x11, mplayer does the\r
+necessary centering for itself).</p></div>\r
+<div class="paragraph"><p>So, when an aspect ratio was specified, i3 adjusts the height of the window\r
+until the size maintains the correct aspect ratio. For the code to do this, see\r
+src/layout.c, function resize_client().</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_rendering_src_layout_c_render_layout_and_render_container">14. Rendering (src/layout.c, render_layout() and render_container())</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>There are several entry points to rendering: <tt>render_layout()</tt>,\r
+<tt>render_workspace()</tt> and <tt>render_container()</tt>. The former one calls\r
+<tt>render_workspace()</tt> for every screen, which in turn will call\r
+<tt>render_container()</tt> for every container inside its layout table. Therefore, if\r
+you need to render only a single container, for example because a window was\r
+removed, added or changed its title, you should directly call\r
+render_container().</p></div>\r
+<div class="paragraph"><p>Rendering consists of two steps: In the first one, in <tt>render_workspace()</tt>, each\r
+container gets its position (screen offset + offset in the table) and size\r
+(container’s width times colspan/rowspan). Then, <tt>render_container()</tt> is called,\r
+which takes different approaches, depending on the mode the container is in:</p></div>\r
+<div class="sect2">\r
+<h3 id="_common_parts">14.1. Common parts</h3>\r
+<div class="paragraph"><p>On the frame (the window which was created around the client’s window for the\r
+decorations), a black rectangle is drawn as a background for windows like\r
+MPlayer, which do not completely fit into the frame.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_default_mode">14.2. Default mode</h3>\r
+<div class="paragraph"><p>Each clients gets the container’s width and an equal amount of height.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_stack_mode">14.3. Stack mode</h3>\r
+<div class="paragraph"><p>In stack mode, a window containing the decorations of all windows inside the\r
+container is placed at the top. The currently focused window is then given the\r
+whole remaining space.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_tabbed_mode">14.4. Tabbed mode</h3>\r
+<div class="paragraph"><p>Tabbed mode is like stack mode, except that the window decorations are drawn\r
+in one single line at the top of the container.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_window_decorations">14.5. Window decorations</h3>\r
+<div class="paragraph"><p>The window decorations consist of a rectangle in the appropriate color (depends\r
+on whether this window is the currently focused one, the last focused one in a\r
+not focused container or not focused at all) forming the background.\r
+Afterwards, two lighter lines are drawn and the last step is drawing the\r
+window’s title (see WM_NAME) onto it.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_fullscreen_windows">14.6. Fullscreen windows</h3>\r
+<div class="paragraph"><p>For fullscreen windows, the <tt>rect</tt> (x, y, width, height) is not changed to\r
+allow the client to easily go back to its previous position. Instead,\r
+fullscreen windows are skipped when rendering.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_resizing_containers">14.7. Resizing containers</h3>\r
+<div class="paragraph"><p>By clicking and dragging the border of a container, you can resize the whole\r
+column (respectively row) which this container is in. This is necessary to keep\r
+the table layout working and consistent.</p></div>\r
+<div class="paragraph"><p>The resizing works similarly to the resizing of floating windows or movement of\r
+floating windows:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+A new, invisible window with the size of the root window is created\r
+ (<tt>grabwin</tt>)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Another window, 2px width and as high as your screen (or vice versa for\r
+ horizontal resizing) is created. Its background color is the border color and\r
+ it is only there to inform the user how big the container will be (it\r
+ creates the impression of dragging the border out of the container).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The <tt>drag_pointer</tt> function of <tt>src/floating.c</tt> is called to grab the pointer\r
+ and enter its own event loop which will pass all events (expose events) but\r
+ motion notify events. This function then calls the specified callback\r
+ (<tt>resize_callback</tt>) which does some boundary checking and moves the helper\r
+ window. As soon as the mouse button is released, this loop will be\r
+ terminated.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The new width_factor for each involved column (respectively row) will be\r
+ calculated.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_user_commands_commandmode_src_commands_c">15. User commands / commandmode (src/commands.c)</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Like in vim, you can control i3 using commands. They are intended to be a\r
+powerful alternative to lots of shortcuts, because they can be combined. There\r
+are a few special commands, which are the following:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+exec <command>\r
+</dt>\r
+<dd>\r
+<p>\r
+Starts the given command by passing it to <tt>/bin/sh</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+restart\r
+</dt>\r
+<dd>\r
+<p>\r
+Restarts i3 by executing <tt>argv[0]</tt> (the path with which you started i3) without\r
+forking.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+w\r
+</dt>\r
+<dd>\r
+<p>\r
+"With". This is used to select a bunch of windows. Currently, only selecting\r
+the whole container in which the window is in, is supported by specifying "w".\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+f, s, d\r
+</dt>\r
+<dd>\r
+<p>\r
+Toggle fullscreen, stacking, default mode for the current window/container.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>The other commands are to be combined with a direction. The directions are h,\r
+j, k and l, like in vim (h = left, j = down, k = up, l = right). When you just\r
+specify the direction keys, i3 will move the focus in that direction. You can\r
+provide "m" or "s" before the direction to move a window respectively or snap.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_gotchas">16. Gotchas</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Forgetting to call <tt>xcb_flush(conn);</tt> after sending a request. This usually\r
+ leads to code which looks like it works fine but which does not work under\r
+ certain conditions.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_using_git_sending_patches">17. Using git / sending patches</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For a short introduction into using git, see\r
+<a href="http://www.spheredev.org/wiki/Git_for_the_lazy">http://www.spheredev.org/wiki/Git_for_the_lazy</a> or, for more documentation, see\r
+<a href="http://git-scm.com/documentation">http://git-scm.com/documentation</a></p></div>\r
+<div class="paragraph"><p>When you want to send a patch because you fixed a bug or implemented a cool\r
+feature (please talk to us before working on features to see whether they are\r
+maybe already implemented, not possible for some some reason, or don’t fit\r
+into the concept), please use git to create a patchfile.</p></div>\r
+<div class="paragraph"><p>First of all, update your working copy to the latest version of the master\r
+branch:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>git pull</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Afterwards, make the necessary changes for your bugfix/feature. Then, review\r
+the changes using <tt>git diff</tt> (you might want to enable colors in the diff using\r
+<tt>git config diff.color auto</tt>). When you are definitely done, use <tt>git commit\r
+-a</tt> to commit all changes you’ve made.</p></div>\r
+<div class="paragraph"><p>Then, use the following command to generate a patchfile which we can directly\r
+apply to the branch, preserving your commit message and name:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>git format-patch origin</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Just send us the generated file via email.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:29:17 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: IPC interface (interprocess communication)</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>IPC interface (interprocess communication)</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">March 2010</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This document describes how to interface with i3 from a separate process. This\r
+is useful for example to remote-control i3 (to write test cases for example) or\r
+to get various information like the current workspaces to implement an external\r
+workspace bar.</p></div>\r
+<div class="paragraph"><p>The method of choice for IPC in our case is a unix socket because it has very\r
+little overhead on both sides and is usually available without headaches in\r
+most languages. In the default configuration file, no ipc-socket path is\r
+specified and thus no socket is created. The standard path (which <tt>i3-msg</tt> and\r
+<tt>i3-input</tt> use) is <tt>~/.i3/ipc.sock</tt>.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_establishing_a_connection">1. Establishing a connection</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>To establish a connection, simply open the IPC socket. The following code\r
+snippet illustrates this in Perl:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>use IO::Socket::UNIX;\r
+my $sock = IO::Socket::UNIX->new(Peer => '~/.i3/ipc.sock');</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_sending_messages_to_i3">2. Sending messages to i3</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>To send a message to i3, you have to format in the binary message format which\r
+i3 expects. This format specifies a magic string in the beginning to ensure\r
+the integrity of messages (to prevent follow-up errors). Following the magic\r
+string comes the length of the payload of the message as 32-bit integer, and\r
+the type of the message as 32-bit integer (the integers are not converted, so\r
+they are in native byte order).</p></div>\r
+<div class="paragraph"><p>The magic string currently is "i3-ipc" and will only be changed when a change\r
+in the IPC API is done which breaks compatibility (we hope that we don’t need\r
+to do that).</p></div>\r
+<div class="paragraph"><p>Currently implemented message types are the following:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+COMMAND (0)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The payload of the message is a command for i3 (like the commands you\r
+ can bind to keys in the configuration file) and will be executed\r
+ directly after receiving it. There is no reply to this message.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+GET_WORKSPACES (1)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Gets the current workspaces. The reply will be a JSON-encoded list of\r
+ workspaces (see the reply section).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+SUBSCRIBE (2)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Subscribes your connection to certain events. See <a href="#events">[events]</a> for a\r
+ description of this message and the concept of events.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+GET_OUTPUTS (3)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Gets the current outputs. The reply will be a JSON-encoded list of outputs\r
+ (see the reply section).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>So, a typical message could look like this:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>"i3-ipc" <message length> <message type> <payload></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Or, as a hexdump:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>00000000 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex|\r
+00000010 69 74 0a |it.|</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>To generate and send such a message, you could use the following code in Perl:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>sub format_ipc_command {\r
+ my ($msg) = @_;\r
+ my $len;\r
+ # Get the real byte count (vs. amount of characters)\r
+ { use bytes; $len = length($msg); }\r
+ return "i3-ipc" . pack("LL", $len, 0) . $msg;\r
+}\r
+\r
+$sock->write(format_ipc_command("exit"));</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_receiving_replies_from_i3">3. Receiving replies from i3</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Replies from i3 usually consist of a simple string (the length of the string\r
+is the message_length, so you can consider them length-prefixed) which in turn\r
+contain the JSON serialization of a data structure. For example, the\r
+GET_WORKSPACES message returns an array of workspaces (each workspace is a map\r
+with certain attributes).</p></div>\r
+<div class="sect2">\r
+<h3 id="_reply_format">3.1. Reply format</h3>\r
+<div class="paragraph"><p>The reply format is identical to the normal message format. There also is\r
+the magic string, then the message length, then the message type and the\r
+payload.</p></div>\r
+<div class="paragraph"><p>The following reply types are implemented:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+COMMAND (0)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Confirmation/Error code for the COMMAND message.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+GET_WORKSPACES (1)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Reply to the GET_WORKSPACES message.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+SUBSCRIBE (2)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Confirmation/Error code for the SUBSCRIBE message.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+GET_OUTPUTS (3)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Reply to the GET_OUTPUTS message.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_command_reply">3.2. COMMAND reply</h3>\r
+<div class="paragraph"><p>The reply consists of a single serialized map. At the moment, the only\r
+property is <tt>success (bool)</tt>, but this will be expanded in future versions.</p></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>{ "success": true }</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_get_workspaces_reply">3.3. GET_WORKSPACES reply</h3>\r
+<div class="paragraph"><p>The reply consists of a serialized list of workspaces. Each workspace has the\r
+following properties:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+num (integer)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The logical number of the workspace. Corresponds to the command\r
+ to switch to this workspace.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+name (string)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The name of this workspace (by default num+1), as changed by the\r
+ user. Encoded in UTF-8.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+visible (boolean)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Whether this workspace is currently visible on an output (multiple\r
+ workspaces can be visible at the same time).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+focused (boolean)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Whether this workspace currently has the focus (only one workspace\r
+ can have the focus at the same time).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+urgent (boolean)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Whether a window on this workspace has the "urgent" flag set.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+rect (map)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The rectangle of this workspace (equals the rect of the output it\r
+ is on), consists of x, y, width, height.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+output (string)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The video output this workspace is on (LVDS1, VGA1, …).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>[\r
+ {\r
+ "num": 0,\r
+ "name": "1",\r
+ "visible": true,\r
+ "focused": true,\r
+ "urgent": false,\r
+ "rect": {\r
+ "x": 0,\r
+ "y": 0,\r
+ "width": 1280,\r
+ "height": 800\r
+ },\r
+ "output": "LVDS1"\r
+ },\r
+ {\r
+ "num": 1,\r
+ "name": "2",\r
+ "visible": false,\r
+ "focused": false,\r
+ "urgent": false,\r
+ "rect": {\r
+ "x": 0,\r
+ "y": 0,\r
+ "width": 1280,\r
+ "height": 800\r
+ },\r
+ "output": "LVDS1"\r
+ }\r
+]</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_subscribe_reply">3.4. SUBSCRIBE reply</h3>\r
+<div class="paragraph"><p>The reply consists of a single serialized map. The only property is\r
+<tt>success (bool)</tt>, indicating whether the subscription was successful (the\r
+default) or whether a JSON parse error occurred.</p></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>{ "success": true }</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_get_outputs_reply">3.5. GET_OUTPUTS reply</h3>\r
+<div class="paragraph"><p>The reply consists of a serialized list of outputs. Each output has the\r
+following properties:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+name (string)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The name of this output (as seen in <tt>xrandr(1)</tt>). Encoded in UTF-8.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+active (boolean)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Whether this output is currently active (has a valid mode).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+current_workspace (integer)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The current workspace which is visible on this output. <tt>null</tt> if the\r
+ output is not active.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+rect (map)\r
+</dt>\r
+<dd>\r
+<p>\r
+ The rectangle of this output (equals the rect of the output it\r
+ is on), consists of x, y, width, height.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>[\r
+ {\r
+ "name": "LVDS1",\r
+ "active": true,\r
+ "current_workspace": 4,\r
+ "rect": {\r
+ "x": 0,\r
+ "y": 0,\r
+ "width": 1280,\r
+ "height": 800\r
+ }\r
+ },\r
+ {\r
+ "name": "VGA1",\r
+ "active": true,\r
+ "current_workspace": 1,\r
+ "rect": {\r
+ "x": 1280,\r
+ "y": 0,\r
+ "width": 1280,\r
+ "height": 1024\r
+ },\r
+ }\r
+]</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_events">4. Events</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph" id="events"><p>To get informed when certain things happen in i3, clients can subscribe to\r
+events. Events consist of a name (like "workspace") and an event reply type\r
+(like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format\r
+as replies to specific commands. However, the highest bit of the message type\r
+is set to 1 to indicate that this is an event reply instead of a normal reply.</p></div>\r
+<div class="paragraph"><p>Caveat: As soon as you subscribe to an event, it is not guaranteed any longer\r
+that the requests to i3 are processed in order. This means, the following\r
+situation can happen: You send a GET_WORKSPACES request but you receive a\r
+"workspace" event before receiving the reply to GET_WORKSPACES. If your\r
+program does not want to cope which such kinds of race conditions (an\r
+event based library may not have a problem here), I suggest you create a\r
+separate connection to receive events.</p></div>\r
+<div class="sect2">\r
+<h3 id="_subscribing_to_events">4.1. Subscribing to events</h3>\r
+<div class="paragraph"><p>By sending a message of type SUBSCRIBE with a JSON-encoded array as payload\r
+you can register to an event.</p></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>type: SUBSCRIBE\r
+payload: [ "workspace", "focus" ]</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_available_events">4.2. Available events</h3>\r
+<div class="paragraph"><p>The numbers in parenthesis is the event type (keep in mind that you need to\r
+strip the highest bit first).</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+workspace (0)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Sent when the user switches to a different workspace, when a new\r
+ workspace is initialized or when a workspace is removed (because the\r
+ last client vanished).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+output (1)\r
+</dt>\r
+<dd>\r
+<p>\r
+ Sent when RandR issues a change notification (of either screens,\r
+ outputs, CRTCs or output properties).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># the appropriate 4 bytes read from the socket are stored in $input\r
+\r
+# unpack a 32-bit unsigned integer\r
+my $message_type = unpack("L", $input);\r
+\r
+# check if the highest bit is 1\r
+my $is_event = (($message_type >> 31) == 1);\r
+\r
+# use the other bits\r
+my $event_type = ($message_type & 0x7F);\r
+\r
+if ($is_event) {\r
+ say "Received event of type $event_type";\r
+}</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_workspace_event">4.3. workspace event</h3>\r
+<div class="paragraph"><p>This event consists of a single serialized map containing a property\r
+<tt>change (string)</tt> which indicates the type of the change ("focus", "init",\r
+"empty", "urgent").</p></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>{ "change": "focus" }</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_output_event">4.4. output event</h3>\r
+<div class="paragraph"><p>This event consists of a single serialized map containing a property\r
+<tt>change (string)</tt> which indicates the type of the change (currently only\r
+"unspecified").</p></div>\r
+<div class="paragraph"><p><strong>Example:</strong></p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>{ "change": "unspecified" }</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_see_also">5. See also</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For some languages, libraries are available (so you don’t have to implement\r
+all this on your own). This list names some (if you wrote one, please let me\r
+know):</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+C\r
+</dt>\r
+<dd>\r
+<p>\r
+ i3 includes a headerfile <tt>i3/ipc.h</tt> which provides you all constants.\r
+ However, there is no library yet.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Ruby\r
+</dt>\r
+<dd>\r
+<p>\r
+ <a href="http://github.com/badboy/i3-ipc">http://github.com/badboy/i3-ipc</a>\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Perl\r
+</dt>\r
+<dd>\r
+<p>\r
+ <a href="http://search.cpan.org/search?query=AnyEvent::I3">http://search.cpan.org/search?query=AnyEvent::I3</a>\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Python\r
+</dt>\r
+<dd>\r
+<p>\r
+ <a href="http://github.com/thepub/i3ipc">http://github.com/thepub/i3ipc</a>\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:28:12 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: The multi-monitor situation</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>The multi-monitor situation</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">March 2010</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>…or: oh no, I have an nVidia graphics card!</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_the_quick_fix">1. The quick fix</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>If you are using the nVidia binary graphics driver (also known as <em>blob</em>)\r
+you need to use the <tt>--force-xinerama</tt> flag (in your .xsession) when starting\r
+i3, like so:</p></div>\r
+<div class="listingblock">\r
+<div class="title">Example:</div>\r
+<div class="content">\r
+<pre><tt>exec i3 --force-xinerama -V >>~/.i3/i3log 2>&1</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_the_explanation">2. The explanation</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Starting with version 3.ε, i3 uses the RandR (Rotate and Resize) API instead\r
+of Xinerama. The reason for this, is that RandR provides more information\r
+about your outputs and connected screens than Xinerama does. To be specific,\r
+the code which handled on-the-fly screen reconfiguration (meaning without\r
+restarting the X server) was a very messy heuristic and most of the time did\r
+not work correctly — that is just not possible with the little information\r
+Xinerama offers (just a list of screen resolutions, no identifiers for the\r
+screens or any additional information). Xinerama simply was not designed\r
+for dynamic configuration.</p></div>\r
+<div class="paragraph"><p>So RandR came along, as a more powerful alternative (RandR 1.2 to be specific).\r
+It offers all of Xinerama’s possibilities and lots more. Using the RandR API\r
+made our code much more robust and clean. Also, you can now reliably assign\r
+workspaces to output names instead of some rather unreliable screen identifier\r
+(position inside the list of screens, which could change, and so on…).</p></div>\r
+<div class="paragraph"><p>As RandR has been around for about three years as of this writing, it seemed\r
+like a very good idea to us, and it still is a very good one. What we did not\r
+expect, however, was the nVidia binary driver. It still does not support RandR\r
+(as of March 2010), even though nVidia has announced that it will support RandR\r
+eventually. What does this mean for you, if you are stuck with the binary\r
+driver for some reason (say the free drivers don’t work with your card)? First\r
+of all, you are stuck with TwinView and cannot use <tt>xrandr</tt>. While this ruins\r
+the user experience, the more grave problem is that the nVidia driver not only\r
+does not support dynamic configuration using RandR, it also does not expose\r
+correct multi-monitor information via the RandR API. So, in some setups, i3\r
+will not find any screens; in others, it will find one large screen which\r
+actually contains both of your physical screens (but it will not know that\r
+these are two screens).</p></div>\r
+<div class="paragraph"><p>For this very reason, we decided to implement the following workaround: As\r
+long as the nVidia driver does not support RandR, an option called\r
+<tt>--force-xinerama</tt> is available in i3. This option gets the list of screens\r
+<strong>once</strong> when starting, and never updates it. As the nVidia driver cannot do\r
+dynamic configuration anyways, this is not a big deal.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_see_also">3. See also</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For more information on how to use multi-monitor setups, see the i3 User’s\r
+Guide.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:28:19 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: Tree branch: Migrating</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>Tree branch: Migrating</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">November 2010</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_introduction">1. Introduction</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>The tree branch (referring to a branch of i3 in the git repository) is the new\r
+version of i3. Due to the very deep changes and heavy refactoring of the source\r
+source, we decided to develop it in a seperate branch (instead of using the\r
+next/master-branch system like before).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_current_status">2. Current status</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Currently, the code is mostly working. Some of the i3 core developers have been\r
+using the tree branch version for a few weeks now. So, if you are eager to try\r
+out the new features and help us find bugs, give it a try!</p></div>\r
+<div class="paragraph"><p>At the same time, a word of warning is appropriate: This version of i3 might\r
+crash unexpectedly, so please be careful with important data (do not work for\r
+two days without saving…).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_getting_the_latest_tree_branch_version">3. Getting the latest tree branch version</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Check out the latest version:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>$ git clone -b tree git://code.stapelberg.de/i3</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Then build and install it (has the same dependencies as the latest stable i3\r
+version):</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>$ cd i3\r
+$ make\r
+$ sudo cp i3 /usr/bin/i3-tree</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>…and execute <tt>i3-tree</tt> instead of <tt>i3</tt> in your Xsession.</p></div>\r
+<div class="paragraph"><p><strong>IMPORTANT:</strong> Please note that configuration file compatibility is not yet done.\r
+So, make sure you use/customize the provided <tt>i3.config</tt> file.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_tree">4. Tree</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>The most important change and reason for the name is that i3 stores all\r
+information about the X11 outputs, workspaces and layout of the windows on them\r
+in a tree. The root node is the X11 root window, followed by the X11 outputs,\r
+then workspaces and finally the windows themselve. In previous versions of i3\r
+we had multiple lists (of outputs, workspaces) and a table for each workspace.\r
+That approach turned out to be complicated to use (snapping), understand and\r
+implement.</p></div>\r
+<div class="sect2">\r
+<h3 id="_the_tree_consists_of_containers">4.1. The tree consists of Containers</h3>\r
+<div class="paragraph"><p>The building blocks of our tree are so called <tt>Containers</tt>. A <tt>Container</tt> can\r
+host a window (meaning an X11 window, one that you can actually see and use,\r
+like a browser). Alternatively, it could contain one or more <tt>Containers</tt>. A\r
+simple example is the workspace: When you start i3 with a single monitor, a\r
+single workspace and you open two terminal windows, you will end up with a tree\r
+like this:</p></div>\r
+<div class="imageblock" style="float:right;">\r
+<div class="content">\r
+<img src="tree-layout2.png" alt="layout2" />\r
+</div>\r
+</div>\r
+<div class="imageblock">\r
+<div class="content">\r
+<img src="tree-shot4.png" alt="shot4" />\r
+</div>\r
+<div class="title">Figure 1. Two terminals on standard workspace</div>\r
+</div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_orientation_and_split_containers">4.2. Orientation and Split Containers</h3>\r
+<div class="paragraph" id="OrientationSplit"><p>It is only natural to use so-called <tt>Split Containers</tt> in order to build a\r
+layout when using a tree as data structure. In i3, every <tt>Container</tt> has an\r
+orientation (horizontal, vertical or unspecified). So, in our example with the\r
+workspace, the default orientation of the workspace <tt>Container</tt> is horizontal\r
+(most monitors are widescreen nowadays). If you change the orientation to\r
+vertical (<tt>Alt+v</tt> in the default config) and <strong>then</strong> open two terminals, i3 will\r
+configure your windows like this:</p></div>\r
+<div class="imageblock">\r
+<div class="content">\r
+<img src="tree-shot2.png" alt="shot2" />\r
+</div>\r
+<div class="title">Figure 2. Vertical Workspace Orientation</div>\r
+</div>\r
+<div class="paragraph"><p>An interesting new feature of the tree branch is the ability to split anything:\r
+Let’s assume you have two terminals on a workspace (with horizontal\r
+orientation), focus is on the right terminal. Now you want to open another\r
+terminal window below the current one. If you would just open a new terminal\r
+window, it would show up to the right due to the horizontal workspace\r
+orientation. Instead, press <tt>Alt+v</tt> to create a <tt>Vertical Split Container</tt> (to\r
+open a <tt>Horizontal Split Container</tt>, use <tt>Alt+h</tt>). Now you can open a new\r
+terminal and it will open below the current one:</p></div>\r
+<div class="imageblock" style="float:right;">\r
+<div class="content">\r
+<img src="tree-layout1.png" alt="Layout" />\r
+</div>\r
+</div>\r
+<div class="imageblock">\r
+<div class="content">\r
+<img src="tree-shot1.png" alt="shot" />\r
+</div>\r
+<div class="title">Figure 3. Vertical Split Container</div>\r
+</div>\r
+<div style="clear:both;"></div>\r
+<div class="paragraph"><p>You probably guessed it already: There is no limit on how deep your hierarchy\r
+of splits can be.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_level_up">4.3. Level up</h3>\r
+<div class="paragraph"><p>Let’s stay with our example from above. We have a terminal on the left and two\r
+vertically split terminals on the right, focus is on the bottom right one. When\r
+you open a new terminal, it will open below the current one.</p></div>\r
+<div class="paragraph"><p>So, how can you open a new terminal window to the <strong>right</strong> of the current one?\r
+The solution is to use <tt>level up</tt>, which will focus the <tt>Parent Container</tt> of\r
+the current <tt>Container</tt>. In this case, you would focus the <tt>Vertical Split\r
+Container</tt> which is <strong>inside</strong> the horizontally oriented workspace. Thus, now new\r
+windows will be opened to the right of the <tt>Vertical Split Container</tt>:</p></div>\r
+<div class="imageblock">\r
+<div class="content">\r
+<img src="tree-shot3.png" alt="shot3" />\r
+</div>\r
+<div class="title">Figure 4. Level Up, then open new terminal</div>\r
+</div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_commands">5. Commands</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>The authoritive reference for commands is <tt>src/cmdparse.y</tt>. You can also find\r
+most commands in <tt>i3.config</tt>. Here comes a short overview over the important\r
+commands:</p></div>\r
+<div class="sect2">\r
+<h3 id="_manipulating_layout">5.1. Manipulating layout</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>layout <default|stacked|tabbed></tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_focus">5.2. Changing Focus</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>next <horizontal|vertical>\r
+prev <horizontal|vertical></tt></pre>\r
+</div></div>\r
+<div class="listingblock">\r
+<div class="title">Examples:</div>\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+Left prev h\r
+bindsym Mod1+Right next h\r
+bindsym Mod1+Down next v\r
+bindsym Mod1+Up prev v</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_moving">5.3. Moving</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>move <before|after> <horizontal|vertical></tt></pre>\r
+</div></div>\r
+<div class="listingblock">\r
+<div class="title">Examples:</div>\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+Shift+Left move before h\r
+bindsym Mod1+Shift+Right move after h\r
+bindsym Mod1+Shift+Down move before v\r
+bindsym Mod1+Shift+Up move after v</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_workspace">5.4. Changing workspace</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace <name></tt></pre>\r
+</div></div>\r
+<div class="listingblock">\r
+<div class="title">Examples:</div>\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+1 workspace 1\r
+bindsym Mod1+2 workspace 2\r
+…</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_moving_containers_to_workspaces">5.5. Moving Containers to workspaces</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>move workspace <name></tt></pre>\r
+</div></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+Shift+1 move workspace 1\r
+bindsym Mod1+Shift+2 move workspace 2\r
+…</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_border_style">5.6. Changing border style</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>border <normal|none|1pixel></tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_container_mode">5.7. Changing container mode</h3>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>mode <tiling|floating|toggle></tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_the_rest">6. The rest</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>What is not mentioned here explicitly is either unchanged and can be read in\r
+the <a href="http://i3.zekjur.net/docs/userguide.html">i3 User’s Guide</a> or it is not yet\r
+implemented.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:29:30 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: i3 User’s Guide</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>i3 User’s Guide</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">March 2010</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This document contains all the information you need to configure and use the i3\r
+window manager. If it does not, please contact me on IRC, Jabber or E-Mail and\r
+I’ll help you out.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_default_keybindings">1. Default keybindings</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For the "too long; didn’t read" people, here is an overview of the default\r
+keybindings (click to see the full size image):</p></div>\r
+<div class="paragraph"><p><strong>Keys to use with Mod1 (alt):</strong></p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<a class="image" href="keyboard-layer1.png">\r
+<img src="keyboard-layer1.png" alt="Keys to use with Mod1 (alt)" width="600" />\r
+</a>\r
+</span></p></div>\r
+<div class="paragraph"><p><strong>Keys to use with Shift+Mod1:</strong></p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<a class="image" href="keyboard-layer2.png">\r
+<img src="keyboard-layer2.png" alt="Keys to use with Shift+Mod1" width="600" />\r
+</a>\r
+</span></p></div>\r
+<div class="paragraph"><p>As i3 uses keycodes in the default configuration, it does not matter which\r
+keyboard layout you actually use. The key positions are what matters (of course\r
+you can also use keysymbols, see <a href="#keybindings">[keybindings]</a>).</p></div>\r
+<div class="paragraph"><p>The red keys are the modifiers you need to press (by default), the blue keys\r
+are your homerow.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_using_i3">2. Using i3</h2>\r
+<div class="sectionbody">\r
+<div class="sect2">\r
+<h3 id="_opening_terminals_and_moving_around">2.1. Opening terminals and moving around</h3>\r
+<div class="paragraph"><p>One very basic operation is opening a new terminal. By default, the keybinding\r
+for this is Mod1+Enter, that is Alt+Enter in the default configuration. By\r
+pressing Mod1+Enter, a new terminal will be opened. It will fill the whole\r
+space available on your screen.</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="single_terminal.png" alt="Single terminal" />\r
+</span></p></div>\r
+<div class="paragraph"><p>It is important to keep in mind that i3 uses a table to manage your windows. At\r
+the moment, you have exactly one column and one row which leaves you with one\r
+cell. In this cell there is a container, which is where your new terminal is\r
+opened.</p></div>\r
+<div class="paragraph"><p>If you now open another terminal, you still have only one cell. However, the\r
+container in that cell holds both of your terminals. So, a container is just a\r
+group of clients with a specific layout. Containers can be resized by adjusting\r
+the size of the cell that holds them.</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="two_terminals.png" alt="Two terminals" />\r
+</span></p></div>\r
+<div class="paragraph"><p>To move the focus between the two terminals, you use the direction keys which\r
+you may know from the editor <tt>vi</tt>. However, in i3, your homerow is used for\r
+these keys (in <tt>vi</tt>, the keys are shifted to the left by one for compatibility\r
+with most keyboard layouts). Therefore, <tt>Mod1+J</tt> is left, <tt>Mod1+K</tt> is down,\r
+<tt>Mod1+L</tt> is up and <tt>Mod1+;</tt> is right. So, to switch between the terminals,\r
+use <tt>Mod1+K</tt> or <tt>Mod1+L</tt>.</p></div>\r
+<div class="paragraph"><p>To create a new row/column (and a new cell), you can simply move a terminal (or\r
+any other window) in the direction you want to expand your table. So, let’s\r
+expand the table to the right by pressing <tt>Mod1+Shift+;</tt>.</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="two_columns.png" alt="Two columns" />\r
+</span></p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_container_modes">2.2. Changing container modes</h3>\r
+<div class="paragraph"><p>A container can have the following modes:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+default\r
+</dt>\r
+<dd>\r
+<p>\r
+Windows are sized so that every window gets an equal amount of space in the\r
+container.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+stacking\r
+</dt>\r
+<dd>\r
+<p>\r
+Only the focused window in the container is displayed. You get a list of\r
+windows at the top of the container.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+tabbed\r
+</dt>\r
+<dd>\r
+<p>\r
+The same principle as <tt>stacking</tt>, but the list of windows at the top is only\r
+a single line which is vertically split.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>To switch modes, press <tt>Mod1+e</tt> for default, <tt>Mod1+h</tt> for stacking and\r
+<tt>Mod1+w</tt> for tabbed.</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="modes.png" alt="Container modes" />\r
+</span></p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_toggling_fullscreen_mode_for_a_window">2.3. Toggling fullscreen mode for a window</h3>\r
+<div class="paragraph"><p>To display a window fullscreen or to go out of fullscreen mode again, press\r
+<tt>Mod1+f</tt>.</p></div>\r
+<div class="paragraph"><p>There is also a global fullscreen mode in i3 in which the client will use all\r
+available outputs. To use it, or to get out of it again, press <tt>Mod1+Shift+f</tt>.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_opening_other_applications">2.4. Opening other applications</h3>\r
+<div class="paragraph"><p>Aside from opening applications from a terminal, you can also use the handy\r
+<tt>dmenu</tt> which is opened by pressing <tt>Mod1+v</tt> by default. Just type the name\r
+(or a part of it) of the application which you want to open. The application\r
+typed has to be in your <tt>$PATH</tt> for this to work.</p></div>\r
+<div class="paragraph"><p>Additionally, if you have applications you open very frequently, you can\r
+create a keybinding for starting the application directly. See the section\r
+"Configuring i3" for details.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_closing_windows">2.5. Closing windows</h3>\r
+<div class="paragraph"><p>If an application does not provide a mechanism for closing (most applications\r
+provide a menu, the escape key or a shortcut like <tt>Control+W</tt> to close), you\r
+can press <tt>Mod1+Shift+q</tt> to kill a window. For applications which support\r
+the WM_DELETE protocol, this will correctly close the application (saving\r
+any modifications or doing other cleanup). If the application doesn’t support\r
+the WM_DELETE protocol your X server will kill the window and the behaviour\r
+depends on the application.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_using_workspaces">2.6. Using workspaces</h3>\r
+<div class="paragraph"><p>Workspaces are an easy way to group a set of windows. By default, you are on\r
+the first workspace, as the bar on the bottom left indicates. To switch to\r
+another workspace, press <tt>Mod1+num</tt> where <tt>num</tt> is the number of the workspace\r
+you want to use. If the workspace does not exist yet, it will be created.</p></div>\r
+<div class="paragraph"><p>A common paradigm is to put the web browser on one workspace, communication\r
+applications (<tt>mutt</tt>, <tt>irssi</tt>, …) on another one, and the ones with which you\r
+work, on the third one. Of course, there is no need to follow this approach.</p></div>\r
+<div class="paragraph"><p>If you have multiple screens, a workspace will be created on each screen at\r
+startup. If you open a new workspace, it will be bound to the screen you\r
+created it on. When you switch to a workspace on another screen, i3 will set\r
+focus to that screen.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_moving_windows_to_workspaces">2.7. Moving windows to workspaces</h3>\r
+<div class="paragraph"><p>To move a window to another workspace, simply press <tt>Mod1+Shift+num</tt> where\r
+<tt>num</tt> is (like when switching workspaces) the number of the target workspace.\r
+Similarly to switching workspaces, the target workspace will be created if\r
+it does not yet exist.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_resizing_columns_rows">2.8. Resizing columns/rows</h3>\r
+<div class="paragraph"><p>To resize columns or rows, just grab the border between the two columns/rows\r
+and move it to the wanted size. Please keep in mind that each cell of the table\r
+holds a <tt>container</tt> and thus you cannot horizontally resize single windows. If\r
+you need applications with different horizontal sizes, place them in seperate\r
+cells one above the other.</p></div>\r
+<div class="paragraph"><p>See <a href="#resizingconfig">[resizingconfig]</a> for how to configure i3 to be able to resize\r
+columns/rows with your keyboard.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_restarting_i3_inplace">2.9. Restarting i3 inplace</h3>\r
+<div class="paragraph"><p>To restart i3 inplace (and thus get into a clean state if there is a bug, or\r
+to upgrade to a newer version of i3) you can use <tt>Mod1+Shift+r</tt>. Be aware,\r
+though, that this kills your current layout and all the windows you have opened\r
+will be put in a default container in only one cell. Saving layouts will be\r
+implemented in a later version.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_exiting_i3">2.10. Exiting i3</h3>\r
+<div class="paragraph"><p>To cleanly exit i3 without killing your X server, you can use <tt>Mod1+Shift+e</tt>.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_snapping">2.11. Snapping</h3>\r
+<div class="paragraph"><p>Snapping is a mechanism to increase/decrease the colspan/rowspan of a container.\r
+Colspan/rowspan is the number of columns/rows a specific cell of the table\r
+consumes. This is easier explained by giving an example, so take the following\r
+layout:</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="snapping.png" alt="Snapping example" />\r
+</span></p></div>\r
+<div class="paragraph"><p>To use the full size of your screen, you can now snap container 3 downwards\r
+by pressing <tt>Mod1+Control+k</tt> (or snap container 2 rightwards).</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_floating">2.12. Floating</h3>\r
+<div class="paragraph"><p>Floating mode is the opposite of tiling mode. The position and size of a window\r
+are not managed by i3, but by you. Using this mode violates the tiling\r
+paradigm but can be useful for some corner cases like "Save as" dialog\r
+windows, or toolbar windows (GIMP or similar).</p></div>\r
+<div class="paragraph"><p>You can enable floating mode for a window by pressing <tt>Mod1+Shift+Space</tt>. By\r
+dragging the window’s titlebar with your mouse you can move the window\r
+around. By grabbing the borders and moving them you can resize the window. You\r
+can also do that by using the <a href="#floating_modifier">[floating_modifier]</a>.</p></div>\r
+<div class="paragraph"><p>For resizing floating windows with your keyboard, see <a href="#resizingconfig">[resizingconfig]</a>.</p></div>\r
+<div class="paragraph"><p>Floating windows are always on top of tiling windows.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_configuring_i3">3. Configuring i3</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This is where the real fun begins ;-). Most things are very dependant on your\r
+ideal working environment so we can’t make reasonable defaults for them.</p></div>\r
+<div class="paragraph"><p>While not using a programming language for the configuration, i3 stays\r
+quite flexible in regards to the things you usually want your window manager\r
+to do.</p></div>\r
+<div class="paragraph"><p>For example, you can configure bindings to jump to specific windows,\r
+you can set specific applications to start on specific workspaces, you can\r
+automatically start applications, you can change the colors of i3, and you\r
+can bind your keys to do useful things.</p></div>\r
+<div class="paragraph"><p>To change the configuration of i3, copy <tt>/etc/i3/config</tt> to <tt>~/.i3/config</tt>\r
+(or <tt>~/.config/i3/config</tt> if you like the XDG directory scheme) and edit it\r
+with a text editor.</p></div>\r
+<div class="sect2">\r
+<h3 id="_comments">3.1. Comments</h3>\r
+<div class="paragraph"><p>It is possible and recommended to use comments in your configuration file to\r
+properly document your setup for later reference. Comments are started with\r
+a # and can only be used at the beginning of a line:</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># This is a comment</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_fonts">3.2. Fonts</h3>\r
+<div class="paragraph"><p>i3 uses X core fonts (not Xft) for rendering window titles and the internal\r
+workspace bar. You can use <tt>xfontsel(1)</tt> to generate such a font description.\r
+To see special characters (Unicode), you need to use a font which supports\r
+the ISO-10646 encoding.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>font <X core font description></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="keybindings">3.3. Keyboard bindings</h3>\r
+<div class="paragraph"><p>A keyboard binding makes i3 execute a command (see below) upon pressing a\r
+specific key. i3 allows you to bind either on keycodes or on keysyms (you can\r
+also mix your bindings, though i3 will not protect you from overlapping ones).</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+A keysym (key symbol) is a description for a specific symbol, like "a"\r
+ or "b", but also more strange ones like "underscore" instead of "_". These\r
+ are the ones you use in Xmodmap to remap your keys. To get the current\r
+ mapping of your keys, use <tt>xmodmap -pke</tt>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Keycodes do not need to have a symbol assigned (handy for some hotkeys\r
+ on some notebooks) and they will not change their meaning as you switch to a\r
+ different keyboard layout (when using <tt>xmodmap</tt>).\r
+</p>\r
+</li>\r
+</ul></div>\r
+<div class="paragraph"><p>My recommendation is: If you often switch keyboard layouts but you want to keep\r
+your bindings in the same physical location on the keyboard, use keycodes.\r
+If you don’t switch layouts, and want a clean and simple config file, use\r
+keysyms.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym [Modifiers+]keysym command\r
+bind [Modifiers+]keycode command</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># Fullscreen\r
+bindsym Mod1+f f\r
+\r
+# Restart\r
+bindsym Mod1+Shift+r restart\r
+\r
+# Notebook-specific hotkeys\r
+bind 214 exec /home/michael/toggle_beamer.sh</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Available Modifiers:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+Mod1-Mod5, Shift, Control\r
+</dt>\r
+<dd>\r
+<p>\r
+Standard modifiers, see <tt>xmodmap(1)</tt>\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Mode_switch\r
+</dt>\r
+<dd>\r
+<p>\r
+Unlike other window managers, i3 can use Mode_switch as a modifier. This allows\r
+you to remap capslock (for example) to Mode_switch and use it for both: typing\r
+umlauts or special characters <em>and</em> having some comfortably reachable key\r
+bindings. For example, when typing, capslock+1 or capslock+2 for switching\r
+workspaces is totally convenient. Try it :-).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="floating_modifier">3.4. The floating modifier</h3>\r
+<div class="paragraph"><p>To move floating windows with your mouse, you can either grab their titlebar\r
+or configure the so called floating modifier which you can then press and\r
+click anywhere in the window itself to move it. The most common setup is to\r
+use the same key you use for managing windows (Mod1 for example). Then\r
+you can press Mod1, click into a window using your left mouse button, and drag\r
+it to the position you want.</p></div>\r
+<div class="paragraph"><p>When holding the floating modifier, you can resize a floating window by\r
+pressing the right mouse button on it and moving around while holding it. If\r
+you hold the shift button as well, the resize will be proportional.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>floating_modifier <Modifiers></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>floating_modifier Mod1</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_layout_mode_for_new_containers">3.5. Layout mode for new containers</h3>\r
+<div class="paragraph"><p>This option determines in which mode new containers will start. See also\r
+<a href="#stack-limit">[stack-limit]</a>.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>new_container <default|stacking|tabbed>\r
+new_container stack-limit <cols|rows> <value></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>new_container tabbed</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_border_style_for_new_windows">3.6. Border style for new windows</h3>\r
+<div class="paragraph"><p>This option determines which border style new windows will have.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>new_window <bp|bn|bb></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>new_window bp</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_variables">3.7. Variables</h3>\r
+<div class="paragraph"><p>As you learned in the section about keyboard bindings, you will have\r
+to configure lots of bindings containing modifier keys. If you want to save\r
+yourself some typing and be able to change the modifier you use later,\r
+variables can be handy.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>set name value</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>set $m Mod1\r
+bindsym $m+Shift+r restart</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Variables are directly replaced in the file when parsing. There is no fancy\r
+handling and there are absolutely no plans to change this. If you need a more\r
+dynamic configuration you should create a little script which generates a\r
+configuration file and run it before starting i3 (for example in your\r
+<tt>.xsession</tt> file).</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_automatically_putting_clients_on_specific_workspaces">3.8. Automatically putting clients on specific workspaces</h3>\r
+<div class="paragraph" id="assign_workspace"><p>It is recommended that you match on window classes wherever possible because\r
+some applications first create their window, and then worry about setting the\r
+correct title. Firefox with Vimperator comes to mind. The window starts up\r
+being named Firefox, and only when Vimperator is loaded does the title change.\r
+As i3 will get the title as soon as the application maps the window (mapping\r
+means actually displaying it on the screen), you’d need to have to match on\r
+<em>Firefox</em> in this case.</p></div>\r
+<div class="paragraph"><p>You can prefix or suffix workspaces with a <tt>~</tt> to specify that matching clients\r
+should be put into floating mode. If you specify only a <tt>~</tt>, the client will\r
+not be put onto any workspace, but will be set floating on the current one.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>assign ["]window class[/window title]["] [→] [~ | workspace]</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>assign urxvt 2\r
+assign urxvt → 2\r
+assign "urxvt" → 2\r
+assign "urxvt/VIM" → 3\r
+assign "gecko" → ~4\r
+assign "xv/MPlayer" → ~</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Note that the arrow is not required, it just looks good :-). If you decide to\r
+use it, it has to be a UTF-8 encoded arrow, not "→" or something like that.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_automatically_starting_applications_on_i3_startup">3.9. Automatically starting applications on i3 startup</h3>\r
+<div class="paragraph"><p>By using the <tt>exec</tt> keyword outside a keybinding, you can configure which\r
+commands will be performed by i3 on initial startup (not when restarting i3\r
+in-place however). These commands will be run in order.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>exec command</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>exec sudo i3status | dzen2 -dock</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="workspace_screen">3.10. Automatically putting workspaces on specific screens</h3>\r
+<div class="paragraph"><p>If you assign clients to workspaces, it might be handy to put the\r
+workspaces on specific screens. Also, the assignment of workspaces to screens\r
+will determine which workspace i3 uses for a new screen when adding screens\r
+or when starting (e.g., by default it will use 1 for the first screen, 2 for\r
+the second screen and so on).</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace <number> output <output></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <em>output</em> is the name of the RandR output you attach your screen to. On a\r
+laptop, you might have VGA1 and LVDS1 as output names. You can see the\r
+available outputs by running <tt>xrandr --current</tt>.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace 1 output LVDS1\r
+workspace 5 output VGA1</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_named_workspaces">3.11. Named workspaces</h3>\r
+<div class="paragraph"><p>If you always have a certain arrangement of workspaces, you might want to give\r
+them names (of course UTF-8 is supported):</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace <number> <name>\r
+workspace <number> output <output> name</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>For more details about the <em>output</em> part of this command, see above.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace 1 www\r
+workspace 2 work\r
+workspace 3 i ♥ workspaces</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_colors">3.12. Changing colors</h3>\r
+<div class="paragraph"><p>You can change all colors which i3 uses to draw the window decorations and the\r
+bottom bar.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>colorclass border background text</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Where colorclass can be one of:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+client.focused\r
+</dt>\r
+<dd>\r
+<p>\r
+ A client which currently has the focus.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+client.focused_inactive\r
+</dt>\r
+<dd>\r
+<p>\r
+ A client which is the focused one of its container, but it does not have\r
+ the focus at the moment.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+client.unfocused\r
+</dt>\r
+<dd>\r
+<p>\r
+ A client which is not the focused one of its container.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+client.urgent\r
+</dt>\r
+<dd>\r
+<p>\r
+ A client which has its urgency hint activated.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+bar.focused\r
+</dt>\r
+<dd>\r
+<p>\r
+ The current workspace in the bottom bar.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+bar.unfocused\r
+</dt>\r
+<dd>\r
+<p>\r
+ All other workspaces in the bottom bar.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+bar.urgent\r
+</dt>\r
+<dd>\r
+<p>\r
+ A workspace which has at least one client with an activated urgency hint.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>You can also specify the color to be used to paint the background of the client\r
+windows. This color will be used to paint the window on top of which the client\r
+will be rendered.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>client.background color</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Only clients that do not cover the whole area of this window expose the color\r
+used to paint it. If you use a color other than black for your terminals, you\r
+most likely want to set the client background color to the same color as your\r
+terminal program’s background color to avoid black gaps between the rendered\r
+area of the termianal and the i3 border.</p></div>\r
+<div class="paragraph"><p>Colors are in HTML hex format (#rrggbb), see the following example:</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># class border backgr. text\r
+client.focused #2F343A #900000 #FFFFFF</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Note that for the window decorations, the color around the child window is the\r
+background color, and the border color is only the two thin lines at the top of\r
+the window.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_interprocess_communication">3.13. Interprocess communication</h3>\r
+<div class="paragraph"><p>i3 uses unix sockets to provide an IPC interface. This allows third-party\r
+programs to get information from i3, such as the current workspaces\r
+(to display a workspace bar), and to control i3.</p></div>\r
+<div class="paragraph"><p>To enable it, you have to configure a path where the unix socket will be\r
+stored. The default path is <tt>~/.i3/ipc.sock</tt>.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>ipc-socket ~/.i3/ipc.sock</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>You can then use the <tt>i3-msg</tt> application to perform any command listed in\r
+the next section.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_disable_focus_follows_mouse">3.14. Disable focus follows mouse</h3>\r
+<div class="paragraph"><p>If you have a setup where your mouse usually is in your way (like a touchpad\r
+on your laptop which you do not want to disable completely), you might want\r
+to disable <em>focus follows mouse</em> and control focus only by using your keyboard.\r
+The mouse will still be useful inside the currently active window (for example\r
+to click on links in your browser window).</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>focus_follows_mouse <yes|no></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>focus_follows_mouse no</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_internal_workspace_bar">3.15. Internal workspace bar</h3>\r
+<div class="paragraph"><p>The internal workspace bar (the thing at the bottom of your screen) is very\r
+simple — it does not provide a way to display custom text and it does not\r
+offer advanced customization features. This is intended because we do not\r
+want to duplicate functionality of tools like <tt>dzen2</tt>, <tt>xmobar</tt> and so on\r
+(they render bars, we manage windows). Instead, there is an option which will\r
+turn off the internal bar completely, so that you can use a separate program to\r
+display it (see <tt>i3-wsbar</tt>, a sample implementation of such a program):</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace_bar <yes|no></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>workspace_bar no</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_list_of_commands">4. List of commands</h2>\r
+<div class="sectionbody">\r
+<div class="sect2">\r
+<h3 id="_manipulating_layout">4.1. Manipulating layout</h3>\r
+<div class="paragraph"><p>To change the layout of the current container to stacking, use <tt>s</tt>, for default\r
+use <tt>d</tt> and for tabbed, use <tt>T</tt>. To make the current client (!) fullscreen,\r
+use <tt>f</tt>, to make it span all outputs, use <tt>fg</tt>, to make it floating (or\r
+tiling again) use <tt>t</tt>:</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+s s\r
+bindsym Mod1+l d\r
+bindsym Mod1+w T\r
+\r
+# Toggle fullscreen\r
+bindsym Mod1+f f\r
+\r
+# Toggle global fullscreen\r
+bindsym Mod1+Shift+f fg\r
+\r
+# Toggle floating/tiling\r
+bindsym Mod1+t t</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_focusing_moving_snapping_clients_containers_screens">4.2. Focusing/Moving/Snapping clients/containers/screens</h3>\r
+<div class="paragraph"><p>To change the focus, use one of the <tt>h</tt>, <tt>j</tt>, <tt>k</tt> and <tt>l</tt> commands, meaning\r
+left, down, up, right (respectively). To focus a container, prefix it with\r
+<tt>wc</tt>. To focus a screen, prefix it with <tt>ws</tt>.</p></div>\r
+<div class="paragraph"><p>The same principle applies for moving and snapping: just prefix the command\r
+with <tt>m</tt> when moving and with <tt>s</tt> when snapping:</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># Focus clients on the left, bottom, top, right:\r
+bindsym Mod1+j h\r
+bindsym Mod1+k j\r
+bindsym Mod1+j k\r
+bindsym Mod1+semicolon l\r
+\r
+# Move client to the left, bottom, top, right:\r
+bindsym Mod1+j mh\r
+bindsym Mod1+k mj\r
+bindsym Mod1+j mk\r
+bindsym Mod1+semicolon ml\r
+\r
+# Snap client to the left, bottom, top, right:\r
+bindsym Mod1+j sh\r
+bindsym Mod1+k sj\r
+bindsym Mod1+j sk\r
+bindsym Mod1+semicolon sl\r
+\r
+# Focus container on the left, bottom, top, right:\r
+bindsym Mod3+j wch\r
+…</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_workspaces_moving_clients_to_workspaces">4.3. Changing workspaces/moving clients to workspaces</h3>\r
+<div class="paragraph"><p>To change to a specific workspace, the command is just the number of the\r
+workspace, e.g. <tt>1</tt> or <tt>3</tt>. To move the current client to a specific workspace,\r
+prefix the number with an <tt>m</tt>.</p></div>\r
+<div class="paragraph"><p>You can also switch to the next and previous workspace with the commands <tt>nw</tt>\r
+and <tt>pw</tt>, which is handy, for example, if you have workspace 1, 3, 4 and 9 and\r
+you want to cycle through them with a single key combination.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+1 1\r
+bindsym Mod1+2 2\r
+...\r
+\r
+bindsym Mod1+Shift+1 m1\r
+bindsym Mod1+Shift+2 m2\r
+...\r
+\r
+bindsym Mod1+o nw\r
+bindsym Mod1+p pw</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="resizingconfig">4.4. Resizing columns/rows</h3>\r
+<div class="paragraph"><p>If you want to resize columns/rows using your keyboard, you can use the\r
+<tt>resize</tt> command, I recommend using it inside a so called <tt>mode</tt>:</p></div>\r
+<div class="listingblock">\r
+<div class="title">Example: Configuration file, defining a mode for resizing</div>\r
+<div class="content">\r
+<pre><tt>mode "resize" {\r
+ # These bindings trigger as soon as you enter the resize mode\r
+\r
+ # They resize the border in the direction you pressed, e.g.\r
+ # when pressing left, the window is resized so that it has\r
+ # more space on its left\r
+\r
+ bindsym n resize left -10\r
+ bindsym Shift+n resize left +10\r
+\r
+ bindsym r resize bottom +10\r
+ bindsym Shift+r resize bottom -10\r
+\r
+ bindsym t resize top -10\r
+ bindsym Shift+t resize top +10\r
+\r
+ bindsym d resize right +10\r
+ bindsym Shift+d resize right -10\r
+\r
+ bind 36 mode default\r
+}\r
+\r
+# Enter resize mode\r
+bindsym Mod1+r mode resize</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_jumping_to_specific_windows">4.5. Jumping to specific windows</h3>\r
+<div class="paragraph"><p>Often when in a multi-monitor environment, you want to quickly jump to a\r
+specific window. For example, while working on workspace 3 you may want to\r
+jump to your mail client to email your boss that you’ve achieved some\r
+important goal. Instead of figuring out how to navigate to your mailclient,\r
+it would be more convenient to have a shortcut.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>jump ["]window class[/window title]["]\r
+jump workspace [ column row ]</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>You can either use the same matching algorithm as in the <tt>assign</tt> command\r
+(see above) or you can specify the position of the client if you always use\r
+the same layout.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># Get me to the next open VIM instance\r
+bindsym Mod1+a jump "urxvt/VIM"</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_vim_like_marks_mark_goto">4.6. VIM-like marks (mark/goto)</h3>\r
+<div class="paragraph" id="vim_like_marks"><p>This feature is like the jump feature: It allows you to directly jump to a\r
+specific window (this means switching to the appropriate workspace and setting\r
+focus to the windows). However, you can directly mark a specific window with\r
+an arbitrary label and use it afterwards. You do not need to ensure that your\r
+windows have unique classes or titles, and you do not need to change your\r
+configuration file.</p></div>\r
+<div class="paragraph"><p>As the command needs to include the label with which you want to mark the\r
+window, you cannot simply bind it to a key. <tt>i3-input</tt> is a tool created\r
+for this purpose: It lets you input a command and sends the command to i3. It\r
+can also prefix this command and display a custom prompt for the input dialog.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>mark <identifier>\r
+goto <identifier></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># Read 1 character and mark the current window with this character\r
+bindsym Mod1+m exec i3-input -p 'mark ' -l 1 -P 'Mark: '\r
+\r
+# Read 1 character and go to the window with the character\r
+bindsym Mod1+g exec i3-input -p 'goto ' -l 1 -P 'Goto: '</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Alternatively, if you do not want to mess with <tt>i3-input</tt>, you could create\r
+seperate bindings for a specific set of labels and then only use those labels.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_traveling_the_focus_stack">4.7. Traveling the focus stack</h3>\r
+<div class="paragraph"><p>This mechanism can be thought of as the opposite of the <tt>jump</tt> command.\r
+It travels the focus stack and jumps to the window which had focus previously.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>focus [number] | floating | tiling | ft</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Where <tt>number</tt> by default is 1 meaning that the next client in the focus stack\r
+will be selected.</p></div>\r
+<div class="paragraph"><p>The special values have the following meaning:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+floating\r
+</dt>\r
+<dd>\r
+<p>\r
+ The next floating window is selected.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+tiling\r
+</dt>\r
+<dd>\r
+<p>\r
+ The next tiling window is selected.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+ft\r
+</dt>\r
+<dd>\r
+<p>\r
+ If the current window is floating, the next tiling window will be\r
+ selected; and vice-versa.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_changing_border_style">4.8. Changing border style</h3>\r
+<div class="paragraph"><p>To change the border of the current client, you can use <tt>bn</tt> to use the normal\r
+border (including window title), <tt>bp</tt> to use a 1-pixel border (no window title)\r
+and <tt>bb</tt> to make the client borderless. There is also <tt>bt</tt> which will toggle\r
+the different border styles.</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+t bn\r
+bindsym Mod1+y bp\r
+bindsym Mod1+u bb</tt></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="stack-limit">4.9. Changing the stack-limit of a container</h3>\r
+<div class="paragraph"><p>If you have a single container with a lot of windows inside it (say, more than\r
+10), the default layout of a stacking container can get a little unhandy.\r
+Depending on your screen’s size, you might end up seeing only half of the\r
+titlebars for each window in the container.</p></div>\r
+<div class="paragraph"><p>Using the <tt>stack-limit</tt> command, you can limit the number of rows or columns\r
+in a stacking container. i3 will create columns or rows (depending on what\r
+you limited) automatically as needed.</p></div>\r
+<div class="paragraph"><p><strong>Syntax</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>stack-limit <cols|rows> <value></tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt># I always want to have two window titles in one line\r
+stack-limit cols 2\r
+\r
+# Not more than 5 rows in this stacking container\r
+stack-limit rows 5</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p><span class="image">\r
+<img src="stacklimit.png" alt="Container limited to two columns" />\r
+</span></p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_reloading_restarting_exiting">4.10. Reloading/Restarting/Exiting</h3>\r
+<div class="paragraph"><p>You can make i3 reload its configuration file with <tt>reload</tt>. You can also\r
+restart i3 inplace with the <tt>restart</tt> command to get it out of some weird state\r
+(if that should ever happen) or to perform an upgrade without having to restart\r
+your X session. However, your layout is not preserved at the moment, meaning\r
+that all open windows will end up in a single container in default layout\r
+after the restart. To exit i3 properly, you can use the <tt>exit</tt> command,\r
+however you don’t need to (simply killing your X session is fine as well).</p></div>\r
+<div class="paragraph"><p><strong>Examples</strong>:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>bindsym Mod1+Shift+r restart\r
+bindsym Mod1+Shift+w reload\r
+bindsym Mod1+Shift+e exit</tt></pre>\r
+</div></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="multi_monitor">5. Multiple monitors</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>As you can see in the goal list on the website, i3 was specifically developed\r
+with support for multiple monitors in mind. This section will explain how to\r
+handle multiple monitors.</p></div>\r
+<div class="paragraph"><p>When you have only one monitor, things are simple. You usually start with\r
+workspace 1 on your monitor and open new ones as you need them.</p></div>\r
+<div class="paragraph"><p>When you have more than one monitor, each monitor will get an initial\r
+workspace. The first monitor gets 1, the second gets 2 and a possible third\r
+would get 3. When you switch to a workspace on a different monitor, i3 will\r
+switch to that monitor and then switch to the workspace. This way, you don’t\r
+need shortcuts to switch to a specific monitor, and you don’t need to remember\r
+where you put which workspace. New workspaces will be opened on the currently\r
+active monitor. It is not possible to have a monitor without a workspace.</p></div>\r
+<div class="paragraph"><p>The idea of making workspaces global is based on the observation that most\r
+users have a very limited set of workspaces on their additional monitors.\r
+They are often used for a specific task (browser, shell) or for monitoring\r
+several things (mail, IRC, syslog, …). Thus, using one workspace on one monitor\r
+and "the rest" on the other monitors often makes sense. However, as you can\r
+create an unlimited number of workspaces in i3 and tie them to specific\r
+screens, you can have the "traditional" approach of having X workspaces per\r
+screen by changing your configuration (using modes, for example).</p></div>\r
+<div class="sect2">\r
+<h3 id="_configuring_your_monitors">5.1. Configuring your monitors</h3>\r
+<div class="paragraph"><p>To help you get going if you have never used multiple monitors before, here is\r
+a short overview of the xrandr options which will probably be of interest to\r
+you. It is always useful to get an overview of the current screen configuration.\r
+Just run "xrandr" and you will get an output like the following:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>$ xrandr\r
+Screen 0: minimum 320 x 200, current 1280 x 800, maximum 8192 x 8192\r
+VGA1 disconnected (normal left inverted right x axis y axis)\r
+LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 261mm x 163mm\r
+ 1280x800 60.0*+ 50.0\r
+ 1024x768 85.0 75.0 70.1 60.0\r
+ 832x624 74.6\r
+ 800x600 85.1 72.2 75.0 60.3 56.2\r
+ 640x480 85.0 72.8 75.0 59.9\r
+ 720x400 85.0\r
+ 640x400 85.1\r
+ 640x350 85.1</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Several things are important here: You can see that <tt>LVDS1</tt> is connected (of\r
+course, it is the internal flat panel) but <tt>VGA1</tt> is not. If you have a monitor\r
+connected to one of the ports but xrandr still says "disconnected", you should\r
+check your cable, monitor or graphics driver.</p></div>\r
+<div class="paragraph"><p>The maximum resolution you can see at the end of the first line is the maximum\r
+combined resolution of your monitors. By default, it is usually too low and has\r
+to be increased by editing <tt>/etc/X11/xorg.conf</tt>.</p></div>\r
+<div class="paragraph"><p>So, say you connected VGA1 and want to use it as an additional screen:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>xrandr --output VGA1 --auto --left-of LVDS1</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This command makes xrandr try to find the native resolution of the device\r
+connected to <tt>VGA1</tt> and configures it to the left of your internal flat panel.\r
+When running "xrandr" again, the output looks like this:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>$ xrandr\r
+Screen 0: minimum 320 x 200, current 2560 x 1024, maximum 8192 x 8192\r
+VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm\r
+ 1280x1024 60.0*+ 75.0\r
+ 1280x960 60.0\r
+ 1152x864 75.0\r
+ 1024x768 75.1 70.1 60.0\r
+ 832x624 74.6\r
+ 800x600 72.2 75.0 60.3 56.2\r
+ 640x480 72.8 75.0 66.7 60.0\r
+ 720x400 70.1\r
+LVDS1 connected 1280x800+1280+0 (normal left inverted right x axis y axis) 261mm x 163mm\r
+ 1280x800 60.0*+ 50.0\r
+ 1024x768 85.0 75.0 70.1 60.0\r
+ 832x624 74.6\r
+ 800x600 85.1 72.2 75.0 60.3 56.2\r
+ 640x480 85.0 72.8 75.0 59.9\r
+ 720x400 85.0\r
+ 640x400 85.1\r
+ 640x350 85.1</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Please note that i3 uses exactly the same API as xrandr does, so it will see\r
+only what you can see in xrandr.</p></div>\r
+<div class="paragraph"><p>See also <a href="#presentations">[presentations]</a> for more examples of multi-monitor setups.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_interesting_configuration_for_multi_monitor_environments">5.2. Interesting configuration for multi-monitor environments</h3>\r
+<div class="paragraph"><p>There are several things to configure in i3 which may be interesting if you\r
+have more than one monitor:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+You can specify which workspace should be put on which screen. This\r
+ allows you to have a different set of workspaces when starting than just\r
+ 1 for the first monitor, 2 for the second and so on. See\r
+ <a href="#workspace_screen">[workspace_screen]</a>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If you want some applications to generally open on the bigger screen\r
+ (MPlayer, Firefox, …), you can assign them to a specific workspace, see\r
+ <a href="#assign_workspace">[assign_workspace]</a>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If you have many workspaces on many monitors, it might get hard to keep\r
+ track of which window you put where. Thus, you can use vim-like marks to\r
+ quickly switch between windows. See <a href="#vim_like_marks">[vim_like_marks]</a>.\r
+</p>\r
+</li>\r
+</ol></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_i3_and_the_rest_of_your_software_world">6. i3 and the rest of your software world</h2>\r
+<div class="sectionbody">\r
+<div class="sect2">\r
+<h3 id="_displaying_a_status_line">6.1. Displaying a status line</h3>\r
+<div class="paragraph"><p>A very common thing amongst users of exotic window managers is a status line at\r
+some corner of the screen. It is an often superior replacement to the widget\r
+approach you have in the task bar of a traditional desktop environment.</p></div>\r
+<div class="paragraph"><p>If you don’t already have your favorite way of generating such a status line\r
+(self-written scripts, conky, …), then i3status is the recommended tool for\r
+this task. It was written in C with the goal of using as few syscalls as\r
+possible to reduce the time your CPU is woken up from sleep states.</p></div>\r
+<div class="paragraph"><p>Regardless of which application you use to generate the status line, you\r
+want to make sure that the application does one of the following things:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Register as a dock window using EWMH hints. This will make i3 position the\r
+ window above the workspace bar but below every other client. This is the\r
+ recommended way, but in case of dzen2, for example, you need to check out\r
+ the source of dzen2 from subversion, as the -dock option is not present\r
+ in the released versions.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Overlay the internal workspace bar. This method will not waste any space\r
+ on the workspace bar, however, it is rather hackish. Just configure\r
+ the output window to be over the workspace bar (say -x 200 and -y 780 if\r
+ your screen is 800 px height).\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p>The planned solution for this problem is to make the workspace bar optional\r
+and switch to a third party application completely (dzen2 for example)\r
+which will then contain the workspace bar.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_giving_presentations_multi_monitor">6.2. Giving presentations (multi-monitor)</h3>\r
+<div class="paragraph"><p>When giving a presentation, you typically want the audience to see what you see\r
+on your screen and then go through a series of slides (if the presentation is\r
+simple). For more complex presentations, you might want to have some notes\r
+which only you can see on your screen, while the audience can only see the\r
+slides.</p></div>\r
+<div class="sect3">\r
+<h4 id="presentations">6.2.1. Case 1: everybody gets the same output</h4>\r
+<div class="paragraph"><p>This is the simple case. You connect your computer to the video projector,\r
+turn on both (computer and video projector) and configure your X server to\r
+clone the internal flat panel of your computer to the video output:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>xrandr --output VGA1 --mode 1024x768 --same-as LVDS1</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>i3 will then use the lowest common subset of screen resolutions, the rest of\r
+your screen will be left untouched (it will show the X background). So, in\r
+our example, this would be 1024x768 (my notebook has 1280x800).</p></div>\r
+</div>\r
+<div class="sect3">\r
+<h4 id="_case_2_you_can_see_more_than_your_audience">6.2.2. Case 2: you can see more than your audience</h4>\r
+<div class="paragraph"><p>This case is a bit harder. First of all, you should configure the VGA output\r
+somewhere near your internal flat panel, say right of it:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>xrandr --output VGA1 --mode 1024x768 --right-of LVDS1</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Now, i3 will put a new workspace (depending on your settings) on the new screen\r
+and you are in multi-monitor mode (see <a href="#multi_monitor">[multi_monitor]</a>).</p></div>\r
+<div class="paragraph"><p>Because i3 is not a compositing window manager, there is no ability to\r
+display a window on two screens at the same time. Instead, your presentation\r
+software needs to do this job (that is, open a window on each screen).</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:28:05 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.4" />\r
+<title>i3: External workspace bars</title>\r
+<link rel="stylesheet" href="/css/style.css" type="text/css" />\r
+<link rel="stylesheet" href="/css/xhtml11.css" type="text/css" />\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}\r
+/*]]>*/\r
+</script>\r
+<script type="text/javascript" src="/js/asciidoc-xhtml11.js"></script>\r
+</head>\r
+<body class="article">\r
+\r
+ <div id="main">\r
+ <h1 id="title">i3 - improved tiling WM</h1>\r
+ <ul id="nav">\r
+ <li><a style="border-bottom: 2px solid #fff" href="/docs">Docs</a></li>\r
+ <li><a href="/screenshots">Screens</a></li>\r
+ <li><a href="/contact">Contact</a></li>\r
+ <li><a href="http://bugs.i3wm.org/">Bugs</a></li>\r
+ </ul>\r
+ <br style="clear: both">\r
+<div id="content">\r
+<div id="header">\r
+<h1>External workspace bars</h1>\r
+<span id="author">Michael Stapelberg</span><br />\r
+<span id="email"><tt><<a href="mailto:michael+i3@stapelberg.de">michael+i3@stapelberg.de</a>></tt></span><br />\r
+<span id="revdate">May 2010</span>\r
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>This document describes why the internal workspace bar is minimal and how an\r
+external workspace bar can be used. It explains the concepts using <tt>i3-wsbar</tt>\r
+as the reference implementation.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_internal_and_external_bars">1. Internal and external bars</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>The internal workspace bar of i3 is meant to be a reasonable default so that\r
+you can use i3 without having too much hassle when setting it up. It is quite\r
+simple and intended to stay this way. So, there is no way to display your own\r
+information in this bar (unlike dwm, wmii, awesome, …).</p></div>\r
+<div class="paragraph"><p>We chose not to implement such a mechanism because that would be duplicating\r
+already existing functionality of tools such as dzen2, xmobar and similar.\r
+Instead, you should disable the internal bar and use an external workspace bar\r
+(which communicates with i3 through its IPC interface).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_dock_mode">2. dock mode</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>You typically want to see the same workspace bar on every workspace on a\r
+specific screen. Also, you don’t want to place the workspace bar somewhere\r
+in your layout by hand. This is where dock mode comes in: When a program sets\r
+the appropriate hint (_NET_WM_WINDOW_TYPE_DOCK), it will be managed in dock\r
+mode by i3. That means it will be placed at the bottom of the screen (while\r
+other edges of the screen are possible in the NetWM standard, this is not yet\r
+implemented in i3), it will not overlap any other window and it will be on\r
+every workspace for the specific screen it was placed on initially.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_the_ipc_interface">3. The IPC interface</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>In the context of using an external workspace bar, the IPC interface needs to\r
+provide the bar program with the current workspaces and output (as in VGA-1,\r
+LVDS-1, …) configuration. In the other direction, the program has to be able\r
+to switch to specific workspaces.</p></div>\r
+<div class="paragraph"><p>By default, the IPC interface is enabled and places its UNIX socket in\r
+<tt>~/.i3/ipc.sock</tt>.</p></div>\r
+<div class="paragraph"><p>To learn more about the protocol which is used for IPC, see <tt>docs/ipc</tt>.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_output_changes_on_the_fly">4. Output changes (on-the-fly)</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>i3 implements the RandR API and can handle changing outputs quite well. So, an\r
+external workspace bar implementation needs to make sure that when you change\r
+the resolution of any of your screens (or enable/disable an output), the bars\r
+will be adjusted properly.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_i3_wsbar_the_reference_implementation">5. i3-wsbar, the reference implementation</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Please keep in mind that <tt>i3-wsbar</tt> is just a reference implementation. It is\r
+shipped with i3 to have a reasonable default. Thus, <tt>i3-wsbar</tt> is designed to\r
+work well with dzen2 and there are no plans to make it more generic.</p></div>\r
+<div class="sect2">\r
+<h3 id="_the_big_picture">5.1. The big picture</h3>\r
+<div class="paragraph"><p>The most common reason to use an external workspace bar is to integrate system\r
+information such as what <tt>i3status</tt> provides into the workspace bar (to save\r
+screen space). So, we have <tt>i3status</tt> or a similar program, which only provides\r
+text output (formatted in some way). To display this text nicely on the screen,\r
+there are programs such as dzen2, xmobar and similar. We will stick to dzen2\r
+from here on. So, we have the output of i3status, which needs to go into dzen2\r
+somehow. But we also want to display the list of workspaces. <tt>i3-wsbar</tt> takes\r
+input on stdin, combines it with a formatted workspace list and pipes it to\r
+dzen2.</p></div>\r
+<div class="paragraph"><p>Please note that <tt>i3-wsbar</tt> does not print its output to stdout. Instead, it\r
+launches the dzen2 instances on its own. This is necessary to handle changes\r
+in the available outputs (to place a new dzen2 on a new screen for example).</p></div>\r
+<div class="paragraph"><p><span class="image">\r
+<a class="image" href="wsbar.png">\r
+<img src="wsbar.png" alt="Overview" />\r
+</a>\r
+</span></p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_running_i3_wsbar">5.2. Running i3-wsbar</h3>\r
+<div class="paragraph"><p>The most simple usage of i3-wsbar looks like this:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>i3-wsbar -c "dzen2 -x %x -dock"</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>%x</tt> in the command name will be replaced by the X position of the output\r
+for which this workspace bar is running. i3 will automatically place the\r
+workspace bar on the correct output when dzen2 is started in dock mode. The\r
+bar which you will see should look exactly like the internal bar of i3.</p></div>\r
+<div class="paragraph"><p>To actually get a benefit, you want to give <tt>i3-wsbar</tt> some input:</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><tt>i3status | i3-wsbar -c "dzen2 -x %x -dock"</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>It is recommended to place the above command in your i3 configuration file\r
+to start it automatically with i3.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2011-07-22 20:28:28 CEST\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
--- /dev/null
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ var cont = document.getElementById("content");
+ var noteholder = document.getElementById("footnotes");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+}
+
+}