gamma: configurable transition duration for time-based night mode

This commit is contained in:
bbedward
2026-08-29 16:23:48 -04:00
parent ce879a6219
commit b8cceb7b3a
10 changed files with 70 additions and 7 deletions
+2
View File
@@ -26,6 +26,7 @@ const (
ErrTypeSecretPromptTimeout
ErrTypeSecretAgentFailed
ErrTypeGeneric
ErrTypeInvalidDuration
)
func NewCustomError(errType ErrorType, message string) error {
@@ -54,6 +55,7 @@ var (
ErrInvalidGamma = NewCustomError(ErrTypeInvalidGamma, "gamma must be between 0 and 10")
ErrInvalidLocation = NewCustomError(ErrTypeInvalidLocation, "invalid latitude/longitude")
ErrInvalidManualTimes = NewCustomError(ErrTypeInvalidManualTimes, "both sunrise and sunset must be set or neither")
ErrInvalidDuration = NewCustomError(ErrTypeInvalidDuration, "duration must be between 0 and 6 hours")
ErrNoWaylandDisplay = NewCustomError(ErrTypeNoWaylandDisplay, "no wayland display available")
ErrNoGammaControl = NewCustomError(ErrTypeNoGammaControl, "compositor does not support gamma control")
ErrNotInitialized = NewCustomError(ErrTypeNotInitialized, "manager not initialized")
+2 -2
View File
@@ -38,7 +38,7 @@ import (
"github.com/AvengeMedia/dankgo/syncmap"
)
const APIVersion = 31
const APIVersion = 32
var CLIVersion = "dev"
@@ -1431,7 +1431,7 @@ func (s *Server) Serve(printDocs bool) error {
log.Info(" wayland.gamma.getState - Get current gamma control state")
log.Info(" wayland.gamma.setTemperature - Set temperature range (params: low, high)")
log.Info(" wayland.gamma.setLocation - Set location (params: latitude, longitude)")
log.Info(" wayland.gamma.setManualTimes - Set manual times (params: sunrise, sunset)")
log.Info(" wayland.gamma.setManualTimes - Set manual times (params: sunrise, sunset, durationMinutes)")
log.Info(" wayland.gamma.setGamma - Set gamma value (params: gamma)")
log.Info(" wayland.gamma.setEnabled - Enable/disable gamma control (params: enabled)")
log.Info(" wayland.gamma.subscribe - Subscribe to gamma state changes (streaming)")
+7 -1
View File
@@ -112,7 +112,13 @@ func handleSetManualTimes(conn *models.Conn, req models.Request, manager *Manage
return
}
if err := manager.SetManualTimes(sunrise, sunset); err != nil {
var duration *time.Duration
if minutes, ok := models.Get[float64](req, "durationMinutes"); ok {
d := time.Duration(minutes) * time.Minute
duration = &d
}
if err := manager.SetManualTimes(sunrise, sunset, duration); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
+13 -3
View File
@@ -1157,17 +1157,19 @@ func (m *Manager) SetUseIPLocation(use bool) {
m.triggerUpdate()
}
func (m *Manager) SetManualTimes(sunrise, sunset time.Time) error {
func (m *Manager) SetManualTimes(sunrise, sunset time.Time, duration *time.Duration) error {
m.configMutex.Lock()
if m.config.ManualSunrise != nil && m.config.ManualSunset != nil &&
m.config.ManualSunrise.Hour() == sunrise.Hour() && m.config.ManualSunrise.Minute() == sunrise.Minute() &&
m.config.ManualSunset.Hour() == sunset.Hour() && m.config.ManualSunset.Minute() == sunset.Minute() {
m.config.ManualSunset.Hour() == sunset.Hour() && m.config.ManualSunset.Minute() == sunset.Minute() &&
durationEqual(m.config.ManualDuration, duration) {
m.configMutex.Unlock()
return nil
}
updated := m.config
updated.ManualSunrise = &sunrise
updated.ManualSunset = &sunset
updated.ManualDuration = duration
if err := updated.Validate(); err != nil {
m.configMutex.Unlock()
return err
@@ -1180,16 +1182,24 @@ func (m *Manager) SetManualTimes(sunrise, sunset time.Time) error {
func (m *Manager) ClearManualTimes() {
m.configMutex.Lock()
if m.config.ManualSunrise == nil && m.config.ManualSunset == nil {
if m.config.ManualSunrise == nil && m.config.ManualSunset == nil && m.config.ManualDuration == nil {
m.configMutex.Unlock()
return
}
m.config.ManualSunrise = nil
m.config.ManualSunset = nil
m.config.ManualDuration = nil
m.configMutex.Unlock()
m.triggerUpdate()
}
func durationEqual(a, b *time.Duration) bool {
if a == nil || b == nil {
return a == b
}
return *a == *b
}
func (m *Manager) SetGamma(gamma float64) error {
m.configMutex.Lock()
if m.config.Gamma == gamma {
+3
View File
@@ -155,6 +155,9 @@ func (c *Config) Validate() error {
if (c.ManualSunrise != nil) != (c.ManualSunset != nil) {
return errdefs.ErrInvalidManualTimes
}
if c.ManualDuration != nil && (*c.ManualDuration < 0 || *c.ManualDuration > 6*time.Hour) {
return errdefs.ErrInvalidDuration
}
return nil
}
+6
View File
@@ -167,6 +167,7 @@ Singleton {
property int nightModeStartMinute: 0
property int nightModeEndHour: 6
property int nightModeEndMinute: 0
property int nightModeTransitionMinutes: 60
property real latitude: 0.0
property real longitude: 0.0
property bool nightModeUseIPLocation: false
@@ -1085,6 +1086,11 @@ Singleton {
saveSettings();
}
function setNightModeTransitionMinutes(minutes) {
nightModeTransitionMinutes = minutes;
saveSettings();
}
function setNightModeUseIPLocation(use) {
nightModeUseIPLocation = use;
saveSettings();
@@ -36,6 +36,7 @@ var SPEC = {
nightModeStartMinute: { def: 0 },
nightModeEndHour: { def: 6 },
nightModeEndMinute: { def: 0 },
nightModeTransitionMinutes: { def: 60 },
latitude: { def: 0.0 },
longitude: { def: 0.0 },
nightModeUseIPLocation: { def: false },
@@ -318,6 +318,20 @@ Item {
}
}
}
SettingsSliderRow {
settingKey: "nightModeTransitionMinutes"
tags: ["gamma", "night", "transition", "duration", "fade"]
width: parent.width
text: I18n.tr("Transition Duration")
minimum: 0
maximum: 180
step: 5
unit: "min"
value: SessionData.nightModeTransitionMinutes
visible: DMSService.apiVersion >= 32
onSliderValueChanged: newValue => SessionData.setNightModeTransitionMinutes(newValue)
}
}
SettingsLocationSection {
+5 -1
View File
@@ -1196,7 +1196,8 @@ Singleton {
DMSService.sendRequest("wayland.gamma.setManualTimes", {
"sunrise": sunrise,
"sunset": sunset
"sunset": sunset,
"durationMinutes": SessionData.nightModeTransitionMinutes
}, response => {
if (response.error) {
log.error("Failed to set manual times:", response.error);
@@ -1534,6 +1535,9 @@ Singleton {
function onNightModeEndMinuteChanged() {
evaluateNightMode();
}
function onNightModeTransitionMinutesChanged() {
evaluateNightMode();
}
function onNightModeTemperatureChanged() {
evaluateNightMode();
}
@@ -8969,6 +8969,23 @@
],
"description": "Color temperature for night mode"
},
{
"section": "nightModeTransitionMinutes",
"label": "Transition Duration",
"tabIndex": 25,
"category": "Displays",
"keywords": [
"displays",
"duration",
"fade",
"gamma",
"monitor",
"night",
"resolution",
"screen",
"transition"
]
},
{
"section": "_tab_26",
"label": "Widgets",