From: Michael Stapelberg Date: Fri, 22 Jul 2011 18:38:31 +0000 (+0200) Subject: add docs (with custom stylesheet) X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=3b75be351599a21356665f731b4ec92d9bb9aefa;p=i3%2Fi3.github.io add docs (with custom stylesheet) --- diff --git a/_docs/Makefile b/_docs/Makefile new file mode 100644 index 0000000..8914d06 --- /dev/null +++ b/_docs/Makefile @@ -0,0 +1,27 @@ + +all: hacking-howto.html debugging.html userguide.html ipc.html multi-monitor.html wsbar.html tree-migrating.html + +hacking-howto.html: hacking-howto + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +debugging.html: debugging + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -n $< + +userguide.html: userguide + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +tree-migrating.html: tree-migrating + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +ipc.html: ipc + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +multi-monitor.html: multi-monitor + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +wsbar.html: wsbar + asciidoc -a linkcss -a stylesdir=/css -a scriptsdir=/js --backend=xhtml11 -f conf/i3html.conf -a toc -n $< + +clean: + rm -f */*.{aux,log,toc,bm,pdf,dvi} + rm -f *.log *.html diff --git a/_docs/conf/i3html.conf b/_docs/conf/i3html.conf new file mode 100644 index 0000000..990a5bf --- /dev/null +++ b/_docs/conf/i3html.conf @@ -0,0 +1,691 @@ +# +# xhtml11.conf +# +# Asciidoc configuration file. +# xhtml11 backend, generates XHTML 1.1 conformant markup. +# + +[miscellaneous] +outfilesuffix=.html + +[attributes] +basebackend=html +basebackend-html= +basebackend-xhtml11= + +[replacements2] +# Line break. +(?m)^(.*)\s\+$=\1
+ +[replacements] +ifdef::asciidoc7compatible[] +# Superscripts. +\^(.+?)\^=\1 +# Subscripts. +~(.+?)~=\1 +endif::asciidoc7compatible[] + +[ruler-blockmacro] +
+ +[pagebreak-blockmacro] +
+ +[blockdef-pass] +asciimath-style=template="asciimathblock",subs=[] +latexmath-style=template="latexmathblock",subs=[] + +[macros] +# math macros. +# Special characters are escaped in HTML math markup. +(?su)[\\]?(?Pasciimath|latexmath):(?P\S*?)\[(?P.*?)(?asciimath|latexmath)::(?P\S*?)(\[(?P.*?)\])$=#[specialcharacters] + +[asciimath-inlinemacro] +`{passtext}` + +[asciimath-blockmacro] +
+
+
{title}
+`{passtext}` +
+ +[asciimathblock] +
+
+
{title}
+`|` +
+ +[latexmath-inlinemacro] +{passtext} + +[latexmath-blockmacro] +
+
+
{title}
+{passtext} +
+ +[latexmathblock] +
+
+
{title}
+| +
+ +[image-inlinemacro] + + +{data-uri%}{alt={target}} +{data-uri#}{alt={target}} +{link#} + + +[image-blockmacro] +
+ +
{caption={figure-caption} {counter:figure-number}. }{title}
+
+ +[unfloat-blockmacro] +
+ +[indexterm-inlinemacro] +# Index term. +{empty} + +[indexterm2-inlinemacro] +# Index term. +# Single entry index term that is visible in the primary text flow. +{1} + +[footnote-inlinemacro] +# footnote:[]. +
[{0}]
+ +[footnoteref-inlinemacro] +# footnoteref:[], create reference to footnote. +{2%}
[{1}]
+# footnoteref:[,], create footnote with ID. +{2#}
[{2}]
+ +[callout-inlinemacro] +ifndef::icons[] +<{index}> +endif::icons[] +ifdef::icons[] +ifndef::data-uri[] +{index} +endif::data-uri[] +ifdef::data-uri[] +{index} +endif::data-uri[] +endif::icons[] + +# Comment line macros. +[comment-inlinemacro] +{showcomments#}
{passtext}
+ +[comment-blockmacro] +{showcomments#}

{passtext}

+ +[literal-inlinemacro] +# Inline literal. +{passtext} + +# List tags. +[listtags-bulleted] +list=
{title?
{title}
}
    |
+item=
  • |
  • +text=

    |

    + +[listtags-numbered] +# The start attribute is not valid XHTML 1.1 but all browsers support it. +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    + +[listtags-labeled] +list=
    {title?
    {title}
    }
    |
    +entry= +label= +term=
    |
    +item=
    |
    +text=

    |

    + +[listtags-horizontal] +list=
    {title?
    {title}
    }{labelwidth?}{itemwidth?}|
    +label=| +term=|
    +entry=| +item=| +text=

    |

    + +[listtags-qanda] +list=
    {title?
    {title}
    }
      |
    +entry=
  • |
  • +label= +term=

    |

    +item= +text=

    |

    + +[listtags-callout] +ifndef::icons[] +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    +endif::icons[] +ifdef::icons[] +list=
    {title?
    {title}
    }|
    +ifndef::data-uri[] +item={listindex}| +endif::data-uri[] +ifdef::data-uri[] +item={listindex}| +endif::data-uri[] +text=| +endif::icons[] + +[listtags-glossary] +list=
    {title?
    {title}
    }
    |
    +label= +entry= +term=
    |
    +item=
    |
    +text=

    |

    + +[listtags-bibliography] +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    + +[tags] +# Quoted text. +emphasis={1?}|{1?} +strong={1?}|{1?} +monospaced={1?}|{1?} +singlequoted={lsquo}{1?}|{1?}{rsquo} +doublequoted={ldquo}{1?}|{1?}{rdquo} +unquoted={1?}|{1?} +superscript={1?}|{1?} +subscript={1?}|{1?} + +ifdef::deprecated-quotes[] +# Override with deprecated quote attributes. +emphasis={role?}|{role?} +strong={role?}|{role?} +monospaced={role?}|{role?} +singlequoted={role?}{1,2,3?}{amp}#8216;|{amp}#8217;{1,2,3?}{role?} +doublequoted={role?}{1,2,3?}{amp}#8220;|{amp}#8221;{1,2,3?}{role?} +unquoted={role?}{1,2,3?}|{1,2,3?}{role?} +superscript={role?}|{role?} +subscript={role?}|{role?} +endif::deprecated-quotes[] + +# Inline macros +[http-inlinemacro] +{0={name}:{target}} +[https-inlinemacro] +{0={name}:{target}} +[ftp-inlinemacro] +{0={name}:{target}} +[file-inlinemacro] +{0={name}:{target}} +[irc-inlinemacro] +{0={name}:{target}} +[mailto-inlinemacro] +{0={target}} +[link-inlinemacro] +{0={target}} +[callto-inlinemacro] +{0={target}} +# anchor:id[text] +[anchor-inlinemacro] + +# [[id,text]] +[anchor2-inlinemacro] + +# [[[id]]] +[anchor3-inlinemacro] +[{1}] +# xref:id[text] +[xref-inlinemacro] +{0=[{target}]} +# <> +[xref2-inlinemacro] +{2=[{1}]} + +# Special word substitution. +[emphasizedwords] +{words} +[monospacedwords] +{words} +[strongwords] +{words} + +# Paragraph substitution. +[paragraph] +
    {title?
    {title}
    }

    +| +

    + +[admonitionparagraph] +template::[admonitionblock] + +# Delimited blocks. +[listingblock] +
    +
    {caption=}{title}
    +
    +
    
    +|
    +
    +
    + +[literalblock] +
    +
    {title}
    +
    +
    
    +|
    +
    +
    + +[sidebarblock] +
    +
    +
    {title}
    +| +
    + +[openblock] +
    +
    {title}
    +
    +| +
    + +[partintroblock] +template::[openblock] + +[abstractblock] +template::[quoteblock] + +[quoteblock] +
    +
    {title}
    +
    +| +
    +
    +{citetitle}{attribution?
    } +— {attribution} +
    + +[verseblock] +
    +
    {title}
    +
    +|
    +
    +
    +{citetitle}{attribution?
    } +— {attribution} +
    + +[exampleblock] +
    +
    {caption={example-caption} {counter:example-number}. }{title}
    +
    +| +
    + +[admonitionblock] +
    + + + +
    +{data-uri%}{icons#}{caption} +{data-uri#}{icons#}{caption} +{icons%}
    {caption}
    +
    +
    {title}
    +| +
    +
    + +# Tables. +[tabletags-default] +colspec= +bodyrow=| +headdata=| +bodydata=| +paragraph=

    |

    + +[tabletags-header] +paragraph=

    |

    + +[tabletags-emphasis] +paragraph=

    |

    + +[tabletags-strong] +paragraph=

    |

    + +[tabletags-monospaced] +paragraph=

    |

    + +[tabletags-verse] +bodydata=
    |
    +paragraph= + +[tabletags-literal] +bodydata=
    |
    +paragraph= + +[tabletags-asciidoc] +bodydata=
    |
    +paragraph= + +[table] +
    + + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + +
    {caption={table-caption} {counter:table-number}. }{title}
    +
    + +#-------------------------------------------------------------------- +# Deprecated old table definitions. +# + +[miscellaneous] +# Screen width in pixels. +pagewidth=800 +pageunits= + +[old_tabledef-default] +template=old_table +colspec= +bodyrow=| +headdata=| +footdata=| +bodydata=| + +[old_table] +
    + + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + +
    {caption={table-caption}}{title}
    +
    + +# End of deprecated old table definitions. +#-------------------------------------------------------------------- + +[floatingtitle] +{title} + +[preamble] +# Untitled elements between header and first section title. +
    +
    +| +
    +
    + +# Document sections. +[sect0] +{title} +| + +[sect1] +
    +{numbered?{sectnum} }{title} +
    +| +
    +
    + +[sect2] +
    +{numbered?{sectnum} }{title} +| +
    + +[sect3] +
    +{numbered?{sectnum} }{title} +| +
    + +[sect4] +
    +{title} +| +
    + +[appendix] +
    +{numbered?{sectnum} }{appendix-caption} {counter:appendix-number:A}: {title} +
    +| +
    +
    + +[toc] +
    +
    {toc-title}
    + +
    + +[header] + + + + + + + +i3: {title} +{title%}i3: {doctitle=} + +ifdef::linkcss[] + +{doctype-manpage} +ifdef::quirks[] + +endif::quirks[] + +ifdef::pygments[] +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +ifndef::disable-javascript[] +ifdef::linkcss[] + + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::disable-javascript[] +ifdef::asciimath[] +ifdef::linkcss[] + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::asciimath[] +ifdef::latexmath[] +ifdef::linkcss[] + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::latexmath[] +{docinfo1,docinfo2#}{include:{docdir}/docinfo.html} +{docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.html} + + + +
    +

    i3 - improved tiling WM

    + +
    +
    +# Article, book header. +ifndef::doctype-manpage[] + +endif::doctype-manpage[] +# Man page header. +ifdef::doctype-manpage[] + +endif::doctype-manpage[] + +[footer] +
    +{disable-javascript%

    } + + + + +ifdef::doctype-manpage[] +[synopsis] +template::[sect1] +endif::doctype-manpage[] + +ifdef::quirks[] +include::{backend}-quirks.conf[] +endif::quirks[] diff --git a/_docs/debugging b/_docs/debugging new file mode 100644 index 0000000..d52edea --- /dev/null +++ b/_docs/debugging @@ -0,0 +1,104 @@ +Debugging i3: How To +==================== +Michael Stapelberg +March 2010 + +This document describes how to debug i3 suitably for sending us useful bug +reports, even if you have no clue of C programming. + +First of all: Thank you for being interested in debugging i3. It really means +something to us to get your bug fixed. If you have any questions about the +debugging and/or need further help, do not hesitate to contact us! + +== Enabling logging + +i3 spits out much information onto stdout, if told so. To have a clearly +defined place where log files will be saved, you should redirect stdout and +stderr in xsession. While you’re at it, putting each run of i3 in a separate +log file with date/time in it is a good idea to not get confused about the +different log files later on. + +-------------------------------------------------------------------- +exec /usr/bin/i3 -V -d all >/home/michael/i3/i3log-$(date +'%F-%k-%M-%S') 2>&1 +-------------------------------------------------------------------- + +== Enabling core dumps + +When i3 crashes, often you have the chance of getting a 'core dump' (an image +of the memory of the i3 process which can be loaded into a debugger). To get a +core dump, you have to make sure that the user limit for core dump files is set +high enough. Many systems ship with a default value which even forbids core +dumps completely. To disable the limit completely and thus enable core dumps, +use the following command (in your .xsession, before starting i3): + +------------------- +ulimit -c unlimited +------------------- + +Furthermore, to easily recognize core dumps and allow multiple of them, you +should set a custom core dump filename pattern, using a command like the +following: + +--------------------------------------------- +sudo sysctl -w kernel.core_pattern=core.%e.%p +--------------------------------------------- + +This will generate files which have the executable’s file name (%e) and the +process id (%p) in it. You can save this setting across reboots using ++/etc/sysctl.conf+. + +== Compiling with debug symbols + +To actually get useful core dumps, you should make sure that your version of i3 +is compiled with debug symbols, that is, that they are not stripped during the +build process. You can check whether your executable contains symbols by +issuing the following command: + +---------------- +file $(which i3) +---------------- + +You should get an output like this: +------------------------------------------------------------------------------ +/usr/bin/i3: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically +linked (uses shared libs), for GNU/Linux 2.6.18, not stripped +------------------------------------------------------------------------------ + +Notice the +not stripped+, which is the important part. If you have a version +which is stripped, please have a look if your distribution provides debug +symbols (package +i3-wm-dbg+ on Debian for example) or if you can turn off +stripping. If nothing helps, please build i3 from source. + +== Generating a backtrace + +Once you have made sure that your i3 is compiled with debug symbols and that +core dumps are enabled, you can start making sense out of the core dumps. + +Because the core dump depends on the original executable (and its debug +symbols), please do this as soon as you encounter the problem. If you +re-compile i3, your core dump might be useless afterwards. + +Please install +gdb+, a debugger for C. No worries, you don’t need to learn it +now. Start gdb using the following command (replacing the actual name of the +core dump of course): + +---------------------------- +gdb $(which i3) core.i3.3849 +---------------------------- + +Then, generate a backtrace using: + +-------------- +backtrace full +-------------- + +== Sending bug reports/debugging on IRC + +When sending bug reports, please paste the relevant part of the log (if in +doubt, please send us rather too much information than too less) and the whole +backtrace (if there was a core dump). + +When debugging with us in IRC, be prepared to use a so called nopaste service +such as http://nopaste.info or http://pastebin.com because pasting large +amounts of text in IRC sometimes leads to incomplete lines (servers have line +length limitations) or flood kicks. diff --git a/_docs/hacking-howto b/_docs/hacking-howto new file mode 100644 index 0000000..dff074c --- /dev/null +++ b/_docs/hacking-howto @@ -0,0 +1,524 @@ +Hacking i3: How To +================== +Michael Stapelberg +December 2009 + +This document is intended to be the first thing you read before looking and/or +touching i3’s source code. It should contain all important information to help +you understand why things are like they are. If it does not mention something +you find necessary, please do not hesitate to contact me. + +== Window Managers + +A window manager is not necessarily needed to run X, but it is usually used in +combination with X to facilitate some things. The window manager's job is to +take care of the placement of windows, to provide the user with some mechanisms +to change the position/size of windows and to communicate with clients to a +certain extent (for example handle fullscreen requests of clients such as +MPlayer). + +There are no different contexts in which X11 clients run, so a window manager +is just another client, like all other X11 applications. However, it handles +some events which normal clients usually don’t handle. + +In the case of i3, the tasks (and order of them) are the following: + +. Grab the key bindings (events will be sent upon keypress/keyrelease) +. Iterate through all existing windows (if the window manager is not started as + the first client of X) and manage them (reparent them, create window + decorations, etc.) +. When new windows are created, manage them +. Handle the client’s `_WM_STATE` property, but only the `_WM_STATE_FULLSCREEN` +. Handle the client’s `WM_NAME` property +. Handle the client’s size hints to display them proportionally +. Handle the client’s urgency hint +. Handle enter notifications (focus follows mouse) +. Handle button (as in mouse buttons) presses for focus/raise on click +. Handle expose events to re-draw own windows such as decorations +. React to the user’s commands: Change focus, Move windows, Switch workspaces, + Change the layout mode of a container (default/stacking/tabbed), start a new + application, restart the window manager + +In the following chapters, each of these tasks and their implementation details +will be discussed. + +=== Tiling window managers + +Traditionally, there are two approaches to managing windows: The most common +one nowadays is floating, which means the user can freely move/resize the +windows. The other approach is called tiling, which means that your window +manager distributes 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 +moving/resizing windows while you usually want to get some work done. After +all, most users sooner or later tend to lay out their windows in a way which +corresponds to tiling or stacking mode in i3. Therefore, why not let i3 do this +for you? Certainly, it’s faster than you could ever do it. + +The problem with most tiling window managers is that they are too unflexible. +In my opinion, a window manager is just another tool, and similar to vim which +can edit all kinds of text files (like source code, HTML, …) and is not limited +to a specific file type, a window manager should not limit itself to a certain +layout (like dwm, awesome, …) but provide mechanisms for you to easily create +the layout you need at the moment. + +=== The layout table + +To accomplish flexible layouts, we decided to simply use a table. The table +grows and shrinks as you need it. Each cell holds a container which then holds +windows (see picture below). You can use different layouts for each container +(default layout and stacking layout). + +So, when you open a terminal and immediately open another one, they reside in +the same container, in default layout. The layout table has exactly one column, +one row and therefore one cell. When you move one of the terminals to the +right, the table needs to grow. It will be expanded to two columns and one row. +This enables you to have different layouts for each container. The table then +looks like this: + +[width="15%",cols="^,^"] +|======== +| T1 | T2 +|======== + +When moving terminal 2 to the bottom, the table will be expanded again. + +[width="15%",cols="^,^"] +|======== +| T1 | +| | T2 +|======== + +You can really think of the layout table like a traditional HTML table, if +you’ve ever designed one. Especially col- and rowspan work 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 +!======== +|======== + +Furthermore, you can freely resize table cells. + +== Files + +include/data.h:: +Contains data definitions used by nearly all files. You really need to read +this first. + +include/*.h:: +Contains forward definitions for all public functions, as well as +doxygen-compatible comments (so if you want to get a bit more of the big +picture, either browse all header files or use doxygen if you prefer that). + +src/cfgparse.l:: +Contains the lexer for i3’s configuration file, written for +flex(1)+. + +src/cfgparse.y:: +Contains the parser for i3’s configuration file, written for +bison(1)+. + +src/click.c:: +Contains all functions which handle mouse button clicks (right mouse button +clicks initiate resizing and thus are relatively complex). + +src/client.c:: +Contains all functions which are specific to a certain client (make it +fullscreen, see if its class/name matches a pattern, kill it, …). + +src/commands.c:: +Parsing commands and actually executing them (focusing, moving, …). + +src/config.c:: +Parses the configuration file. + +src/debug.c:: +Contains debugging functions to print unhandled X events. + +src/floating.c:: +Contains functions for floating mode (mostly resizing/dragging). + +src/handlers.c:: +Contains all handlers for all kinds of X events (new window title, new hints, +unmapping, key presses, button presses, …). + +src/ipc.c:: +Contains code for the IPC interface. + +src/layout.c:: +Renders your layout (screens, workspaces, containers). + +src/mainx.c:: +Initializes the window manager. + +src/manage.c:: +Looks at existing or new windows and decides whether to manage them. If so, it +reparents the window and inserts it into our data structures. + +src/resize.c:: +Contains the functions to resize columns/rows in the table. + +src/table.c:: +Manages the most important internal data structure, the design table. + +src/util.c:: +Contains useful functions which are not really dependant on anything. + +src/workspace.c:: +Contains all functions related to workspaces (displaying, hiding, renaming…) + +src/xcb.c:: +Contains wrappers to use xcb more easily. + +src/xinerama.c:: +(Re-)initializes the available screens and converts them to virtual screens +(see below). + +== Data structures + +See include/data.h for documented data structures. The most important ones are +explained right here. + +image:bigpicture.png[The Big Picture] + +So, the hierarchy is: + +. *Virtual screens* (Screen 0 in this example) +. *Workspaces* (Workspace 1 in this example) +. *Table* (There can only be one table per Workspace) +. *Container* (left and right in this example) +. *Client* (The two clients in the left container) + +=== Virtual screens + +A virtual screen (type `i3Screen`) is generated from the connected screens +obtained through Xinerama. The difference to the raw Xinerama monitors as seen +when using +xrandr(1)+ is that it falls back to the lowest common resolution of +the logical screens. + +For example, if your notebook has 1280x800 and you connect a video projector +with 1024x768, set up in clone mode (+xrandr \--output VGA \--mode 1024x768 +\--same-as LVDS+), i3 will have one virtual screen. + +However, if you configure it using +xrandr \--output VGA \--mode 1024x768 +\--right-of LVDS+, i3 will generate two virtual screens. For each virtual +screen, a new workspace will be assigned. New workspaces are created on the +screen you are currently on. + +=== Workspace + +A workspace is identified by its number. Basically, you could think of +workspaces as different desks in your office, if you like the desktop +methaphor. They just contain different sets of windows and are completely +separate of each other. Other window managers also call this ``Virtual +desktops''. + +=== The layout table + +Each workspace has a table, which is just a two-dimensional dynamic array +containing Containers (see below). This table grows and shrinks as you need it +(by moving windows to the right you can create a new column in the table, by +moving them to the bottom you create a new row). + +=== Container + +A container is the content of a table’s cell. It holds an arbitrary amount of +windows and has a specific layout (default layout, stack layout or tabbed +layout). Containers can consume multiple table cells by modifying their +colspan/rowspan attribute. + +=== Client + +A client is x11-speak for a window. + +== List/queue macros + +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 +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). + +The lists used are `SLIST` (single linked lists), `CIRCLEQ` (circular +queues) and TAILQ (tail queues). Usually, only forward traversal is necessary, +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 +windows inside a container, a `CIRCLEQ` is necessary to go from the currently +selected window to the window above/below. + +== Naming conventions + +There is a row of standard variables used in many events. The following names +should be chosen for those: + + * ``conn'' is the xcb_connection_t + * ``event'' is the event of the particular type + * ``container'' names a container + * ``client'' names a client, for example when using a +CIRCLEQ_FOREACH+ + +== Startup (src/mainx.c, main()) + + * Establish the xcb connection + * Check for XKB extension on the separate X connection + * Check for Xinerama screens + * Grab the keycodes for which bindings exist + * Manage all existing windows + * Enter the event loop + +== Keybindings + +=== Grabbing the bindings + +Grabbing the bindings is quite straight-forward. You pass X your combination of +modifiers and the keycode you want to grab and whether you want to grab them +actively or passively. Most bindings (everything except for bindings using +Mode_switch) are grabbed passively, that is, just the window manager gets the +event and cannot replay it. + +We need to grab bindings that use Mode_switch actively because of a bug in X. +When the window manager receives the keypress/keyrelease event for an actively +grabbed keycode, it has to decide what to do with this event: It can either +replay it so that other applications get it or it can prevent other +applications from receiving it. + +So, why do we need to grab keycodes actively? Because X does not set the +state-property of keypress/keyrelease events properly. The Mode_switch bit is +not set and we need to get it using XkbGetState. This means we cannot pass X +our combination of modifiers containing Mode_switch when grabbing the key and +therefore need to grab the keycode itself without any modifiers. This means, +if you bind Mode_switch + keycode 38 ("a"), i3 will grab keycode 38 ("a") and +check on each press of "a" if the Mode_switch bit is set using XKB. If yes, it +will handle the event, if not, it will replay the event. + +=== Handling a keypress + +As mentioned in "Grabbing the bindings", upon a keypress event, i3 first gets +the correct state. + +Then, it looks through all bindings and gets the one which matches the received +event. + +The bound command is parsed directly in command mode. + +== Manage windows (src/mainx.c, manage_window() and reparent_window()) + +`manage_window()` does some checks to decide whether the window should be +managed at all: + + * Windows have to be mapped, that is, visible on screen + * The override_redirect must not be set. Windows with override_redirect shall + not be managed by a window manager + +Afterwards, i3 gets the intial geometry and reparents the window (see +`reparent_window()`) if it wasn’t already managed. + +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 +reparented to the bigger one (called "frame"). + +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 +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 +of the screen. To get the height which needsd to be reserved for the window, +the `_NET_WM_STRUT_PARTIAL` property is used. + +Furthermore, the list of assignments (to other workspaces, which may be on +other screens) is checked. If the window matches one of the user’s criteria, +it may either be put in floating mode or moved to a different workspace. If the +target workspace is not visible, the window will not be mapped. + +== What happens when an application is started? + +i3 does not care for applications. All it notices is when new windows are +mapped (see `src/handlers.c`, `handle_map_request()`). The window is then +reparented (see section "Manage windows"). + +After reparenting the window, `render_layout()` is called which renders the +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 +moved/resized so that the currently active layout (default/stacking/tabbed mode) +is rendered correctly. To move/resize windows, a window is ``configured'' in +X11-speak. + +Some applications, such as MPlayer obviously assume the window manager is +stupid and try to configure their windows by themselves. This generates an +event called configurerequest. i3 handles these events and tells the window the +size it had before the configurerequest (with the exception of not yet mapped +windows, which get configured like they want to, and floating windows, which +can reconfigure themselves). + +== _NET_WM_STATE + +Only the _NET_WM_STATE_FULLSCREEN atom is handled. It calls +``toggle_fullscreen()'' for the specific client which just configures the +client to use the whole screen on which it currently is. Also, it is set as +fullscreen_client for the i3Screen. + +== WM_NAME + +When the WM_NAME property of a window changes, its decoration (containing the +title) is re-rendered. Note that WM_NAME is in COMPOUND_TEXT encoding which is +totally uncommon and cumbersome. Therefore, the _NET_WM_NAME atom will be used +if present. + +== _NET_WM_NAME + +Like WM_NAME, this atom contains the title of a window. However, _NET_WM_NAME +is encoded in UTF-8. i3 will recode it to UCS-2 in order to be able to pass it +to X. Using an appropriate font (ISO-10646), you can see most special +characters (every special character contained in your font). + +== Size hints + +Size hints specify the minimum/maximum size for a given window as well as its +aspect ratio. This is important for clients like mplayer, who only set the +aspect ratio and resize their window to be as small as possible (but only with +some video outputs, for example in Xv, while when using x11, mplayer does the +necessary centering for itself). + +So, when an aspect ratio was specified, i3 adjusts the height of the window +until the size maintains the correct aspect ratio. For the code to do this, see +src/layout.c, function resize_client(). + +== Rendering (src/layout.c, render_layout() and render_container()) + +There are several entry points to rendering: `render_layout()`, +`render_workspace()` and `render_container()`. The former one calls +`render_workspace()` for every screen, which in turn will call +`render_container()` for every container inside its layout table. Therefore, if +you need to render only a single container, for example because a window was +removed, added or changed its title, you should directly call +render_container(). + +Rendering consists of two steps: In the first one, in `render_workspace()`, each +container gets its position (screen offset + offset in the table) and size +(container's width times colspan/rowspan). Then, `render_container()` is called, +which takes different approaches, depending on the mode the container is in: + +=== Common parts + +On the frame (the window which was created around the client’s window for the +decorations), a black rectangle is drawn as a background for windows like +MPlayer, which do not completely fit into the frame. + +=== Default mode + +Each clients gets the container’s width and an equal amount of height. + +=== Stack mode + +In stack mode, a window containing the decorations of all windows inside the +container is placed at the top. The currently focused window is then given the +whole remaining space. + +=== Tabbed mode + +Tabbed mode is like stack mode, except that the window decorations are drawn +in one single line at the top of the container. + +=== Window decorations + +The window decorations consist of a rectangle in the appropriate color (depends +on whether this window is the currently focused one, the last focused one in a +not focused container or not focused at all) forming the background. +Afterwards, two lighter lines are drawn and the last step is drawing the +window’s title (see WM_NAME) onto it. + +=== Fullscreen windows + +For fullscreen windows, the `rect` (x, y, width, height) is not changed to +allow the client to easily go back to its previous position. Instead, +fullscreen windows are skipped when rendering. + +=== Resizing containers + +By clicking and dragging the border of a container, you can resize the whole +column (respectively row) which this container is in. This is necessary to keep +the table layout working and consistent. + +The resizing works similarly to the resizing of floating windows or movement of +floating windows: + +* A new, invisible window with the size of the root window is created + (+grabwin+) +* Another window, 2px width and as high as your screen (or vice versa for + horizontal resizing) is created. Its background color is the border color and + it is only there to inform the user how big the container will be (it + creates the impression of dragging the border out of the container). +* The +drag_pointer+ function of +src/floating.c+ is called to grab the pointer + and enter its own event loop which will pass all events (expose events) but + motion notify events. This function then calls the specified callback + (+resize_callback+) which does some boundary checking and moves the helper + window. As soon as the mouse button is released, this loop will be + terminated. +* The new width_factor for each involved column (respectively row) will be + calculated. + +== User commands / commandmode (src/commands.c) + +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. + +== Gotchas + +* Forgetting to call `xcb_flush(conn);` after sending a request. This usually + leads to code which looks like it works fine but which does not work under + certain conditions. + +== Using git / sending patches + +For a short introduction into using git, see +http://www.spheredev.org/wiki/Git_for_the_lazy or, for more documentation, see +http://git-scm.com/documentation + +When you want to send a patch because you fixed a bug or implemented a cool +feature (please talk to us before working on features to see whether they are +maybe already implemented, not possible for some some reason, or don’t fit +into the concept), please use git to create a patchfile. + +First of all, update your working copy to the latest version of the master +branch: + +-------- +git pull +-------- + +Afterwards, make the necessary changes for your bugfix/feature. Then, review +the changes using +git diff+ (you might want to enable colors in the diff using ++git config diff.color auto+). When you are definitely done, use +git commit +-a+ to commit all changes you’ve made. + +Then, use the following command to generate a patchfile which we can directly +apply to the branch, preserving your commit message and name: + +----------------------- +git format-patch origin +----------------------- + +Just send us the generated file via email. diff --git a/_docs/ipc b/_docs/ipc new file mode 100644 index 0000000..5db6f00 --- /dev/null +++ b/_docs/ipc @@ -0,0 +1,326 @@ +IPC interface (interprocess communication) +========================================== +Michael Stapelberg +March 2010 + +This document describes how to interface with i3 from a separate process. This +is useful for example to remote-control i3 (to write test cases for example) or +to get various information like the current workspaces to implement an external +workspace bar. + +The method of choice for IPC in our case is a unix socket because it has very +little overhead on both sides and is usually available without headaches in +most languages. In the default configuration file, no ipc-socket path is +specified and thus no socket is created. The standard path (which +i3-msg+ and ++i3-input+ use) is +~/.i3/ipc.sock+. + +== Establishing a connection + +To establish a connection, simply open the IPC socket. The following code +snippet illustrates this in Perl: + +------------------------------------------------------------- +use IO::Socket::UNIX; +my $sock = IO::Socket::UNIX->new(Peer => '~/.i3/ipc.sock'); +------------------------------------------------------------- + +== Sending messages to i3 + +To send a message to i3, you have to format in the binary message format which +i3 expects. This format specifies a magic string in the beginning to ensure +the integrity of messages (to prevent follow-up errors). Following the magic +string comes the length of the payload of the message as 32-bit integer, and +the type of the message as 32-bit integer (the integers are not converted, so +they are in native byte order). + +The magic string currently is "i3-ipc" and will only be changed when a change +in the IPC API is done which breaks compatibility (we hope that we don’t need +to do that). + +Currently implemented message types are the following: + +COMMAND (0):: + The payload of the message is a command for i3 (like the commands you + can bind to keys in the configuration file) and will be executed + directly after receiving it. There is no reply to this message. +GET_WORKSPACES (1):: + Gets the current workspaces. The reply will be a JSON-encoded list of + workspaces (see the reply section). +SUBSCRIBE (2):: + Subscribes your connection to certain events. See <> for a + description of this message and the concept of events. +GET_OUTPUTS (3):: + Gets the current outputs. The reply will be a JSON-encoded list of outputs + (see the reply section). + +So, a typical message could look like this: +-------------------------------------------------- +"i3-ipc" +-------------------------------------------------- + +Or, as a hexdump: +------------------------------------------------------------------------------ +00000000 69 33 2d 69 70 63 04 00 00 00 00 00 00 00 65 78 |i3-ipc........ex| +00000010 69 74 0a |it.| +------------------------------------------------------------------------------ + +To generate and send such a message, you could use the following code in Perl: +------------------------------------------------------------ +sub format_ipc_command { + my ($msg) = @_; + my $len; + # Get the real byte count (vs. amount of characters) + { use bytes; $len = length($msg); } + return "i3-ipc" . pack("LL", $len, 0) . $msg; +} + +$sock->write(format_ipc_command("exit")); +------------------------------------------------------------------------------ + +== Receiving replies from i3 + +Replies from i3 usually consist of a simple string (the length of the string +is the message_length, so you can consider them length-prefixed) which in turn +contain the JSON serialization of a data structure. For example, the +GET_WORKSPACES message returns an array of workspaces (each workspace is a map +with certain attributes). + +=== Reply format + +The reply format is identical to the normal message format. There also is +the magic string, then the message length, then the message type and the +payload. + +The following reply types are implemented: + +COMMAND (0):: + Confirmation/Error code for the COMMAND message. +GET_WORKSPACES (1):: + Reply to the GET_WORKSPACES message. +SUBSCRIBE (2):: + Confirmation/Error code for the SUBSCRIBE message. +GET_OUTPUTS (3):: + Reply to the GET_OUTPUTS message. + +=== COMMAND reply + +The reply consists of a single serialized map. At the moment, the only +property is +success (bool)+, but this will be expanded in future versions. + +*Example:* +------------------- +{ "success": true } +------------------- + +=== GET_WORKSPACES reply + +The reply consists of a serialized list of workspaces. Each workspace has the +following properties: + +num (integer):: + The logical number of the workspace. Corresponds to the command + to switch to this workspace. +name (string):: + The name of this workspace (by default num+1), as changed by the + user. Encoded in UTF-8. +visible (boolean):: + Whether this workspace is currently visible on an output (multiple + workspaces can be visible at the same time). +focused (boolean):: + Whether this workspace currently has the focus (only one workspace + can have the focus at the same time). +urgent (boolean):: + Whether a window on this workspace has the "urgent" flag set. +rect (map):: + The rectangle of this workspace (equals the rect of the output it + is on), consists of x, y, width, height. +output (string):: + The video output this workspace is on (LVDS1, VGA1, …). + +*Example:* +------------------- +[ + { + "num": 0, + "name": "1", + "visible": true, + "focused": true, + "urgent": false, + "rect": { + "x": 0, + "y": 0, + "width": 1280, + "height": 800 + }, + "output": "LVDS1" + }, + { + "num": 1, + "name": "2", + "visible": false, + "focused": false, + "urgent": false, + "rect": { + "x": 0, + "y": 0, + "width": 1280, + "height": 800 + }, + "output": "LVDS1" + } +] +------------------- + +=== SUBSCRIBE reply + +The reply consists of a single serialized map. The only property is ++success (bool)+, indicating whether the subscription was successful (the +default) or whether a JSON parse error occurred. + +*Example:* +------------------- +{ "success": true } +------------------- + +=== GET_OUTPUTS reply + +The reply consists of a serialized list of outputs. Each output has the +following properties: + +name (string):: + The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8. +active (boolean):: + Whether this output is currently active (has a valid mode). +current_workspace (integer):: + The current workspace which is visible on this output. +null+ if the + output is not active. +rect (map):: + The rectangle of this output (equals the rect of the output it + is on), consists of x, y, width, height. + +*Example:* +------------------- +[ + { + "name": "LVDS1", + "active": true, + "current_workspace": 4, + "rect": { + "x": 0, + "y": 0, + "width": 1280, + "height": 800 + } + }, + { + "name": "VGA1", + "active": true, + "current_workspace": 1, + "rect": { + "x": 1280, + "y": 0, + "width": 1280, + "height": 1024 + }, + } +] +------------------- + +== Events + +[[events]] + +To get informed when certain things happen in i3, clients can subscribe to +events. Events consist of a name (like "workspace") and an event reply type +(like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format +as replies to specific commands. However, the highest bit of the message type +is set to 1 to indicate that this is an event reply instead of a normal reply. + +Caveat: As soon as you subscribe to an event, it is not guaranteed any longer +that the requests to i3 are processed in order. This means, the following +situation can happen: You send a GET_WORKSPACES request but you receive a +"workspace" event before receiving the reply to GET_WORKSPACES. If your +program does not want to cope which such kinds of race conditions (an +event based library may not have a problem here), I suggest you create a +separate connection to receive events. + +=== Subscribing to events + +By sending a message of type SUBSCRIBE with a JSON-encoded array as payload +you can register to an event. + +*Example:* +--------------------------------- +type: SUBSCRIBE +payload: [ "workspace", "focus" ] +--------------------------------- + + +=== Available events + +The numbers in parenthesis is the event type (keep in mind that you need to +strip the highest bit first). + +workspace (0):: + Sent when the user switches to a different workspace, when a new + workspace is initialized or when a workspace is removed (because the + last client vanished). +output (1):: + Sent when RandR issues a change notification (of either screens, + outputs, CRTCs or output properties). + +*Example:* +-------------------------------------------------------------------- +# the appropriate 4 bytes read from the socket are stored in $input + +# unpack a 32-bit unsigned integer +my $message_type = unpack("L", $input); + +# check if the highest bit is 1 +my $is_event = (($message_type >> 31) == 1); + +# use the other bits +my $event_type = ($message_type & 0x7F); + +if ($is_event) { + say "Received event of type $event_type"; +} +-------------------------------------------------------------------- + +=== workspace event + +This event consists of a single serialized map containing a property ++change (string)+ which indicates the type of the change ("focus", "init", +"empty", "urgent"). + +*Example:* +--------------------- +{ "change": "focus" } +--------------------- + +=== output event + +This event consists of a single serialized map containing a property ++change (string)+ which indicates the type of the change (currently only +"unspecified"). + +*Example:* +--------------------------- +{ "change": "unspecified" } +--------------------------- + +== See also + +For some languages, libraries are available (so you don’t have to implement +all this on your own). This list names some (if you wrote one, please let me +know): + +C:: + i3 includes a headerfile +i3/ipc.h+ which provides you all constants. + However, there is no library yet. +Ruby:: + http://github.com/badboy/i3-ipc +Perl:: + http://search.cpan.org/search?query=AnyEvent::I3 +Python:: + http://github.com/thepub/i3ipc diff --git a/_docs/multi-monitor b/_docs/multi-monitor new file mode 100644 index 0000000..ec0256c --- /dev/null +++ b/_docs/multi-monitor @@ -0,0 +1,60 @@ +The multi-monitor situation +=========================== +Michael Stapelberg +March 2010 + +…or: oh no, I have an nVidia graphics card! + +== The quick fix + +If you are using the nVidia binary graphics driver (also known as 'blob') +you need to use the +--force-xinerama+ flag (in your .xsession) when starting +i3, like so: + +.Example: +---------------------------------------------- +exec i3 --force-xinerama -V >>~/.i3/i3log 2>&1 +---------------------------------------------- + +== The explanation + +Starting with version 3.ε, i3 uses the RandR (Rotate and Resize) API instead +of Xinerama. The reason for this, is that RandR provides more information +about your outputs and connected screens than Xinerama does. To be specific, +the code which handled on-the-fly screen reconfiguration (meaning without +restarting the X server) was a very messy heuristic and most of the time did +not work correctly -- that is just not possible with the little information +Xinerama offers (just a list of screen resolutions, no identifiers for the +screens or any additional information). Xinerama simply was not designed +for dynamic configuration. + +So RandR came along, as a more powerful alternative (RandR 1.2 to be specific). +It offers all of Xinerama’s possibilities and lots more. Using the RandR API +made our code much more robust and clean. Also, you can now reliably assign +workspaces to output names instead of some rather unreliable screen identifier +(position inside the list of screens, which could change, and so on…). + +As RandR has been around for about three years as of this writing, it seemed +like a very good idea to us, and it still is a very good one. What we did not +expect, however, was the nVidia binary driver. It still does not support RandR +(as of March 2010), even though nVidia has announced that it will support RandR +eventually. What does this mean for you, if you are stuck with the binary +driver for some reason (say the free drivers don’t work with your card)? First +of all, you are stuck with TwinView and cannot use +xrandr+. While this ruins +the user experience, the more grave problem is that the nVidia driver not only +does not support dynamic configuration using RandR, it also does not expose +correct multi-monitor information via the RandR API. So, in some setups, i3 +will not find any screens; in others, it will find one large screen which +actually contains both of your physical screens (but it will not know that +these are two screens). + +For this very reason, we decided to implement the following workaround: As +long as the nVidia driver does not support RandR, an option called ++--force-xinerama+ is available in i3. This option gets the list of screens +*once* when starting, and never updates it. As the nVidia driver cannot do +dynamic configuration anyways, this is not a big deal. + +== See also + +For more information on how to use multi-monitor setups, see the i3 User’s +Guide. diff --git a/_docs/tree-migrating b/_docs/tree-migrating new file mode 100644 index 0000000..15ea54e --- /dev/null +++ b/_docs/tree-migrating @@ -0,0 +1,192 @@ +Tree branch: Migrating +====================== +Michael Stapelberg +November 2010 + +== Introduction + +The tree branch (referring to a branch of i3 in the git repository) is the new +version of i3. Due to the very deep changes and heavy refactoring of the source +source, we decided to develop it in a seperate branch (instead of using the +next/master-branch system like before). + +== Current status + +Currently, the code is mostly working. Some of the i3 core developers have been +using the tree branch version for a few weeks now. So, if you are eager to try +out the new features and help us find bugs, give it a try! + +At the same time, a word of warning is appropriate: This version of i3 might +crash unexpectedly, so please be careful with important data (do not work for +two days without saving…). + +== Getting the latest tree branch version + +Check out the latest version: +--------------------------------------------- +$ git clone -b tree git://code.stapelberg.de/i3 +--------------------------------------------- + +Then build and install it (has the same dependencies as the latest stable i3 +version): +----------------------------- +$ cd i3 +$ make +$ sudo cp i3 /usr/bin/i3-tree +----------------------------- + +…and execute +i3-tree+ instead of +i3+ in your Xsession. + +*IMPORTANT:* Please note that configuration file compatibility is not yet done. +So, make sure you use/customize the provided +i3.config+ file. + +== Tree + +The most important change and reason for the name is that i3 stores all +information about the X11 outputs, workspaces and layout of the windows on them +in a tree. The root node is the X11 root window, followed by the X11 outputs, +then workspaces and finally the windows themselve. In previous versions of i3 +we had multiple lists (of outputs, workspaces) and a table for each workspace. +That approach turned out to be complicated to use (snapping), understand and +implement. + +=== The tree consists of Containers + +The building blocks of our tree are so called +Containers+. A +Container+ can +host a window (meaning an X11 window, one that you can actually see and use, +like a browser). Alternatively, it could contain one or more +Containers+. A +simple example is the workspace: When you start i3 with a single monitor, a +single workspace and you open two terminal windows, you will end up with a tree +like this: + +image::tree-layout2.png["layout2",float="right"] +image::tree-shot4.png["shot4",title="Two terminals on standard workspace"] + +=== Orientation and Split Containers + +[[OrientationSplit]] + +It is only natural to use so-called +Split Containers+ in order to build a +layout when using a tree as data structure. In i3, every +Container+ has an +orientation (horizontal, vertical or unspecified). So, in our example with the +workspace, the default orientation of the workspace +Container+ is horizontal +(most monitors are widescreen nowadays). If you change the orientation to +vertical (+Alt+v+ in the default config) and *then* open two terminals, i3 will +configure your windows like this: + +image::tree-shot2.png["shot2",title="Vertical Workspace Orientation"] + +An interesting new feature of the tree branch is the ability to split anything: +Let’s assume you have two terminals on a workspace (with horizontal +orientation), focus is on the right terminal. Now you want to open another +terminal window below the current one. If you would just open a new terminal +window, it would show up to the right due to the horizontal workspace +orientation. Instead, press +Alt+v+ to create a +Vertical Split Container+ (to +open a +Horizontal Split Container+, use +Alt+h+). Now you can open a new +terminal and it will open below the current one: + +image::tree-layout1.png["Layout",float="right"] +image::tree-shot1.png["shot",title="Vertical Split Container"] + +unfloat::[] + +You probably guessed it already: There is no limit on how deep your hierarchy +of splits can be. + +=== Level up + +Let’s stay with our example from above. We have a terminal on the left and two +vertically split terminals on the right, focus is on the bottom right one. When +you open a new terminal, it will open below the current one. + +So, how can you open a new terminal window to the *right* of the current one? +The solution is to use +level up+, which will focus the +Parent Container+ of +the current +Container+. In this case, you would focus the +Vertical Split +Container+ which is *inside* the horizontally oriented workspace. Thus, now new +windows will be opened to the right of the +Vertical Split Container+: + +image::tree-shot3.png["shot3",title="Level Up, then open new terminal"] + +== Commands + +The authoritive reference for commands is +src/cmdparse.y+. You can also find +most commands in +i3.config+. Here comes a short overview over the important +commands: + +=== Manipulating layout + +------------------------------- +layout +------------------------------- + +=== Changing Focus + +-------------------------- +next +prev +-------------------------- + +.Examples: +------------------------- +bindsym Mod1+Left prev h +bindsym Mod1+Right next h +bindsym Mod1+Down next v +bindsym Mod1+Up prev v +------------------------- + +=== Moving + +----------------------------------------- +move +----------------------------------------- + +.Examples: +----------------------------------------- +bindsym Mod1+Shift+Left move before h +bindsym Mod1+Shift+Right move after h +bindsym Mod1+Shift+Down move before v +bindsym Mod1+Shift+Up move after v +----------------------------------------- + +=== Changing workspace + +--------------------------- +workspace +--------------------------- + +.Examples: +--------------------------- +bindsym Mod1+1 workspace 1 +bindsym Mod1+2 workspace 2 +… +--------------------------- + +=== Moving Containers to workspaces + +--------------------- +move workspace +--------------------- + +------------------------------------- +bindsym Mod1+Shift+1 move workspace 1 +bindsym Mod1+Shift+2 move workspace 2 +… +------------------------------------- + +=== Changing border style + +--------------------------- +border +--------------------------- + +=== Changing container mode + +----------------------------- +mode +----------------------------- + +== The rest + +What is not mentioned here explicitly is either unchanged and can be read in +the http://i3.zekjur.net/docs/userguide.html[i3 User’s Guide] or it is not yet +implemented. diff --git a/_docs/userguide b/_docs/userguide new file mode 100644 index 0000000..42599ca --- /dev/null +++ b/_docs/userguide @@ -0,0 +1,998 @@ +i3 User’s Guide +=============== +Michael Stapelberg +March 2010 + +This document contains all the information you need to configure and use the i3 +window manager. If it does not, please contact me on IRC, Jabber or E-Mail and +I’ll help you out. + +== Default keybindings + +For the "too long; didn’t read" people, here is an overview of the default +keybindings (click to see the full size image): + +*Keys to use with Mod1 (alt):* + +image:keyboard-layer1.png["Keys to use with Mod1 (alt)",width=600,link="keyboard-layer1.png"] + +*Keys to use with Shift+Mod1:* + +image:keyboard-layer2.png["Keys to use with Shift+Mod1",width=600,link="keyboard-layer2.png"] + +As i3 uses keycodes in the default configuration, it does not matter which +keyboard layout you actually use. The key positions are what matters (of course +you can also use keysymbols, see <>). + +The red keys are the modifiers you need to press (by default), the blue keys +are your homerow. + +== Using i3 + +=== Opening terminals and moving around + +One very basic operation is opening a new terminal. By default, the keybinding +for this is Mod1+Enter, that is Alt+Enter in the default configuration. By +pressing Mod1+Enter, a new terminal will be opened. It will fill the whole +space available on your screen. + +image:single_terminal.png[Single terminal] + +It is important to keep in mind that i3 uses a table to manage your windows. At +the moment, you have exactly one column and one row which leaves you with one +cell. In this cell there is a container, which is where your new terminal is +opened. + +If you now open another terminal, you still have only one cell. However, the +container in that cell holds both of your terminals. So, a container is just a +group of clients with a specific layout. Containers can be resized by adjusting +the size of the cell that holds them. + +image:two_terminals.png[Two terminals] + +To move the focus between the two terminals, you use the direction keys which +you may know from the editor +vi+. However, in i3, your homerow is used for +these keys (in +vi+, the keys are shifted to the left by one for compatibility +with most keyboard layouts). Therefore, +Mod1+J+ is left, +Mod1+K+ is down, ++Mod1+L+ is up and `Mod1+;` is right. So, to switch between the terminals, +use +Mod1+K+ or +Mod1+L+. + +To create a new row/column (and a new cell), you can simply move a terminal (or +any other window) in the direction you want to expand your table. So, let’s +expand the table to the right by pressing `Mod1+Shift+;`. + +image:two_columns.png[Two columns] + +=== Changing container modes + +A container can have the following modes: + +default:: +Windows are sized so that every window gets an equal amount of space in the +container. +stacking:: +Only the focused window in the container is displayed. You get a list of +windows at the top of the container. +tabbed:: +The same principle as +stacking+, but the list of windows at the top is only +a single line which is vertically split. + +To switch modes, press +Mod1+e+ for default, +Mod1+h+ for stacking and ++Mod1+w+ for tabbed. + +image:modes.png[Container modes] + +=== Toggling fullscreen mode for a window + +To display a window fullscreen or to go out of fullscreen mode again, press ++Mod1+f+. + +There is also a global fullscreen mode in i3 in which the client will use all +available outputs. To use it, or to get out of it again, press +Mod1+Shift+f+. + +=== Opening other applications + +Aside from opening applications from a terminal, you can also use the handy ++dmenu+ which is opened by pressing +Mod1+v+ by default. Just type the name +(or a part of it) of the application which you want to open. The application +typed has to be in your +$PATH+ for this to work. + +Additionally, if you have applications you open very frequently, you can +create a keybinding for starting the application directly. See the section +"Configuring i3" for details. + +=== Closing windows + +If an application does not provide a mechanism for closing (most applications +provide a menu, the escape key or a shortcut like +Control+W+ to close), you +can press +Mod1+Shift+q+ to kill a window. For applications which support +the WM_DELETE protocol, this will correctly close the application (saving +any modifications or doing other cleanup). If the application doesn’t support +the WM_DELETE protocol your X server will kill the window and the behaviour +depends on the application. + +=== Using workspaces + +Workspaces are an easy way to group a set of windows. By default, you are on +the first workspace, as the bar on the bottom left indicates. To switch to +another workspace, press +Mod1+num+ where +num+ is the number of the workspace +you want to use. If the workspace does not exist yet, it will be created. + +A common paradigm is to put the web browser on one workspace, communication +applications (+mutt+, +irssi+, ...) on another one, and the ones with which you +work, on the third one. Of course, there is no need to follow this approach. + +If you have multiple screens, a workspace will be created on each screen at +startup. If you open a new workspace, it will be bound to the screen you +created it on. When you switch to a workspace on another screen, i3 will set +focus to that screen. + +=== Moving windows to workspaces + +To move a window to another workspace, simply press +Mod1+Shift+num+ where ++num+ is (like when switching workspaces) the number of the target workspace. +Similarly to switching workspaces, the target workspace will be created if +it does not yet exist. + +=== Resizing columns/rows + +To resize columns or rows, just grab the border between the two columns/rows +and move it to the wanted size. Please keep in mind that each cell of the table +holds a +container+ and thus you cannot horizontally resize single windows. If +you need applications with different horizontal sizes, place them in seperate +cells one above the other. + +See <> for how to configure i3 to be able to resize +columns/rows with your keyboard. + +=== Restarting i3 inplace + +To restart i3 inplace (and thus get into a clean state if there is a bug, or +to upgrade to a newer version of i3) you can use +Mod1+Shift+r+. Be aware, +though, that this kills your current layout and all the windows you have opened +will be put in a default container in only one cell. Saving layouts will be +implemented in a later version. + +=== Exiting i3 + +To cleanly exit i3 without killing your X server, you can use +Mod1+Shift+e+. + +=== Snapping + +Snapping is a mechanism to increase/decrease the colspan/rowspan of a container. +Colspan/rowspan is the number of columns/rows a specific cell of the table +consumes. This is easier explained by giving an example, so take the following +layout: + +image:snapping.png[Snapping example] + +To use the full size of your screen, you can now snap container 3 downwards +by pressing +Mod1+Control+k+ (or snap container 2 rightwards). + +=== Floating + +Floating mode is the opposite of tiling mode. The position and size of a window +are not managed by i3, but by you. Using this mode violates the tiling +paradigm but can be useful for some corner cases like "Save as" dialog +windows, or toolbar windows (GIMP or similar). + +You can enable floating mode for a window by pressing +Mod1+Shift+Space+. By +dragging the window’s titlebar with your mouse you can move the window +around. By grabbing the borders and moving them you can resize the window. You +can also do that by using the <>. + +For resizing floating windows with your keyboard, see <>. + +Floating windows are always on top of tiling windows. + +== Configuring i3 + +This is where the real fun begins ;-). Most things are very dependant on your +ideal working environment so we can’t make reasonable defaults for them. + +While not using a programming language for the configuration, i3 stays +quite flexible in regards to the things you usually want your window manager +to do. + +For example, you can configure bindings to jump to specific windows, +you can set specific applications to start on specific workspaces, you can +automatically start applications, you can change the colors of i3, and you +can bind your keys to do useful things. + +To change the configuration of i3, copy +/etc/i3/config+ to +\~/.i3/config+ +(or +~/.config/i3/config+ if you like the XDG directory scheme) and edit it +with a text editor. + +=== Comments + +It is possible and recommended to use comments in your configuration file to +properly document your setup for later reference. Comments are started with +a # and can only be used at the beginning of a line: + +*Examples*: +------------------- +# This is a comment +------------------- + +=== Fonts + +i3 uses X core fonts (not Xft) for rendering window titles and the internal +workspace bar. You can use +xfontsel(1)+ to generate such a font description. +To see special characters (Unicode), you need to use a font which supports +the ISO-10646 encoding. + +*Syntax*: +------------------------------ +font +------------------------------ + +*Examples*: +-------------------------------------------------------------- +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +-------------------------------------------------------------- + +[[keybindings]] + +=== Keyboard bindings + +A keyboard binding makes i3 execute a command (see below) upon pressing a +specific key. i3 allows you to bind either on keycodes or on keysyms (you can +also mix your bindings, though i3 will not protect you from overlapping ones). + +* A keysym (key symbol) is a description for a specific symbol, like "a" + or "b", but also more strange ones like "underscore" instead of "_". These + are the ones you use in Xmodmap to remap your keys. To get the current + mapping of your keys, use +xmodmap -pke+. + +* Keycodes do not need to have a symbol assigned (handy for some hotkeys + on some notebooks) and they will not change their meaning as you switch to a + different keyboard layout (when using +xmodmap+). + +My recommendation is: If you often switch keyboard layouts but you want to keep +your bindings in the same physical location on the keyboard, use keycodes. +If you don’t switch layouts, and want a clean and simple config file, use +keysyms. + +*Syntax*: +---------------------------------- +bindsym [Modifiers+]keysym command +bind [Modifiers+]keycode command +---------------------------------- + +*Examples*: +-------------------------------- +# Fullscreen +bindsym Mod1+f f + +# Restart +bindsym Mod1+Shift+r restart + +# Notebook-specific hotkeys +bind 214 exec /home/michael/toggle_beamer.sh +-------------------------------- + +Available Modifiers: + +Mod1-Mod5, Shift, Control:: +Standard modifiers, see +xmodmap(1)+ + +Mode_switch:: +Unlike other window managers, i3 can use Mode_switch as a modifier. This allows +you to remap capslock (for example) to Mode_switch and use it for both: typing +umlauts or special characters 'and' having some comfortably reachable key +bindings. For example, when typing, capslock+1 or capslock+2 for switching +workspaces is totally convenient. Try it :-). + +[[floating_modifier]] + +=== The floating modifier + +To move floating windows with your mouse, you can either grab their titlebar +or configure the so called floating modifier which you can then press and +click anywhere in the window itself to move it. The most common setup is to +use the same key you use for managing windows (Mod1 for example). Then +you can press Mod1, click into a window using your left mouse button, and drag +it to the position you want. + +When holding the floating modifier, you can resize a floating window by +pressing the right mouse button on it and moving around while holding it. If +you hold the shift button as well, the resize will be proportional. + +*Syntax*: +-------------------------------- +floating_modifier +-------------------------------- + +*Examples*: +-------------------------------- +floating_modifier Mod1 +-------------------------------- + +=== Layout mode for new containers + +This option determines in which mode new containers will start. See also +<>. + +*Syntax*: +--------------------------------------------- +new_container +new_container stack-limit +--------------------------------------------- + +*Examples*: +--------------------- +new_container tabbed +--------------------- + +=== Border style for new windows + +This option determines which border style new windows will have. + +*Syntax*: +--------------------------------------------- +new_window +--------------------------------------------- + +*Examples*: +--------------------- +new_window bp +--------------------- + +=== Variables + +As you learned in the section about keyboard bindings, you will have +to configure lots of bindings containing modifier keys. If you want to save +yourself some typing and be able to change the modifier you use later, +variables can be handy. + +*Syntax*: +-------------- +set name value +-------------- + +*Examples*: +------------------------ +set $m Mod1 +bindsym $m+Shift+r restart +------------------------ + +Variables are directly replaced in the file when parsing. There is no fancy +handling and there are absolutely no plans to change this. If you need a more +dynamic configuration you should create a little script which generates a +configuration file and run it before starting i3 (for example in your ++.xsession+ file). + +=== Automatically putting clients on specific workspaces + +[[assign_workspace]] + +It is recommended that you match on window classes wherever possible because +some applications first create their window, and then worry about setting the +correct title. Firefox with Vimperator comes to mind. The window starts up +being named Firefox, and only when Vimperator is loaded does the title change. +As i3 will get the title as soon as the application maps the window (mapping +means actually displaying it on the screen), you’d need to have to match on +'Firefox' in this case. + +You can prefix or suffix workspaces with a `~` to specify that matching clients +should be put into floating mode. If you specify only a `~`, the client will +not be put onto any workspace, but will be set floating on the current one. + +*Syntax*: +------------------------------------------------------------ +assign ["]window class[/window title]["] [→] [~ | workspace] +------------------------------------------------------------ + +*Examples*: +---------------------- +assign urxvt 2 +assign urxvt → 2 +assign "urxvt" → 2 +assign "urxvt/VIM" → 3 +assign "gecko" → ~4 +assign "xv/MPlayer" → ~ +---------------------- + +Note that the arrow is not required, it just looks good :-). If you decide to +use it, it has to be a UTF-8 encoded arrow, not "->" or something like that. + +=== Automatically starting applications on i3 startup + +By using the +exec+ keyword outside a keybinding, you can configure which +commands will be performed by i3 on initial startup (not when restarting i3 +in-place however). These commands will be run in order. + +*Syntax*: +------------ +exec command +------------ + +*Examples*: +-------------------------------- +exec sudo i3status | dzen2 -dock +-------------------------------- + +[[workspace_screen]] + +=== Automatically putting workspaces on specific screens + +If you assign clients to workspaces, it might be handy to put the +workspaces on specific screens. Also, the assignment of workspaces to screens +will determine which workspace i3 uses for a new screen when adding screens +or when starting (e.g., by default it will use 1 for the first screen, 2 for +the second screen and so on). + +*Syntax*: +---------------------------------- +workspace output +---------------------------------- + +The 'output' is the name of the RandR output you attach your screen to. On a +laptop, you might have VGA1 and LVDS1 as output names. You can see the +available outputs by running +xrandr --current+. + +*Examples*: +--------------------------- +workspace 1 output LVDS1 +workspace 5 output VGA1 +--------------------------- + +=== Named workspaces + +If you always have a certain arrangement of workspaces, you might want to give +them names (of course UTF-8 is supported): + +*Syntax*: +--------------------------------------- +workspace +workspace output name +--------------------------------------- + +For more details about the 'output' part of this command, see above. + +*Examples*: +-------------------------- +workspace 1 www +workspace 2 work +workspace 3 i ♥ workspaces +-------------------------- + +=== Changing colors + +You can change all colors which i3 uses to draw the window decorations and the +bottom bar. + +*Syntax*: +-------------------------------------------- +colorclass border background text +-------------------------------------------- + +Where colorclass can be one of: + +client.focused:: + A client which currently has the focus. +client.focused_inactive:: + A client which is the focused one of its container, but it does not have + the focus at the moment. +client.unfocused:: + A client which is not the focused one of its container. +client.urgent:: + A client which has its urgency hint activated. +bar.focused:: + The current workspace in the bottom bar. +bar.unfocused:: + All other workspaces in the bottom bar. +bar.urgent:: + A workspace which has at least one client with an activated urgency hint. + +You can also specify the color to be used to paint the background of the client +windows. This color will be used to paint the window on top of which the client +will be rendered. + +*Syntax*: +----------------------- +client.background color +----------------------- + +Only clients that do not cover the whole area of this window expose the color +used to paint it. If you use a color other than black for your terminals, you +most likely want to set the client background color to the same color as your +terminal program's background color to avoid black gaps between the rendered +area of the termianal and the i3 border. + +Colors are in HTML hex format (#rrggbb), see the following example: + +*Examples*: +-------------------------------------- +# class border backgr. text +client.focused #2F343A #900000 #FFFFFF +-------------------------------------- + +Note that for the window decorations, the color around the child window is the +background color, and the border color is only the two thin lines at the top of +the window. + +=== Interprocess communication + +i3 uses unix sockets to provide an IPC interface. This allows third-party +programs to get information from i3, such as the current workspaces +(to display a workspace bar), and to control i3. + +To enable it, you have to configure a path where the unix socket will be +stored. The default path is +~/.i3/ipc.sock+. + +*Examples*: +---------------------------- +ipc-socket ~/.i3/ipc.sock +---------------------------- + +You can then use the +i3-msg+ application to perform any command listed in +the next section. + +=== Disable focus follows mouse + +If you have a setup where your mouse usually is in your way (like a touchpad +on your laptop which you do not want to disable completely), you might want +to disable 'focus follows mouse' and control focus only by using your keyboard. +The mouse will still be useful inside the currently active window (for example +to click on links in your browser window). + +*Syntax*: +---------------------------- +focus_follows_mouse +---------------------------- + +*Examples*: +---------------------- +focus_follows_mouse no +---------------------- + +=== Internal workspace bar + +The internal workspace bar (the thing at the bottom of your screen) is very +simple -- it does not provide a way to display custom text and it does not +offer advanced customization features. This is intended because we do not +want to duplicate functionality of tools like +dzen2+, +xmobar+ and so on +(they render bars, we manage windows). Instead, there is an option which will +turn off the internal bar completely, so that you can use a separate program to +display it (see +i3-wsbar+, a sample implementation of such a program): + +*Syntax*: +---------------------- +workspace_bar +---------------------- + +*Examples*: +---------------- +workspace_bar no +---------------- + +== List of commands + +=== Manipulating layout + +To change the layout of the current container to stacking, use +s+, for default +use +d+ and for tabbed, use +T+. To make the current client (!) fullscreen, +use +f+, to make it span all outputs, use +fg+, to make it floating (or +tiling again) use +t+: + +*Examples*: +-------------- +bindsym Mod1+s s +bindsym Mod1+l d +bindsym Mod1+w T + +# Toggle fullscreen +bindsym Mod1+f f + +# Toggle global fullscreen +bindsym Mod1+Shift+f fg + +# Toggle floating/tiling +bindsym Mod1+t t +-------------- + +=== Focusing/Moving/Snapping clients/containers/screens + +To change the focus, use one of the +h+, +j+, +k+ and +l+ commands, meaning +left, down, up, right (respectively). To focus a container, prefix it with ++wc+. To focus a screen, prefix it with +ws+. + +The same principle applies for moving and snapping: just prefix the command +with +m+ when moving and with +s+ when snapping: + +*Examples*: +---------------------- +# Focus clients on the left, bottom, top, right: +bindsym Mod1+j h +bindsym Mod1+k j +bindsym Mod1+j k +bindsym Mod1+semicolon l + +# Move client to the left, bottom, top, right: +bindsym Mod1+j mh +bindsym Mod1+k mj +bindsym Mod1+j mk +bindsym Mod1+semicolon ml + +# Snap client to the left, bottom, top, right: +bindsym Mod1+j sh +bindsym Mod1+k sj +bindsym Mod1+j sk +bindsym Mod1+semicolon sl + +# Focus container on the left, bottom, top, right: +bindsym Mod3+j wch +… +---------------------- + +=== Changing workspaces/moving clients to workspaces + +To change to a specific workspace, the command is just the number of the +workspace, e.g. +1+ or +3+. To move the current client to a specific workspace, +prefix the number with an +m+. + +You can also switch to the next and previous workspace with the commands +nw+ +and +pw+, which is handy, for example, if you have workspace 1, 3, 4 and 9 and +you want to cycle through them with a single key combination. + +*Examples*: +------------------------- +bindsym Mod1+1 1 +bindsym Mod1+2 2 +... + +bindsym Mod1+Shift+1 m1 +bindsym Mod1+Shift+2 m2 +... + +bindsym Mod1+o nw +bindsym Mod1+p pw +------------------------- + +[[resizingconfig]] + +=== Resizing columns/rows + +If you want to resize columns/rows using your keyboard, you can use the ++resize+ command, I recommend using it inside a so called +mode+: + +.Example: Configuration file, defining a mode for resizing +---------------------------------------------------------------------- +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # They resize the border in the direction you pressed, e.g. + # when pressing left, the window is resized so that it has + # more space on its left + + bindsym n resize left -10 + bindsym Shift+n resize left +10 + + bindsym r resize bottom +10 + bindsym Shift+r resize bottom -10 + + bindsym t resize top -10 + bindsym Shift+t resize top +10 + + bindsym d resize right +10 + bindsym Shift+d resize right -10 + + bind 36 mode default +} + +# Enter resize mode +bindsym Mod1+r mode resize +---------------------------------------------------------------------- + +=== Jumping to specific windows + +Often when in a multi-monitor environment, you want to quickly jump to a +specific window. For example, while working on workspace 3 you may want to +jump to your mail client to email your boss that you’ve achieved some +important goal. Instead of figuring out how to navigate to your mailclient, +it would be more convenient to have a shortcut. + +*Syntax*: +---------------------------------------------------- +jump ["]window class[/window title]["] +jump workspace [ column row ] +---------------------------------------------------- + +You can either use the same matching algorithm as in the +assign+ command +(see above) or you can specify the position of the client if you always use +the same layout. + +*Examples*: +-------------------------------------- +# Get me to the next open VIM instance +bindsym Mod1+a jump "urxvt/VIM" +-------------------------------------- + +=== VIM-like marks (mark/goto) + +[[vim_like_marks]] + +This feature is like the jump feature: It allows you to directly jump to a +specific window (this means switching to the appropriate workspace and setting +focus to the windows). However, you can directly mark a specific window with +an arbitrary label and use it afterwards. You do not need to ensure that your +windows have unique classes or titles, and you do not need to change your +configuration file. + +As the command needs to include the label with which you want to mark the +window, you cannot simply bind it to a key. +i3-input+ is a tool created +for this purpose: It lets you input a command and sends the command to i3. It +can also prefix this command and display a custom prompt for the input dialog. + +*Syntax*: +----------------- +mark +goto +----------------- + +*Examples*: +--------------------------------------- +# Read 1 character and mark the current window with this character +bindsym Mod1+m exec i3-input -p 'mark ' -l 1 -P 'Mark: ' + +# Read 1 character and go to the window with the character +bindsym Mod1+g exec i3-input -p 'goto ' -l 1 -P 'Goto: ' +--------------------------------------- + +Alternatively, if you do not want to mess with +i3-input+, you could create +seperate bindings for a specific set of labels and then only use those labels. + +=== Traveling the focus stack + +This mechanism can be thought of as the opposite of the +jump+ command. +It travels the focus stack and jumps to the window which had focus previously. + +*Syntax*: +-------------- +focus [number] | floating | tiling | ft +-------------- + +Where +number+ by default is 1 meaning that the next client in the focus stack +will be selected. + +The special values have the following meaning: + +floating:: + The next floating window is selected. +tiling:: + The next tiling window is selected. +ft:: + If the current window is floating, the next tiling window will be + selected; and vice-versa. + +=== Changing border style + +To change the border of the current client, you can use +bn+ to use the normal +border (including window title), +bp+ to use a 1-pixel border (no window title) +and +bb+ to make the client borderless. There is also +bt+ which will toggle +the different border styles. + +*Examples*: +------------------ +bindsym Mod1+t bn +bindsym Mod1+y bp +bindsym Mod1+u bb +------------------ + +[[stack-limit]] + +=== Changing the stack-limit of a container + +If you have a single container with a lot of windows inside it (say, more than +10), the default layout of a stacking container can get a little unhandy. +Depending on your screen’s size, you might end up seeing only half of the +titlebars for each window in the container. + +Using the +stack-limit+ command, you can limit the number of rows or columns +in a stacking container. i3 will create columns or rows (depending on what +you limited) automatically as needed. + +*Syntax*: +-------------------------------- +stack-limit +-------------------------------- + +*Examples*: +------------------- +# I always want to have two window titles in one line +stack-limit cols 2 + +# Not more than 5 rows in this stacking container +stack-limit rows 5 +------------------- + +image:stacklimit.png[Container limited to two columns] + +=== Reloading/Restarting/Exiting + +You can make i3 reload its configuration file with +reload+. You can also +restart i3 inplace with the +restart+ command to get it out of some weird state +(if that should ever happen) or to perform an upgrade without having to restart +your X session. However, your layout is not preserved at the moment, meaning +that all open windows will end up in a single container in default layout +after the restart. To exit i3 properly, you can use the +exit+ command, +however you don’t need to (simply killing your X session is fine as well). + +*Examples*: +---------------------------- +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+w reload +bindsym Mod1+Shift+e exit +---------------------------- + +[[multi_monitor]] + +== Multiple monitors + +As you can see in the goal list on the website, i3 was specifically developed +with support for multiple monitors in mind. This section will explain how to +handle multiple monitors. + +When you have only one monitor, things are simple. You usually start with +workspace 1 on your monitor and open new ones as you need them. + +When you have more than one monitor, each monitor will get an initial +workspace. The first monitor gets 1, the second gets 2 and a possible third +would get 3. When you switch to a workspace on a different monitor, i3 will +switch to that monitor and then switch to the workspace. This way, you don’t +need shortcuts to switch to a specific monitor, and you don’t need to remember +where you put which workspace. New workspaces will be opened on the currently +active monitor. It is not possible to have a monitor without a workspace. + +The idea of making workspaces global is based on the observation that most +users have a very limited set of workspaces on their additional monitors. +They are often used for a specific task (browser, shell) or for monitoring +several things (mail, IRC, syslog, …). Thus, using one workspace on one monitor +and "the rest" on the other monitors often makes sense. However, as you can +create an unlimited number of workspaces in i3 and tie them to specific +screens, you can have the "traditional" approach of having X workspaces per +screen by changing your configuration (using modes, for example). + +=== Configuring your monitors + +To help you get going if you have never used multiple monitors before, here is +a short overview of the xrandr options which will probably be of interest to +you. It is always useful to get an overview of the current screen configuration. +Just run "xrandr" and you will get an output like the following: +------------------------------------------------------------------------------- +$ xrandr +Screen 0: minimum 320 x 200, current 1280 x 800, maximum 8192 x 8192 +VGA1 disconnected (normal left inverted right x axis y axis) +LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 261mm x 163mm + 1280x800 60.0*+ 50.0 + 1024x768 85.0 75.0 70.1 60.0 + 832x624 74.6 + 800x600 85.1 72.2 75.0 60.3 56.2 + 640x480 85.0 72.8 75.0 59.9 + 720x400 85.0 + 640x400 85.1 + 640x350 85.1 +-------------------------------------------------------------------------------------- + +Several things are important here: You can see that +LVDS1+ is connected (of +course, it is the internal flat panel) but +VGA1+ is not. If you have a monitor +connected to one of the ports but xrandr still says "disconnected", you should +check your cable, monitor or graphics driver. + +The maximum resolution you can see at the end of the first line is the maximum +combined resolution of your monitors. By default, it is usually too low and has +to be increased by editing +/etc/X11/xorg.conf+. + +So, say you connected VGA1 and want to use it as an additional screen: +------------------------------------------- +xrandr --output VGA1 --auto --left-of LVDS1 +------------------------------------------- +This command makes xrandr try to find the native resolution of the device +connected to +VGA1+ and configures it to the left of your internal flat panel. +When running "xrandr" again, the output looks like this: +------------------------------------------------------------------------------- +$ xrandr +Screen 0: minimum 320 x 200, current 2560 x 1024, maximum 8192 x 8192 +VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm + 1280x1024 60.0*+ 75.0 + 1280x960 60.0 + 1152x864 75.0 + 1024x768 75.1 70.1 60.0 + 832x624 74.6 + 800x600 72.2 75.0 60.3 56.2 + 640x480 72.8 75.0 66.7 60.0 + 720x400 70.1 +LVDS1 connected 1280x800+1280+0 (normal left inverted right x axis y axis) 261mm x 163mm + 1280x800 60.0*+ 50.0 + 1024x768 85.0 75.0 70.1 60.0 + 832x624 74.6 + 800x600 85.1 72.2 75.0 60.3 56.2 + 640x480 85.0 72.8 75.0 59.9 + 720x400 85.0 + 640x400 85.1 + 640x350 85.1 +------------------------------------------------------------------------------- +Please note that i3 uses exactly the same API as xrandr does, so it will see +only what you can see in xrandr. + +See also <> for more examples of multi-monitor setups. + +=== Interesting configuration for multi-monitor environments + +There are several things to configure in i3 which may be interesting if you +have more than one monitor: + +1. You can specify which workspace should be put on which screen. This + allows you to have a different set of workspaces when starting than just + 1 for the first monitor, 2 for the second and so on. See + <>. +2. If you want some applications to generally open on the bigger screen + (MPlayer, Firefox, …), you can assign them to a specific workspace, see + <>. +3. If you have many workspaces on many monitors, it might get hard to keep + track of which window you put where. Thus, you can use vim-like marks to + quickly switch between windows. See <>. + +== i3 and the rest of your software world + +=== Displaying a status line + +A very common thing amongst users of exotic window managers is a status line at +some corner of the screen. It is an often superior replacement to the widget +approach you have in the task bar of a traditional desktop environment. + +If you don’t already have your favorite way of generating such a status line +(self-written scripts, conky, …), then i3status is the recommended tool for +this task. It was written in C with the goal of using as few syscalls as +possible to reduce the time your CPU is woken up from sleep states. + +Regardless of which application you use to generate the status line, you +want to make sure that the application does one of the following things: + +1. Register as a dock window using EWMH hints. This will make i3 position the + window above the workspace bar but below every other client. This is the + recommended way, but in case of dzen2, for example, you need to check out + the source of dzen2 from subversion, as the -dock option is not present + in the released versions. +2. Overlay the internal workspace bar. This method will not waste any space + on the workspace bar, however, it is rather hackish. Just configure + the output window to be over the workspace bar (say -x 200 and -y 780 if + your screen is 800 px height). + +The planned solution for this problem is to make the workspace bar optional +and switch to a third party application completely (dzen2 for example) +which will then contain the workspace bar. + +=== Giving presentations (multi-monitor) + +When giving a presentation, you typically want the audience to see what you see +on your screen and then go through a series of slides (if the presentation is +simple). For more complex presentations, you might want to have some notes +which only you can see on your screen, while the audience can only see the +slides. + +[[presentations]] +==== Case 1: everybody gets the same output +This is the simple case. You connect your computer to the video projector, +turn on both (computer and video projector) and configure your X server to +clone the internal flat panel of your computer to the video output: +----------------------------------------------------- +xrandr --output VGA1 --mode 1024x768 --same-as LVDS1 +----------------------------------------------------- +i3 will then use the lowest common subset of screen resolutions, the rest of +your screen will be left untouched (it will show the X background). So, in +our example, this would be 1024x768 (my notebook has 1280x800). + +==== Case 2: you can see more than your audience +This case is a bit harder. First of all, you should configure the VGA output +somewhere near your internal flat panel, say right of it: +----------------------------------------------------- +xrandr --output VGA1 --mode 1024x768 --right-of LVDS1 +----------------------------------------------------- +Now, i3 will put a new workspace (depending on your settings) on the new screen +and you are in multi-monitor mode (see <>). + +Because i3 is not a compositing window manager, there is no ability to +display a window on two screens at the same time. Instead, your presentation +software needs to do this job (that is, open a window on each screen). diff --git a/_docs/wsbar b/_docs/wsbar new file mode 100644 index 0000000..9e379dd --- /dev/null +++ b/_docs/wsbar @@ -0,0 +1,94 @@ +External workspace bars +======================= +Michael Stapelberg +May 2010 + +This document describes why the internal workspace bar is minimal and how an +external workspace bar can be used. It explains the concepts using +i3-wsbar+ +as the reference implementation. + +== Internal and external bars + +The internal workspace bar of i3 is meant to be a reasonable default so that +you can use i3 without having too much hassle when setting it up. It is quite +simple and intended to stay this way. So, there is no way to display your own +information in this bar (unlike dwm, wmii, awesome, …). + +We chose not to implement such a mechanism because that would be duplicating +already existing functionality of tools such as dzen2, xmobar and similar. +Instead, you should disable the internal bar and use an external workspace bar +(which communicates with i3 through its IPC interface). + +== dock mode + +You typically want to see the same workspace bar on every workspace on a +specific screen. Also, you don’t want to place the workspace bar somewhere +in your layout by hand. This is where dock mode comes in: When a program sets +the appropriate hint (_NET_WM_WINDOW_TYPE_DOCK), it will be managed in dock +mode by i3. That means it will be placed at the bottom of the screen (while +other edges of the screen are possible in the NetWM standard, this is not yet +implemented in i3), it will not overlap any other window and it will be on +every workspace for the specific screen it was placed on initially. + +== The IPC interface + +In the context of using an external workspace bar, the IPC interface needs to +provide the bar program with the current workspaces and output (as in VGA-1, +LVDS-1, …) configuration. In the other direction, the program has to be able +to switch to specific workspaces. + +By default, the IPC interface is enabled and places its UNIX socket in ++~/.i3/ipc.sock+. + +To learn more about the protocol which is used for IPC, see +docs/ipc+. + +== Output changes (on-the-fly) + +i3 implements the RandR API and can handle changing outputs quite well. So, an +external workspace bar implementation needs to make sure that when you change +the resolution of any of your screens (or enable/disable an output), the bars +will be adjusted properly. + +== i3-wsbar, the reference implementation + +Please keep in mind that +i3-wsbar+ is just a reference implementation. It is +shipped with i3 to have a reasonable default. Thus, +i3-wsbar+ is designed to +work well with dzen2 and there are no plans to make it more generic. + +=== The big picture + +The most common reason to use an external workspace bar is to integrate system +information such as what +i3status+ provides into the workspace bar (to save +screen space). So, we have +i3status+ or a similar program, which only provides +text output (formatted in some way). To display this text nicely on the screen, +there are programs such as dzen2, xmobar and similar. We will stick to dzen2 +from here on. So, we have the output of i3status, which needs to go into dzen2 +somehow. But we also want to display the list of workspaces. +i3-wsbar+ takes +input on stdin, combines it with a formatted workspace list and pipes it to +dzen2. + +Please note that +i3-wsbar+ does not print its output to stdout. Instead, it +launches the dzen2 instances on its own. This is necessary to handle changes +in the available outputs (to place a new dzen2 on a new screen for example). + +image:wsbar.png["Overview",link="wsbar.png"] + +=== Running i3-wsbar + +The most simple usage of i3-wsbar looks like this: +------------------------------- +i3-wsbar -c "dzen2 -x %x -dock" +------------------------------- + +The +%x+ in the command name will be replaced by the X position of the output +for which this workspace bar is running. i3 will automatically place the +workspace bar on the correct output when dzen2 is started in dock mode. The +bar which you will see should look exactly like the internal bar of i3. + +To actually get a benefit, you want to give +i3-wsbar+ some input: +------------------------------------------ +i3status | i3-wsbar -c "dzen2 -x %x -dock" +------------------------------------------ + +It is recommended to place the above command in your i3 configuration file +to start it automatically with i3. diff --git a/css/xhtml11.css b/css/xhtml11.css new file mode 100644 index 0000000..f4fd4d4 --- /dev/null +++ b/css/xhtml11.css @@ -0,0 +1,404 @@ +a { + color: #3ec2ff; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: #3ec2ff; +} + +strong { + font-weight: bold; + color: #3ec2ff; +} + +tt { + font-family: 'Droid Sans Mono', sans-serif; + font-size: inherit; + color: #3ec2ff; +} + +div.listingblock tt { + color: black; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 1.2em; + margin-bottom: 0.5em; +} + +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +/*ul > li { color: #aaa; }*/ +/*ul > li > * { color: black; }*/ + +pre { + padding: 0; + margin: 0; +} + +span#author { + font-weight: bold; + font-size: 1.1em; +} +span#email { +} +span#revnumber, span#revdate, span#revremark { +} + +div#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +div#footer-text { + float: left; + padding-bottom: 0.5em; +} +div#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +div#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #777777; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #3ec2ff; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: #3ec2ff; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #3ec2ff; +} +thead, p.table.header { + font-weight: bold; + color: #3ec2ff; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + div#footer-badges { display: none; } +} + +div#toc { + margin-bottom: 2.5em; +} + +div#toctitle { + color: #3ec2ff; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + +span.aqua { color: aqua; } +span.black { color: black; } +span.blue { color: blue; } +span.fuchsia { color: fuchsia; } +span.gray { color: gray; } +span.green { color: green; } +span.lime { color: lime; } +span.maroon { color: maroon; } +span.navy { color: navy; } +span.olive { color: olive; } +span.purple { color: purple; } +span.red { color: red; } +span.silver { color: silver; } +span.teal { color: teal; } +span.white { color: white; } +span.yellow { color: yellow; } + +span.aqua-background { background: aqua; } +span.black-background { background: black; } +span.blue-background { background: blue; } +span.fuchsia-background { background: fuchsia; } +span.gray-background { background: gray; } +span.green-background { background: green; } +span.lime-background { background: lime; } +span.maroon-background { background: maroon; } +span.navy-background { background: navy; } +span.olive-background { background: olive; } +span.purple-background { background: purple; } +span.red-background { background: red; } +span.silver-background { background: silver; } +span.teal-background { background: teal; } +span.white-background { background: white; } +span.yellow-background { background: yellow; } + +span.big { font-size: 2em; } +span.small { font-size: 0.6em; } + +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: normal; + src: local('Droid Sans Mono'), local('DroidSansMono'), url('/fonts/DroidSansMono.ttf') format('truetype'); +} diff --git a/docs/bigpicture.png b/docs/bigpicture.png new file mode 100644 index 0000000..fc3c8db Binary files /dev/null and b/docs/bigpicture.png differ diff --git a/docs/debugging.html b/docs/debugging.html new file mode 100644 index 0000000..51abbf9 --- /dev/null +++ b/docs/debugging.html @@ -0,0 +1,148 @@ + + + + + +i3: Debugging i3: How To + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    This document describes how to debug i3 suitably for sending us useful bug +reports, even if you have no clue of C programming.

    +

    First of all: Thank you for being interested in debugging i3. It really means +something to us to get your bug fixed. If you have any questions about the +debugging and/or need further help, do not hesitate to contact us!

    +
    +
    +
    +

    1. Enabling logging

    +
    +

    i3 spits out much information onto stdout, if told so. To have a clearly +defined place where log files will be saved, you should redirect stdout and +stderr in xsession. While you’re at it, putting each run of i3 in a separate +log file with date/time in it is a good idea to not get confused about the +different log files later on.

    +
    +
    +
    exec /usr/bin/i3 -V -d all >/home/michael/i3/i3log-$(date +'%F-%k-%M-%S') 2>&1
    +
    +
    +
    +
    +

    2. Enabling core dumps

    +
    +

    When i3 crashes, often you have the chance of getting a core dump (an image +of the memory of the i3 process which can be loaded into a debugger). To get a +core dump, you have to make sure that the user limit for core dump files is set +high enough. Many systems ship with a default value which even forbids core +dumps completely. To disable the limit completely and thus enable core dumps, +use the following command (in your .xsession, before starting i3):

    +
    +
    +
    ulimit -c unlimited
    +
    +

    Furthermore, to easily recognize core dumps and allow multiple of them, you +should set a custom core dump filename pattern, using a command like the +following:

    +
    +
    +
    sudo sysctl -w kernel.core_pattern=core.%e.%p
    +
    +

    This will generate files which have the executable’s file name (%e) and the +process id (%p) in it. You can save this setting across reboots using +/etc/sysctl.conf.

    +
    +
    +
    +

    3. Compiling with debug symbols

    +
    +

    To actually get useful core dumps, you should make sure that your version of i3 +is compiled with debug symbols, that is, that they are not stripped during the +build process. You can check whether your executable contains symbols by +issuing the following command:

    +
    +
    +
    file $(which i3)
    +
    +

    You should get an output like this:

    +
    +
    +
    /usr/bin/i3: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
    +linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
    +
    +

    Notice the not stripped, which is the important part. If you have a version +which is stripped, please have a look if your distribution provides debug +symbols (package i3-wm-dbg on Debian for example) or if you can turn off +stripping. If nothing helps, please build i3 from source.

    +
    +
    +
    +

    4. Generating a backtrace

    +
    +

    Once you have made sure that your i3 is compiled with debug symbols and that +core dumps are enabled, you can start making sense out of the core dumps.

    +

    Because the core dump depends on the original executable (and its debug +symbols), please do this as soon as you encounter the problem. If you +re-compile i3, your core dump might be useless afterwards.

    +

    Please install gdb, a debugger for C. No worries, you don’t need to learn it +now. Start gdb using the following command (replacing the actual name of the +core dump of course):

    +
    +
    +
    gdb $(which i3) core.i3.3849
    +
    +

    Then, generate a backtrace using:

    +
    +
    +
    backtrace full
    +
    +
    +
    +
    +

    5. Sending bug reports/debugging on IRC

    +
    +

    When sending bug reports, please paste the relevant part of the log (if in +doubt, please send us rather too much information than too less) and the whole +backtrace (if there was a core dump).

    +

    When debugging with us in IRC, be prepared to use a so called nopaste service +such as http://nopaste.info or http://pastebin.com because pasting large +amounts of text in IRC sometimes leads to incomplete lines (servers have line +length limitations) or flood kicks.

    +
    +
    +
    +

    + + + diff --git a/docs/hacking-howto.html b/docs/hacking-howto.html new file mode 100644 index 0000000..d99aad9 --- /dev/null +++ b/docs/hacking-howto.html @@ -0,0 +1,891 @@ + + + + + +i3: Hacking i3: How To + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    This document is intended to be the first thing you read before looking and/or +touching i3’s source code. It should contain all important information to help +you understand why things are like they are. If it does not mention something +you find necessary, please do not hesitate to contact me.

    +
    +
    +
    +

    1. Window Managers

    +
    +

    A window manager is not necessarily needed to run X, but it is usually used in +combination with X to facilitate some things. The window manager’s job is to +take care of the placement of windows, to provide the user with some mechanisms +to change the position/size of windows and to communicate with clients to a +certain extent (for example handle fullscreen requests of clients such as +MPlayer).

    +

    There are no different contexts in which X11 clients run, so a window manager +is just another client, like all other X11 applications. However, it handles +some events which normal clients usually don’t handle.

    +

    In the case of i3, the tasks (and order of them) are the following:

    +
      +
    1. +

      +Grab the key bindings (events will be sent upon keypress/keyrelease) +

      +
    2. +
    3. +

      +Iterate through all existing windows (if the window manager is not started as + the first client of X) and manage them (reparent them, create window + decorations, etc.) +

      +
    4. +
    5. +

      +When new windows are created, manage them +

      +
    6. +
    7. +

      +Handle the client’s _WM_STATE property, but only the _WM_STATE_FULLSCREEN +

      +
    8. +
    9. +

      +Handle the client’s WM_NAME property +

      +
    10. +
    11. +

      +Handle the client’s size hints to display them proportionally +

      +
    12. +
    13. +

      +Handle the client’s urgency hint +

      +
    14. +
    15. +

      +Handle enter notifications (focus follows mouse) +

      +
    16. +
    17. +

      +Handle button (as in mouse buttons) presses for focus/raise on click +

      +
    18. +
    19. +

      +Handle expose events to re-draw own windows such as decorations +

      +
    20. +
    21. +

      +React to the user’s commands: Change focus, Move windows, Switch workspaces, + Change the layout mode of a container (default/stacking/tabbed), start a new + application, restart the window manager +

      +
    22. +
    +

    In the following chapters, each of these tasks and their implementation details +will be discussed.

    +
    +

    1.1. Tiling window managers

    +

    Traditionally, there are two approaches to managing windows: The most common +one nowadays is floating, which means the user can freely move/resize the +windows. The other approach is called tiling, which means that your window +manager distributes 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 +moving/resizing windows while you usually want to get some work done. After +all, most users sooner or later tend to lay out their windows in a way which +corresponds to tiling or stacking mode in i3. Therefore, why not let i3 do this +for you? Certainly, it’s faster than you could ever do it.

    +

    The problem with most tiling window managers is that they are too unflexible. +In my opinion, a window manager is just another tool, and similar to vim which +can edit all kinds of text files (like source code, HTML, …) and is not limited +to a specific file type, a window manager should not limit itself to a certain +layout (like dwm, awesome, …) but provide mechanisms for you to easily create +the layout you need at the moment.

    +
    +
    +

    1.2. The layout table

    +

    To accomplish flexible layouts, we decided to simply use a table. The table +grows and shrinks as you need it. Each cell holds a container which then holds +windows (see picture below). You can use different layouts for each container +(default layout and stacking layout).

    +

    So, when you open a terminal and immediately open another one, they reside in +the same container, in default layout. The layout table has exactly one column, +one row and therefore one cell. When you move one of the terminals to the +right, the table needs to grow. It will be expanded to two columns and one row. +This enables you to have different layouts for each container. The table then +looks like this:

    +
    + +++ + + + + + +

    T1

    T2

    +
    +

    When moving terminal 2 to the bottom, the table will be expanded again.

    +
    + +++ + + + + + + + + + +

    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).

    +
    + ++ + + + + + + + +
    +
    +
    T1
    +
    + +++ + + + + + +

    T2

    T3

    +
    +
    +

    Furthermore, you can freely resize table cells.

    +
    +
    +
    +
    +

    2. Files

    +
    +
    +
    +include/data.h +
    +
    +

    +Contains data definitions used by nearly all files. You really need to read +this first. +

    +
    +
    +include/*.h +
    +
    +

    +Contains forward definitions for all public functions, as well as +doxygen-compatible comments (so if you want to get a bit more of the big +picture, either browse all header files or use doxygen if you prefer that). +

    +
    +
    +src/cfgparse.l +
    +
    +

    +Contains the lexer for i3’s configuration file, written for flex(1). +

    +
    +
    +src/cfgparse.y +
    +
    +

    +Contains the parser for i3’s configuration file, written for bison(1). +

    +
    +
    +src/click.c +
    +
    +

    +Contains all functions which handle mouse button clicks (right mouse button +clicks initiate resizing and thus are relatively complex). +

    +
    +
    +src/client.c +
    +
    +

    +Contains all functions which are specific to a certain client (make it +fullscreen, see if its class/name matches a pattern, kill it, …). +

    +
    +
    +src/commands.c +
    +
    +

    +Parsing commands and actually executing them (focusing, moving, …). +

    +
    +
    +src/config.c +
    +
    +

    +Parses the configuration file. +

    +
    +
    +src/debug.c +
    +
    +

    +Contains debugging functions to print unhandled X events. +

    +
    +
    +src/floating.c +
    +
    +

    +Contains functions for floating mode (mostly resizing/dragging). +

    +
    +
    +src/handlers.c +
    +
    +

    +Contains all handlers for all kinds of X events (new window title, new hints, +unmapping, key presses, button presses, …). +

    +
    +
    +src/ipc.c +
    +
    +

    +Contains code for the IPC interface. +

    +
    +
    +src/layout.c +
    +
    +

    +Renders your layout (screens, workspaces, containers). +

    +
    +
    +src/mainx.c +
    +
    +

    +Initializes the window manager. +

    +
    +
    +src/manage.c +
    +
    +

    +Looks at existing or new windows and decides whether to manage them. If so, it +reparents the window and inserts it into our data structures. +

    +
    +
    +src/resize.c +
    +
    +

    +Contains the functions to resize columns/rows in the table. +

    +
    +
    +src/table.c +
    +
    +

    +Manages the most important internal data structure, the design table. +

    +
    +
    +src/util.c +
    +
    +

    +Contains useful functions which are not really dependant on anything. +

    +
    +
    +src/workspace.c +
    +
    +

    +Contains all functions related to workspaces (displaying, hiding, renaming…) +

    +
    +
    +src/xcb.c +
    +
    +

    +Contains wrappers to use xcb more easily. +

    +
    +
    +src/xinerama.c +
    +
    +

    +(Re-)initializes the available screens and converts them to virtual screens +(see below). +

    +
    +
    +
    +
    +
    +

    3. Data structures

    +
    +

    See include/data.h for documented data structures. The most important ones are +explained right here.

    +

    +The Big Picture +

    +

    So, the hierarchy is:

    +
      +
    1. +

      +Virtual screens (Screen 0 in this example) +

      +
    2. +
    3. +

      +Workspaces (Workspace 1 in this example) +

      +
    4. +
    5. +

      +Table (There can only be one table per Workspace) +

      +
    6. +
    7. +

      +Container (left and right in this example) +

      +
    8. +
    9. +

      +Client (The two clients in the left container) +

      +
    10. +
    +
    +

    3.1. Virtual screens

    +

    A virtual screen (type i3Screen) is generated from the connected screens +obtained through Xinerama. The difference to the raw Xinerama monitors as seen +when using xrandr(1) is that it falls back to the lowest common resolution of +the logical screens.

    +

    For example, if your notebook has 1280x800 and you connect a video projector +with 1024x768, set up in clone mode (xrandr --output VGA --mode 1024x768 +--same-as LVDS), i3 will have one virtual screen.

    +

    However, if you configure it using xrandr --output VGA --mode 1024x768 +--right-of LVDS, i3 will generate two virtual screens. For each virtual +screen, a new workspace will be assigned. New workspaces are created on the +screen you are currently on.

    +
    +
    +

    3.2. Workspace

    +

    A workspace is identified by its number. Basically, you could think of +workspaces as different desks in your office, if you like the desktop +methaphor. They just contain different sets of windows and are completely +separate of each other. Other window managers also call this “Virtual +desktops”.

    +
    +
    +

    3.3. The layout table

    +

    Each workspace has a table, which is just a two-dimensional dynamic array +containing Containers (see below). This table grows and shrinks as you need it +(by moving windows to the right you can create a new column in the table, by +moving them to the bottom you create a new row).

    +
    +
    +

    3.4. Container

    +

    A container is the content of a table’s cell. It holds an arbitrary amount of +windows and has a specific layout (default layout, stack layout or tabbed +layout). Containers can consume multiple table cells by modifying their +colspan/rowspan attribute.

    +
    +
    +

    3.5. Client

    +

    A client is x11-speak for a window.

    +
    +
    +
    +
    +

    4. List/queue macros

    +
    +

    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 +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).

    +

    The lists used are SLIST (single linked lists), CIRCLEQ (circular +queues) and TAILQ (tail queues). Usually, only forward traversal is necessary, +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 +windows inside a container, a CIRCLEQ is necessary to go from the currently +selected window to the window above/below.

    +
    +
    +
    +

    5. Naming conventions

    +
    +

    There is a row of standard variables used in many events. The following names +should be chosen for those:

    +
      +
    • +

      +“conn” is the xcb_connection_t +

      +
    • +
    • +

      +“event” is the event of the particular type +

      +
    • +
    • +

      +“container” names a container +

      +
    • +
    • +

      +“client” names a client, for example when using a CIRCLEQ_FOREACH +

      +
    • +
    +
    +
    +
    +

    6. Startup (src/mainx.c, main())

    +
    +
      +
    • +

      +Establish the xcb connection +

      +
    • +
    • +

      +Check for XKB extension on the separate X connection +

      +
    • +
    • +

      +Check for Xinerama screens +

      +
    • +
    • +

      +Grab the keycodes for which bindings exist +

      +
    • +
    • +

      +Manage all existing windows +

      +
    • +
    • +

      +Enter the event loop +

      +
    • +
    +
    +
    +
    +

    7. Keybindings

    +
    +
    +

    7.1. Grabbing the bindings

    +

    Grabbing the bindings is quite straight-forward. You pass X your combination of +modifiers and the keycode you want to grab and whether you want to grab them +actively or passively. Most bindings (everything except for bindings using +Mode_switch) are grabbed passively, that is, just the window manager gets the +event and cannot replay it.

    +

    We need to grab bindings that use Mode_switch actively because of a bug in X. +When the window manager receives the keypress/keyrelease event for an actively +grabbed keycode, it has to decide what to do with this event: It can either +replay it so that other applications get it or it can prevent other +applications from receiving it.

    +

    So, why do we need to grab keycodes actively? Because X does not set the +state-property of keypress/keyrelease events properly. The Mode_switch bit is +not set and we need to get it using XkbGetState. This means we cannot pass X +our combination of modifiers containing Mode_switch when grabbing the key and +therefore need to grab the keycode itself without any modifiers. This means, +if you bind Mode_switch + keycode 38 ("a"), i3 will grab keycode 38 ("a") and +check on each press of "a" if the Mode_switch bit is set using XKB. If yes, it +will handle the event, if not, it will replay the event.

    +
    +
    +

    7.2. Handling a keypress

    +

    As mentioned in "Grabbing the bindings", upon a keypress event, i3 first gets +the correct state.

    +

    Then, it looks through all bindings and gets the one which matches the received +event.

    +

    The bound command is parsed directly in command mode.

    +
    +
    +
    +
    +

    8. Manage windows (src/mainx.c, manage_window() and reparent_window())

    +
    +

    manage_window() does some checks to decide whether the window should be +managed at all:

    +
      +
    • +

      +Windows have to be mapped, that is, visible on screen +

      +
    • +
    • +

      +The override_redirect must not be set. Windows with override_redirect shall + not be managed by a window manager +

      +
    • +
    +

    Afterwards, i3 gets the intial geometry and reparents the window (see +reparent_window()) if it wasn’t already managed.

    +

    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 +reparented to the bigger one (called "frame").

    +

    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 +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 +of the screen. To get the height which needsd to be reserved for the window, +the _NET_WM_STRUT_PARTIAL property is used.

    +

    Furthermore, the list of assignments (to other workspaces, which may be on +other screens) is checked. If the window matches one of the user’s criteria, +it may either be put in floating mode or moved to a different workspace. If the +target workspace is not visible, the window will not be mapped.

    +
    +
    +
    +

    9. What happens when an application is started?

    +
    +

    i3 does not care for applications. All it notices is when new windows are +mapped (see src/handlers.c, handle_map_request()). The window is then +reparented (see section "Manage windows").

    +

    After reparenting the window, render_layout() is called which renders the +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 +moved/resized so that the currently active layout (default/stacking/tabbed mode) +is rendered correctly. To move/resize windows, a window is “configured” in +X11-speak.

    +

    Some applications, such as MPlayer obviously assume the window manager is +stupid and try to configure their windows by themselves. This generates an +event called configurerequest. i3 handles these events and tells the window the +size it had before the configurerequest (with the exception of not yet mapped +windows, which get configured like they want to, and floating windows, which +can reconfigure themselves).

    +
    +
    +
    +

    10. _NET_WM_STATE

    +
    +

    Only the _NET_WM_STATE_FULLSCREEN atom is handled. It calls +“toggle_fullscreen()” for the specific client which just configures the +client to use the whole screen on which it currently is. Also, it is set as +fullscreen_client for the i3Screen.

    +
    +
    +
    +

    11. WM_NAME

    +
    +

    When the WM_NAME property of a window changes, its decoration (containing the +title) is re-rendered. Note that WM_NAME is in COMPOUND_TEXT encoding which is +totally uncommon and cumbersome. Therefore, the _NET_WM_NAME atom will be used +if present.

    +
    +
    +
    +

    12. _NET_WM_NAME

    +
    +

    Like WM_NAME, this atom contains the title of a window. However, _NET_WM_NAME +is encoded in UTF-8. i3 will recode it to UCS-2 in order to be able to pass it +to X. Using an appropriate font (ISO-10646), you can see most special +characters (every special character contained in your font).

    +
    +
    +
    +

    13. Size hints

    +
    +

    Size hints specify the minimum/maximum size for a given window as well as its +aspect ratio. This is important for clients like mplayer, who only set the +aspect ratio and resize their window to be as small as possible (but only with +some video outputs, for example in Xv, while when using x11, mplayer does the +necessary centering for itself).

    +

    So, when an aspect ratio was specified, i3 adjusts the height of the window +until the size maintains the correct aspect ratio. For the code to do this, see +src/layout.c, function resize_client().

    +
    +
    +
    +

    14. Rendering (src/layout.c, render_layout() and render_container())

    +
    +

    There are several entry points to rendering: render_layout(), +render_workspace() and render_container(). The former one calls +render_workspace() for every screen, which in turn will call +render_container() for every container inside its layout table. Therefore, if +you need to render only a single container, for example because a window was +removed, added or changed its title, you should directly call +render_container().

    +

    Rendering consists of two steps: In the first one, in render_workspace(), each +container gets its position (screen offset + offset in the table) and size +(container’s width times colspan/rowspan). Then, render_container() is called, +which takes different approaches, depending on the mode the container is in:

    +
    +

    14.1. Common parts

    +

    On the frame (the window which was created around the client’s window for the +decorations), a black rectangle is drawn as a background for windows like +MPlayer, which do not completely fit into the frame.

    +
    +
    +

    14.2. Default mode

    +

    Each clients gets the container’s width and an equal amount of height.

    +
    +
    +

    14.3. Stack mode

    +

    In stack mode, a window containing the decorations of all windows inside the +container is placed at the top. The currently focused window is then given the +whole remaining space.

    +
    +
    +

    14.4. Tabbed mode

    +

    Tabbed mode is like stack mode, except that the window decorations are drawn +in one single line at the top of the container.

    +
    +
    +

    14.5. Window decorations

    +

    The window decorations consist of a rectangle in the appropriate color (depends +on whether this window is the currently focused one, the last focused one in a +not focused container or not focused at all) forming the background. +Afterwards, two lighter lines are drawn and the last step is drawing the +window’s title (see WM_NAME) onto it.

    +
    +
    +

    14.6. Fullscreen windows

    +

    For fullscreen windows, the rect (x, y, width, height) is not changed to +allow the client to easily go back to its previous position. Instead, +fullscreen windows are skipped when rendering.

    +
    +
    +

    14.7. Resizing containers

    +

    By clicking and dragging the border of a container, you can resize the whole +column (respectively row) which this container is in. This is necessary to keep +the table layout working and consistent.

    +

    The resizing works similarly to the resizing of floating windows or movement of +floating windows:

    +
      +
    • +

      +A new, invisible window with the size of the root window is created + (grabwin) +

      +
    • +
    • +

      +Another window, 2px width and as high as your screen (or vice versa for + horizontal resizing) is created. Its background color is the border color and + it is only there to inform the user how big the container will be (it + creates the impression of dragging the border out of the container). +

      +
    • +
    • +

      +The drag_pointer function of src/floating.c is called to grab the pointer + and enter its own event loop which will pass all events (expose events) but + motion notify events. This function then calls the specified callback + (resize_callback) which does some boundary checking and moves the helper + window. As soon as the mouse button is released, this loop will be + terminated. +

      +
    • +
    • +

      +The new width_factor for each involved column (respectively row) will be + calculated. +

      +
    • +
    +
    +
    +
    +
    +

    15. User commands / commandmode (src/commands.c)

    +
    +

    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 <command> +
    +
    +

    +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.

    +
    +
    +
    +

    16. Gotchas

    +
    +
      +
    • +

      +Forgetting to call xcb_flush(conn); after sending a request. This usually + leads to code which looks like it works fine but which does not work under + certain conditions. +

      +
    • +
    +
    +
    +
    +

    17. Using git / sending patches

    +
    +

    For a short introduction into using git, see +http://www.spheredev.org/wiki/Git_for_the_lazy or, for more documentation, see +http://git-scm.com/documentation

    +

    When you want to send a patch because you fixed a bug or implemented a cool +feature (please talk to us before working on features to see whether they are +maybe already implemented, not possible for some some reason, or don’t fit +into the concept), please use git to create a patchfile.

    +

    First of all, update your working copy to the latest version of the master +branch:

    +
    +
    +
    git pull
    +
    +

    Afterwards, make the necessary changes for your bugfix/feature. Then, review +the changes using git diff (you might want to enable colors in the diff using +git config diff.color auto). When you are definitely done, use git commit +-a to commit all changes you’ve made.

    +

    Then, use the following command to generate a patchfile which we can directly +apply to the branch, preserving your commit message and name:

    +
    +
    +
    git format-patch origin
    +
    +

    Just send us the generated file via email.

    +
    +
    +
    +

    + + + diff --git a/docs/ipc.html b/docs/ipc.html new file mode 100644 index 0000000..d9b8b54 --- /dev/null +++ b/docs/ipc.html @@ -0,0 +1,530 @@ + + + + + +i3: IPC interface (interprocess communication) + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    This document describes how to interface with i3 from a separate process. This +is useful for example to remote-control i3 (to write test cases for example) or +to get various information like the current workspaces to implement an external +workspace bar.

    +

    The method of choice for IPC in our case is a unix socket because it has very +little overhead on both sides and is usually available without headaches in +most languages. In the default configuration file, no ipc-socket path is +specified and thus no socket is created. The standard path (which i3-msg and +i3-input use) is ~/.i3/ipc.sock.

    +
    +
    +
    +

    1. Establishing a connection

    +
    +

    To establish a connection, simply open the IPC socket. The following code +snippet illustrates this in Perl:

    +
    +
    +
    use IO::Socket::UNIX;
    +my $sock = IO::Socket::UNIX->new(Peer => '~/.i3/ipc.sock');
    +
    +
    +
    +
    +

    2. Sending messages to i3

    +
    +

    To send a message to i3, you have to format in the binary message format which +i3 expects. This format specifies a magic string in the beginning to ensure +the integrity of messages (to prevent follow-up errors). Following the magic +string comes the length of the payload of the message as 32-bit integer, and +the type of the message as 32-bit integer (the integers are not converted, so +they are in native byte order).

    +

    The magic string currently is "i3-ipc" and will only be changed when a change +in the IPC API is done which breaks compatibility (we hope that we don’t need +to do that).

    +

    Currently implemented message types are the following:

    +
    +
    +COMMAND (0) +
    +
    +

    + The payload of the message is a command for i3 (like the commands you + can bind to keys in the configuration file) and will be executed + directly after receiving it. There is no reply to this message. +

    +
    +
    +GET_WORKSPACES (1) +
    +
    +

    + Gets the current workspaces. The reply will be a JSON-encoded list of + workspaces (see the reply section). +

    +
    +
    +SUBSCRIBE (2) +
    +
    +

    + Subscribes your connection to certain events. See [events] for a + description of this message and the concept of events. +

    +
    +
    +GET_OUTPUTS (3) +
    +
    +

    + Gets the current outputs. The reply will be a JSON-encoded list of outputs + (see the reply section). +

    +
    +
    +

    So, a typical message could look like this:

    +
    +
    +
    "i3-ipc" <message length> <message type> <payload>
    +
    +

    Or, as a hexdump:

    +
    +
    +
    00000000  69 33 2d 69 70 63 04 00  00 00 00 00 00 00 65 78  |i3-ipc........ex|
    +00000010  69 74 0a                                          |it.|
    +
    +

    To generate and send such a message, you could use the following code in Perl:

    +
    +
    +
    sub format_ipc_command {
    +    my ($msg) = @_;
    +    my $len;
    +    # Get the real byte count (vs. amount of characters)
    +    { use bytes; $len = length($msg); }
    +    return "i3-ipc" . pack("LL", $len, 0) . $msg;
    +}
    +
    +$sock->write(format_ipc_command("exit"));
    +
    +
    +
    +
    +

    3. Receiving replies from i3

    +
    +

    Replies from i3 usually consist of a simple string (the length of the string +is the message_length, so you can consider them length-prefixed) which in turn +contain the JSON serialization of a data structure. For example, the +GET_WORKSPACES message returns an array of workspaces (each workspace is a map +with certain attributes).

    +
    +

    3.1. Reply format

    +

    The reply format is identical to the normal message format. There also is +the magic string, then the message length, then the message type and the +payload.

    +

    The following reply types are implemented:

    +
    +
    +COMMAND (0) +
    +
    +

    + Confirmation/Error code for the COMMAND message. +

    +
    +
    +GET_WORKSPACES (1) +
    +
    +

    + Reply to the GET_WORKSPACES message. +

    +
    +
    +SUBSCRIBE (2) +
    +
    +

    + Confirmation/Error code for the SUBSCRIBE message. +

    +
    +
    +GET_OUTPUTS (3) +
    +
    +

    + Reply to the GET_OUTPUTS message. +

    +
    +
    +
    +
    +

    3.2. COMMAND reply

    +

    The reply consists of a single serialized map. At the moment, the only +property is success (bool), but this will be expanded in future versions.

    +

    Example:

    +
    +
    +
    { "success": true }
    +
    +
    +
    +

    3.3. GET_WORKSPACES reply

    +

    The reply consists of a serialized list of workspaces. Each workspace has the +following properties:

    +
    +
    +num (integer) +
    +
    +

    + The logical number of the workspace. Corresponds to the command + to switch to this workspace. +

    +
    +
    +name (string) +
    +
    +

    + The name of this workspace (by default num+1), as changed by the + user. Encoded in UTF-8. +

    +
    +
    +visible (boolean) +
    +
    +

    + Whether this workspace is currently visible on an output (multiple + workspaces can be visible at the same time). +

    +
    +
    +focused (boolean) +
    +
    +

    + Whether this workspace currently has the focus (only one workspace + can have the focus at the same time). +

    +
    +
    +urgent (boolean) +
    +
    +

    + Whether a window on this workspace has the "urgent" flag set. +

    +
    +
    +rect (map) +
    +
    +

    + The rectangle of this workspace (equals the rect of the output it + is on), consists of x, y, width, height. +

    +
    +
    +output (string) +
    +
    +

    + The video output this workspace is on (LVDS1, VGA1, …). +

    +
    +
    +

    Example:

    +
    +
    +
    [
    + {
    +  "num": 0,
    +  "name": "1",
    +  "visible": true,
    +  "focused": true,
    +  "urgent": false,
    +  "rect": {
    +   "x": 0,
    +   "y": 0,
    +   "width": 1280,
    +   "height": 800
    +  },
    +  "output": "LVDS1"
    + },
    + {
    +  "num": 1,
    +  "name": "2",
    +  "visible": false,
    +  "focused": false,
    +  "urgent": false,
    +  "rect": {
    +   "x": 0,
    +   "y": 0,
    +   "width": 1280,
    +   "height": 800
    +  },
    +  "output": "LVDS1"
    + }
    +]
    +
    +
    +
    +

    3.4. SUBSCRIBE reply

    +

    The reply consists of a single serialized map. The only property is +success (bool), indicating whether the subscription was successful (the +default) or whether a JSON parse error occurred.

    +

    Example:

    +
    +
    +
    { "success": true }
    +
    +
    +
    +

    3.5. GET_OUTPUTS reply

    +

    The reply consists of a serialized list of outputs. Each output has the +following properties:

    +
    +
    +name (string) +
    +
    +

    + The name of this output (as seen in xrandr(1)). Encoded in UTF-8. +

    +
    +
    +active (boolean) +
    +
    +

    + Whether this output is currently active (has a valid mode). +

    +
    +
    +current_workspace (integer) +
    +
    +

    + The current workspace which is visible on this output. null if the + output is not active. +

    +
    +
    +rect (map) +
    +
    +

    + The rectangle of this output (equals the rect of the output it + is on), consists of x, y, width, height. +

    +
    +
    +

    Example:

    +
    +
    +
    [
    + {
    +  "name": "LVDS1",
    +  "active": true,
    +  "current_workspace": 4,
    +  "rect": {
    +   "x": 0,
    +   "y": 0,
    +   "width": 1280,
    +   "height": 800
    +  }
    + },
    + {
    +  "name": "VGA1",
    +  "active": true,
    +  "current_workspace": 1,
    +  "rect": {
    +   "x": 1280,
    +   "y": 0,
    +   "width": 1280,
    +   "height": 1024
    +  },
    + }
    +]
    +
    +
    +
    +
    +
    +

    4. Events

    +
    +

    To get informed when certain things happen in i3, clients can subscribe to +events. Events consist of a name (like "workspace") and an event reply type +(like I3_IPC_EVENT_WORKSPACE). The events sent by i3 are in the same format +as replies to specific commands. However, the highest bit of the message type +is set to 1 to indicate that this is an event reply instead of a normal reply.

    +

    Caveat: As soon as you subscribe to an event, it is not guaranteed any longer +that the requests to i3 are processed in order. This means, the following +situation can happen: You send a GET_WORKSPACES request but you receive a +"workspace" event before receiving the reply to GET_WORKSPACES. If your +program does not want to cope which such kinds of race conditions (an +event based library may not have a problem here), I suggest you create a +separate connection to receive events.

    +
    +

    4.1. Subscribing to events

    +

    By sending a message of type SUBSCRIBE with a JSON-encoded array as payload +you can register to an event.

    +

    Example:

    +
    +
    +
    type: SUBSCRIBE
    +payload: [ "workspace", "focus" ]
    +
    +
    +
    +

    4.2. Available events

    +

    The numbers in parenthesis is the event type (keep in mind that you need to +strip the highest bit first).

    +
    +
    +workspace (0) +
    +
    +

    + Sent when the user switches to a different workspace, when a new + workspace is initialized or when a workspace is removed (because the + last client vanished). +

    +
    +
    +output (1) +
    +
    +

    + Sent when RandR issues a change notification (of either screens, + outputs, CRTCs or output properties). +

    +
    +
    +

    Example:

    +
    +
    +
    # the appropriate 4 bytes read from the socket are stored in $input
    +
    +# unpack a 32-bit unsigned integer
    +my $message_type = unpack("L", $input);
    +
    +# check if the highest bit is 1
    +my $is_event = (($message_type >> 31) == 1);
    +
    +# use the other bits
    +my $event_type = ($message_type & 0x7F);
    +
    +if ($is_event) {
    +  say "Received event of type $event_type";
    +}
    +
    +
    +
    +

    4.3. workspace event

    +

    This event consists of a single serialized map containing a property +change (string) which indicates the type of the change ("focus", "init", +"empty", "urgent").

    +

    Example:

    +
    +
    +
    { "change": "focus" }
    +
    +
    +
    +

    4.4. output event

    +

    This event consists of a single serialized map containing a property +change (string) which indicates the type of the change (currently only +"unspecified").

    +

    Example:

    +
    +
    +
    { "change": "unspecified" }
    +
    +
    +
    +
    +
    +

    5. See also

    +
    +

    For some languages, libraries are available (so you don’t have to implement +all this on your own). This list names some (if you wrote one, please let me +know):

    +
    +
    +C +
    +
    +

    + i3 includes a headerfile i3/ipc.h which provides you all constants. + However, there is no library yet. +

    +
    +
    +Ruby +
    +
    +

    + http://github.com/badboy/i3-ipc +

    +
    +
    +Perl +
    +
    +

    + http://search.cpan.org/search?query=AnyEvent::I3 +

    +
    +
    +Python +
    +
    +

    + http://github.com/thepub/i3ipc +

    +
    +
    +
    +
    +
    +

    + + + diff --git a/docs/keyboard-layer1.png b/docs/keyboard-layer1.png new file mode 100644 index 0000000..88268f7 Binary files /dev/null and b/docs/keyboard-layer1.png differ diff --git a/docs/keyboard-layer2.png b/docs/keyboard-layer2.png new file mode 100644 index 0000000..85a7d21 Binary files /dev/null and b/docs/keyboard-layer2.png differ diff --git a/docs/modes.png b/docs/modes.png new file mode 100644 index 0000000..656a6db Binary files /dev/null and b/docs/modes.png differ diff --git a/docs/multi-monitor.html b/docs/multi-monitor.html new file mode 100644 index 0000000..671d2be --- /dev/null +++ b/docs/multi-monitor.html @@ -0,0 +1,109 @@ + + + + + +i3: The multi-monitor situation + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    …or: oh no, I have an nVidia graphics card!

    +
    +
    +
    +

    1. The quick fix

    +
    +

    If you are using the nVidia binary graphics driver (also known as blob) +you need to use the --force-xinerama flag (in your .xsession) when starting +i3, like so:

    +
    +
    Example:
    +
    +
    exec i3 --force-xinerama -V >>~/.i3/i3log 2>&1
    +
    +
    +
    +
    +

    2. The explanation

    +
    +

    Starting with version 3.ε, i3 uses the RandR (Rotate and Resize) API instead +of Xinerama. The reason for this, is that RandR provides more information +about your outputs and connected screens than Xinerama does. To be specific, +the code which handled on-the-fly screen reconfiguration (meaning without +restarting the X server) was a very messy heuristic and most of the time did +not work correctly — that is just not possible with the little information +Xinerama offers (just a list of screen resolutions, no identifiers for the +screens or any additional information). Xinerama simply was not designed +for dynamic configuration.

    +

    So RandR came along, as a more powerful alternative (RandR 1.2 to be specific). +It offers all of Xinerama’s possibilities and lots more. Using the RandR API +made our code much more robust and clean. Also, you can now reliably assign +workspaces to output names instead of some rather unreliable screen identifier +(position inside the list of screens, which could change, and so on…).

    +

    As RandR has been around for about three years as of this writing, it seemed +like a very good idea to us, and it still is a very good one. What we did not +expect, however, was the nVidia binary driver. It still does not support RandR +(as of March 2010), even though nVidia has announced that it will support RandR +eventually. What does this mean for you, if you are stuck with the binary +driver for some reason (say the free drivers don’t work with your card)? First +of all, you are stuck with TwinView and cannot use xrandr. While this ruins +the user experience, the more grave problem is that the nVidia driver not only +does not support dynamic configuration using RandR, it also does not expose +correct multi-monitor information via the RandR API. So, in some setups, i3 +will not find any screens; in others, it will find one large screen which +actually contains both of your physical screens (but it will not know that +these are two screens).

    +

    For this very reason, we decided to implement the following workaround: As +long as the nVidia driver does not support RandR, an option called +--force-xinerama is available in i3. This option gets the list of screens +once when starting, and never updates it. As the nVidia driver cannot do +dynamic configuration anyways, this is not a big deal.

    +
    +
    +
    +

    3. See also

    +
    +

    For more information on how to use multi-monitor setups, see the i3 User’s +Guide.

    +
    +
    +
    +

    + + + diff --git a/docs/refcard.pdf b/docs/refcard.pdf new file mode 100644 index 0000000..f1bb36f Binary files /dev/null and b/docs/refcard.pdf differ diff --git a/docs/single_terminal.png b/docs/single_terminal.png new file mode 100644 index 0000000..4fe918c Binary files /dev/null and b/docs/single_terminal.png differ diff --git a/docs/snapping.png b/docs/snapping.png new file mode 100644 index 0000000..65fe6e4 Binary files /dev/null and b/docs/snapping.png differ diff --git a/docs/stacklimit.png b/docs/stacklimit.png new file mode 100644 index 0000000..ab5bed7 Binary files /dev/null and b/docs/stacklimit.png differ diff --git a/docs/tree-layout1.png b/docs/tree-layout1.png new file mode 100644 index 0000000..ee69f1a Binary files /dev/null and b/docs/tree-layout1.png differ diff --git a/docs/tree-layout2.png b/docs/tree-layout2.png new file mode 100644 index 0000000..5cbadde Binary files /dev/null and b/docs/tree-layout2.png differ diff --git a/docs/tree-migrating.html b/docs/tree-migrating.html new file mode 100644 index 0000000..5ba6188 --- /dev/null +++ b/docs/tree-migrating.html @@ -0,0 +1,270 @@ + + + + + +i3: Tree branch: Migrating + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +

    1. Introduction

    +
    +

    The tree branch (referring to a branch of i3 in the git repository) is the new +version of i3. Due to the very deep changes and heavy refactoring of the source +source, we decided to develop it in a seperate branch (instead of using the +next/master-branch system like before).

    +
    +
    +
    +

    2. Current status

    +
    +

    Currently, the code is mostly working. Some of the i3 core developers have been +using the tree branch version for a few weeks now. So, if you are eager to try +out the new features and help us find bugs, give it a try!

    +

    At the same time, a word of warning is appropriate: This version of i3 might +crash unexpectedly, so please be careful with important data (do not work for +two days without saving…).

    +
    +
    +
    +

    3. Getting the latest tree branch version

    +
    +

    Check out the latest version:

    +
    +
    +
    $ git clone -b tree git://code.stapelberg.de/i3
    +
    +

    Then build and install it (has the same dependencies as the latest stable i3 +version):

    +
    +
    +
    $ cd i3
    +$ make
    +$ sudo cp i3 /usr/bin/i3-tree
    +
    +

    …and execute i3-tree instead of i3 in your Xsession.

    +

    IMPORTANT: Please note that configuration file compatibility is not yet done. +So, make sure you use/customize the provided i3.config file.

    +
    +
    +
    +

    4. Tree

    +
    +

    The most important change and reason for the name is that i3 stores all +information about the X11 outputs, workspaces and layout of the windows on them +in a tree. The root node is the X11 root window, followed by the X11 outputs, +then workspaces and finally the windows themselve. In previous versions of i3 +we had multiple lists (of outputs, workspaces) and a table for each workspace. +That approach turned out to be complicated to use (snapping), understand and +implement.

    +
    +

    4.1. The tree consists of Containers

    +

    The building blocks of our tree are so called Containers. A Container can +host a window (meaning an X11 window, one that you can actually see and use, +like a browser). Alternatively, it could contain one or more Containers. A +simple example is the workspace: When you start i3 with a single monitor, a +single workspace and you open two terminal windows, you will end up with a tree +like this:

    +
    +
    +layout2 +
    +
    +
    +
    +shot4 +
    +
    Figure 1. Two terminals on standard workspace
    +
    +
    +
    +

    4.2. Orientation and Split Containers

    +

    It is only natural to use so-called Split Containers in order to build a +layout when using a tree as data structure. In i3, every Container has an +orientation (horizontal, vertical or unspecified). So, in our example with the +workspace, the default orientation of the workspace Container is horizontal +(most monitors are widescreen nowadays). If you change the orientation to +vertical (Alt+v in the default config) and then open two terminals, i3 will +configure your windows like this:

    +
    +
    +shot2 +
    +
    Figure 2. Vertical Workspace Orientation
    +
    +

    An interesting new feature of the tree branch is the ability to split anything: +Let’s assume you have two terminals on a workspace (with horizontal +orientation), focus is on the right terminal. Now you want to open another +terminal window below the current one. If you would just open a new terminal +window, it would show up to the right due to the horizontal workspace +orientation. Instead, press Alt+v to create a Vertical Split Container (to +open a Horizontal Split Container, use Alt+h). Now you can open a new +terminal and it will open below the current one:

    +
    +
    +Layout +
    +
    +
    +
    +shot +
    +
    Figure 3. Vertical Split Container
    +
    +
    +

    You probably guessed it already: There is no limit on how deep your hierarchy +of splits can be.

    +
    +
    +

    4.3. Level up

    +

    Let’s stay with our example from above. We have a terminal on the left and two +vertically split terminals on the right, focus is on the bottom right one. When +you open a new terminal, it will open below the current one.

    +

    So, how can you open a new terminal window to the right of the current one? +The solution is to use level up, which will focus the Parent Container of +the current Container. In this case, you would focus the Vertical Split +Container which is inside the horizontally oriented workspace. Thus, now new +windows will be opened to the right of the Vertical Split Container:

    +
    +
    +shot3 +
    +
    Figure 4. Level Up, then open new terminal
    +
    +
    +
    +
    +
    +

    5. Commands

    +
    +

    The authoritive reference for commands is src/cmdparse.y. You can also find +most commands in i3.config. Here comes a short overview over the important +commands:

    +
    +

    5.1. Manipulating layout

    +
    +
    +
    layout <default|stacked|tabbed>
    +
    +
    +
    +

    5.2. Changing Focus

    +
    +
    +
    next <horizontal|vertical>
    +prev <horizontal|vertical>
    +
    +
    +
    Examples:
    +
    +
    bindsym Mod1+Left prev h
    +bindsym Mod1+Right next h
    +bindsym Mod1+Down next v
    +bindsym Mod1+Up prev v
    +
    +
    +
    +

    5.3. Moving

    +
    +
    +
    move <before|after> <horizontal|vertical>
    +
    +
    +
    Examples:
    +
    +
    bindsym Mod1+Shift+Left move before h
    +bindsym Mod1+Shift+Right move after h
    +bindsym Mod1+Shift+Down move before v
    +bindsym Mod1+Shift+Up move after v
    +
    +
    +
    +

    5.4. Changing workspace

    +
    +
    +
    workspace <name>
    +
    +
    +
    Examples:
    +
    +
    bindsym Mod1+1 workspace 1
    +bindsym Mod1+2 workspace 2
    +…
    +
    +
    +
    +

    5.5. Moving Containers to workspaces

    +
    +
    +
    move workspace <name>
    +
    +
    +
    +
    bindsym Mod1+Shift+1 move workspace 1
    +bindsym Mod1+Shift+2 move workspace 2
    +…
    +
    +
    +
    +

    5.6. Changing border style

    +
    +
    +
    border <normal|none|1pixel>
    +
    +
    +
    +

    5.7. Changing container mode

    +
    +
    +
    mode <tiling|floating|toggle>
    +
    +
    +
    +
    +
    +

    6. The rest

    +
    +

    What is not mentioned here explicitly is either unchanged and can be read in +the i3 User’s Guide or it is not yet +implemented.

    +
    +
    +
    +

    + + + diff --git a/docs/tree-shot1.png b/docs/tree-shot1.png new file mode 100644 index 0000000..3bbeae1 Binary files /dev/null and b/docs/tree-shot1.png differ diff --git a/docs/tree-shot2.png b/docs/tree-shot2.png new file mode 100644 index 0000000..f003264 Binary files /dev/null and b/docs/tree-shot2.png differ diff --git a/docs/tree-shot3.png b/docs/tree-shot3.png new file mode 100644 index 0000000..fe4c11e Binary files /dev/null and b/docs/tree-shot3.png differ diff --git a/docs/tree-shot4.png b/docs/tree-shot4.png new file mode 100644 index 0000000..61e8c91 Binary files /dev/null and b/docs/tree-shot4.png differ diff --git a/docs/two_columns.png b/docs/two_columns.png new file mode 100644 index 0000000..6dc8c40 Binary files /dev/null and b/docs/two_columns.png differ diff --git a/docs/two_terminals.png b/docs/two_terminals.png new file mode 100644 index 0000000..20b45ac Binary files /dev/null and b/docs/two_terminals.png differ diff --git a/docs/userguide.html b/docs/userguide.html new file mode 100644 index 0000000..5e8f025 --- /dev/null +++ b/docs/userguide.html @@ -0,0 +1,1129 @@ + + + + + +i3: i3 User’s Guide + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    This document contains all the information you need to configure and use the i3 +window manager. If it does not, please contact me on IRC, Jabber or E-Mail and +I’ll help you out.

    +
    +
    +
    +

    1. Default keybindings

    +
    +

    For the "too long; didn’t read" people, here is an overview of the default +keybindings (click to see the full size image):

    +

    Keys to use with Mod1 (alt):

    +

    + +Keys to use with Mod1 (alt) + +

    +

    Keys to use with Shift+Mod1:

    +

    + +Keys to use with Shift+Mod1 + +

    +

    As i3 uses keycodes in the default configuration, it does not matter which +keyboard layout you actually use. The key positions are what matters (of course +you can also use keysymbols, see [keybindings]).

    +

    The red keys are the modifiers you need to press (by default), the blue keys +are your homerow.

    +
    +
    +
    +

    2. Using i3

    +
    +
    +

    2.1. Opening terminals and moving around

    +

    One very basic operation is opening a new terminal. By default, the keybinding +for this is Mod1+Enter, that is Alt+Enter in the default configuration. By +pressing Mod1+Enter, a new terminal will be opened. It will fill the whole +space available on your screen.

    +

    +Single terminal +

    +

    It is important to keep in mind that i3 uses a table to manage your windows. At +the moment, you have exactly one column and one row which leaves you with one +cell. In this cell there is a container, which is where your new terminal is +opened.

    +

    If you now open another terminal, you still have only one cell. However, the +container in that cell holds both of your terminals. So, a container is just a +group of clients with a specific layout. Containers can be resized by adjusting +the size of the cell that holds them.

    +

    +Two terminals +

    +

    To move the focus between the two terminals, you use the direction keys which +you may know from the editor vi. However, in i3, your homerow is used for +these keys (in vi, the keys are shifted to the left by one for compatibility +with most keyboard layouts). Therefore, Mod1+J is left, Mod1+K is down, +Mod1+L is up and Mod1+; is right. So, to switch between the terminals, +use Mod1+K or Mod1+L.

    +

    To create a new row/column (and a new cell), you can simply move a terminal (or +any other window) in the direction you want to expand your table. So, let’s +expand the table to the right by pressing Mod1+Shift+;.

    +

    +Two columns +

    +
    +
    +

    2.2. Changing container modes

    +

    A container can have the following modes:

    +
    +
    +default +
    +
    +

    +Windows are sized so that every window gets an equal amount of space in the +container. +

    +
    +
    +stacking +
    +
    +

    +Only the focused window in the container is displayed. You get a list of +windows at the top of the container. +

    +
    +
    +tabbed +
    +
    +

    +The same principle as stacking, but the list of windows at the top is only +a single line which is vertically split. +

    +
    +
    +

    To switch modes, press Mod1+e for default, Mod1+h for stacking and +Mod1+w for tabbed.

    +

    +Container modes +

    +
    +
    +

    2.3. Toggling fullscreen mode for a window

    +

    To display a window fullscreen or to go out of fullscreen mode again, press +Mod1+f.

    +

    There is also a global fullscreen mode in i3 in which the client will use all +available outputs. To use it, or to get out of it again, press Mod1+Shift+f.

    +
    +
    +

    2.4. Opening other applications

    +

    Aside from opening applications from a terminal, you can also use the handy +dmenu which is opened by pressing Mod1+v by default. Just type the name +(or a part of it) of the application which you want to open. The application +typed has to be in your $PATH for this to work.

    +

    Additionally, if you have applications you open very frequently, you can +create a keybinding for starting the application directly. See the section +"Configuring i3" for details.

    +
    +
    +

    2.5. Closing windows

    +

    If an application does not provide a mechanism for closing (most applications +provide a menu, the escape key or a shortcut like Control+W to close), you +can press Mod1+Shift+q to kill a window. For applications which support +the WM_DELETE protocol, this will correctly close the application (saving +any modifications or doing other cleanup). If the application doesn’t support +the WM_DELETE protocol your X server will kill the window and the behaviour +depends on the application.

    +
    +
    +

    2.6. Using workspaces

    +

    Workspaces are an easy way to group a set of windows. By default, you are on +the first workspace, as the bar on the bottom left indicates. To switch to +another workspace, press Mod1+num where num is the number of the workspace +you want to use. If the workspace does not exist yet, it will be created.

    +

    A common paradigm is to put the web browser on one workspace, communication +applications (mutt, irssi, …) on another one, and the ones with which you +work, on the third one. Of course, there is no need to follow this approach.

    +

    If you have multiple screens, a workspace will be created on each screen at +startup. If you open a new workspace, it will be bound to the screen you +created it on. When you switch to a workspace on another screen, i3 will set +focus to that screen.

    +
    +
    +

    2.7. Moving windows to workspaces

    +

    To move a window to another workspace, simply press Mod1+Shift+num where +num is (like when switching workspaces) the number of the target workspace. +Similarly to switching workspaces, the target workspace will be created if +it does not yet exist.

    +
    +
    +

    2.8. Resizing columns/rows

    +

    To resize columns or rows, just grab the border between the two columns/rows +and move it to the wanted size. Please keep in mind that each cell of the table +holds a container and thus you cannot horizontally resize single windows. If +you need applications with different horizontal sizes, place them in seperate +cells one above the other.

    +

    See [resizingconfig] for how to configure i3 to be able to resize +columns/rows with your keyboard.

    +
    +
    +

    2.9. Restarting i3 inplace

    +

    To restart i3 inplace (and thus get into a clean state if there is a bug, or +to upgrade to a newer version of i3) you can use Mod1+Shift+r. Be aware, +though, that this kills your current layout and all the windows you have opened +will be put in a default container in only one cell. Saving layouts will be +implemented in a later version.

    +
    +
    +

    2.10. Exiting i3

    +

    To cleanly exit i3 without killing your X server, you can use Mod1+Shift+e.

    +
    +
    +

    2.11. Snapping

    +

    Snapping is a mechanism to increase/decrease the colspan/rowspan of a container. +Colspan/rowspan is the number of columns/rows a specific cell of the table +consumes. This is easier explained by giving an example, so take the following +layout:

    +

    +Snapping example +

    +

    To use the full size of your screen, you can now snap container 3 downwards +by pressing Mod1+Control+k (or snap container 2 rightwards).

    +
    +
    +

    2.12. Floating

    +

    Floating mode is the opposite of tiling mode. The position and size of a window +are not managed by i3, but by you. Using this mode violates the tiling +paradigm but can be useful for some corner cases like "Save as" dialog +windows, or toolbar windows (GIMP or similar).

    +

    You can enable floating mode for a window by pressing Mod1+Shift+Space. By +dragging the window’s titlebar with your mouse you can move the window +around. By grabbing the borders and moving them you can resize the window. You +can also do that by using the [floating_modifier].

    +

    For resizing floating windows with your keyboard, see [resizingconfig].

    +

    Floating windows are always on top of tiling windows.

    +
    +
    +
    +
    +

    3. Configuring i3

    +
    +

    This is where the real fun begins ;-). Most things are very dependant on your +ideal working environment so we can’t make reasonable defaults for them.

    +

    While not using a programming language for the configuration, i3 stays +quite flexible in regards to the things you usually want your window manager +to do.

    +

    For example, you can configure bindings to jump to specific windows, +you can set specific applications to start on specific workspaces, you can +automatically start applications, you can change the colors of i3, and you +can bind your keys to do useful things.

    +

    To change the configuration of i3, copy /etc/i3/config to ~/.i3/config +(or ~/.config/i3/config if you like the XDG directory scheme) and edit it +with a text editor.

    +
    +

    3.1. Comments

    +

    It is possible and recommended to use comments in your configuration file to +properly document your setup for later reference. Comments are started with +a # and can only be used at the beginning of a line:

    +

    Examples:

    +
    +
    +
    # This is a comment
    +
    +
    +
    +

    3.2. Fonts

    +

    i3 uses X core fonts (not Xft) for rendering window titles and the internal +workspace bar. You can use xfontsel(1) to generate such a font description. +To see special characters (Unicode), you need to use a font which supports +the ISO-10646 encoding.

    +

    Syntax:

    +
    +
    +
    font <X core font description>
    +
    +

    Examples:

    +
    +
    +
    font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
    +
    +
    +
    +

    3.3. Keyboard bindings

    +

    A keyboard binding makes i3 execute a command (see below) upon pressing a +specific key. i3 allows you to bind either on keycodes or on keysyms (you can +also mix your bindings, though i3 will not protect you from overlapping ones).

    +
      +
    • +

      +A keysym (key symbol) is a description for a specific symbol, like "a" + or "b", but also more strange ones like "underscore" instead of "_". These + are the ones you use in Xmodmap to remap your keys. To get the current + mapping of your keys, use xmodmap -pke. +

      +
    • +
    • +

      +Keycodes do not need to have a symbol assigned (handy for some hotkeys + on some notebooks) and they will not change their meaning as you switch to a + different keyboard layout (when using xmodmap). +

      +
    • +
    +

    My recommendation is: If you often switch keyboard layouts but you want to keep +your bindings in the same physical location on the keyboard, use keycodes. +If you don’t switch layouts, and want a clean and simple config file, use +keysyms.

    +

    Syntax:

    +
    +
    +
    bindsym [Modifiers+]keysym command
    +bind [Modifiers+]keycode command
    +
    +

    Examples:

    +
    +
    +
    # Fullscreen
    +bindsym Mod1+f f
    +
    +# Restart
    +bindsym Mod1+Shift+r restart
    +
    +# Notebook-specific hotkeys
    +bind 214 exec /home/michael/toggle_beamer.sh
    +
    +

    Available Modifiers:

    +
    +
    +Mod1-Mod5, Shift, Control +
    +
    +

    +Standard modifiers, see xmodmap(1) +

    +
    +
    +Mode_switch +
    +
    +

    +Unlike other window managers, i3 can use Mode_switch as a modifier. This allows +you to remap capslock (for example) to Mode_switch and use it for both: typing +umlauts or special characters and having some comfortably reachable key +bindings. For example, when typing, capslock+1 or capslock+2 for switching +workspaces is totally convenient. Try it :-). +

    +
    +
    +
    +
    +

    3.4. The floating modifier

    +

    To move floating windows with your mouse, you can either grab their titlebar +or configure the so called floating modifier which you can then press and +click anywhere in the window itself to move it. The most common setup is to +use the same key you use for managing windows (Mod1 for example). Then +you can press Mod1, click into a window using your left mouse button, and drag +it to the position you want.

    +

    When holding the floating modifier, you can resize a floating window by +pressing the right mouse button on it and moving around while holding it. If +you hold the shift button as well, the resize will be proportional.

    +

    Syntax:

    +
    +
    +
    floating_modifier <Modifiers>
    +
    +

    Examples:

    +
    +
    +
    floating_modifier Mod1
    +
    +
    +
    +

    3.5. Layout mode for new containers

    +

    This option determines in which mode new containers will start. See also +[stack-limit].

    +

    Syntax:

    +
    +
    +
    new_container <default|stacking|tabbed>
    +new_container stack-limit <cols|rows> <value>
    +
    +

    Examples:

    +
    +
    +
    new_container tabbed
    +
    +
    +
    +

    3.6. Border style for new windows

    +

    This option determines which border style new windows will have.

    +

    Syntax:

    +
    +
    +
    new_window <bp|bn|bb>
    +
    +

    Examples:

    +
    +
    +
    new_window bp
    +
    +
    +
    +

    3.7. Variables

    +

    As you learned in the section about keyboard bindings, you will have +to configure lots of bindings containing modifier keys. If you want to save +yourself some typing and be able to change the modifier you use later, +variables can be handy.

    +

    Syntax:

    +
    +
    +
    set name value
    +
    +

    Examples:

    +
    +
    +
    set $m Mod1
    +bindsym $m+Shift+r restart
    +
    +

    Variables are directly replaced in the file when parsing. There is no fancy +handling and there are absolutely no plans to change this. If you need a more +dynamic configuration you should create a little script which generates a +configuration file and run it before starting i3 (for example in your +.xsession file).

    +
    +
    +

    3.8. Automatically putting clients on specific workspaces

    +

    It is recommended that you match on window classes wherever possible because +some applications first create their window, and then worry about setting the +correct title. Firefox with Vimperator comes to mind. The window starts up +being named Firefox, and only when Vimperator is loaded does the title change. +As i3 will get the title as soon as the application maps the window (mapping +means actually displaying it on the screen), you’d need to have to match on +Firefox in this case.

    +

    You can prefix or suffix workspaces with a ~ to specify that matching clients +should be put into floating mode. If you specify only a ~, the client will +not be put onto any workspace, but will be set floating on the current one.

    +

    Syntax:

    +
    +
    +
    assign ["]window class[/window title]["] [→] [~ | workspace]
    +
    +

    Examples:

    +
    +
    +
    assign urxvt 2
    +assign urxvt → 2
    +assign "urxvt" → 2
    +assign "urxvt/VIM" → 3
    +assign "gecko" → ~4
    +assign "xv/MPlayer" → ~
    +
    +

    Note that the arrow is not required, it just looks good :-). If you decide to +use it, it has to be a UTF-8 encoded arrow, not "→" or something like that.

    +
    +
    +

    3.9. Automatically starting applications on i3 startup

    +

    By using the exec keyword outside a keybinding, you can configure which +commands will be performed by i3 on initial startup (not when restarting i3 +in-place however). These commands will be run in order.

    +

    Syntax:

    +
    +
    +
    exec command
    +
    +

    Examples:

    +
    +
    +
    exec sudo i3status | dzen2 -dock
    +
    +
    +
    +

    3.10. Automatically putting workspaces on specific screens

    +

    If you assign clients to workspaces, it might be handy to put the +workspaces on specific screens. Also, the assignment of workspaces to screens +will determine which workspace i3 uses for a new screen when adding screens +or when starting (e.g., by default it will use 1 for the first screen, 2 for +the second screen and so on).

    +

    Syntax:

    +
    +
    +
    workspace <number> output <output>
    +
    +

    The output is the name of the RandR output you attach your screen to. On a +laptop, you might have VGA1 and LVDS1 as output names. You can see the +available outputs by running xrandr --current.

    +

    Examples:

    +
    +
    +
    workspace 1 output LVDS1
    +workspace 5 output VGA1
    +
    +
    +
    +

    3.11. Named workspaces

    +

    If you always have a certain arrangement of workspaces, you might want to give +them names (of course UTF-8 is supported):

    +

    Syntax:

    +
    +
    +
    workspace <number> <name>
    +workspace <number> output <output> name
    +
    +

    For more details about the output part of this command, see above.

    +

    Examples:

    +
    +
    +
    workspace 1 www
    +workspace 2 work
    +workspace 3 i ♥ workspaces
    +
    +
    +
    +

    3.12. Changing colors

    +

    You can change all colors which i3 uses to draw the window decorations and the +bottom bar.

    +

    Syntax:

    +
    +
    +
    colorclass border background text
    +
    +

    Where colorclass can be one of:

    +
    +
    +client.focused +
    +
    +

    + A client which currently has the focus. +

    +
    +
    +client.focused_inactive +
    +
    +

    + A client which is the focused one of its container, but it does not have + the focus at the moment. +

    +
    +
    +client.unfocused +
    +
    +

    + A client which is not the focused one of its container. +

    +
    +
    +client.urgent +
    +
    +

    + A client which has its urgency hint activated. +

    +
    +
    +bar.focused +
    +
    +

    + The current workspace in the bottom bar. +

    +
    +
    +bar.unfocused +
    +
    +

    + All other workspaces in the bottom bar. +

    +
    +
    +bar.urgent +
    +
    +

    + A workspace which has at least one client with an activated urgency hint. +

    +
    +
    +

    You can also specify the color to be used to paint the background of the client +windows. This color will be used to paint the window on top of which the client +will be rendered.

    +

    Syntax:

    +
    +
    +
    client.background color
    +
    +

    Only clients that do not cover the whole area of this window expose the color +used to paint it. If you use a color other than black for your terminals, you +most likely want to set the client background color to the same color as your +terminal program’s background color to avoid black gaps between the rendered +area of the termianal and the i3 border.

    +

    Colors are in HTML hex format (#rrggbb), see the following example:

    +

    Examples:

    +
    +
    +
    # class        border  backgr. text
    +client.focused #2F343A #900000 #FFFFFF
    +
    +

    Note that for the window decorations, the color around the child window is the +background color, and the border color is only the two thin lines at the top of +the window.

    +
    +
    +

    3.13. Interprocess communication

    +

    i3 uses unix sockets to provide an IPC interface. This allows third-party +programs to get information from i3, such as the current workspaces +(to display a workspace bar), and to control i3.

    +

    To enable it, you have to configure a path where the unix socket will be +stored. The default path is ~/.i3/ipc.sock.

    +

    Examples:

    +
    +
    +
    ipc-socket ~/.i3/ipc.sock
    +
    +

    You can then use the i3-msg application to perform any command listed in +the next section.

    +
    +
    +

    3.14. Disable focus follows mouse

    +

    If you have a setup where your mouse usually is in your way (like a touchpad +on your laptop which you do not want to disable completely), you might want +to disable focus follows mouse and control focus only by using your keyboard. +The mouse will still be useful inside the currently active window (for example +to click on links in your browser window).

    +

    Syntax:

    +
    +
    +
    focus_follows_mouse <yes|no>
    +
    +

    Examples:

    +
    +
    +
    focus_follows_mouse no
    +
    +
    +
    +

    3.15. Internal workspace bar

    +

    The internal workspace bar (the thing at the bottom of your screen) is very +simple — it does not provide a way to display custom text and it does not +offer advanced customization features. This is intended because we do not +want to duplicate functionality of tools like dzen2, xmobar and so on +(they render bars, we manage windows). Instead, there is an option which will +turn off the internal bar completely, so that you can use a separate program to +display it (see i3-wsbar, a sample implementation of such a program):

    +

    Syntax:

    +
    +
    +
    workspace_bar <yes|no>
    +
    +

    Examples:

    +
    +
    +
    workspace_bar no
    +
    +
    +
    +
    +
    +

    4. List of commands

    +
    +
    +

    4.1. Manipulating layout

    +

    To change the layout of the current container to stacking, use s, for default +use d and for tabbed, use T. To make the current client (!) fullscreen, +use f, to make it span all outputs, use fg, to make it floating (or +tiling again) use t:

    +

    Examples:

    +
    +
    +
    bindsym Mod1+s s
    +bindsym Mod1+l d
    +bindsym Mod1+w T
    +
    +# Toggle fullscreen
    +bindsym Mod1+f f
    +
    +# Toggle global fullscreen
    +bindsym Mod1+Shift+f fg
    +
    +# Toggle floating/tiling
    +bindsym Mod1+t t
    +
    +
    +
    +

    4.2. Focusing/Moving/Snapping clients/containers/screens

    +

    To change the focus, use one of the h, j, k and l commands, meaning +left, down, up, right (respectively). To focus a container, prefix it with +wc. To focus a screen, prefix it with ws.

    +

    The same principle applies for moving and snapping: just prefix the command +with m when moving and with s when snapping:

    +

    Examples:

    +
    +
    +
    # Focus clients on the left, bottom, top, right:
    +bindsym Mod1+j h
    +bindsym Mod1+k j
    +bindsym Mod1+j k
    +bindsym Mod1+semicolon l
    +
    +# Move client to the left, bottom, top, right:
    +bindsym Mod1+j mh
    +bindsym Mod1+k mj
    +bindsym Mod1+j mk
    +bindsym Mod1+semicolon ml
    +
    +# Snap client to the left, bottom, top, right:
    +bindsym Mod1+j sh
    +bindsym Mod1+k sj
    +bindsym Mod1+j sk
    +bindsym Mod1+semicolon sl
    +
    +# Focus container on the left, bottom, top, right:
    +bindsym Mod3+j wch
    +…
    +
    +
    +
    +

    4.3. Changing workspaces/moving clients to workspaces

    +

    To change to a specific workspace, the command is just the number of the +workspace, e.g. 1 or 3. To move the current client to a specific workspace, +prefix the number with an m.

    +

    You can also switch to the next and previous workspace with the commands nw +and pw, which is handy, for example, if you have workspace 1, 3, 4 and 9 and +you want to cycle through them with a single key combination.

    +

    Examples:

    +
    +
    +
    bindsym Mod1+1 1
    +bindsym Mod1+2 2
    +...
    +
    +bindsym Mod1+Shift+1 m1
    +bindsym Mod1+Shift+2 m2
    +...
    +
    +bindsym Mod1+o nw
    +bindsym Mod1+p pw
    +
    +
    +
    +

    4.4. Resizing columns/rows

    +

    If you want to resize columns/rows using your keyboard, you can use the +resize command, I recommend using it inside a so called mode:

    +
    +
    Example: Configuration file, defining a mode for resizing
    +
    +
    mode "resize" {
    +        # These bindings trigger as soon as you enter the resize mode
    +
    +        # They resize the border in the direction you pressed, e.g.
    +        # when pressing left, the window is resized so that it has
    +        # more space on its left
    +
    +        bindsym n resize left -10
    +        bindsym Shift+n resize left +10
    +
    +        bindsym r resize bottom +10
    +        bindsym Shift+r resize bottom -10
    +
    +        bindsym t resize top -10
    +        bindsym Shift+t resize top +10
    +
    +        bindsym d resize right +10
    +        bindsym Shift+d resize right -10
    +
    +        bind 36 mode default
    +}
    +
    +# Enter resize mode
    +bindsym Mod1+r mode resize
    +
    +
    +
    +

    4.5. Jumping to specific windows

    +

    Often when in a multi-monitor environment, you want to quickly jump to a +specific window. For example, while working on workspace 3 you may want to +jump to your mail client to email your boss that you’ve achieved some +important goal. Instead of figuring out how to navigate to your mailclient, +it would be more convenient to have a shortcut.

    +

    Syntax:

    +
    +
    +
    jump ["]window class[/window title]["]
    +jump workspace [ column row ]
    +
    +

    You can either use the same matching algorithm as in the assign command +(see above) or you can specify the position of the client if you always use +the same layout.

    +

    Examples:

    +
    +
    +
    # Get me to the next open VIM instance
    +bindsym Mod1+a jump "urxvt/VIM"
    +
    +
    +
    +

    4.6. VIM-like marks (mark/goto)

    +

    This feature is like the jump feature: It allows you to directly jump to a +specific window (this means switching to the appropriate workspace and setting +focus to the windows). However, you can directly mark a specific window with +an arbitrary label and use it afterwards. You do not need to ensure that your +windows have unique classes or titles, and you do not need to change your +configuration file.

    +

    As the command needs to include the label with which you want to mark the +window, you cannot simply bind it to a key. i3-input is a tool created +for this purpose: It lets you input a command and sends the command to i3. It +can also prefix this command and display a custom prompt for the input dialog.

    +

    Syntax:

    +
    +
    +
    mark <identifier>
    +goto <identifier>
    +
    +

    Examples:

    +
    +
    +
    # Read 1 character and mark the current window with this character
    +bindsym Mod1+m exec i3-input -p 'mark ' -l 1 -P 'Mark: '
    +
    +# Read 1 character and go to the window with the character
    +bindsym Mod1+g exec i3-input -p 'goto ' -l 1 -P 'Goto: '
    +
    +

    Alternatively, if you do not want to mess with i3-input, you could create +seperate bindings for a specific set of labels and then only use those labels.

    +
    +
    +

    4.7. Traveling the focus stack

    +

    This mechanism can be thought of as the opposite of the jump command. +It travels the focus stack and jumps to the window which had focus previously.

    +

    Syntax:

    +
    +
    +
    focus [number] | floating | tiling | ft
    +
    +

    Where number by default is 1 meaning that the next client in the focus stack +will be selected.

    +

    The special values have the following meaning:

    +
    +
    +floating +
    +
    +

    + The next floating window is selected. +

    +
    +
    +tiling +
    +
    +

    + The next tiling window is selected. +

    +
    +
    +ft +
    +
    +

    + If the current window is floating, the next tiling window will be + selected; and vice-versa. +

    +
    +
    +
    +
    +

    4.8. Changing border style

    +

    To change the border of the current client, you can use bn to use the normal +border (including window title), bp to use a 1-pixel border (no window title) +and bb to make the client borderless. There is also bt which will toggle +the different border styles.

    +

    Examples:

    +
    +
    +
    bindsym Mod1+t bn
    +bindsym Mod1+y bp
    +bindsym Mod1+u bb
    +
    +
    +
    +

    4.9. Changing the stack-limit of a container

    +

    If you have a single container with a lot of windows inside it (say, more than +10), the default layout of a stacking container can get a little unhandy. +Depending on your screen’s size, you might end up seeing only half of the +titlebars for each window in the container.

    +

    Using the stack-limit command, you can limit the number of rows or columns +in a stacking container. i3 will create columns or rows (depending on what +you limited) automatically as needed.

    +

    Syntax:

    +
    +
    +
    stack-limit <cols|rows> <value>
    +
    +

    Examples:

    +
    +
    +
    # I always want to have two window titles in one line
    +stack-limit cols 2
    +
    +# Not more than 5 rows in this stacking container
    +stack-limit rows 5
    +
    +

    +Container limited to two columns +

    +
    +
    +

    4.10. Reloading/Restarting/Exiting

    +

    You can make i3 reload its configuration file with reload. You can also +restart i3 inplace with the restart command to get it out of some weird state +(if that should ever happen) or to perform an upgrade without having to restart +your X session. However, your layout is not preserved at the moment, meaning +that all open windows will end up in a single container in default layout +after the restart. To exit i3 properly, you can use the exit command, +however you don’t need to (simply killing your X session is fine as well).

    +

    Examples:

    +
    +
    +
    bindsym Mod1+Shift+r restart
    +bindsym Mod1+Shift+w reload
    +bindsym Mod1+Shift+e exit
    +
    +
    +
    +
    +
    +

    5. Multiple monitors

    +
    +

    As you can see in the goal list on the website, i3 was specifically developed +with support for multiple monitors in mind. This section will explain how to +handle multiple monitors.

    +

    When you have only one monitor, things are simple. You usually start with +workspace 1 on your monitor and open new ones as you need them.

    +

    When you have more than one monitor, each monitor will get an initial +workspace. The first monitor gets 1, the second gets 2 and a possible third +would get 3. When you switch to a workspace on a different monitor, i3 will +switch to that monitor and then switch to the workspace. This way, you don’t +need shortcuts to switch to a specific monitor, and you don’t need to remember +where you put which workspace. New workspaces will be opened on the currently +active monitor. It is not possible to have a monitor without a workspace.

    +

    The idea of making workspaces global is based on the observation that most +users have a very limited set of workspaces on their additional monitors. +They are often used for a specific task (browser, shell) or for monitoring +several things (mail, IRC, syslog, …). Thus, using one workspace on one monitor +and "the rest" on the other monitors often makes sense. However, as you can +create an unlimited number of workspaces in i3 and tie them to specific +screens, you can have the "traditional" approach of having X workspaces per +screen by changing your configuration (using modes, for example).

    +
    +

    5.1. Configuring your monitors

    +

    To help you get going if you have never used multiple monitors before, here is +a short overview of the xrandr options which will probably be of interest to +you. It is always useful to get an overview of the current screen configuration. +Just run "xrandr" and you will get an output like the following:

    +
    +
    +
    $ xrandr
    +Screen 0: minimum 320 x 200, current 1280 x 800, maximum 8192 x 8192
    +VGA1 disconnected (normal left inverted right x axis y axis)
    +LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 261mm x 163mm
    +   1280x800       60.0*+   50.0
    +   1024x768       85.0     75.0     70.1     60.0
    +   832x624        74.6
    +   800x600        85.1     72.2     75.0     60.3     56.2
    +   640x480        85.0     72.8     75.0     59.9
    +   720x400        85.0
    +   640x400        85.1
    +   640x350        85.1
    +
    +

    Several things are important here: You can see that LVDS1 is connected (of +course, it is the internal flat panel) but VGA1 is not. If you have a monitor +connected to one of the ports but xrandr still says "disconnected", you should +check your cable, monitor or graphics driver.

    +

    The maximum resolution you can see at the end of the first line is the maximum +combined resolution of your monitors. By default, it is usually too low and has +to be increased by editing /etc/X11/xorg.conf.

    +

    So, say you connected VGA1 and want to use it as an additional screen:

    +
    +
    +
    xrandr --output VGA1 --auto --left-of LVDS1
    +
    +

    This command makes xrandr try to find the native resolution of the device +connected to VGA1 and configures it to the left of your internal flat panel. +When running "xrandr" again, the output looks like this:

    +
    +
    +
    $ xrandr
    +Screen 0: minimum 320 x 200, current 2560 x 1024, maximum 8192 x 8192
    +VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm
    +   1280x1024      60.0*+   75.0
    +   1280x960       60.0
    +   1152x864       75.0
    +   1024x768       75.1     70.1     60.0
    +   832x624        74.6
    +   800x600        72.2     75.0     60.3     56.2
    +   640x480        72.8     75.0     66.7     60.0
    +   720x400        70.1
    +LVDS1 connected 1280x800+1280+0 (normal left inverted right x axis y axis) 261mm x 163mm
    +   1280x800       60.0*+   50.0
    +   1024x768       85.0     75.0     70.1     60.0
    +   832x624        74.6
    +   800x600        85.1     72.2     75.0     60.3     56.2
    +   640x480        85.0     72.8     75.0     59.9
    +   720x400        85.0
    +   640x400        85.1
    +   640x350        85.1
    +
    +

    Please note that i3 uses exactly the same API as xrandr does, so it will see +only what you can see in xrandr.

    +

    See also [presentations] for more examples of multi-monitor setups.

    +
    +
    +

    5.2. Interesting configuration for multi-monitor environments

    +

    There are several things to configure in i3 which may be interesting if you +have more than one monitor:

    +
      +
    1. +

      +You can specify which workspace should be put on which screen. This + allows you to have a different set of workspaces when starting than just + 1 for the first monitor, 2 for the second and so on. See + [workspace_screen]. +

      +
    2. +
    3. +

      +If you want some applications to generally open on the bigger screen + (MPlayer, Firefox, …), you can assign them to a specific workspace, see + [assign_workspace]. +

      +
    4. +
    5. +

      +If you have many workspaces on many monitors, it might get hard to keep + track of which window you put where. Thus, you can use vim-like marks to + quickly switch between windows. See [vim_like_marks]. +

      +
    6. +
    +
    +
    +
    +
    +

    6. i3 and the rest of your software world

    +
    +
    +

    6.1. Displaying a status line

    +

    A very common thing amongst users of exotic window managers is a status line at +some corner of the screen. It is an often superior replacement to the widget +approach you have in the task bar of a traditional desktop environment.

    +

    If you don’t already have your favorite way of generating such a status line +(self-written scripts, conky, …), then i3status is the recommended tool for +this task. It was written in C with the goal of using as few syscalls as +possible to reduce the time your CPU is woken up from sleep states.

    +

    Regardless of which application you use to generate the status line, you +want to make sure that the application does one of the following things:

    +
      +
    1. +

      +Register as a dock window using EWMH hints. This will make i3 position the + window above the workspace bar but below every other client. This is the + recommended way, but in case of dzen2, for example, you need to check out + the source of dzen2 from subversion, as the -dock option is not present + in the released versions. +

      +
    2. +
    3. +

      +Overlay the internal workspace bar. This method will not waste any space + on the workspace bar, however, it is rather hackish. Just configure + the output window to be over the workspace bar (say -x 200 and -y 780 if + your screen is 800 px height). +

      +
    4. +
    +

    The planned solution for this problem is to make the workspace bar optional +and switch to a third party application completely (dzen2 for example) +which will then contain the workspace bar.

    +
    +
    +

    6.2. Giving presentations (multi-monitor)

    +

    When giving a presentation, you typically want the audience to see what you see +on your screen and then go through a series of slides (if the presentation is +simple). For more complex presentations, you might want to have some notes +which only you can see on your screen, while the audience can only see the +slides.

    +
    +

    6.2.1. Case 1: everybody gets the same output

    +

    This is the simple case. You connect your computer to the video projector, +turn on both (computer and video projector) and configure your X server to +clone the internal flat panel of your computer to the video output:

    +
    +
    +
    xrandr --output VGA1 --mode 1024x768 --same-as LVDS1
    +
    +

    i3 will then use the lowest common subset of screen resolutions, the rest of +your screen will be left untouched (it will show the X background). So, in +our example, this would be 1024x768 (my notebook has 1280x800).

    +
    +
    +

    6.2.2. Case 2: you can see more than your audience

    +

    This case is a bit harder. First of all, you should configure the VGA output +somewhere near your internal flat panel, say right of it:

    +
    +
    +
    xrandr --output VGA1 --mode 1024x768 --right-of LVDS1
    +
    +

    Now, i3 will put a new workspace (depending on your settings) on the new screen +and you are in multi-monitor mode (see [multi_monitor]).

    +

    Because i3 is not a compositing window manager, there is no ability to +display a window on two screens at the same time. Instead, your presentation +software needs to do this job (that is, open a window on each screen).

    +
    +
    +
    +
    +
    +

    + + + diff --git a/docs/wsbar.html b/docs/wsbar.html new file mode 100644 index 0000000..677dc46 --- /dev/null +++ b/docs/wsbar.html @@ -0,0 +1,148 @@ + + + + + +i3: External workspace bars + + + + + + + +
    +

    i3 - improved tiling WM

    + +
    +
    + +
    +
    +

    This document describes why the internal workspace bar is minimal and how an +external workspace bar can be used. It explains the concepts using i3-wsbar +as the reference implementation.

    +
    +
    +
    +

    1. Internal and external bars

    +
    +

    The internal workspace bar of i3 is meant to be a reasonable default so that +you can use i3 without having too much hassle when setting it up. It is quite +simple and intended to stay this way. So, there is no way to display your own +information in this bar (unlike dwm, wmii, awesome, …).

    +

    We chose not to implement such a mechanism because that would be duplicating +already existing functionality of tools such as dzen2, xmobar and similar. +Instead, you should disable the internal bar and use an external workspace bar +(which communicates with i3 through its IPC interface).

    +
    +
    +
    +

    2. dock mode

    +
    +

    You typically want to see the same workspace bar on every workspace on a +specific screen. Also, you don’t want to place the workspace bar somewhere +in your layout by hand. This is where dock mode comes in: When a program sets +the appropriate hint (_NET_WM_WINDOW_TYPE_DOCK), it will be managed in dock +mode by i3. That means it will be placed at the bottom of the screen (while +other edges of the screen are possible in the NetWM standard, this is not yet +implemented in i3), it will not overlap any other window and it will be on +every workspace for the specific screen it was placed on initially.

    +
    +
    +
    +

    3. The IPC interface

    +
    +

    In the context of using an external workspace bar, the IPC interface needs to +provide the bar program with the current workspaces and output (as in VGA-1, +LVDS-1, …) configuration. In the other direction, the program has to be able +to switch to specific workspaces.

    +

    By default, the IPC interface is enabled and places its UNIX socket in +~/.i3/ipc.sock.

    +

    To learn more about the protocol which is used for IPC, see docs/ipc.

    +
    +
    +
    +

    4. Output changes (on-the-fly)

    +
    +

    i3 implements the RandR API and can handle changing outputs quite well. So, an +external workspace bar implementation needs to make sure that when you change +the resolution of any of your screens (or enable/disable an output), the bars +will be adjusted properly.

    +
    +
    +
    +

    5. i3-wsbar, the reference implementation

    +
    +

    Please keep in mind that i3-wsbar is just a reference implementation. It is +shipped with i3 to have a reasonable default. Thus, i3-wsbar is designed to +work well with dzen2 and there are no plans to make it more generic.

    +
    +

    5.1. The big picture

    +

    The most common reason to use an external workspace bar is to integrate system +information such as what i3status provides into the workspace bar (to save +screen space). So, we have i3status or a similar program, which only provides +text output (formatted in some way). To display this text nicely on the screen, +there are programs such as dzen2, xmobar and similar. We will stick to dzen2 +from here on. So, we have the output of i3status, which needs to go into dzen2 +somehow. But we also want to display the list of workspaces. i3-wsbar takes +input on stdin, combines it with a formatted workspace list and pipes it to +dzen2.

    +

    Please note that i3-wsbar does not print its output to stdout. Instead, it +launches the dzen2 instances on its own. This is necessary to handle changes +in the available outputs (to place a new dzen2 on a new screen for example).

    +

    + +Overview + +

    +
    +
    +

    5.2. Running i3-wsbar

    +

    The most simple usage of i3-wsbar looks like this:

    +
    +
    +
    i3-wsbar -c "dzen2 -x %x -dock"
    +
    +

    The %x in the command name will be replaced by the X position of the output +for which this workspace bar is running. i3 will automatically place the +workspace bar on the correct output when dzen2 is started in dock mode. The +bar which you will see should look exactly like the internal bar of i3.

    +

    To actually get a benefit, you want to give i3-wsbar some input:

    +
    +
    +
    i3status | i3-wsbar -c "dzen2 -x %x -dock"
    +
    +

    It is recommended to place the above command in your i3 configuration file +to start it automatically with i3.

    +
    +
    +
    +
    +

    + + + diff --git a/docs/wsbar.png b/docs/wsbar.png new file mode 100644 index 0000000..0789dec Binary files /dev/null and b/docs/wsbar.png differ diff --git a/fonts/DroidSansMono.ttf b/fonts/DroidSansMono.ttf new file mode 100644 index 0000000..38b920a Binary files /dev/null and b/fonts/DroidSansMono.ttf differ diff --git a/js/asciidoc-xhtml11.js b/js/asciidoc-xhtml11.js new file mode 100644 index 0000000..30d738a --- /dev/null +++ b/js/asciidoc-xhtml11.js @@ -0,0 +1,128 @@ +var asciidoc = { // Namespace. + +///////////////////////////////////////////////////////////////////// +// Table Of Contents generator +///////////////////////////////////////////////////////////////////// + +/* Author: Mihai Bazon, September 2002 + * http://students.infoiasi.ro/~mishoo + * + * Table Of Content generator + * Version: 0.4 + * + * Feel free to use this script under the terms of the GNU General Public + * License, as long as you do not remove or alter this notice. + */ + + /* modified by Troy D. Hanson, September 2006. License: GPL */ + /* modified by Stuart Rackham, 2006, 2009. License: GPL */ + +// toclevels = 1..4. +toc: function (toclevels) { + + function getText(el) { + var text = ""; + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. + text += i.data; + else if (i.firstChild != null) + text += getText(i); + } + return text; + } + + function TocEntry(el, text, toclevel) { + this.element = el; + this.text = text; + this.toclevel = toclevel; + } + + function tocEntries(el, toclevels) { + var result = new Array; + var re = new RegExp('[hH]([2-'+(toclevels+1)+'])'); + // Function that scans the DOM tree for header elements (the DOM2 + // nodeIterator API would be a better technique but not supported by all + // browsers). + var iterate = function (el) { + for (var i = el.firstChild; i != null; i = i.nextSibling) { + if (i.nodeType == 1 /* Node.ELEMENT_NODE */) { + var mo = re.exec(i.tagName); + if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") { + result[result.length] = new TocEntry(i, getText(i), mo[1]-1); + } + iterate(i); + } + } + } + iterate(el); + return result; + } + + var toc = document.getElementById("toc"); + var entries = tocEntries(document.getElementById("content"), toclevels); + for (var i = 0; i < entries.length; ++i) { + var entry = entries[i]; + if (entry.element.id == "") + entry.element.id = "_toc_" + i; + var a = document.createElement("a"); + a.href = "#" + entry.element.id; + a.appendChild(document.createTextNode(entry.text)); + var div = document.createElement("div"); + div.appendChild(a); + div.className = "toclevel" + entry.toclevel; + toc.appendChild(div); + } + if (entries.length == 0) + toc.parentNode.removeChild(toc); +}, + + +///////////////////////////////////////////////////////////////////// +// Footnotes generator +///////////////////////////////////////////////////////////////////// + +/* Based on footnote generation code from: + * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html + */ + +footnotes: function () { + var cont = document.getElementById("content"); + var noteholder = document.getElementById("footnotes"); + var spans = cont.getElementsByTagName("span"); + var refs = {}; + var n = 0; + for (i=0; i" + + "" + + n + ". " + note + "
    "; + spans[i].innerHTML = + "[" + n + "]"; + var id =spans[i].getAttribute("id"); + if (id != null) refs["#"+id] = n; + } + } + if (n == 0) + noteholder.parentNode.removeChild(noteholder); + else { + // Process footnoterefs. + for (i=0; i" + n + "]"; + } + } + } +} + +}