blog · git · desktop · images · contact
2008-05-11
Ok, vermutlich wird soetwas wie das hier bald dazu führen, dass ich den Window Manager wechsele - obgleich ich noch nicht weiß, ob das woanders wirklich besser/einfacher lösbar ist.
Ich hab' ziemlich schnell Gefallen am klebenden Terminal gefunden, also wollte ich mehrere davon haben. Lässt sich prinzipiell auch einfach realisieren (oder man verwendet einfach screen), wenn ich nicht einige Extrawünsche hätte. :)
Meine Lösung ist jetzt eine Sammlung von 4 teilweise nicht mehr kurzen Shellscripten.
Bin sicher, dass es irgendwie auch einfacher und/oder eleganter geht ... ;)
Im "globalen" Startskript wird eine Liste der Terminals definiert, die gestartet werden sollen - hier wird einfach nur deren Geometrie jeweils angegeben.
Pro Terminal wird dann ein "Keeper" gestartet, der sich darum kümmert, dass das Terminal die richtigen Fenstereigenschaften hat und nach Beenden wieder gestartet wird. Nach jedem Start schreibt er die PID in eine Pool-Datei, bei jedem Beenden wird die letzte bekannte PID gelöscht.
Beim Drücken des Hotkeys (Zuordnung wie bisher) wird dann eine erweiterte Variante des "klebeterm-showdesktop.sh" aufgerufen, welches zuerst "Show Desktop" aktiviert und dann für alle gespeicherten PID's im Pool die Window-ID für wmctrl heraussucht, um diese Fenster wiederherzustellen.
devilspie ist leider keine Lösung - hier stimmt die Positionierung der Fenster bei mir nicht mehr. Desweiteren wird nun urxvt verwendet, da dieses direkte Unterstützung bietet, "borderless" zu sein.
klebeterm.sh
#!/bin/bash
# Wird vom Nutzer aufgerufen und hat dafür zu sorgen, dass alle
# klebenden Terminals gestartet werden und irgendwie deren Eigenschaften
# richtig gesetzt werden. Außerdem sollen sie immer da bleiben, bzw. neu
# gestartet werden, wenn sie beendet werden.
PIDPOOL="/tmp/klebepids"
GEOMS="90x55+0+0 88x27+935+0 88x27+935+585"
if [ -f "$PIDPOOL" ]; then
rm $PIDPOOL
fi
for i in $GEOMS; do
/home/blabla/klebeterm-keep.sh $i &
echo "Keeper gestartet: $!"
done
klebeterm-keep.sh
#!/bin/bash
# Verwaltet ein klebendes Terminal mit der als Parameter übergebenen Geometrie.
# Sorgt dafür, dass es bei Beenden neu gestartet wird.
# Es wird jedesmal, wenn ein Terminal (neu) gestartet wird, seine PID in eine
# Pool-Datei geschrieben. Wird es beendet, dann wird die PID wieder dort
# herausgelöscht. So kann man in klebeterm-showdesktop.sh sicher identifizieren,
# was wieder de-minimiert werden soll.
PIDPOOL="/tmp/klebepids"
function msg()
{
echo $*
}
function err()
{
echo $* >&2
}
function addPID()
{
if [ -z $1 ]; then
err "PID für Pool (add) als Parameter übergeben."
return 1
fi
echo $1 >> "$PIDPOOL"
}
function removePID()
{
if [ -z $1 ]; then
err "PID für Pool (remove) als Parameter übergeben."
return 1
fi
if [ ! -f "$PIDPOOL" ]; then
err "PIDPOOL existiert nicht: $PIDPOOL"
return 1
fi
while read LINE
do
if [[ "$LINE" != $1 ]]; then
echo "$LINE" >> "$PIDPOOL.2"
fi
done < "$PIDPOOL"
mv "$PIDPOOL.2" "$PIDPOOL" || return 1
}
function waitForWindow()
{
if [ -z $1 ]; then
err "Window ID als Parameter übergeben."
return 1
fi
# Jetzt schonmal 'ne Sekunde warten - ist sicher noch nicht da, wenn man direkt nachschaut
sleep 1
# Maximal 30 Mal = 30 Sekunden lang warten, bis ein Fenster auf dieser PID registriert ist
typeset -i tries=0
while [ $tries -lt 30 ]; do
# wmctrl auflisten lassen, zurechtstutzen und dann schauen, ob die PID
# nach einem Blank und am Ende der Zeile auftaucht
WINDOW=$(wmctrl -l -p | cut -d " " -f1,4 | grep "\ $TERMPID\$" | cut -d " " -f1)
if [[ "$WINDOW" != "" ]]; then
# Jetzt ist es da! Merke: $WINDOW ist global gesetzt
return 0
fi
tries=tries+1
err "Fenster für PID $1 nicht gefunden, warte das $tries. Mal ..."
sleep 1
done
err "Fenster erschien zu lange nicht. Gebe auf."
return 1
}
function settingsForWindow()
{
if [ -z $1 ]; then
err "Window ID als Parameter übergeben."
return 1
fi
# Hier Eigenschaften für das Zielfenster setzen
wmctrl -i -r $1 -b add,below || return 1
}
if [ -z $1 ]; then
err "Usage: $0 [-v] <geometry>"
exit 1
fi
if [[ "$1" == "-v" ]]; then
verbose=yes
shift
fi
while true; do
# Terminal als Job starten
urxvt -ssc -ip -sh 80 -bl +sb -fg grey -bg black -geometry $1 -fn "x:-*-terminus-medium-*-*-*-20-*-*-*-*-*-*-*" &
# Die PID holen und dann warten, bis das Fenster da ist und dann die Window ID holen
TERMPID=$!
addPID $TERMPID || exit 1
WINDOW=""
waitForWindow $TERMPID || exit 1
# Jetzt Eigenschaften für dieses Fenster setzen
settingsForWindow $WINDOW || exit 1
if [ "$verbose" ]; then
msg "PID: $TERMPID, Window ID: $WINDOW"
fi
# Warten, bis/ob sich das Terminal beendet. Wenn ja, nochmal von vorne.
wait $TERMPID
if [ "$verbose" ]; then
msg "Terminal gestorben, starte neu ..."
fi
removePID $TERMPID || exit 1
done
klebeterm-showdesktop.sh
#!/bin/bash
# Wird aufgerufen, wenn alle Fenster minimiert werden sollen. Stellt dann *alle*
# klebenden Terminals wieder her.
# PIDPOOL?
PIDPOOL="/tmp/klebepids"
# "Show Desktop" modus anschalten
wmctrl -k on
# Für jede registrierte KlebePID die Window ID holen und dann wiederherstellen
for i in $(cat /tmp/klebepids); do
WINDOW=$(wmctrl -l -p | awk -v pid=$i '{if ($3 == pid) {print $1}}')
wmctrl -i -a $WINDOW
done
klebeterm-kill.sh
#!/bin/bash
# Beendet alle klebenden Terminals wieder
PIDPOOL="/tmp/klebepids"
TARGETEXE="urxvt"
function err()
{
echo $* >&2
}
killall klebeterm-keep.sh
if [ -f "$PIDPOOL" ]; then
for i in $(cat "$PIDPOOL"); do
EXENAME=$(ps --no-headers -o comm -p $i)
if [[ "$EXENAME" == "$TARGETEXE" ]]; then
kill $i
else
err "Gegegbene PID \"$i\" gehört zu \"$EXENAME\" statt \"$TARGETEXE\""
fi
done
rm "$PIDPOOL"
else
killall urxvt
fi
Natürlich muss für andere Kisten hier und da noch was angepasst werden.