Commit | Line | Data |
---|---|---|
f617db13 | 1 | #! /bin/bash |
8e08f814 MW |
2 | ### |
3 | ### X startup script | |
f617db13 | 4 | |
8e08f814 MW |
5 | ###-------------------------------------------------------------------------- |
6 | ### Utility functions. | |
f617db13 | 7 | |
8e08f814 MW |
8 | ## Progress indicators. |
9 | info=yes | |
10 | info () { | |
11 | case $info in yes) echo "- $*" >&2 ;; esac | |
12 | } | |
f617db13 | 13 | |
8e08f814 MW |
14 | run=yes |
15 | run () { | |
16 | local what=$1; shift | |
17 | local bg=no | |
f617db13 | 18 | |
8e08f814 MW |
19 | case $what in bg*) bg=yes what=${what#bg} ;; esac |
20 | info "run $what: $*" | |
f617db13 | 21 | |
8e08f814 MW |
22 | case "$run,$bg" in |
23 | yes,no) "$@" ;; | |
24 | yes,yes) "$@" & ;; | |
25 | esac | |
26 | } | |
eebca092 | 27 | |
74bd743a MW |
28 | manage () { |
29 | local when=$(date +%s) now | |
30 | local fail=0 rc report | |
31 | ||
32 | while :; do | |
33 | "$@"; rc=$? | |
34 | case $rc in | |
35 | 0) info "manage $1: successful exit"; break ;; | |
36 | 143) info "manage $1: terminated"; break ;; | |
37 | esac | |
38 | now=$(date +%s) | |
39 | report="rc = $rc" | |
40 | if (( $now - $when > 5 )); then | |
41 | fail=0 | |
42 | else | |
43 | report="$report, early failure" | |
44 | fail=$(( $fail + 1 )) | |
45 | if (( $fail >= 5 )); then | |
46 | info "manage $1: exit ($report), giving up after $fail failures" | |
47 | break | |
48 | fi | |
49 | fi | |
50 | info "manage $1: exit ($report), restarting" | |
51 | when=$now | |
52 | done | |
53 | } | |
54 | ||
8e08f814 | 55 | ## Program choice |
eebca092 | 56 | pick_program () { |
8e08f814 MW |
57 | local what=$1; shift |
58 | local choice=false | |
eebca092 | 59 | for i in "$@"; do |
8e08f814 | 60 | if type -t >/dev/null "$i"; then choice=$i; break; fi |
eebca092 | 61 | done |
8e08f814 MW |
62 | info "pick $what = $choice" |
63 | echo "$choice" | |
eebca092 MW |
64 | } |
65 | ||
8e08f814 MW |
66 | ###-------------------------------------------------------------------------- |
67 | ### Parse arguments. | |
f617db13 | 68 | |
8e08f814 MW |
69 | vnc=no |
70 | atomtag= | |
71 | start=yes | |
72 | wait=yes | |
f617db13 | 73 | |
8e08f814 MW |
74 | for opt; do |
75 | case "$opt" in | |
76 | help) | |
77 | cat <<EOF | |
78 | Options: | |
79 | tag=TAG | |
80 | [no]trace | |
81 | [no]info | |
82 | [no]run | |
83 | [no]start | |
84 | [no]wait | |
85 | [no]vnc | |
86 | EOF | |
87 | exit | |
88 | ;; | |
f617db13 | 89 | |
8e08f814 MW |
90 | tag=*) atomtag=/${opt#tag=} ;; |
91 | trace) set -x ;; | |
92 | notrace) set +x ;; | |
93 | info | run | start | wait | vnc) eval "$opt=yes" ;; | |
94 | noinfo | norun | nostart | nowait | novnc) eval "${opt#no}=no" ;; | |
95 | ||
96 | *) echo "unknown option $opt" >&2; exit 1 ;; | |
97 | esac | |
98 | done | |
99 | ||
100 | ###-------------------------------------------------------------------------- | |
27b6787d MW |
101 | ### Preliminary hook. |
102 | ||
103 | if [ -r $HOME/.xinitrc-prehook ]; then | |
104 | . $HOME/.xinitrc-prehook | |
105 | fi | |
106 | ||
107 | ###-------------------------------------------------------------------------- | |
8e08f814 MW |
108 | ### Iniitial settings. |
109 | ||
110 | ## Assume X sessions are secure. | |
111 | export __mdw_sechost="`hostname`" | |
112 | ||
113 | ## Obtain the screen dimensions. | |
114 | case ",$XWIDTH,$XHEIGHT," in | |
115 | *,,*) eval $(xscsize -bx) ;; | |
116 | esac | |
117 | info "screen size = $XWIDTH x $XHEIGHT" | |
118 | ||
119 | initialize () { | |
120 | ## Load the X resource database. | |
121 | run init xrdb -override $HOME/.Xdefaults | |
122 | ||
123 | ## Random xsettery. | |
8ab9747e | 124 | run init xset b 5 2000 50 |
8e08f814 MW |
125 | run init xset r rate 500 50 |
126 | run init xset m 2 1 | |
127 | ||
f4450ac9 | 128 | ## Key mappings. |
cd38b61d MW |
129 | xmodmap $HOME/.xmodmap |
130 | if [ -r $HOME/.xmodmap-local ]; then | |
131 | xmodmap $HOME/.xmodmap-local | |
132 | fi | |
8e08f814 MW |
133 | } |
134 | ||
135 | ###-------------------------------------------------------------------------- | |
136 | ### Start a window manager. | |
137 | ||
6f6bd6da | 138 | wm=$(pick_program window-manager e16 compiz enlightenment e17 twm) |
8e08f814 MW |
139 | wmopts="" |
140 | case "$wm,$vnc" in | |
141 | enlightenment,yes | e16,yes) | |
142 | wmopts="$eopts -econfdir $HOME/.enlightenment-vnc" | |
143 | ;; | |
144 | esac | |
145 | ||
16ee7a8c | 146 | start-e16 () { |
74bd743a | 147 | run bginit manage $wm $wmopts |
16ee7a8c MW |
148 | win=nil |
149 | for i in $(seq 10); do | |
b35a9c36 | 150 | sleep 1 |
16ee7a8c MW |
151 | if eesh version >/dev/null 2>&1; then |
152 | win=t | |
153 | break | |
154 | fi | |
16ee7a8c MW |
155 | done |
156 | case $win in | |
157 | t) | |
158 | info "$wm started ok" | |
159 | run init xsetroot -cursor_name left_ptr | |
160 | ;; | |
161 | nil) | |
162 | info "$wm failed to start!" | |
163 | ;; | |
164 | esac | |
165 | } | |
166 | ||
167 | start-window-manager () { | |
168 | case $(type -t start-$wm || echo "not-found") in | |
169 | function) | |
170 | start-$wm $wmopts | |
171 | ;; | |
172 | *) | |
74bd743a | 173 | run bginit manage $wm $wmopts |
16ee7a8c MW |
174 | ;; |
175 | esac | |
8e08f814 MW |
176 | } |
177 | ||
178 | ###-------------------------------------------------------------------------- | |
179 | ### Random useful clients. | |
180 | ||
54951353 MW |
181 | start-clients-local () { :; } |
182 | ||
8e08f814 | 183 | start-clients () { |
2e60c7f3 | 184 | |
5587cf4f | 185 | ## Gnome session. |
d83c96c9 MW |
186 | case "$vnc,$(xfce4-session --version 2>&1),$(gnome-session --version 2>&1)" |
187 | in | |
188 | no,xfce4-session*) | |
189 | run bginit xfce4-session | |
190 | ;; | |
191 | no,*,gnome-session\ 2.3[2-9].* | \ | |
192 | no,*,gnome-session\ 2.4[0-9].* | \ | |
193 | no,*,gnome-session\ 2.[1-9][0-9][0-9]*) | |
2e60c7f3 MW |
194 | run bginit gnome-session --session mdw |
195 | ;; | |
d83c96c9 | 196 | no,*,gnome-session*) |
2e60c7f3 MW |
197 | run bginit gnome-session |
198 | ;; | |
199 | esac | |
54951353 MW |
200 | |
201 | ## Local clients. | |
202 | start-clients-local | |
8e08f814 MW |
203 | } |
204 | ||
205 | ###-------------------------------------------------------------------------- | |
206 | ### Main screen layout. | |
f617db13 | 207 | |
8e08f814 | 208 | ## Choose appropriate clients. |
0c47c911 | 209 | emacs=$(pick_program emacs emacs23 emacs22 emacs21 emacs) |
8e08f814 | 210 | term=$(pick_program terminal pterm Eterm xterm) |
f617db13 | 211 | |
8e08f814 | 212 | ## Emacs window measurements. |
85bbf8d3 | 213 | case "$emacs" in |
8e08f814 | 214 | emacs21 | emacs) |
85bbf8d3 MW |
215 | e_colwd=492 e_hextra=34 |
216 | e_colchars=82 e_cextra=-2 | |
217 | e_lineht=13 e_vextra=52 | |
218 | ;; | |
0c47c911 | 219 | emacs22 | emacs23) |
85bbf8d3 MW |
220 | e_colwd=492 e_hextra=8 |
221 | e_colchars=82 e_cextra=-6 | |
222 | e_lineht=13 e_vextra=46 | |
223 | ;; | |
224 | esac | |
f617db13 | 225 | |
8e08f814 | 226 | ## Terminal window measurements. |
85bbf8d3 | 227 | case "$term" in |
e2b44bd9 | 228 | pterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-geometry;; |
85bbf8d3 MW |
229 | Eterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-g;; |
230 | xterm) t_wd=507 t_lineht=13 t_vextra=27 geom=-geometry;; | |
231 | esac | |
f617db13 | 232 | |
8e08f814 | 233 | ## GNOME stuff measurements. |
f617db13 MW |
234 | declare -i xbound="XWIDTH - 113" |
235 | ||
8e08f814 MW |
236 | ## Choose a width for Emacs. |
237 | ## | |
238 | ## We'd like it to be as wide as possible, allowing for a column of xterms | |
239 | ## down the right hand side. However, I'd prefer a double-width Emacs to a | |
240 | ## single-width Emacs and xterms. If it's not going to work at all, a single | |
241 | ## Emacs column will have to do. Also, there's a strange thing with Emacs21 | |
242 | ## and the toolbar, so we add on some rows which are later mysteriously | |
243 | ## subtracted. | |
f617db13 | 244 | |
85bbf8d3 MW |
245 | declare -i ecols="(xbound - t_wd - e_hextra)/e_colwd" |
246 | if (( ecols < 2 && xbound > e_colwd * 2 + e_hextra )); then | |
f617db13 MW |
247 | ecols=2 |
248 | elif (( ecols < 1 )); then | |
249 | ecols=1 | |
250 | fi | |
251 | ||
8e08f814 MW |
252 | declare -i \ |
253 | emacsx="ecols * e_colchars + e_cextra" \ | |
254 | emacsy="(XHEIGHT - e_vextra)/e_lineht" | |
255 | ||
256 | start-emacs () { | |
bf057abe MW |
257 | GDK_NATIVE_WINDOWS=1 run bgclients noip \ |
258 | $emacs -geometry ${emacsx}x${emacsy}+0+0 | |
8e08f814 MW |
259 | } |
260 | ||
261 | ## Now place some xterms. | |
262 | ## | |
263 | ## A few smaller xterms are in general better than one great big one. 35 | |
264 | ## lines is a good height for most terminals. 25 lines is a minimum. The | |
265 | ## strategy for doling out xterms into a column is to make as many 35-liners | |
266 | ## as we can, until the remaining space would be too small for a 25-liner. | |
267 | ## If we can get two 25s out of that then we do (largest first); otherwise | |
268 | ## just make one big one. We stop at the end of a page, once we've made | |
269 | ## three xterms. | |
270 | ||
271 | start-xterms () { | |
272 | ||
273 | ## Initialize some parameters. | |
6b4faba6 | 274 | declare -i x="ecols * e_colwd + e_hextra" xb=xbound |
8e08f814 MW |
275 | declare -i n=0 pgx=0 l h y ht |
276 | declare -i hstd="35 * t_lineht + t_vextra" hmin="25 * t_lineht + t_vextra" | |
277 | ||
278 | ## Do the placement. | |
279 | while :; do | |
280 | ||
281 | ## Start a new iteration. | |
6b4faba6 | 282 | if ((x + t_wd > xb)); then |
8e08f814 | 283 | if ((n >= 3)); then break; fi |
6b4faba6 | 284 | x="pgx + XWIDTH" pgx="pgx + XWIDTH" xb="xb + XWIDTH" |
8e08f814 MW |
285 | fi |
286 | ||
287 | ## Make large xterms. | |
288 | y=0 ht=XHEIGHT | |
289 | while ((ht - hstd >= hmin)); do | |
290 | run bgclients $term $geom 80x35+$x+$y | |
291 | y="y + hstd" ht="ht - hstd" n="n + 1" | |
292 | done | |
293 | ||
294 | ## Fill the remaining space. | |
295 | if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi | |
296 | l="(h - t_vextra)/t_lineht" h="l * t_lineht + t_vextra" | |
297 | run bgclients $term $geom 80x$l+$x+$y | |
298 | y="y + h" ht="ht - h" n="n + 1" | |
299 | if ((ht >= hmin)); then | |
300 | run bgclients $term $geom 80x25+$x+$y | |
301 | n="n + 1" | |
302 | fi | |
303 | x="x + t_wd" | |
f617db13 | 304 | done |
8e08f814 | 305 | } |
f617db13 | 306 | |
8e08f814 | 307 | ###-------------------------------------------------------------------------- |
3bdada49 MW |
308 | ### Requesters. |
309 | ||
310 | req () { | |
311 | declare title=$1 hist=$2; shift 2 | |
3f88bd1f | 312 | cmd=$(xgetline -t "$title" -p "_Command:" -Hl "$HOME/$hist") && |
3bdada49 MW |
313 | exec "$@" "$cmd" |
314 | } | |
315 | ||
316 | ###-------------------------------------------------------------------------- | |
8e08f814 MW |
317 | ### Final waiting. |
318 | ||
319 | atom=XINIT_COMMAND$atomtag | |
320 | ||
321 | xwait () { | |
322 | while :; do | |
323 | xatom delete $atom | |
324 | info "waiting on $atom" | |
325 | line=$(xatom wait $atom) | |
326 | info "xatom: $line" | |
327 | ||
328 | case "$line" in | |
329 | :help) | |
330 | xmsg -I -t "xinitrc help" -d "xinitrc commands" - <<EOF & | |
331 | :help | |
332 | :emacs :xterms :window-manager :clients | |
3bdada49 | 333 | :ask-run :ask-command |
8e08f814 MW |
334 | :init |
335 | :terminal | |
336 | ! SHELL-COMMAND | |
337 | CLIENT | |
338 | EOF | |
339 | ;; | |
340 | :emacs | :xterms | :window-manager | :clients) | |
341 | start-${line#:} | |
342 | ;; | |
343 | :terminal) | |
344 | run bgclients $term | |
345 | ;; | |
346 | :init) | |
347 | initialize | |
348 | ;; | |
349 | :exec) | |
350 | info "restarting xinitrc" | |
351 | exec "$0" wait nostart | |
352 | ;; | |
3bdada49 | 353 | :ask-run) |
a6780078 | 354 | req "Shell command" .cmd.hist xcatch -F"Fixed 13" -- sh -c& |
3bdada49 MW |
355 | ;; |
356 | :ask-command) | |
357 | req "xinit command" .xinit.hist xatom set XINIT_COMMAND$atomtag& | |
358 | ;; | |
8e08f814 MW |
359 | :*) |
360 | xmsg -E -t "xinitrc error" "Unknown command \`$line'" & | |
361 | ;; | |
362 | !*) | |
363 | eval "${line#!}" | |
364 | ;; | |
365 | *) | |
2f616761 | 366 | set -- $line |
8e08f814 MW |
367 | run bgclients "$@" |
368 | ;; | |
369 | esac | |
370 | done | |
371 | } | |
372 | ||
373 | ###-------------------------------------------------------------------------- | |
8ca91005 MW |
374 | ### Gnome session care and feeding. |
375 | ||
376 | session-running-p () { | |
377 | dbus-send --session --print-reply --dest=org.freedesktop.DBus / \ | |
378 | org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager \ | |
379 | >/dev/null 2>&1 | |
380 | } | |
381 | ||
d83c96c9 MW |
382 | dbus-service-running-p () { |
383 | dbus-send >/dev/null 2>&1 --session --print-reply \ | |
384 | --dest=org.freedesktop.DBus / \ | |
385 | org.freedesktop.DBus.GetNameOwner string:$1 | |
386 | } | |
387 | ||
8ca91005 | 388 | kill-gnome-session () { |
d83c96c9 MW |
389 | win=nil |
390 | while read service object logout; do | |
391 | if dbus-service-running-p $service; then win=t; break; fi | |
392 | done <<EOF | |
393 | org.xfce.SessionManager /org/xfce/SessionManager org.xfce.Session.Manager.Shutdown uint32:1 boolean:false | |
394 | org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.Logout uint32:2 | |
395 | EOF | |
396 | case $win in nil) return ;; esac | |
397 | info "killing session manager" | |
398 | dbus-send --session --dest=$service $object $logout | |
399 | for i in 1 2 3 4 5; do | |
400 | sleep 1 | |
401 | if ! dbus-service-running-p $service; then break; fi | |
402 | done | |
8ca91005 MW |
403 | } |
404 | ||
405 | ###-------------------------------------------------------------------------- | |
8e08f814 MW |
406 | ### Actually start things up. |
407 | ||
54951353 MW |
408 | if [ -f $HOME/.xinitrc-local ]; then |
409 | . $HOME/.xinitrc-local | |
410 | fi | |
411 | ||
8e08f814 MW |
412 | case "$start" in |
413 | yes) | |
414 | info "starting standard clients" | |
415 | initialize | |
416 | start-window-manager | |
417 | start-clients | |
418 | start-emacs | |
419 | start-xterms | |
420 | ;; | |
421 | no) | |
422 | info "not starting standard clients" | |
423 | ;; | |
424 | esac | |
425 | ||
426 | case "$wait" in | |
427 | yes) | |
428 | xwait | |
8ca91005 | 429 | kill-gnome-session |
8e08f814 MW |
430 | ;; |
431 | no) | |
432 | info "not waiting before exit" | |
433 | ;; | |
434 | esac | |
f617db13 | 435 | |
8e08f814 | 436 | ###----- That's all, folks -------------------------------------------------- |