aboutsummaryrefslogtreecommitdiffstats
path: root/herbstluftwm/.local/bin/q3terminal.sh
blob: e69b5ee48ae56375ca6c99810894bc65ba897562 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/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}" "$@" ;}

termwidth_percent=${WIDTH_PERC:-100}
mrect=( $(hc monitor_rect -p "" ) )
termwidth=$(( (${mrect[2]} * termwidth_percent) / 100 ))
termheight=${HEIGHT_PIXELS:-400}

rect=(
    $termwidth
    $termheight
    $(( ${mrect[0]} + (${mrect[2]} - termwidth) / 2 ))
    $(( ${mrect[1]} - termheight ))
)

y_line=${mrect[1]}


hc add "$tag"


monitor=dropdown

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=${ANIMATION_STEPS:-1}
interval=${ANIMATION_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