]> git.sur5r.net Git - i3/i3.github.io/blobdiff - docs/4.8/hacking-howto.html
save docs for 4.8
[i3/i3.github.io] / docs / 4.8 / hacking-howto.html
diff --git a/docs/4.8/hacking-howto.html b/docs/4.8/hacking-howto.html
new file mode 100644 (file)
index 0000000..8326751
--- /dev/null
@@ -0,0 +1,1599 @@
+<!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
+<link rel="icon" type="image/x-icon" href="/favicon.ico">\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.8" />\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
+document.addEventListener("DOMContentLoaded", function(){asciidoc.footnotes(); asciidoc.toc(2);}, false);\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
+            <a href="/"><h1 id="title">i3 - improved tiling WM</h1></a>\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>&lt;<a href="mailto:michael@i3wm.org">michael@i3wm.org</a>&gt;</tt></span><br />\r
+<span id="revdate">February 2013</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&#8217;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 <tt>_WM_STATE_FULLSCREEN</tt> and\r
+  <tt>_NET_WM_STATE_DEMANDS_ATTENTION</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 inflexible.\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_tree">1.2. The layout tree</h3>\r
+<div class="paragraph"><p>The data structure which i3 uses to keep track of your windows is a tree. Every\r
+node in the tree is a container (type <tt>Con</tt>). Some containers represent actual\r
+windows (every container with a <tt>window != NULL</tt>), some represent split\r
+containers and a few have special purposes: they represent workspaces, outputs\r
+(like VGA1, LVDS1, …) or the X11 root window.</p></div>\r
+<div class="paragraph"><p>So, when you open a terminal and immediately open another one, they reside in\r
+the same split container, which uses the default layout. In case of an empty\r
+workspace, the split container we are talking about is the workspace.</p></div>\r
+<div class="paragraph"><p>To get an impression of how different layouts are represented, just play around\r
+and look at the data structures&#8201;&#8212;&#8201;they are exposed as a JSON hash. See\r
+<a href="http://i3wm.org/docs/ipc.html#_tree_reply">http://i3wm.org/docs/ipc.html#_tree_reply</a> for documentation on that and an\r
+example.</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/atoms.xmacro\r
+</dt>\r
+<dd>\r
+<p>\r
+A file containing all X11 atoms which i3 uses. This file will be included\r
+various times (for defining, requesting and receiving the atoms), each time\r
+with a different definition of xmacro().\r
+</p>\r
+</dd>\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/config_parser.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains a custom configuration parser. See src/command_parser.c for rationale\r
+ on why we use a custom parser.\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/command_parser.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains a hand-written parser to parse commands (commands are what\r
+you bind on keys and what you can send to i3 using the IPC interface, like\r
+<em>move left</em> or <em>workspace 4</em>).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/con.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all functions which deal with containers directly (creating\r
+containers, searching containers, getting specific properties from containers,\r
+…).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/config.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains all functions handling the configuration file (calling the parser\r
+(src/cfgparse.y) with the correct path, switching key bindings mode).\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/ewmh.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Functions to get/set certain EWMH properties easily.\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/load_layout.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains code for loading layouts from JSON files.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/log.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains the logging functions.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/main.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/match.c\r
+</dt>\r
+<dd>\r
+<p>\r
+A "match" is a data structure which acts like a mask or expression to match\r
+certain windows or not. For example, when using commands, you can specify a\r
+command like this: [title="<strong>Firefox</strong>"] kill. The title member of the match\r
+data structure will then be filled and i3 will check each window using\r
+match_matches_window() to find the windows affected by this command.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/move.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains code to move a container in a specific direction.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/output.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Functions to handle CT_OUTPUT cons.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/randr.c\r
+</dt>\r
+<dd>\r
+<p>\r
+The RandR API is used to get (and re-query) the configured outputs (monitors,\r
+…).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/render.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Renders the tree data structure by assigning coordinates to every node. These\r
+values will later be pushed to X11 in <tt>src/x.c</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/resize.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains the functions to resize containers.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/restore_layout.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Everything for restored containers that is not pure state parsing (which can be\r
+found in load_layout.c).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/sighandler.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Handles <tt>SIGSEGV</tt>, <tt>SIGABRT</tt> and <tt>SIGFPE</tt> by showing a dialog that i3 crashed.\r
+You can chose to let it dump core, to restart it in-place or to restart it\r
+in-place but forget about the layout.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/tree.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Contains functions which open or close containers in the tree, change focus or\r
+cleanup ("flatten") the tree. See also <tt>src/move.c</tt> for another similar\r
+function, which was moved into its own file because it is so long.\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/window.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Handlers to update X11 window properties like <tt>WM_CLASS</tt>, <tt>_NET_WM_NAME</tt>,\r
+<tt>CLIENT_LEADER</tt>, etc.\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/x.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Transfers our in-memory tree (see <tt>src/render.c</tt>) to X11.\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/xcursor.c\r
+</dt>\r
+<dd>\r
+<p>\r
+XCursor functions (for cursor themes).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+src/xinerama.c\r
+</dt>\r
+<dd>\r
+<p>\r
+Legacy support for Xinerama. See <tt>src/randr.c</tt> for the preferred API.\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>So, the hierarchy is:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+<strong>X11 root window</strong>, the root container\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Output container</strong> (LVDS1 in this example)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Content container</strong> (there are also containers for dock windows)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Workspaces</strong> (Workspace 1 in this example, with horizontal orientation)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>Split container</strong> (vertically split)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<strong>X11 window containers</strong>\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p>The data type is <tt>Con</tt>, in all cases.</p></div>\r
+<div class="sect2">\r
+<h3 id="_x11_root_window">3.1. X11 root window</h3>\r
+<div class="paragraph"><p>The X11 root window is a single window per X11 display (a display is identified\r
+by <tt>:0</tt> or <tt>:1</tt> etc.). The root window is what you draw your background image\r
+on. It spans all the available outputs, e.g. <tt>VGA1</tt> is a specific part of the\r
+root window and <tt>LVDS1</tt> is a specific part of the root window.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_output_container">3.2. Output container</h3>\r
+<div class="paragraph"><p>Every active output obtained through RandR is represented by one output\r
+container. Outputs are considered active when a mode is configured (meaning\r
+something is actually displayed on the output) and the output is not a clone.</p></div>\r
+<div class="paragraph"><p>For example, if your notebook has a screen resolution of 1280x800 px and you\r
+connect a video projector with a resolution of 1024x768 px, set it up in clone\r
+mode (<tt>xrandr --output VGA1 --mode 1024x768 --same-as LVDS1</tt>), i3 will\r
+reduce the resolution to the lowest common resolution and disable one of the\r
+cloned outputs afterwards.</p></div>\r
+<div class="paragraph"><p>However, if you configure it using <tt>xrandr --output VGA1 --mode 1024x768\r
+--right-of LVDS1</tt>, i3 will set both outputs active. For each output, a new\r
+workspace will be assigned. New workspaces are created on the output you are\r
+currently on.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_content_container">3.3. Content container</h3>\r
+<div class="paragraph"><p>Each output has multiple children. Two of them are dock containers which hold\r
+dock clients. The other one is the content container, which holds the actual\r
+content (workspaces) of this output.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_workspace">3.4. Workspace</h3>\r
+<div class="paragraph"><p>A workspace is identified by its name. Basically, you could think of\r
+workspaces as different desks in your office, if you like the desktop\r
+metaphor. They just contain different sets of windows and are completely\r
+separate of each other. Other window managers also call this &#8220;Virtual\r
+desktops&#8221;.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_split_container">3.5. Split container</h3>\r
+<div class="paragraph"><p>A split container is a container which holds an arbitrary amount of split\r
+containers or X11 window containers. It has an orientation (horizontal or\r
+vertical) and a layout.</p></div>\r
+<div class="paragraph"><p>Split containers (and X11 window containers, which are a subtype of split\r
+containers) can have different border styles.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_x11_window_container">3.6. X11 window container</h3>\r
+<div class="paragraph"><p>An X11 window container holds exactly one X11 window. These are the leaf nodes\r
+of the layout tree, they cannot have any children.</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 <tt>TAILQ</tt> (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
+&#8220;conn&#8221; is the xcb_connection_t\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+&#8220;event&#8221; is the event of the particular type\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+&#8220;con&#8221; names a container\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+&#8220;current&#8221; is a loop variable when using <tt>TAILQ_FOREACH</tt> etc.\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, load Xcursor\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Check for RandR screens (with a fall-back to Xinerama)\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 by the cmdparse lexer/parser, see <tt>parse_cmd</tt> in\r
+<tt>src/cmdparse.y</tt>.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_manage_windows_src_main_c_manage_window_and_reparent_window">8. Manage windows (src/main.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 initial 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
+or top of the screen (in the appropriate dock area containers). To get the\r
+height which needs to be reserved for the window, the <tt>_NET_WM_STRUT_PARTIAL</tt>\r
+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 about 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_tree()</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 &#8220;configured&#8221; 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
+&#8220;toggle_fullscreen()&#8221; 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>Rendering in i3 version 4 is the step which assigns the correct sizes for\r
+borders, decoration windows, child windows and the stacking order of all\r
+windows. In a separate step (<tt>x_push_changes()</tt>), these changes are pushed to\r
+X11.</p></div>\r
+<div class="paragraph"><p>Keep in mind that all these properties (<tt>rect</tt>, <tt>window_rect</tt> and <tt>deco_rect</tt>)\r
+are temporary, meaning they will be overwritten by calling <tt>render_con</tt>.\r
+Persistent position/size information is kept in <tt>geometry</tt>.</p></div>\r
+<div class="paragraph"><p>The entry point for every rendering operation (except for the case of moving\r
+floating windows around) currently is <tt>tree_render()</tt> which will re-render\r
+everything that’s necessary (for every output, only the currently displayed\r
+workspace is rendered). This behavior is expected to change in the future,\r
+since for a lot of updates, re-rendering everything is not actually necessary.\r
+Focus was on getting it working correct, not getting it work very fast.</p></div>\r
+<div class="paragraph"><p>What <tt>tree_render()</tt> actually does is calling <tt>render_con()</tt> on the root\r
+container and then pushing the changes to X11. The following sections talk\r
+about the different rendering steps, in the order of "top of the tree" (root\r
+container) to the bottom.</p></div>\r
+<div class="sect2">\r
+<h3 id="_rendering_the_root_container">14.1. Rendering the root container</h3>\r
+<div class="paragraph"><p>The i3 root container (<tt>con-&gt;type == CT_ROOT</tt>) represents the X11 root window.\r
+It contains one child container for every output (like LVDS1, VGA1, …), which\r
+is available on your computer.</p></div>\r
+<div class="paragraph"><p>Rendering the root will first render all tiling windows and then all floating\r
+windows. This is necessary because a floating window can be positioned in such\r
+a way that it is visible on two different outputs. Therefore, by first\r
+rendering all the tiling windows (of all outputs), we make sure that floating\r
+windows can never be obscured by tiling windows.</p></div>\r
+<div class="paragraph"><p>Essentially, though, this code path will just call <tt>render_con()</tt> for every\r
+output and <tt>x_raise_con(); render_con()</tt> for every floating window.</p></div>\r
+<div class="paragraph"><p>In the special case of having a "global fullscreen" window (fullscreen mode\r
+spanning all outputs), a shortcut is taken and <tt>x_raise_con(); render_con()</tt> is\r
+only called for the global fullscreen window.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_rendering_an_output">14.2. Rendering an output</h3>\r
+<div class="paragraph"><p>Output containers (<tt>con-&gt;layout == L_OUTPUT</tt>) represent a hardware output like\r
+LVDS1, VGA1, etc. An output container has three children (at the moment): One\r
+content container (having workspaces as children) and the top/bottom dock area\r
+containers.</p></div>\r
+<div class="paragraph"><p>The rendering happens in the function <tt>render_l_output()</tt> in the following\r
+steps:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Find the content container (<tt>con-&gt;type == CT_CON</tt>)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Get the currently visible workspace (<tt>con_get_fullscreen_con(content,\r
+   CF_OUTPUT)</tt>).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If there is a fullscreened window on that workspace, directly render it and\r
+   return, thus ignoring the dock areas.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Sum up the space used by all the dock windows (they have a variable height\r
+   only).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Set the workspace rects (x/y/width/height) based on the position of the\r
+   output (stored in <tt>con-&gt;rect</tt>) and the usable space\r
+   (<tt>con-&gt;rect.{width,height}</tt> without the space used for dock windows).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Recursively raise and render the output’s child containers (meaning dock\r
+   area containers and the content container).\r
+</p>\r
+</li>\r
+</ol></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_rendering_a_workspace_or_split_container">14.3. Rendering a workspace or split container</h3>\r
+<div class="paragraph"><p>From here on, there really is no difference anymore. All containers are of\r
+<tt>con-&gt;type == CT_CON</tt> (whether workspace or split container) and some of them\r
+have a <tt>con-&gt;window</tt>, meaning they represent an actual window instead of a\r
+split container.</p></div>\r
+<div class="sect3">\r
+<h4 id="_default_layout">14.3.1. Default layout</h4>\r
+<div class="paragraph"><p>In default layout, containers are placed horizontally or vertically next to\r
+each other (depending on the <tt>con-&gt;orientation</tt>). If a child is a leaf node (as\r
+opposed to a split container) and has border style "normal", appropriate space\r
+will be reserved for its window decoration.</p></div>\r
+</div>\r
+<div class="sect3">\r
+<h4 id="_stacked_layout">14.3.2. Stacked layout</h4>\r
+<div class="paragraph"><p>In stacked layout, only the focused window is actually shown (this is achieved\r
+by calling <tt>x_raise_con()</tt> in reverse focus order at the end of <tt>render_con()</tt>).</p></div>\r
+<div class="paragraph"><p>The available space for the focused window is the size of the container minus\r
+the height of the window decoration for all windows inside this stacked\r
+container.</p></div>\r
+<div class="paragraph"><p>If border style is "1pixel" or "none", no window decoration height will be\r
+reserved (or displayed later on), unless there is more than one window inside\r
+the stacked container.</p></div>\r
+</div>\r
+<div class="sect3">\r
+<h4 id="_tabbed_layout">14.3.3. Tabbed layout</h4>\r
+<div class="paragraph"><p>Tabbed layout works precisely like stacked layout, but the window decoration\r
+position/size is different: They are placed next to each other on a single line\r
+(fixed height).</p></div>\r
+</div>\r
+<div class="sect3">\r
+<h4 id="_dock_area_layout">14.3.4. Dock area layout</h4>\r
+<div class="paragraph"><p>This is a special case. Users cannot choose the dock area layout, but it will be\r
+set for the dock area containers. In the dockarea layout (at the moment!),\r
+windows will be placed above each other.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_rendering_a_window">14.4. Rendering a window</h3>\r
+<div class="paragraph"><p>A window’s size and position will be determined in the following way:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Subtract the border if border style is not "none" (but "normal" or "1pixel").\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Subtract the X11 border, if the window has an X11 border &gt; 0.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Obey the aspect ratio of the window (think MPlayer).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Obey the height- and width-increments of the window (think terminal emulator\r
+   which can only be resized in one-line or one-character steps).\r
+</p>\r
+</li>\r
+</ol></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_pushing_updates_to_x11_drawing">15. Pushing updates to X11 / Drawing</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>A big problem with i3 before version 4 was that we just sent requests to X11\r
+anywhere in the source code. This was bad because nobody could understand the\r
+entirety of our interaction with X11, it lead to subtle bugs and a lot of edge\r
+cases which we had to consider all over again.</p></div>\r
+<div class="paragraph"><p>Therefore, since version 4, we have a single file, <tt>src/x.c</tt>, which is\r
+responsible for repeatedly transferring parts of our tree datastructure to X11.</p></div>\r
+<div class="paragraph"><p><tt>src/x.c</tt> consists of multiple parts:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+The state pushing: <tt>x_push_changes()</tt>, which calls <tt>x_push_node()</tt>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+State modification functions: <tt>x_con_init</tt>, <tt>x_reinit</tt>,\r
+   <tt>x_reparent_child</tt>, <tt>x_move_win</tt>, <tt>x_con_kill</tt>, <tt>x_raise_con</tt>, <tt>x_set_name</tt>\r
+   and <tt>x_set_warp_to</tt>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Expose event handling (drawing decorations): <tt>x_deco_recurse()</tt> and\r
+   <tt>x_draw_decoration()</tt>.\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="sect2">\r
+<h3 id="_pushing_state_to_x11">15.1. Pushing state to X11</h3>\r
+<div class="paragraph"><p>In general, the function <tt>x_push_changes</tt> should be called to push state\r
+changes. Only when the scope of the state change is clearly defined (for\r
+example only the title of a window) and its impact is known beforehand, one can\r
+optimize this and call <tt>x_push_node</tt> on the appropriate con directly.</p></div>\r
+<div class="paragraph"><p><tt>x_push_changes</tt> works in the following steps:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Clear the eventmask for all mapped windows. This leads to not getting\r
+   useless ConfigureNotify or EnterNotify events which are caused by our\r
+   requests. In general, we only want to handle user input.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Stack windows above each other, in reverse stack order (starting with the\r
+   most obscured/bottom window). This is relevant for floating windows which\r
+   can overlap each other, but also for tiling windows in stacked or tabbed\r
+   containers. We also update the <tt>_NET_CLIENT_LIST_STACKING</tt> hint which is\r
+   necessary for tab drag and drop in Chromium.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>x_push_node</tt> will be called for the root container, recursively calling\r
+   itself for the container’s children. This function actually pushes the\r
+   state, see the next paragraph.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If the pointer needs to be warped to a different position (for example when\r
+   changing focus to a differnt output), it will be warped now.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The eventmask is restored for all mapped windows.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Window decorations will be rendered by calling <tt>x_deco_recurse</tt> on the root\r
+   container, which then recursively calls itself for the children.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If the input focus needs to be changed (because the user focused a different\r
+   window), it will be updated now.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>x_push_node_unmaps</tt> will be called for the root container. This function\r
+   only pushes UnmapWindow requests. Separating the state pushing is necessary\r
+   to handle fullscreen windows (and workspace switches) in a smooth fashion:\r
+   The newly visible windows should be visible before the old windows are\r
+   unmapped.\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p><tt>x_push_node</tt> works in the following steps:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Update the window’s <tt>WM_NAME</tt>, if changed (the <tt>WM_NAME</tt> is set on i3\r
+   containers mainly for debugging purposes).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Reparents a child window into the i3 container if the container was created\r
+   for a specific managed window.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+If the size/position of the i3 container changed (due to opening a new\r
+   window or switching layouts for example), the window will be reconfigured.\r
+   Also, the pixmap which is used to draw the window decoration/border on is\r
+   reconfigured (pixmaps are size-dependent).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Size/position for the child window is adjusted.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The i3 container is mapped if it should be visible and was not yet mapped.\r
+   When mapping, <tt>WM_STATE</tt> is set to <tt>WM_STATE_NORMAL</tt>. Also, the eventmask of\r
+   the child window is updated and the i3 container’s contents are copied from\r
+   the pixmap.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>x_push_node</tt> is called recursively for all children of the current\r
+   container.\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p><tt>x_push_node_unmaps</tt> handles the remaining case of an i3 container being\r
+unmapped if it should not be visible anymore. <tt>WM_STATE</tt> will be set to\r
+<tt>WM_STATE_WITHDRAWN</tt>.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_drawing_window_decorations_borders_backgrounds">15.2. Drawing window decorations/borders/backgrounds</h3>\r
+<div class="paragraph"><p><tt>x_draw_decoration</tt> draws window decorations. It is run for every leaf\r
+container (representing an actual X11 window) and for every non-leaf container\r
+which is in a stacked/tabbed container (because stacked/tabbed containers\r
+display a window decoration for split containers, which at the moment just says\r
+"another container").</p></div>\r
+<div class="paragraph"><p>Then, parameters are collected to be able to determine whether this decoration\r
+drawing is actually necessary or was already done. This saves a substantial\r
+number of redraws (depending on your workload, but far over 50%).</p></div>\r
+<div class="paragraph"><p>Assuming that we need to draw this decoration, we start by filling the empty\r
+space around the child window (think of MPlayer with a specific aspect ratio)\r
+in the user-configured client background color.</p></div>\r
+<div class="paragraph"><p>Afterwards, we draw the appropriate border (in case of border styles "normal"\r
+and "1pixel") and the top bar (in case of border style "normal").</p></div>\r
+<div class="paragraph"><p>The last step is drawing the window title on the top bar.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_user_commands_parser_specs_commands_spec">16. User commands (parser-specs/commands.spec)</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>In the configuration file and when using i3 interactively (with <tt>i3-msg</tt>, for\r
+example), you use commands to make i3 do things, like focus a different window,\r
+set a window to fullscreen, and so on. An example command is <tt>floating enable</tt>,\r
+which enables floating mode for the currently focused window. See the\r
+appropriate section in the <a href="userguide.html">User’s Guide</a> for a reference of\r
+all commands.</p></div>\r
+<div class="paragraph"><p>In earlier versions of i3, interpreting these commands was done using lex and\r
+yacc, but experience has shown that lex and yacc are not well suited for our\r
+command language. Therefore, starting from version 4.2, we use a custom parser\r
+for user commands (not yet for the configuration file).\r
+The input specification for this parser can be found in the file\r
+<tt>parser-specs/commands.spec</tt>. Should you happen to use Vim as an editor, use\r
+:source parser-specs/highlighting.vim to get syntax highlighting for this file\r
+(highlighting files for other editors are welcome).</p></div>\r
+<div class="listingblock">\r
+<div class="title">Excerpt from commands.spec</div>\r
+<div class="content">\r
+<pre><tt>state INITIAL:\r
+  '[' -&gt; call cmd_criteria_init(); CRITERIA\r
+  'move' -&gt; MOVE\r
+  'exec' -&gt; EXEC\r
+  'workspace' -&gt; WORKSPACE\r
+  'exit' -&gt; call cmd_exit()\r
+  'restart' -&gt; call cmd_restart()\r
+  'reload' -&gt; call cmd_reload()</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The input specification is written in an extremely simple format. The\r
+specification is then converted into C code by the Perl script\r
+generate-commands-parser.pl (the output file names begin with GENERATED and the\r
+files are stored in the <tt>include</tt> directory). The parser implementation\r
+<tt>src/commands_parser.c</tt> includes the generated C code at compile-time.</p></div>\r
+<div class="paragraph"><p>The above excerpt from commands.spec illustrates nearly all features of our\r
+specification format: You describe different states and what can happen within\r
+each state. State names are all-caps; the state in the above excerpt is called\r
+INITIAL. A list of tokens and their actions (separated by an ASCII arrow)\r
+follows. In the excerpt, all tokens are literals, that is, simple text strings\r
+which will be compared with the input. An action is either the name of a state\r
+in which the parser will transition into, or the keyword <em>call</em>, followed by\r
+the name of a function (and optionally a state).</p></div>\r
+<div class="sect2">\r
+<h3 id="_example_the_workspace_state">16.1. Example: The WORKSPACE state</h3>\r
+<div class="paragraph"><p>Let’s have a look at the WORKSPACE state, which is a good example of all\r
+features. This is its definition:</p></div>\r
+<div class="listingblock">\r
+<div class="title">WORKSPACE state (commands.spec)</div>\r
+<div class="content">\r
+<pre><tt># workspace next|prev|next_on_output|prev_on_output\r
+# workspace back_and_forth\r
+# workspace &lt;name&gt;\r
+state WORKSPACE:\r
+  direction = 'next_on_output', 'prev_on_output', 'next', 'prev'\r
+      -&gt; call cmd_workspace($direction)\r
+  'back_and_forth'\r
+      -&gt; call cmd_workspace_back_and_forth()\r
+  workspace = string\r
+      -&gt; call cmd_workspace_name($workspace)</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>As you can see from the commands, there are multiple different valid variants\r
+of the workspace command:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+workspace &lt;direction&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+        The word <em>workspace</em> can be followed by any of the tokens <em>next</em>,\r
+        <em>prev</em>, <em>next_on_output</em> or <em>prev_on_output</em>. This command will\r
+        switch to the next or previous workspace (optionally on the same\r
+        output).<br />\r
+        There is one function called <tt>cmd_workspace</tt>, which is defined\r
+        in <tt>src/commands.c</tt>. It will handle this kind of command. To know which\r
+        direction was specified, the direction token is stored on the stack\r
+        with the name "direction", which is what the "direction = " means in\r
+        the beginning.<br />\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Note</div>\r
+</td>\r
+<td class="content">Note that you can specify multiple literals in the same line. This has\r
+        exactly the same effect as if you specified <tt>direction =\r
+        'next_on_output' -&gt; call cmd_workspace($direction)</tt> and so forth.<br /></td>\r
+</tr></table>\r
+</div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Note</div>\r
+</td>\r
+<td class="content">Also note that the order of literals is important here: If <em>next</em> were\r
+        ordered before <em>next_on_output</em>, then <em>next_on_output</em> would never\r
+        match.</td>\r
+</tr></table>\r
+</div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+workspace back_and_forth\r
+</dt>\r
+<dd>\r
+<p>\r
+        This is a very simple case: When the literal <em>back_and_forth</em> is found\r
+        in the input, the function <tt>cmd_workspace_back_and_forth</tt> will be\r
+        called without parameters and the parser will return to the INITIAL\r
+        state (since no other state was specified).\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+workspace &lt;name&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+        In this case, the workspace command is followed by an arbitrary string,\r
+        possibly in quotes, for example "workspace 3" or "workspace bleh".<br />\r
+        This is the first time that the token is actually not a literal (not in\r
+        single quotes), but just called string. Other possible tokens are word\r
+        (the same as string, but stops matching at a whitespace) and end\r
+        (matches the end of the input).\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_introducing_a_new_command">16.2. Introducing a new command</h3>\r
+<div class="paragraph"><p>The following steps have to be taken in order to properly introduce a new\r
+command (or possibly extend an existing command):</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Define a function beginning with <tt>cmd_</tt> in the file <tt>src/commands.c</tt>. Copy\r
+   the prototype of an existing function.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+After adding a comment on what the function does, copy the comment and\r
+   function definition to <tt>include/commands.h</tt>. Make the comment in the header\r
+   file use double asterisks to make doxygen pick it up.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Write a test case (or extend an existing test case) for your feature, see\r
+   <a href="testsuite.html">i3 testsuite</a>. For now, it is sufficient to simply call\r
+   your command in all the various possible ways.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Extend the parser specification in <tt>parser-specs/commands.spec</tt>. Run the\r
+   testsuite and see if your new function gets called with the appropriate\r
+   arguments for the appropriate input.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Actually implement the feature.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Document the feature in the <a href="userguide.html">User’s Guide</a>.\r
+</p>\r
+</li>\r
+</ol></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_moving_containers">17. Moving containers</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>The movement code is pretty delicate. You need to consider all cases before\r
+making any changes or before being able to fully understand how it works.</p></div>\r
+<div class="sect2">\r
+<h3 id="_case_1_moving_inside_the_same_container">17.1. Case 1: Moving inside the same container</h3>\r
+<div class="paragraph"><p>The reference layout for this case is a single workspace in horizontal\r
+orientation with two containers on it. Focus is on the left container (1).</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">1</p></td>\r
+<td align="center" valign="top"><p class="table">2</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>When moving the left window to the right (command <tt>move right</tt>), tree_move will\r
+look for a container with horizontal orientation and finds the parent of the\r
+left container, that is, the workspace. Afterwards, it runs the code branch\r
+commented with "the easy case": it calls TAILQ_NEXT to get the container right\r
+of the current one and swaps both containers.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_case_2_move_a_container_into_a_split_container">17.2. Case 2: Move a container into a split container</h3>\r
+<div class="paragraph"><p>The reference layout for this case is a horizontal workspace with two\r
+containers. The right container is a v-split with two containers. Focus is on\r
+the left container (1).</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 rowspan="2" align="center" valign="middle"><p class="table">1</p></td>\r
+<td align="center" valign="top"><p class="table">2</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">3</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>When moving to the right (command <tt>move right</tt>), i3 will work like in case 1\r
+("the easy case"). However, as the right container is not a leaf container, but\r
+a v-split, the left container (1) will be inserted at the right position (below\r
+2, assuming that 2 is focused inside the v-split) by calling <tt>insert_con_into</tt>.</p></div>\r
+<div class="paragraph"><p><tt>insert_con_into</tt> detaches the container from its parent and inserts it\r
+before/after the given target container. Afterwards, the on_remove_child\r
+callback is called on the old parent container which will then be closed, if\r
+empty.</p></div>\r
+<div class="paragraph"><p>Afterwards, <tt>con_focus</tt> will be called to fix the focus stack and the tree will\r
+be flattened.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_case_3_moving_to_non_existant_top_bottom">17.3. Case 3: Moving to non-existant top/bottom</h3>\r
+<div class="paragraph"><p>Like in case 1, the reference layout for this case is a single workspace in\r
+horizontal orientation with two containers on it. Focus is on the left\r
+container:</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">1</p></td>\r
+<td align="center" valign="top"><p class="table">2</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>This time however, the command is <tt>move up</tt> or <tt>move down</tt>. tree_move will look\r
+for a container with vertical orientation. As it will not find any,\r
+<tt>same_orientation</tt> is NULL and therefore i3 will perform a forced orientation\r
+change on the workspace by creating a new h-split container, moving the\r
+workspace contents into it and then changing the workspace orientation to\r
+vertical. Now it will again search for parent containers with vertical\r
+orientation and it will find the workspace.</p></div>\r
+<div class="paragraph"><p>This time, the easy case code path will not be run as we are not moving inside\r
+the same container. Instead, <tt>insert_con_into</tt> will be called with the focused\r
+container and the container above/below the current one (on the level of\r
+<tt>same_orientation</tt>).</p></div>\r
+<div class="paragraph"><p>Now, <tt>con_focus</tt> will be called to fix the focus stack and the tree will be\r
+flattened.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_case_4_moving_to_existant_top_bottom">17.4. Case 4: Moving to existant top/bottom</h3>\r
+<div class="paragraph"><p>The reference layout for this case is a vertical workspace with two containers.\r
+The bottom one is a h-split containing two containers (1 and 2). Focus is on\r
+the bottom left container (1).</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 colspan="2" align="center" valign="top"><p class="table">3</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">1</p></td>\r
+<td align="center" valign="top"><p class="table">2</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>This case is very much like case 3, only this time the forced workspace\r
+orientation change does not need to be performed because the workspace already\r
+is in vertical orientation.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_case_5_moving_in_one_child_h_split">17.5. Case 5: Moving in one-child h-split</h3>\r
+<div class="paragraph"><p>The reference layout for this case is a horizontal workspace with two\r
+containers having a v-split on the left side with a one-child h-split on the\r
+bottom. Focus is on the bottom left container (2(h)):</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">1</p></td>\r
+<td rowspan="2" align="center" valign="middle"><p class="table">3</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center" valign="top"><p class="table">2(h)</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>In this case, <tt>same_orientation</tt> will be set to the h-split container around\r
+the focused container. However, when trying the easy case, the next/previous\r
+container <tt>swap</tt> will be NULL. Therefore, i3 will search again for a\r
+<tt>same_orientation</tt> container, this time starting from the parent of the h-split\r
+container.</p></div>\r
+<div class="paragraph"><p>After determining a new <tt>same_orientation</tt> container (if it is NULL, the\r
+orientation will be force-changed), this case is equivalent to case 2 or case\r
+4.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_case_6_floating_containers">17.6. Case 6: Floating containers</h3>\r
+<div class="paragraph"><p>The reference layout for this case is a horizontal workspace with two\r
+containers plus one floating h-split container. Focus is on the floating\r
+container.</p></div>\r
+<div class="paragraph"><p>TODO: nice illustration. table not possible?</p></div>\r
+<div class="paragraph"><p>When moving up/down, the container needs to leave the floating container and it\r
+needs to be placed on the workspace (at workspace level). This is accomplished\r
+by calling the function <tt>attach_to_workspace</tt>.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_click_handling">18. Click handling</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Without much ado, here is the list of cases which need to be considered:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+click to focus (tiling + floating) and raise (floating)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+click to focus/raise when in stacked/tabbed mode\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+floating_modifier + left mouse button to drag a floating con\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+floating_modifier + right mouse button to resize a floating con\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+click on decoration in a floating con to either initiate a resize (if there\r
+  is more than one child in the floating con) or to drag the\r
+  floating con (if it’s the one at the top).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+click on border in a floating con to resize the floating con\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+floating_modifier + right mouse button to resize a tiling con\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+click on border/decoration to resize a tiling con\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_gotchas">19. 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
+<li>\r
+<p>\r
+Forgetting to call <tt>floating_fix_coordinates(con, old_rect, new_rect)</tt> after\r
+  moving workspaces across outputs. Coordinates for floating containers are\r
+  not relative to workspace boundaries, so you must correct their coordinates\r
+  or those containers will show up in the wrong workspace or not at all.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_using_git_sending_patches">20. Using git / sending patches</h2>\r
+<div class="sectionbody">\r
+<div class="sect2">\r
+<h3 id="_introduction">20.1. Introduction</h3>\r
+<div class="paragraph"><p>For a short introduction into using git, see\r
+<a href="http://web.archive.org/web/20121024222556/http://www.spheredev.org/wiki/Git_for_the_lazy">http://web.archive.org/web/20121024222556/http://www.spheredev.org/wiki/Git_for_the_lazy</a>\r
+or, for more documentation, see <a href="http://git-scm.com/documentation">http://git-scm.com/documentation</a></p></div>\r
+<div class="paragraph"><p>Please talk to us before working on new features to see whether they will be\r
+accepted. There are a few things which we don’t want to see in i3, e.g. a\r
+command which will focus windows in an alt+tab like way.</p></div>\r
+<div class="paragraph"><p>When working on bugfixes, please make sure you mention that you are working on\r
+it in the corresponding bugreport at <a href="https://github.com/i3/i3/issues">https://github.com/i3/i3/issues</a> In case\r
+there is no bugreport yet, please create one.</p></div>\r
+<div class="paragraph"><p>After you are done, please submit your work for review at <a href="https://github.com/i3/i3">https://github.com/i3/i3</a></p></div>\r
+<div class="paragraph"><p>Do not send emails to the mailing list or any author directly, and don’t submit\r
+them in the bugtracker, since all reviews should be done in public at\r
+<a href="http://cr.i3wm.org/">http://cr.i3wm.org/</a>. In order to make your review go as fast as possible, you\r
+could have a look at previous reviews and see what the common mistakes are.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_which_branch_to_use">20.2. Which branch to use?</h3>\r
+<div class="paragraph"><p>Work on i3 generally happens in two branches: “master” and “next”. Since\r
+“master” is what people get when they check out the git repository, its\r
+contents are always stable. That is, it contains the source code of the latest\r
+release, plus any bugfixes that were applied since that release.</p></div>\r
+<div class="paragraph"><p>New features are only found in the “next” branch. Therefore, if you are working\r
+on a new feature, use the “next” branch. If you are working on a bugfix, use\r
+the “next” branch, too, but make sure your code also works on “master”.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_thought_experiments">21. Thought experiments</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>In this section, we collect thought experiments, so that we don’t forget our\r
+thoughts about specific topics. They are not necessary to get into hacking i3,\r
+but if you are interested in one of the topics they cover, you should read them\r
+before asking us why things are the way they are or why we don’t implement\r
+things.</p></div>\r
+<div class="sect2">\r
+<h3 id="_using_cgroups_per_workspace">21.1. Using cgroups per workspace</h3>\r
+<div class="paragraph"><p>cgroups (control groups) are a linux-only feature which provides the ability to\r
+group multiple processes. For each group, you can individually set resource\r
+limits, like allowed memory usage. Furthermore, and more importantly for our\r
+purposes, they serve as a namespace, a label which you can attach to processes\r
+and their children.</p></div>\r
+<div class="paragraph"><p>One interesting use for cgroups is having one cgroup per workspace (or\r
+container, doesn’t really matter). That way, you could set different priorities\r
+and have a workspace for important stuff (say, writing a LaTeX document or\r
+programming) and a workspace for unimportant background stuff (say,\r
+JDownloader). Both tasks can obviously consume a lot of I/O resources, but in\r
+this example it doesn’t really matter if JDownloader unpacks the download a\r
+minute earlier or not. However, your compiler should work as fast as possible.\r
+Having one cgroup per workspace, you would assign more resources to the\r
+programming workspace.</p></div>\r
+<div class="paragraph"><p>Another interesting feature is that an inherent problem of the workspace\r
+concept could be solved by using cgroups: When starting an application on\r
+workspace 1, then switching to workspace 2, you will get the application’s\r
+window(s) on workspace 2 instead of the one you started it on. This is because\r
+the window manager does not have any mapping between the process it starts (or\r
+gets started in any way) and the window(s) which appear.</p></div>\r
+<div class="paragraph"><p>Imagine for example using dmenu: The user starts dmenu by pressing Mod+d, dmenu\r
+gets started with PID 3390. The user then decides to launch Firefox, which\r
+takes a long time. So he enters firefox into dmenu and presses enter. Firefox\r
+gets started with PID 4001. When it finally finishes loading, it creates an X11\r
+window and uses MapWindow to make it visible. This is the first time i3\r
+actually gets in touch with Firefox. It decides to map the window, but it has\r
+no way of knowing that this window (even though it has the _NET_WM_PID property\r
+set to 4001) belongs to the dmenu the user started before.</p></div>\r
+<div class="paragraph"><p>How do cgroups help with this? Well, when pressing Mod+d to launch dmenu, i3\r
+would create a new cgroup, let’s call it i3-3390-1. It launches dmenu in that\r
+cgroup, which gets PID 3390. As before, the user enters firefox and Firefox\r
+gets launched with PID 4001. This time, though, the Firefox process with PID\r
+4001 is <strong>also</strong> member of the cgroup i3-3390-1 (because fork()ing in a cgroup\r
+retains the cgroup property). Therefore, when mapping the window, i3 can look\r
+up in which cgroup the process is and can establish a mapping between the\r
+workspace and the window.</p></div>\r
+<div class="paragraph"><p>There are multiple problems with this approach:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Every application has to properly set <tt>_NET_WM_PID</tt>. This is acceptable and\r
+  patches can be written for the few applications which don’t set the hint yet.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+It does only work on Linux, since cgroups are a Linux-only feature. Again,\r
+  this is acceptable.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The main problem is that some applications create X11 windows completely\r
+  independent of UNIX processes. An example for this is Chromium (or\r
+  gnome-terminal), which, when being started a second time, communicates with\r
+  the first process and lets the first process open a new window. Therefore, if\r
+  you have a Chromium window on workspace 2 and you are currently working on\r
+  workspace 3, starting <tt>chromium</tt> does not lead to the desired result (the\r
+  window will open on workspace 2).\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p>Therefore, my conclusion is that the only proper way of fixing the "window gets\r
+opened on the wrong workspace" problem is in the application itself. Most\r
+modern applications support freedesktop startup-notifications  which can be\r
+used for this.</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer" lang="de">\r
+© 2009-2011 Michael Stapelberg, <a href="/impress.html">Impressum</a>\r
+</div>\r
+</body>\r
+</html>\r