]> git.sur5r.net Git - i3/i3/blobdiff - docs/hacking-howto
Bugfix: Repeatedly try to find screens if none are available (Thanks mxf)
[i3/i3] / docs / hacking-howto
index 24d36d2c438f3dd3bfb528ec6519a1c87798edd8..22649c38b9faea189263494dc1bf11d4a7af0c84 100644 (file)
@@ -1,7 +1,7 @@
 Hacking i3: How To
 ==================
 Michael Stapelberg <michael+i3@stapelberg.de>
-March 2009
+May 2009
 
 This document is intended to be the first thing you read before looking and/or touching
 i3’s source code. It should contain all important information to help you understand
@@ -38,31 +38,110 @@ Restart the window manager
 
 In the following chapters, each of these tasks and their implementation details will be discussed.
 
+=== Tiling window managers
+
+Traditionally, there are two approaches to managing windows: The most common one nowadays is
+floating, which means the user can freely move/resize the windows. The other approach is called
+tiling, which means that your window manager distributing windows to use as much space as
+possible while not overlapping.
+
+The idea behind tiling is that you should not need to waste your time moving/resizing windows
+while you usually want to get some work done. After all, most users sooner or later tend to
+lay out their windows in a way which corresponds to tiling or stacking mode in i3. Therefore,
+why not let i3 do this for you? Certainly, it’s faster than you could ever do it.
+
+The problem with most tiling window managers is that they are too unflexible. In my opinion, a
+window manager is just another tool, and similar to vim which can edit all kinds of text files
+(like source code, HTML, …) and is not limited to a specific file type, a window manager should
+not limit itself to a certain layout (like dwm, awesome, …) but provide mechanisms for you to
+easily create the layout you need at the moment.
+
+=== The layout table
+
+To accomplish flexible layouts, we decided to simply use a table. The table grows and shrinks
+as you need it. Each cell holds a container which then holds windows (see picture below). You
+can use different layouts for each container (default layout and stacking layout).
+
+So, when you open a terminal and immediately open another one, they reside in the same container,
+in default layout. The layout table has exactly one column, one row and therefore one cell.
+When you move one of the terminals to the right, the table needs to grow. It will be expanded
+to two columns and one row. This enables you to have different layouts for each container.
+The table then looks like this:
+
+[width="15%",cols="^,^"]
+|========
+| T1 | T2
+|========
+
+When moving terminal 2 to the bottom, the table will be expanded again.
+
+[width="15%",cols="^,^"]
+|========
+| T1 |
+|    | T2
+|========
+
+You can really think of the layout table like a traditional HTML table, if you’ve ever
+designed one. Especially col- and rowspan work equally. Below you see an example of
+colspan=2 for the first container (which has T1 as window).
+
+[width="15%",cols="^asciidoc"]
+|========
+| T1
+|
+[cols="^,^",frame="none"]
+!========
+! T2 ! T3
+!========
+|========
+
+Furthermore, you can freely resize table cells.
+
 == Files
 
 include/data.h::
 Contains data definitions used by nearly all files. You really need to read this first.
 
 include/*.h::
-Contains forward definitions for all public functions.
+Contains forward definitions for all public functions, aswell as doxygen-compatible
+comments (so if you want to get a bit more of the big picture, either browse all
+header files or use doxygen if you prefer that).
+
+src/client.c::
+Contains all functions which are specific to a certain client (make it
+fullscreen, see if its class/name matches a pattern, kill it, …).
 
 src/commands.c::
-Parsing commands
+Parsing commands and actually execute them (focussing, moving, …).
 
 src/config.c::
-Parses the configuration file
+Parses the configuration file.
 
 src/debug.c::
-Contains debugging functions to print unhandled X events
+Contains debugging functions to print unhandled X events.
+
+src/floating.c::
+Contains functions for floating mode (mostly resizing/dragging).
 
 src/handlers.c::
-Contains all handlers for all kind of X events
+Contains all handlers for all kind of X events (new window title, new hints,
+unmapping, key presses, button presses, …).
 
 src/layout.c::
-Renders your layout (screens, workspaces, containers)
+Renders your layout (screens, workspaces, containers).
 
 src/mainx.c::
-Initializes the window manager
+Initializes the window manager.
+
+src/manage.c::
+Looks at existing or new windows and decides whether to manage them. If so, it
+reparents the window and inserts it into our data structures.
+
+src/resize.c::
+Contains the functions to resize columns/rows in the table.
+
+src/resize.c::
+Contains the functions to resize columns/rows in the table.
 
 src/table.c::
 Manages the most important internal data structure, the design table.
@@ -81,19 +160,27 @@ src/xinerama.c::
 See include/data.h for documented data structures. The most important ones are explained
 right here.
 
-TODO: We need a slick graphic here
+image:bigpicture.png[The Big Picture]
+
+So, the hierarchy is:
+
+. *Virtual screens* (Screen 0 in this example)
+. *Workspaces* (Workspace 1 in this example)
+. *Table* (There can only be one table per Workspace)
+. *Container* (left and right in this example)
+. *Client* (The two clients in the left container)
 
 === Virtual screens
 
 A virtual screen (type `i3Screen`) is generated from the connected screens obtained
-through Xinerama. The difference to the raw Xinerama monitors as seen when using xrandr(1)
+through Xinerama. The difference to the raw Xinerama monitors as seen when using +xrandr(1)+
 is that it falls back to the lowest common resolution of the logical screens.
 
 For example, if your notebook has 1280x800 and you connect a video projector with
-1024x768, set up in clone mode (xrandr \--output VGA \--mode 1024x768 \--same-as LVDS),
+1024x768, set up in clone mode (+xrandr \--output VGA \--mode 1024x768 \--same-as LVDS+),
 i3 will have one virtual screen.
 
-However, if you configure it using xrandr \--output VGA \--mode 1024x768 \--right-of LVDS,
+However, if you configure it using +xrandr \--output VGA \--mode 1024x768 \--right-of LVDS+,
 i3 will generate two virtual screens. For each virtual screen, a new workspace will be
 assigned. New workspaces are created on the screen you are currently on.
 
@@ -141,7 +228,7 @@ chosen for those:
  * ``conn'' is the xcb_connection_t
  * ``event'' is the event of the particular type
  * ``container'' names a container
- * ``client'' names a client, for example when using a `CIRCLEQ_FOREACH`
+ * ``client'' names a client, for example when using a +CIRCLEQ_FOREACH+
 
 == Startup (src/mainx.c, main())
 
@@ -232,7 +319,15 @@ is re-rendered.
 
 == Size hints
 
-TODO
+Size hints specify the minimum/maximum size for a given window aswell as its aspect ratio.
+At the moment, as i3 does not have a floating mode yet, only the aspect ratio is parsed.
+This is important for clients like mplayer, who only set the aspect ratio and resize their
+window to be as small as possible (but only with some video outputs, for example in Xv,
+while when using x11, mplayer does the necessary centering for itself).
+
+So, when an aspect ratio was specified, i3 adjusts the height of the window until the
+size maintains the correct aspect ratio. For the code to do this, see src/layout.c,
+function resize_client().
 
 == Rendering (src/layout.c, render_layout() and render_container())
 
@@ -281,9 +376,26 @@ when rendering.
 
 === Resizing containers
 
-By clicking and dragging the border of a container, you can resize it freely.
+By clicking and dragging the border of a container, you can resize the whole column
+(respectively row) which this container is in. This is necessary to keep the table
+layout working and consistent.
+
+Currently, only vertical resizing is implemented.
 
-TODO
+The resizing works similarly to the resizing of floating windows or movement of floating
+windows:
+
+* A new, invisible window with the size of the root window is created (+grabwin+)
+* Another window, 2px width and as high as your screen (or vice versa for horizontal
+  resizing) is created. Its background color is the border color and it is only
+  there to signalize the user how big the container will be (it creates the impression
+  of dragging the border out of the container).
+* The +drag_pointer+ function of +src/floating.c+ is called to grab the pointer and
+  enter an own event loop which will pass all events (expose events) but motion notify
+  events. This function then calls the specified callback (+resize_callback+) which
+  does some boundary checking and moves the helper window. As soon as the mouse
+  button is released, this loop will be terminated.
+* The new width_factor for each involved column (respectively row) will be calculated.
 
 == User commands / commandmode (src/commands.c)
 
@@ -314,3 +426,31 @@ direction to move a window respectively or snap.
 * Forgetting to call `xcb_flush(conn);` after sending a request. This usually leads to
   code which looks like it works fine but which does not work under certain conditions.
 
+== Using git / sending patches
+
+For a short introduction into using git, see http://www.spheredev.org/wiki/Git_for_the_lazy
+or, for more documentation, see http://git-scm.com/documentation
+
+When you want to send a patch because you fixed a bug or implemented a cool feature (please
+talk to us before working on features to see whether they are maybe already implemented, not
+possible because of some reason or don’t fit into the concept), please use git to create
+a patchfile.
+
+First of all, update your working copy to the latest version of the master branch:
+
+--------
+git pull
+--------
+
+Afterwards, make the necessary changes for your bugfix/feature. Then, review the changes
+using +git diff+ (you might want to enable colors in the diff using +git config diff.color auto+).
+When you are definitely done, use +git commit -a+ to commit all changes you’ve made.
+
+Then, use the following command to generate a patchfile which we can directly apply to
+the branch, preserving your commit message and name:
+
+-----------------------
+git format-patch origin
+-----------------------
+
+Just send us the generated file via mail.