aboutsummaryrefslogtreecommitdiff
path: root/bin/gnome-window-switcher
blob: 87cbcdcad5535e71f569da3069445a7da3c84dcc (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
#!/bin/sh

workspace_router_call() {
    method="$1"
    shift

    command -v gdbus >/dev/null 2>&1 || return 1

    gdbus call \
        --session \
        --dest name.rbenencia.WorkspaceRouter \
        --object-path /name/rbenencia/WorkspaceRouter \
        --method "name.rbenencia.WorkspaceRouter.$method" \
        "$@"
}

list_windows_json() {
    workspace_router_call ListWindows |
        sed -n "s/^('\\(.*\\)',)\$/\\1/p"
}

activate_window() {
    window_id="$1"
    workspace_router_call ActivateWindow "uint32:$window_id" >/dev/null
}

command -v jq >/dev/null 2>&1 || {
    echo "gnome-window-switcher: jq is required" >&2
    exit 1
}

command -v rofi >/dev/null 2>&1 || {
    echo "gnome-window-switcher: rofi is required" >&2
    exit 1
}

windows_json=$(list_windows_json) || {
    echo "gnome-window-switcher: Workspace Router is unavailable" >&2
    exit 1
}

choices=$(
    printf '%s\n' "$windows_json" |
        jq -r '
            sort_by(.workspace, .appName, .title)
            | .[]
            | [.id, ("[" + ((.workspace + 1) | tostring) + "]"), (.appName // .wmClass // "Unknown"), (.title // "")]
            | @tsv
        '
)

[ -n "$choices" ] || exit 0

# GNOME invokes custom keybindings before the shortcut is fully released.
# Give rofi a moment, then force the keyboard grab and focus takeover.
sleep 0.1

selection=$(
    printf '%s\n' "$choices" |
        cut -f2- |
        rofi -dmenu -i -p "window" -format i -no-lazy-grab -steal-focus
) || exit 0

window_id=$(
    printf '%s\n' "$choices" |
        sed -n "$((selection + 1))p" |
        cut -f1
)

[ -n "$window_id" ] || exit 1

activate_window "$window_id"
nihil fit ex nihilo