1#!/usr/local/bin/bash 2 3# a q3-like (or yakuake-like) terminal for arbitrary applications. 4# 5# this lets a new monitor called "q3terminal" scroll in from the top into the 6# current monitor. There the "scratchpad" will be shown (it will be created if 7# it doesn't exist yet). If the monitor already exists it is scrolled out of 8# the screen and removed again. 9# 10# Warning: this uses much resources because herbstclient is forked for each 11# animation step. 12# 13# If a tag name is supplied, this is used instead of the scratchpad 14 15tag="${1:-scratchpad}" 16hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;} 17 18termwidth_percent=${WIDTH_PERC:-100} 19mrect=( $(hc monitor_rect -p "" ) ) 20termwidth=$(( (${mrect[2]} * termwidth_percent) / 100 )) 21termheight=${HEIGHT_PIXELS:-400} 22 23rect=( 24 $termwidth 25 $termheight 26 $(( ${mrect[0]} + (${mrect[2]} - termwidth) / 2 )) 27 $(( ${mrect[1]} - termheight )) 28) 29 30y_line=${mrect[1]} 31 32 33hc add "$tag" 34 35 36monitor=q3terminal 37 38exists=false 39if ! hc add_monitor $(printf "%dx%d%+d%+d" "${rect[@]}") \ 40 "$tag" $monitor 2> /dev/null ; then 41 exists=true 42else 43 # remember which monitor was focused previously 44 hc chain \ 45 , new_attr string monitors.by-name."$monitor".my_prev_focus \ 46 , substitute M monitors.focus.index \ 47 set_attr monitors.by-name."$monitor".my_prev_focus M 48fi 49 50update_geom() { 51 local geom=$(printf "%dx%d%+d%+d" "${rect[@]}") 52 hc move_monitor "$monitor" $geom 53} 54 55steps=${ANIMATION_STEPS:-5} 56interval=${ANIMATION_INTERVAL:-0.01} 57 58animate() { 59 progress=( "$@" ) 60 for i in "${progress[@]}" ; do 61 rect[3]=$((y_line - (i * termheight) / steps)) 62 update_geom 63 sleep "$interval" 64 done 65} 66 67show() { 68 hc lock 69 hc raise_monitor "$monitor" 70 hc focus_monitor "$monitor" 71 hc unlock 72 hc lock_tag "$monitor" 73 animate $(seq $steps -1 0) 74} 75 76hide() { 77 rect=( $(hc monitor_rect "$monitor" ) ) 78 local tmp=${rect[0]} 79 rect[0]=${rect[2]} 80 rect[2]=${tmp} 81 local tmp=${rect[1]} 82 rect[1]=${rect[3]} 83 rect[3]=${tmp} 84 termheight=${rect[1]} 85 y_line=${rect[3]} # height of the upper screen border 86 87 animate $(seq 0 +1 $steps) 88 # if q3terminal still is focused, then focus the previously focused monitor 89 # (that mon which was focused when starting q3terminal) 90 hc substitute M monitors.by-name."$monitor".my_prev_focus \ 91 and + compare monitors.focus.name = "$monitor" \ 92 + focus_monitor M 93 hc remove_monitor "$monitor" 94} 95 96[ $exists = true ] && hide || show 97 98