mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-09 06:58:29 -04:00
gamma: fix scheduler losing track during suspend
port 1.5
(cherry picked from commit 5d2093e54a)
This commit is contained in:
@@ -23,6 +23,9 @@ import (
|
|||||||
|
|
||||||
const animKelvinStep = 25
|
const animKelvinStep = 25
|
||||||
|
|
||||||
|
// Go timers freeze during suspend; cap sleeps so wall-clock deadlines can't be missed.
|
||||||
|
const maxScheduleWait = 5 * time.Minute
|
||||||
|
|
||||||
func NewManager(display wlclient.WaylandDisplay, config Config) (*Manager, error) {
|
func NewManager(display wlclient.WaylandDisplay, config Config) (*Manager, error) {
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -304,8 +307,8 @@ func (m *Manager) setupControlHandlers(state *outputState, control *wlr_gamma_co
|
|||||||
out.rampSize = size
|
out.rampSize = size
|
||||||
out.failed = false
|
out.failed = false
|
||||||
out.retryCount = 0
|
out.retryCount = 0
|
||||||
|
out.lastTemp = 0
|
||||||
}
|
}
|
||||||
m.lastAppliedTemp = 0
|
|
||||||
m.applyCurrentTemp("gamma_size")
|
m.applyCurrentTemp("gamma_size")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -507,6 +510,10 @@ func (m *Manager) recalcSchedule(now time.Time) {
|
|||||||
config.ManualSunrise.Hour(), config.ManualSunrise.Minute(), config.ManualSunrise.Second(), 0, now.Location())
|
config.ManualSunrise.Hour(), config.ManualSunrise.Minute(), config.ManualSunrise.Second(), 0, now.Location())
|
||||||
sunset := time.Date(now.Year(), now.Month(), now.Day(),
|
sunset := time.Date(now.Year(), now.Month(), now.Day(),
|
||||||
config.ManualSunset.Hour(), config.ManualSunset.Minute(), config.ManualSunset.Second(), 0, now.Location())
|
config.ManualSunset.Hour(), config.ManualSunset.Minute(), config.ManualSunset.Second(), 0, now.Location())
|
||||||
|
if !sunset.After(sunrise) {
|
||||||
|
// night start past midnight belongs to the next day
|
||||||
|
sunset = sunset.Add(24 * time.Hour)
|
||||||
|
}
|
||||||
times = SunTimes{
|
times = SunTimes{
|
||||||
Dawn: sunrise.Add(-dur),
|
Dawn: sunrise.Add(-dur),
|
||||||
Sunrise: sunrise,
|
Sunrise: sunrise,
|
||||||
@@ -518,6 +525,8 @@ func (m *Manager) recalcSchedule(now time.Time) {
|
|||||||
lat, lon := m.getLocation()
|
lat, lon := m.getLocation()
|
||||||
if lat == nil || lon == nil {
|
if lat == nil || lon == nil {
|
||||||
m.gammaState = StateStatic
|
m.gammaState = StateStatic
|
||||||
|
// stale times from a previous config must not drive applies
|
||||||
|
m.schedule = sunSchedule{}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
times, cond = CalculateSunTimesWithTwilight(*lat, *lon, now, config.ElevationTwilight, config.ElevationDaylight)
|
times, cond = CalculateSunTimesWithTwilight(*lat, *lon, now, config.ElevationTwilight, config.ElevationDaylight)
|
||||||
@@ -611,7 +620,26 @@ func (m *Manager) getSunPosition(now time.Time) float64 {
|
|||||||
return 1.0
|
return 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shiftTimes(times SunTimes, d time.Duration) SunTimes {
|
||||||
|
return SunTimes{
|
||||||
|
Dawn: times.Dawn.Add(d),
|
||||||
|
Sunrise: times.Sunrise.Add(d),
|
||||||
|
Sunset: times.Sunset.Add(d),
|
||||||
|
Night: times.Night.Add(d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// activeCycle maps early-morning hours back to yesterday's cycle when the
|
||||||
|
// schedule crosses midnight.
|
||||||
|
func activeCycle(now time.Time, times SunTimes) SunTimes {
|
||||||
|
if now.Before(times.Night.Add(-24 * time.Hour)) {
|
||||||
|
return shiftTimes(times, -24*time.Hour)
|
||||||
|
}
|
||||||
|
return times
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) getSunPositionNormal(now time.Time, times SunTimes) float64 {
|
func (m *Manager) getSunPositionNormal(now time.Time, times SunTimes) float64 {
|
||||||
|
times = activeCycle(now, times)
|
||||||
if now.Before(times.Dawn) {
|
if now.Before(times.Dawn) {
|
||||||
return 0.0
|
return 0.0
|
||||||
}
|
}
|
||||||
@@ -666,7 +694,7 @@ func (m *Manager) getNextDeadline(now time.Time) time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) getDeadlineNormal(now time.Time, sched sunSchedule) time.Time {
|
func (m *Manager) getDeadlineNormal(now time.Time, sched sunSchedule) time.Time {
|
||||||
times := sched.times
|
times := activeCycle(now, sched.times)
|
||||||
switch {
|
switch {
|
||||||
case now.Before(times.Dawn):
|
case now.Before(times.Dawn):
|
||||||
return times.Dawn
|
return times.Dawn
|
||||||
@@ -737,8 +765,11 @@ func (m *Manager) schedulerLoop() {
|
|||||||
if enabled {
|
if enabled {
|
||||||
deadline := m.getNextDeadline(now)
|
deadline := m.getNextDeadline(now)
|
||||||
waitDur = time.Until(deadline)
|
waitDur = time.Until(deadline)
|
||||||
if waitDur < time.Second {
|
switch {
|
||||||
|
case waitDur < time.Second:
|
||||||
waitDur = time.Second
|
waitDur = time.Second
|
||||||
|
case waitDur > maxScheduleWait:
|
||||||
|
waitDur = maxScheduleWait
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
waitDur = 24 * time.Hour
|
waitDur = 24 * time.Hour
|
||||||
@@ -818,8 +849,6 @@ func (m *Manager) applyGamma(temp int) {
|
|||||||
return
|
return
|
||||||
case !m.controlsInitialized:
|
case !m.controlsInitialized:
|
||||||
return
|
return
|
||||||
case m.lastAppliedTemp == temp && m.lastAppliedGamma == gamma:
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var outs []*outputState
|
var outs []*outputState
|
||||||
@@ -845,6 +874,8 @@ func (m *Manager) applyGamma(temp int) {
|
|||||||
continue
|
continue
|
||||||
case out.gammaControl == nil:
|
case out.gammaControl == nil:
|
||||||
continue
|
continue
|
||||||
|
case out.lastTemp == temp && out.lastGamma == gamma:
|
||||||
|
continue
|
||||||
case !m.outputStillValid(out):
|
case !m.outputStillValid(out):
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -865,19 +896,19 @@ func (m *Manager) applyGamma(temp int) {
|
|||||||
for _, j := range jobs {
|
for _, j := range jobs {
|
||||||
err := m.setGammaBytes(j.out, j.data)
|
err := m.setGammaBytes(j.out, j.data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
j.out.lastTemp = temp
|
||||||
|
j.out.lastGamma = gamma
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Warnf("gamma: failed to set output %d: %v", j.out.id, err)
|
log.Warnf("gamma: failed to set output %d: %v", j.out.id, err)
|
||||||
j.out.failed = true
|
j.out.failed = true
|
||||||
j.out.rampSize = 0
|
j.out.rampSize = 0
|
||||||
|
j.out.lastTemp = 0
|
||||||
if isConnectionDeadErr(err) {
|
if isConnectionDeadErr(err) {
|
||||||
m.markConnectionDead(err)
|
m.markConnectionDead(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.lastAppliedTemp = temp
|
|
||||||
m.lastAppliedGamma = gamma
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) setGammaBytes(out *outputState, data []byte) error {
|
func (m *Manager) setGammaBytes(out *outputState, data []byte) error {
|
||||||
@@ -939,7 +970,8 @@ func (m *Manager) updateStateFromSchedule() {
|
|||||||
pos = m.getSunPosition(now)
|
pos = m.getSunPosition(now)
|
||||||
temp = m.getTempFromPosition(pos)
|
temp = m.getTempFromPosition(pos)
|
||||||
deadline = m.getNextDeadline(now)
|
deadline = m.getNextDeadline(now)
|
||||||
isDay = now.After(times.Sunrise) && now.Before(times.Sunset)
|
cycle := activeCycle(now, times)
|
||||||
|
isDay = now.After(cycle.Sunrise) && now.Before(cycle.Sunset)
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := State{
|
newState := State{
|
||||||
@@ -1053,14 +1085,15 @@ func (m *Manager) handleResume() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compositors (Niri, Hyprland, wlroots-based) re-apply the cached gamma
|
// Compositor gamma state is unknown after resume; force a resend (#1235)
|
||||||
// ramp to DRM on resume; gamma_control objects stay valid. We just need
|
// and re-arm the scheduler timer, which froze during suspend.
|
||||||
// to force a resend so the schedule catches up with the current time of
|
m.outputs.Range(func(_ uint32, out *outputState) bool {
|
||||||
// day — the original #1235 regression was caused by lastAppliedTemp
|
out.lastTemp = 0
|
||||||
// matching and the send being skipped.
|
return true
|
||||||
|
})
|
||||||
m.recalcSchedule(time.Now())
|
m.recalcSchedule(time.Now())
|
||||||
m.lastAppliedTemp = 0
|
|
||||||
m.applyCurrentTemp("resume")
|
m.applyCurrentTemp("resume")
|
||||||
|
m.triggerUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) triggerUpdate() {
|
func (m *Manager) triggerUpdate() {
|
||||||
|
|||||||
@@ -102,9 +102,6 @@ type Manager struct {
|
|||||||
dbusSignal chan *dbus.Signal
|
dbusSignal chan *dbus.Signal
|
||||||
|
|
||||||
geoClient geolocation.Client
|
geoClient geolocation.Client
|
||||||
|
|
||||||
lastAppliedTemp int
|
|
||||||
lastAppliedGamma float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type outputState struct {
|
type outputState struct {
|
||||||
@@ -117,6 +114,8 @@ type outputState struct {
|
|||||||
isVirtual bool
|
isVirtual bool
|
||||||
retryCount int
|
retryCount int
|
||||||
lastFailTime time.Time
|
lastFailTime time.Time
|
||||||
|
lastTemp int
|
||||||
|
lastGamma float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultConfig() Config {
|
func DefaultConfig() Config {
|
||||||
|
|||||||
Reference in New Issue
Block a user