Draft: daemon: Introduce proper dimming API for ScreenBrightnessController
Progress towards fixing #38. As concluded in #38 (comment 1065728), we'll start out with just an API for temporary dimming adjustments, leaving profile-dependent brightness changes and ambient light sensors to keep using standard setBrightness()
calls for the time being. Depends on !470 (merged) and !475 which were originally part of this MR, but split out into separate MRs for easier merging.
Draft status for several reasons:
-
An annoying timing issue means that BUG: 452492 is still not fixed. Before merging, we should figure out how to move forward on this. More details below.- Fixed by the new upload, see !466 (comment 1077001).
- No KWin/Wayland protocol for dimming at this time. It doesn't have to be part of this MR, but some design work might also help guide this.
- More testing needed.
In a nutshell, this change will restore non-dimmed brightness after reconnecting if the hardware brightness value is equal to brightness * dimmingRatio
which we had set before the display was removed earlier. If hardware brightness was not dimmed, or is set to any other value, nothing needs to be restored and dimming ratio remains at 1.0.
EDIT: Annoying timing issue, fixed by the new upload
It currently breaks down originally broke down because idle wake-up tends to happen after a display is disconnected, but before `ScreenBrightnessController` knows about this. The annoying timing issue goes like this:- Internal and external displays get dimmed. Dimming ratio was set to 0.3 for both displays.
- Unplug external display.
- Unplugging wakes up from idle.
- In the background, KWin has already forgotten the output and won't set its brightness anymore. (Alternatively, without KWin, the
DDCutilDisplay
is still present for a while but also won't set brightness anymore.) - Both displays still known to the controller, restoring dimming ratio to 1.0 and setting (cached) brightness value accordingly, but brightness fails to apply to the underlying device (or KWin config).
- In the background, KWin has already forgotten the output and won't set its brightness anymore. (Alternatively, without KWin, the
-
DisplayBrightness
removal (KWinBrightnessDisplay
orDDCutilDisplay
) arrives at PowerDevil's controller. Dimming ratio for the removed display is remembered as 1.0, the last value that was set. - Plug in external display again.
- Hardware brightness is still at 30% of the original, but doesn't match original
brightness * dimmingRatio
because the latter is 1.0 rather than 0.3. Remembered display state is discarded without getting applied.
This causes a deeper issue because DisplayBrightness
exposes cached brightness, rather than hardware brightness. In order to correctly restore brightness after reconnection, we would have to do one of two things:
- (a) Remember brightness and dimming ratio that were applied to hardware, rather than cached brightness. We may have to introduce some notion of applied brightness, or committed state, or similar.
- (b) Or, skip the check for hardware brightness matching
brightness * dimmingRatio
, which may work well enough but would undo any brightness changes that the user has made on their OSD or in a different user session.
So, throwing this out there right now and hoping for feedback. Targeting for 6.2 if all goes well, could also go into 6.3 only depending on feedback.
Commit message
daemon: Introduce proper dimming API for ScreenBrightnessController
This allows us to correctly restore brightness for displays that were disconnected when they were dimmed, and are reconnected later. It doesn't quite fix restoring dimmed displays across reboots yet, this will be an extension requiring Wayland protocol updates.
ScreenBrightnessController
now keeps track of more data for each
connected display, enough to recognize the display after it appears
again later (possibly with a different display ID) and restore some
runtime state.
This allows us to store and restore values for a display's nominal brightness, minimum brightness, and dimming ratio.
The dimming ratio is multiplied with the nominal brightness and capped by the minimum brightness to produce a display's desired actual brightness. Several callers can set a dimming ratio, the lowest one will be used. For now, the DimDisplay action is the only user; however, other dimming methods are anticipated in the future.
Importantly, by being able to restore these values separately from just a single hardware brightness value, we can tell if the display is still in the expected state from before the disconnect. If it is, we can continue using the earlier nominal brightness but update the dimming ratio to the current runtime setting. Unrecognized or changed displays can remain untouched, they can be assumed with a 1.0 dimming ratio from their current brightness level.
Note that this API is meant only for temporary dimming from the baseline of the current nominal brightness. It isn't meant for profile-dependent brightness changes or for ambient light sensors driving gradual, automatic brightness adjustments. We can have dedicated APIs later for these use cases.