]> git.sur5r.net Git - i3/i3.github.io/blobdiff - docs/3.e/hacking-howto.html
add (versioned) docs for 4.0
[i3/i3.github.io] / docs / 3.e / hacking-howto.html
diff --git a/docs/3.e/hacking-howto.html b/docs/3.e/hacking-howto.html
new file mode 100644 (file)
index 0000000..90029de
--- /dev/null
@@ -0,0 +1,890 @@
+<!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/png" href="/favicon.png">\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
+            <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+i3@stapelberg.de">michael+i3@stapelberg.de</a>&gt;</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&#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 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 &#8220;Virtual\r
+desktops&#8221;.</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
+&#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;container&#8221; names a container\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+&#8220;client&#8221; 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 &#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>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&#8217;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 &lt;command&gt;\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" lang="de">\r
+© 2009-2011 Michael Stapelberg, <a href="/impress.html">Impressum</a>\r
+</div>\r
+</body>\r
+</html>\r