AvengeMedia / AvengeMedia/DankMaterialShell

Night mode: software overlay fallback when hardware gamma is unavailable (Apple Silicon/Asahi)

Open
#2,061 0 comments 1 reaction 0 assignees View on GitHub
feature request
Dominant language
QML
Stars
8.1k
Forks
515
Avg merge
1d 8h
Merged PRs (30d)
102

Description

## Problem

On Apple Silicon (Asahi Linux), DMS night mode reports as enabled but has no visible effect. The DMS backend initializes gamma control successfully via `zwlr_gamma_control_v1`, but the compositor (niri) cannot apply the gamma LUT because the Apple DCP kernel driver does not expose the `GAMMA_LUT` CRTC property.

This affects all Apple Silicon Macs running Asahi Linux with niri (and likely sway/Hyprland too).

The `gammaControlAvailable` property in `DisplayService` reports `true` because the Wayland protocol initializes without error — but the actual display color never changes.

## Root cause

- Apple DCP DRM driver: `gamma_size=0`, no `GAMMA_LUT` property
- Niri accepts `zwlr_gamma_control_v1` requests but silently no-ops since there's no LUT to set
- DMS backend sees success, `DisplayService.gammaControlAvailable = true`
- Upstream tracker: [AsahiLinux/linux#91](https://github.com/AsahiLinux/linux/issues/91)
- Niri CTM fallback request: [niri-wm/niri#3672](https://github.com/niri-wm/niri/issues/3672)

## Workaround (working DMS plugin)

I wrote a daemon plugin that creates a click-through layer-shell overlay with a warm color tint when night mode is enabled. It works well as an immediate workaround:

```qml
// ~/.config/DankMaterialShell/plugins/nightOverlay/NightOverlay.qml
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services

Item {
id: root
property var pluginService: null
property string pluginId: ""

readonly property bool shouldShow: SessionData.nightModeEnabled

function tempToColor(kelvin) {
if (kelvin >= 6000) return Qt.rgba(1, 0.82, 0.48, 0.04);
if (kelvin >= 5000) return Qt.rgba(1, 0.68, 0.28, 0.09);
if (kelvin >= 4000) return Qt.rgba(1, 0.56, 0.18, 0.14);
if (kelvin >= 3500) return Qt.rgba(1, 0.46, 0.10, 0.18);
if (kelvin >= 3000) return Qt.rgba(1, 0.38, 0.06, 0.22);
return Qt.rgba(1, 0.32, 0.03, 0.26);
}

readonly property color tintColor: tempToColor(SessionData.nightModeTemperature)

Variants {
model: root.shouldShow ? Quickshell.screens : []

PanelWindow {
required property var modelData
screen: modelData
anchors { left: true; right: true; top: true; bottom: true }
mask: Region {}
WlrLayershell.namespace: "dms:night-overlay"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
Rectangle {
anchors.fill: parent
color: root.tintColor
Behavior on color { ColorAnimation { duration: 500 } }
}
}
}
}
```

## Feature request

Consider adding a built-in software fallback to DMS's gamma control system:

1. **Detect gamma failure**: After enabling gamma via the backend, check if `gammaCurrentTemp` actually changes (with a short timeout). If it stays at 0, the hardware path is broken.
2. **Overlay fallback**: Create a click-through layer-shell overlay (exactly like the plugin above) as a built-in fallback when hardware gamma is unavailable.
3. **UI indicator**: Show a note in Settings > Gamma Control that software mode is active.

This is a better long-term solution than requiring users to install a plugin, since it would work out of the box on affected hardware.

## System info

- DMS 1.4.4
- niri 25.11
- Kernel 6.18.15-400.asahi.fc43.aarch64+16k
- Apple M2 (MacBook Air)

Contributor guide

Open the contributing guide

Research direction

Start by reading the working workaround at ~/.config/DankMaterialShell/plugins/nightOverlay/NightOverlay.qml and tracing the existing DisplayService gamma-control path and Settings > Gamma Control UI. Determine how gammaCurrentTemp is reported after enablement and how layer-shell overlays are created. Done means a built-in software overlay activates when hardware gamma has no effect and the UI identifies software mode.

Written by the indexing model from the issue text.

Assessment

Domain
desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.