Skip to main content

Window switcher

·
Table of Contents
niri - This article is part of a series.
Part 2: This Article

Introduction
#

Even though the same functionality can be implemented with rofi and the window mode, I wanted to write my own version with the following additions:

  • Displays the Niri workspace on which the window is open
  • The currently focused window is prefixed with an asterisk
  • If no windows are open, a rofi menu is displayed with favourite programs
  • For each workspace, the total number of windows is displayed

Screenshot
#

Window List

Requirements
#

Please ensure that you have the following programs installed:

  • rofi
  • fuzzel
If using rofi you can change the theme file, the prompt, and the number of lines shown.

If using fuzzel you can change the font family, the font size, and the window width.

You can also change the length of time that the dunstify notification is shown for.

Bash Script
#

#!/bin/bash

WINS="$(niri msg -j windows | jq "[.[] | select(.is_urgent == false|true )] | length")"

D_TIMER=2000

if [[ $WINS -eq 0 ]]; then
    dunstify "There are no other windows to display" -t $D_TIMER
    exit 0
fi

R_PROMPT="Window List ($WINS open) "
R_CONFIG="/home/karmst/.config/rofi/themes/fzf_finder.rasi"
R_LINES=12

F_WIDTH=108
F_FONT="ComicSansMS"
F_FONT="ComicNeue-Italic"
F_FONT="Monospace"
F_SIZE=10
F_FONTCONFIG="$F_FONT:size=$F_SIZE"

RUNNER="rofi -dmenu -i -l "$R_LINES" -p "$R_PROMPT" -config "$R_CONFIG" -theme-str 'window {width: 80%;} listview { scrollbar: false; }'"
RUNNER="fuzzel -d -w $F_WIDTH -f $F_FONTCONFIG"

options=()
for ((index=0; index<WINS; index++)); do
    ID=$(niri msg -j windows | jq ".[$index]" | jq ".id")
    TITLE=$(niri msg -j windows | jq ".[$index]" | jq ".title" | sed 's/\"\(disabled.\+\)"/\1/')

    WS=$(niri msg -j windows | jq ".[$index]" | jq ".workspace_id")
    WS_NAME="$(niri msg -j workspaces | jq ".[] | select(.id == $WS)" | jq ".name" | sed 's/\"\(.\+\)"/\1/')"
    WIN_COUNT="$(niri msg -j windows | jq "[.[] | select(.workspace_id == $WS)] | length")"

    IS_FOCUSED=$(niri msg -j windows | jq ".[$index]" | jq ".is_focused")

    FOCUSED="  "
    if [[ $IS_FOCUSED == true ]]; then
        FOCUSED="* "
    fi

    CONCAT="$FOCUSED[$WIN_COUNT : $WS_NAME] : $TITLE#~#$ID"
    options+=("$CONCAT")
done

if [[ $WINS -eq 1 ]]; then
    cmd=$(niri msg action focus-window --id "$ID")
    exit 0
fi

get_options() {
    for opt in "${options[@]}"; do
        echo "${opt%%#~#*}"
    done
}

selection=$(get_options | $RUNNER)

if [[ -z "$selection" ]]; then
    exit 0
fi

action=""
for opt in "${options[@]}"; do
    display_name="${opt%%#~#*}"
    if [[ "$selection" == "$display_name" ]]; then
        action="${opt##*#~#}"
        break
    fi
done

if [[ -n "$action" ]]; then
    cmd=$(niri msg action focus-window --id "$action")
fi

exit 0
niri - This article is part of a series.
Part 2: This Article