mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-01 19:18:28 -04:00
90291bd627
ppd, and some things. Add a simple wpa_supplicant backend
97 lines
2.0 KiB
Go
97 lines
2.0 KiB
Go
package trayrecovery
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/loginctl"
|
|
"github.com/godbus/dbus/v5"
|
|
)
|
|
|
|
const resumeDelay = 3 * time.Second
|
|
|
|
type Manager struct {
|
|
conn *dbus.Conn
|
|
stopChan chan struct{}
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
func NewManager() (*Manager, error) {
|
|
conn, err := dbus.ConnectSessionBus()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to connect to session bus: %w", err)
|
|
}
|
|
|
|
m := &Manager{
|
|
conn: conn,
|
|
stopChan: make(chan struct{}),
|
|
}
|
|
|
|
// Only run a startup scan when the system has been suspended at least once.
|
|
// On a fresh boot CLOCK_BOOTTIME ≈ CLOCK_MONOTONIC (difference ~0).
|
|
// After any suspend/resume cycle the difference grows by the time spent
|
|
// sleeping. This avoids duplicate registrations on normal boot where apps
|
|
// are still starting up and will register their own tray icons shortly.
|
|
if timeSuspended() > 5*time.Second {
|
|
go m.scheduleRecovery()
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
// WatchLoginctl subscribes to loginctl session state changes and triggers
|
|
// tray recovery after resume from suspend (PrepareForSleep false transition).
|
|
// This handles the case where the process survives suspend.
|
|
func (m *Manager) WatchLoginctl(lm *loginctl.Manager) {
|
|
ch := lm.Subscribe("tray-recovery")
|
|
m.wg.Add(1)
|
|
go func() {
|
|
defer m.wg.Done()
|
|
defer lm.Unsubscribe("tray-recovery")
|
|
|
|
wasSleeping := false
|
|
for {
|
|
select {
|
|
case <-m.stopChan:
|
|
return
|
|
case state, ok := <-ch:
|
|
if !ok {
|
|
return
|
|
}
|
|
if state.PreparingForSleep {
|
|
wasSleeping = true
|
|
continue
|
|
}
|
|
if wasSleeping {
|
|
wasSleeping = false
|
|
go m.scheduleRecovery()
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (m *Manager) scheduleRecovery() {
|
|
select {
|
|
case <-time.After(resumeDelay):
|
|
m.recoverTrayItems()
|
|
case <-m.stopChan:
|
|
}
|
|
}
|
|
|
|
func (m *Manager) Close() {
|
|
select {
|
|
case <-m.stopChan:
|
|
return
|
|
default:
|
|
close(m.stopChan)
|
|
}
|
|
m.wg.Wait()
|
|
if m.conn != nil {
|
|
m.conn.Close()
|
|
}
|
|
log.Info("TrayRecovery manager closed")
|
|
}
|