Skip to content

RhoMancer/temperlux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

147 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Temperlux

English | Deutsch | हिन्दी | Español | Français | العربية | বাংলা | Русский | Português | اردو | Indonesia | 中文 | 日本語 | 한국어 | Türkçe | Italiano | Polski | Українська | Nederlands | فارسی | Tiếng Việt | ไทย | Bahasa Melayu | Čeština | Magyar | Română

CI crates.io License: GPL-3.0-or-later Ko-fi

A brightness controller for external (DDC/CI) and internal (backlight) displays, written in Rust with GTK4/Libadwaita GUI.

Based on Luminance by sidevesh — rewritten from scratch with FFI-based DDC for performance and a testable architecture.

Temperlux — Angus (dark)

Features

Display control

  • GUI — per-display brightness sliders with live hardware control
  • CLI — full suite of commands for scripting and terminal use
  • Multi-monitor — supports any combination of DDC/CI external displays and internal backlights
  • Laptop support — internal backlight displays detected automatically via /sys/class/backlight
  • Hardware detection — FFI-based libddcutil integration for reliable display enumeration

Sync modes

Control brightness relationships across multiple displays:

Mode Behavior
Off Each display controlled independently
Same Value All displays set to the same brightness percentage
Proportional Displays maintain proportional brightness ratios

Brightness caps

Set per-display minimum and maximum brightness limits (0–100%). Caps apply to both GUI sliders and CLI commands:

# Clamp display 1 to range 20–80%
temperlux caps 1 --min 20 --max 80

Scheduling

Automate brightness changes based on time of day, sunrise, or sunset:

# Dim monitors at sunset
temperlux schedule add --name "Evening" --after-sunset 0 --monitors "all=30"

# Full brightness at sunrise
temperlux schedule add --name "Morning" --after-sunrise 0 --monitors "all=80"

# Specific time
temperlux schedule add --name "Night" --time "23:00" --monitors "ddc:1=10,ddc:2=15"

Sunrise/sunset calculation — set your geographic location for accurate solar timing:

temperlux schedule location --lat 41.88 --lon -87.63   # Chicago
temperlux schedule detect-location                       # auto-detect via IP

systemd timer integration — generate user timer units for headless scheduling:

temperlux schedule generate-timers

Display management

  • Rename — custom display names persisted across sessions
  • Reorder — drag-order displays in Preferences; order persists across restarts
  • Refresh — rescan for display hotplug changes without restarting

Display formatting

# Show/hide display numbers
temperlux config --show-numbers false

# Toggle 24-hour time format in schedule editor
temperlux config --use-24h true

# Show/hide brightness range labels
temperlux config --show-range-labels true

JSON output

Script-friendly JSON output for waybar, polybar, and other integrations:

temperlux list --json
[
  {"id": "ddc:1", "name": "Left Monitor", "brightness": 75, "type": "ddc"},
  {"id": "ddc:2", "name": "Right Monitor", "brightness": 60, "type": "ddc"},
  {"id": "backlight:intel_backlight", "name": "Built-in", "brightness": 100, "type": "backlight"}
]

Autostart

Optional "Start on login" toggle in Preferences. Installs a .desktop file in ~/.config/autostart/.

Error handling

Error messages auto-expire after 5 seconds — no need to dismiss them manually.

Theming

Temperlux includes 16 color themes with independent light and dark mode pickers. Choose separate palettes for each mode in Preferences — themes switch instantly without restart.

Available themes

Theme Light variants Dark variants Accent
Angus (brand) Angus (light) Angus (dark) Teal #006A6A
Catppuccin Latte Frappe, Macchiato, Mocha Mauve #8839EF
Nord Nord Polar Nord Frost blue #81A1C1
Gruvbox Gruvbox Light Gruvbox Dark Yellow #D79921
Solarized Solarized Light Solarized Dark Blue #268BD2
Dracula Dracula Purple #BD93F9
Rose Pine Rose Pine Dawn Rose Pine, Rose Pine Moon Pine #31748F

Screenshots

Dracula (dark) Catppuccin Latte (light)
Dracula Latte
Catppuccin Mocha (dark) Nord (dark)
Mocha Nord
Gruvbox Dark Angus (brand, dark)
Gruvbox Angus

How it works

  • Angus brand themes generate M3 CSS dynamically from design tokens
  • Community themes are pre-generated CSS files embedded at compile time via include_str!
  • CSS is applied at STYLE_PROVIDER_PRIORITY_USER using @define-color and CSS custom properties
  • The dark_notify signal from libadwaita's StyleManager triggers automatic theme reloading
  • All themes appear in both dropdowns — mismatch warnings appear when a dark-only theme is picked for light mode (or vice versa)

