wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit e1ea2479946206babdea6cc157285e5cbd0e7703
parent 68b77ab4e8e55214a4e71626e94e0a126fe23d41
Author: Kris Maglione <kris@suckless.org>
Date:   Sun, 27 Jun 2010 17:08:20 -0400

[guide] Split guide sections into separate .tex files.

Diffstat:
doc/customizing.tex | 943+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
doc/gettingstarted.tex | 294+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
doc/introduction.tex | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
doc/license.tex | 29+++++++++++++++++++++++++++++
doc/wmii.tex | 1506+++----------------------------------------------------------------------------
5 files changed, 1481 insertions(+), 1457 deletions(-)

diff --git a/doc/customizing.tex b/doc/customizing.tex @@ -0,0 +1,943 @@ +\chapter{Customizing \wmii} + +There are several configuration schemes available for \wmii. If +you're only looking to add basic key bindings, status monitors, +\emph{et cetera}, you should have no trouble modifying the stock +configuration for your language of choice. If you're looking for +deeper knowledge of \wmii's control interface though, this +section is for you. We'll proceed by building a configuration +script in \POSIX\ |sh| syntax and then move on to a discussion +of the higher level constructs in the stock configuration +scripts. + +For the purposes of pedagogy, we'll construct the script in the +literate programming style of Knuth, whereby we construct the +code in fragments and explain each one in detail. For your +convenience, each fragment name is linked to its definition. + +\section{Events} + +The \wmii\ control interface is largely event driven. Each event +is represented by a single, plain-text line written to the +|/event| file. You can think of this file as a named pipe. When +reading it, you won't receive an EOF\footnote{End of File} until +\wmii\ exits. Moreover, any lines written to the file will be +transmitted to everyone currently reading from it. Notable +events include key presses, the creation and destruction of +windows, and changes of focus and views. + +We'll start building our configuration with an event processing +framework: + +\begin{Fragment}{Event Loop} + # Broadcast a custom event + wmiir xwrite /event Start wmiirc + + # Turn off globbing + set -f + # Open /event for reading + wmiir read /event | + # Read the events line by line + while read line; do + # Split the line into words, store in $@ + set -- $line + event=$1; shift + line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)" + # Process the event + case $event in + Start) # Quit when a new instance starts + [ $1 = wmiirc ] && exit;; + «Event Handlers» + esac + done +\end{Fragment} + +Now, we need to consider which types of events we'll need to +handle: + +\begin{Fragment}{Event Handlers} + «View Button Events» + «Urgency Events» + «Unresponsive Clients» + «Notice Events» + «Key Events» + «Client Menu Events» + «Tag Menu Events» +\end{Fragment} + +\section{Bar Items} + +The bar is described by the files in the two directories |/lbar/| and +|/rbar/| for buttons on the left and right side of the bar, +respectively. The files act as control files (section +\ref{sec:controlfiles}) with the contents: + +\begin{code} + color ‹Color Tuple› + label ‹Label› +\end{code} + +A ‹Color Tuple› is defined as: + +\begin{code} + ‹Color Tuple› ≔ ‹foreground color› ‹background color› ‹border color› + ‹* Color› ≔ ‹RGB color› | ‹RGBA color› + ‹RGB color› ≔ #‹6 character RGB hex color code› + ‹RGBA color› ≔ rgba:‹red›/‹green›/‹blue›/‹alpha› +\end{code} + +\noindent +where all of the colors are represented as lowercase, +hexidecimal values. In the case of RGBA colors, they may be 1--4 +characters long, though they will be standardized internally to +2 characters. + +\medskip + +Let's define our basic theme information now: + +\begin{Fragment}{Theme Definitions} + normcolors=‘#000000 #c1c48b #81654f’ + focuscolors=‘#000000 #81654f #000000’ + background=‘#333333’ + font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’ +\end{Fragment} + +\subsection{View Buttons} + +With a basic understanding of bar items in mind, we can write +our view event handlers: + +\index{events!CreateTag} +\index{events!DestroyTag} +\index{events!FocusTag} +\index{events!UnfocusTag} +\begin{Fragment}{View Button Events} + CreateTag) # CreateTag ‹Tag Name› + echo $normcolors $1 | wmiir create /lbar/$1;; + DestroyTag) # DestroyTag ‹Tag Name› + wmiir rm /lbar/$1;; + FocusTag) # FocusTag ‹Tag Name› + wmiir xwrite /lbar/$1 $focuscolors $1;; + UnfocusTag) # UnfocusTag ‹Tag Name› + wmiir xwrite /lbar/$1 $normcolors $1;; +\end{Fragment} + +\subsection{Urgency} + +\index{events!UrgentTag|(} +\index{events!NotUrgentTag|(} +Windows can specify that they require attention, and in X11 +parlance, this is called urgency\footnote{\ICCCM{4.1.2.4}}. When +a window requests attention as such, or declares that it's been +satisfied, \wmii\ broadcasts an event for the client and an +event for each view that it belongs to. It also fills in the +layout box of any client deemed urgent. It's the job of a script +to decide how to handle urgency events above and beyond that +basic measure. The standard scripts simply mark urgent views +with an asterisk: + +\begin{Fragment}{Urgency Events} + # The urgency events are ‘Client’ events when the program + # owning the window sets its urgency state. They're ‘Manager’ + # events when wmii or the wmii user sets the state. + UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› + wmiir xwrite /lbar/$2 $2;; + NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› + wmiir xwrite /lbar/$2 $2;; +\end{Fragment} +\index{events!UrgentTag|)} +\index{events!NotUrgentTag|)} + +\subsection{Notices} + +The standard scripts provide a custom Notice event for +displaying status information. The events appear in the long bar +between the left and right sides for five seconds. + +\begin{Fragment}{Notice Events} + Notice) + wmiir xwrite /rbar/!notice $line + kill $xpid 2>/dev/null # Let's hope this isn't reused... + { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & + xpid = $!;; +\end{Fragment} + +\section{Keys} + +\label{sec:keybindings} +\index{key bindings} +\index{filesystem!/!keys} +\index{filesystem!/!event} +Now to the part you've no doubt been waiting for: binding keys. +When binding keys, you need to be aware of two files, |/keys| +and |/event|. The former defines which keys \wmii\ needs to +grab, and the latter broadcasts the events when they're pressed. + +Key names are specified as a series of modifiers followed by a +key name, all separated by hyphens. Valid modifier names are +|Control|, |Shift|, |Mod1| (usually Alt), |Mod2|, |Mod3|, |Mod4| +(usually the Windows® key), and |Mod5|. Modifier keys can be +changed via |xmodmap(1)|, the details of which are beyond the +scope of this document. + +Key names can be detected by running |xev| from a +terminal, pressing the desired key, and looking at the output +(it's in the parentheses, after the keysym). Or, more simply, +you can run the \man 1 {wikeyname} utility bundled with \wmii\ +and press the key you wish to bind. + +Examples of key bindings: + +\begin{description} + \item[Windows® key + Capital A] |Mod4-Shift-A| + \item[Control + Alt + Space] |Mod1-Control-Space| +\end{description} + +Now, let's bind the keys we plan on using: + +\begin{Fragment}{Bind Keys} + { + cat <<! + Mod4-space + Mod4-d + Mod4-s + Mod4-m + Mod4-a + Mod4-p + Mod4-t + Mod4-Return + Mod4-Shift-space + Mod4-f + Mod4-Shift-c + Mod4-Shift-t + Mod4-h + Mod4-j + Mod4-k + Mod4-l + Mod4-Shift-h + Mod4-Shift-j + Mod4-Shift-k + Mod4-Shift-l + ! + for i in 1 2 3 4 5 6 7 8 9 0; do + echo Mod4-$i + echo Mod4-Shift-$i + done + } | wmiir write /keys +\end{Fragment} + +and lay a framework for processing their events: + +\begin{Fragment}{Key Events} + Key) # Key ‹Key Name› + case $1 in + «Motion Keys» + «Client Movement Keys» + «Column Mode Keys» + «Client Command Keys» + «Command Execution Keys» + «Tag Selection Keys» + «Tagging Keys» + esac;; +\end{Fragment} + +\section{Click Menus} + +Sometimes, you have your hand on the mouse and don't want to +reach for the keyboard. To help cope, \wmii\ provides a +mouse-driven, single-click menu. The default configuration uses +it for client and tag menus. + +\begin{Fragment}{Click Menu Initialization} + clickmenu() { + if res=$(wmii9menu -- “$@”); then eval “$res”; fi + } +\end{Fragment} + +\section{Control Files} + +\label{sec:controlfiles} + +Several directories including the root, have control files, +named |ctl|. These files are used to control the object (e.g., a +client or tag) represented by the directory. Each line of the +file, with the possible section of the first, represents a +control variable and its value. In the case of all but the root +|/ctl| file, the first line represents the id of the directory. +In the case of |/tag/foo/ctl|, for instance, the first line +should read |foo|. This is useful when dealing with the special +|sel/| directories. For instance, when |foo| is the selected +tag, the special |/tag/sel| directory is a link to |/tag/foo|, +and the first line of |/tag/sel/ctl| will read |foo|, just as +if you'd accessed |/tag/foo/ctl| directly. + +The rest of the lines, the control variables, can be modified by +writing new values to the control file. For instance, if a +client is fullscreen, its control file will contain the line: + +\begin{code} + fullscreen on +\end{code} + +\noindent To restore the client from fullscreen, either of the +following lines may be written to its control file: + +\begin{code} + fullscreen off + fullscreen toggle +\end{code} + +When next read, the |fullscreen on| line will have been replaced +with |fullscreen off|. No care need be taken to preserve the +other contents of the file. They're generated anew each time +it's read. + +\section{Clients} + +\def\clientlabel{/client/$\langle\mathit{client}\rangle$/} +\index{filesystem!/client/*/@\clientlabel|(} +Clients are represented by directories under the |/client/| +tree. Subdirectory names represent the client's X11 window ID. +The special |sel/| directory represents the currently selected +client. The files in these directories are: + +\begin{description} + \item[ctl] The client's control file, containing the following + properties: + \index{filesystem!/client/*/@\clientlabel!ctl} + \begin{description} + \item[allow] The set of unusual actions the client is + allowed to perform, in the same format as the tag set. + \begin{description} + \item[activate] The client is allowed to activate + itself—that is, focus its window and, as the case may + require, uncollapse it and select a tag it resides on. + This flag must be set on a client if you wish it able to + activate itself from the system tray. + \end{description} + \item[floating] Defines whether this client is likely to + float when attached to a new view. May be |on|, |off|, + |always|, or |never|. Ordinarilly, the value changes + automatically whenever the window is moved between the + floating and managed layers. However, setting a value of + |always| or |never| overrides this behavior. + \item[fullscreen] The client's fullscreen state. When + |on|, the client is displayed fullscreen on all of its + views. Possible values are |on|, |off|, and |toggle|. + \item[group] The client's group ID, or |0| if not part of + a group. Clients tend to open with the same tags and in + the same columns as the last active member of their + group. Setting this property is only useful when done + via the rules file. + \item[kill] When written, the window is closed politely, + if possible. + \item[pid] Read-only value of the PID of the program that + owns the window, if the value is available and the + process is on the same machine as wmii. + \item[slay] When written, the client is disconnected + peremptorily. If the client's PID is available and the + process is the same machine as wmii, its parent process + is killed + \item[tags] The client's tags. The same as the tags file. + \item[urgent] The client's urgency state. When |on|, the + client's layout box will be highlighted. Possible values + are |on|, |off|, and |toggle|. + \end{description} + \item[props] The client's window class (the X11 + |WM_CLASS|\footnote{\ICCCM{4.1.2.5}} + property) and title string, separated by colons. This file + is not writable. + \index{filesystem!/client/*/@\clientlabel!props} + \item[label] The client's window title. May be written to + change the client's title. + \index{filesystem!/client/*/@\clientlabel!label} + \item[tags] + \index{filesystem!/client/*/@\clientlabel!tags} + The client's tags. Tag names are separated by |+|, |-|, or + |^| signs. Tag names which directly follow a |+| sign are + added, while whose following a |-| sign are removed and + those following a |^| are toggled. If the value written + begins with one of these characters, the value is appended + to the clients tags rather than replacing them. + + Tags formatted as |/‹regex›/| are treated as regular + expressions, which place the client on any extant matching + tag\footnote{While a client with a regex tag will always + appear in all matching views, it will not keep those views + in existence. When the last client explicitly tagged with a + view is removed, the view is deleted as soon as it becomes + inactive.}. Regular expression tags which directly follow a + minus sign are treated as exclusion expressions. For + example, the tag string |+/foo/-/food/| will match the tag + |foobar|, but not the tag |foodstand|. +\end{description} + +\index{filesystem!/client/*/@\clientlabel|)} + +\subsection{Key Bindings} + +To control clients, we'll add the following key bindings: + +\begin{Fragment}{Client Command Keys} + Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;; + Mod4-f) wmiir xwrite /client/sel/ctl Fullscreen toggle;; +\end{Fragment} + +And to manage their tags, we'll need: + +\begin{Fragment}{Tagging Keys} + Mod4-Shift-t) + # Get the selected client's id + c=$(wmiir read /client/sel/ctl | sed 1q) + # Prompt the user for new tags + tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) + # Write them to the client + wmiir xwrite /client/$c/tags $tag;; + Mod4-Shift-[0-9]) + wmiir xwrite /client/sel/tags ${1##*-};; +\end{Fragment} + +\subsection{Click Menus} + +\index{events!ClientMouseDown} +\begin{Fragment}{Client Menu Events} + ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button› + [ $2 = 3 ] && clickmenu \ + “Delete:wmiir xwrite /client/$1/ctl kill” \ + “Kill: wmiirxwrite /client/$1/ctl slay” \ + “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on” +\end{Fragment} + +\subsection{Unresponsive Clients} + +\index{events!UnresponsiveClient|(} +When \wmii\ tries to close a window, it waits 8 seconds for the +client to respond, and then lets its scripts decide what to do +with it. The stock scripts prompt the user for input: + +\begin{Fragment}{Unresponsive Clients} + UnresponsiveClient) # UnresponsiveClient ‹Client ID› + { + # Use wihack to make the xmessage a transient window of + # the problem client. This will force it to open in the + # floaing layer of whatever views the client is attached to + resp=$(wihack -transient $1 \ + xmessage -nearmouse -buttons Kill,Wait -print \ + “The following client is not responding.” \ + “What would you like to do?$(echo)” \ + $(wmiir read /client/$1/label)) + [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay + } &;; +\end{Fragment} +\index{events!UnresponsiveClient|)} + +\section{Views} + +\def\taglabel{/tag/$\langle\mathit{tag}\rangle$/} +\index{filesystem!/tag/*/@\taglabel|(} +Views are represented by directories under the |/tag/| tree. The +special |sel/| directory represents the currently selected +client. The |sel| tag is treated similarly elsewhere. The files +in these directories are: + +\begin{description} + \item[ctl] + The view's control file. The properties are: + \index{filesystem!/tag/*/@\taglabel!ctl|(} + \begin{description} + \item[select ‹Area›] Select the column ‹Area›, where + ‹Area› is a 1-based column index, or |~| for the floating + area. It may be optionally preceded by ‹Screen›|:|, where + ‹Screen› is a 0-based Xinerama screen index, or “sel”. When + omitted, ‹Screen› defaults to 0, the primary screen. + \item[select ‹Area› ‹Client Index›] Select the column ‹Area›, and + the ‹Client Index›th client. + \item[select client ‹Client ID›] Select the client with the + X11 window ID ‹Client ID›. + \item[select ‹Direction›] + Select the client in ‹Direction› where ‹Direction› may be + one of ‹up $\wedge$ down $\wedge$ left $\wedge$ right›. + \item[send client ‹Client ID› ‹Area›] Send ‹Client ID› to + ‹Area›. ‹Area› may be |sel| for the selected area, and + |client ‹Client ID›| may be |sel| for the currently selected + client. + \item[send client ‹Client ID› ‹Direction›] + Send ‹Client ID› to a column or position in its column in + the given direction. + \item[send client ‹Client ID› toggle] If ‹Client ID› is + floating, send it to the managed layer. If it's managed, + send it to the floating layer. + \item[swap client ‹Client ID› \ldots] The same as the |send| + commands, but swap ‹Client ID› with the client at the given + location. + \item[colmode ‹Area› ‹Mode›] Set ‹Area›'s mode to ‹Mode›, + where ‹Mode› is a string of values similar to tag + specifications. Values which may be added and removed are as + follows for managed areas: + + \begin{description} + \item[stack] One and only one client in the area is + uncollapsed at any given time. When a new client is + selected, it is uncollapsed and the previously selected + client is collapsed. + \item[max] Collapsed clients are hidden from view + entirely. Uncollapsed clients display an indicator + {\it‹n›/‹m›}, where ‹m› is the number of collapsed + clients directly above and below the client, plus one, + and ‹n› is the client's index in the stack. + \item[default] Like subtracting the stack mode, but all + clients in the column are given equal height. + \end{description} + + For the floating area, the values are the same, except that + in |max| mode, floating clients are hidden when the managed + layer is selected. + \item[grow ‹Frame› ‹Direction› {[‹Amount›]}] Grow ‹Frame› in + the given direction, by ‹Amount›. ‹Amount› may be any + integer, positive or negative. If suffixed with |px|, + it specifies an exact pixel amount, otherwise it specifies a + “reasonable increment”. Defaults to 1. + + ‹Frame› may be one of: + \begin{itemize} + \item client ‹Client ID› + \item ‹Area› ‹Client Index› + \end{itemize} + \item[nudge ‹Frame› ‹Direction› {[‹Amount›]}] Like + |grow|, but move the client in ‹Direction› instead of + resizing it. + \end{description} + \index{filesystem!/tag/*/@\taglabel!ctl|)} +\end{description} + +\index{filesystem!/tag/*/@\taglabel|)} + +\subsection{Key Bindings} + +We'll use the following key bindings to interact with views: + +\begin{Fragment}{Motion Keys} + Mod4-h) wmiir xwrite /tag/sel/ctl select left;; + Mod4-l) wmiir xwrite /tag/sel/ctl select right;; + Mod4-k) wmiir xwrite /tag/sel/ctl select up;; + Mod4-j) wmiir xwrite /tag/sel/ctl select down;; + Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;; +\end{Fragment} + +\begin{Fragment}{Client Movement Keys} + Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;; + Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;; + Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;; + Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;; + Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;; +\end{Fragment} + +\begin{Fragment}{Column Mode Keys} + Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;; + Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;; + Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;; +\end{Fragment} + +\subsection{Click Menus} + +\index{events!LeftBarMouseDown} +\begin{Fragment}{Tag Menu Events} + LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name› + [ $1 = 3 ] && clickmenu \ + “Delete:delete_view $2” +\end{Fragment} + +\section{Command and Program Execution} + +Perhaps the most important function we need to provide for is +the execution of programs. Since \wmii\ users tend to use +terminals often, we'll add a direct shortcut to launch one. +Aside from that, we'll add a menu to launch arbitrary programs +(with completions) and a separate menu to launch wmii specific +commands. + +We use |wmiir setsid| to launch programs with their own session +IDs to prevent untoward effects when this script dies. + +\begin{Fragment}{Command Execution Initialization} + terminal() { wmiir setsid xterm “$@” } + proglist() { + IFS=: + wmiir proglist $1 | sort | uniq + unset IFS + } +\end{Fragment} + +\subsection{Key Bindings} +\begin{Fragment}{Command Execution Keys} + Mod4-Return) terminal & ;; + Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;; + Mod4-a) { + set -- $(proglist $WMII_CONFPATH | wimenu) + which=$(which which) + prog=$(PATH=$WMII_CONFPATH $which $1); shift + eval exec $prog “$@” + } &;; +\end{Fragment} + +\section{The Root} + +The root filesystem contains the following: + +\index{!filesystem!/|(} +\begin{description} + \item[ctl] The control file. The properties are: + \index{filesystem!/!ctl} + \begin{description} + \item[bar on ‹top $\wedge$ bottom›] Controls where the bar + is shown. + \item[bar off] Disables the bar entirely. + \item[border] The border width, in pixels, of floating + clients. + \item[colmode ‹Mode›] The default column mode for newly + created columns. + \item[focuscolors ‹Color Tuple›] The colors of focused + clients. + \item[normcolors ‹Color Tuple›] The colors of unfocused + clients and the default color of bar buttons. + \item[font ‹Font›] The font used throughout \wmii. If + prefixed with |xft:|, the Xft font renderer is used, and + fonts may be antialiased. Xft font names follow the + fontconfig formula. For instance, 10pt, italic Lucida + Sans would be specified as + + \begin{code} + xft:Lucida Sans-10:italic + \end{code} + + See \man 1 {fc-match}. + + \item[grabmod ‹Modifier Keys›] The key which must be + pressed to move and resize windows with the mouse + without clicking hot spots. + \item[incmode ‹Mode›] Controls how X11 increment hints are + handled in managed mode. Possible values are: + \begin{description} + \item[ignore] Increment hints are ignored entirely. + Clients are stretched to fill their full allocated + space. + \item[show] Gaps are shown around managed client + windows when their increment hints prevent them from + filling their entire allocated space. + \item[squeeze] When increment hints cause gaps to show + around clients, \wmii\ will try to adjust the sizes + of the clients in the column to minimize lost space. + \end{description} + \item[view ‹Tag›] Change the currently visible view. + \item[exec ‹Command›] Replaces this \wmii\ instance with + ‹Command›. ‹Command› is split according to rc quoting + rules, and no expansion occurs. If the command fails to + execute, \wmii\ will respawn. + \item[spawn ‹Command›] Spawns ‹Command› as it would spawn + |wmiirc| at startup. If ‹Command› is a single argument + and doesn't begin with |/| or |./|,% + \hskip 1ex|$WMII_CONF|\-|PATH| is + searched for the executable. Otherwise, the whole + argument is passed to the shell for evaluation. + \end{description} + \item[keys] The global keybindings. See section \ref{sec:keybindings}. + \index{filesystem!/!keys|primary} + \item[event] The global event feed. See section \ref{sec:keybindings}. + \index{filesystem!/!event|primary} + \item[colrules] + \index{filesystem!/!colrules} + The |/colrules| file contains a list of + rules which affect the width of newly created columns. + Rules have the form: + + \begin{quote}\texttt{ + /‹regex›/ -> ‹width›{\color{gray}[}+‹width›{\color{gray}]*}} + \end{quote} + + Where, + + \begin{code} + ‹width› ≔ ‹percent of screen› | ‹pixels›px + \end{code} + + When a new column, ‹n›, is created on a view whose name + matches ‹regex›, it is given the ‹n›th supplied ‹width›. + If there is no ‹n›th width, it is given + $1/\mbox{‹ncol›th}$ of the screen. + + \item[rules] + \index{filesystem!/!rules} + The |/rules| file contains a list of + rules similar to the colrules. These rules set + properties for a client when it is created. + Rules are specified: + + \begin{quote}\texttt{ + /‹regex›/ -> ‹key›{\color{gray}=}‹value› {\color{gray}\ldots}} + \end{quote} + + When a client's ‹name›:‹class›:‹title› matches + ‹regex›, the matching rules are applied. For each + ‹key›=‹value› pair, the |ctl| file property matching + ‹key› is set to ‹value›. Additionally, the following + keys are accepted and have special meaning: + + \begin{description} + \item[continue] + Normally, when a matching rule is encountered, + rule matching stops. When the continue key is + provided (with any value), matching continues at + the next rule. + \item[force-tags] + Like tags, but overrides any settings obtained + obtained from the client's group or from the + |_WMII_TAGS| window property. + \end{description} + +\end{description} + +\index{!filesystem!/|)} + +\subsection{Configuration} + +We'll need to let \wmii\ know about our previously defined theme +information: + +\begin{Fragment}{Configuration} + «Theme Definitions» + + xsetroot -solid $background + wmiir write /ctl <<! + border 2 + focuscolors $focuscolors + normcolors $normcolors + font $font + grabmod Mod4 + ! +\end{Fragment} + +\subsection{Key Bindings} + +And we need a few more key bindings to select our views: + +\begin{Fragment}{Tag Selection Keys} + Mod4-t) + # Prompt the user for a tag + tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) + # Write it to the filesystem. + wmiir xwrite /ctl view $tags;; + Mod4-[0-9]) + wmiir xwrite /ctl view ${1##*-};; +\end{Fragment} + +\section{Tieing it All Together} + +\begin{code} + #!/bin/sh + «Click Menu Initialization» + «Command Execution Initialization» + + «Configuration» + + «Bind Keys» + «Event Loop» +\end{code} + +\section{The End Result} + +For clarity, here is the end result: + +\begin{code} + #!/bin/sh + # «Click Menu Initialization» + clickmenu() { + if res=$(wmii9menu -- “$@”); then eval “$res”; fi + } + # «Command Execution Initialization» + terminal() { wmiir setsid xterm “$@” } + proglist() { + IFS=: + wmiir proglist $1 | sort | uniq + unset IFS + } + + # «Configuration» + # «Theme Definitions» + normcolors=‘#000000 #c1c48b #81654f’ + focuscolors=‘#000000 #81654f #000000’ + background=‘#333333’ + font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’ + + xsetroot -solid $background + wmiir write /ctl <<! + border 2 + focuscolors $focuscolors + normcolors $normcolors + font $font + grabmod Mod4 + ! + + # «Bind Keys» + { + cat <<! + Mod4-space + Mod4-d + Mod4-s + Mod4-m + Mod4-a + Mod4-p + Mod4-t + Mod4-Return + Mod4-Shift-space + Mod4-f + Mod4-Shift-c + Mod4-Shift-t + Mod4-h + Mod4-j + Mod4-k + Mod4-l + Mod4-Shift-h + Mod4-Shift-j + Mod4-Shift-k + Mod4-Shift-l + ! + for i in 1 2 3 4 5 6 7 8 9 0; do + echo Mod4-$i + echo Mod4-Shift-$i + done + } | wmiir write /keys + + # «Event Loop» + # Broadcast a custom event + wmiir xwrite /event Start wmiirc + + # Turn off globbing + set -f + # Open /event for reading + wmiir read /event | + # Read the events line by line + while read line; do + # Split the line into words, store in $@ + set -- $line + event=$1; shift + line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)" + + # Process the event + case $event in + Start) # Quit when a new instance starts + [ $1 = wmiirc ] && exit;; + + # «Event Handlers» + # «View Button Events» + CreateTag) # CreateTag ‹Tag Name› + echo $normcolors $1 | wmiir create /lbar/$1;; + DestroyTag) # DestroyTag ‹Tag Name› + wmiir rm /lbar/$1;; + FocusTag) # FocusTag ‹Tag Name› + wmiir xwrite /lbar/$1 $focuscolors $1;; + UnfocusTag) # UnfocusTag ‹Tag Name› + wmiir xwrite /lbar/$1 $normcolors $1;; + + # «Urgency Events» + # The urgency events are ‘Client’ events when the program + # owning the window sets its urgency state. They're ‘Manager’ + # events when wmii or the wmii user sets the state. + UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› + wmiir xwrite /lbar/$2 $2;; + NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› + wmiir xwrite /lbar/$2 $2;; + + # «Unresponsive Clients» + UnresponsiveClient) # UnresponsiveClient ‹Client ID› + { + # Use wihack to make the xmessage a transient window of + # the problem client. This will force it to open in the + # floaing layer of whatever views the client is attached to + resp=$(wihack -transient $1 \ + xmessage -nearmouse -buttons Kill,Wait -print \ + “The following client is not responding.” \ + “What would you like to do?$(echo)” \ + $(wmiir read /client/$1/label)) + [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay + } &;; + + # «Notice Events» + Notice) + wmiir xwrite /rbar/!notice $line + kill $xpid 2>/dev/null # Let's hope this isn't reused... + { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & + xpid = $!;; + + # «Key Events» + Key) # Key ‹Key Name› + case $1 in + # «Motion Keys» + Mod4-h) wmiir xwrite /tag/sel/ctl select left;; + Mod4-l) wmiir xwrite /tag/sel/ctl select right;; + Mod4-k) wmiir xwrite /tag/sel/ctl select up;; + Mod4-j) wmiir xwrite /tag/sel/ctl select down;; + Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;; + + # «Client Movement Keys» + Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;; + Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;; + Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;; + Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;; + Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;; + + # «Column Mode Keys» + Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;; + Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;; + Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;; + + # «Client Command Keys» + Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;; + Mod4-f) wmiir xwrite /client/sel/ctl fullscreen toggle;; + + # «Command Execution Keys» + Mod4-Return) terminal & ;; + Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;; + Mod4-a) { + set -- $(proglist $WMII_CONFPATH | wimenu) + prog=$(PATH=$WMII_CONFPATH which $1); shift + eval exec $prog “$@” + } &;; + + # «Tag Selection Keys» + Mod4-t) + # Prompt the user for a tag + tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) + # Write it to the filesystem. + wmiir xwrite /ctl view $tag;; + Mod4-[0-9]) + wmiir xwrite /ctl view ${1##*-};; + + # «Tagging Keys» + Mod4-Shift-t) + # Get the selected client's id + c=$(wmiir read /client/sel/ctl | sed 1q) + # Prompt the user for new tags + tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) + # Write them to the client + wmiir xwrite /client/$c/tags $tag;; + Mod4-Shift-[0-9]) + wmiir xwrite /client/sel/tags ${1##*-};; + + esac;; + + # «Client Menu Events» + ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button› + [ $2 = 3 ] && clickmenu \ + “Delete:wmiir xwrite /client/$1/ctl kill” \ + “Kill:wmiir xwrite /client/$1/ctl slay” \ + “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on” + + # «Tag Menu Events» + LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name› + [ $1 = 3 ] && clickmenu \ + “Delete:delete_view $2” + esac + done +\end{code} + diff --git a/doc/gettingstarted.tex b/doc/gettingstarted.tex @@ -0,0 +1,294 @@ +\chapter{Getting Started} + +This section will walk you through your first \wmii\ startup. +For your first experience, we recommend running \wmii\ in its +own X session, so you can easily switch back to a more +comfortable environment if you get lost. Though you may start +\wmii\ from a session manager in your day to day use, these +instructions will use |xinit|. To begin with, copy this file +to your home directory, so we can open it in your new X session. +Then setup your |~/.xinitrc| as follows: + +\begin{code} + cd + + # Start a PDF viewer with this guide. Use any viewer + # you're comfortable with. + xpdf wmii.pdf & + + # Launch wmii + exec wmii + + # That was easy. +\end{code} + +Before you run |xinit|, make sure you know how to switch +between terminals. Depending on your system, your current X +session is probably on terminal 5 or 7. You should be able to +switch between your terminals by pressing +Ctrl-Alt-F$\langle n\rangle$. Assuming that your current X +session is on terminal 7, you should be able to switch between +it and your new session by pressing Ctrl-Alt-F7 and Ctrl-Alt-F8. +Now you should be ready to start \wmii. When you run the +following command, you should be presented with a new X session +running wmii and a PDF viewer showing this document. + +\begin{code} + xinit +\end{code} + +When you're there, find this page in the new PDF viewer and +continue. + +\section{Your First Steps} + +If everything went according to plan, you should be viewing this +from a nearly empty \wmii\ session. We're going to be using the +keyboard a lot, so let's start with a convention for key +notation. We'll be using the key modifiers Control, Alt, Shift, +and Meta\footnote{The Windows$^{\mbox{\tiny®}}$ key on most +keyboards. The Penguin key on the more tongue in cheek +varieties.}, which we'll specify as C-, A-, S-, and M-, +respectively. So, <C-S-a> means pressing ‘|a|’ while holding +|Control| and |Shift|. We'll also express mouse clicks this +way, with <M-Mouse1> signifying a press of the right mouse +button, with the Meta key depressed. Buttons 4 and 5 are the up +and down scroll wheel directions, respectively. + +\subsection{Floating Mode} + +Beginning with what's familiar to most users, we'll first explore +floating mode. First, we need to select the floating layer. +Press <M-Space>. You should see the titlebar of this window +change color. Now, press <M-Return> to launch a terminal. +The easiest way to drag the terminal around is to press and hold +<M-Mouse1> over the window and simply drag the window +around. You should be able to drag the window anywhere onscreen +without ever releasing the mouse button. As you drag near the +screen edges, you should notice a snap. If you try to drag the +window fully off-screen, you'll find it constrained so that a +portion always remains visible. Now, release the window and move +the mouse toward one of its corners. Press and hold +<M-Mouse3>\footnote{The right button.}. As you drag the +mouse around, you should see the window resized accordingly. + +To move the window without the modifier key, move the pointer +over the layout box to the left of its titlebar. You should see +the cursor change. Now, simply click and drag. To resize it, +move the pointer toward the window's edge until you see the +cursor change, and again, click and drag. Now, to close the +window, move the mouse over the windows titlebar, press and hold +<Mouse3>, select |Delete|, and release it. You should +see this window's titlebar return to its original color, +indicating that it's regained focus. + +\subsection{Managed Mode} + +Now, for the fun part. We'll start exploring managed mode by +looking at the basics of columns. In the default configuration, +columns have three modes: + +\begin{description} + \item[Stack] <M-s> The default mode for new columns. Only one window + is fully visible per column at once. The others only display + their title bars. When new windows are added to the column, + the active window collapses, and the new one takes its + place. Whenever a collapsed client is selected, the active + window is collapsed to take its place. + \item[Max] <M-m> Like stack mode, but the titlebars of collapsed + clients are hidden. + \item[Default] <M-d> Multiple uncollapsed windows may be visible at + once. New windows split the space with the other uncollapsed + windows in their vicinity. Windows may still be collapsed by + shrinking them to the size of their titlebars. At this + point, the behavior of a stack of collapsed and uncollapsed + clients is similar to that of stack mode. +\end{description} + +Before we open any new windows in managed mode, we need to +explore the column modes a bit. Column modes are activated with +the key bindings listed above. This column should be in stack +mode now. Watch the right side of the titlebar as you press +<M-m> to enter max mode. You should see an indicator appear. +This tells you the number of hidden windows directly above and +below the current window, and its position in that stack. Press +<M-d> to enter default mode. Now we're ready to open another +client. Press <M-Return> to launch another terminal. Now, +press <M-S-l> to move the terminal to a new column to the +right of this one. Once it's there, press <M-Return> two +more times to launch two more terminals. Now that you have more +than one window in a column, cycle through the three column +modes again until they seem familiar. + +\subsection{Keyboard Navigation} + +To begin, switch back to default mode. The basic keyboard +navigation keys, <M-h>, <M-j>, <M-k>, and <M-l>, +derive from vi, and represent moving left, down, up, and right +respectively. Try selecting each of the four windows currently +visible on screen. Notice that navigation wraps from one side of +the screen to the other, and from the top to the bottom. Now, +return to the write column, switch to stack mode, and select +each of the three terminals again. Do the same in max mode, +paying careful attention to the indicator to the right of the +titlebar. + +Now that you can select windows, you'll want to move them +around. To move a window, just add the Shift key to the +direction keys. So, to move a window left, instead of <M-h>, +type <M-S-h>. Now, experiment with moving windows, just as +you did with navigating them, in each of the three column modes. +Once you're comfortable with that, move a window to the floating +layer. Since we toggled between the floating and managed layers +with <M-Space>, we'll move windows between them with +<M-S-Space>. Try moving some windows back and forth until it +becomes familiar. Now, move several windows to the floating +layer and try switching between them with the keyboard. You'll +notice that <M-h> and <M-l> don't function in the +floating layer. This is for both historical and logistical +reasons. <M-j> and <M-k> cycle through floating windows +in order of their most recent use. + +\subsection{Mouse Navigation} + +\wmii\ uses the “sloppy focus” model, which is to say, it focuses +windows when the mouse enters them and when you click them. It +focuses windows only when you select them with the keyboard, +click their titlebars, or press click them with <M-Mouse2>. +Collapsed windows may be opened with the mouse by clicking their +titlebars. Moving and resizing floating windows should be +largely familiar, and has already been covered. The same can't +be said for managed windows. + +Let's begin working with the mouse in the managed layer. Return +to a layout with this document in a column on the left, and +three terminals in a column to the right. Switch the right +column to default mode. Now, bring the mouse to the top of the +third terminal's titlebar until you see a resize cursor. Click +and drag the titlebar to the very top of the screen. Now, move +the cursor to the top of the second terminal's titlebar and drag +it to the very bottom of the screen. Press <M-d> to restore the +terminals to their original sizes. Now, click and hold the +layout box of the second terminal. Drag it to the middle of the +terminal's window and release. Click and hold the layout box of +the third terminal and drag it to the middle of the first +terminal's window. Finally, drag the first terminal's layout box +to halfway down this window. <M-Mouse1> works to the same +effect as dragging the layout box, but allows you to click +anywhere in the window. + +Now that you've seen the basics of moving and dragging windows, +let's move on to columns. Click and drag the border between the +two columns. If that's a difficult target to click, there's a +triangle at the top of the division between the two columns that +you can click and drag as well. If that's still too hard a +target, try using <M-Mouse3>, which works anywhere and provides +much richer functionality. + +\subsection{Window Focus and Selection} + +For the purposes of keyboard navigation, \wmii\ keeps track of +which window is currently selected, and confers its titlebar a +different color scheme from the other windows. This window is +the basis of relative motion commands, such as “select the +window to the left”, and the target of commands such as “close +this window”. Normally, the selected window is the same as the +focused window, i.e., the window that receives keyboard events. +Some applications, however, present strange corner cases. + +\begin{description} + \item[Focused, selected window] This is the normal case of a + window which is both selected and has the keyboard focus. + \titlebar{selected} + \item[Unfocused, unselected window] This is the normal case for an + unselected window which does not have the keyboard focus. + \titlebar{unselected} + \item[Unfocused, selected window] This is the first unusual + case. This is the selected window, for the purposes of + keyboard navigation, but it does not receive keyboard events. + A good example is an onscreen keyboard, which will receive + mouse clicks and translate them to keyboard events, but + won't absorb those keyboard events itself. Other examples + include any window whilst another (such as \wimenu) has + grabbed the keyboard. + \titlebar{unfocused} + \item[Focused, unselected window] This is the second unusual + focus case. The window has the keyboard focus, but for the + purposes of keyboard navigation, it is not considered + selected. In the case of an onscreen keyboard, this is the + window which will receive the generated events. In the case + of a keyboard grab, the will likely be the window holding + the grab. + \titlebar{focused} +\end{description} + +\section{Running Programs} + +You've already seen the convenient key binding to launch a +terminal, but what about other programs? To get a menu of all of +the executables in your path, type <M-p>. This should replace +the bar at the bottom of the screen with a prompt, followed by a +string of completions. Start typing the name of a program that +you want to open. You can press <Tab> and <S-Tab> to cycle +through the completions, or you can just press <Return> to +select the first one. If you want to execute a more complex +command, just type it out and press <Return>. If you want to +recall that command later, use \wimenu's history. Start typing +the command you want and then press <C-p> until you come to it. + +When you're done with a program, you'll probably want an easy +way to close it. The first way is to ask the program to close +itself. Since that can be tedious (and sometimes impossible), +\wmii\ provides other ways. As mentioned, you can right click +the titlebar and select |Delete|. If you're at the keyboard, +you can type <M-S-c>. These two actions cause \wmii\ to ask +nicely that the program exit. In those sticky cases where the +program doesn't respond, \wmii\ will wait 10 seconds before +prompting you to kill the program. If you don't feel like +waiting, you can select |Kill| from the window's titlebar +menu, in which case \wmii\ will forcefully and immediately kill +it. Beware, killing clients is a last resort. In cases where the +same program opens multiple windows, killing one will kill them +all—without warning. + +\section{Using Views} + +As already noticed, \wmii's concept of virtual workspaces is +somewhat unique, so let's begin exploring it. Open up a terminal +and press <M-S-2>. You should see a new button on the bar at the +bottom of the screen. When you click it, you should see your +original terminal. Press <M-1> to come back here. Now, press +<M-3>, and <M-1> again to return here once more. Notice that the +views were created when needed, and destroyed when no longer +necessary. If you want to select a view with a proper name, use +<M-t> and enter the name. Other than the dynamic creation of +views, this is still similar to the familiar X11 workspace +model. But that's just the beginning of \wmii's model. Open a new +terminal, and type: + +\begin{code} + echo ‘Hello world!’ +\end{code} + +\noindent Now, type <M-S-t>. In the menu that appears, enter +|1+2+3|. Now, visit the views |1|, |2|, and |3|, and you'll see +the client on each. To remove a tag, type <M-S-t> again, and +this time enter |-2|. You'll notice that the client is no longer +on the |2| view. Finally, tag names needn't be discrete, +ordinary strings. They can also be regular expressions. Select +the terminal again, and enter |+/^5/|. Now, switch to the |5| +view. Now try the |6| view. Finally, type <M-t> and enter |50| +to check the |50| view. Clients tagged with regular expressions +are attached to any matching views when they're created. So, +when you switch to an empty view, or tag a client with a new +tag, any clients with matching regular expressions are +automatically added to it. When all explicitly tagged clients +disappear from the view, and it's no longer visible, clients +held there by regular expressions are automatically removed. + +\section{Learning More} + +For full tables of the standard key bindings, and descriptions +of the precise semantics of the topics discussed above, you +should refer to \wmii's |man| pages. + diff --git a/doc/introduction.tex b/doc/introduction.tex @@ -0,0 +1,166 @@ +\chapter{Introduction} + +\wmii\ is a simple but powerful window manager for the X Window +System. It provides both the classic (“floating”) and tiling +(“managed”) window management paradigms, which is to say, it does +the job of managing your windows, so you don't have to. It also +provides programability by means of a simple file-like +interface, which allows the user to program in virtually any +language he chooses. These basic features have become +indispensable to the many users of \wmii\ and other similar +window managers, but they come at a cost. Though our penchant +for simplicity makes \wmii's learning curve significantly +shorter than most of its competitors, there's still a lot to +learn. The rest of this guide will be devoted to familiarizing +new users with \wmii's novel features and eccentricities, as +well as provide advanced users with an in-depth look at our +customization facilities. + +\section{Concepts} + +As noted, \wmii\ provides two management styles: + +\begin{description} + \item[Managed] This is the primary style of window management + in \wmii. Windows managed in this style are automatically + arranged by \wmii\ into columns. Columns are created and + destroyed on demand. Individual windows in the column may be + moved or resized, and are often collapsed or hidden + entirely. Ad-hoc stacks of collapsed and uncollapsed windows + allow the user to efficiently manage their tasks. When + switching from an active to a collapsed window, the active + window collapses and the collapsed one effectively takes + its place. + + Managed windows have an unadorned titlebar: + + \titlebar{managed} + + \item[Floating] Since some programs aren't designed in ways + conducive to the managed work flow, \wmii\ also provides the + classic “floating” window management model. Windows managed + in this model float above the managed windows and may be moved + freely about. Other than automatic placement of new windows + and snapping of edges, \wmii\ doesn't manage floating + windows at all. + + Floating windows are indicated by a decorated titlebar: + + \titlebar{floating} + + \item[Fullscreen] Fullscreen mode is actually a subset of the + floating style. Windows may be toggled to and from + fullscreen mode at will. When fullscreen, windows reside in + the floating layer, above the managed windows. They have no + borders or titlebars, and occupy the full area of the + screen. Other than that, however, they're not special in any + way. Other floating windows may appear above them and the + user can still select, open, and close other windows at + will. +\end{description} + +\subsection{The Filesystem} + +All of \wmii's customization is done via a virtual filesystem. +Since the filesystem is implemented in the standardized \ninep\ +protocol, it can be accessed in many ways. \wmii\ provides a +simple command-line client, \wmiir, but many alternatives exist, +including libraries for Python, Perl, Ruby, PHP, and C. It can +even be mounted, either by Linux's 9p.ko kernel module or +indirectly via FUSE. + +The filesystem that \wmii\ provides is “virtual”, which is to +say that it doesn't reside on disk anywhere. In a sense, it's a +figment of \wmii's imagination. Files, when read, represent +\wmii's current configuration or state. When written, they +perform actions, update the UI, etc. For instance, the directory +|/client/| contains a directory for each window that \wmii\ +is currently managing. Each of those directories, in turn, +contains files describing the client's properties (its title, +its views\footnote{Views in \wmii\ are akin to workspaces or +virtual desktops in other window managers, but with some subtle +differences.}, its state). Most files can be written to update +the state they describe. For instance, +|/client/sel/ctl| describes the state of the selected +client. If a client is fullscreen, it contains the line: + +\begin{code} + fullscreen on +\end{code} + +\noindent To change this, you'd update the file with the line +% XXX: Line broken at /ctl cmd. +|fullscreen off| or even |fullscreen| |toggle| to toggle +the client's fullscreen state. + +The concept of controlling a program via a filesystem derives +from \plannine, where such interfaces are extensive and well +proven\footnote{The concept has also taken hold on most Unixes +in the form of \texttt{/proc} and \texttt{/sys} virtual +filesystems, but tends to be very kernel-centric. On \plannine, +where the model is more pervasive, there are more virtual +filesystems for user-level applications than for the kernel.}. +The metaphor has shown itself to be quite intuitive to Unix +users, once the shock of a “virtual” filesystem wears off. The +flexibility of being able to control \wmii\ from myriad +programming languages, including the standard Unix shell and +even from the command line, is well worth the shock. + +\subsection{Views and Tags} + +Like most X11 window managers, \wmii\ provides virtual +workspaces. Unlike other window managers though, \wmii's +workspaces are created and destroyed on demand. Instead of being +sent to a workspace, windows in \wmii\ are tagged with any +number of names. Views are created dynamically from these tags, +and automatically if the user tries to access them. For +instance, if a window is given the tags ‘foo’ and ‘bar’, the two +views ‘foo’ and ‘bar’ are created, if they don't already exist. +The window is now visible on both of them. Moreover, tags can be +specified as regular expressions. So, a client tagged with {\tt +\verb+/^foo/+} will appear on any view named ‘foo’, ‘foo:bar’, +and so forth. Any time a client is tagged with a matching tag, +or the user opens a matching view, the window is automatically +added to it. + +\subsection{The Bar} + +\wmii\ provides a general purpose information bar at the top or +bottom of the screen. The bar is divided into a left and a right +section. Each section is made up of buttons, with a single +button spanning the gap between the two sides. Buttons can be +individually styled and can hold any text content the user +wishes. By convention, the buttons to the left show view names, +and those to the right display status information. + +\subsection{The Menus} + +\wmii\ includes two simple, external menu programs. The first, +\wimenu, is keyboard-based, and is used to launch programs and +generally prompt the user for input. It provides a list of +completions which are automatically filtered as you type. The +second, \wiIXmenu, is mouse-based, and is generally used to +provide context menus for titlebars and view buttons. Both menus +can be easily launched from shell scripts or the command line, +as well as from more complex scripting languages. + +\subsection{The Keyboard} + +\wmii\ is a very keyboard friendly window manager. Most actions +can be performed without touching the mouse, including +launching, closing, moving, resizing, and selecting programs. +New keybindings of any complexity can easily be added to handle +any missing functionality, or to simplify any repetitive tasks. + +\subsection{The Mouse} + +Despite being highly keyboard-accessible, \wmii\ strives to be +highly mouse accessible as well. Windows can be moved or resized +by dragging their window borders. When combined with a key +press, they can be moved, resized, or raised by dragging any +visible portion of the window. Mouse menus are accessed with a +single click and drag. View buttons in the bar and client +titlebars respond to the mouse wheel; view buttons can be +activated by dragging any draggable object (e.g., a file from a +file manager) over them. + diff --git a/doc/license.tex b/doc/license.tex @@ -0,0 +1,29 @@ +\chapter*{License} + +This file is distributed under the same terms as wmii: + +\begingroup +\ttfamily +\parindent=0pt +\parskip=1em + +Copyright © 2009-2010 Kris Maglione <\href{mailto:maglione.k@gmail.com}{maglione.k@gmail.com}> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +\endgroup diff --git a/doc/wmii.tex b/doc/wmii.tex @@ -23,6 +23,7 @@ \let\primary=\textbf \setmainfont[Mapping=tex-text, Numbers=OldStyle]{Palatino LT Std} +\def\lining{\addfontfeature{Numbers=Lining}} \let\primary=\textbf @@ -34,7 +35,7 @@ \makeatletter %% Key specs -\def\key#1{{\small$\langle$\addfontfeature{Numbers=Lining}#1\/$\rangle$}} +\def\key#1{{\small$\langle$\lining#1\/$\rangle$}} \let\<=< \catcode`\<=\active \def<#1>{\key{#1}} @@ -72,17 +73,14 @@ % Display |...| as verbatim, teletype text. \DefineShortVerb{\|} +\def\macroname#1{% + \expandafter\@macroname\string#1} +\def\@macroname#1{} +\def\defverb#1{% + \EA\def\EA#1\EA{\EA\protect\EA\UseVerb\EA{\macroname#1}}% + \EA\SaveVerb\EA{\macroname#1}} + \let\idx@@heading\chapter -\def\:{:} -\iffalse - \catcode`\:=\active - \gdef:{\@ifnextchar:{\coloncoloneq}{\:}} - \gdef\coloncoloneq#1{\@ifnextchar={$\Coloneqq$\coloncoloneqq}{\:\:}} - \gdef\coloncoloneqq#1{} -\fi -\def\≔{≔} -\catcode`\≔=\active -\def≔{\ensuremath{\Coloneqq}} %% Create a verbatim {code} environment which highlights strings %% and comments. Several unicode characters are hacked to replace @@ -92,24 +90,30 @@ \colorlet{string}{red!100!black!90} \let\‘=‘ \let\“=“ -\catcode`¶=6 -\catcode`#=\active\let#=\# -\catcode`\#=\active -\catcode`“=\active -\catcode`‘=\active -\def“¶1”{{\color{string}\“¶1”}}% -\def‘¶1’{{\color{string}\‘¶1’}}% -\def\comment{\itshape\color{comment}\let“=\“\let‘=\‘\#} -\def\docodes{\catcode`\#=\active\catcode`“=\active\catcode`‘=\active\catcode`\☺=0} -\def\dodefineactive{ - \let#=\comment - } +\def\≔{≔} +\catcode`#=\active +\catcode`\≔=\active +\def\docodes{% + \catcode`\#=\active% + \catcode`“=\active% + \catcode`‘=\active} + +\def≔{\ensuremath{\Coloneqq}} +\let#=\# +\begingroup + \docodes + \catcode`\#=\active% + \catcode`¶=6 + \gdef\comment{\itshape\color{comment}\let“=\“\let‘=\‘\#} + \gdef\dodefineactive{% + \let#=\comment% + \gdef“¶¶1”{{\color{string}\“¶¶1”}}% + \gdef‘¶¶1’{{\color{string}\‘¶¶1’}}} +\endgroup + \DefineVerbatimEnvironment{code}{Verbatim}{xleftmargin=2em,gobble=2,% - codes={\docodes},% + codes={\docodes\catcode`\☺=0},% defineactive={\dodefineactive}} -\catcode`\#=6 -\catcode`“=12 -\catcode`‘=12 %% Save code fragments for piecing together later \begingroup @@ -143,7 +147,6 @@ \def\UseFragment#1#2{ \begingroup - % \message{UseFragment #2^^J} \EA\let\EA\a\csname SV@#2\endcsname \ifx\a\undefined\def\a{\ldots}\fi \ifx\FV@EnvironName\relax% @@ -152,19 +155,26 @@ \newtoks\tokens \EA\tokens\EA{\a} \everyeof{\noexpand}% - % \EA\message\EA{\the\tokens} \scantokens\EA{\the\tokens} \endgroup } %% Convenience defs for the various wmii commands, and a few %% others. -\def\wmii{\texttt{wmii}} -\def\wiIXmenu{\texttt{wi9menu}} -\def\wimenu{\texttt{wimenu}} -\def\wmiir{\texttt{wmiir}} -\def\ninep{{\addfontfeature{Numbers=Lining}9P}} +\defverb\wmii|wmii| +\defverb\wiIXmenu|wimii9menu| +\defverb\wimenu|wimenu| +\defverb\wmiir|wmiir| +\def\ninep{{\lining 9P}} \def\POSIX{\textsc{POSIX}} +\def\plannine{{\lining Plan 9}} +\def\ICCCM#1{% + \@ICCCM#1@ + \href{http://www.tronche.com/gui/x/icccm/sec-\@ICCCM@chap.html\#s-#1}{% + ICCCM \lining§#1}} +\def\@ICCCM#1.#2@{\def\@ICCCM@chap{#1}} + +\makeatother \begin{document} \thispagestyle{empty} @@ -183,7 +193,7 @@ \Large Kris Maglione \\[1em] - \addfontfeature{Numbers=Lining} + \lining 13 October 2009 \end{center} @@ -197,1432 +207,14 @@ \tableofcontents \newpage -\chapter*{License} - -This file is distributed under the same terms as wmii: -\begingroup -\ttfamily -\parindent=0pt -\parskip=1em - -Copyright © 2009 Kris Maglione <\href{mailto:maglione.k@gmail.com}{maglione.k@gmail.com}> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -\endgroup +\include{license} \mainmatter -\chapter{Introduction} - -\wmii\ is a simple but powerful window manager for the X Window -System. It provides both the classic (“floating”) and tiling -(“managed”) window management paradigms, which is to say, it does -the job of managing your windows, so you don't have to. It also -provides programability by means of a simple file-like -interface, which allows the user to program in virtually any -language he chooses. These basic features have become -indispensable to the many users of \wmii\ and other similar -window managers, but they come at a cost. Though our penchant -for simplicity makes \wmii's learning curve significantly -shorter than most of its competitors, there's still a lot to -learn. The rest of this guide will be devoted to familiarizing -new users with \wmii's novel features and eccentricities, as -well as provide advanced users with an in-depth look at our -customization facilities. - -\section{Concepts} - -As noted, \wmii\ provides two management styles: - -\begin{description} - \item[Managed] This is the primary style of window management - in \wmii. Windows managed in this style are automatically - arranged by \wmii\ into columns. Columns are created and - destroyed on demand. Individual windows in the column may be - moved or resized, and are often collapsed or hidden - entirely. Ad-hoc stacks of collapsed and uncollapsed windows - allow the user to efficiently manage their tasks. When - switching from an active to a collapsed window, the active - window collapses and the collapsed one effectively takes - its place. - - Managed windows have an unadorned titlebar: - - \titlebar{managed} - - \item[Floating] Since some programs aren't designed in ways - conducive to the managed work flow, \wmii\ also provides the - classic “floating” window management model. Windows managed - in this model float above the managed windows and may be moved - freely about. Other than automatic placement of new windows - and snapping of edges, \wmii\ doesn't manage floating - windows at all. - - Floating windows are indicated by a decorated titlebar: - - \titlebar{floating} - - \item[Fullscreen] Fullscreen mode is actually a subset of the - floating style. Windows may be toggled to and from - fullscreen mode at will. When fullscreen, windows reside in - the floating layer, above the managed windows. They have no - borders or titlebars, and occupy the full area of the - screen. Other than that, however, they're not special in any - way. Other floating windows may appear above them and the - user can still select, open, and close other windows at - will. -\end{description} - -\subsection{The Filesystem} - -All of \wmii's customization is done via a virtual filesystem. -Since the filesystem is implemented in the standardized \ninep\ -protocol, it can be accessed in many ways. \wmii\ provides a -simple command-line client, \wmiir, but many alternatives exist, -including libraries for Python, Perl, Ruby, PHP, and C. It can -even be mounted, either by Linux's 9p.ko kernel module or -indirectly via FUSE. - -The filesystem that \wmii\ provides is “virtual”, which is to -say that it doesn't reside on disk anywhere. In a sense, it's a -figment of \wmii's imagination. Files, when read, represent -\wmii's current configuration or state. When written, they -perform actions, update the UI, etc. For instance, the directory -|/client/| contains a directory for each window that \wmii\ -is currently managing. Each of those directories, in turn, -contains files describing the client's properties (its title, -its views\footnote{Views in \wmii\ are akin to workspaces or -virtual desktops in other window managers, but with some subtle -differences.}, its state). Most files can be written to update -the state they describe. For instance, -|/client/sel/ctl| describes the state of the selected -client. If a client is fullscreen, it contains the line: - -\begin{code} - fullscreen on -\end{code} - -\noindent To change this, you'd update the file with the line -% XXX: Line broken at /ctl cmd. -|fullscreen off| or even |fullscreen| |toggle| to toggle -the client's fullscreen state. - -The concept of controlling a program via a filesystem derives -from Plan 9, where such interfaces are extensive and well -proven\footnote{The concept has also taken hold on most Unixes -in the form of \texttt{/proc} and \texttt{/sys} virtual -filesystems, but tends to be very kernel-centric. On Plan 9, -where the model is more pervasive, there are more virtual -filesystems for user-level applications than for the kernel.}. -The metaphor has shown itself to be quite intuitive to Unix -users, once the shock of a “virtual” filesystem wears off. The -flexibility of being able to control \wmii\ from myriad -programming languages, including the standard Unix shell and -even from the command line, is well worth the shock. - -\subsection{Views and Tags} - -Like most X11 window managers, \wmii\ provides virtual -workspaces. Unlike other window managers though, \wmii's -workspaces are created and destroyed on demand. Instead of being -sent to a workspace, windows in \wmii\ are tagged with any -number of names. Views are created dynamically from these tags, -and automatically if the user tries to access them. For -instance, if a window is given the tags ‘foo’ and ‘bar’, the two -views ‘foo’ and ‘bar’ are created, if they don't already exist. -The window is now visible on both of them. Moreover, tags can be -specified as regular expressions. So, a client tagged with {\tt -\verb+/^foo/+} will appear on any view named ‘foo’, ‘foo:bar’, -and so forth. Any time a client is tagged with a matching tag, -or the user opens a matching view, the window is automatically -added to it. - -\subsection{The Bar} - -\wmii\ provides a general purpose information bar at the top or -bottom of the screen. The bar is divided into a left and a right -section. Each section is made up of buttons, with a single -button spanning the gap between the two sides. Buttons can be -individually styled and can hold any text content the user -wishes. By convention, the buttons to the left show view names, -and those to the right display status information. - -\subsection{The Menus} - -\wmii\ includes two simple, external menu programs. The first, -\wimenu, is keyboard-based, and is used to launch programs and -generally prompt the user for input. It provides a list of -completions which are automatically filtered as you type. The -second, \wiIXmenu, is mouse-based, and is generally used to -provide context menus for titlebars and view buttons. Both menus -can be easily launched from shell scripts or the command line, -as well as from more complex scripting languages. - -\subsection{The Keyboard} - -\wmii\ is a very keyboard friendly window manager. Most actions -can be performed without touching the mouse, including -launching, closing, moving, resizing, and selecting programs. -New keybindings of any complexity can easily be added to handle -any missing functionality, or to simplify any repetitive tasks. - -\subsection{The Mouse} - -Despite being highly keyboard-accessible, \wmii\ strives to be -highly mouse accessible as well. Windows can be moved or resized -by dragging their window borders. When combined with a key -press, they can be moved, resized, or raised by dragging any -visible portion of the window. Mouse menus are accessed with a -single click and drag. View buttons in the bar and client -titlebars respond to the mouse wheel; view buttons can be -activated by dragging any draggable object (e.g., a file from a -file manager) over them. - -\chapter{Getting Started} - -This section will walk you through your first \wmii\ startup. -For your first experience, we recommend running \wmii\ in its -own X session, so you can easily switch back to a more -comfortable environment if you get lost. Though you may start -\wmii\ from a session manager in your day to day use, these -instructions will use |xinit|. To begin with, copy this file -to your home directory, so we can open it in your new X session. -Then setup your |~/.xinitrc| as follows: - -\begin{code} - cd - - # Start a PDF viewer with this guide. Use any viewer - # you're comfortable with. - xpdf wmii.pdf & - - # Launch wmii - exec wmii - - # That was easy. -\end{code} - -Before you run |xinit|, make sure you know how to switch -between terminals. Depending on your system, your current X -session is probably on terminal 5 or 7. You should be able to -switch between your terminals by pressing -Ctrl-Alt-F$\langle n\rangle$. Assuming that your current X -session is on terminal 7, you should be able to switch between -it and your new session by pressing Ctrl-Alt-F7 and Ctrl-Alt-F8. -Now you should be ready to start \wmii. When you run the -following command, you should be presented with a new X session -running wmii and a PDF viewer showing this document. - -\begin{code} - xinit -\end{code} - -When you're there, find this page in the new PDF viewer and -continue. - -\section{Your First Steps} - -If everything went according to plan, you should be viewing this -from a nearly empty \wmii\ session. We're going to be using the -keyboard a lot, so let's start with a convention for key -notation. We'll be using the key modifiers Control, Alt, Shift, -and Meta\footnote{The Windows$^{\mbox{\tiny®}}$ key on most -keyboards. The Penguin key, on the more tongue in cheek -varieties.}, which we'll specify as C-, A-, S-, and M-, -respectively. So, <C-S-a> means pressing ‘|a|’ while holding -|Control| and |Shift|. We'll also express mouse clicks this -way, with <M-Mouse1> signifying a press of the right mouse -button, with the Meta key depressed. Buttons 4 and 5 are the up -and down scroll wheel directions, respectively. - -\subsection{Floating Mode} - -Beginning with what's familiar to most users, we'll first explore -floating mode. First, we need to select the floating layer. -Press <M-Space>. You should see the titlebar of this window -change color. Now, press <M-Return> to launch a terminal. -The easiest way to drag the terminal around is to press and hold -<M-Mouse1> over the window and simply drag the window -around. You should be able to drag the window anywhere onscreen -without ever releasing the mouse button. As you drag near the -screen edges, you should notice a snap. If you try to drag the -window fully off-screen, you'll find it constrained so that a -portion always remains visible. Now, release the window and move -the mouse toward one of its corners. Press and hold -<M-Mouse3>\footnote{The right button.}. As you drag the -mouse around, you should see the window resized accordingly. - -To move the window without the modifier key, move the pointer -over the layout box to the left of its titlebar. You should see -the cursor change. Now, simply click and drag. To resize it, -move the pointer toward the window's edge until you see the -cursor change, and again, click and drag. Now, to close the -window, move the mouse over the windows titlebar, press and hold -<Mouse3>, select |Delete|, and release it. You should -see this window's titlebar return to its original color, -indicating that it's regained focus. - -\subsection{Managed Mode} - -Now, for the fun part. We'll start exploring managed mode by -looking at the basics of columns. In the default configuration, -columns have three modes: - -\begin{description} - \item[Stack] <M-s> The default mode for new columns. Only one window - is fully visible per column at once. The others only display - their title bars. When new windows are added to the column, - the active window collapses, and the new one takes its - place. Whenever a collapsed client is selected, the active - window is collapsed to take its place. - \item[Max] <M-m> Like stack mode, but the titlebars of collapsed - clients are hidden. - \item[Default] <M-d> Multiple uncollapsed windows may be visible at - once. New windows split the space with the other uncollapsed - windows in their vicinity. Windows may still be collapsed by - shrinking them to the size of their titlebars. At this - point, the behavior of a stack of collapsed and uncollapsed - clients is similar to that of stack mode. -\end{description} - -Before we open any new windows in managed mode, we need to -explore the column modes a bit. Column modes are activated with -the key bindings listed above. This column should be in stack -mode now. Watch the right side of the titlebar as you press -<M-m> to enter max mode. You should see an indicator appear. -This tells you the number of hidden windows directly above and -below the current window, and its position in that stack. Press -<M-d> to enter default mode. Now we're ready to open another -client. Press <M-Return> to launch another terminal. Now, -press <M-S-l> to move the terminal to a new column to the -right of this one. Once it's there, press <M-Return> two -more times to launch two more terminals. Now that you have more -than one window in a column, cycle through the three column -modes again until they seem familiar. - -\subsection{Keyboard Navigation} - -To begin, switch back to default mode. The basic keyboard -navigation keys, <M-h>, <M-j>, <M-k>, and <M-l>, -derive from vi, and represent moving left, down, up, and right -respectively. Try selecting each of the four windows currently -visible on screen. Notice that navigation wraps from one side of -the screen to the other, and from the top to the bottom. Now, -return to the write column, switch to stack mode, and select -each of the three terminals again. Do the same in max mode, -paying careful attention to the indicator to the right of the -titlebar. - -Now that you can select windows, you'll want to move them -around. To move a window, just add the Shift key to the -direction keys. So, to move a window left, instead of <M-h>, -type <M-S-h>. Now, experiment with moving windows, just as -you did with navigating them, in each of the three column modes. -Once you're comfortable with that, move a window to the floating -layer. Since we toggled between the floating and managed layers -with <M-Space>, we'll move windows between them with -<M-S-Space>. Try moving some windows back and forth until it -becomes familiar. Now, move several windows to the floating -layer and try switching between them with the keyboard. You'll -notice that <M-h> and <M-l> don't function in the -floating layer. This is for both historical and logistical -reasons. <M-j> and <M-k> cycle through floating windows -in order of their most recent use. - -\subsection{Mouse Navigation} - -\wmii\ uses the “sloppy focus” model, which is to say, it focuses -windows when the mouse enters them and when you click them. It -focuses windows only when you select them with the keyboard, -click their titlebars, or press click them with <M-Mouse2>. -Collapsed windows may be opened with the mouse by clicking their -titlebars. Moving and resizing floating windows should be -largely familiar, and has already been covered. The same can't -be said for managed windows. - -Let's begin working with the mouse in the managed layer. Return -to a layout with this document in a column on the left, and -three terminals in a column to the right. Switch the right -column to default mode. Now, bring the mouse to the top of the -third terminal's titlebar until you see a resize cursor. Click -and drag the titlebar to the very top of the screen. Now, move -the cursor to the top of the second terminal's titlebar and drag -it to the very bottom of the screen. Press <M-d> to restore the -terminals to their original sizes. Now, click and hold the -layout box of the second terminal. Drag it to the middle of the -terminal's window and release. Click and hold the layout box of -the third terminal and drag it to the middle of the first -terminal's window. Finally, drag the first terminal's layout box -to halfway down this window. <M-Mouse1> works to the same -effect as dragging the layout box, but allows you to click -anywhere in the window. - -Now that you've seen the basics of moving and dragging windows, -let's move on to columns. Click and drag the border between the -two columns. If that's a difficult target to click, there's a -triangle at the top of the division between the two columns that -you can click and drag as well. If that's still too hard a -target, try using <M-Mouse3>, which works anywhere and provides -much richer functionality. - -\subsection{Window Focus and Selection} - -For the purposes of keyboard navigation, \wmii\ keeps track of -which window is currently selected, and confers its titlebar a -different color scheme from the other windows. This window is -the basis of relative motion commands, such as “select the -window to the left”, and the target of commands such as “close -this window”. Normally, the selected window is the same as the -focused window, i.e., the window that receives keyboard events. -Some applications, however, present strange corner cases. - -\begin{description} - \item[Focused, selected window] This is the normal case of a - window which is both selected and has the keyboard focus. - \titlebar{selected} - \item[Unfocused, unselected window] This is the normal case for an - unselected window which does not have the keyboard focus. - \titlebar{unselected} - \item[Unfocused, selected window] This is the first unusual - case. This is the selected window, for the purposes of - keyboard navigation, but it does not receive keyboard events. - A good example is an onscreen keyboard, which will receive - mouse clicks and translate them to keyboard events, but - won't absorb those keyboard events itself. Other examples - include any window whilst another (such as \wimenu) has - grabbed the keyboard. - \titlebar{unfocused} - \item[Focused, unselected window] This is the second unusual - focus case. The window has the keyboard focus, but for the - purposes of keyboard navigation, it is not considered - selected. In the case of an onscreen keyboard, this is the - window which will receive the generated events. In the case - of a keyboard grab, the will likely be the window holding - the grab. - \titlebar{focused} -\end{description} - -\section{Running Programs} - -You've already seen the convenient key binding to launch a -terminal, but what about other programs? To get a menu of all of -the executables in your path, type <M-p>. This should replace -the bar at the bottom of the screen with a prompt, followed by a -string of completions. Start typing the name of a program that -you want to open. You can press <Tab> and <S-Tab> to cycle -through the completions, or you can just press <Return> to -select the first one. If you want to execute a more complex -command, just type it out and press <Return>. If you want to -recall that command later, use \wimenu's history. Start typing -the command you want and then press <C-p> until you come to it. - -When you're done with a program, you'll probably want an easy -way to close it. The first way is to ask the program to close -itself. Since that can be tedious (and sometimes impossible), -\wmii\ provides other ways. As mentioned, you can right click -the titlebar and select |Delete|. If you're at the keyboard, -you can type <M-S-c>. These two actions cause \wmii\ to ask -nicely that the program exit. In those sticky cases where the -program doesn't respond, \wmii\ will wait 10 seconds before -prompting you to kill the program. If you don't feel like -waiting, you can select |Kill| from the window's titlebar -menu, in which case \wmii\ will forcefully and immediately kill -it. Beware, killing clients is a last resort. In cases where the -same program opens multiple windows, killing one will kill them -all—without warning. - -\section{Using Views} - -As already noticed, \wmii's concept of virtual workspaces is -somewhat unique, so let's begin exploring it. Open up a terminal -and press <M-S-2>. You should see a new button on the bar at the -bottom of the screen. When you click it, you should see your -original terminal. Press <M-1> to come back here. Now, press -<M-3>, and <M-1> again to return here once more. Notice that the -views were created when needed, and destroyed when no longer -necessary. If you want to select a view with a proper name, use -<M-t> and enter the name. Other than the dynamic creation of -views, this is still similar to the familiar X11 workspace -model. But that's just the beginning of \wmii's model. Open a new -terminal, and type: - -\begin{code} - echo ‘Hello world!’ -\end{code} - -\noindent Now, type <M-S-t>. In the menu that appears, enter -|1+2+3|. Now, visit the views |1|, |2|, and |3|, and you'll see -the client on each. To remove a tag, type <M-S-t> again, and -this time enter |-2|. You'll notice that the client is no longer -on the |2| view. Finally, tag names needn't be discrete, -ordinary strings. They can also be regular expressions. Select -the terminal again, and enter |+/^5/|. Now, switch to the |5| -view. Now try the |6| view. Finally, type <M-t> and enter |50| -to check the |50| view. Clients tagged with regular expressions -are attached to any matching views when they're created. So, -when you switch to an empty view, or tag a client with a new -tag, any clients with matching regular expressions are -automatically added to it. When all explicitly tagged clients -disappear from the view, and it's no longer visible, clients -held there by regular expressions are automatically removed. - -\section{Learning More} - -For full tables of the standard key bindings, and descriptions -of the precise semantics of the topics discussed above, you -should refer to \wmii's |man| pages. - -\chapter{Customizing \wmii} - -There are several configuration schemes available for \wmii. If -you're only looking to add basic key bindings, status monitors, -\emph{et cetera}, you should have no trouble modifying the stock -configuration for your language of choice. If you're looking for -deeper knowledge of \wmii's control interface though, this -section is for you. We'll proceed by building a configuration -script in \POSIX\ |sh| syntax and then move on to a discussion -of the higher level constructs in the stock configuration -scripts. - -\section{Events} - -The \wmii\ control interface is largely event driven. Each event -is represented by a single, plain-text line written to the -|/event| file. You can think of this file as a named pipe. When -reading it, you won't receive an EOF\footnote{End of File} until -\wmii\ exits. Moreover, any lines written to the file will be -transmitted to everyone currently reading from it. Notable -events include key presses, the creation and destruction of -windows, and changes of focus and views. - -We'll start building our configuration with an event processing -framework: - -\begin{Fragment}{Event Loop} - # Broadcast a custom event - wmiir xwrite /event Start wmiirc - - # Turn off globbing - set -f - # Open /event for reading - wmiir read /event | - # Read the events line by line - while read line; do - # Split the line into words, store in $@ - set -- $line - event=$1; shift - line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)" - # Process the event - case $event in - Start) # Quit when a new instance starts - [ $1 = wmiirc ] && exit;; - «Event Handlers» - esac - done -\end{Fragment} - -Now, we need to consider which types of events we'll need to -handle: - -\begin{Fragment}{Event Handlers} - «View Button Events» - «Urgency Events» - «Unresponsive Clients» - «Notice Events» - «Key Events» - «Client Menu Events» - «Tag Menu Events» -\end{Fragment} - -\section{Bar Items} - -The bar is described by the files in the two directories |/lbar/| and -|/rbar/| for buttons on the left and right side of the bar, -respectively. The files act as control files (section -\ref{sec:controlfiles}) with the contents: - -\begin{code} - color ‹Color Tuple› - label ‹Label› -\end{code} - -A ‹Color Tuple› is defined as: - -\begin{code} - ‹Color Tuple› ≔ ‹foreground color› ‹background color› ‹border color› - ‹* Color› ≔ ‹RGB color› | ‹RGBA color› - ‹RGB color› ≔ #‹6 character RGB hex color code› - ‹RGBA color› ≔ rgba:‹red›/‹green›/‹blue›/‹alpha› -\end{code} - -\noindent -where all of the colors are represented as lowercase, -hexidecimal values. In the case of RGBA colors, they may be 1--4 -characters long, though they will be standardized internally to -2 characters. - -\medskip - -Let's define our basic theme information now: - -\begin{Fragment}{Theme Definitions} - normcolors=‘#000000 #c1c48b #81654f’ - focuscolors=‘#000000 #81654f #000000’ - background=‘#333333’ - font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’ -\end{Fragment} - -\subsection{View Buttons} - -With a basic understanding of bar items in mind, we can write -our view event handlers: - -\index{events!CreateTag} -\index{events!DestroyTag} -\index{events!FocusTag} -\index{events!UnfocusTag} -\begin{Fragment}{View Button Events} - CreateTag) # CreateTag ‹Tag Name› - echo $normcolors $1 | wmiir create /lbar/$1;; - DestroyTag) # DestroyTag ‹Tag Name› - wmiir rm /lbar/$1;; - FocusTag) # FocusTag ‹Tag Name› - wmiir xwrite /lbar/$1 $focuscolors $1;; - UnfocusTag) # UnfocusTag ‹Tag Name› - wmiir xwrite /lbar/$1 $normcolors $1;; -\end{Fragment} - -\subsection{Urgency} - -\index{events!UrgentTag|(} -\index{events!NotUrgentTag|(} -Windows can specify that they require attention, and in X11 -parlance, this is called urgency. When a window requests -attention as such, or declares that it's been satisfied, \wmii\ -broadcasts an event for the client and an event for each view -that it belongs to. It also fills in the layout box of any -client deemed urgent. It's the job of a script to decide how to -handle urgency events above and beyond that basic measure. The -standard scripts simply mark urgent views with an asterisk: - -\begin{Fragment}{Urgency Events} - # The urgency events are ‘Client’ events when the program - # owning the window sets its urgency state. They're ‘Manager’ - # events when wmii or the wmii user sets the state. - UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› - wmiir xwrite /lbar/$2 $2;; - NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› - wmiir xwrite /lbar/$2 $2;; -\end{Fragment} -\index{events!UrgentTag|)} -\index{events!NotUrgentTag|)} - -\subsection{Notices} - -The standard scripts provide a custom Notice event for -displaying status information. The events appear in the long bar -between the left and right sides for five seconds. - -\begin{Fragment}{Notice Events} - Notice) - wmiir xwrite /rbar/!notice $line - kill $xpid 2>/dev/null # Let's hope this isn't reused... - { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & - xpid = $!;; -\end{Fragment} - -\section{Keys} - -\label{sec:keybindings} -\index{key bindings} -\index{filesystem!/!keys} -\index{filesystem!/!event} -Now to the part you've no doubt been waiting for: binding keys. -When binding keys, you need to be aware of two files, |/keys| -and |/event|. The former defines which keys \wmii\ needs to -grab, and the latter broadcasts the events when they're pressed. - -Key names are specified as a series of modifiers followed by a -key name, all separated by hyphens. Valid modifier names are -|Control|, |Shift|, |Mod1| (usually Alt), |Mod2|, |Mod3|, |Mod4| -(usually the Windows® key), and |Mod5|. Modifier keys can be -changed via |xmodmap(1)|, the details of which are beyond the -scope of this document. - -Key names can be detected by running |xev| from a -terminal, pressing the desired key, and looking at the output -(it's in the parentheses, after the keysym). Or, more simply, -you can run the \man 1 {wikeyname} utility bundled with \wmii\ -and press the key you wish to bind. - -Examples of key bindings: - -\begin{description} - \item[Windows® key + Capital A] |Mod4-Shift-A| - \item[Control + Alt + Space] |Mod1-Control-Space| -\end{description} - -Now, let's bind the keys we plan on using: - -\begin{Fragment}{Bind Keys} - { - cat <<! - Mod4-space - Mod4-d - Mod4-s - Mod4-m - Mod4-a - Mod4-p - Mod4-t - Mod4-Return - Mod4-Shift-space - Mod4-f - Mod4-Shift-c - Mod4-Shift-t - Mod4-h - Mod4-j - Mod4-k - Mod4-l - Mod4-Shift-h - Mod4-Shift-j - Mod4-Shift-k - Mod4-Shift-l - ! - for i in 1 2 3 4 5 6 7 8 9 0; do - echo Mod4-$i - echo Mod4-Shift-$i - done - } | wmiir write /keys -\end{Fragment} - -and lay a framework for processing their events: - -\begin{Fragment}{Key Events} - Key) # Key ‹Key Name› - case $1 in - «Motion Keys» - «Client Movement Keys» - «Column Mode Keys» - «Client Command Keys» - «Command Execution Keys» - «Tag Selection Keys» - «Tagging Keys» - esac;; -\end{Fragment} - -\section{Click Menus} - -Sometimes, you have your hand on the mouse and don't want to -reach for the keyboard. To help cope, \wmii\ provides a -mouse-driven, single-click menu. The default configuration uses -it for client and tag menus. - -\begin{Fragment}{Click Menu Initialization} - clickmenu() { - if res=$(wmii9menu -- “$@”); then eval “$res”; fi - } -\end{Fragment} - -\section{Control Files} - -\label{sec:controlfiles} - -Several directories including the root, have control files, -named |ctl|. These files are used to control the object (e.g., a -client or tag) represented by the directory. Each line of the -file, with the possible section of the first, represents a -control variable and its value. In the case of all but the root -|/ctl| file, the first line represents the id of the directory. -In the case of |/tag/foo/ctl|, for instance, the first line -should read |foo|. This is useful when dealing with the special -|sel/| directories. For instance, when |foo| is the selected -tag, the special |/tag/sel| directory is a link to |/tag/foo|, -and the first line of |/tag/sel/ctl| will read |foo|, just as -if you'd accessed |/tag/foo/ctl| directly. - -The rest of the lines, the control variables, can be modified by -writing new values to the control file. For instance, if a -client is fullscreen, its control file will contain the line: - -\begin{code} - fullscreen on -\end{code} - -\noindent To restore the client from fullscreen, either of the -following lines may be written to its control file: - -\begin{code} - fullscreen off - fullscreen toggle -\end{code} - -When next read, the |fullscreen on| line will have been replaced -with |fullscreen off|. No care need be taken to preserve the -other contents of the file. They're generated anew each time -it's read. - -\section{Clients} - -\def\clientlabel{/client/$\langle\mathit{client}\rangle$/} -\index{filesystem!/client/*/@\clientlabel|(} -Clients are represented by directories under the |/client/| -tree. Subdirectory names represent the client's X11 window ID. -The special |sel/| directory represents the currently selected -client. The files in these directories are: - -\begin{description} - \item[ctl] The control file. The properties are: - \index{filesystem!/client/*/@\clientlabel!ctl} - \begin{description} - \item[allow] The set of unusual actions the client is - allowed to perform, in the same format as the tag set. - \begin{description} - \item[activate] The client is allowed to activate - itself—that is, focus its window and, as the case may - require, uncollapse it and select a tag it resides on. - This flag must be set on a client if you wish it able to - activate itself from the system tray. - \end{description} - \item[floating] Defines whether this client is likely to - float when attached to a new view. May be |on|, |off|, - |always|, or |never|. Ordinarilly, the value changes - automatically whenever the window is moved between the - floating and managed layers. However, setting a value of - |always| or |never| overrides this behavior. - \item[fullscreen] The client's fullscreen state. When - |on|, the client is displayed fullscreen on all of its - views. Possible values are |on|, |off|, and |toggle|. - \item[group] The client's group ID, or 0 if not part of a - group. Clients tend to open with the same tags and in - the same columns as the last active member of their - group. Setting this property is only useful when done - via the rules file. - \item[kill] When written, the window is closed politely, - if possible. - \item[pid] Read-only value of the PID of the program that - owns the window, if the value is available and the - process is on the same machine as wmii. - \item[slay] When written, the client is disconnected - peremptorily. If the client's PID is available and the - process is the same machine as wmii, its parent process - is killed - \item[tags] The client's tags. The same as the tags file. - \item[urgent] The client's urgency state. When |on|, the - client's layout box will be highlighted. Possible values - are |on|, |off|, and |toggle|. - \end{description} - \item[props] The client's window class (the X11 |WM_CLASS| - property) and title string, separated by colons. This file - is not writable. - \index{filesystem!/client/*/@\clientlabel!props} - \item[label] The client's window title. May be written to - change the client's title. - \index{filesystem!/client/*/@\clientlabel!label} - \item[tags] - \index{filesystem!/client/*/@\clientlabel!tags} - The client's tags. Tag names are separated by |+|, |-|, or - |^| signs. Tag names which directly follow a |+| sign are - added, while whose following a |-| sign are removed and - those following a |^| are toggled. If the value written - begins with one of these characters, the value is appended - to the clients tags rather than replacing them. - - Tags formatted as |/‹regex›/| are treated as regular - expressions, which place the client on any extant matching - tag\footnote{While a client with a regex tag will always - appear in all matching views, it will not keep those views - in existence. When the last client explicitly tagged with a - view is removed, the view is deleted as soon as it becomes - inactive.}. Regular expression tags which directly follow a - minus sign are treated as exclusion expressions. For - example, the tag string |+/foo/-/food/| will match the tag - |foobar|, but not the tag |foodstand|. -\end{description} - -\index{filesystem!/client/*/@\clientlabel|)} - -\subsection{Key Bindings} - -To control clients, we'll add the following key bindings: - -\begin{Fragment}{Client Command Keys} - Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;; - Mod4-f) wmiir xwrite /client/sel/ctl Fullscreen toggle;; -\end{Fragment} - -And to manage their tags, we'll need: - -\begin{Fragment}{Tagging Keys} - Mod4-Shift-t) - # Get the selected client's id - c=$(wmiir read /client/sel/ctl | sed 1q) - # Prompt the user for new tags - tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) - # Write them to the client - wmiir xwrite /client/$c/tags $tag;; - Mod4-Shift-[0-9]) - wmiir xwrite /client/sel/tags ${1##*-};; -\end{Fragment} - -\subsection{Click Menus} - -\index{events!ClientMouseDown} -\begin{Fragment}{Client Menu Events} - ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button› - [ $2 = 3 ] && clickmenu \ - “Delete:wmiir xwrite /client/$1/ctl kill” \ - “Kill: wmiirxwrite /client/$1/ctl slay” \ - “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on” -\end{Fragment} - -\subsection{Unresponsive Clients} - -\index{events!UnresponsiveClient|(} -When \wmii\ tries to close a window, it waits 8 seconds for the -client to respond, and then lets its scripts decide what to do -with it. The stock scripts prompt the user for input: - -\begin{Fragment}{Unresponsive Clients} - UnresponsiveClient) # UnresponsiveClient ‹Client ID› - { - # Use wihack to make the xmessage a transient window of - # the problem client. This will force it to open in the - # floaing layer of whatever views the client is attached to - resp=$(wihack -transient $1 \ - xmessage -nearmouse -buttons Kill,Wait -print \ - “The following client is not responding.” \ - “What would you like to do?$(echo)” \ - $(wmiir read /client/$1/label)) - [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay - } &;; -\end{Fragment} -\index{events!UnresponsiveClient|)} - -\section{Views} - -\def\taglabel{/tag/$\langle\mathit{tag}\rangle$/} -\index{filesystem!/tag/*/@\taglabel|(} -Views are represented by directories under the |/tag/| tree. The -special |sel/| directory represents the currently selected -client. The |sel| tag is treated similarly elsewhere. The files -in these directories are: - -\begin{description} - \item[ctl] - The view's control file. The properties are: - \index{filesystem!/tag/*/@\taglabel!ctl|(} - \begin{description} - \item[select ‹Area›] Select the column ‹Area›, where - ‹Area› is a 1-based column index, or |~| for the floating - area. It may be optionally preceded by ‹Screen›|:|, where - ‹Screen› is a 0-based Xinerama screen index, or “sel”. When - omitted, ‹Screen› defaults to 0, the primary screen. - \item[select ‹Area› ‹Client Index›] Select the column ‹Area›, and - the ‹Client Index›th client. - \item[select client ‹Client ID›] Select the client with the - X11 window ID ‹Client ID›. - \item[select ‹Direction›] - Select the client in ‹Direction› where ‹Direction› may be - one of ‹up $\wedge$ down $\wedge$ left $\wedge$ right›. - \item[send client ‹Client ID› ‹Area›] Send ‹Client ID› to - ‹Area›. ‹Area› may be |sel| for the selected area, and - |client ‹Client ID›| may be |sel| for the currently selected - client. - \item[send client ‹Client ID› ‹Direction›] - Send ‹Client ID› to a column or position in its column in - the given direction. - \item[send client ‹Client ID› toggle] If ‹Client ID› is - floating, send it to the managed layer. If it's managed, - send it to the floating layer. - \item[swap client ‹Client ID› \ldots] The same as the |send| - commands, but swap ‹Client ID› with the client at the given - location. - \item[colmode ‹Area› ‹Mode›] Set ‹Area›'s mode to ‹Mode›, - where ‹Mode› is a string of values similar to tag - specifications. Values which may be added and removed are as - follows for managed areas: - - \begin{description} - \item[stack] One and only one client in the area is - uncollapsed at any given time. When a new client is - selected, it is uncollapsed and the previously selected - client is collapsed. - \item[max] Collapsed clients are hidden from view - entirely. Uncollapsed clients display an indicator - {\it‹n›/‹m›}, where ‹m› is the number of collapsed - clients directly above and below the client, plus one, - and ‹n› is the client's index in the stack. - \item[default] Like subtracting the stack mode, but all - clients in the column are given equal height. - \end{description} - - For the floating area, the values are the same, except that - in |max| mode, floating clients are hidden when the managed - layer is selected. - \item[grow ‹Frame› ‹Direction› {[‹Amount›]}] Grow ‹Frame› in - the given direction, by ‹Amount›. ‹Amount› may be any - integer, positive or negative. If suffixed with |px|, - it specifies an exact pixel amount, otherwise it specifies a - “reasonable increment”. Defaults to 1. - - ‹Frame› may be one of: - \begin{itemize} - \item client ‹Client ID› - \item ‹Area› ‹Client Index› - \end{itemize} - \item[nudge ‹Frame› ‹Direction› {[‹Amount›]}] Like - |grow|, but move the client in ‹Direction› instead of - resizing it. - \end{description} - \index{filesystem!/tag/*/@\taglabel!ctl|)} -\end{description} - -\index{filesystem!/tag/*/@\taglabel|)} - -\subsection{Key Bindings} - -We'll use the following key bindings to interact with views: - -\begin{Fragment}{Motion Keys} - Mod4-h) wmiir xwrite /tag/sel/ctl select left;; - Mod4-l) wmiir xwrite /tag/sel/ctl select right;; - Mod4-k) wmiir xwrite /tag/sel/ctl select up;; - Mod4-j) wmiir xwrite /tag/sel/ctl select down;; - Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;; -\end{Fragment} - -\begin{Fragment}{Client Movement Keys} - Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;; - Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;; - Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;; - Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;; - Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;; -\end{Fragment} - -\begin{Fragment}{Column Mode Keys} - Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;; - Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;; - Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;; -\end{Fragment} - -\subsection{Click Menus} - -\index{events!LeftBarMouseDown} -\begin{Fragment}{Tag Menu Events} - LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name› - [ $1 = 3 ] && clickmenu \ - “Delete:delete_view $2” -\end{Fragment} - -\section{Command and Program Execution} - -Perhaps the most important function we need to provide for is -the execution of programs. Since \wmii\ users tend to use -terminals often, we'll add a direct shortcut to launch one. -Aside from that, we'll add a menu to launch arbitrary programs -(with completions) and a separate menu to launch wmii specific -commands. - -We use |wmiir setsid| to launch programs with their own session -IDs to prevent untoward effects when this script dies. - -\begin{Fragment}{Command Execution Initialization} - terminal() { wmiir setsid xterm “$@” } - proglist() { - IFS=: - wmiir proglist $1 | sort | uniq - unset IFS - } -\end{Fragment} - -\subsection{Key Bindings} -\begin{Fragment}{Command Execution Keys} - Mod4-Return) terminal & ;; - Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;; - Mod4-a) { - set -- $(proglist $WMII_CONFPATH | wimenu) - which=$(which which) - prog=$(PATH=$WMII_CONFPATH $which $1); shift - eval exec $prog “$@” - } &;; -\end{Fragment} - -\section{The Root} - -The root filesystem contains the following: - -\index{!filesystem!/|(} -\begin{description} - \item[ctl] The control file. The properties are: - \index{filesystem!/!ctl} - \begin{description} - \item[bar on ‹top $\wedge$ bottom›] Controls where the bar - is shown. - \item[bar off] Disables the bar entirely. - \item[border] The border width, in pixels, of floating - clients. - \item[colmode ‹Mode›] The default column mode for newly - created columns. - \item[focuscolors ‹Color Tuple›] The colors of focused - clients. - \item[normcolors ‹Color Tuple›] The colors of unfocused - clients and the default color of bar buttons. - \item[font ‹Font›] The font used throughout \wmii. If - prefixed with |xft:|, the Xft font renderer is used, and - fonts may be antialiased. Xft font names follow the - fontconfig formula. For instance, 10pt, italic Lucida - Sans would be specified as - - \begin{code} - xft:Lucida Sans-10:italic - \end{code} - - See \man 1 {fc-match}. - - \item[grabmod ‹Modifier Keys›] The key which must be - pressed to move and resize windows with the mouse - without clicking hot spots. - \item[incmode ‹Mode›] Controls how X11 increment hints are - handled in managed mode. Possible values are: - \begin{description} - \item[ignore] Increment hints are ignored entirely. - Clients are stretched to fill their full allocated - space. - \item[show] Gaps are shown around managed client - windows when their increment hints prevent them from - filling their entire allocated space. - \item[squeeze] When increment hints cause gaps to show - around clients, \wmii\ will try to adjust the sizes - of the clients in the column to minimize lost space. - \end{description} - \item[view ‹Tag›] Change the currently visible view. - \item[exec ‹Command›] Replaces this \wmii\ instance with - ‹Command›. ‹Command› is split according to rc quoting - rules, and no expansion occurs. If the command fails to - execute, \wmii\ will respawn. - \item[spawn ‹Command›] Spawns ‹Command› as it would spawn - |wmiirc| at startup. If ‹Command› is a single argument - and doesn't begin with |/| or |./|,% - \hskip 1ex|$WMII_CONF|\-|PATH| is - searched for the executable. Otherwise, the whole - argument is passed to the shell for evaluation. - \end{description} - \item[keys] The global keybindings. See section \ref{sec:keybindings}. - \index{filesystem!/!keys|primary} - \item[event] The global event feed. See section \ref{sec:keybindings}. - \index{filesystem!/!event|primary} - \item[colrules] - \index{filesystem!/!colrules} - The |/colrules| file contains a list of - rules which affect the width of newly created columns. - Rules have the form: - - \begin{quote}\texttt{ - /‹regex›/ -> ‹width›{\color{gray}[}+‹width›{\color{gray}]*}} - \end{quote} - - Where, - - \begin{code} - ‹width› ≔ ‹percent of screen› | ‹pixels›px - \end{code} - - When a new column, ‹n›, is created on a view whose name - matches ‹regex›, it is given the ‹n›th supplied ‹width›. - If there is no ‹n›th width, it is given - $1/\mbox{‹ncol›th}$ of the screen. - - \item[rules] - \index{filesystem!/!rules} - The |/rules| file contains a list of - rules similar to the colrules. These rules set - properties for a client when it is created. - Rules are specified: - - \begin{quote}\texttt{ - /‹regex›/ -> ‹key›{\color{gray}=}‹value› {\color{gray}\ldots}} - \end{quote} - - When a client's ‹name›:‹class›:‹title› matches - ‹regex›, the matching rules are applied. For each - ‹key›=‹value› pair, the |ctl| file property matching - ‹key› is set to ‹value›. Additionally, the following - keys are accepted and have special meaning: - - \begin{description} - \item[continue] - Normally, when a matching rule is encountered, - rule matching stops. When the continue key is - provided (with any value), matching continues at - the next rule. - \item[force-tags] - Like tags, but overrides any settings obtained - obtained from the client's group or from the - |_WMII_TAGS| window property. - \end{description} - -\end{description} - -\index{!filesystem!/|)} - -\subsection{Configuration} - -We'll need to let \wmii\ know about our previously defined theme -information: - -\begin{Fragment}{Configuration} - «Theme Definitions» - - xsetroot -solid $background - wmiir write /ctl <<! - border 2 - focuscolors $focuscolors - normcolors $normcolors - font $font - grabmod Mod4 - ! -\end{Fragment} - -\subsection{Key Bindings} - -And we need a few more key bindings to select our views: - -\begin{Fragment}{Tag Selection Keys} - Mod4-t) - # Prompt the user for a tag - tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) - # Write it to the filesystem. - wmiir xwrite /ctl view $tags;; - Mod4-[0-9]) - wmiir xwrite /ctl view ${1##*-};; -\end{Fragment} - -\section{Tieing it All Together} - -\begin{code} - #!/bin/sh - «Click Menu Initialization» - «Command Execution Initialization» - - «Configuration» - - «Bind Keys» - «Event Loop» -\end{code} - -\section{The End Result} - -For clarity, here is the end result: - -\begin{code} - #!/bin/sh - # «Click Menu Initialization» - clickmenu() { - if res=$(wmii9menu -- “$@”); then eval “$res”; fi - } - # «Command Execution Initialization» - terminal() { wmiir setsid xterm “$@” } - proglist() { - IFS=: - wmiir proglist $1 | sort | uniq - unset IFS - } - - # «Configuration» - # «Theme Definitions» - normcolors=‘#000000 #c1c48b #81654f’ - focuscolors=‘#000000 #81654f #000000’ - background=‘#333333’ - font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’ - - xsetroot -solid $background - wmiir write /ctl <<! - border 2 - focuscolors $focuscolors - normcolors $normcolors - font $font - grabmod Mod4 - ! - - # «Bind Keys» - { - cat <<! - Mod4-space - Mod4-d - Mod4-s - Mod4-m - Mod4-a - Mod4-p - Mod4-t - Mod4-Return - Mod4-Shift-space - Mod4-f - Mod4-Shift-c - Mod4-Shift-t - Mod4-h - Mod4-j - Mod4-k - Mod4-l - Mod4-Shift-h - Mod4-Shift-j - Mod4-Shift-k - Mod4-Shift-l - ! - for i in 1 2 3 4 5 6 7 8 9 0; do - echo Mod4-$i - echo Mod4-Shift-$i - done - } | wmiir write /keys - - # «Event Loop» - # Broadcast a custom event - wmiir xwrite /event Start wmiirc - - # Turn off globbing - set -f - # Open /event for reading - wmiir read /event | - # Read the events line by line - while read line; do - # Split the line into words, store in $@ - set -- $line - event=$1; shift - line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)" - - # Process the event - case $event in - Start) # Quit when a new instance starts - [ $1 = wmiirc ] && exit;; - - # «Event Handlers» - # «View Button Events» - CreateTag) # CreateTag ‹Tag Name› - echo $normcolors $1 | wmiir create /lbar/$1;; - DestroyTag) # DestroyTag ‹Tag Name› - wmiir rm /lbar/$1;; - FocusTag) # FocusTag ‹Tag Name› - wmiir xwrite /lbar/$1 $focuscolors $1;; - UnfocusTag) # UnfocusTag ‹Tag Name› - wmiir xwrite /lbar/$1 $normcolors $1;; - - # «Urgency Events» - # The urgency events are ‘Client’ events when the program - # owning the window sets its urgency state. They're ‘Manager’ - # events when wmii or the wmii user sets the state. - UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› - wmiir xwrite /lbar/$2 $2;; - NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› - wmiir xwrite /lbar/$2 $2;; - - # «Unresponsive Clients» - UnresponsiveClient) # UnresponsiveClient ‹Client ID› - { - # Use wihack to make the xmessage a transient window of - # the problem client. This will force it to open in the - # floaing layer of whatever views the client is attached to - resp=$(wihack -transient $1 \ - xmessage -nearmouse -buttons Kill,Wait -print \ - “The following client is not responding.” \ - “What would you like to do?$(echo)” \ - $(wmiir read /client/$1/label)) - [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay - } &;; - - # «Notice Events» - Notice) - wmiir xwrite /rbar/!notice $line - kill $xpid 2>/dev/null # Let's hope this isn't reused... - { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & - xpid = $!;; - - # «Key Events» - Key) # Key ‹Key Name› - case $1 in - # «Motion Keys» - Mod4-h) wmiir xwrite /tag/sel/ctl select left;; - Mod4-l) wmiir xwrite /tag/sel/ctl select right;; - Mod4-k) wmiir xwrite /tag/sel/ctl select up;; - Mod4-j) wmiir xwrite /tag/sel/ctl select down;; - Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;; - - # «Client Movement Keys» - Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;; - Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;; - Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;; - Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;; - Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;; - - # «Column Mode Keys» - Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;; - Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;; - Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;; - - # «Client Command Keys» - Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;; - Mod4-f) wmiir xwrite /client/sel/ctl fullscreen toggle;; - - # «Command Execution Keys» - Mod4-Return) terminal & ;; - Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;; - Mod4-a) { - set -- $(proglist $WMII_CONFPATH | wimenu) - prog=$(PATH=$WMII_CONFPATH which $1); shift - eval exec $prog “$@” - } &;; - - # «Tag Selection Keys» - Mod4-t) - # Prompt the user for a tag - tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) - # Write it to the filesystem. - wmiir xwrite /ctl view $tag;; - Mod4-[0-9]) - wmiir xwrite /ctl view ${1##*-};; - - # «Tagging Keys» - Mod4-Shift-t) - # Get the selected client's id - c=$(wmiir read /client/sel/ctl | sed 1q) - # Prompt the user for new tags - tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) - # Write them to the client - wmiir xwrite /client/$c/tags $tag;; - Mod4-Shift-[0-9]) - wmiir xwrite /client/sel/tags ${1##*-};; - - esac;; - - # «Client Menu Events» - ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button› - [ $2 = 3 ] && clickmenu \ - “Delete:wmiir xwrite /client/$1/ctl kill” \ - “Kill:wmiir xwrite /client/$1/ctl slay” \ - “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on” - - # «Tag Menu Events» - LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name› - [ $1 = 3 ] && clickmenu \ - “Delete:delete_view $2” - esac - done -\end{code} +\include{introduction} +\include{gettingstarted} +\include{customizing} \backmatter