Skip to content

Theming System

Joseph Chacko edited this page Jul 22, 2026 · 2 revisions

Theming System

Relevant source files

The following files were used as context for generating this wiki page:

The Aurora theming system provides an end-to-end pipeline for dynamic UI customization. It supports hot-reloading from a configuration file, allowing the user to change the entire color palette of the application without restarting the daemon or the player.

System Overview

The theming lifecycle spans across the daemon, the protocol, and the GUI frontend.

  1. Storage: Themes are defined in ~/.config/aurora-player/config.toml.
  2. Detection: The theme_thread in the daemon watches this file for changes.
  3. Broadcast: Upon change, the daemon sends a Response::Theme IPC message to all connected clients.
  4. Conversion: The player receives hex strings and converts them to Slint-compatible color objects.
  5. Application: A global Theme singleton in Slint propagates these colors to all UI components.

Theming Pipeline Data Flow

The following diagram illustrates how a change in the configuration file propagates through the system entities.

Theme Propagation Flow

graph TD
    subgraph "Filesystem Space"
        CONFIG["config.toml"]
    end

    subgraph "aurora-daemon (Natural Language Space)"
        WATCHER["theme_thread::init"]
        GET_CFG["theme_thread::get_config"]
        STATE["StateStruct.theme"]
    end

    subgraph "aurora-protocol"
        RES_THEME["Response::Theme(Theme)"]
    end

    subgraph "aurora-player (Code Entity Space)"
        IFACE["interface.rs: unix_recver"]
        HEX_CONV["interface.rs: hex_to_u8"]
        SLINT_THEME["Types.slint: global Theme"]
    end

    CONFIG -.->|"inotify event"| WATCHER
    WATCHER --> GET_CFG
    GET_CFG -->|"TOML Parse"| STATE
    STATE -->|"Broadcast"| RES_THEME
    RES_THEME --> IFACE
    IFACE --> HEX_CONV
    HEX_CONV -->|"aurora.set_Theme_..."| SLINT_THEME
Loading

Sources: daemon/src/theme_thread.rs:32-54, app/src/interface.rs:58-72, app/src/interface.rs:191-204


Configuration & Presets

The theme is controlled by a TOML file located at $XDG_CONFIG_HOME/aurora-player/config.toml daemon/src/theme_thread.rs:19-22. If the file is missing, the system falls back to a "Gruvbox-inspired" hardcoded default daemon/src/theme_thread.rs:7-18.

config.toml Format

The configuration defines 10 specific color keys that map to the UI's functional areas:

Key Description Typical Use Case
bgd0 Deepest Background Main window root background
bgd1 Secondary Background Active tab, sidebar elements
bgd2 Surface Background Cards, search bars, containers
bgd3 Elevated Background Hover states, borders
bgd4 Highlight Background Pressed states, active accents
txt1 Primary Text Song titles, active labels
txt2 Secondary Text Artist names, durations, inactive labels
acct Accent Icons, sliders, active tab text
srch Search Background Specific background for the search input
btns Button/Icon color Standard color for transport controls

Bundled Presets

The project includes several bundled presets within the themes/config.toml file, including:

Sources: themes/config.toml:1-77, daemon/src/theme_thread.rs:6-18


Daemon Implementation: theme_thread

The daemon manages the theme via a dedicated background thread initialized during startup.

File Watching and Hot-Reload

The theme_thread::init function uses the notify crate to establish a recursive watcher on the configuration directory daemon/src/theme_thread.rs:37-39. It listens for Create, Modify, or Remove events daemon/src/theme_thread.rs:43.

When an event is detected:

  1. get_config() is called to re-read the TOML file daemon/src/theme_thread.rs:44.
  2. The StateStruct is updated with the new Theme struct daemon/src/theme_thread.rs:45.
  3. helpers::send_to_all broadcasts the new theme to all connected Unix socket clients via Response::Theme(theme) daemon/src/theme_thread.rs:46.

Sources: daemon/src/theme_thread.rs:32-54, daemon/src/theme_thread.rs:6-30


Frontend Implementation: interface.rs

The player application receives the theme as a set of hex strings (e.g., "#cba6f7") and must apply them to the Slint runtime.

Hex to Color Conversion

Slint requires a slint::Color type, whereas the protocol transmits strings. The hex_to_u8 utility function handles this conversion:

Applying the Theme

Within the unix_recver loop, the Response::Theme(theme) variant triggers an update to the Slint global singleton app/src/interface.rs:191-204. This is executed within app.upgrade_in_event_loop to ensure thread safety when interacting with the UI app/src/interface.rs:192.

Code Mapping: IPC Response to Slint Global

graph LR
    subgraph "Response::Theme Handler"
        direction TB
        A["theme.bgd0"] -->|"hex_to_u8"| B["aurora.set_Theme_bgd0"]
        C["theme.acct"] -->|"hex_to_u8"| D["aurora.set_Theme_acct"]
        E["theme.txt1"] -->|"hex_to_u8"| F["aurora.set_Theme_txt1"]
    end
    
    B --> G["Types.slint: global Theme"]
    D --> G
    F --> G
Loading

Sources: app/src/interface.rs:20-28, app/src/interface.rs:191-204


Slint Integration: Theme Singleton

The UI components do not define their own colors. Instead, they bind to properties of the global Theme declared in Types.slint.

Global Definition

The Theme global contains in-out properties for every color key defined in the protocol app/ui/Types.slint:40-51.

Component Binding

UI components import the Theme and use its properties for backgrounds, text colors, and animations. For example, the TabButton changes its background and text color based on whether it is active, using Theme.bgd1, Theme.bgd2, and Theme.acct app/ui/TabSelectorView.slint:8-16.

Because Slint properties are reactive, calling aurora.set_Theme_bgd1(...) from Rust automatically triggers a re-render of every component referencing that property across the entire application.

Sources: app/ui/Types.slint:40-51, app/ui/TabSelectorView.slint:1-16

Clone this wiki locally