master ohmu/wmutils / src / contrib / switch_grid.sh
ohmu  ·  2026-07-25
 1#!/bin/sh
 2#
 3# Copyright (c) 2015 Greduan <me@greduan.com>, licensed under the WTFPL license
 4# Credit where credit is due, the grid algorithm was written by z3bra
 5#
 6# When used puts all the windows in a grid and when you focus one of the windows
 7# it puts all the windows back to their original location and focuses the window
 8# you switched to.
 9# depends on: wew focus.sh
10
11TEMP=$(mktemp) && wattr xywhi $(lsw) > $TEMP
12NB=$(wc -l < $TEMP) # NB as in NumBer of windows
13
14# just safety
15if [ $NB -eq 1 ]; then
16    exit
17fi
18
19# user defined
20BW=${BW:-4} # width of your borders
21GAP=${GAP:-20} # gap between windows
22
23# get monitor dimensions
24ROOT=$(lsw -r)
25SW=$(wattr w $ROOT)
26SH=$(wattr h $ROOT)
27# reduce screen useable screen area to improve later expressions
28SW=$(( SW - GAP - 2*BW ))
29SH=$(( SH - GAP - 2*BW ))
30
31# calculate the size of the grid using the square root of the number of windows
32ROWS=$(echo "sqrt($NB)" | bc)
33COLS=$ROWS
34
35# FOLLOWING WAS WRITTEN BY Z3BRA, don't give me credit for this awesome logic
36# for each row...
37for r in `seq 1 $ROWS`; do
38
39    # .. if we're on the last row, display all the remaining windows
40    # eg: if we have 12 windows, the square root would be 3 (truncated).
41    # so the script would draw a 3x3 grid. This would leave 3 windows apart. To
42    # avoid this, we set the number of columns of the last row as
43    #
44    #    12 - 3 * (3-1)
45    # => 12 - 3 * 2
46    # => 12 - 6
47    # == 6
48    # so we will have 6 windows on the last row, instead of 3.
49    # This do not lead to the best looking grid, I know (the best one would be
50    # 3x4), but it's the simplest algo I've found. Don't forget we're playing
51    # with shell scripts here, not matlab..
52    test $r -eq $ROWS && COLS=$(( NB - ROWS * (ROWS-1) ))
53
54    # for each column of each row..
55    for c in `seq 1 $COLS`; do
56
57        # exit if we don't have other windows to display
58        test $(( (r-1)*r + c )) -gt $NB && break
59
60        # heigh of windows (total heigh minus gaps and borders)
61        H=$(( SH/ROWS - GAP - BW ))
62        # same for width
63        W=$(( SW/COLS - GAP - BW ))
64
65        # and the tricky part..
66        # The X offset is the width * the actual column (starting from 0) + the
67        # gaps/borders multiplied by the column number (draw it on a sheet of
68        # paper like me, it will make much more sense!
69        X=$(( W * (c-1) + c*(GAP + BW) ))
70        # same for the Y offset
71        Y=$(( H * (r-1) + r*(GAP + BW) ))
72
73        # finally, teleport the window to the place we just calculated.
74        # the sed trick is used to get the corresponding line number in the file
75        # holding the window infos.
76        wtp $X $Y $W $H $(sed "$(( (r-1)*r + c ))p;d" $TEMP | cut -d\  -f5)
77    done
78done
79# END Z3BRA
80
81# listen to wew for our desired event
82wew -m 4 | while IFS=: read ev wid; do
83    if [ $ev -eq 4 ]; then
84        while read line; do
85            wtp $line
86        done < $TEMP
87        focus.sh $wid
88        killall wew
89    fi
90done
91
92# cleanup
93rm $TEMP