toggle_theme script

This literate configuration for setting and toggling theme in swaywm is maintained in org mode . org-babel tangles this to ~/.config/sway/scripts/toggle_theme↗ , available as part of dotfiles .

The :tangle-mode (identity #o755) is added to the header args. Otherwise every tangle will reset the permissions and the script permission needs to be changed everytime to make it an executable.

Initialization

Let any reference to an unset variable become a fatal error.

#!/bin/sh
set -u

Variables

Define light and dark theme names and config paths for Sway, Foot etc..

DARK_THEME="Nordic"
LIGHT_THEME="Adwaita"

SWAY_CONFIG_DIR="$HOME/.config/sway"
SWAY_THEMES_DIR="$SWAY_CONFIG_DIR/themes"
SWAY_DARK_CONFIG="$SWAY_THEMES_DIR/nord.conf"
SWAY_LIGHT_CONFIG="$SWAY_THEMES_DIR/adwaita.conf"
GTK3_CONFIG="$HOME/.config/gtk-3.0/settings.ini"
FOOT_THEMES_DIR="$HOME/.config/foot/themes"
FOOT_DARK_CONFIG="$FOOT_THEMES_DIR/dark.ini"
FOOT_LIGHT_CONFIG="$FOOT_THEMES_DIR/light.ini"
FOOT_CURRENT_LINK="$HOME/.config/foot/current_theme.ini"

Helper Functions

Setting theme for different applications or components of a desktop is handled by their respective helper functions. These helper functions are invoked by the theme setting functions.

Foot terminal

The theme toggle script requires few changes in the foot configuration file . It needs an include section and necessary theme files for the toggle script to work. We reset the symbolic file link for current theme using the force option to overwrites existing link. These settings are effective only for new terminals as the config file is read once at process start.

For changing the theme of existing foot terminals, signals 1 and 2 are sent as per documentation. For the signals to work, need to include [colors-dark] and [colors-light] sections.

apply_foot_theme() {
    local theme_file="$1"
    if [ -f "$theme_file" ]; then
        ln -sf "$theme_file" "$FOOT_CURRENT_LINK"
    fi
}

Gtk applications

The gsetting based command to update D-Bus works only for modern gtk apps. For legacy apps, we update the physical config file.

apply_gtk_theme() {
    local theme=$1
    local color_scheme=$2

    gsettings set org.gnome.desktop.interface gtk-theme "$theme"
    gsettings set org.gnome.desktop.interface color-scheme "$color_scheme"

    if [ -f "$GTK3_CONFIG" ]; then
        sed -i "s/^gtk-theme-name=.*/gtk-theme-name=$theme/" "$GTK3_CONFIG"
    fi
}

Sway

Similar to foot, we reset the symbolic file link for current theme using the force option to overwrite existing link. This is also logged to system log.

apply_sway_theme() {
    local theme_file="$1"
    local target="$SWAY_CONFIG_DIR/current_theme.conf"

    if [ -f "$theme_file" ]; then
        ln -sf "$theme_file" "$target"
        swaymsg reload
        logger "Symlinked $theme_file to $target"
    fi
}

Dark theme

The order of applying theme was choosen based on the response time of each option.


prabu@homepc2 ~> time gsettings set org.gnome.desktop.interface gtk-theme Nordic

________________________________________________________
Executed in   40.58 millis    fish           external
   usr time   17.67 millis    1.53 millis   16.14 millis
   sys time    6.99 millis    0.02 millis    6.97 millis

prabu@homepc2 ~> time gsettings set org.gnome.desktop.interface color-scheme prefer-dark

________________________________________________________
Executed in   37.77 millis    fish           external
   usr time   16.97 millis    0.71 millis   16.25 millis
   sys time    9.69 millis    1.03 millis    8.65 millis

prabu@homepc2 ~> time swaymsg reload

________________________________________________________
Executed in  356.76 millis    fish           external
   usr time    0.69 millis    0.69 millis    0.00 millis
   sys time    2.91 millis    1.03 millis    1.88 millis

Since swaymsg reload takes the longest time, it is applied at the end.

set_dark_theme() {
    echo "Switching to dark theme ($DARK_THEME)..."
        apply_foot_theme "$FOOT_DARK_CONFIG"
        pkill -SIGUSR1 foot
        apply_gtk_theme "$DARK_THEME" "prefer-dark"
        apply_sway_theme "$SWAY_DARK_CONFIG"
}

Light theme

set_light_theme() {
    echo "Switching to light theme ($LIGHT_THEME)..."
        apply_foot_theme "$FOOT_LIGHT_CONFIG"
        pkill -SIGUSR2 foot
        apply_gtk_theme "$LIGHT_THEME" "prefer-light"
        apply_sway_theme "$SWAY_LIGHT_CONFIG"
}

Default theme

Always initialize with dark theme. This option is invoked in sway config file. The option ${1:-} means “use $1 if it’s set, otherwise substitute an empty string”.

if [ "${1:-}" = "init" ]; then
    logger "Sway Init: Forcing dark theme"
    set_dark_theme
    exit 0
fi

Toggle logic

The toggle logic fetches the current theme from gsettings to toggle the theme.

CURRENT_GTK_THEME=$(gsettings get org.gnome.desktop.interface gtk-theme)
CURRENT_GTK_THEME=$(echo "$CURRENT_GTK_THEME" | tr -d "'")

if [ "$CURRENT_GTK_THEME" = "$DARK_THEME" ]; then
    set_light_theme
else
    set_dark_theme
fi

© Prabu Anand K 2020-2026