mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-28 15:32:50 -05:00
brightness: more aggressive ddc rescans on device changes
This commit is contained in:
@@ -40,6 +40,10 @@ func (b *DDCBackend) scanI2CDevices() error {
|
|||||||
return b.scanI2CDevicesInternal(false)
|
return b.scanI2CDevicesInternal(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *DDCBackend) ForceRescan() error {
|
||||||
|
return b.scanI2CDevicesInternal(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *DDCBackend) scanI2CDevicesInternal(force bool) error {
|
func (b *DDCBackend) scanI2CDevicesInternal(force bool) error {
|
||||||
b.scanMutex.Lock()
|
b.scanMutex.Lock()
|
||||||
defer b.scanMutex.Unlock()
|
defer b.scanMutex.Unlock()
|
||||||
@@ -261,8 +265,16 @@ func (b *DDCBackend) setBrightnessImmediateWithExponent(id string, value int) er
|
|||||||
|
|
||||||
busPath := fmt.Sprintf("/dev/i2c-%d", dev.bus)
|
busPath := fmt.Sprintf("/dev/i2c-%d", dev.bus)
|
||||||
|
|
||||||
|
if _, err := os.Stat(busPath); os.IsNotExist(err) {
|
||||||
|
b.devices.Delete(id)
|
||||||
|
log.Debugf("removed stale DDC device %s (bus no longer exists)", id)
|
||||||
|
return fmt.Errorf("device disconnected: %s", id)
|
||||||
|
}
|
||||||
|
|
||||||
fd, err := syscall.Open(busPath, syscall.O_RDWR, 0)
|
fd, err := syscall.Open(busPath, syscall.O_RDWR, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.devices.Delete(id)
|
||||||
|
log.Debugf("removed DDC device %s (open failed: %v)", id, err)
|
||||||
return fmt.Errorf("open i2c device: %w", err)
|
return fmt.Errorf("open i2c device: %w", err)
|
||||||
}
|
}
|
||||||
defer syscall.Close(fd)
|
defer syscall.Close(fd)
|
||||||
|
|||||||
@@ -89,6 +89,13 @@ func (m *Manager) initDDC() {
|
|||||||
|
|
||||||
func (m *Manager) Rescan() {
|
func (m *Manager) Rescan() {
|
||||||
log.Debug("Rescanning brightness devices...")
|
log.Debug("Rescanning brightness devices...")
|
||||||
|
|
||||||
|
if m.ddcReady && m.ddcBackend != nil {
|
||||||
|
if err := m.ddcBackend.ForceRescan(); err != nil {
|
||||||
|
log.Debugf("DDC force rescan failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m.updateState()
|
m.updateState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,18 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/pilebones/go-udev/netlink"
|
"github.com/pilebones/go-udev/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UdevMonitor struct {
|
type UdevMonitor struct {
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
|
rescanMutex sync.Mutex
|
||||||
|
rescanTimer *time.Timer
|
||||||
|
rescanPending bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUdevMonitor(manager *Manager) *UdevMonitor {
|
func NewUdevMonitor(manager *Manager) *UdevMonitor {
|
||||||
@@ -34,10 +39,8 @@ func (m *UdevMonitor) run(manager *Manager) {
|
|||||||
matcher := &netlink.RuleDefinitions{
|
matcher := &netlink.RuleDefinitions{
|
||||||
Rules: []netlink.RuleDefinition{
|
Rules: []netlink.RuleDefinition{
|
||||||
{Env: map[string]string{"SUBSYSTEM": "backlight"}},
|
{Env: map[string]string{"SUBSYSTEM": "backlight"}},
|
||||||
// ! TODO: most drivers dont emit this for leds?
|
{Env: map[string]string{"SUBSYSTEM": "drm"}},
|
||||||
// ! inotify brightness_hw_changed works, but thn some devices dont do that...
|
{Env: map[string]string{"SUBSYSTEM": "i2c"}},
|
||||||
// ! So for now the GUI just shows OSDs for leds, without reflecting actual HW value
|
|
||||||
// {Env: map[string]string{"SUBSYSTEM": "leds"}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := matcher.Compile(); err != nil {
|
if err := matcher.Compile(); err != nil {
|
||||||
@@ -49,7 +52,7 @@ func (m *UdevMonitor) run(manager *Manager) {
|
|||||||
errs := make(chan error)
|
errs := make(chan error)
|
||||||
conn.Monitor(events, errs, matcher)
|
conn.Monitor(events, errs, matcher)
|
||||||
|
|
||||||
log.Info("Udev monitor started for backlight/leds events")
|
log.Info("Udev monitor started for backlight/drm/i2c events")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -75,11 +78,54 @@ func (m *UdevMonitor) handleEvent(manager *Manager, event netlink.UEvent) {
|
|||||||
sysname := filepath.Base(devpath)
|
sysname := filepath.Base(devpath)
|
||||||
action := string(event.Action)
|
action := string(event.Action)
|
||||||
|
|
||||||
|
switch subsystem {
|
||||||
|
case "drm", "i2c":
|
||||||
|
m.handleDisplayEvent(manager, action, subsystem, sysname)
|
||||||
|
case "backlight":
|
||||||
|
m.handleBacklightEvent(manager, action, sysname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UdevMonitor) handleDisplayEvent(manager *Manager, action, subsystem, sysname string) {
|
||||||
|
switch action {
|
||||||
|
case "add", "remove", "change":
|
||||||
|
log.Debugf("Udev %s event: %s:%s - queueing DDC rescan", action, subsystem, sysname)
|
||||||
|
m.debouncedRescan(manager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UdevMonitor) debouncedRescan(manager *Manager) {
|
||||||
|
m.rescanMutex.Lock()
|
||||||
|
defer m.rescanMutex.Unlock()
|
||||||
|
|
||||||
|
m.rescanPending = true
|
||||||
|
|
||||||
|
if m.rescanTimer != nil {
|
||||||
|
m.rescanTimer.Reset(2 * time.Second)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.rescanTimer = time.AfterFunc(2*time.Second, func() {
|
||||||
|
m.rescanMutex.Lock()
|
||||||
|
pending := m.rescanPending
|
||||||
|
m.rescanPending = false
|
||||||
|
m.rescanMutex.Unlock()
|
||||||
|
|
||||||
|
if !pending {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Executing debounced DDC rescan")
|
||||||
|
manager.Rescan()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UdevMonitor) handleBacklightEvent(manager *Manager, action, sysname string) {
|
||||||
switch action {
|
switch action {
|
||||||
case "change":
|
case "change":
|
||||||
m.handleChange(manager, subsystem, sysname)
|
m.handleChange(manager, "backlight", sysname)
|
||||||
case "add", "remove":
|
case "add", "remove":
|
||||||
log.Debugf("Udev %s event: %s:%s - triggering rescan", action, subsystem, sysname)
|
log.Debugf("Udev %s event: backlight:%s - triggering rescan", action, sysname)
|
||||||
manager.Rescan()
|
manager.Rescan()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -752,15 +752,28 @@ Singleton {
|
|||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: screenChangeRescanTimer
|
id: screenChangeRescanTimer
|
||||||
|
property int rescanAttempt: 0
|
||||||
interval: 3000
|
interval: 3000
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: rescanDevices()
|
onTriggered: {
|
||||||
|
rescanDevices();
|
||||||
|
rescanAttempt++;
|
||||||
|
if (rescanAttempt < 3) {
|
||||||
|
interval = rescanAttempt === 1 ? 5000 : 8000;
|
||||||
|
restart();
|
||||||
|
} else {
|
||||||
|
rescanAttempt = 0;
|
||||||
|
interval = 3000;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Quickshell
|
target: Quickshell
|
||||||
|
|
||||||
function onScreensChanged() {
|
function onScreensChanged() {
|
||||||
|
screenChangeRescanTimer.rescanAttempt = 0;
|
||||||
|
screenChangeRescanTimer.interval = 3000;
|
||||||
screenChangeRescanTimer.restart();
|
screenChangeRescanTimer.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user