Files
DankMaterialShell/quickshell/Modals
KIDult2226 1c5cae105b feat(display): per-output ICC color profiles and color temperature
Rebuild of #3388 on current master: the previous branch was cut from an
older base and reverted unrelated fixes in the gamma stack and the display
settings UI.

ICC profiles:
- core/internal/icc: ICC v2/v4 parser (TRC, LUT8/16 and parametric curves,
  vcgt, description/version/color space) plus gamma ramp generation, with
  synthetic coverage and optional vendor-profile tests (ICC_TEST_DIR).
- wayland manager: load iccProfiles from the compositor's DMS config dir,
  build the ramp from the profile when one is set (falling back to the
  temperature ramp when it is missing or unparsable), and re-apply on
  output hotplug and after resume.
- ICC ramps apply while the night light schedule is disabled; outputs
  without a profile keep an identity ramp.
- desc/mluc offsets are validated before slicing, so a malformed profile
  returns an error instead of panicking the daemon.

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

Gamma control lifecycle:
- needsControls() now keeps the controls alive for configured ICC profiles
  and per-output temperatures, so toggling the night light off no longer
  destroys the controls and drops the ramps.
- Re-apply paths clear the per-output dedup state instead of adding a
  manager-level guard, which would have suppressed contrast-only writes and
  the post-resume forced resend (#1235), and left a recreated control
  without a ramp.
- Monitor sleep/disconnect still re-establishes controls when an output
  comes back.

IPC / CLI / UI:
- wayland.icc.{getStatus,apply,remove,listOutputs,setTemp,getTemps}
- dms icc list | info <file> | apply <output> <file> | remove <output> | status
- Display Config output card gains a Color Profile row (browse/apply/remove
  with description, version, color space and active state) and a per-output
  color temperature slider, backed by Services/ICCService.qml.

Config path:
- DMSConfigDir() follows the compositor layout (niri/dms, hypr/dms,
  mango/dms) via the shared compositor detection and utils.XDGConfigHome(),
  replacing the hardcoded niri path in both the manager and `dms icc`.

Tests: TZ=UTC go test ./... (60 packages ok), including red/green coverage
for the icc parser bounds checks and needsControls().
2026-09-13 00:34:55 +08:00
..