Themes are sourced from the Angus-Software-Theming pipeline, which maps community palettes to Material 3 semantic roles using WCAG contrast analysis.

Install

From source (recommended for GUI)

# Install dependencies
sudo apt install ddcutil libddcutil-dev libgtk-4-dev libadwaita-1-dev pkg-config

# Build and install (CLI + GUI)
make && sudo make install

This installs:

  • temperlux (CLI) → /usr/local/bin/
  • temperlux-gui (GUI) → /usr/local/bin/
  • Desktop entry → /usr/local/share/applications/
  • App icon → /usr/local/share/icons/hicolor/

From crates.io

# CLI only (no GUI)
cargo install temperlux

# With GUI
cargo install temperlux --features gui

Uninstall

sudo make uninstall

Usage

GUI

temperlux-gui

The GUI provides:

  • Per-display brightness sliders with live hardware control
  • Preferences dialog for sync mode, caps, display names, ordering, and themes
  • Schedule editor for creating and managing brightness profiles
  • One-click refresh for display hotplug changes

CLI

# List all displays
temperlux list

# JSON output for scripting
temperlux list --json

# Get brightness of display 1
temperlux get 1

# Set display 1 to 75%
temperlux set 1 --percent 75

# Set all displays to 50%
temperlux set --percent 50

# Increase all displays by 10%
temperlux increase --percent 10

# Decrease display 2 by 5%
temperlux decrease 2 --percent 5

# Rename a display
temperlux rename 1 "Left Monitor"

# Set brightness caps
temperlux caps 1 --min 20 --max 80

# Set sync mode
temperlux sync proportional

# Reorder displays
temperlux order 1 2    # swap positions of display 1 and 2

# Toggle autostart
temperlux autostart enable

Scheduling (CLI)

# List schedule profiles
temperlux schedule list

# Create a profile
temperlux schedule add --name "Evening" --after-sunset 0 --monitors "all=30"

# Edit a profile
temperlux schedule edit --name "Evening" --time "20:00"

# Delete a profile
temperlux schedule delete "Evening"

# Apply schedules now (checks if any are due)
temperlux schedule apply

# Set location for sunrise/sunset
temperlux schedule location --lat 41.88 --lon -87.63
temperlux schedule detect-location

# Generate systemd user timers
temperlux schedule generate-timers

Shell completions

# Bash
temperlux completions bash > ~/.local/share/bash-completion/completions/temperlux

# Zsh
temperlux completions zsh > ~/.zfunc/_temperlux

# Fish
temperlux completions fish > ~/.config/fish/completions/temperlux.fish

# Elvish
temperlux completions elvish > ~/.config/elvish/completions/temperlux

Internationalization

Temperlux supports 26 languages out of the box, covering ~80% of the world population and ~97%+ of Linux desktop users. The UI and CLI automatically detect your system language from LANG/LC_ALL.

Supported languages

Language Code Speakers Tier
English en 1.5B Default
Chinese (Mandarin) zh 1.1B Tier 1
Hindi hi 602M Tier 1
Spanish es 548M Tier 1
French fr 280M Tier 1
Arabic ar 274M Tier 1
Bengali bn 272M Tier 1
Russian ru 258M Tier 1
Portuguese pt 257M Tier 1
Urdu ur 231M Tier 1
Indonesian id 199M Tier 1
German de 134M Tier 1
Japanese ja 125M Tier 2
Korean ko 81M Tier 2
Turkish tr 88M Tier 2
Italian it 67M Tier 2
Polish pl 41M Tier 2
Ukrainian uk 41M Tier 2
Dutch nl 25M Tier 2
Persian fa 77M Tier 3
Vietnamese vi 85M Tier 3
Thai th 60M Tier 3
Malay ms 60M Tier 3
Czech cs 10M Tier 3
Hungarian hu 13M Tier 3
Romanian ro 24M Tier 3

Testing a language

# German GUI
LANG=de_DE.UTF-8 temperlux-gui

# Japanese CLI help
LANG=ja_JP.UTF-8 temperlux --help

Or change your system language in GNOME Settings → Region & Language.

Adding a new language

  1. Copy locales/en.yml to locales/<lang>.yml
  2. Translate the values (keep keys identical)
  3. Rebuild — translations are embedded at compile time
  4. Run cargo test -- --test-threads=1 — the test suite verifies every key resolves in every locale

The i18n system uses rust-i18n — pure Rust, no system dependencies.

Build

# CLI only (default)
cargo build --release

# With GUI
cargo build --release --features gui

# Run tests
cargo test

# Lint
cargo clippy -- -D warnings

