diff --git a/core/internal/server/wayland/manager.go b/core/internal/server/wayland/manager.go index 62a9f2b7..0d2d047a 100644 --- a/core/internal/server/wayland/manager.go +++ b/core/internal/server/wayland/manager.go @@ -103,18 +103,16 @@ func (m *Manager) waylandActor() { } } -func (m *Manager) allOutputsReady() bool { - hasOutputs := false - allReady := true +func (m *Manager) anyOutputReady() bool { + anyReady := false m.outputs.Range(func(_ uint32, out *outputState) bool { - hasOutputs = true - if out.rampSize == 0 || out.failed { - allReady = false - return false + if out.rampSize > 0 && !out.failed { + anyReady = true + return false // stop iteration } return true }) - return hasOutputs && allReady + return anyReady } func (m *Manager) setupDBusMonitor() error { @@ -278,7 +276,8 @@ func (m *Manager) setupControlHandlers(state *outputState, control *wlr_gamma_co out.failed = false out.retryCount = 0 } - m.applyCurrentTemp() + m.lastAppliedTemp = 0 + m.applyCurrentTemp("gamma_size") }) }) @@ -528,8 +527,9 @@ func (m *Manager) getNextDeadline(now time.Time) time.Time { return m.tomorrow(now) case StateNormal: return m.getDeadlineNormal(now, sched) + default: + return m.tomorrow(now) } - return m.tomorrow(now) } func (m *Manager) getDeadlineNormal(now time.Time, sched sunSchedule) time.Time { @@ -588,7 +588,7 @@ func (m *Manager) schedulerLoop() { m.configMutex.RUnlock() if enabled { - m.post(func() { m.applyCurrentTemp() }) + m.post(func() { m.applyCurrentTemp("startup") }) } var timer *time.Timer @@ -630,24 +630,27 @@ func (m *Manager) schedulerLoop() { enabled := m.config.Enabled m.configMutex.RUnlock() if enabled { - m.post(func() { m.applyCurrentTemp() }) + m.post(func() { m.applyCurrentTemp("updateTrigger") }) } case <-timer.C: m.configMutex.RLock() enabled := m.config.Enabled m.configMutex.RUnlock() if enabled { - m.post(func() { m.applyCurrentTemp() }) + m.post(func() { m.applyCurrentTemp("timer") }) } } } } -func (m *Manager) applyCurrentTemp() { - if !m.controlsInitialized || !m.allOutputsReady() { +func (m *Manager) applyCurrentTemp(_ string) { + if !m.controlsInitialized || !m.anyOutputReady() { return } + // Ensure schedule is up-to-date (handles display wake after overnight sleep) + m.recalcSchedule(time.Now()) + m.configMutex.RLock() low, high := m.config.LowTemp, m.config.HighTemp m.configMutex.RUnlock() @@ -680,6 +683,10 @@ func (m *Manager) applyGamma(temp int) { return } + if m.lastAppliedTemp == temp && m.lastAppliedGamma == gamma { + return + } + var outs []*outputState m.outputs.Range(func(_ uint32, out *outputState) bool { outs = append(outs, out) @@ -715,6 +722,7 @@ func (m *Manager) applyGamma(temp int) { for _, j := range jobs { if err := m.setGammaBytes(j.out, j.data); err != nil { + log.Warnf("gamma: failed to set output %d: %v", j.out.id, err) j.out.failed = true j.out.rampSize = 0 outID := j.out.id @@ -727,6 +735,9 @@ func (m *Manager) applyGamma(temp int) { }) } } + + m.lastAppliedTemp = temp + m.lastAppliedGamma = gamma } func (m *Manager) setGammaBytes(out *outputState, data []byte) error { @@ -901,6 +912,10 @@ func (m *Manager) SetConfig(config Config) error { func (m *Manager) SetTemperature(low, high int) error { m.configMutex.Lock() + if m.config.LowTemp == low && m.config.HighTemp == high { + m.configMutex.Unlock() + return nil + } m.config.LowTemp = low m.config.HighTemp = high err := m.config.Validate() @@ -914,6 +929,11 @@ func (m *Manager) SetTemperature(low, high int) error { func (m *Manager) SetLocation(lat, lon float64) error { m.configMutex.Lock() + if m.config.Latitude != nil && m.config.Longitude != nil && + *m.config.Latitude == lat && *m.config.Longitude == lon && !m.config.UseIPLocation { + m.configMutex.Unlock() + return nil + } m.config.Latitude = &lat m.config.Longitude = &lon m.config.UseIPLocation = false @@ -928,6 +948,10 @@ func (m *Manager) SetLocation(lat, lon float64) error { func (m *Manager) SetUseIPLocation(use bool) { m.configMutex.Lock() + if m.config.UseIPLocation == use { + m.configMutex.Unlock() + return + } m.config.UseIPLocation = use if use { m.config.Latitude = nil @@ -946,6 +970,12 @@ func (m *Manager) SetUseIPLocation(use bool) { func (m *Manager) SetManualTimes(sunrise, sunset time.Time) 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.configMutex.Unlock() + return nil + } m.config.ManualSunrise = &sunrise m.config.ManualSunset = &sunset err := m.config.Validate() @@ -959,6 +989,10 @@ 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 { + m.configMutex.Unlock() + return + } m.config.ManualSunrise = nil m.config.ManualSunset = nil m.configMutex.Unlock() @@ -967,6 +1001,10 @@ func (m *Manager) ClearManualTimes() { func (m *Manager) SetGamma(gamma float64) error { m.configMutex.Lock() + if m.config.Gamma == gamma { + m.configMutex.Unlock() + return nil + } m.config.Gamma = gamma err := m.config.Validate() m.configMutex.Unlock() @@ -980,6 +1018,10 @@ func (m *Manager) SetGamma(gamma float64) error { func (m *Manager) SetEnabled(enabled bool) { m.configMutex.Lock() wasEnabled := m.config.Enabled + if wasEnabled == enabled { + m.configMutex.Unlock() + return + } m.config.Enabled = enabled highTemp := m.config.HighTemp m.configMutex.Unlock() @@ -989,7 +1031,7 @@ func (m *Manager) SetEnabled(enabled bool) { m.post(func() { gammaMgr := m.gammaControl.(*wlr_gamma_control.ZwlrGammaControlManagerV1) if err := m.setupOutputControls(m.availableOutputs, gammaMgr); err != nil { - log.Errorf("Failed to create gamma controls: %v", err) + log.Errorf("gamma: failed to create controls: %v", err) return } m.controlsInitialized = true diff --git a/core/internal/server/wayland/types.go b/core/internal/server/wayland/types.go index d7e2bd0b..44861bdd 100644 --- a/core/internal/server/wayland/types.go +++ b/core/internal/server/wayland/types.go @@ -96,6 +96,9 @@ type Manager struct { dbusConn *dbus.Conn dbusSignal chan *dbus.Signal + + lastAppliedTemp int + lastAppliedGamma float64 } type outputState struct {