mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-14 17:52:10 -04:00
screensaver: emit ActiveChanged on lock/unlock (#1761)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package freedesktop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -15,45 +16,9 @@ type screensaverHandler struct {
|
||||
manager *Manager
|
||||
}
|
||||
|
||||
func (m *Manager) initializeScreensaver() error {
|
||||
if m.sessionConn == nil {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
reply, err := m.sessionConn.RequestName(dbusScreensaverName, dbus.NameFlagDoNotQueue)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to request screensaver name: %v", err)
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
if reply != dbus.RequestNameReplyPrimaryOwner {
|
||||
log.Warnf("Screensaver name already owned by another process")
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
handler := &screensaverHandler{manager: m}
|
||||
|
||||
if err := m.sessionConn.Export(handler, dbusScreensaverPath, dbusScreensaverInterface); err != nil {
|
||||
log.Warnf("Failed to export screensaver on %s: %v", dbusScreensaverPath, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.sessionConn.Export(handler, dbusScreensaverPath2, dbusScreensaverInterface); err != nil {
|
||||
log.Warnf("Failed to export screensaver on %s: %v", dbusScreensaverPath2, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
screensaverIface := introspect.Interface{
|
||||
Name: dbusScreensaverInterface,
|
||||
func screensaverIntrospectIface(ifaceName string) introspect.Interface {
|
||||
return introspect.Interface{
|
||||
Name: ifaceName,
|
||||
Methods: []introspect.Method{
|
||||
{
|
||||
Name: "Inhibit",
|
||||
@@ -69,40 +34,110 @@ func (m *Manager) initializeScreensaver() error {
|
||||
{Name: "cookie", Type: "u", Direction: "in"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GetActive",
|
||||
Args: []introspect.Arg{
|
||||
{Name: "active", Type: "b", Direction: "out"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "SetActive",
|
||||
Args: []introspect.Arg{
|
||||
{Name: "active", Type: "b", Direction: "in"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Lock",
|
||||
},
|
||||
},
|
||||
Signals: []introspect.Signal{
|
||||
{
|
||||
Name: "ActiveChanged",
|
||||
Args: []introspect.Arg{
|
||||
{Name: "new_value", Type: "b"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) initializeScreensaver() error {
|
||||
if m.sessionConn == nil {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
introNode := &introspect.Node{
|
||||
Name: dbusScreensaverPath,
|
||||
Interfaces: []introspect.Interface{
|
||||
introspect.IntrospectData,
|
||||
screensaverIface,
|
||||
},
|
||||
}
|
||||
if err := m.sessionConn.Export(introspect.NewIntrospectable(introNode), dbusScreensaverPath, "org.freedesktop.DBus.Introspectable"); err != nil {
|
||||
log.Warnf("Failed to export introspectable on %s: %v", dbusScreensaverPath, err)
|
||||
handler := &screensaverHandler{manager: m}
|
||||
|
||||
// Try to claim org.freedesktop.ScreenSaver (may fail if the compositor
|
||||
// or another process already owns this name).
|
||||
if reply, err := m.sessionConn.RequestName(dbusScreensaverName, dbus.NameFlagDoNotQueue); err != nil {
|
||||
log.Warnf("Failed to request screensaver name %s: %v", dbusScreensaverName, err)
|
||||
} else if reply != dbus.RequestNameReplyPrimaryOwner {
|
||||
log.Warnf("Screensaver name %s already owned by another process", dbusScreensaverName)
|
||||
} else if err := m.exportScreensaverOnPaths(handler, dbusScreensaverInterface,
|
||||
dbusScreensaverPath, dbusScreensaverPath2); err != nil {
|
||||
log.Warnf("Failed to export freedesktop screensaver: %v", err)
|
||||
} else {
|
||||
m.screensaverFreedesktopClaimed = true
|
||||
log.Infof("Claimed %s on session bus", dbusScreensaverName)
|
||||
}
|
||||
|
||||
introNode2 := &introspect.Node{
|
||||
Name: dbusScreensaverPath2,
|
||||
Interfaces: []introspect.Interface{
|
||||
introspect.IntrospectData,
|
||||
screensaverIface,
|
||||
},
|
||||
// Try to claim org.gnome.ScreenSaver independently as a fallback.
|
||||
if reply, err := m.sessionConn.RequestName(dbusGnomeScreensaverName, dbus.NameFlagDoNotQueue); err != nil {
|
||||
log.Warnf("Failed to request screensaver name %s: %v", dbusGnomeScreensaverName, err)
|
||||
} else if reply != dbus.RequestNameReplyPrimaryOwner {
|
||||
log.Warnf("Screensaver name %s already owned by another process", dbusGnomeScreensaverName)
|
||||
} else if err := m.exportScreensaverOnPaths(handler, dbusGnomeScreensaverInterface,
|
||||
dbusGnomeScreensaverPath); err != nil {
|
||||
log.Warnf("Failed to export gnome screensaver: %v", err)
|
||||
} else {
|
||||
m.screensaverGnomeClaimed = true
|
||||
log.Infof("Claimed %s on session bus", dbusGnomeScreensaverName)
|
||||
}
|
||||
if err := m.sessionConn.Export(introspect.NewIntrospectable(introNode2), dbusScreensaverPath2, "org.freedesktop.DBus.Introspectable"); err != nil {
|
||||
log.Warnf("Failed to export introspectable on %s: %v", dbusScreensaverPath2, err)
|
||||
|
||||
if !m.screensaverFreedesktopClaimed && !m.screensaverGnomeClaimed {
|
||||
log.Warn("No screensaver interface could be claimed")
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
go m.watchPeerDisconnects()
|
||||
|
||||
m.stateMutex.Lock()
|
||||
m.state.Screensaver.Available = true
|
||||
m.state.Screensaver.Active = false
|
||||
m.state.Screensaver.Inhibited = false
|
||||
m.state.Screensaver.Inhibitors = []ScreensaverInhibitor{}
|
||||
m.stateMutex.Unlock()
|
||||
|
||||
log.Info("Screensaver inhibit listener initialized")
|
||||
log.Info("Screensaver listener initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
// exportScreensaverOnPaths exports the handler and introspection on the given
|
||||
// paths under the specified interface name.
|
||||
func (m *Manager) exportScreensaverOnPaths(handler *screensaverHandler, ifaceName string, paths ...dbus.ObjectPath) error {
|
||||
iface := screensaverIntrospectIface(ifaceName)
|
||||
for _, path := range paths {
|
||||
if err := m.sessionConn.Export(handler, path, ifaceName); err != nil {
|
||||
return fmt.Errorf("export handler on %s: %w", path, err)
|
||||
}
|
||||
node := &introspect.Node{
|
||||
Name: string(path),
|
||||
Interfaces: []introspect.Interface{
|
||||
introspect.IntrospectData,
|
||||
iface,
|
||||
},
|
||||
}
|
||||
if err := m.sessionConn.Export(introspect.NewIntrospectable(node), path, "org.freedesktop.DBus.Introspectable"); err != nil {
|
||||
log.Warnf("Failed to export introspectable on %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -268,3 +303,53 @@ func (m *Manager) NotifyScreensaverSubscribers() {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (h *screensaverHandler) GetActive() (bool, *dbus.Error) {
|
||||
h.manager.stateMutex.RLock()
|
||||
active := h.manager.state.Screensaver.Active
|
||||
h.manager.stateMutex.RUnlock()
|
||||
return active, nil
|
||||
}
|
||||
|
||||
func (h *screensaverHandler) SetActive(active bool) *dbus.Error {
|
||||
h.manager.SetScreenLockActive(active)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *screensaverHandler) Lock() *dbus.Error {
|
||||
h.manager.SetScreenLockActive(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetScreenLockActive updates the screensaver active (locked) state and emits
|
||||
// ActiveChanged on all claimed session bus interfaces.
|
||||
func (m *Manager) SetScreenLockActive(active bool) {
|
||||
m.stateMutex.Lock()
|
||||
changed := m.state.Screensaver.Active != active
|
||||
m.state.Screensaver.Active = active
|
||||
m.stateMutex.Unlock()
|
||||
|
||||
if !changed {
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Screen lock active changed: %v", active)
|
||||
|
||||
if m.sessionConn != nil {
|
||||
if m.screensaverFreedesktopClaimed {
|
||||
if err := m.sessionConn.Emit(dbusScreensaverPath, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
|
||||
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath, err)
|
||||
}
|
||||
if err := m.sessionConn.Emit(dbusScreensaverPath2, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
|
||||
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath2, err)
|
||||
}
|
||||
}
|
||||
if m.screensaverGnomeClaimed {
|
||||
if err := m.sessionConn.Emit(dbusGnomeScreensaverPath, dbusGnomeScreensaverInterface+".ActiveChanged", active); err != nil {
|
||||
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusGnomeScreensaverPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.NotifyScreensaverSubscribers()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user