# dgl/wmii forked from sunaku/wmii

### Subversion checkout URL

You can clone with HTTPS or Subversion.

 e5e7abe [guide] Split guide sections into separate .tex files. Kris Maglione authored Jun 27, 2010 1 \chapter{Customizing \wmii} 2 3 There are several configuration schemes available for \wmii. If 4 you're only looking to add basic key bindings, status monitors, 5 \emph{et cetera}, you should have no trouble modifying the stock 6 configuration for your language of choice. If you're looking for 7 deeper knowledge of \wmii's control interface though, this 8 section is for you. We'll proceed by building a configuration 9 script in \POSIX\ |sh| syntax and then move on to a discussion 10 of the higher level constructs in the stock configuration 11 scripts. 12 13 For the purposes of pedagogy, we'll construct the script in the 14 literate programming style of Knuth, whereby we construct the 15 code in fragments and explain each one in detail. For your 16 convenience, each fragment name is linked to its definition. 17 18 \section{Events} 19 20 The \wmii\ control interface is largely event driven. Each event 21 is represented by a single, plain-text line written to the 22 |/event| file. You can think of this file as a named pipe. When 23 reading it, you won't receive an EOF\footnote{End of File} until 24 \wmii\ exits. Moreover, any lines written to the file will be 25 transmitted to everyone currently reading from it. Notable 26 events include key presses, the creation and destruction of 27 windows, and changes of focus and views. 28 29 We'll start building our configuration with an event processing 30 framework: 31 32 \begin{Fragment}{Event Loop} 33 # Broadcast a custom event 34 wmiir xwrite /event Start wmiirc 35 36 # Turn off globbing 37 set -f 38 # Open /event for reading 39 wmiir read /event | 40 # Read the events line by line 41 while read line; do 42 # Split the line into words, store in $@ 43 set --$line 44 event=$1; shift 45 line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)" 46 # Process the event 47 case$event in 48 Start) # Quit when a new instance starts 49 [ $1 = wmiirc ] && exit;; 50 «Event Handlers» 51 esac 52 done 53 \end{Fragment} 54 55 Now, we need to consider which types of events we'll need to 56 handle: 57 58 \begin{Fragment}{Event Handlers} 59 «View Button Events» 60 «Urgency Events» 61 «Unresponsive Clients» 62 «Notice Events» 63 «Key Events» 64 «Client Menu Events» 65 «Tag Menu Events» 66 \end{Fragment} 67 68 \section{Bar Items} 69 70 The bar is described by the files in the two directories |/lbar/| and 71 |/rbar/| for buttons on the left and right side of the bar, 72 respectively. The files act as control files (section 73 \ref{sec:controlfiles}) with the contents: 74 75 \begin{code} 76 color ‹Color Tuple› 77 label ‹Label› 78 \end{code} 79 80 A ‹Color Tuple› is defined as: 81 82 \begin{code} 83 ‹Color Tuple› ≔ ‹foreground color› ‹background color› ‹border color› 84 ‹* Color› ≔ ‹RGB color› | ‹RGBA color› 85 ‹RGB color› ≔ ＃‹6 character RGB hex color code› 86 ‹RGBA color› ≔ rgba:‹red›/‹green›/‹blue›/‹alpha› 87 \end{code} 88 89 \noindent 90 where all of the colors are represented as lowercase, 91 hexidecimal values. In the case of RGBA colors, they may be 1--4 92 characters long, though they will be standardized internally to 93 2 characters. 94 95 \medskip 96 97 Let's define our basic theme information now: 98 99 \begin{Fragment}{Theme Definitions} 100 normcolors=‘＃000000 ＃c1c48b ＃81654f’ 101 focuscolors=‘＃000000 ＃81654f ＃000000’ 102 background=‘＃333333’ 103 font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’ 104 \end{Fragment} 105 106 \subsection{View Buttons} 107 108 With a basic understanding of bar items in mind, we can write 109 our view event handlers: 110 111 \index{events!CreateTag} 112 \index{events!DestroyTag} 113 \index{events!FocusTag} 114 \index{events!UnfocusTag} 115 \begin{Fragment}{View Button Events} 116 CreateTag) # CreateTag ‹Tag Name› 117 echo$normcolors $1 | wmiir create /lbar/$1;; 118 DestroyTag) # DestroyTag ‹Tag Name› 119 wmiir rm /lbar/$1;; 120 FocusTag) # FocusTag ‹Tag Name› 121 wmiir xwrite /lbar/$1 $focuscolors$1;; 122 UnfocusTag) # UnfocusTag ‹Tag Name› 123 wmiir xwrite /lbar/$1$normcolors $1;; 124 \end{Fragment} 125 126 \subsection{Urgency} 127 128 \index{events!UrgentTag|(} 129 \index{events!NotUrgentTag|(} 130 Windows can specify that they require attention, and in X11 131 parlance, this is called urgency\footnote{\ICCCM{4.1.2.4}}. When 132 a window requests attention as such, or declares that it's been 133 satisfied, \wmii\ broadcasts an event for the client and an 134 event for each view that it belongs to. It also fills in the 135 layout box of any client deemed urgent. It's the job of a script 136 to decide how to handle urgency events above and beyond that 137 basic measure. The standard scripts simply mark urgent views 138 with an asterisk: 139 140 \begin{Fragment}{Urgency Events} 141 # The urgency events are ‘Client’ events when the program 142 # owning the window sets its urgency state. They're ‘Manager’ 143 # events when wmii or the wmii user sets the state. 144 UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› 145 wmiir xwrite /lbar/$2 $2;; 146 NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name› 147 wmiir xwrite /lbar/$2 $2;; 148 \end{Fragment} 149 \index{events!UrgentTag|)} 150 \index{events!NotUrgentTag|)} 151 152 \subsection{Notices} 153 154 The standard scripts provide a custom Notice event for 155 displaying status information. The events appear in the long bar 156 between the left and right sides for five seconds. 157 158 \begin{Fragment}{Notice Events} 159 Notice) 160 wmiir xwrite /rbar/!notice$line 161 kill $xpid 2>/dev/null # Let's hope this isn't reused... 162 { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & 163 xpid =$!;; 164 \end{Fragment} 165 166 \section{Keys} 167 168 \label{sec:keybindings} 169 \index{key bindings} 170 \index{filesystem!/!keys} 171 \index{filesystem!/!event} 172 Now to the part you've no doubt been waiting for: binding keys. 173 When binding keys, you need to be aware of two files, |/keys| 174 and |/event|. The former defines which keys \wmii\ needs to 175 grab, and the latter broadcasts the events when they're pressed. 176 177 Key names are specified as a series of modifiers followed by a 178 key name, all separated by hyphens. Valid modifier names are 179 |Control|, |Shift|, |Mod1| (usually Alt), |Mod2|, |Mod3|, |Mod4| 180 (usually the Windows® key), and |Mod5|. Modifier keys can be 181 changed via |xmodmap(1)|, the details of which are beyond the 182 scope of this document. 183 184 Key names can be detected by running |xev| from a 185 terminal, pressing the desired key, and looking at the output 186 (it's in the parentheses, after the keysym). Or, more simply, 187 you can run the \man 1 {wikeyname} utility bundled with \wmii\ 188 and press the key you wish to bind. 189 190 Examples of key bindings: 191 192 \begin{description} 193 \item[Windows® key + Capital A] |Mod4-Shift-A| 194 \item[Control + Alt + Space] |Mod1-Control-Space| 195 \end{description} 196 197 Now, let's bind the keys we plan on using: 198 199 \begin{Fragment}{Bind Keys} 200 { 201 cat < ‹width›{\color{gray}[}+‹width›{\color{gray}]*}} 659 \end{quote} 660 661 Where, 662 663 \begin{code} 664 ‹width› ≔ ‹percent of screen› | ‹pixels›px 665 \end{code} 666 667 When a new column, ‹n›, is created on a view whose name 668 matches ‹regex›, it is given the ‹n›th supplied ‹width›. 669 If there is no ‹n›th width, it is given 670 $1/\mbox{‹ncol›th}$ of the screen. 671 672 \item[rules] 673 \index{filesystem!/!rules} 674 The |/rules| file contains a list of 675 rules similar to the colrules. These rules set 676 properties for a client when it is created. 677 Rules are specified: 678 679 \begin{quote}\texttt{ 680 /‹regex›/ -> ‹key›{\color{gray}=}‹value› {\color{gray}\ldots}} 681 \end{quote} 682 683 When a client's ‹name›:‹class›:‹title› matches 684 ‹regex›, the matching rules are applied. For each 685 ‹key›=‹value› pair, the |ctl| file property matching 686 ‹key› is set to ‹value›. Additionally, the following 687 keys are accepted and have special meaning: 688 689 \begin{description} 690 \item[continue] 691 Normally, when a matching rule is encountered, 692 rule matching stops. When the continue key is 693 provided (with any value), matching continues at 694 the next rule. 695 \item[force-tags] 696 Like tags, but overrides any settings obtained 697 obtained from the client's group or from the 698 |_WMII_TAGS| window property. 699 \end{description} 700 701 \end{description} 702 703 \index{!filesystem!/|)} 704 705 \subsection{Configuration} 706 707 We'll need to let \wmii\ know about our previously defined theme 708 information: 709 710 \begin{Fragment}{Configuration} 711 «Theme Definitions» 712 713 xsetroot -solid $background 714 wmiir write /ctl </dev/null # Let's hope this isn't reused... 872 { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } & 873 xpid =$!;; 874 875 # «Key Events» 876 Key) # Key ‹Key Name› 877 case $1 in 878 # «Motion Keys» 879 Mod4-h) wmiir xwrite /tag/sel/ctl select left;; 880 Mod4-l) wmiir xwrite /tag/sel/ctl select right;; 881 Mod4-k) wmiir xwrite /tag/sel/ctl select up;; 882 Mod4-j) wmiir xwrite /tag/sel/ctl select down;; 883 Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;; 884 885 # «Client Movement Keys» 886 Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;; 887 Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;; 888 Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;; 889 Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;; 890 Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;; 891 892 # «Column Mode Keys» 893 Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;; 894 Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;; 895 Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;; 896 897 # «Client Command Keys» 898 Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;; 899 Mod4-f) wmiir xwrite /client/sel/ctl fullscreen toggle;; 900 901 # «Command Execution Keys» 902 Mod4-Return) terminal & ;; 903 Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;; 904 Mod4-a) { 905 set --$(proglist $WMII_CONFPATH | wimenu) 906 prog=$(PATH=$WMII_CONFPATH which$1); shift 907 eval exec $prog “$@” 908 } &;; 909 910 # «Tag Selection Keys» 911 Mod4-t) 912 # Prompt the user for a tag 913 tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) 914 # Write it to the filesystem. 915 wmiir xwrite /ctl view $tag;; 916 Mod4-[0-9]) 917 wmiir xwrite /ctl view${1＃＃*-};; 918 919 # «Tagging Keys» 920 Mod4-Shift-t) 921 # Get the selected client's id 922 c=$(wmiir read /client/sel/ctl | sed 1q) 923 # Prompt the user for new tags 924 tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu) 925 # Write them to the client 926 wmiir xwrite /client/$c/tags $tag;; 927 Mod4-Shift-[0-9]) 928 wmiir xwrite /client/sel/tags${1＃＃*-};; 929 930 esac;; 931 932 # «Client Menu Events» 933 ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button› 934 [ $2 = 3 ] && clickmenu \ 935 “Delete:wmiir xwrite /client/$1/ctl kill” \ 936 “Kill:wmiir xwrite /client/$1/ctl slay” \ 937 “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on” 938 939 # «Tag Menu Events» 940 LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name› 941 [ $1 = 3 ] && clickmenu \ 942 “Delete:delete_view$2” 943 esac 944 done 945 \end{code} 946