partially update hacking-howto with an explanation of the moving code

This commit is contained in:
Michael Stapelberg 2011-02-19 21:45:57 +01:00
parent c5ab16c00d
commit 579551a2bd

View File

@ -1,13 +1,15 @@
Hacking i3: How To
==================
Michael Stapelberg <michael+i3@stapelberg.de>
December 2009
February 2010
This document is intended to be the first thing you read before looking and/or
touching i3s source code. It should contain all important information to help
you understand why things are like they are. If it does not mention something
you find necessary, please do not hesitate to contact me.
PLEASE BEWARE THAT THIS DOCUMENT IS ONLY PARTIALLY UPDATED FOR -tree YET!
== Window Managers
A window manager is not necessarily needed to run X, but it is usually used in
@ -485,6 +487,131 @@ j, k and l, like in vim (h = left, j = down, k = up, l = right). When you just
specify the direction keys, i3 will move the focus in that direction. You can
provide "m" or "s" before the direction to move a window respectively or snap.
== Moving containers
The movement code is pretty delicate. You need to consider all cases before
making any changes or before being able to fully understand how it works.
=== Case 1: Moving inside the same container
The reference layout for this case is a single workspace in horizontal
orientation with two containers on it. Focus is on the left container (1).
[width="15%",cols="^,^"]
|========
| 1 | 2
|========
When moving the left window to the right (command +move right+), tree_move will
look for a container with horizontal orientation and finds the parent of the
left container, that is, the workspace. Afterwards, it runs the code branch
commented with "the easy case": it calls TAILQ_NEXT to get the container right
of the current one and swaps both containers.
=== Case 2: Move a container into a split container
The reference layout for this case is a horizontal workspace with two
containers. The right container is a v-split with two containers. Focus is on
the left container (1).
[width="15%",cols="^,^"]
|========
1.2+^.^| 1 | 2
| 3
|========
When moving to the right (command +move right+), i3 will work like in case 1
("the easy case"). However, as the right container is not a leaf container, but
a v-split, the left container (1) will be inserted at the right position (below
2, assuming that 2 is focused inside the v-split) by calling +insert_con_into+.
+insert_con_into+ detaches the container from its parent and inserts it
before/after the given target container. Afterwards, the on_remove_child
callback is called on the old parent container which will then be closed, if
empty.
Afterwards, +con_focus+ will be called to fix the focus stack and the tree will
be flattened.
=== Case 3: Moving to non-existant top/bottom
Like in case 1, the reference layout for this case is a single workspace in
horizontal orientation with two containers on it. Focus is on the left
container:
[width="15%",cols="^,^"]
|========
| 1 | 2
|========
This time however, the command is +move up+ or +move down+. tree_move will look
for a container with vertical orientation. As it will not find any,
+same_orientation+ is NULL and therefore i3 will perform a forced orientation
change on the workspace by creating a new h-split container, moving the
workspace contents into it and then changing the workspace orientation to
vertical. Now it will again search for parent containers with vertical
orientation and it will find the workspace.
This time, the easy case code path will not be run as we are not moving inside
the same container. Instead, +insert_con_into+ will be called with the focused
container and the container above/below the current one (on the level of
+same_orientation+).
Now, +con_focus+ will be called to fix the focus stack and the tree will be
flattened.
=== Case 4: Moving to existant top/bottom
The reference layout for this case is a vertical workspace with two containers.
The bottom one is a h-split containing two containers (1 and 2). Focus is on
the bottom left container (1).
[width="15%",cols="^,^"]
|========
2+| 3
| 1 | 2
|========
This case is very much like case 3, only this time the forced workspace
orientation change does not need to be performed because the workspace already
is in vertical orientation.
=== Case 5: Moving in one-child h-split
The reference layout for this case is a horizontal workspace with two
containers having a v-split on the left side with a one-child h-split on the
bottom. Focus is on the bottom left container (2(h)):
[width="15%",cols="^,^"]
|========
| 1 1.2+^.^| 3
| 2(h)
|========
In this case, +same_orientation+ will be set to the h-split container around
the focused container. However, when trying the easy case, the next/previous
container +swap+ will be NULL. Therefore, i3 will search again for a
+same_orientation+ container, this time starting from the parent of the h-split
container.
After determining a new +same_orientation+ container (if it is NULL, the
orientation will be force-changed), this case is equivalent to case 2 or case
4.
=== Case 6: Floating containers
The reference layout for this case is a horizontal workspace with two
containers plus one floating h-split container. Focus is on the floating
container.
TODO: nice illustration. table not possible?
When moving up/down, the container needs to leave the floating container and it
needs to be placed on the workspace (at workspace level). This is accomplished
by calling the function +attach_to_workspace+.
== Gotchas
* Forgetting to call `xcb_flush(conn);` after sending a request. This usually