X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=docs%2Fhacking-howto;h=836d5701acff304f68aa7b3e3c7ca346f9425df0;hb=c7ea8c42b679be191e843f653f5024846ce42fe9;hp=1377d87c8c4f50086df323e7775b7d715458738b;hpb=752b1019162b13ac9975634d5974ebd1f34c14a5;p=i3%2Fi3 diff --git a/docs/hacking-howto b/docs/hacking-howto index 1377d87c..836d5701 100644 --- a/docs/hacking-howto +++ b/docs/hacking-howto @@ -63,57 +63,22 @@ 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 +=== The layout tree -********************************************************************************* -This section has not been updated for v4.0 yet, sorry! We wanted to release on -time, but we will update this soon. Please talk to us on IRC if you need to -know stuff *NOW* :). -********************************************************************************* - -///////////////////////////////////////////////////////////////////////////////// -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). +The data structure which i3 uses to keep track of your windows is a tree. Every +node in the tree is a container (type +Con+). Some containers represent actual +windows (every container with a +window != NULL+), some represent split +containers and a few have special purposes: they represent workspaces, outputs +(like VGA1, LVDS1, …) or the X11 root window. 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 similarly. 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 -!======== -|======== +the same split container, which uses the default layout. In case of an empty +workspace, the split container we are talking about is the workspace. -Furthermore, you can freely resize table cells. -///////////////////////////////////////////////////////////////////////////////// +To get an impression of how different layouts are represented, just play around +and look at the data structures -- they are exposed as a JSON hash. See +http://i3wm.org/docs/ipc.html#_get_tree_reply for documentation on that and an +example. == Files @@ -707,41 +672,123 @@ floating windows: ///////////////////////////////////////////////////////////////////////////////// -== User commands / commandmode (src/cmdparse.{l,y}) - -********************************************************************************* -This section has not been updated for v4.0 yet, sorry! We wanted to release on -time, but we will update this soon. Please talk to us on IRC if you need to -know stuff *NOW* :). -********************************************************************************* - -///////////////////////////////////////////////////////////////////////////////// - - -Like in vim, you can control i3 using commands. They are intended to be a -powerful alternative to lots of shortcuts, because they can be combined. There -are a few special commands, which are the following: - -exec :: -Starts the given command by passing it to `/bin/sh`. - -restart:: -Restarts i3 by executing `argv[0]` (the path with which you started i3) without -forking. - -w:: -"With". This is used to select a bunch of windows. Currently, only selecting -the whole container in which the window is in, is supported by specifying "w". - -f, s, d:: -Toggle fullscreen, stacking, default mode for the current window/container. - -The other commands are to be combined with a direction. The directions are h, -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. - -///////////////////////////////////////////////////////////////////////////////// +== User commands (parser-specs/commands.spec) + +In the configuration file and when using i3 interactively (with +i3-msg+, for +example), you use commands to make i3 do things, like focus a different window, +set a window to fullscreen, and so on. An example command is +floating enable+, +which enables floating mode for the currently focused window. See the +appropriate section in the link:userguide.html[User’s Guide] for a reference of +all commands. + +In earlier versions of i3, interpreting these commands was done using lex and +yacc, but experience has shown that lex and yacc are not well suited for our +command language. Therefore, starting from version 4.2, we use a custom parser +for user commands (not yet for the configuration file). +The input specification for this parser can be found in the file ++parser-specs/commands.spec+. Should you happen to use Vim as an editor, use +:source parser-specs/highlighting.vim to get syntax highlighting for this file +(highlighting files for other editors are welcome). + +.Excerpt from commands.spec +----------------------------------------------------------------------- +state INITIAL: + '[' -> call cmd_criteria_init(); CRITERIA + 'move' -> MOVE + 'exec' -> EXEC + 'workspace' -> WORKSPACE + 'exit' -> call cmd_exit() + 'restart' -> call cmd_restart() + 'reload' -> call cmd_reload() +----------------------------------------------------------------------- + +The input specification is written in an extremely simple format. The +specification is then converted into C code by the Perl script +generate-commands-parser.pl (the output file names begin with GENERATED and the +files are stored in the +include+ directory). The parser implementation ++src/commands_parser.c+ includes the generated C code at compile-time. + +The above excerpt from commands.spec illustrates nearly all features of our +specification format: You describe different states and what can happen within +each state. State names are all-caps; the state in the above excerpt is called +INITIAL. A list of tokens and their actions (separated by an ASCII arrow) +follows. In the excerpt, all tokens are literals, that is, simple text strings +which will be compared with the input. An action is either the name of a state +in which the parser will transition into, or the keyword 'call', followed by +the name of a function (and optionally a state). + +=== Example: The WORKSPACE state + +Let’s have a look at the WORKSPACE state, which is a good example of all +features. This is its definition: + +.WORKSPACE state (commands.spec) +---------------------------------------------------------------- +# workspace next|prev|next_on_output|prev_on_output +# workspace back_and_forth +# workspace +state WORKSPACE: + direction = 'next_on_output', 'prev_on_output', 'next', 'prev' + -> call cmd_workspace($direction) + 'back_and_forth' + -> call cmd_workspace_back_and_forth() + workspace = string + -> call cmd_workspace_name($workspace) +---------------------------------------------------------------- + +As you can see from the commands, there are multiple different valid variants +of the workspace command: + +workspace :: + The word 'workspace' can be followed by any of the tokens 'next', + 'prev', 'next_on_output' or 'prev_on_output'. This command will + switch to the next or previous workspace (optionally on the same + output). + + There is one function called +cmd_workspace+, which is defined + in +src/commands.c+. It will handle this kind of command. To know which + direction was specified, the direction token is stored on the stack + with the name "direction", which is what the "direction = " means in + the beginning. + + +NOTE: Note that you can specify multiple literals in the same line. This has + exactly the same effect as if you specified `direction = + 'next_on_output' -> call cmd_workspace($direction)` and so forth. + + +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 + match. + +workspace back_and_forth:: + This is a very simple case: When the literal 'back_and_forth' is found + in the input, the function +cmd_workspace_back_and_forth+ will be + called without parameters and the parser will return to the INITIAL + state (since no other state was specified). +workspace :: + In this case, the workspace command is followed by an arbitrary string, + possibly in quotes, for example "workspace 3" or "workspace bleh". + + This is the first time that the token is actually not a literal (not in + single quotes), but just called string. Other possible tokens are word + (the same as string, but stops matching at a whitespace) and end + (matches the end of the input). + +=== Introducing a new command + +The following steps have to be taken in order to properly introduce a new +command (or possibly extend an existing command): + +1. Define a function beginning with +cmd_+ in the file +src/commands.c+. Copy + the prototype of an existing function. +2. After adding a comment on what the function does, copy the comment and + function definition to +include/commands.h+. Make the comment in the header + file use double asterisks to make doxygen pick it up. +3. Write a test case (or extend an existing test case) for your feature, see + link:testsuite.html[i3 testsuite]. For now, it is sufficient to simply call + your command in all the various possible ways. +4. Extend the parser specification in +parser-specs/commands.spec+. Run the + testsuite and see if your new function gets called with the appropriate + arguments for the appropriate input. +5. Actually implement the feature. +6. Document the feature in the link:userguide.html[User’s Guide]. == Moving containers