chiark / gitweb /
xinitrc, setup: Overhaul of X session handling.
[profile] / xinitrc
diff --git a/xinitrc b/xinitrc
index 43ca142dacb962a4e77e5ac40e1710a3b945fb23..60a11e6f9f18fa622c996970c61b9e2d3e7687ca 100755 (executable)
--- a/xinitrc
+++ b/xinitrc
 #! /bin/bash
+###
+### X startup script
 
-xx= tt=:; if [ "$XINIT_TEST" != "" ]; then xx=: tt=echo; set -x; fi
-$xx xrdb -override $HOME/.Xdefaults
-: ${VNCSESSION=false}
-export __mdw_sechost="`hostname`"
-
-# --- Do some fiddling ---
+###--------------------------------------------------------------------------
+### Utility functions.
 
-cleanup=":"
-xset b 10 2000 50
-xset r rate 500 50
-xset m 1 1
-$xx mail-notification&
-$xx $VNCSESSION || $xx gkrellm&
-if [ "$XINIT_TEST" = "" ] || [ "$XWIDTH" = "" ] || [ "$XHEIGHT" = "" ]; then
-  eval `xscsize -bx`
-fi
+## Progress indicators.
+info=yes
+info () {
+  case $info in yes) echo "- $*" >&2 ;; esac
+}
 
-# --- Crank up ESD ---
+run=yes
+run () {
+  local what=$1; shift
+  local bg=no
 
-if ! $xx [ -r /tmp/.esd/socket ]; then
-  esd -nobeeps -as 10&
-  cleanup="$cleanup; kill $!"
-fi
+  case $what in bg*) bg=yes what=${what#bg} ;; esac
+  info "run $what: $*"
 
-# --- Picking appropriate programs ---
+  case "$run,$bg" in
+    yes,no) "$@" ;;
+    yes,yes) "$@" & ;;
+  esac
+}
 
+## Program choice
 pick_program () {
+  local what=$1; shift
+  local choice=false
   for i in "$@"; do
-    if type -t >/dev/null "$i"; then echo "$i"; return; fi
+    if type -t >/dev/null "$i"; then choice=$i; break; fi
   done
-  echo false
+  info "pick $what = $choice"
+  echo "$choice"
 }
 
-# --- Start a nice window manager ---
+###--------------------------------------------------------------------------
+### Parse arguments.
 
-: ${wm=$(pick_program enlightenment e16)}
-$tt Window manager is $wm.
-$xx $wm $EOPTS&
+vnc=no
+atomtag=
+start=yes
+wait=yes
 
-# --- Crank up a screenlock program ---
+for opt; do
+  case "$opt" in
+    help)
+      cat <<EOF
+Options:
+  tag=TAG
+  [no]trace
+  [no]info
+  [no]run
+  [no]start
+  [no]wait
+  [no]vnc
+EOF
+      exit
+      ;;
 
-if ! $xx $VNCSESSION; then
-  xscreensaver-command -exit
-  xscreensaver -no-splash&
-  $xx gnome-settings-daemon&
-  $xx gnome-panel&
-fi
+    tag=*) atomtag=/${opt#tag=} ;;
+    trace) set -x ;;
+    notrace) set +x ;;
+    info | run | start | wait | vnc) eval "$opt=yes" ;;
+    noinfo | norun | nostart | nowait | novnc) eval "${opt#no}=no" ;;
+
+    *) echo "unknown option $opt" >&2; exit 1 ;;
+  esac
+done
+
+###--------------------------------------------------------------------------
+### Iniitial settings.
+
+## Assume X sessions are secure.
+export __mdw_sechost="`hostname`"
+
+## Obtain the screen dimensions.
+case ",$XWIDTH,$XHEIGHT," in
+  *,,*) eval $(xscsize -bx) ;;
+esac
+info "screen size = $XWIDTH x $XHEIGHT"
+
+initialize () {
+  ## Load the X resource database.
+  run init xrdb -override $HOME/.Xdefaults
+
+  ## Random xsettery.
+  run init xset b 10 2000 50
+  run init xset r rate 500 50
+  run init xset m 2 1
+
+  ## Gnome settings.
+  case $vnc in no) run bginit gnome-settings-daemon ;; esac
+}
+
+###--------------------------------------------------------------------------
+### Start a window manager.
+
+wm=$(pick_program window-manager enlightenment e16 twm)
+wmopts=""
+case "$wm,$vnc" in
+  enlightenment,yes | e16,yes)
+    wmopts="$eopts -econfdir $HOME/.enlightenment-vnc"
+    ;;
+esac
+
+start-window-manager () {
+  run bginit $wm $wmopts
+}
+
+###--------------------------------------------------------------------------
+### Random useful clients.
+
+start-clients () {
+  ## Mail notification.
+  run bginit mail-notification
+
+  ## System monitor.
+  case $vnc in no) run bginit gkrellm ;; esac
+
+  ## Screensaver.
+  case $vnc in
+    no)
+      run init xscreensaver-command -exit
+      run bginit xscreensaver -no-splash
+      ;;
+  esac
+
+  ## Panel.
+  case $vnc in no) run bginit gnome-panel ;; esac
+}
+
+###--------------------------------------------------------------------------
+### Main screen layout.
 
-# --- Emacs window measurements ---
-#
-# Horizontal column pixel width = 492; window manager overhead = 34
-# Column character width = 82; Emacs magic overhead = -2
-# Vertical line pixel height = 13; misc overhead = 52
+## Choose appropriate clients.
+emacs=$(pick_program emacs emacs22 emacs21 emacs)
+term=$(pick_program terminal pterm Eterm xterm)
 
-: ${emacs=$(pick_program emacs22 emacs21)}
-$tt Using editor $emacs.
+## Emacs window measurements.
 case "$emacs" in
-  emacs21)
+  emacs21 | emacs)
     e_colwd=492 e_hextra=34
     e_colchars=82 e_cextra=-2
     e_lineht=13 e_vextra=52
@@ -69,33 +153,24 @@ case "$emacs" in
     ;;
 esac
 
-# --- Xterm window measurements ---
-#
-# Window width is 503 (fixed).
-# Vertical line pixel height = 13; misc overhead = 23
-
-: ${term=$(pick_program pterm Eterm xterm)}
-$tt Using terminal $tt
+## Terminal window measurements.
 case "$term" in
   pterm) t_wd=503 t_lineht=13 t_vextra=23 geom=-geometry;;
   Eterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-g;;
   xterm) t_wd=507 t_lineht=13 t_vextra=27 geom=-geometry;;
 esac
 
-# --- GNOME stuff measurements ---
-#
-# GNOME panel width = 113
-
+## GNOME stuff measurements.
 declare -i xbound="XWIDTH - 113"
 
-# --- Choose a width for Emacs ---
-#
-# We'd like it to be as wide as possible, allowing for a column of xterms
-# down the right hand side.  However, I'd prefer a double-width Emacs to a
-# single-width Emacs and xterms.  If it's not going to work at all, a single
-# Emacs column will have to do.  Also, there's a strange thing with Emacs21
-# and the toolbar, so we add on some rows which are later mysteriously
-# subtracted.
+## Choose a width for Emacs.
+##
+## We'd like it to be as wide as possible, allowing for a column of xterms
+## down the right hand side.  However, I'd prefer a double-width Emacs to a
+## single-width Emacs and xterms.  If it's not going to work at all, a single
+## Emacs column will have to do.  Also, there's a strange thing with Emacs21
+## and the toolbar, so we add on some rows which are later mysteriously
+## subtracted.
 
 declare -i ecols="(xbound - t_wd - e_hextra)/e_colwd"
 if (( ecols < 2 && xbound > e_colwd * 2 + e_hextra )); then
@@ -104,43 +179,134 @@ elif (( ecols < 1 )); then
   ecols=1
 fi
 
