diff --git a/display/color_temp.go b/display/color_temp.go index 6ca58a1c..530693bb 100644 --- a/display/color_temp.go +++ b/display/color_temp.go @@ -8,9 +8,11 @@ import ( "bufio" "bytes" "errors" + configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" "math" "os" "os/exec" + "regexp" "strconv" "strings" "sync" @@ -28,20 +30,28 @@ const ( ColorTemperatureModeAuto // ColorTemperatureModeManual 手动调整色温 ColorTemperatureModeManual + ColorTemperatureModeCustom ) const ( timeZoneFile = "/usr/share/zoneinfo/zone1970.tab" + + defaultAutoColorTemperatureConf = "6500:3500" + defaultTemperature = 6500 ) func isValidColorTempMode(mode int32) bool { - return mode >= ColorTemperatureModeNone && mode <= ColorTemperatureModeManual + return mode >= ColorTemperatureModeNone && mode <= ColorTemperatureModeCustom } // dbus 上导出的方法 func (m *Manager) setColorTempMode(mode int32) error { if !isValidColorTempMode(mode) { - return errors.New("mode out of range, not 0 or 1 or 2") + return errors.New("mode out of range, not 0 or 1 or 3") + } + + if mode != ColorTemperatureModeNone { + m.setCustomColorTempModeOn(mode) } m.setPropColorTemperatureMode(mode) m.setPropColorTemperatureEnabled(mode != 0) @@ -57,11 +67,15 @@ func (m *Manager) setColorTempModeReal(mode int32) { switch mode { case ColorTemperatureModeAuto: // 自动模式调节色温 启动服务 m.redshiftRunner.start() - + m.stopCustomColorTempMode() case ColorTemperatureModeManual, ColorTemperatureModeNone: // manual 手动调节色温 // none 恢复正常色温 m.redshiftRunner.stop() + m.stopCustomColorTempMode() + case ColorTemperatureModeCustom: + m.redshiftRunner.stop() + m.listenCustomColorTempTime() } // 对于自动模式,也要先把色温设置为正常。 m.setColorTempOneShot() @@ -156,12 +170,19 @@ func (r *redshiftRunner) start() { return } r.state = redshiftStateRunning - + var colorConf string + val, err := getGlobalDconfValue(DSettingsAppID, DSettingsDisplayName, "", DSettingsKeyAutoColorTemperature) + if err != nil { + colorConf = defaultAutoColorTemperatureConf + logger.Warning(err) + } else { + colorConf = val.(string) + } latitude := r.zoneInfoMap[_timeZone].latitude longitude := r.zoneInfoMap[_timeZone].longitude geographicalPosition := strconv.FormatFloat(latitude, 'f', -1, 64) + ":" + strconv.FormatFloat(longitude, 'f', -1, 64) logger.Info("Get geographicalPosition:", geographicalPosition) - cmd := exec.Command("redshift", "-m", "dummy", "-t", "6500:3500", "-r") + cmd := exec.Command("redshift", "-m", "dummy", "-t", colorConf, "-r") if geographicalPosition != "" { cmd.Args = append(cmd.Args, "-l", geographicalPosition) } @@ -372,6 +393,12 @@ func (m *Manager) getColorTemperatureValue() int { return int(manual) case ColorTemperatureModeAuto: return m.redshiftRunner.getValue() + case ColorTemperatureModeCustom: + value := defaultTemperature + if m.customColorTempFlag { + value = int(manual) + } + return value } return defaultTemperatureManual @@ -484,3 +511,152 @@ func (r *redshiftRunner) registerGeoClueAgent() error { r.geoAgentRegistered = true return nil } + +func setGlobalDconfValue(appID string, name string, subPath string, key string, value dbus.Variant) error { + sysBus, err := dbus.SystemBus() + if err != nil { + logger.Warning(err) + return err + } + ds := configManager.NewConfigManager(sysBus) + managerPath, err := ds.AcquireManager(0, appID, name, subPath) + if err != nil { + logger.Warning(err) + return err + } + + dsManager, err := configManager.NewManager(sysBus, managerPath) + if err != nil { + logger.Warning(err) + return err + } + + err = dsManager.SetValue(0, key, value) + if err != nil { + logger.Warning(err) + return err + } + return nil +} + +func (m *Manager) setCustomColorTempTimePeriod(timePeriod string) error { + pattern := `^(?:[01]\d|2[0-3]):[0-5]\d-(?:[01]\d|2[0-3]):[0-5]\d$` + re := regexp.MustCompile(pattern) + var err error + if re.MatchString(timePeriod) { + m.CustomColorTempTimePeriod = timePeriod + err = setGlobalDconfValue(DSettingsAppID, DSettingsDisplayName, "", DSettingsKeyCustomModeTime, dbus.MakeVariant(timePeriod)) + } else { + err = errors.New("The timeperiod parameter is invalid") + } + return err +} + +func (m *Manager) setCustomColorTempModeOn(modeOn int32) error { + var err error + err = setGlobalDconfValue(DSettingsAppID, DSettingsDisplayName, "", DSettingKeyColorTemperatureModeOn, dbus.MakeVariant(modeOn)) + if err != nil { + logger.Warning("try set modeOn failed") + } + + return err +} + +func (m *Manager) listenCustomColorTempTime() { + if m.customColorTempTimer == nil { + m.customColorTempTimer = time.NewTimer(5 * time.Second) + } else { + m.customColorTempTimer.Reset(5 * time.Second) + } + go func() { + for { + select { + case <-m.customColorTempTimer.C: + if m.ColorTemperatureMode == ColorTemperatureModeCustom { + m.customColorTempFlag = m.checkCustomModeTime() + m.setColorTempOneShot() + } + } + if m.customColorTempTimer == nil { + m.customColorTempTimer = time.NewTimer(5 * time.Second) + } else { + m.customColorTempTimer.Reset(5 * time.Second) + } + } + }() +} + +func (m *Manager) checkCustomModeTime() bool { + parts := strings.Split(m.CustomColorTempTimePeriod, "-") + if len(parts) == 2 { + // 获取当前日期 + timeLocation, err := time.LoadLocation(_timeZone) + if err != nil { + logger.Warning(err) + return false + } + currentTime := time.Now().In(timeLocation) + year, month, day := currentTime.Date() + + // 构建目标时间 + targetTimeLayout := "15:04" + targetTimeStart, err := time.Parse(targetTimeLayout, parts[0]) + if err != nil { + logger.Warning("Failed to get start time:", err) + return false + } + targetTimeEnd, err := time.Parse(targetTimeLayout, parts[1]) + if err != nil { + logger.Warning("Failed to get start time:", err) + return false + } + // 需要考虑凌晨,因为不是同一天 + targetTimeStart = time.Date(year, month, day, targetTimeStart.Hour(), targetTimeStart.Minute(), 0, 0, currentTime.Location()) + targetTimeEnd = time.Date(year, month, day, targetTimeEnd.Hour(), targetTimeEnd.Minute(), 0, 0, currentTime.Location()) + // 计算时间间隔 + currentToStart := targetTimeStart.Sub(currentTime) + currentToEnd := targetTimeEnd.Sub(currentTime) + startToEnd := targetTimeEnd.Sub(targetTimeStart) + // 如果设定的时间段小于0,表示结束时间为第二天 + if startToEnd < 0 { + return (currentToStart < 0 && currentToEnd < 0) || (currentToStart > 0 && currentToEnd > 0) + } else { + return (currentToStart < 0) && (currentToEnd > 0) + } + } + return false +} + +func (m *Manager) stopCustomColorTempMode() { + if m.customColorTempTimer != nil { + m.customColorTempTimer.Stop() + m.customColorTempTimer = nil + } +} + +func getGlobalDconfValue(appID string, name string, subPath string, key string) (interface{}, error) { + sysBus, err := dbus.SystemBus() + if err != nil { + logger.Warning(err) + return nil, err + } + ds := configManager.NewConfigManager(sysBus) + managerPath, err := ds.AcquireManager(0, appID, name, subPath) + if err != nil { + logger.Warning(err) + return nil, err + } + + dsManager, err := configManager.NewManager(sysBus, managerPath) + if err != nil { + logger.Warning(err) + return nil, err + } + + val, err := dsManager.Value(0, key) + if err != nil { + logger.Warning(err) + return nil, err + } + return val.Value(), nil +} diff --git a/display/display.go b/display/display.go index d32928d9..f0c4d4b0 100644 --- a/display/display.go +++ b/display/display.go @@ -121,7 +121,9 @@ func Start(service *dbusutil.Service) error { } mode := ColorTemperatureModeNone if value { - mode = cfg.ColorTemperatureModeOn + mode = m.colorTemperatureModeOn + } else { + m.colorTemperatureModeOn = m.ColorTemperatureMode } err = m.setColorTempMode(mode) return dbusutil.ToError(err) diff --git a/display/exported_methods_auto.go b/display/exported_methods_auto.go index 34dfcb1b..abe21a87 100644 --- a/display/exported_methods_auto.go +++ b/display/exported_methods_auto.go @@ -104,6 +104,11 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.SetColorTemperature, InArgs: []string{"value"}, }, + { + Name: "SetCustomColorTempTimePeriod", + Fn: v.SetCustomColorTempTimePeriod, + InArgs: []string{"timePeriod"}, + }, { Name: "SetMethodAdjustCCT", Fn: v.SetMethodAdjustCCT, diff --git a/display/manager.go b/display/manager.go index d40b13d9..c9b315d3 100644 --- a/display/manager.go +++ b/display/manager.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" "math" "os" "os/exec" @@ -69,6 +70,13 @@ const ( ) const ( + DSettingsAppID = "org.deepin.startdde" + DSettingsDisplayName = "org.deepin.Display" + DSettingsKeyAutoColorTemperature = "auto-color-temperature" + DSettingsKeyDefaultTemperatureManual = "default-temperature-manual" + DSettingsKeyCustomModeTime = "custom-mode-time" + DSettingKeyColorTemperatureModeOn = "color-temperature-mode-on" + gsSchemaDisplay = "com.deepin.dde.display" gsKeyDisplayMode = "display-mode" gsKeyBrightness = "brightness" @@ -201,10 +209,6 @@ type Manager struct { ScreenHeight uint16 MaxBacklightBrightness uint32 - // method of adjust color temperature according to time and location - ColorTemperatureMode int32 - // adjust color temperature by manual adjustment - ColorTemperatureManual int32 // TODO 删除下面 2 个色温相关字段 // 存在gsetting中的色温模式 gsColorTemperatureMode int32 @@ -215,8 +219,16 @@ type Manager struct { unsupportGammaDrmList []string drmSupportGamma bool + customColorTempTimer *time.Timer + customColorTempFlag bool ColorTemperatureEnabled bool `prop:"access:rw"` SupportColorTemperature bool + // 用户设置的模式,用于使能开关时恢复设置 + colorTemperatureModeOn int32 + ColorTemperatureMode int32 + // adjust color temperature by manual adjustment + ColorTemperatureManual int32 + CustomColorTempTimePeriod string } type monitorSizeInfo struct { @@ -226,6 +238,8 @@ type monitorSizeInfo struct { var _ monitorManagerHooks = (*Manager)(nil) var _timeZone string +var _dsConfigManager configManager.Manager +var _dsDefaultTemperatureManual int32 func newManager(service *dbusutil.Service) *Manager { m := &Manager{ @@ -284,6 +298,8 @@ func newManager(service *dbusutil.Service) *Manager { m.sysSigLoop = sysSigLoop sysSigLoop.Start() + m.initDSettings(m.sysBus) + m.dbusDaemon = ofdbus.NewDBus(m.sysBus) m.dbusDaemon.InitSignalExt(sysSigLoop, true) @@ -384,6 +400,77 @@ func newManager(service *dbusutil.Service) *Manager { return m } +func (m *Manager) initDSettings(sysBus *dbus.Conn) { + ds := configManager.NewConfigManager(sysBus) + configManagerPath, err := ds.AcquireManager(0, DSettingsAppID, DSettingsDisplayName, "") + if err != nil || configManagerPath == "" { + logger.Warning(err) + return + } + + _dsConfigManager, err = configManager.NewManager(sysBus, configManagerPath) + if err != nil { + logger.Warning(err) + return + } + getDefaultTemperatureManual := func() { + v, err := _dsConfigManager.Value(0, DSettingsKeyDefaultTemperatureManual) + if err != nil { + logger.Warning(err) + return + } + switch vv := v.Value().(type) { + case float64: + _dsDefaultTemperatureManual = int32(vv) + case int64: + _dsDefaultTemperatureManual = int32(vv) + default: + logger.Warning("type is wrong!") + } + logger.Info("Default temperature manual:", _dsDefaultTemperatureManual) + } + + getCustomTemperatureTime := func() { + v, err := _dsConfigManager.Value(0, DSettingsKeyCustomModeTime) + if err != nil { + logger.Warning(err) + return + } + m.CustomColorTempTimePeriod = v.Value().(string) + logger.Info("Custom Mode Time:", m.CustomColorTempTimePeriod) + } + + getColorTemperatureModeOn := func() { + v, err := _dsConfigManager.Value(0, DSettingKeyColorTemperatureModeOn) + if err != nil { + logger.Warning(err) + return + } + m.colorTemperatureModeOn = int32(v.Value().(int64)) + logger.Info("Custom Mode on:", m.colorTemperatureModeOn) + } + + getDefaultTemperatureManual() + getCustomTemperatureTime() + getColorTemperatureModeOn() + m.ColorTemperatureManual = _dsDefaultTemperatureManual + + _dsConfigManager.InitSignalExt(m.sysSigLoop, true) + _, err = _dsConfigManager.ConnectValueChanged(func(key string) { + switch key { + case DSettingsKeyCustomModeTime: + getCustomTemperatureTime() + case DSettingKeyColorTemperatureModeOn: + getColorTemperatureModeOn() + default: + break + } + }) + if err != nil { + logger.Warning(err) + } +} + // 初始化系统级 display 服务的信号处理 func (m *Manager) initSysDisplay() { m.sysDisplay.InitSignalExt(m.sysSigLoop, true) @@ -414,7 +501,6 @@ func (m *Manager) initSysDisplay() { logger.Warning(err) } go func() { - // 依赖dsettings数据,需要在initDSettings后执行 m.drmSupportGamma = m.detectDrmSupportGamma() if m.drmSupportGamma { logger.Debug("setColorTempModeReal") diff --git a/display/manager_ifc.go b/display/manager_ifc.go index 4c51d24c..0b981b98 100644 --- a/display/manager_ifc.go +++ b/display/manager_ifc.go @@ -315,3 +315,8 @@ func (m *Manager) GetRealDisplayMode() (uint8, *dbus.Error) { func (m *Manager) SupportSetColorTemperature() (bool, *dbus.Error) { return !(_inVM || !m.drmSupportGamma), nil } + +func (m *Manager) SetCustomColorTempTimePeriod(timePeriod string) *dbus.Error { + err := m.setCustomColorTempTimePeriod(timePeriod) + return dbusutil.ToError(err) +} diff --git a/misc/dsettings/org.deepin.Display.json b/misc/dsettings/org.deepin.Display.json new file mode 100644 index 00000000..e4ca53a3 --- /dev/null +++ b/misc/dsettings/org.deepin.Display.json @@ -0,0 +1,42 @@ +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "auto-color-temperature": { + "value": "6500:3500", + "serial": 0, + "flags": [], + "name": "auto color temperature", + "description": "Automatically adjust color temperature", + "permissions": "readwrite", + "visibility": "private" + }, + "default-temperature-manual": { + "value": 3500, + "serial": 0, + "flags": [], + "name": "default temperature manual", + "description": "default temperature by manual", + "permissions": "readwrite", + "visibility": "private" + }, + "custom-mode-time": { + "value": "22:00-7:00", + "serial": 0, + "flags": [], + "name": "Color Temperature Custom Mode Time", + "description": "Recording the time for custom mode", + "permissions": "readwrite", + "visibility": "private" + }, + "color-temperature-mode-on": { + "value": 2, + "serial": 0, + "flags": [], + "name": "Color Temperature Mode On", + "description": "Recording the mode for last time", + "permissions": "readwrite", + "visibility": "private" + } + } +}