/
focus.sh
executable file
·119 lines (102 loc) · 2.69 KB
/
focus.sh
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env bash
dir=$1
node=$(bspc query -N -n)
node=${node^^}
target=$(bspc query -N -n $dir)
# if there are any floating windows, use an edge of that if it overlaps into us
node_dir=$1
case $node_dir in
east) dir=x; sign=-lt;;
west) dir=x; sign=-gt;;
north) dir=y; sign=-gt;;
south) dir=y; sign=-lt;;
esac
floating_windows=$(bspc query -N -d -n .window.local.floating)
declare -A winmap=();
while read wid x y w h; do
wid="${wid^^}"
# capture window corners, 1234 clockwise from top left
winmap["${wid}_1_x"]=$x
winmap["${wid}_1_y"]=$y
winmap["${wid}_2_x"]=$((x+w))
winmap["${wid}_2_y"]=$y
winmap["${wid}_3_x"]=$((x+w))
winmap["${wid}_3_y"]=$((y + h))
winmap["${wid}_4_x"]=$x
winmap["${wid}_4_y"]=$((y+h))
done < <(wattr ixywh $floating_windows $node $og_target)
inside_node() {
x=$1
y=$2
ax="${winmap["${node}_1_x"]}"
ay="${winmap["${node}_1_y"]}"
bx="${winmap["${node}_2_x"]}"
by="${winmap["${node}_2_y"]}"
dx="${winmap["${node}_4_x"]}"
dy="${winmap["${node}_4_y"]}"
bax=$((bx - ax))
bay=$((by - ay))
dax=$((dx - ax))
day=$((dy - ay))
[ $(( (x - ax) * bax + (y - ay) * bay )) -lt "0" ] && return 1
[ $(( (x - bx) * bax + (y - by) * bay )) -gt "0" ] && return 1
[ $(( (x - ax) * dax + (y - ay) * day )) -lt "0" ] && return 1
[ $(( (x - dx) * dax + (y - dy) * day )) -gt "0" ] && return 1
return 0;
}
check_corner() {
for c in $*; do
x=${winmap["${wid}_${c}_x"]}
y=${winmap["${wid}_${c}_y"]}
if ! inside_node $x $y; then
return 1
fi
done
return 0
}
check_corners() {
wid="$1"
# if they are all inside node, we don't care
# turns out this meant we couldn't grab floaters in certain situations
# if check_corner 1 2 3 4; then
# return 0;
# fi
case $node_dir in
east) corners="1 4";;
west) corners="2 3";;
north) corners="3 4";;
south) corners="1 2";;
esac
# if ! check_corner $corners; then
# return
# fi
for corner in $corners; do
x=${winmap["${wid}_${corner}_x"]}
y=${winmap["${wid}_${corner}_y"]}
if inside_node $x $y; then
if [ -z "$target_x" ]; then
target_x=$x
target_y=$y
target="$wid"
fi
# bias towards close corners
val=${winmap["${wid}_${corner}_${dir}"]}
if [ "$val" "$sign" "$(eval echo \$target_$dir)" ]; then
target=$wid
target_x=$x
target_y=$y
fi
fi
done
}
# if any corner falls in us, use that, biased to higher values
if [ ! -z "$floating_windows" ]; then
for wid in $floating_windows; do
wid="${wid^^}"
[ "$wid" = "$node" ] && continue
check_corners "$wid"
done
fi
bspc config pointer_follows_focus true
bspc node -f $target
bspc config pointer_follows_focus false