-declare -i x="ecols * e_colwd + e_hextra"
-noip $emacs -geometry $((ecols * e_colchars + e_cextra))x$(((XHEIGHT - e_vextra)/e_lineht))+0+0&
-
-# --- Now place some xterms ---
-#
-# A few smaller xterms are in general better than one great big one.  35
-# lines is a good height for most terminals.  25 lines is a minimum.  The
-# strategy for doling out xterms into a column is to make as many 35-liners
-# as we can, until the remaining space would be too small for a 25-liner.  If
-# we can get two 25s out of that then we do (largest first); otherwise just
-# make one big one.  We stop at the end of a page, once we've made three
-# xterms.
-
-declare -i n=0 pgx=0 l h y ht
-declare -i hstd="35 * t_lineht + t_vextra" hmin="25 * t_lineht + t_vextra"
-while true; do
-  if ((x + t_wd > xbound)); then
-    if ((n >= 3)); then break; fi
-    x="pgx + XWIDTH" pgx="pgx + XWIDTH" xbound="xbound + XWIDTH"
-  fi
-  y=0 ht=XHEIGHT
-  while ((ht - hstd >= hmin)); do
-    $term $geom 80x35+$x+$y&
-    y="y + hstd" ht="ht - hstd" n="n + 1"
+declare -i \
+  emacsx="ecols * e_colchars + e_cextra" \
+  emacsy="(XHEIGHT - e_vextra)/e_lineht"
+
+start-emacs () {
+  run bgclients noip $emacs -geometry ${emacsx}x${emacsy}+0+0
+}
+
+## Now place some xterms.
+##
+## A few smaller xterms are in general better than one great big one.  35
+## lines is a good height for most terminals.  25 lines is a minimum.  The
+## strategy for doling out xterms into a column is to make as many 35-liners
+## as we can, until the remaining space would be too small for a 25-liner.
+## If we can get two 25s out of that then we do (largest first); otherwise
+## just make one big one.  We stop at the end of a page, once we've made
+## three xterms.
+
+start-xterms () {
+
+  ## Initialize some parameters.
+  declare -i x="ecols * e_colwd + e_hextra"
+  declare -i n=0 pgx=0 l h y ht
+  declare -i hstd="35 * t_lineht + t_vextra" hmin="25 * t_lineht + t_vextra"
+
+  ## Do the placement.
+  while :; do
+
+    ## Start a new iteration.
+    if ((x + t_wd > xbound)); then
+      if ((n >= 3)); then break; fi
+      x="pgx + XWIDTH" pgx="pgx + XWIDTH" xbound="xbound + XWIDTH"
+    fi
+
+    ## Make large xterms.
+    y=0 ht=XHEIGHT
+    while ((ht - hstd >= hmin)); do
+      run bgclients $term $geom 80x35+$x+$y
+      y="y + hstd" ht="ht - hstd" n="n + 1"
+    done
+
+    ## Fill the remaining space.
+    if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi
+    l="(h - t_vextra)/t_lineht" h="l * t_lineht + t_vextra"
+    run bgclients $term $geom 80x$l+$x+$y
+    y="y + h" ht="ht - h" n="n + 1"
+    if ((ht >= hmin)); then
+      run bgclients $term $geom 80x25+$x+$y
+      n="n + 1"
+    fi
+    x="x + t_wd"
   done
-  if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi
-  l="(h - t_vextra)/t_lineht" h="l * t_lineht + t_vextra"
-  $term $geom 80x$l+$x+$y&
-  y="y + h" ht="ht - h" n="n + 1"
-  if ((ht >= hmin)); then
-    $term $geom 80x25+$x+$y&
-    n="n + 1"
-  fi
-  x="x + t_wd"
-done
+}
 
-# --- Wait for the world to end ---
+###--------------------------------------------------------------------------
+### Final waiting.
+
+atom=XINIT_COMMAND$atomtag
+
+xwait () {
+  while :; do
+    xatom delete $atom
+    info "waiting on $atom"
+    line=$(xatom wait $atom)
+    info "xatom: $line"
+
+    case "$line" in
+      :help)
+       xmsg -I -t "xinitrc help" -d "xinitrc commands" - <<EOF &
+:help
+:emacs :xterms :window-manager :clients
+:init
+:terminal
+! SHELL-COMMAND
+CLIENT
+EOF
+       ;;
+      :emacs | :xterms | :window-manager | :clients)
+       start-${line#:}
+       ;;
+      :terminal)
+       run bgclients $term
+       ;;
+      :init)
+       initialize
+       ;;
+      :exec)
+       info "restarting xinitrc"
+       exec "$0" wait nostart
+       ;;
+      :*)
+       xmsg -E -t "xinitrc error" "Unknown command \`$line'" &
+       ;;
+      !*)
+       eval "${line#!}"
+       ;;
+      *)
+        set -- $line
+       run bgclients "$@"
+       ;;
+    esac
+  done
+}
+
+###--------------------------------------------------------------------------
+### Actually start things up.
+
+case "$start" in
+  yes)
+    info "starting standard clients"
+    initialize
+    start-window-manager
+    start-clients
+    start-emacs
+    start-xterms
+    ;;
+  no)
+    info "not starting standard clients"
+    ;;
+esac
+
+case "$wait" in
+  yes)
+    xwait
+    ;;
+  no)
+    info "not waiting before exit"
+    ;;
+esac
 
-$xx xwait XWAIT_DIE:XWAIT_DIE_NOW
-$xx eval "$cleanup"
+###----- That's all, folks --------------------------------------------------