Skip to content

feat(display): per-output ICC color profiles and color temperature - #3388

Open
KIDult2226 wants to merge 7 commits into
AvengeMedia:masterfrom
KIDult2226:icc-per-output
Open

feat(display): per-output ICC color profiles and color temperature#3388
KIDult2226 wants to merge 7 commits into
AvengeMedia:masterfrom
KIDult2226:icc-per-output

Conversation

@KIDult2226

@KIDult2226 KIDult2226 commented Sep 10, 2026

Copy link
Copy Markdown

Description

Adds per-output ICC color profile support and per-output color temperature to the night light / gamma stack.

ICC profiles

  • New core/internal/icc package: ICC v2/v4 parser (TRC curves, LUT8/LUT16 and parametric curves, vcgt, description/version/color space metadata) with unit tests.
  • The wayland manager loads iccProfiles from the night light config (~/.config/niri/dms/wayland.json), builds gamma ramps from the parsed profile per output, falls back to temperature ramps when a profile is missing or unparsable, and re-applies on output hotplug and after resume.
  • ICC ramps are applied even when the global night light is off (outputs without a profile keep identity/neutral), so a calibrated profile is not silently dropped when the schedule is disabled.

Per-output temperature

  • outputTemps in the same config; SetOutputTemp accepts 1000-10000K and the Display Config slider exposes the full 3000-10000K range, which matters for displays calibrated at a higher white point (e.g. a 7000K-calibrated ICC profile).

IPC / CLI

  • wayland.icc.getStatus, wayland.icc.apply, wayland.icc.remove, wayland.icc.listOutputs, wayland.icc.setTemp, wayland.icc.getTemps.
  • dms icc list | info <file> | apply <output> <file> | remove <output> | status.

UI

  • Display Config output card gains a Color Profile row (browse/apply/remove with description, version, color space and active state) plus a per-output color temperature slider, backed by quickshell/Services/ICCService.qml.

Included fix

  • LoadConfig() now takes its fallback values from DefaultConfig() and covers Contrast. Validate() rejects Contrast == 0, so night light configs written before that field existed aborted manager construction and took gamma/ICC down entirely (wayland manager not initialized).

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Refactor / internal cleanup
  • Documentation
  • Other

Related issues

Screenshots / video

Display Config output cards with the new Color Profile row (browse / apply / remove, showing an applied profile with version, color space and active state) and the per-output Color Temp slider set to 7000K on the calibrated display:

Display Config: Color Profile row and per-output color temperature

Checklist

  • My code follows the conventions in CONTRIBUTING.md
  • I have tested my changes locally
  • New user-facing strings are wrapped in I18n.tr() with translator context, reusing existing terms where possible
  • Go changes: ran make fmt, added/updated tests, make test passes (TZ=UTC go test ./... -> 51 ok, 0 fail), and go mod tidy is clean
  • QML changes: ran make lint-qml with no new warnings
  • I have opened a corresponding pull request in dlx-docs to document any new behaviors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant