Codebase list i3-gaps / 66d2eba
Merge remote-tracking branch 'vanilla/next' into gaps-next Ingo Bürk 4 years ago
14 changed file(s) with 303 addition(s) and 329 deletion(s). Raw diff Collapse all Expand all
3737 * 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.
3838 * 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.
3939
40 There's a very good [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
40 There's an [overview of the codebase](https://i3wm.org/docs/hacking-howto.html) available to get you started.
1616 • make dock client order deterministic (sorted by class/instance) as a
1717 side effect, i3bars without an explicit bar-id will be sorted according
1818 to their definition order in the config file
19 • update i3bar config when necessary (reduces redraws on bar mode changes)
20 • mention rofi in default config file
1921
2022 ┌────────────────────────────┐
2123 │ Bugfixes │
3234 • i3-dmenu-desktop: Support symlinks in search path
3335 • build: correctly provide auxiliary functions when needed
3436 • build: fix issues with parallel build
37 • set _NET_DESKTOP_VIEWPORT after randr changes
0 import drawtree;
1 treeLevelStep = 2cm;
2 TreeNode n94457831379296 = makeNode("``root'' (splith) []");
3 TreeNode n94457831380944 = makeNode(n94457831379296, "``\_\_i3'' (output) []");
4 TreeNode n94457831384048 = makeNode(n94457831380944, "``content'' (splith) []");
5 TreeNode n94457831387184 = makeNode(n94457831384048, "``\_\_i3\_scratch'' (splith) []");
6 TreeNode n94457831390576 = makeNode(n94457831379296, "``eDP-1'' (output) []");
7 TreeNode n94457831393744 = makeNode(n94457831390576, "``topdock'' (dockarea) []");
8 TreeNode n94457831396992 = makeNode(n94457831390576, "``content'' (splith) []");
9 TreeNode n94457831628304 = makeNode(n94457831396992, "``1'' (splith) []");
10 TreeNode n94457831571040 = makeNode(n94457831628304, "``Hacking i3: How To - Mozilla Firefox'' (leaf) []");
11 TreeNode n94457831246384 = makeNode(n94457831628304, "``vim'' (leaf) []");
12 TreeNode n94457831461088 = makeNode(n94457831396992, "``Named workspace'' (splith) []");
13 TreeNode n94457831471424 = makeNode(n94457831461088, "``[Empty]'' (tabbed) []");
14 TreeNode n94457831570576 = makeNode(n94457831471424, "``contrib/dump-asy.pl --no-gv'' (leaf) [Marks go here]");
15 TreeNode n94457831645488 = makeNode(n94457831471424, "``ipython'' (leaf) []");
16 TreeNode n94457831400192 = makeNode(n94457831390576, "``bottomdock'' (dockarea) []");
17 TreeNode n94457831424848 = makeNode(n94457831400192, "``i3bar for output eDP-1'' (leaf) []");
18 draw(n94457831379296, (0, 0));
Binary diff not shown
docs/bigpicture.xcf less more
Binary diff not shown
77 you understand why things are like they are. If it does not mention something
88 you find necessary, please do not hesitate to contact me.
99
10 ++++
11 <div style="background-color:red; color:white; padding:20px;">
12 <strong style="color:white;">WARNING!</strong>
13 <p>
14 ++++
15 This document is not 100% up to date. Specifically, everything up to and
16 including <<data_structures>> has been updated recently. The rest might contain
17 outdated information.
18 ++++
19 </p>
20 </div>
21 ++++
22
1023 == Building i3
1124
1225 You can build i3 like you build any other software package which uses autotools.
1730 $ ../configure
1831 $ make -j8
1932
20 (The autoreconf -fi step is unnecessary if you are building from a release tarball,
21 but shouldn’t hurt either.)
33 The autoreconf -fi step is unnecessary if you are building from a release
34 tarball, but shouldn’t hurt either.
2235
2336 === Build system features
2437
25 * We use the AX_ENABLE_BUILDDIR macro to enforce builds happening in a separate
26 directory. This is a prerequisite for the AX_EXTEND_SRCDIR macro and building
38 * We use the +AX_ENABLE_BUILDDIR+ macro to enforce builds happening in a separate
39 directory. This is a prerequisite for the +AX_EXTEND_SRCDIR+ macro and building
2740 in a separate directory is common practice anyway. In case this causes any
2841 trouble when packaging i3 for your distribution, please open an issue.
2942
30 * “make check” runs the i3 testsuite. See docs/testsuite for details.
31
32 * “make distcheck” (runs testsuite on “make dist” result, tiny bit quicker
43 * +make check+ runs the i3 testsuite. See docs/testsuite for details.
44
45 * +make distcheck+ (runs testsuite on +make dist+ result, tiny bit quicker
3346 feedback cycle than waiting for the travis build to catch the issue).
3447
35 * “make uninstall” (occasionally requested by users who compile from source)
36
37 * “make” will build manpages/docs by default if the tools are installed.
48 * +make uninstall+ (occasionally requested by users who compile from source)
49
50 * +make+ will build manpages/docs by default if the tools are installed.
3851 Conversely, manpages/docs are not tried to be built for users who don’t want
39 to install all these dependencies to get started hacking on i3.
52 to install all these dependencies to get started hacking on i3. Manpages and
53 docs can be disabled with the +--disable-mans++ and ++--disable-docs++
54 configure options respectively.
4055
4156 * non-release builds will enable address sanitizer by default. Use the
42 --disable-sanitizers configure option to turn off all sanitizers, and see
43 --help for available sanitizers.
44
45 * Support for pre-compiled headers (PCH) has been dropped for now in the
46 interest of simplicity. If you need support for PCH, please open an issue.
47
48 * Coverage reports are now generated using “make check-code-coverage”, which
49 requires specifying --enable-code-coverage when calling configure.
50
51 == Using git / sending patches
52
53 For a short introduction into using git, see
54 https://web.archive.org/web/20121024222556/http://www.spheredev.org/wiki/Git_for_the_lazy
55 or, for more documentation, see https://git-scm.com/documentation
57 +--disable-sanitizers+ configure option to turn off all sanitizers, and see
58 +--help+ for available sanitizers.
59
60 * Coverage reports are now generated using +make check-code-coverage+, which
61 requires specifying +--enable-code-coverage+ when calling configure.
62
63 == Pull requests
5664
5765 Please talk to us before working on new features to see whether they will be
5866 accepted. A good way for this is to open an issue and asking for opinions on it.
59 Even for accepted features, this can be a good way to refine an idea upfront. However,
60 we don't want to see certain features in i3, e.g., switching window focus in an
61 Alt+Tab like way.
62
63 When working on bugfixes, please make sure you mention that you are working on
64 it in the corresponding bug report at https://github.com/i3/i3/issues. In case
65 there is no bug report yet, please create one.
67 Even for accepted features, this can be a good way to refine an idea upfront.
68 However, we don't want to see certain features in i3, e.g., switching window
69 focus in an Alt+Tab like way.
70
71 When working on bugfixes, please make sure you mention that you are working on it
72 in the corresponding bug report at https://github.com/i3/i3/issues. In case there
73 is no bug report yet, please create one.
6674
6775 After you are done, please submit your work for review as a pull request at
68 https://github.com/i3/i3.
69
70 Do not send emails to the mailing list or any author directly, and don’t submit
71 them in the bugtracker, since all reviews should be done in public at
72 https://github.com/i3/i3. In order to make your review go as fast as possible, you
73 could have a look at previous reviews and see what the common mistakes are.
76 https://github.com/i3/i3. In order to make your review go as fast as possible,
77 you could have a look at previous reviews and see what the common mistakes are.
7478
7579 === Which branch to use?
7680
8185 The contents of “master” are always stable. That is, it contains the source code
8286 of the latest release, plus any bugfixes that were applied since that release.
8387
84 New features are only found in the “next” branch. Therefore, if you are working
85 on a new feature, use the “next” branch. If you are working on a bugfix, use the
86 “next” branch, too, but make sure your code also works on “master”.
88 New features are only found in the “next” branch. Always use this branch when
89 writing new code (both bugfixes and features).
8790
8891 == Window Managers
8992
105108 the first client of X) and manage them (reparent them, create window
106109 decorations, etc.)
107110 . When new windows are created, manage them
108 . Handle the client’s `_WM_STATE` property, but only `_WM_STATE_FULLSCREEN` and
109 `_NET_WM_STATE_DEMANDS_ATTENTION`
110 . Handle the client’s `WM_NAME` property
111 . Handle the client’s +_WM_STATE+ property, but only +_WM_STATE_FULLSCREEN+ and
112 +_NET_WM_STATE_DEMANDS_ATTENTION+
113 . Handle the client’s +WM_NAME+ property
111114 . Handle the client’s size hints to display them proportionally
112115 . Handle the client’s urgency hint
113116 . Handle enter notifications (focus follows mouse)
122125
123126 === Tiling window managers
124127
125 Traditionally, there are two approaches to managing windows: The most common
126 one nowadays is floating, which means the user can freely move/resize the
127 windows. The other approach is called tiling, which means that your window
128 manager distributes windows to use as much space as possible while not
129 overlapping each other.
128 Traditionally, there are two approaches to managing windows: The most common one
129 nowadays is stacking (or floating, using i3's terminology), which means the user
130 can freely move/resize the windows, potentially overlapping them. The other
131 approach is called tiling, which means that the window manager distributes
132 windows to use as much space as possible while not overlapping each other.
130133
131134 The idea behind tiling is that you should not need to waste your time
132135 moving/resizing windows while you usually want to get some work done. After
160163
161164 == Files
162165
166 i3's source code is in the +src+ folder while header files reside in +include+.
167 Other tools such as i3bar and i3-nagbar have their own folders. i3 and its tools
168 share an internal library called ``libi3'' which also has its own folder.
169
170 The following list gives an overview of the codebase, explaining the
171 functionality of the most important, core source code files. Other files in the
172 tree that are not mentioned here implement specific functionalities: for example,
173 +src/scratchpad.c+ is obviously about the scratchpad functionality.
174
175 include/data.h::
176 Contains data definitions used by nearly all files.
177
178 include/*.h::
179 Contains forward definitions for all public functions, as well as
180 doxygen-compatible comments (so if you want to get a bit more of the big
181 picture, either browse all header files or use doxygen if you prefer that).
182
183 src/config_directives.c::
184 src/commands.c::
185 Contain the definitions for all high-level config and command directives. These
186 are excellent places to start with a top-to-bottom approach to understand
187 specific i3 behavior. For example, if you want to investigate a bug that happens
188 for the +move to mark+ command, you can use gdb to pause in
189 +cmd_move_con_to_mark+ and then work your way from there, stepping into
190 lower-level functions.
191
192 src/con.c::
193 Contains all functions which deal with containers directly (creating containers,
194 searching containers, getting specific properties from containers, …). Contains
195 abstractions and auxiliary functions necessary to work with the container
196 structure which is used in almost all parts of the codebase.
197
198 src/tree.c::
199 Contains functions which deal with the tree abstraction. However, be aware that
200 +src/con.c+ also contains functions that heavily interact with the tree
201 structure. Some functions that are included in +str/tree.c+ are those that handle
202 opening and closing containers in the tree, finding the container that should be
203 focused next and flattening the tree. See also +src/move.c+ for other
204 move-specific functions that interact with the tree, which were moved into their
205 own file because they are so long.
206
207 src/workspace.c::
208 Contains functions which deal with workspaces. Includes code that creates new
209 workspaces, shows existing ones and deals with workspace assignments.
210
211 src/handlers.c::
212 Contains all handlers for all kinds of X events (new window title, new hints,
213 unmapping, key presses, button presses, …). This is a very important file to
214 understand how i3 interacts with changes to its environment.
215
216 src/command_parser.c::
217 src/config_parser.c::
218 Contain a hand-written parser to parse commands and configuration (commands are what
219 you bind on keys and what you can send to i3 using the IPC interface, like
220 +move left+ or +workspace 4+). +src/config.c+ is responsible for calling the
221 configuration parser.
222
223 src/click.c::
224 src/resize.c::
225 Contain functions which handle mouse button clicks (right mouse button
226 clicks initiate resizing and thus are relatively complex).
227
228 src/manage.c::
229 Looks at existing or new windows and decides whether to manage them. If so, it
230 reparents the window and inserts it into our data structures.
231
232 src/match.c::
233 A "match" is a data structure which acts like a mask or expression to match
234 certain windows or not. For example, when using commands, you can specify a
235 command like this: +[title="*Firefox*"] kill+. The title member of the match
236 data structure will then be filled and i3 will check each window using
237 +match_matches_window()+ to find the windows affected by this command.
238
239 src/randr.c::
240 The RandR API is used to get (and re-query) the configured outputs (monitors,
241 …). Legacy Xinerama support resides in +src/xinerama.c+.
242
243 src/render.c::
244 Renders the tree data structure by assigning coordinates to every node. These
245 values will later be pushed to X11 in +src/x.c+.
246
247 src/sighandler.c::
248 Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
249 You can choose to let it dump core and restart i3 in-place (either trying to
250 preserve layout or forget about it).
251
252 src/window.c::
253 Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+,
254 +CLIENT_LEADER+, etc.
255
163256 include/atoms.xmacro::
164257 A file containing all X11 atoms which i3 uses. This file will be included
165258 various times (for defining, requesting and receiving the atoms), each time
166259 with a different definition of xmacro().
167260
168 include/data.h::
169 Contains data definitions used by nearly all files. You really need to read
170 this first.
171
172 include/*.h::
173 Contains forward definitions for all public functions, as well as
174 doxygen-compatible comments (so if you want to get a bit more of the big
175 picture, either browse all header files or use doxygen if you prefer that).
176
177 src/config_parser.c::
178 Contains a custom configuration parser. See src/command_parser.c for rationale
179 on why we use a custom parser.
180
181 src/click.c::
182 Contains all functions which handle mouse button clicks (right mouse button
183 clicks initiate resizing and thus are relatively complex).
184
185 src/command_parser.c::
186 Contains a hand-written parser to parse commands (commands are what
187 you bind on keys and what you can send to i3 using the IPC interface, like
188 'move left' or 'workspace 4').
189
190 src/con.c::
191 Contains all functions which deal with containers directly (creating
192 containers, searching containers, getting specific properties from containers,
193 …).
194
195 src/config.c::
196 Contains all functions handling the configuration file (calling the parser
197 src/config_parser.c) with the correct path, switching key bindings mode).
198
199 src/ewmh.c::
200 Functions to get/set certain EWMH properties easily.
201
202 src/floating.c::
203 Contains functions for floating mode (mostly resizing/dragging).
204
205 src/handlers.c::
206 Contains all handlers for all kinds of X events (new window title, new hints,
207 unmapping, key presses, button presses, …).
208
209 src/ipc.c::
210 Contains code for the IPC interface.
211
212 src/load_layout.c::
213 Contains code for loading layouts from JSON files.
214
215 src/log.c::
216 Contains the logging functions.
217
218 src/main.c::
219 Initializes the window manager.
220
221 src/manage.c::
222 Looks at existing or new windows and decides whether to manage them. If so, it
223 reparents the window and inserts it into our data structures.
224
225 src/match.c::
226 A "match" is a data structure which acts like a mask or expression to match
227 certain windows or not. For example, when using commands, you can specify a
228 command like this: [title="*Firefox*"] kill. The title member of the match
229 data structure will then be filled and i3 will check each window using
230 match_matches_window() to find the windows affected by this command.
231
232 src/move.c::
233 Contains code to move a container in a specific direction.
234
235 src/output.c::
236 Functions to handle CT_OUTPUT cons.
237
238 src/randr.c::
239 The RandR API is used to get (and re-query) the configured outputs (monitors,
240 …).
241
242 src/render.c::
243 Renders the tree data structure by assigning coordinates to every node. These
244 values will later be pushed to X11 in +src/x.c+.
245
246 src/resize.c::
247 Contains the functions to resize containers.
248
249 src/restore_layout.c::
250 Everything for restored containers that is not pure state parsing (which can be
251 found in load_layout.c).
252
253 src/sighandler.c::
254 Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
255 You can chose to let it dump core, to restart it in-place or to restart it
256 in-place but forget about the layout.
257
258 src/tree.c::
259 Contains functions which open or close containers in the tree, change focus or
260 cleanup ("flatten") the tree. See also +src/move.c+ for another similar
261 function, which was moved into its own file because it is so long.
262
263 src/util.c::
264 Contains useful functions which are not really dependent on anything.
265
266 src/window.c::
267 Handlers to update X11 window properties like +WM_CLASS+, +_NET_WM_NAME+,
268 +CLIENT_LEADER+, etc.
269
270 src/workspace.c::
271 Contains all functions related to workspaces (displaying, hiding, renaming…)
272
273 src/x.c::
274 Transfers our in-memory tree (see +src/render.c+) to X11.
275
276 src/xcb.c::
277 Contains wrappers to use xcb more easily.
278
279 src/xcursor.c::
280 XCursor functions (for cursor themes).
281
282 src/xinerama.c::
283 Legacy support for Xinerama. See +src/randr.c+ for the preferred API.
284
261 [[data_structures]]
285262 == Data structures
286263
287
288 See include/data.h for documented data structures. The most important ones are
289 explained right here.
290
291 /////////////////////////////////////////////////////////////////////////////////
292 // TODO: update image
293
294 image:bigpicture.png[The Big Picture]
295
296 /////////////////////////////////////////////////////////////////////////////////
297
298 So, the hierarchy is:
299
300 . *X11 root window*, the root container
301 . *Output container* (LVDS1 in this example)
302 . *Content container* (there are also containers for dock windows)
303 . *Workspaces* (Workspace 1 in this example, with horizontal orientation)
304 . *Split container* (vertically split)
305 . *X11 window containers*
264 See +include/data.h+ for documented data structures. The most important ones are
265 explained here.
266
267 The following picture is generated by the +contrib/dump-asy.pl+ script.
268
269 image:bigpicture.png["The Big Picture",width=1000,link="bigpicture.png"]
270
271 The hierarchy is:
272
273 . *Root container*
274 . *Output containers*: +eDP-1+ in this example and the internal +__i3++ output
275 . *Content and 2 dockarea containers*
276 . *Workspaces*: Numbered workspace ``1'' and a ``Named workspace''
277 . *Split containers*: One horizontal in the first workspace and a tabbed one in
278 the named one.
279 . *Leaf containers*: Windows like vim and an i3bar dock.
306280
307281 The data type is +Con+, in all cases.
308282
309 === X11 root window
310
311 The X11 root window is a single window per X11 display (a display is identified
312 by +:0+ or +:1+ etc.). The root window is what you draw your background image
313 on. It spans all the available outputs, e.g. +VGA1+ is a specific part of the
314 root window and +LVDS1+ is a specific part of the root window.
283 === Root container
284
285 The root container (global variable +croot+) is the up-most ascendant of every i3
286 container. It can be used to iterate over the whole tree structure. E.g., it is
287 used to reply to the +GET_WORKSPACES+ request, iterating over it's children to
288 find all workspaces. This is different from the X11 root window.
289
290 The X11 root window (global variable +root+) is a single window per X11 display
291 (a display is identified by +:0+ or +:1+ etc.). The root window is what you draw
292 your background image on. It spans all the available outputs, e.g. +VGA1+ is a
293 specific part of the root window and +LVDS1+ is a specific part of the root
294 window.
315295
316296 === Output container
317297
333313 === Content container
334314
335315 Each output has multiple children. Two of them are dock containers which hold
336 dock clients. The other one is the content container, which holds the actual
337 content (workspaces) of this output.
316 the top and bottom dock clients. The other one is the content container, which
317 holds the actual content (workspaces) of this output.
338318
339319 === Workspace
340320
353333 Split containers (and X11 window containers, which are a subtype of split
354334 containers) can have different border styles.
355335
356 === X11 window container
357
358 An X11 window container holds exactly one X11 window. These are the leaf nodes
359 of the layout tree, they cannot have any children.
336 === Leaf containers
337
338 A leaf container holds exactly one X11 window. They can't have any children.
360339
361340 == List/queue macros
362341
363342 i3 makes heavy use of the list macros defined in BSD operating systems. To
364343 ensure that the operating system on which i3 is compiled has all the expected
365 features, i3 comes with `include/queue.h`. On BSD systems, you can use man
366 `queue(3)`. On Linux, you have to use google (or read the source).
344 features, i3 comes with +include/queue.h+. On BSD systems, you can use +man
345 queue(3)+. On Linux, you have to use google (or read the source).
367346
368347 The lists used are +SLIST+ (single linked lists), +CIRCLEQ+ (circular
369348 queues) and +TAILQ+ (tail queues). Usually, only forward traversal is necessary,
370 so an `SLIST` works fine. If inserting elements at arbitrary positions or at
349 so an +SLIST+ works fine. If inserting elements at arbitrary positions or at
371350 the end of a list is necessary, a +TAILQ+ is used instead. However, for the
372351 windows inside a container, a +CIRCLEQ+ is necessary to go from the currently
373352 selected window to the window above/below.
377356 There is a row of standard variables used in many events. The following names
378357 should be chosen for those:
379358
380 * ``conn'' is the xcb_connection_t
381 * ``event'' is the event of the particular type
382 * ``con'' names a container
383 * ``current'' is a loop variable when using +TAILQ_FOREACH+ etc.
359 * +conn+ is the xcb_connection_t
360 * +event+ is the event of the particular type
361 * +con+ names a container
362 * +current+ is a loop variable when using +TAILQ_FOREACH+ etc.
384363
385364 == Startup (src/mainx.c, main())
386365
429408
430409 == Manage windows (src/main.c, manage_window() and reparent_window())
431410
432 `manage_window()` does some checks to decide whether the window should be
411 +manage_window()+ does some checks to decide whether the window should be
433412 managed at all:
434413
435414 * Windows have to be mapped, that is, visible on screen
437416 not be managed by a window manager
438417
439418 Afterwards, i3 gets the initial geometry and reparents the window (see
440 `reparent_window()`) if it wasn’t already managed.
419 +reparent_window()+) if it wasn’t already managed.
441420
442421 Reparenting means that for each window which is reparented, a new window,
443422 slightly larger than the original one, is created. The original window is then
444423 reparented to the bigger one (called "frame").
445424
446 After reparenting, the window type (`_NET_WM_WINDOW_TYPE`) is checked to see
447 whether this window is a dock (`_NET_WM_WINDOW_TYPE_DOCK`), like dzen2 for
425 After reparenting, the window type (+_NET_WM_WINDOW_TYPE+) is checked to see
426 whether this window is a dock (+_NET_WM_WINDOW_TYPE_DOCK+), like dzen2 for
448427 example. Docks are handled differently, they don’t have decorations and are not
449428 assigned to a specific container. Instead, they are positioned at the bottom
450429 or top of the screen (in the appropriate dock area containers). To get the
451 height which needs to be reserved for the window, the `_NET_WM_STRUT_PARTIAL`
430 height which needs to be reserved for the window, the +_NET_WM_STRUT_PARTIAL+
452431 property is used.
453432
454433 Furthermore, the list of assignments (to other workspaces, which may be on
459438 == What happens when an application is started?
460439
461440 i3 does not care about applications. All it notices is when new windows are
462 mapped (see `src/handlers.c`, `handle_map_request()`). The window is then
441 mapped (see +src/handlers.c+, +handle_map_request()+). The window is then
463442 reparented (see section "Manage windows").
464443
465 After reparenting the window, `render_tree()` is called which renders the
444 After reparenting the window, +render_tree()+ is called which renders the
466445 internal layout table. The new window has been placed in the currently focused
467446 container and therefore the new window and the old windows (if any) need to be
468447 moved/resized so that the currently active layout (default/stacking/tabbed mode)
481460 Only the _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION atoms
482461 are handled.
483462
484 The former calls ``toggle_fullscreen()'' for the specific client which just
463 The former calls +toggle_fullscreen()+ for the specific client which just
485464 configures the client to use the whole screen on which it currently is.
486465 Also, it is set as fullscreen_client for the i3Screen.
487466
538517
539518 === Rendering the root container
540519
541 The i3 root container (`con->type == CT_ROOT`) represents the X11 root window.
520 The i3 root container (+con->type == CT_ROOT+) represents the X11 root window.
542521 It contains one child container for every output (like LVDS1, VGA1, …), which
543522 is available on your computer.
544523
557536
558537 === Rendering an output
559538
560 Output containers (`con->layout == L_OUTPUT`) represent a hardware output like
539 Output containers (+con->layout == L_OUTPUT+) represent a hardware output like
561540 LVDS1, VGA1, etc. An output container has three children (at the moment): One
562541 content container (having workspaces as children) and the top/bottom dock area
563542 containers.
565544 The rendering happens in the function +render_l_output()+ in the following
566545 steps:
567546
568 1. Find the content container (`con->type == CT_CON`)
547 1. Find the content container (+con->type == CT_CON+)
569548 2. Get the currently visible workspace (+con_get_fullscreen_con(content,
570549 CF_OUTPUT)+).
571550 3. If there is a fullscreened window on that workspace, directly render it and
573552 4. Sum up the space used by all the dock windows (they have a variable height
574553 only).
575554 5. Set the workspace rects (x/y/width/height) based on the position of the
576 output (stored in `con->rect`) and the usable space
577 (`con->rect.{width,height}` without the space used for dock windows).
555 output (stored in +con->rect+) and the usable space
556 (+con->rect.{width,height}+ without the space used for dock windows).
578557 6. Recursively raise and render the output’s child containers (meaning dock
579558 area containers and the content container).
580559
581560 === Rendering a workspace or split container
582561
583562 From here on, there really is no difference anymore. All containers are of
584 `con->type == CT_CON` (whether workspace or split container) and some of them
585 have a `con->window`, meaning they represent an actual window instead of a
563 +con->type == CT_CON+ (whether workspace or split container) and some of them
564 have a +con->window+, meaning they represent an actual window instead of a
586565 split container.
587566
588567 ==== Default layout
589568
590569 In default layout, containers are placed horizontally or vertically next to
591 each other (depending on the `con->orientation`). If a child is a leaf node (as
570 each other (depending on the +con->orientation+). If a child is a leaf node (as
592571 opposed to a split container) and has border style "normal", appropriate space
593572 will be reserved for its window decoration.
594573
834813 the beginning. +
835814
836815 NOTE: Note that you can specify multiple literals in the same line. This has
837 exactly the same effect as if you specified `direction =
838 'next_on_output' -> call cmd_workspace($direction)` and so forth. +
816 exactly the same effect as if you specified +direction =
817 'next_on_output' -> call cmd_workspace($direction)+ and so forth. +
839818
840819 NOTE: Also note that the order of literals is important here: If 'next' were
841820 ordered before 'next_on_output', then 'next_on_output' would never
1019998
1020999 == Gotchas
10211000
1022 * Forgetting to call `xcb_flush(conn);` after sending a request. This usually
1001 * Forgetting to call +xcb_flush(conn);+ after sending a request. This usually
10231002 leads to code which looks like it works fine but which does not work under
10241003 certain conditions.
10251004
1026 * Forgetting to call `floating_fix_coordinates(con, old_rect, new_rect)` after
1005 * Forgetting to call +floating_fix_coordinates(con, old_rect, new_rect)+ after
10271006 moving workspaces across outputs. Coordinates for floating containers are
10281007 not relative to workspace boundaries, so you must correct their coordinates
10291008 or those containers will show up in the wrong workspace or not at all.
5252
5353 # start dmenu (a program launcher)
5454 bindsym Mod1+d exec dmenu_run
55 # There also is the (new) i3-dmenu-desktop which only displays applications
56 # shipping a .desktop file. It is a wrapper around dmenu, so you need that
57 # installed.
55 # A more modern dmenu replacement is rofi:
56 # bindsym Mod1+d exec rofi -modi drun,run -show drun
57 # There also is i3-dmenu-desktop which only displays applications shipping a
58 # .desktop file. It is a wrapper around dmenu, so you need that installed.
5859 # bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop
5960
6061 # change focus
4646
4747 # start dmenu (a program launcher)
4848 bindcode $mod+40 exec dmenu_run
49 # There also is the (new) i3-dmenu-desktop which only displays applications
50 # shipping a .desktop file. It is a wrapper around dmenu, so you need that
51 # installed.
52 # bindsym $mod+d exec --no-startup-id i3-dmenu-desktop
49 # A more modern dmenu replacement is rofi:
50 # bindcode $mod+40 exec rofi -modi drun,run -show drun
51 # There also is i3-dmenu-desktop which only displays applications shipping a
52 # .desktop file. It is a wrapper around dmenu, so you need that installed.
53 bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop
5354
5455 # change focus
5556 bindcode $mod+44 focus left
314314 void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name);
315315
316316 /**
317 * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
318 *
319 */
320 void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id);
317 * Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
318 *
319 */
320 void cmd_bar_mode(I3_CMD, const char *bar_mode, const char *bar_id);
321
322 /**
323 * Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
324 *
325 */
326 void cmd_bar_hidden_state(I3_CMD, const char *bar_hidden_state, const char *bar_id);
321327
322328 /**
323329 * Implementation of 'shmlog <size>|toggle|on|off'
436436 *
437437 */
438438 void ungrab_all_keys(xcb_connection_t *conn);
439
440 /**
441 * Sends the current bar configuration as an event to all barconfig_update listeners.
442 *
443 */
444 void update_barconfig(void);
477477 -> BAR_MODE
478478
479479 state BAR_HIDDEN_STATE:
480 bar_value = 'hide', 'show', 'toggle'
481 -> BAR_W_ID
480 bar_hidden_state = 'hide', 'show', 'toggle'
481 ->
482 bar_id = word
483 ->
484 end
485 -> call cmd_bar_hidden_state($bar_hidden_state, $bar_id)
482486
483487 state BAR_MODE:
484488 bar_value = 'dock', 'hide', 'invisible', 'toggle'
485 -> BAR_W_ID
486
487 state BAR_W_ID:
489 ->
488490 bar_id = word
489491 ->
490492 end
491 -> call cmd_bar($bar_type, $bar_value, $bar_id)
493 -> call cmd_bar_mode($bar_value, $bar_id)
16201620 x_set_i3_atoms();
16211621 /* Send an IPC event just in case the ws names have changed */
16221622 ipc_send_workspace_event("reload", NULL, NULL);
1623 /* Send an update event for the barconfig just in case it has changed */
1624 update_barconfig();
1623 /* Send an update event for each barconfig just in case it has changed */
1624 Barconfig *current;
1625 TAILQ_FOREACH (current, &barconfigs, configs) {
1626 ipc_send_barconfig_update_event(current);
1627 }
16251628
16261629 // XXX: default reply for now, make this a better reply
16271630 ysuccess(true);
20742077 * Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
20752078 *
20762079 */
2077 static bool cmd_bar_mode(const char *bar_mode, const char *bar_id) {
2080 void cmd_bar_mode(I3_CMD, const char *bar_mode, const char *bar_id) {
20782081 int mode = M_DOCK;
20792082 bool toggle = false;
20802083 if (strcmp(bar_mode, "dock") == 0)
20872090 toggle = true;
20882091 else {
20892092 ELOG("Unknown bar mode \"%s\", this is a mismatch between code and parser spec.\n", bar_mode);
2090 return false;
2091 }
2092
2093 bool changed_sth = false;
2093 assert(false);
2094 }
2095
20942096 Barconfig *current = NULL;
20952097 TAILQ_FOREACH (current, &barconfigs, configs) {
2096 if (bar_id && strcmp(current->id, bar_id) != 0)
2098 if (strcmp(current->id, bar_id) != 0) {
20972099 continue;
2098
2099 if (toggle)
2100 }
2101
2102 if (toggle) {
21002103 mode = (current->mode + 1) % 2;
2101
2102 DLOG("Changing bar mode of bar_id '%s' to '%s (%d)'\n", current->id, bar_mode, mode);
2103 current->mode = mode;
2104 changed_sth = true;
2105
2106 if (bar_id)
2107 break;
2108 }
2109
2110 if (bar_id && !changed_sth) {
2111 DLOG("Changing bar mode of bar_id %s failed, bar_id not found.\n", bar_id);
2112 return false;
2113 }
2114
2115 return true;
2104 }
2105
2106 DLOG("Changing bar mode of bar_id '%s' from '%d' to '%s (%d)'\n",
2107 current->id, current->mode, bar_mode, mode);
2108 if ((int)current->mode != mode) {
2109 current->mode = mode;
2110 ipc_send_barconfig_update_event(current);
2111 }
2112
2113 ysuccess(true);
2114 return;
2115 }
2116
2117 yerror("Changing bar mode of bar_id %s failed, bar_id not found.\n", bar_id);
21162118 }
21172119
21182120 /*
21192121 * Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
21202122 *
21212123 */
2122 static bool cmd_bar_hidden_state(const char *bar_hidden_state, const char *bar_id) {
2124 void cmd_bar_hidden_state(I3_CMD, const char *bar_hidden_state, const char *bar_id) {
21232125 int hidden_state = S_SHOW;
21242126 bool toggle = false;
21252127 if (strcmp(bar_hidden_state, "hide") == 0)
21302132 toggle = true;
21312133 else {
21322134 ELOG("Unknown bar state \"%s\", this is a mismatch between code and parser spec.\n", bar_hidden_state);
2133 return false;
2134 }
2135
2136 bool changed_sth = false;
2135 assert(false);
2136 }
2137
21372138 Barconfig *current = NULL;
21382139 TAILQ_FOREACH (current, &barconfigs, configs) {
2139 if (bar_id && strcmp(current->id, bar_id) != 0)
2140 if (strcmp(current->id, bar_id) != 0) {
21402141 continue;
2141
2142 if (toggle)
2142 }
2143
2144 if (toggle) {
21432145 hidden_state = (current->hidden_state + 1) % 2;
2144
2145 DLOG("Changing bar hidden_state of bar_id '%s' to '%s (%d)'\n", current->id, bar_hidden_state, hidden_state);
2146 current->hidden_state = hidden_state;
2147 changed_sth = true;
2148
2149 if (bar_id)
2150 break;
2151 }
2152
2153 if (bar_id && !changed_sth) {
2154 DLOG("Changing bar hidden_state of bar_id %s failed, bar_id not found.\n", bar_id);
2155 return false;
2156 }
2157
2158 return true;
2159 }
2160
2161 /*
2162 * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
2163 *
2164 */
2165 void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id) {
2166 bool ret;
2167 if (strcmp(bar_type, "mode") == 0)
2168 ret = cmd_bar_mode(bar_value, bar_id);
2169 else if (strcmp(bar_type, "hidden_state") == 0)
2170 ret = cmd_bar_hidden_state(bar_value, bar_id);
2171 else {
2172 ELOG("Unknown bar option type \"%s\", this is a mismatch between code and parser spec.\n", bar_type);
2173 ret = false;
2174 }
2175
2176 ysuccess(ret);
2177 if (!ret)
2178 return;
2179
2180 update_barconfig();
2146 }
2147
2148 DLOG("Changing bar hidden_state of bar_id '%s' from '%d' to '%s (%d)'\n",
2149 current->id, current->hidden_state, bar_hidden_state, hidden_state);
2150 if ((int)current->hidden_state != hidden_state) {
2151 current->hidden_state = hidden_state;
2152 ipc_send_barconfig_update_event(current);
2153 }
2154
2155 ysuccess(true);
2156 return;
2157 }
2158
2159 yerror("Changing bar hidden_state of bar_id %s failed, bar_id not found.\n", bar_id);
21812160 }
21822161
21832162 /*
2525 void ungrab_all_keys(xcb_connection_t *conn) {
2626 DLOG("Ungrabbing all keys\n");
2727 xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY);
28 }
29
30 /*
31 * Sends the current bar configuration as an event to all barconfig_update listeners.
32 *
33 */
34 void update_barconfig(void) {
35 Barconfig *current;
36 TAILQ_FOREACH (current, &barconfigs, configs) {
37 ipc_send_barconfig_update_event(current);
38 }
3928 }
4029
4130 static void free_configuration(void) {
10221022 }
10231023
10241024 /* render_layout flushes */
1025 ewmh_update_desktop_properties();
10251026 tree_render();
10261027
10271028 FREE(primary);