diff --git a/config/herbstluftwm/autostart b/config/herbstluftwm/autostart index e220d36..98c5aa5 100755 --- a/config/herbstluftwm/autostart +++ b/config/herbstluftwm/autostart @@ -63,6 +63,7 @@ hc keybind $Mod-Control-Up resize up +$resizestep hc keybind $Mod-Control-Right resize right +$resizestep # custom keybindings +hc keybind $Mod-grave spawn "$HOME"/.config/herbstluftwm/q3terminal.sh 9 if [ "$HOSTNAME" = warthog ]; then hc keybind $Mod-d spawn /usr/bin/dmenu_run -fn "Monospace-9" else diff --git a/config/herbstluftwm/q3terminal.sh b/config/herbstluftwm/q3terminal.sh new file mode 100755 index 0000000..6e7eb35 --- /dev/null +++ b/config/herbstluftwm/q3terminal.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# a q3-like (or yakuake-like) terminal for arbitrary applications. +# +# this lets a new monitor called "q3terminal" scroll in from the top into the +# current monitor. There the "scratchpad" will be shown (it will be created if +# it doesn't exist yet). If the monitor already exists it is scrolled out of +# the screen and removed again. +# +# Warning: this uses much resources because herbstclient is forked for each +# animation step. +# +# If a tag name is supplied, this is used instead of the scratchpad + +tag="${1:-scratchpad}" +hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;} + +mrect=( $(hc monitor_rect -p "" ) ) +termwidth=$(( (${mrect[2]} * 8) / 10 )) +termheight=$(( (${mrect[3]} * 5) / 10 )) + +rect=( + $termwidth + $termheight + $(( ${mrect[0]} + (${mrect[2]} - termwidth) / 2 )) + $(( ${mrect[1]} - termheight )) +) + +y_line=${mrect[1]} + + +hc add "$tag" + + +monitor=q3terminal + +exists=false +if ! hc add_monitor $(printf "%dx%d%+d%+d" "${rect[@]}") \ + "$tag" $monitor 2> /dev/null ; then + exists=true +else + # remember which monitor was focused previously + hc chain \ + , new_attr string monitors.by-name."$monitor".my_prev_focus \ + , substitute M monitors.focus.index \ + set_attr monitors.by-name."$monitor".my_prev_focus M +fi + +update_geom() { + local geom=$(printf "%dx%d%+d%+d" "${rect[@]}") + hc move_monitor "$monitor" $geom +} + +steps=5 +interval=0.01 + +animate() { + progress=( "$@" ) + for i in "${progress[@]}" ; do + rect[3]=$((y_line - (i * termheight) / steps)) + update_geom + sleep "$interval" + done +} + +show() { + hc lock + hc raise_monitor "$monitor" + hc focus_monitor "$monitor" + hc unlock + hc lock_tag "$monitor" + animate $(seq $steps -1 0) +} + +hide() { + rect=( $(hc monitor_rect "$monitor" ) ) + local tmp=${rect[0]} + rect[0]=${rect[2]} + rect[2]=${tmp} + local tmp=${rect[1]} + rect[1]=${rect[3]} + rect[3]=${tmp} + termheight=${rect[1]} + y_line=${rect[3]} # height of the upper screen border + + animate $(seq 0 +1 $steps) + # if q3terminal still is focused, then focus the previously focused monitor + # (that mon which was focused when starting q3terminal) + hc substitute M monitors.by-name."$monitor".my_prev_focus \ + and + compare monitors.focus.name = "$monitor" \ + + focus_monitor M + hc remove_monitor "$monitor" +} + +[ $exists = true ] && hide || show +