ohmu
·
2026-07-25
1#!/bin/sh
2
3GAP=$1
4MASTER_RATIO=0.6
5MASTER_SIZE=1
6
7STATE_DIR="/tmp/2bwm-tiling"
8mkdir -p "$STATE_DIR"
9
10get_master_windows() {
11 [ -f "$STATE_DIR/master" ] && cat "$STATE_DIR/master" || echo ""
12}
13
14get_stack_windows() {
15 [ -f "$STATE_DIR/stack" ] && cat "$STATE_DIR/stack" || echo ""
16}
17
18save_windows() {
19 master="$1"
20 stack="$2"
21 echo "$master" > "$STATE_DIR/master"
22 echo "$stack" > "$STATE_DIR/stack"
23}
24
25get_focused_window() {
26 lsw | head -1
27}
28
29tile() {
30 root=$(lsw -r)
31 windows=$(lsw | grep -v "^$root$")
32
33 if [ -z "$windows" ]; then
34 exit 0
35 fi
36
37 screen_w=$(wattr w $root)
38 screen_h=$(wattr h $root)
39 count=$(echo "$windows" | wc -l)
40
41 if [ $count -eq 3 ]; then
42 master=$(echo "$windows" | head -1)
43 stack_windows=$(echo "$windows" | tail -n +2)
44
45 master_w=$(( (screen_w - GAP * 3) / 2 ))
46 wtp $GAP $GAP $master_w $((screen_h - GAP * 2)) $master
47
48 stack_x=$((master_w + GAP * 2))
49 stack_w=$((screen_w - stack_x - GAP))
50 stack_h=$(( (screen_h - GAP * 3) / 2 ))
51
52 i=0
53 for win in $stack_windows; do
54 y=$((GAP + i * (stack_h + GAP)))
55 wtp $stack_x $y $stack_w $stack_h $win
56 i=$((i + 1))
57 done
58 exit 0
59 fi
60
61 case $count in
62 1) cols=1; rows=1 ;;
63 2) cols=2; rows=1 ;;
64 4) cols=2; rows=2 ;;
65 5|6) cols=3; rows=2 ;;
66 7|8) cols=4; rows=2 ;;
67 9) cols=3; rows=3 ;;
68 *) cols=4; rows=$(( (count + cols - 1) / cols )) ;;
69 esac
70
71 cell_w=$(( (screen_w - GAP * (cols + 1)) / cols ))
72 cell_h=$(( (screen_h - GAP * (rows + 1)) / rows ))
73
74 i=0
75 for win in $windows; do
76 if [ $i -lt $((cols * rows)) ]; then
77 col=$((i % cols))
78 row=$((i / cols))
79 x=$((GAP + col * (cell_w + GAP)))
80 y=$((GAP + row * (cell_h + GAP)))
81 wtp $x $y $cell_w $cell_h $win
82 i=$((i + 1))
83 fi
84 done
85}
86
87tile_master_stack() {
88 root=$(lsw -r)
89 all_windows=$(lsw | grep -v "^$root$")
90
91 if [ -z "$all_windows" ]; then
92 exit 0
93 fi
94
95 master_windows=$(get_master_windows)
96 stack_windows=$(get_stack_windows)
97
98 if [ -z "$master_windows" ]; then
99 master_windows=$(echo "$all_windows" | head -$MASTER_SIZE)
100 stack_windows=$(echo "$all_windows" | tail -n +$((MASTER_SIZE + 1)))
101 save_windows "$master_windows" "$stack_windows"
102 fi
103
104 screen_w=$(wattr w $root)
105 screen_h=$(wattr h $root)
106
107 master_width=$(( (screen_w - GAP * 3) * MASTER_RATIO / 1 ))
108 stack_width=$((screen_w - master_width - GAP * 3))
109
110 master_count=$(echo "$master_windows" | wc -l)
111 stack_count=$(echo "$stack_windows" | wc -l)
112
113 if [ $master_count -gt 0 ]; then
114 master_window_height=$(( (screen_h - GAP * (master_count + 1)) / master_count ))
115 i=0
116 for win in $master_windows; do
117 y=$((GAP + i * (master_window_height + GAP)))
118 wtp $GAP $y $master_width $master_window_height $win
119 i=$((i + 1))
120 done
121 fi
122
123 if [ $stack_count -gt 0 ]; then
124 stack_window_height=$(( (screen_h - GAP * (stack_count + 1)) / stack_count ))
125 i=0
126 for win in $stack_windows; do
127 y=$((GAP + i * (stack_window_height + GAP)))
128 x=$((master_width + GAP * 2))
129 wtp $x $y $stack_width $stack_window_height $win
130 i=$((i + 1))
131 done
132 fi
133}
134
135focus_master() {
136 master_windows=$(get_master_windows)
137 if [ -n "$master_windows" ]; then
138 first_master=$(echo "$master_windows" | head -1)
139 chwso -r "$first_master"
140 fi
141}
142
143focus_next() {
144 current=$(get_focused_window)
145 all_windows=$(lsw | grep -v "^$(lsw -r)$")
146 if [ -n "$all_windows" ]; then
147 next=$(echo "$all_windows" | grep -A1 "^$current$" | tail -1)
148 if [ "$next" != "$current" ] && [ -n "$next" ]; then
149 chwso -r "$next"
150 else
151 first=$(echo "$all_windows" | head -1)
152 chwso -r "$first"
153 fi
154 fi
155}
156
157focus_prev() {
158 current=$(get_focused_window)
159 all_windows=$(lsw | grep -v "^$(lsw -r)$")
160 if [ -n "$all_windows" ]; then
161 prev=$(echo "$all_windows" | grep -B1 "^$current$" | head -1)
162 if [ "$prev" != "$current" ] && [ -n "$prev" ]; then
163 chwso -r "$prev"
164 else
165 last=$(echo "$all_windows" | tail -1)
166 chwso -r "$last"
167 fi
168 fi
169}
170
171promote_to_master() {
172 window=$(get_focused_window)
173 master_windows=$(get_master_windows)
174 stack_windows=$(get_stack_windows)
175
176 if echo "$stack_windows" | grep -q "^$window$"; then
177 new_stack=$(echo "$stack_windows" | grep -v "^$window$")
178 new_master=$(echo -e "$window\n$master_windows" | head -$MASTER_SIZE)
179 save_windows "$new_master" "$new_stack"
180 tile_master_stack
181 fi
182}
183
184demote_to_stack() {
185 window=$(get_focused_window)
186 master_windows=$(get_master_windows)
187 stack_windows=$(get_stack_windows)
188
189 if echo "$master_windows" | grep -q "^$window$"; then
190 new_master=$(echo "$master_windows" | grep -v "^$window$")
191 new_stack=$(echo -e "$window\n$stack_windows")
192 save_windows "$new_master" "$new_stack"
193 tile_master_stack
194 fi
195}
196
197swap_master() {
198 master_windows=$(get_master_windows)
199 if [ -n "$master_windows" ]; then
200 first_master=$(echo "$master_windows" | head -1)
201 second_master=$(echo "$master_windows" | head -2 | tail -1)
202 if [ -n "$second_master" ]; then
203 new_master=$(echo "$master_windows" | sed "1s/^$first_master$/$second_master/; 2s/^$second_master$/$first_master/")
204 save_windows "$new_master" "$(get_stack_windows)"
205 tile_master_stack
206 chwso -r "$first_master"
207 fi
208 fi
209}
210
211increase_master() {
212 MASTER_SIZE=$((MASTER_SIZE + 1))
213 all_windows=$(lsw | grep -v "^$(lsw -r)$")
214 master_windows=$(echo "$all_windows" | head -$MASTER_SIZE)
215 stack_windows=$(echo "$all_windows" | tail -n +$((MASTER_SIZE + 1)))
216 save_windows "$master_windows" "$stack_windows"
217 tile_master_stack
218}
219
220decrease_master() {
221 if [ $MASTER_SIZE -gt 1 ]; then
222 MASTER_SIZE=$((MASTER_SIZE - 1))
223 all_windows=$(lsw | grep -v "^$(lsw -r)$")
224 master_windows=$(echo "$all_windows" | head -$MASTER_SIZE)
225 stack_windows=$(echo "$all_windows" | tail -n +$((MASTER_SIZE + 1)))
226 save_windows "$master_windows" "$stack_windows"
227 tile_master_stack
228 fi
229}
230
231rotate_stack() {
232 stack_windows=$(get_stack_windows)
233 if [ -n "$stack_windows" ]; then
234 first=$(echo "$stack_windows" | head -1)
235 rest=$(echo "$stack_windows" | tail -n +2)
236 new_stack=$(echo -e "$rest\n$first")
237 save_windows "$(get_master_windows)" "$new_stack"
238 tile_master_stack
239 fi
240}
241
242rebalance() {
243 save_windows "" ""
244 tile_master_stack
245}
246
247if [ $# -eq 0 ]; then
248 tile
249 exit 0
250fi
251
252tile