Skip to content

jjo/drm-colortemp

Repository files navigation

DRM Color Temperature Control for COSMIC DE

Build

A workaround for adjusting screen color temperature on COSMIC Desktop Environment (Pop!_OS), until native gamma control is implemented (cosmic-comp#2059).

The Problem

COSMIC DE doesn't implement wlr-gamma-control-unstable-v1 protocol yet, so tools like redshift, wlsunset, and gammastep don't work.

The Solution

This package provides:

  • Direct DRM manipulation tool to set color temperature
  • Automatic daemon that applies settings when you switch TTYs (auto, force warm, force cool)
  • Config file with live reload (changes apply instantly via inotify)
  • Desktop notifications to remind you when to apply (optional)

How It Works

  1. A daemon runs in the background monitoring TTY switches
  2. You press Ctrl+Alt+F3 (switches to TTY3) for automatic time-based temperature
  3. Daemon detects the switch and applies gamma (COSMIC releases DRM lock on TTY switch)
  4. You immediately press Ctrl+Alt+F2 (back to COSMIC)
  5. Total time: ~2 seconds, screen flickers briefly

You can also force a specific temperature:

  • Ctrl+Alt+F4 (TTY4) - Force warm/night temperature (e.g. 3500K)
  • Ctrl+Alt+F5 (TTY5) - Force cool/day temperature (6500K)

The gamma settings persist even after switching back to COSMIC!

Build Dependencies (Pop!_OS / Ubuntu)

sudo apt install build-essential libdrm-dev linux-libc-dev libnotify-bin
  • build-essential - gcc, make
  • libdrm-dev - DRM/KMS headers and library
  • linux-libc-dev - Linux kernel headers (ioctl definitions)
  • libnotify-bin - notify-send for desktop notifications (optional)

Quick Start

# Clone and build
git clone https://github.com/jjo/drm-colortemp.git
cd drm-colortemp
make

# Interactive installer (recommended)
sudo ./scripts/install_daemon.sh

# Or non-interactive
sudo make install
sudo make install-notifier  # Optional: desktop notifications
sudo systemctl enable --now drm-colortemp-daemon
sudo systemctl enable --now drm-colortemp-notifier  # Optional

# Use it! Press Ctrl+Alt+F3, then immediately Ctrl+Alt+F2

Pre-built binaries are also available on the Releases page.

Daily Usage

With Notifications (Optional)

At 19:55 (if sunset is 20:00), you'll see:

🌙 Night Mode Ready
Press Ctrl+Alt+F3 then F2 to apply warm 3500K

Press Ctrl+Alt+F3 then Ctrl+Alt+F2. Done!

Without Notifications

Just press Ctrl+Alt+F3 then Ctrl+Alt+F2 whenever you want to apply:

  • Evening (after 20:00): Warm 3500K applied
  • Morning (after 08:00): Neutral 6500K applied

Force Override

Override time-based logic anytime:

  • Ctrl+Alt+F4 then Ctrl+Alt+F2 - Force warm (NIGHT_TEMP)
  • Ctrl+Alt+F5 then Ctrl+Alt+F2 - Force cool (DAY_TEMP)

Manual Usage

You can also use the tool directly (requires TTY):

# From TTY (Ctrl+Alt+F3):
sudo drm_colortemp -d /dev/dri/card1 -t 3500

Configuration

Edit the config file (changes apply automatically via inotify, no restart needed):

sudo nano /etc/default/drm-colortemp.conf

Options

Option Default Description
DEVICE (auto) DRM device — omit to auto-detect all cards with CRTCs
DEVICE1 … DEVICE8 Explicit multi-card setup (see below)
DAY_TEMP 6500 Daytime temperature (Kelvin)
NIGHT_TEMP 3500 Nighttime temperature (Kelvin)
SUNSET_HOUR 20 When to switch to night mode (24h)
SUNRISE_HOUR 8 When to switch to day mode (24h)
MONITOR_TTY 3 Which TTY to monitor for auto-apply
WARM_TTY 4 TTY to force warm (night) temperature
COOL_TTY 5 TTY to force cool (day) temperature
NOTIFY_ENABLED 0 Enable desktop notifications (0/1)
NOTIFY_USER "" Username to send notifications to
NOTIFY_MINUTES_BEFORE 5 Minutes before sunset/sunrise to notify
VERBOSE 0 Enable verbose logging (0/1)

Multi-Card / Device Selection

By default (no DEVICE key set), the daemon auto-detects all DRM cards that have active CRTCs and applies temperature to all of them simultaneously.

For explicit control:

# Single card (legacy syntax, still supported)
DEVICE="/dev/dri/card1"

# Multi-card: apply to two GPUs at once
DEVICE1="/dev/dri/card0"
DEVICE2="/dev/dri/card1"

Up to 8 devices (DEVICE1DEVICE8) are supported. If both DEVICE and DEVICE1 are specified, DEVICE1 takes the slot 1 position.

Color Temperature Guide

  • 6500K - Neutral daylight (default)
  • 5500K - Slightly warm
  • 4500K - Warm
  • 3500K - Evening/sunset
  • 2700K - Warm incandescent bulb
  • 2000K - Very warm candlelight

Desktop Notifications

# Install notification service (if not done during initial install)
sudo make install-notifier

# Set in /etc/default/drm-colortemp.conf:
#   NOTIFY_ENABLED=1
#   NOTIFY_USER="your_username"

sudo systemctl enable --now drm-colortemp-notifier

See NOTIFICATIONS.md for detailed documentation.

Systemd Service Management

# Main daemon
sudo systemctl status drm-colortemp-daemon
sudo systemctl restart drm-colortemp-daemon
sudo journalctl -u drm-colortemp-daemon -f

# Notification daemon (if installed)
sudo systemctl status drm-colortemp-notifier
sudo journalctl -u drm-colortemp-notifier -f

Troubleshooting

"Permission denied" errors

  • Ensure daemon is running: sudo systemctl status drm-colortemp-daemon
  • Check device path in config: /etc/default/drm-colortemp.conf
  • Verify you're on the correct TTY when applying

Color not applying

  • Check logs: sudo journalctl -u drm-colortemp-daemon -f
  • Ensure you switch to TTY3 (not TTY1 or TTY2)
  • Verify the tool works manually from TTY3

Config changes not detected

  • Check logs for inotify errors
  • Make sure config file exists: ls -la /etc/default/drm-colortemp.conf
  • Inotify watches the directory, so any editor (nano, vim, etc.) should work

Notifications not appearing

  • Check NOTIFY_ENABLED=1 and NOTIFY_USER in config
  • Ensure notify-send is installed: sudo apt install libnotify-bin
  • Test manually: sudo ./scripts/drm-colortemp-notify.sh your_username 3500 night

Finding your DRM device

ls -la /dev/dri/
# Look for card0, card1, etc.

The daemon auto-detects all cards with CRTCs when no DEVICE is configured. To target specific cards, set DEVICE1, DEVICE2, etc. in /etc/default/drm-colortemp.conf.

Uninstallation

sudo make uninstall
# Config file is preserved at /etc/default/drm-colortemp.conf
# Remove manually if desired: sudo rm /etc/default/drm-colortemp.conf

Rust Implementation (v2.0)

New in v2.0: Complete rewrite in Rust for improved safety and maintainability!

The Rust implementation (drm-colortemp-rs) provides:

  • Memory safety - No segfaults, buffer overflows, or use-after-free bugs
  • Thread-safe daemon - Proper signal handling and concurrent access
  • Better error messages - Clear, actionable error output
  • Same functionality - 100% feature parity with C version
  • Smaller binary - ~1.8 MB stripped (vs ~3 MB for C version)

Building the Rust Version

# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Build release version
cd drm-colortemp
cargo build --release

# Install binary
sudo cp target/release/drm-colortemp-rs /usr/local/bin/drm-colortemp
sudo cp drm-colortemp.service /etc/systemd/system/
sudo systemctl daemon-reload

Rust vs C Version

Feature C Version Rust Version
CLI tool
Daemon mode
Config parsing
Inotify watch
Signal handling
Memory safety ⚠️ Manual ✅ Compile-time
Binary size ~3 MB ~1.8 MB
Build time ~5s ~45s

Both versions are supported. The C version remains available for systems without Rust.


Original C Implementation

Why This Works

The Linux DRM (Direct Rendering Manager) subsystem controls display output. Wayland compositors like COSMIC hold "DRM master" - exclusive control over the display. This prevents other processes from adjusting gamma.

When you switch to a text console (TTY3), COSMIC temporarily releases DRM master. Our daemon detects this switch and immediately applies the gamma settings before COSMIC reclaims control. When you switch back, the settings persist because COSMIC doesn't actively reset them.

Components

  1. drm_colortemp - CLI tool using DRM ioctls to set gamma LUTs
  2. drm_colortemp_daemon - Monitors VT switches via VT_GETSTATE ioctl
  3. drm_device - Shared DRM device detection and auto-fallback
  4. inotify - Watches config file directory for changes without polling
  5. systemd - Manages daemon lifecycle and logging
  6. notification system - Optional reminder service with desktop notifications

Why Not Just Use Redshift?

COSMIC needs to implement the wlr-gamma-control-unstable-v1 Wayland protocol for tools like redshift and wlsunset to work. Until then, direct DRM manipulation is the only option.

Track progress: pop-os/cosmic-comp#2059

Future

Once COSMIC implements wlr-gamma-control-unstable-v1, you can switch to:

  • wlsunset - Automatic sunset/sunrise calculation
  • gammastep - Redshift fork for Wayland
  • Native COSMIC settings

Until then, this provides a functional workaround!

License

Apache License 2.0 - see LICENSE

Credits

Color temperature algorithm based on Tanner Helland's work: http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/

Contributing

See CONTRIBUTING.md for contribution guidelines.

This is a workaround tool. The real solution is for COSMIC to implement gamma control protocol. Consider contributing to https://github.com/pop-os/cosmic-comp.

About

DRM Color Temperature Control for COSMIC DE (workaround)

Resources

License

Contributing

Stars

76 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors