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 .
Initialization
Let any reference to an unset variable become a fatal error.
#!/bin/sh
set -u
Variables
Light and dark theme names and config paths for Sway, Foot etc are defined here.
Initially i used Adwaita as light theme, but later moved to Nordic-Polar. I’m using Nordic-Darker and Nordic-Polar for dark and light theme. The Icon theme is Nordzy where dark variant is used for dark mode. Since these themes and icons were earlier shared between Arch and Alpine Linux , i maintained these in a common folder and created soft links from each OS.
DARK_THEME="Nordic-darker"
LIGHT_THEME="Nordic-Polar"
DARK_ICONS="Nordzy-dark"
LIGHT_ICONS="Nordzy"
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/nord_light.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.
Papirus icons
I tested Papirus icons with Papirus-Nord colors on 2026-07-04, it required a number of changes in addition to a helper function. Papirus-Dark and Papirus-Light icons were used for dark and light mode respectively, with folder colors set via papirus folders script. The folder color variables needs to be added if Papirus icons are used.
PAPIRUS_DARK_FOLDER_COLOR="frostblue1"
PAPIRUS_LIGHT_FOLDER_COLOR="polarnight1"
The install scripts provided by the Papirus-Nord expects elevated privileges. I used the following script to copy over Papirus-Nord to Papirus, Papirus-Dark and Papirus-Light folders.
#!/bin/sh
PAPIRUS_DIR="/data/docs/Computer/linux/icons/papirus-icon-theme-20250501"
for theme in Papirus Papirus-Dark Papirus-Light; do
for size in 22x22 24x24 32x32 48x48 64x64; do
cp -f "Icons/$size/"* "$PAPIRUS_DIR/$theme/$size/places/"
done
done
The below command will show Papirus-Nord colors, if the above step worked correctly.
papirus-folders -l --theme Papirus-Dark
To use Papirus-Nord colors, the papirus-folders script used by the papirus icon theme can still expect elevated privileges even if the icons are installed in folders with write privileges as it tries to remember the last-used color in a config file at /var folder. Since this tracking is done by this script, we use the papirus-folders script with –once flag to avoid permission errors.
apply_folder_color() {
local icons=$1
local color=$2
if command -v papirus-folders >/dev/null 2>&1; then
papirus-folders --once -C "$color" --theme "$icons"
else
logger "papirus-folders not found; skipping folder recolor"
fi
}
The above helper function needs to be called in set_dark_theme and set_light_theme functions respectively.
apply_folder_color "$DARK_ICONS" "$PAPIRUS_DARK_FOLDER_COLOR"
apply_folder_color "$LIGHT_ICONS" "$PAPIRUS_LIGHT_FOLDER_COLOR"
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
local icons=$3
gsettings set org.gnome.desktop.interface gtk-theme "$theme"
gsettings set org.gnome.desktop.interface color-scheme "$color_scheme"
gsettings set org.gnome.desktop.interface icon-theme "$icons"
if [ -f "$GTK3_CONFIG" ]; then
sed -i "s/^gtk-theme-name=.*/gtk-theme-name=$theme/" "$GTK3_CONFIG"
sed -i "s/^gtk-icon-theme-name=.*/gtk-icon-theme-name=$icons/" "$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" "$DARK_ICONS"
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" "$LIGHT_ICONS"
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