Requirements

  • Rust 1.82+
  • libddcutil 2.0+ and development headers
  • GTK4 + Libadwaita 1.2+ (for GUI feature)
  • pkg-config

Install dependencies (Debian/Ubuntu)

sudo apt install ddcutil libddcutil-dev libgtk-4-dev libadwaita-1-dev pkg-config

Install dependencies (Fedora)

sudo dnf install ddcutil ddcutil-devel gtk4-devel libadwaita-devel pkg-config

Install dependencies (Arch)

sudo pacman -S ddcutil gtk4 libadwaita pkgconf

Architecture

src/
  main.rs            CLI entry point (dispatches to subcommands)
  cli.rs             clap argument definitions + shell completions
  i18n.rs            Internationalization (tr/tr_args, locale normalization)
  autostart.rs       Autostart .desktop file management
  settings.rs        JSON config (~/.config/temperlux/settings.json)
  sync.rs            Sync mode math (proportional map, delta apply)
  caps.rs            Min/max brightness clamping
  schedule.rs        Schedule profile definitions + sunrise/sunset calc
  display/
    ddc_ffi.rs       DdcService (FFI libddcutil, parallel writes, command coalescing)
    backlight.rs     RealBacklightProvider (/sys/class/backlight)
    manager.rs       DisplayManager (unified display operations)
    provider.rs      BacklightProvider trait
  gui/
    window.rs        Main window, display rows, preferences, schedule editor
    viewmodel.rs     DisplayRow data model
    debounce.rs      Slider debouncing + worker pool
    schedule.rs      Schedule UI (profile editor, time pickers)
    theme.rs         Color theme system (brand CSS, community themes, live switching)
    themes/          14 embedded community theme CSS files
    widgets/         Custom GTK4 widgets
locales/             Translation files (en, de, es, fr, pt, ru, zh, it, pl, nl, ja, ko, tr, uk, id, hi, ar, bn, ur, fa, vi, th, ms, cs, hu, ro)

Both CLI and GUI use DdcService (FFI libddcutil) for reliable display detection and fast parallel DDC writes with command coalescing. Hardware access is behind provider traits with mock implementations for testing.

Testing

The codebase has 185 tests with mock-based architecture — all hardware access is behind traits (DdcProvider, BacklightProvider), enabling full unit testing without physical displays. The i18n test suite verifies every translation key resolves in all 25 locales.

cargo test                           # run all tests
cargo test --features gui            # include GUI tests
cargo test -- --test-threads=1       # serial (required for locale-switching tests)
cargo test -- --nocapture sync_test  # verbose specific test

Configuration

Config file: ~/.config/temperlux/settings.json

{
  "sync_mode": "proportional",
  "show_display_numbers": true,
  "use_24h_time": true,
  "show_range_labels": true,
  "autostart": false,
  "theme_mode": "system",
  "light_theme": "angus_light",
  "dark_theme": "angus_dark",
  "display_order": ["ddc:2", "ddc:1", "ddc:3"],
  "displays": {
    "ddc:1": {
      "min_brightness": 20.0,
      "max_brightness": 80.0,
      "custom_name": "Left Monitor"
    },
    "ddc:2": {
      "min_brightness": 0.0,
      "max_brightness": 100.0,
      "custom_name": "Right Monitor"
    }
  }
}

Settings reference

Field Type Default Description
sync_mode "off" | "same" | "proportional" "off" Brightness sync across displays
show_display_numbers bool true Show index numbers in display names
use_24h_time bool true 24h format in schedule editor
show_range_labels bool true Show min/max range labels on sliders
autostart bool false Launch on login
theme_mode "system" | "light" | "dark" "system" UI color mode
light_theme string "angus_light" Color palette for light mode
dark_theme string "angus_dark" Color palette for dark mode
display_order string[] Display ordering
displays object Per-display config (caps, names)

CI/CD

  • Build + Test — every push to master
  • Clippy — lint with -D warnings
  • Coverage tollgate — 80% line coverage required
  • Diff coverage — new code must meet coverage threshold
  • Release — tag push triggers GitHub Release (binary tarball) + crates.io publish

Diagnostics

# Run the diagnostic binary to troubleshoot display detection
ddc-diag

This checks libddcutil version, I2C device permissions, and DDC/CI capability for each detected display.

License

GPL-3.0-or-later. See LICENSE and NOTICE.

This project is a rewrite of Luminance by sidevesh, which is also licensed under GPL-3.0-or-later.

Community themes are individually licensed under MIT by their respective authors:

Support

If Temperlux makes your day a little brighter, consider supporting development:

Ko-fi

Packages

 
 
 

Contributors

Languages