Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 947 lines (813 sloc) 33.337 kb
e5e7abe [guide] Split guide sections into separate .tex files.
Kris Maglione authored
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=‘#00000081654f #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 <<!
202 Mod4-space
203 Mod4-d
204 Mod4-s
205 Mod4-m
206 Mod4-a
207 Mod4-p
208 Mod4-t
209 Mod4-Return
210 Mod4-Shift-space
211 Mod4-f
212 Mod4-Shift-c
213 Mod4-Shift-t
214 Mod4-h
215 Mod4-j
216 Mod4-k
217 Mod4-l
218 Mod4-Shift-h
219 Mod4-Shift-j
220 Mod4-Shift-k
221 Mod4-Shift-l
222 !
223 for i in 1 2 3 4 5 6 7 8 9 0; do
224 echo Mod4-$i
225 echo Mod4-Shift-$i
226 done
227 } | wmiir write /keys
228 \end{Fragment}
229
230 and lay a framework for processing their events:
231
232 \begin{Fragment}{Key Events}
233 Key) # Key ‹Key Name›
234 case $1 in
235 «Motion Keys»
236 «Client Movement Keys»
237 «Column Mode Keys»
238 «Client Command Keys»
239 «Command Execution Keys»
240 «Tag Selection Keys»
241 «Tagging Keys»
242 esac;;
243 \end{Fragment}
244
245 \section{Click Menus}
246
247 Sometimes, you have your hand on the mouse and don't want to
248 reach for the keyboard. To help cope, \wmii\ provides a
249 mouse-driven, single-click menu. The default configuration uses
250 it for client and tag menus.
251
252 \begin{Fragment}{Click Menu Initialization}
253 clickmenu() {
254 if res=$(wmii9menu -- “$@”); then eval “$res”; fi
255 }
256 \end{Fragment}
257
258 \section{Control Files}
259
260 \label{sec:controlfiles}
261
262 Several directories including the root, have control files,
263 named |ctl|. These files are used to control the object (e.g., a
264 client or tag) represented by the directory. Each line of the
265 file, with the possible section of the first, represents a
266 control variable and its value. In the case of all but the root
267 |/ctl| file, the first line represents the id of the directory.
268 In the case of |/tag/foo/ctl|, for instance, the first line
269 should read |foo|. This is useful when dealing with the special
270 |sel/| directories. For instance, when |foo| is the selected
271 tag, the special |/tag/sel| directory is a link to |/tag/foo|,
272 and the first line of |/tag/sel/ctl| will read |foo|, just as
273 if you'd accessed |/tag/foo/ctl| directly.
274
275 The rest of the lines, the control variables, can be modified by
276 writing new values to the control file. For instance, if a
277 client is fullscreen, its control file will contain the line:
278
279 \begin{code}
280 fullscreen on
281 \end{code}
282
283 \noindent To restore the client from fullscreen, either of the
284 following lines may be written to its control file:
285
286 \begin{code}
287 fullscreen off
288 fullscreen toggle
289 \end{code}
290
291 When next read, the |fullscreen on| line will have been replaced
292 with |fullscreen off|. No care need be taken to preserve the
293 other contents of the file. They're generated anew each time
294 it's read.
295
296 \section{Clients}
297
298 \def\clientlabel{/client/$\langle\mathit{client}\rangle$/}
299 \index{filesystem!/client/*/@\clientlabel|(}
300 Clients are represented by directories under the |/client/|
301 tree. Subdirectory names represent the client's X11 window ID.
302 The special |sel/| directory represents the currently selected
303 client. The files in these directories are:
304
305 \begin{description}
306 \item[ctl] The client's control file, containing the following
307 properties:
308 \index{filesystem!/client/*/@\clientlabel!ctl}
309 \begin{description}
310 \item[allow] The set of unusual actions the client is
311 allowed to perform, in the same format as the tag set.
312 \begin{description}
313 \item[activate] The client is allowed to activate
314 itself—that is, focus its window and, as the case may
315 require, uncollapse it and select a tag it resides on.
316 This flag must be set on a client if you wish it able to
317 activate itself from the system tray.
318 \end{description}
319 \item[floating] Defines whether this client is likely to
320 float when attached to a new view. May be |on|, |off|,
321 |always|, or |never|. Ordinarilly, the value changes
322 automatically whenever the window is moved between the
323 floating and managed layers. However, setting a value of
324 |always| or |never| overrides this behavior.
325 \item[fullscreen] The client's fullscreen state. When
326 |on|, the client is displayed fullscreen on all of its
327 views. Possible values are |on|, |off|, and |toggle|.
328 \item[group] The client's group ID, or |0| if not part of
329 a group. Clients tend to open with the same tags and in
330 the same columns as the last active member of their
331 group. Setting this property is only useful when done
332 via the rules file.
333 \item[kill] When written, the window is closed politely,
334 if possible.
335 \item[pid] Read-only value of the PID of the program that
336 owns the window, if the value is available and the
337 process is on the same machine as wmii.
338 \item[slay] When written, the client is disconnected
339 peremptorily. If the client's PID is available and the
340 process is the same machine as wmii, its parent process
341 is killed
342 \item[tags] The client's tags. The same as the tags file.
643cb45 @dgl Support titleless client ctl option to remove titlebar
authored
343 \item[titleless] The client's titlebar state. When |on|,
344 the client will not show a titlebar, unless the client
345 is inactive in a stack. Possible values are |on|, |off|,
346 and |toggle|.
e5e7abe [guide] Split guide sections into separate .tex files.
Kris Maglione authored
347 \item[urgent] The client's urgency state. When |on|, the
348 client's layout box will be highlighted. Possible values
349 are |on|, |off|, and |toggle|.
350 \end{description}
351 \item[props] The client's window class (the X11
352 |WM_CLASS|\footnote{\ICCCM{4.1.2.5}}
353 property) and title string, separated by colons. This file
354 is not writable.
355 \index{filesystem!/client/*/@\clientlabel!props}
356 \item[label] The client's window title. May be written to
357 change the client's title.
358 \index{filesystem!/client/*/@\clientlabel!label}
359 \item[tags]
360 \index{filesystem!/client/*/@\clientlabel!tags}
361 The client's tags. Tag names are separated by |+|, |-|, or
362 |^| signs. Tag names which directly follow a |+| sign are
363 added, while whose following a |-| sign are removed and
364 those following a |^| are toggled. If the value written
365 begins with one of these characters, the value is appended
366 to the clients tags rather than replacing them.
367
368 Tags formatted as |/‹regex›/| are treated as regular
369 expressions, which place the client on any extant matching
370 tag\footnote{While a client with a regex tag will always
371 appear in all matching views, it will not keep those views
372 in existence. When the last client explicitly tagged with a
373 view is removed, the view is deleted as soon as it becomes
374 inactive.}. Regular expression tags which directly follow a
375 minus sign are treated as exclusion expressions. For
376 example, the tag string |+/foo/-/food/| will match the tag
377 |foobar|, but not the tag |foodstand|.
378 \end{description}
379
380 \index{filesystem!/client/*/@\clientlabel|)}
381
382 \subsection{Key Bindings}
383
384 To control clients, we'll add the following key bindings:
385
386 \begin{Fragment}{Client Command Keys}
387 Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;;
388 Mod4-f) wmiir xwrite /client/sel/ctl Fullscreen toggle;;
389 \end{Fragment}
390
391 And to manage their tags, we'll need:
392
393 \begin{Fragment}{Tagging Keys}
394 Mod4-Shift-t)
395 # Get the selected client's id
396 c=$(wmiir read /client/sel/ctl | sed 1q)
397 # Prompt the user for new tags
398 tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu)
399 # Write them to the client
400 wmiir xwrite /client/$c/tags $tag;;
401 Mod4-Shift-[0-9])
402 wmiir xwrite /client/sel/tags ${1##*-};;
403 \end{Fragment}
404
405 \subsection{Click Menus}
406
407 \index{events!ClientMouseDown}
408 \begin{Fragment}{Client Menu Events}
409 ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button›
410 [ $2 = 3 ] && clickmenu \
411 “Delete:wmiir xwrite /client/$1/ctl kill” \
412 “Kill: wmiirxwrite /client/$1/ctl slay” \
413 “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on”
414 \end{Fragment}
415
416 \subsection{Unresponsive Clients}
417
418 \index{events!UnresponsiveClient|(}
419 When \wmii\ tries to close a window, it waits 8 seconds for the
420 client to respond, and then lets its scripts decide what to do
421 with it. The stock scripts prompt the user for input:
422
423 \begin{Fragment}{Unresponsive Clients}
424 UnresponsiveClient) # UnresponsiveClient ‹Client ID›
425 {
426 # Use wihack to make the xmessage a transient window of
427 # the problem client. This will force it to open in the
428 # floaing layer of whatever views the client is attached to
429 resp=$(wihack -transient $1 \
430 xmessage -nearmouse -buttons Kill,Wait -print \
431 “The following client is not responding.” \
432 “What would you like to do?$(echo)” \
433 $(wmiir read /client/$1/label))
434 [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay
435 } &;;
436 \end{Fragment}
437 \index{events!UnresponsiveClient|)}
438
439 \section{Views}
440
441 \def\taglabel{/tag/$\langle\mathit{tag}\rangle$/}
442 \index{filesystem!/tag/*/@\taglabel|(}
443 Views are represented by directories under the |/tag/| tree. The
444 special |sel/| directory represents the currently selected
445 client. The |sel| tag is treated similarly elsewhere. The files
446 in these directories are:
447
448 \begin{description}
449 \item[ctl]
450 The view's control file. The properties are:
451 \index{filesystem!/tag/*/@\taglabel!ctl|(}
452 \begin{description}
453 \item[select ‹Area›] Select the column ‹Area›, where
454 ‹Area› is a 1-based column index, or |~| for the floating
455 area. It may be optionally preceded by ‹Screen›|:|, where
456 ‹Screen› is a 0-based Xinerama screen index, or “sel”. When
457 omitted, ‹Screen› defaults to 0, the primary screen.
458 \item[select ‹Area› ‹Client Index›] Select the column ‹Area›, and
459 the ‹Client Index›th client.
460 \item[select client ‹Client ID›] Select the client with the
461 X11 window ID ‹Client ID›.
462 \item[select ‹Direction›]
463 Select the client in ‹Direction› where ‹Direction› may be
464 one of ‹up $\wedge$ down $\wedge$ left $\wedge$ right›.
465 \item[send client ‹Client ID› ‹Area›] Send ‹Client ID› to
466 ‹Area›. ‹Area› may be |sel| for the selected area, and
467 |client ‹Client ID›| may be |sel| for the currently selected
468 client.
469 \item[send client ‹Client ID› ‹Direction›]
470 Send ‹Client ID› to a column or position in its column in
471 the given direction.
472 \item[send client ‹Client ID› toggle] If ‹Client ID› is
473 floating, send it to the managed layer. If it's managed,
474 send it to the floating layer.
475 \item[swap client ‹Client ID› \ldots] The same as the |send|
476 commands, but swap ‹Client ID› with the client at the given
477 location.
478 \item[colmode ‹Area› ‹Mode›] Set ‹Area›'s mode to ‹Mode›,
479 where ‹Mode› is a string of values similar to tag
480 specifications. Values which may be added and removed are as
481 follows for managed areas:
482
483 \begin{description}
484 \item[stack] One and only one client in the area is
485 uncollapsed at any given time. When a new client is
486 selected, it is uncollapsed and the previously selected
487 client is collapsed.
488 \item[max] Collapsed clients are hidden from view
489 entirely. Uncollapsed clients display an indicator
490 {\it‹n›/‹m›}, where ‹m› is the number of collapsed
491 clients directly above and below the client, plus one,
492 and ‹n› is the client's index in the stack.
493 \item[default] Like subtracting the stack mode, but all
494 clients in the column are given equal height.
495 \end{description}
496
497 For the floating area, the values are the same, except that
498 in |max| mode, floating clients are hidden when the managed
499 layer is selected.
500 \item[grow ‹Frame› ‹Direction› {[‹Amount›]}] Grow ‹Frame› in
501 the given direction, by ‹Amount›. ‹Amount› may be any
502 integer, positive or negative. If suffixed with |px|,
503 it specifies an exact pixel amount, otherwise it specifies a
504 “reasonable increment”. Defaults to 1.
505
506 ‹Frame› may be one of:
507 \begin{itemize}
508 \item client ‹Client ID›
509 \item ‹Area› ‹Client Index›
510 \end{itemize}
511 \item[nudge ‹Frame› ‹Direction› {[‹Amount›]}] Like
512 |grow|, but move the client in ‹Direction› instead of
513 resizing it.
514 \end{description}
515 \index{filesystem!/tag/*/@\taglabel!ctl|)}
516 \end{description}
517
518 \index{filesystem!/tag/*/@\taglabel|)}
519
520 \subsection{Key Bindings}
521
522 We'll use the following key bindings to interact with views:
523
524 \begin{Fragment}{Motion Keys}
525 Mod4-h) wmiir xwrite /tag/sel/ctl select left;;
526 Mod4-l) wmiir xwrite /tag/sel/ctl select right;;
527 Mod4-k) wmiir xwrite /tag/sel/ctl select up;;
528 Mod4-j) wmiir xwrite /tag/sel/ctl select down;;
529 Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;;
530 \end{Fragment}
531
532 \begin{Fragment}{Client Movement Keys}
533 Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;;
534 Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;;
535 Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;;
536 Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;;
537 Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;;
538 \end{Fragment}
539
540 \begin{Fragment}{Column Mode Keys}
541 Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;;
542 Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;;
543 Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;;
544 \end{Fragment}
545
546 \subsection{Click Menus}
547
548 \index{events!LeftBarMouseDown}
549 \begin{Fragment}{Tag Menu Events}
550 LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name›
551 [ $1 = 3 ] && clickmenu \
552 “Delete:delete_view $2
553 \end{Fragment}
554
555 \section{Command and Program Execution}
556
557 Perhaps the most important function we need to provide for is
558 the execution of programs. Since \wmii\ users tend to use
559 terminals often, we'll add a direct shortcut to launch one.
560 Aside from that, we'll add a menu to launch arbitrary programs
561 (with completions) and a separate menu to launch wmii specific
562 commands.
563
564 We use |wmiir setsid| to launch programs with their own session
565 IDs to prevent untoward effects when this script dies.
566
567 \begin{Fragment}{Command Execution Initialization}
568 terminal() { wmiir setsid xterm “$@” }
569 proglist() {
570 IFS=:
571 wmiir proglist $1 | sort | uniq
572 unset IFS
573 }
574 \end{Fragment}
575
576 \subsection{Key Bindings}
577 \begin{Fragment}{Command Execution Keys}
578 Mod4-Return) terminal & ;;
579 Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;;
580 Mod4-a) {
581 set -- $(proglist $WMII_CONFPATH | wimenu)
582 which=$(which which)
583 prog=$(PATH=$WMII_CONFPATH $which $1); shift
584 eval exec $prog “$@”
585 } &;;
586 \end{Fragment}
587
588 \section{The Root}
589
590 The root filesystem contains the following:
591
592 \index{!filesystem!/|(}
593 \begin{description}
594 \item[ctl] The control file. The properties are:
595 \index{filesystem!/!ctl}
596 \begin{description}
597 \item[bar on ‹top $\wedge$ bottom›] Controls where the bar
598 is shown.
599 \item[border] The border width, in pixels, of floating
600 clients.
601 \item[colmode ‹Mode›] The default column mode for newly
602 created columns.
603 \item[focuscolors ‹Color Tuple›] The colors of focused
604 clients.
605 \item[normcolors ‹Color Tuple›] The colors of unfocused
606 clients and the default color of bar buttons.
607 \item[font ‹Font›] The font used throughout \wmii. If
608 prefixed with |xft:|, the Xft font renderer is used, and
609 fonts may be antialiased. Xft font names follow the
610 fontconfig formula. For instance, 10pt, italic Lucida
611 Sans would be specified as
612
613 \begin{code}
614 xft:Lucida Sans-10:italic
615 \end{code}
616
617 See \man 1 {fc-match}.
618
619 \item[grabmod ‹Modifier Keys›] The key which must be
620 pressed to move and resize windows with the mouse
621 without clicking hot spots.
622 \item[incmode ‹Mode›] Controls how X11 increment hints are
623 handled in managed mode. Possible values are:
624 \begin{description}
625 \item[ignore] Increment hints are ignored entirely.
626 Clients are stretched to fill their full allocated
627 space.
628 \item[show] Gaps are shown around managed client
629 windows when their increment hints prevent them from
630 filling their entire allocated space.
631 \item[squeeze] When increment hints cause gaps to show
632 around clients, \wmii\ will try to adjust the sizes
633 of the clients in the column to minimize lost space.
634 \end{description}
635 \item[view ‹Tag›] Change the currently visible view.
636 \item[exec ‹Command›] Replaces this \wmii\ instance with
637 ‹Command›. ‹Command› is split according to rc quoting
638 rules, and no expansion occurs. If the command fails to
639 execute, \wmii\ will respawn.
640 \item[spawn ‹Command›] Spawns ‹Command› as it would spawn
641 |wmiirc| at startup. If ‹Command› is a single argument
642 and doesn't begin with |/| or |./|,%
643 \hskip 1ex|$WMII_CONF|\-|PATH| is
644 searched for the executable. Otherwise, the whole
645 argument is passed to the shell for evaluation.
646 \end{description}
647 \item[keys] The global keybindings. See section \ref{sec:keybindings}.
648 \index{filesystem!/!keys|primary}
649 \item[event] The global event feed. See section \ref{sec:keybindings}.
650 \index{filesystem!/!event|primary}
651 \item[colrules]
652 \index{filesystem!/!colrules}
653 The |/colrules| file contains a list of
654 rules which affect the width of newly created columns.
655 Rules have the form:
656
657 \begin{quote}\texttt{
658 /‹regex›/ -> ‹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 <<!
715 border 2
716 focuscolors $focuscolors
717 normcolors $normcolors
718 font $font
719 grabmod Mod4
720 !
721 \end{Fragment}
722
723 \subsection{Key Bindings}
724
725 And we need a few more key bindings to select our views:
726
727 \begin{Fragment}{Tag Selection Keys}
728 Mod4-t)
729 # Prompt the user for a tag
730 tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu)
731 # Write it to the filesystem.
732 wmiir xwrite /ctl view $tags;;
733 Mod4-[0-9])
734 wmiir xwrite /ctl view ${1##*-};;
735 \end{Fragment}
736
737 \section{Tieing it All Together}
738
739 \begin{code}
740 #!/bin/sh
741 «Click Menu Initialization»
742 «Command Execution Initialization»
743
744 «Configuration»
745
746 «Bind Keys»
747 «Event Loop»
748 \end{code}
749
750 \section{The End Result}
751
752 For clarity, here is the end result:
753
754 \begin{code}
755 #!/bin/sh
756 # «Click Menu Initialization»
757 clickmenu() {
758 if res=$(wmii9menu -- “$@”); then eval “$res”; fi
759 }
760 # «Command Execution Initialization»
761 terminal() { wmiir setsid xterm “$@” }
762 proglist() {
763 IFS=:
764 wmiir proglist $1 | sort | uniq
765 unset IFS
766 }
767
768 # «Configuration»
769 # «Theme Definitions»
770 normcolors=‘#000000 #c1c48b #81654f’
771 focuscolors=‘#00000081654f #000000
772 background=‘#333333
773 font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’
774
775 xsetroot -solid $background
776 wmiir write /ctl <<!
777 border 2
778 focuscolors $focuscolors
779 normcolors $normcolors
780 font $font
781 grabmod Mod4
782 !
783
784 # «Bind Keys»
785 {
786 cat <<!
787 Mod4-space
788 Mod4-d
789 Mod4-s
790 Mod4-m
791 Mod4-a
792 Mod4-p
793 Mod4-t
794 Mod4-Return
795 Mod4-Shift-space
796 Mod4-f
797 Mod4-Shift-c
798 Mod4-Shift-t
799 Mod4-h
800 Mod4-j
801 Mod4-k
802 Mod4-l
803 Mod4-Shift-h
804 Mod4-Shift-j
805 Mod4-Shift-k
806 Mod4-Shift-l
807 !
808 for i in 1 2 3 4 5 6 7 8 9 0; do
809 echo Mod4-$i
810 echo Mod4-Shift-$i
811 done
812 } | wmiir write /keys
813
814 # «Event Loop»
815 # Broadcast a custom event
816 wmiir xwrite /event Start wmiirc
817
818 # Turn off globbing
819 set -f
820 # Open /event for reading
821 wmiir read /event |
822 # Read the events line by line
823 while read line; do
824 # Split the line into words, store in $@
825 set -- $line
826 event=$1; shift
827 line = "$(echo $line | sed ‘s/^[^ ]* //’ | tr -d ‘\n’)"
828
829 # Process the event
830 case $event in
831 Start) # Quit when a new instance starts
832 [ $1 = wmiirc ] && exit;;
833
834 # «Event Handlers»
835 # «View Button Events»
836 CreateTag) # CreateTag ‹Tag Name›
837 echo $normcolors $1 | wmiir create /lbar/$1;;
838 DestroyTag) # DestroyTag ‹Tag Name›
839 wmiir rm /lbar/$1;;
840 FocusTag) # FocusTag ‹Tag Name›
841 wmiir xwrite /lbar/$1 $focuscolors $1;;
842 UnfocusTag) # UnfocusTag ‹Tag Name›
843 wmiir xwrite /lbar/$1 $normcolors $1;;
844
845 # «Urgency Events»
846 # The urgency events are ‘Client’ events when the program
847 # owning the window sets its urgency state. They're ‘Manager’
848 # events when wmii or the wmii user sets the state.
849 UrgentTag) # UrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name›
850 wmiir xwrite /lbar/$2 $2;;
851 NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name›
852 wmiir xwrite /lbar/$2 $2;;
853
854 # «Unresponsive Clients»
855 UnresponsiveClient) # UnresponsiveClient ‹Client ID›
856 {
857 # Use wihack to make the xmessage a transient window of
858 # the problem client. This will force it to open in the
859 # floaing layer of whatever views the client is attached to
860 resp=$(wihack -transient $1 \
861 xmessage -nearmouse -buttons Kill,Wait -print \
862 “The following client is not responding.” \
863 “What would you like to do?$(echo)” \
864 $(wmiir read /client/$1/label))
865 [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay
866 } &;;
867
868 # «Notice Events»
869 Notice)
870 wmiir xwrite /rbar/!notice $line
871 kill $xpid 2>/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
Something went wrong with that request. Please try again.