Merge pull request #4057 from orestisfl/hacking-howto
Update first 1/3 of hacking-howto document
This commit is contained in:
commit
e4629d678e
|
@ -38,4 +38,4 @@ Note that bug reports and feature requests for related projects should be filed
|
||||||
* Find a [reproducible bug](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Areproducible+label%3Abug+) from the issue tracker. These issues have been reviewed and confirmed by a project contributor.
|
* Find a [reproducible bug](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Areproducible+label%3Abug+) from the issue tracker. These issues have been reviewed and confirmed by a project contributor.
|
||||||
* Find an [accepted enhancement](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Aaccepted+label%3Aenhancement) from the issue tracker. These have been approved and are ok to start working on.
|
* Find an [accepted enhancement](https://github.com/i3/i3/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Aaccepted+label%3Aenhancement) from the issue tracker. These have been approved and are ok to start working on.
|
||||||
|
|
||||||
There's a very good [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
|
There's an [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import drawtree;
|
||||||
|
treeLevelStep = 2cm;
|
||||||
|
TreeNode n94457831379296 = makeNode("``root'' (splith) []");
|
||||||
|
TreeNode n94457831380944 = makeNode(n94457831379296, "``\_\_i3'' (output) []");
|
||||||
|
TreeNode n94457831384048 = makeNode(n94457831380944, "``content'' (splith) []");
|
||||||
|
TreeNode n94457831387184 = makeNode(n94457831384048, "``\_\_i3\_scratch'' (splith) []");
|
||||||
|
TreeNode n94457831390576 = makeNode(n94457831379296, "``eDP-1'' (output) []");
|
||||||
|
TreeNode n94457831393744 = makeNode(n94457831390576, "``topdock'' (dockarea) []");
|
||||||
|
TreeNode n94457831396992 = makeNode(n94457831390576, "``content'' (splith) []");
|
||||||
|
TreeNode n94457831628304 = makeNode(n94457831396992, "``1'' (splith) []");
|
||||||
|
TreeNode n94457831571040 = makeNode(n94457831628304, "``Hacking i3: How To - Mozilla Firefox'' (leaf) []");
|
||||||
|
TreeNode n94457831246384 = makeNode(n94457831628304, "``vim'' (leaf) []");
|
||||||
|
TreeNode n94457831461088 = makeNode(n94457831396992, "``Named workspace'' (splith) []");
|
||||||
|
TreeNode n94457831471424 = makeNode(n94457831461088, "``[Empty]'' (tabbed) []");
|
||||||
|
TreeNode n94457831570576 = makeNode(n94457831471424, "``contrib/dump-asy.pl --no-gv'' (leaf) [Marks go here]");
|
||||||
|
TreeNode n94457831645488 = makeNode(n94457831471424, "``ipython'' (leaf) []");
|
||||||
|
TreeNode n94457831400192 = makeNode(n94457831390576, "``bottomdock'' (dockarea) []");
|
||||||
|
TreeNode n94457831424848 = makeNode(n94457831400192, "``i3bar for output eDP-1'' (leaf) []");
|
||||||
|
draw(n94457831379296, (0, 0));
|
Binary file not shown.
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 330 KiB |
Binary file not shown.
|
@ -8,6 +8,19 @@ touching i3’s source code. It should contain all important information to help
|
||||||
you understand why things are like they are. If it does not mention something
|
you understand why things are like they are. If it does not mention something
|
||||||
you find necessary, please do not hesitate to contact me.
|
you find necessary, please do not hesitate to contact me.
|
||||||
|
|
||||||
|
++++
|
||||||
|
<div style="background-color:red; color:white; padding:20px;">
|
||||||
|
<strong style="color:white;">WARNING!</strong>
|
||||||
|
<p>
|
||||||
|
++++
|
||||||
|
This document is not 100% up to date. Specifically, everything up to and
|
||||||
|
including <<data_structures>> has been updated recently. The rest might contain
|
||||||
|
outdated information.
|
||||||
|
++++
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
++++
|
||||||
|
|
||||||
== Building i3
|
== Building i3
|
||||||
|
|
||||||
You can build i3 like you build any other software package which uses autotools.
|
You can build i3 like you build any other software package which uses autotools.
|
||||||
|
@ -18,60 +31,51 @@ Here’s a memory refresher:
|
||||||
$ ../configure
|
$ ../configure
|
||||||
$ make -j8
|
$ make -j8
|
||||||
|
|
||||||
(The autoreconf -fi step is unnecessary if you are building from a release tarball,
|
The autoreconf -fi step is unnecessary if you are building from a release
|
||||||
but shouldn’t hurt either.)
|
tarball, but shouldn’t hurt either.
|
||||||
|
|
||||||
=== Build system features
|
=== Build system features
|
||||||
|
|
||||||
* We use the AX_ENABLE_BUILDDIR macro to enforce builds happening in a separate
|
* We use the +AX_ENABLE_BUILDDIR+ macro to enforce builds happening in a separate
|
||||||
directory. This is a prerequisite for the AX_EXTEND_SRCDIR macro and building
|
directory. This is a prerequisite for the +AX_EXTEND_SRCDIR+ macro and building
|
||||||
in a separate directory is common practice anyway. In case this causes any
|
in a separate directory is common practice anyway. In case this causes any
|
||||||
trouble when packaging i3 for your distribution, please open an issue.
|
trouble when packaging i3 for your distribution, please open an issue.
|
||||||
|
|
||||||
* “make check” runs the i3 testsuite. See docs/testsuite for details.
|
* +make check+ runs the i3 testsuite. See docs/testsuite for details.
|
||||||
|
|
||||||
* “make distcheck” (runs testsuite on “make dist” result, tiny bit quicker
|
* +make distcheck+ (runs testsuite on +make dist+ result, tiny bit quicker
|
||||||
feedback cycle than waiting for the travis build to catch the issue).
|
feedback cycle than waiting for the travis build to catch the issue).
|
||||||
|
|
||||||
* “make uninstall” (occasionally requested by users who compile from source)
|
* +make uninstall+ (occasionally requested by users who compile from source)
|
||||||
|
|
||||||
* “make” will build manpages/docs by default if the tools are installed.
|
* +make+ will build manpages/docs by default if the tools are installed.
|
||||||
Conversely, manpages/docs are not tried to be built for users who don’t want
|
Conversely, manpages/docs are not tried to be built for users who don’t want
|
||||||
to install all these dependencies to get started hacking on i3.
|
to install all these dependencies to get started hacking on i3. Manpages and
|
||||||
|
docs can be disabled with the +--disable-mans++ and ++--disable-docs++
|
||||||
|
configure options respectively.
|
||||||
|
|
||||||
* non-release builds will enable address sanitizer by default. Use the
|
* non-release builds will enable address sanitizer by default. Use the
|
||||||
--disable-sanitizers configure option to turn off all sanitizers, and see
|
+--disable-sanitizers+ configure option to turn off all sanitizers, and see
|
||||||
--help for available sanitizers.
|
+--help+ for available sanitizers.
|
||||||
|
|
||||||
* Support for pre-compiled headers (PCH) has been dropped for now in the
|
* Coverage reports are now generated using +make check-code-coverage+, which
|
||||||
interest of simplicity. If you need support for PCH, please open an issue.
|
requires specifying +--enable-code-coverage+ when calling configure.
|
||||||
|
|
||||||
* Coverage reports are now generated using “make check-code-coverage”, which
|
== Pull requests
|
||||||
requires specifying --enable-code-coverage when calling configure.
|
|
||||||
|
|
||||||
== Using git / sending patches
|
|
||||||
|
|
||||||
For a short introduction into using git, see
|
|
||||||
https://web.archive.org/web/20121024222556/http://www.spheredev.org/wiki/Git_for_the_lazy
|
|
||||||
or, for more documentation, see https://git-scm.com/documentation
|
|
||||||
|
|
||||||
Please talk to us before working on new features to see whether they will be
|
Please talk to us before working on new features to see whether they will be
|
||||||
accepted. A good way for this is to open an issue and asking for opinions on it.
|
accepted. A good way for this is to open an issue and asking for opinions on it.
|
||||||
Even for accepted features, this can be a good way to refine an idea upfront. However,
|
Even for accepted features, this can be a good way to refine an idea upfront.
|
||||||
we don't want to see certain features in i3, e.g., switching window focus in an
|
However, we don't want to see certain features in i3, e.g., switching window
|
||||||
Alt+Tab like way.
|
focus in an Alt+Tab like way.
|
||||||
|
|
||||||
When working on bugfixes, please make sure you mention that you are working on
|
When working on bugfixes, please make sure you mention that you are working on it
|
||||||
it in the corresponding bug report at https://github.com/i3/i3/issues. In case
|
in the corresponding bug report at https://github.com/i3/i3/issues. In case there
|
||||||
there is no bug report yet, please create one.
|
is no bug report yet, please create one.
|
||||||
|
|
||||||
After you are done, please submit your work for review as a pull request at
|
After you are done, please submit your work for review as a pull request at
|
||||||
https://github.com/i3/i3.
|
https://github.com/i3/i3. In order to make your review go as fast as possible,
|
||||||
|
you could have a look at previous reviews and see what the common mistakes are.
|
||||||
Do not send emails to the mailing list or any author directly, and don’t submit
|
|
||||||
them in the bugtracker, since all reviews should be done in public at
|
|
||||||
https://github.com/i3/i3. In order to make your review go as fast as possible, you
|
|
||||||
could have a look at previous reviews and see what the common mistakes are.
|
|
||||||
|
|
||||||
=== Which branch to use?
|
=== Which branch to use?
|
||||||
|
|
||||||
|
@ -82,9 +86,8 @@ repository).
|
||||||
The contents of “master” are always stable. That is, it contains the source code
|
The contents of “master” are always stable. That is, it contains the source code
|
||||||
of the latest release, plus any bugfixes that were applied since that release.
|
of the latest release, plus any bugfixes that were applied since that release.
|
||||||
|
|
||||||
New features are only found in the “next” branch. Therefore, if you are working
|
New features are only found in the “next” branch. Always use this branch when
|
||||||
on a new feature, use the “next” branch. If you are working on a bugfix, use the
|
writing new code (both bugfixes and features).
|
||||||
“next” branch, too, but make sure your code also works on “master”.
|
|
||||||
|
|
||||||
== Window Managers
|
== Window Managers
|
||||||
|
|
||||||
|
@ -106,9 +109,9 @@ In the case of i3, the tasks (and order of them) are the following:
|
||||||
the first client of X) and manage them (reparent them, create window
|
the first client of X) and manage them (reparent them, create window
|
||||||
decorations, etc.)
|
decorations, etc.)
|
||||||
. When new windows are created, manage them
|
. When new windows are created, manage them
|
||||||
. Handle the client’s `_WM_STATE` property, but only `_WM_STATE_FULLSCREEN` and
|
. Handle the client’s +_WM_STATE+ property, but only +_WM_STATE_FULLSCREEN+ and
|
||||||
`_NET_WM_STATE_DEMANDS_ATTENTION`
|
+_NET_WM_STATE_DEMANDS_ATTENTION+
|
||||||
. Handle the client’s `WM_NAME` property
|
. Handle the client’s +WM_NAME+ property
|
||||||
. Handle the client’s size hints to display them proportionally
|
. Handle the client’s size hints to display them proportionally
|
||||||
. Handle the client’s urgency hint
|
. Handle the client’s urgency hint
|
||||||
. Handle enter notifications (focus follows mouse)
|
. Handle enter notifications (focus follows mouse)
|
||||||
|
@ -123,11 +126,11 @@ will be discussed.
|
||||||
|
|
||||||
=== Tiling window managers
|
=== Tiling window managers
|
||||||
|
|
||||||
Traditionally, there are two approaches to managing windows: The most common
|
Traditionally, there are two approaches to managing windows: The most common one
|
||||||
one nowadays is floating, which means the user can freely move/resize the
|
nowadays is stacking (or floating, using i3's terminology), which means the user
|
||||||
windows. The other approach is called tiling, which means that your window
|
can freely move/resize the windows, potentially overlapping them. The other
|
||||||
manager distributes windows to use as much space as possible while not
|
approach is called tiling, which means that the window manager distributes
|
||||||
overlapping each other.
|
windows to use as much space as possible while not overlapping each other.
|
||||||
|
|
||||||
The idea behind tiling is that you should not need to waste your time
|
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
|
moving/resizing windows while you usually want to get some work done. After
|
||||||
|
@ -161,63 +164,67 @@ example.
|
||||||
|
|
||||||
== Files
|
== Files
|
||||||
|
|
||||||
include/atoms.xmacro::
|
i3's source code is in the +src+ folder while header files reside in +include+.
|
||||||
A file containing all X11 atoms which i3 uses. This file will be included
|
Other tools such as i3bar and i3-nagbar have their own folders. i3 and its tools
|
||||||
various times (for defining, requesting and receiving the atoms), each time
|
share an internal library called ``libi3'' which also has its own folder.
|
||||||
with a different definition of xmacro().
|
|
||||||
|
The following list gives an overview of the codebase, explaining the
|
||||||
|
functionality of the most important, core source code files. Other files in the
|
||||||
|
tree that are not mentioned here implement specific functionalities: for example,
|
||||||
|
+src/scratchpad.c+ is obviously about the scratchpad functionality.
|
||||||
|
|
||||||
include/data.h::
|
include/data.h::
|
||||||
Contains data definitions used by nearly all files. You really need to read
|
Contains data definitions used by nearly all files.
|
||||||
this first.
|
|
||||||
|
|
||||||
include/*.h::
|
include/*.h::
|
||||||
Contains forward definitions for all public functions, as well as
|
Contains forward definitions for all public functions, as well as
|
||||||
doxygen-compatible comments (so if you want to get a bit more of the big
|
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).
|
picture, either browse all header files or use doxygen if you prefer that).
|
||||||
|
|
||||||
src/config_parser.c::
|
src/config_directives.c::
|
||||||
Contains a custom configuration parser. See src/command_parser.c for rationale
|
src/commands.c::
|
||||||
on why we use a custom parser.
|
Contain the definitions for all high-level config and command directives. These
|
||||||
|
are excellent places to start with a top-to-bottom approach to understand
|
||||||
src/click.c::
|
specific i3 behavior. For example, if you want to investigate a bug that happens
|
||||||
Contains all functions which handle mouse button clicks (right mouse button
|
for the +move to mark+ command, you can use gdb to pause in
|
||||||
clicks initiate resizing and thus are relatively complex).
|
+cmd_move_con_to_mark+ and then work your way from there, stepping into
|
||||||
|
lower-level functions.
|
||||||
src/command_parser.c::
|
|
||||||
Contains a hand-written parser to parse commands (commands are what
|
|
||||||
you bind on keys and what you can send to i3 using the IPC interface, like
|
|
||||||
'move left' or 'workspace 4').
|
|
||||||
|
|
||||||
src/con.c::
|
src/con.c::
|
||||||
Contains all functions which deal with containers directly (creating
|
Contains all functions which deal with containers directly (creating containers,
|
||||||
containers, searching containers, getting specific properties from containers,
|
searching containers, getting specific properties from containers, …). Contains
|
||||||
…).
|
abstractions and auxiliary functions necessary to work with the container
|
||||||
|
structure which is used in almost all parts of the codebase.
|
||||||
|
|
||||||
src/config.c::
|
src/tree.c::
|
||||||
Contains all functions handling the configuration file (calling the parser
|
Contains functions which deal with the tree abstraction. However, be aware that
|
||||||
src/config_parser.c) with the correct path, switching key bindings mode).
|
+src/con.c+ also contains functions that heavily interact with the tree
|
||||||
|
structure. Some functions that are included in +str/tree.c+ are those that handle
|
||||||
|
opening and closing containers in the tree, finding the container that should be
|
||||||
|
focused next and flattening the tree. See also +src/move.c+ for other
|
||||||
|
move-specific functions that interact with the tree, which were moved into their
|
||||||
|
own file because they are so long.
|
||||||
|
|
||||||
src/ewmh.c::
|
src/workspace.c::
|
||||||
Functions to get/set certain EWMH properties easily.
|
Contains functions which deal with workspaces. Includes code that creates new
|
||||||
|
workspaces, shows existing ones and deals with workspace assignments.
|
||||||
src/floating.c::
|
|
||||||
Contains functions for floating mode (mostly resizing/dragging).
|
|
||||||
|
|
||||||
src/handlers.c::
|
src/handlers.c::
|
||||||
Contains all handlers for all kinds of X events (new window title, new hints,
|
Contains all handlers for all kinds of X events (new window title, new hints,
|
||||||
unmapping, key presses, button presses, …).
|
unmapping, key presses, button presses, …). This is a very important file to
|
||||||
|
understand how i3 interacts with changes to its environment.
|
||||||
|
|
||||||
src/ipc.c::
|
src/command_parser.c::
|
||||||
Contains code for the IPC interface.
|
src/config_parser.c::
|
||||||
|
Contain a hand-written parser to parse commands and configuration (commands are what
|
||||||
|
you bind on keys and what you can send to i3 using the IPC interface, like
|
||||||
|
+move left+ or +workspace 4+). +src/config.c+ is responsible for calling the
|
||||||
|
configuration parser.
|
||||||
|
|
||||||
src/load_layout.c::
|
src/click.c::
|
||||||
Contains code for loading layouts from JSON files.
|
src/resize.c::
|
||||||
|
Contain functions which handle mouse button clicks (right mouse button
|
||||||
src/log.c::
|
clicks initiate resizing and thus are relatively complex).
|
||||||
Contains the logging functions.
|
|
||||||
|
|
||||||
src/main.c::
|
|
||||||
Initializes the window manager.
|
|
||||||
|
|
||||||
src/manage.c::
|
src/manage.c::
|
||||||
Looks at existing or new windows and decides whether to manage them. If so, it
|
Looks at existing or new windows and decides whether to manage them. If so, it
|
||||||
|
@ -226,93 +233,66 @@ reparents the window and inserts it into our data structures.
|
||||||
src/match.c::
|
src/match.c::
|
||||||
A "match" is a data structure which acts like a mask or expression to match
|
A "match" is a data structure which acts like a mask or expression to match
|
||||||
certain windows or not. For example, when using commands, you can specify a
|
certain windows or not. For example, when using commands, you can specify a
|
||||||
command like this: [title="*Firefox*"] kill. The title member of the match
|
command like this: +[title="*Firefox*"] kill+. The title member of the match
|
||||||
data structure will then be filled and i3 will check each window using
|
data structure will then be filled and i3 will check each window using
|
||||||
match_matches_window() to find the windows affected by this command.
|
+match_matches_window()+ to find the windows affected by this command.
|
||||||
|
|
||||||
src/move.c::
|
|
||||||
Contains code to move a container in a specific direction.
|
|
||||||
|
|
||||||
src/output.c::
|
|
||||||
Functions to handle CT_OUTPUT cons.
|
|
||||||
|
|
||||||
src/randr.c::
|
src/randr.c::
|
||||||
The RandR API is used to get (and re-query) the configured outputs (monitors,
|
The RandR API is used to get (and re-query) the configured outputs (monitors,
|
||||||
…).
|
…). Legacy Xinerama support resides in +src/xinerama.c+.
|
||||||
|
|
||||||
src/render.c::
|
src/render.c::
|
||||||
Renders the tree data structure by assigning coordinates to every node. These
|
Renders the tree data structure by assigning coordinates to every node. These
|
||||||
values will later be pushed to X11 in +src/x.c+.
|
values will later be pushed to X11 in +src/x.c+.
|
||||||
|
|
||||||
src/resize.c::
|
|
||||||
Contains the functions to resize containers.
|
|
||||||
|
|
||||||
src/restore_layout.c::
|
|
||||||
Everything for restored containers that is not pure state parsing (which can be
|
|
||||||
found in load_layout.c).
|
|
||||||
|
|
||||||
src/sighandler.c::
|
src/sighandler.c::
|
||||||
Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
|
Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
|
||||||
You can chose to let it dump core, to restart it in-place or to restart it
|
You can choose to let it dump core and restart i3 in-place (either trying to
|
||||||
in-place but forget about the layout.
|
preserve layout or forget about it).
|
||||||
|
|
||||||
src/tree.c::
|
|
||||||
Contains functions which open or close containers in the tree, change focus or
|
|
||||||
cleanup ("flatten") the tree. See also +src/move.c+ for another similar
|
|
||||||
function, which was moved into its own file because it is so long.
|
|
||||||
|
|
||||||
src/util.c::
|
|
||||||
Contains useful functions which are not really dependent on anything.
|
|
||||||
|
|
||||||
src/window.c::
|
src/window.c::
|
||||||
Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+,
|
Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+,
|
||||||
+CLIENT_LEADER+, etc.
|
+CLIENT_LEADER+, etc.
|
||||||
|
|
||||||
src/workspace.c::
|
include/atoms.xmacro::
|
||||||
Contains all functions related to workspaces (displaying, hiding, renaming…)
|
A file containing all X11 atoms which i3 uses. This file will be included
|
||||||
|
various times (for defining, requesting and receiving the atoms), each time
|
||||||
src/x.c::
|
with a different definition of xmacro().
|
||||||
Transfers our in-memory tree (see +src/render.c+) to X11.
|
|
||||||
|
|
||||||
src/xcb.c::
|
|
||||||
Contains wrappers to use xcb more easily.
|
|
||||||
|
|
||||||
src/xcursor.c::
|
|
||||||
XCursor functions (for cursor themes).
|
|
||||||
|
|
||||||
src/xinerama.c::
|
|
||||||
Legacy support for Xinerama. See +src/randr.c+ for the preferred API.
|
|
||||||
|
|
||||||
|
[[data_structures]]
|
||||||
== Data structures
|
== Data structures
|
||||||
|
|
||||||
|
See +include/data.h+ for documented data structures. The most important ones are
|
||||||
|
explained here.
|
||||||
|
|
||||||
See include/data.h for documented data structures. The most important ones are
|
The following picture is generated by the +contrib/dump-asy.pl+ script.
|
||||||
explained right here.
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
image:bigpicture.png["The Big Picture",width=1000,link="bigpicture.png"]
|
||||||
// TODO: update image
|
|
||||||
|
|
||||||
image:bigpicture.png[The Big Picture]
|
The hierarchy is:
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
. *Root container*
|
||||||
|
. *Output containers*: +eDP-1+ in this example and the internal +__i3++ output
|
||||||
So, the hierarchy is:
|
. *Content and 2 dockarea containers*
|
||||||
|
. *Workspaces*: Numbered workspace ``1'' and a ``Named workspace''
|
||||||
. *X11 root window*, the root container
|
. *Split containers*: One horizontal in the first workspace and a tabbed one in
|
||||||
. *Output container* (LVDS1 in this example)
|
the named one.
|
||||||
. *Content container* (there are also containers for dock windows)
|
. *Leaf containers*: Windows like vim and an i3bar dock.
|
||||||
. *Workspaces* (Workspace 1 in this example, with horizontal orientation)
|
|
||||||
. *Split container* (vertically split)
|
|
||||||
. *X11 window containers*
|
|
||||||
|
|
||||||
The data type is +Con+, in all cases.
|
The data type is +Con+, in all cases.
|
||||||
|
|
||||||
=== X11 root window
|
=== Root container
|
||||||
|
|
||||||
The X11 root window is a single window per X11 display (a display is identified
|
The root container (global variable +croot+) is the up-most ascendant of every i3
|
||||||
by +:0+ or +:1+ etc.). The root window is what you draw your background image
|
container. It can be used to iterate over the whole tree structure. E.g., it is
|
||||||
on. It spans all the available outputs, e.g. +VGA1+ is a specific part of the
|
used to reply to the +GET_WORKSPACES+ request, iterating over it's children to
|
||||||
root window and +LVDS1+ is a specific part of the root window.
|
find all workspaces. This is different from the X11 root window.
|
||||||
|
|
||||||
|
The X11 root window (global variable +root+) is a single window per X11 display
|
||||||
|
(a display is identified by +:0+ or +:1+ etc.). The root window is what you draw
|
||||||
|
your background image on. It spans all the available outputs, e.g. +VGA1+ is a
|
||||||
|
specific part of the root window and +LVDS1+ is a specific part of the root
|
||||||
|
window.
|
||||||
|
|
||||||
=== Output container
|
=== Output container
|
||||||
|
|
||||||
|
@ -334,8 +314,8 @@ currently on.
|
||||||
=== Content container
|
=== Content container
|
||||||
|
|
||||||
Each output has multiple children. Two of them are dock containers which hold
|
Each output has multiple children. Two of them are dock containers which hold
|
||||||
dock clients. The other one is the content container, which holds the actual
|
the top and bottom dock clients. The other one is the content container, which
|
||||||
content (workspaces) of this output.
|
holds the actual content (workspaces) of this output.
|
||||||
|
|
||||||
=== Workspace
|
=== Workspace
|
||||||
|
|
||||||
|
@ -354,21 +334,20 @@ vertical) and a layout.
|
||||||
Split containers (and X11 window containers, which are a subtype of split
|
Split containers (and X11 window containers, which are a subtype of split
|
||||||
containers) can have different border styles.
|
containers) can have different border styles.
|
||||||
|
|
||||||
=== X11 window container
|
=== Leaf containers
|
||||||
|
|
||||||
An X11 window container holds exactly one X11 window. These are the leaf nodes
|
A leaf container holds exactly one X11 window. They can't have any children.
|
||||||
of the layout tree, they cannot have any children.
|
|
||||||
|
|
||||||
== List/queue macros
|
== List/queue macros
|
||||||
|
|
||||||
i3 makes heavy use of the list macros defined in BSD operating systems. To
|
i3 makes heavy use of the list macros defined in BSD operating systems. To
|
||||||
ensure that the operating system on which i3 is compiled has all the expected
|
ensure that the operating system on which i3 is compiled has all the expected
|
||||||
features, i3 comes with `include/queue.h`. On BSD systems, you can use man
|
features, i3 comes with +include/queue.h+. On BSD systems, you can use +man
|
||||||
`queue(3)`. On Linux, you have to use google (or read the source).
|
queue(3)+. On Linux, you have to use google (or read the source).
|
||||||
|
|
||||||
The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular
|
The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular
|
||||||
queues) and +TAILQ+ (tail queues). Usually, only forward traversal is necessary,
|
queues) and +TAILQ+ (tail queues). Usually, only forward traversal is necessary,
|
||||||
so an `SLIST` works fine. If inserting elements at arbitrary positions or at
|
so an +SLIST+ works fine. If inserting elements at arbitrary positions or at
|
||||||
the end of a list is necessary, a +TAILQ+ is used instead. However, for the
|
the end of a list is necessary, a +TAILQ+ is used instead. However, for the
|
||||||
windows inside a container, a +CIRCLEQ+ is necessary to go from the currently
|
windows inside a container, a +CIRCLEQ+ is necessary to go from the currently
|
||||||
selected window to the window above/below.
|
selected window to the window above/below.
|
||||||
|
@ -378,10 +357,10 @@ selected window to the window above/below.
|
||||||
There is a row of standard variables used in many events. The following names
|
There is a row of standard variables used in many events. The following names
|
||||||
should be chosen for those:
|
should be chosen for those:
|
||||||
|
|
||||||
* ``conn'' is the xcb_connection_t
|
* +conn+ is the xcb_connection_t
|
||||||
* ``event'' is the event of the particular type
|
* +event+ is the event of the particular type
|
||||||
* ``con'' names a container
|
* +con+ names a container
|
||||||
* ``current'' is a loop variable when using +TAILQ_FOREACH+ etc.
|
* +current+ is a loop variable when using +TAILQ_FOREACH+ etc.
|
||||||
|
|
||||||
== Startup (src/mainx.c, main())
|
== Startup (src/mainx.c, main())
|
||||||
|
|
||||||
|
@ -430,7 +409,7 @@ The bound command is parsed by the cmdparse lexer/parser, see +parse_cmd+ in
|
||||||
|
|
||||||
== Manage windows (src/main.c, manage_window() and reparent_window())
|
== Manage windows (src/main.c, manage_window() and reparent_window())
|
||||||
|
|
||||||
`manage_window()` does some checks to decide whether the window should be
|
+manage_window()+ does some checks to decide whether the window should be
|
||||||
managed at all:
|
managed at all:
|
||||||
|
|
||||||
* Windows have to be mapped, that is, visible on screen
|
* Windows have to be mapped, that is, visible on screen
|
||||||
|
@ -438,18 +417,18 @@ managed at all:
|
||||||
not be managed by a window manager
|
not be managed by a window manager
|
||||||
|
|
||||||
Afterwards, i3 gets the initial geometry and reparents the window (see
|
Afterwards, i3 gets the initial geometry and reparents the window (see
|
||||||
`reparent_window()`) if it wasn’t already managed.
|
+reparent_window()+) if it wasn’t already managed.
|
||||||
|
|
||||||
Reparenting means that for each window which is reparented, a new window,
|
Reparenting means that for each window which is reparented, a new window,
|
||||||
slightly larger than the original one, is created. The original window is then
|
slightly larger than the original one, is created. The original window is then
|
||||||
reparented to the bigger one (called "frame").
|
reparented to the bigger one (called "frame").
|
||||||
|
|
||||||
After reparenting, the window type (`_NET_WM_WINDOW_TYPE`) is checked to see
|
After reparenting, the window type (+_NET_WM_WINDOW_TYPE+) is checked to see
|
||||||
whether this window is a dock (`_NET_WM_WINDOW_TYPE_DOCK`), like dzen2 for
|
whether this window is a dock (+_NET_WM_WINDOW_TYPE_DOCK+), like dzen2 for
|
||||||
example. Docks are handled differently, they don’t have decorations and are not
|
example. Docks are handled differently, they don’t have decorations and are not
|
||||||
assigned to a specific container. Instead, they are positioned at the bottom
|
assigned to a specific container. Instead, they are positioned at the bottom
|
||||||
or top of the screen (in the appropriate dock area containers). To get the
|
or top of the screen (in the appropriate dock area containers). To get the
|
||||||
height which needs to be reserved for the window, the `_NET_WM_STRUT_PARTIAL`
|
height which needs to be reserved for the window, the +_NET_WM_STRUT_PARTIAL+
|
||||||
property is used.
|
property is used.
|
||||||
|
|
||||||
Furthermore, the list of assignments (to other workspaces, which may be on
|
Furthermore, the list of assignments (to other workspaces, which may be on
|
||||||
|
@ -460,10 +439,10 @@ target workspace is not visible, the window will not be mapped.
|
||||||
== What happens when an application is started?
|
== What happens when an application is started?
|
||||||
|
|
||||||
i3 does not care about applications. All it notices is when new windows are
|
i3 does not care about applications. All it notices is when new windows are
|
||||||
mapped (see `src/handlers.c`, `handle_map_request()`). The window is then
|
mapped (see +src/handlers.c+, +handle_map_request()+). The window is then
|
||||||
reparented (see section "Manage windows").
|
reparented (see section "Manage windows").
|
||||||
|
|
||||||
After reparenting the window, `render_tree()` is called which renders the
|
After reparenting the window, +render_tree()+ is called which renders the
|
||||||
internal layout table. The new window has been placed in the currently focused
|
internal layout table. The new window has been placed in the currently focused
|
||||||
container and therefore the new window and the old windows (if any) need to be
|
container and therefore the new window and the old windows (if any) need to be
|
||||||
moved/resized so that the currently active layout (default/stacking/tabbed mode)
|
moved/resized so that the currently active layout (default/stacking/tabbed mode)
|
||||||
|
@ -482,7 +461,7 @@ can reconfigure themselves).
|
||||||
Only the _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION atoms
|
Only the _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION atoms
|
||||||
are handled.
|
are handled.
|
||||||
|
|
||||||
The former calls ``toggle_fullscreen()'' for the specific client which just
|
The former calls +toggle_fullscreen()+ for the specific client which just
|
||||||
configures the client to use the whole screen on which it currently is.
|
configures the client to use the whole screen on which it currently is.
|
||||||
Also, it is set as fullscreen_client for the i3Screen.
|
Also, it is set as fullscreen_client for the i3Screen.
|
||||||
|
|
||||||
|
@ -539,7 +518,7 @@ container) to the bottom.
|
||||||
|
|
||||||
=== Rendering the root container
|
=== Rendering the root container
|
||||||
|
|
||||||
The i3 root container (`con->type == CT_ROOT`) represents the X11 root window.
|
The i3 root container (+con->type == CT_ROOT+) represents the X11 root window.
|
||||||
It contains one child container for every output (like LVDS1, VGA1, …), which
|
It contains one child container for every output (like LVDS1, VGA1, …), which
|
||||||
is available on your computer.
|
is available on your computer.
|
||||||
|
|
||||||
|
@ -558,7 +537,7 @@ only called for the global fullscreen window.
|
||||||
|
|
||||||
=== Rendering an output
|
=== Rendering an output
|
||||||
|
|
||||||
Output containers (`con->layout == L_OUTPUT`) represent a hardware output like
|
Output containers (+con->layout == L_OUTPUT+) represent a hardware output like
|
||||||
LVDS1, VGA1, etc. An output container has three children (at the moment): One
|
LVDS1, VGA1, etc. An output container has three children (at the moment): One
|
||||||
content container (having workspaces as children) and the top/bottom dock area
|
content container (having workspaces as children) and the top/bottom dock area
|
||||||
containers.
|
containers.
|
||||||
|
@ -566,7 +545,7 @@ containers.
|
||||||
The rendering happens in the function +render_l_output()+ in the following
|
The rendering happens in the function +render_l_output()+ in the following
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
1. Find the content container (`con->type == CT_CON`)
|
1. Find the content container (+con->type == CT_CON+)
|
||||||
2. Get the currently visible workspace (+con_get_fullscreen_con(content,
|
2. Get the currently visible workspace (+con_get_fullscreen_con(content,
|
||||||
CF_OUTPUT)+).
|
CF_OUTPUT)+).
|
||||||
3. If there is a fullscreened window on that workspace, directly render it and
|
3. If there is a fullscreened window on that workspace, directly render it and
|
||||||
|
@ -574,22 +553,22 @@ steps:
|
||||||
4. Sum up the space used by all the dock windows (they have a variable height
|
4. Sum up the space used by all the dock windows (they have a variable height
|
||||||
only).
|
only).
|
||||||
5. Set the workspace rects (x/y/width/height) based on the position of the
|
5. Set the workspace rects (x/y/width/height) based on the position of the
|
||||||
output (stored in `con->rect`) and the usable space
|
output (stored in +con->rect+) and the usable space
|
||||||
(`con->rect.{width,height}` without the space used for dock windows).
|
(+con->rect.{width,height}+ without the space used for dock windows).
|
||||||
6. Recursively raise and render the output’s child containers (meaning dock
|
6. Recursively raise and render the output’s child containers (meaning dock
|
||||||
area containers and the content container).
|
area containers and the content container).
|
||||||
|
|
||||||
=== Rendering a workspace or split container
|
=== Rendering a workspace or split container
|
||||||
|
|
||||||
From here on, there really is no difference anymore. All containers are of
|
From here on, there really is no difference anymore. All containers are of
|
||||||
`con->type == CT_CON` (whether workspace or split container) and some of them
|
+con->type == CT_CON+ (whether workspace or split container) and some of them
|
||||||
have a `con->window`, meaning they represent an actual window instead of a
|
have a +con->window+, meaning they represent an actual window instead of a
|
||||||
split container.
|
split container.
|
||||||
|
|
||||||
==== Default layout
|
==== Default layout
|
||||||
|
|
||||||
In default layout, containers are placed horizontally or vertically next to
|
In default layout, containers are placed horizontally or vertically next to
|
||||||
each other (depending on the `con->orientation`). If a child is a leaf node (as
|
each other (depending on the +con->orientation+). If a child is a leaf node (as
|
||||||
opposed to a split container) and has border style "normal", appropriate space
|
opposed to a split container) and has border style "normal", appropriate space
|
||||||
will be reserved for its window decoration.
|
will be reserved for its window decoration.
|
||||||
|
|
||||||
|
@ -835,8 +814,8 @@ workspace <direction>::
|
||||||
the beginning. +
|
the beginning. +
|
||||||
|
|
||||||
NOTE: Note that you can specify multiple literals in the same line. This has
|
NOTE: Note that you can specify multiple literals in the same line. This has
|
||||||
exactly the same effect as if you specified `direction =
|
exactly the same effect as if you specified +direction =
|
||||||
'next_on_output' -> call cmd_workspace($direction)` and so forth. +
|
'next_on_output' -> call cmd_workspace($direction)+ and so forth. +
|
||||||
|
|
||||||
NOTE: Also note that the order of literals is important here: If 'next' were
|
NOTE: Also note that the order of literals is important here: If 'next' were
|
||||||
ordered before 'next_on_output', then 'next_on_output' would never
|
ordered before 'next_on_output', then 'next_on_output' would never
|
||||||
|
@ -1020,11 +999,11 @@ Without much ado, here is the list of cases which need to be considered:
|
||||||
|
|
||||||
== Gotchas
|
== Gotchas
|
||||||
|
|
||||||
* Forgetting to call `xcb_flush(conn);` after sending a request. This usually
|
* 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
|
leads to code which looks like it works fine but which does not work under
|
||||||
certain conditions.
|
certain conditions.
|
||||||
|
|
||||||
* Forgetting to call `floating_fix_coordinates(con, old_rect, new_rect)` after
|
* Forgetting to call +floating_fix_coordinates(con, old_rect, new_rect)+ after
|
||||||
moving workspaces across outputs. Coordinates for floating containers are
|
moving workspaces across outputs. Coordinates for floating containers are
|
||||||
not relative to workspace boundaries, so you must correct their coordinates
|
not relative to workspace boundaries, so you must correct their coordinates
|
||||||
or those containers will show up in the wrong workspace or not at all.
|
or those containers will show up in the wrong workspace or not at all.
|
||||||
|
|
Loading…
Reference in New Issue