~3m16:06
saneAspect

How to Rice Hyprland (Part 6) | Theme Switcher

Mar 28, 2025

Read: ~3m · You save: 13 min

How to Create a Theme Switcher in Hyprland with Rofi (Part 6)

Learn to build a custom theme switcher for Hyprland with Rofi! Step-by-step guide to dynamic wallpapers, color schemes, and notifications.

This guide details the process of creating a custom theme switcher for the Hyprland window manager, leveraging Rofi for user interaction and a custom script to apply changes. The system allows users to select a wallpaper, which then dynamically updates the system's theme, including the wallpaper, terminal colors, and application themes.

System Overview and Setup

The core of this theme switching mechanism is a script, here named wallset, which takes a wallpaper image path as an argument. This script orchestrates several actions:

  1. Notification: It sends a notification to the user indicating that the theme is being changed.
  2. Wallpaper Application: It sets the chosen wallpaper using swww (Simple Wayland Wallpaper Utility). The command swww img --transition-type <type> --transition-step <steps> --transition-fps <fps> <image_path> is used, allowing for customizable transition effects, steps, and frame rates.
  3. Color Generation: It utilizes pywal to generate color schemes based on the selected wallpaper. Specific flags are used with pywal:
    • -n: Skips setting the wallpaper (as it's already handled by swww).
    • -s: Skips changing colors in terminals.
    • -t: Skips changing colors in TTY.
    • -e: Skips reloading xrdb, i3, sway, or polybar. These are omitted as the environment is Wayland.
  4. Application Theming:
    • Neovim: An extension, base64-pywal, is used to make Neovim adopt the generated pywal colors. This requires cloning the repository, building it, and adding a configuration line to init.lua. Executing python3 chad.py refreshes colors in open Neovim instances.
    • Spotify: spicetify is employed to adapt Spotify's theme to the pywal colors.
    • Dribbbl: This component is mentioned but deferred for explanation in a separate context.
    • Matugen: This tool, previously explained, generates Material You colors for various applications, including Hyprland, Waybar, and web applications. The configuration for these applications is stored in ~/.config/matugen/config.toml.
  5. Wayland Compositor Reload: hyprctl reload is used to refresh Hyprland's configuration.
  6. Notification Center Reload: swaync-client -R is executed to reload the Sway Notification Center, which also clears existing notifications.
  7. Final Notification: A success message is displayed to the user, confirming that the wallpaper and theme have been applied.

Path Configuration

To ensure the wallset script is accessible system-wide, its directory, ~/lo/bin, must be added to the system's PATH environment variable. For Zsh users, this is done by adding the following line to ~/.zshrc:

export PATH="$HOME/lo/bin:$PATH"

For Bash users, the configuration would be added to ~/.bash_profile.

Additionally, environment variables like TERM (set to kitty in this example) and QT_QPA_PLATFORMTHEME (set to gtk3 for Qt applications) can be configured.

Creating the wallset Backend Script

The wallset script, located in ~/lo/bin, handles the actual theme application.

Argument Handling

The script first checks if a wallpaper image path has been provided as an argument. If not, it displays a usage message: Usage: <program_name> <path_to_image> and exits with a non-zero status code.

if [ -z "$1" ]; then
  echo "Usage: $0 <path_to_image>"
  exit 1
fi

The provided image path is stored in the image variable:

image="$1"

Script Execution Flow

  1. Notification:
    notify-send "Changing theme" "Applying new wallpaper..."
    
  2. Wallpaper Setting:
    swww img --transition-type Center --transition-step 10 --transition-fps 60 "$image"
    
  3. Pywal Color Generation:
    wal -n -s -t -e --theme-name "$image" # Using image name for theme name
    
    Note: The original draft mentions pywal flags -n, -s, -t, -e. The example command includes --theme-name "$image" which is not a standard pywal flag for theme naming in this context, but rather a placeholder for a potential custom theme naming convention.
  4. Neovim Refresh:
    python3 ~/.config/nvim/base64-pywal/chad.py
    
  5. Spotify Refresh:
    spicetify update
    
  6. Matugen Configuration:
    matugen --config ~/.config/matugen/config.toml --wallpaper "$image"
    
  7. Hyprland Reload:
    hyprctl reload
    
  8. Sway Notification Center Reload:
    swaync-client -R
    
  9. Success Notification:
    notify-send "Theme Applied" "Wallpaper and theme updated successfully."
    

Integrating with Rofi

To enable theme switching via Rofi, a separate script, named wallify (or a similar user-chosen name), is created in ~/lo/bin. This script handles the user selection process.

Script Structure

  1. Store Current Directory: The script first saves the current working directory to a variable CWD for later use.
    CWD=$(pwd)
    
  2. Change to Wallpaper Directory: It then changes the directory to the location of the wallpaper images. If this fails, the script exits.
    cd ~/Pictures/Wallpapers || exit 1
    
  3. Set Internal Field Separator: The IFS variable is set to a newline character (\n) to correctly handle filenames with spaces.
    IFS=$'\n'
    
  4. User Selection with Rofi: The script uses Rofi to present a list of available wallpapers (JPG and PNG files) to the user.
    selected_wall=$(ls *.jpg *.png | rofi -dmenu -p "Choose Wallpaper: " -i)
    
    • ls *.jpg *.png: Lists all files ending with .jpg or .png in the current directory.
    • rofi -dmenu -p "Choose Wallpaper: " -i: Runs Rofi in dmenu mode, displaying the list of files. -p sets the prompt text, and -i enables case-insensitive matching.
  5. Apply Selected Theme: If a wallpaper is selected (i.e., selected_wall is not empty), the wallset backend script is called with the chosen wallpaper path.
    if [ -n "$selected_wall" ]; then
      ~/lo/bin/wallset "$selected_wall"
    fi
    
  6. Return to Original Directory: Finally, the script changes back to the original working directory.
    cd "$CWD" || exit 1
    

Making Scripts Executable

Both the wallset and wallify scripts must be made executable using the chmod command:

chmod +x ~/lo/bin/wallset
chmod +x ~/lo/bin/wallify

Keybind Configuration

To trigger the wallify script with a keyboard shortcut, users need to configure a keybind in their Hyprland configuration file (~/.config/hypr/hyprland.conf). For example, to use Super + R:

bind = $mainMod, R, exec, ~/lo/bin/wallify

After setting up these scripts and the keybind, pressing Super + R will launch Rofi, allowing the user to select a wallpaper. Upon selection, the wallset script will execute, applying the chosen wallpaper and updating the system's theme accordingly.

Introduction and Demonstration

Demonstrates the functionality of the theme switcher by selecting a wallpaper and observing system-wide changes, including notifications.

  • The theme switcher applies changes based on a selected wallpaper.
  • Notifications are displayed to confirm theme application.
  • The tool can be named by the user (e.g., 'wallify', 'change theme').

Environment Setup: PATH and Variables

Explains the necessity of adding `/home/user/.local/bin` to the system's PATH for script execution and briefly touches upon terminal and QT/GTK theme settings.

  • The directory ~/.local/bin must be added to the system's PATH.
  • For Zsh shell, modify ~/.zshrc with export PATH=$HOME/.local/bin:$PATH.
  • For Bash shell, modify ~/.bash_profile.
  • TERM variable sets the terminal emulator (e.g., Kitty).
  • QT_QPA_PLATFORMTHEME can set GTK3 themes for QT applications.

The `wallset-backend` Script

Details the creation and functionality of the `wallset-backend` script, including argument handling, notification display, wallpaper setting, and color generation using `pywal`.

  • The script is named wallset-backend and placed in ~/.local/bin.
  • It checks for a required image path argument; otherwise, it displays usage instructions.
  • Notifications are sent using notify-send.
  • Wallpapers are set using swww with options for transitions.
  • pywal is used to generate color schemes from the wallpaper.
  • Flags like -n, -s, -t, -e control pywal's behavior (skip wallpaper, colors, TTY, xrdb reload).

Color Theming Integration

Explains how to integrate `pywal` colors with Neovim and Spicetify, and how `mako` generates Material You colors for various applications.

  • A Neovim plugin (base46-pywal) can apply pywal colors to the editor.
  • Spicetify can be used to theme Spotify with pywal colors.
  • mako (or materia-gen) generates Material You colors for applications defined in ~/.config/mako/config.toml.
  • The web start page can also adopt Material You colors.

Refreshing Wayland and Notifications

Covers refreshing Wayland compositor (`Hyprland` or `Sway`) and the Sway notification center (`swaync`) after theme changes.

  • Wayland compositors like Hyprland or Sway can be restarted using commands like hyprctl reload or swaymsg reload (or mod+r).
  • Sway notification center (swaync) can be refreshed to clear notifications and reload its configuration.

Finalizing and Executing the Theme Switcher

Details the final success notification and the execution of the `wallset-backend` script with an example.

  • A final notification confirms successful theme application.
  • The script is executed by running wallset-backend <path_to_image>.
  • Example path: ~/Pictures/Wallpapers/some_wallhaven_wallpaper.png.

Integration with Rofi

Explains how to make the script executable and integrate it with Rofi for a graphical selection interface.

  • Make the script executable using chmod +x ~/.local/bin/<script_name>.
  • The rofi command is used to present a list of wallpapers.
  • The wallet script (a wrapper) is executed by a keybind to launch rofi.
  • Internal field separator (IFS) is set to newline to handle filenames with spaces.
  • The selected wallpaper path is passed to wallset-backend.

The `wallet` Rofi Integration Script

Provides the core logic for the `wallet` script, which prepares the wallpaper list for Rofi and calls the backend script upon selection.

  • The wallet script navigates to the wallpaper directory.
  • It handles potential errors during directory changes.
  • It iterates through .jpg and .png files to create a list for Rofi.
  • echo -e and echo -n are used for formatting output.
  • The output is piped to rofi -dmenu for user selection.
  • The selected wallpaper is passed to wallset-backend.
  • The script returns to the original working directory.