Invert display and lockscreen control dependencies

This commit is contained in:
Kristóf Tóth 2020-08-20 16:57:57 +02:00
parent e6458aba0b
commit ebbd1974df
7 changed files with 59 additions and 17 deletions

View File

@ -1,9 +1,6 @@
package afterlock
import(
"after-lock/evdev"
"after-lock/lockscreen"
"after-lock/display"
"after-lock/atomicflag"
"time"
"sync"
@ -11,6 +8,22 @@ import(
)
// Display controls and monitors the physical display
type Display interface {
Suspend() error
IsOn() (bool, error)
}
// Lockscreen can determine whether the screensaver is active or not
type Lockscreen interface {
IsActive() (bool, error)
}
// KeypressDetector can wait for keypresses
type KeypressDetector interface {
BlockUntilKeypress(string) error
}
// AfterLock suspends the display when the lockscreen is active
type AfterLock struct {
InitialDelay uint
@ -19,6 +32,9 @@ type AfterLock struct {
wg sync.WaitGroup
stopFlag *atomicflag.AtomicFlag
keypressFlag *atomicflag.AtomicFlag
Display Display
LockScreen Lockscreen
KeypressDetector KeypressDetector
}
// New constructs a new AfterLock instance
@ -30,11 +46,12 @@ func New(keyboardDeviceNode string) *AfterLock {
}
}
// Start starts monitoring the lockscreen/keyboard status to determine
// Start starts monitoring the lockscreen/keyboard to determine
// when to suspend the display.
// Exits after the computer is unlocked
// Requires InitialDelay, LoopDelay, Display and LockScreen to be set
func (af *AfterLock) Start() {
af.checkDelaysConfigured()
af.checkStructConfigured()
af.wg.Add(1)
go af.detectKeypresses()
@ -43,18 +60,27 @@ func (af *AfterLock) Start() {
af.hybernateDisplayLoop()
}
func (af *AfterLock) checkDelaysConfigured() {
func (af *AfterLock) checkStructConfigured() {
if af.InitialDelay == 0 {
panic(errors.New("InitialDelay not configured"))
}
if af.LoopDelay == 0 {
panic(errors.New("LoopDelay not configured"))
}
if af.Display == nil {
panic(errors.New("Display not configured"))
}
if af.LockScreen == nil {
panic(errors.New("LockScreen not configured"))
}
if af.KeypressDetector == nil {
panic(errors.New("KeypressDetector not configured"))
}
}
func (af *AfterLock) detectKeypresses() {
for {
err := evdev.BlockUntilKeypress(af.keyboardDeviceNode)
err := af.KeypressDetector.BlockUntilKeypress(af.keyboardDeviceNode)
if err != nil {
panic(err)
}
@ -68,7 +94,7 @@ func (af *AfterLock) detectKeypresses() {
func (af *AfterLock) hybernateDisplayLoop() {
for {
screenLocked, err := lockscreen.IsActive()
screenLocked, err := af.LockScreen.IsActive()
if err != nil {
panic(err)
}
@ -78,12 +104,12 @@ func (af *AfterLock) hybernateDisplayLoop() {
return
}
displayOn, err := display.IsOn()
displayOn, err := af.Display.IsOn()
if err != nil {
panic(err)
}
if displayOn {
err := display.Suspend()
err := af.Display.Suspend()
if err != nil {
panic(err)
}

View File

@ -2,10 +2,13 @@ package main
import (
"after-lock/afterlock"
"after-lock/display"
"after-lock/keypressdetector"
"after-lock/lockfile"
"after-lock/lockscreen"
"fmt"
"runtime/debug"
"os"
"runtime/debug"
)
const (
@ -26,6 +29,9 @@ func main() {
al := afterlock.New(keyboardDeviceNode)
al.InitialDelay = initialDelay
al.LoopDelay = loopDelay
al.Display = display.Xset{}
al.LockScreen = lockscreen.XDG{}
al.KeypressDetector = keypressdetector.Evdev{}
al.Start()
}

View File

@ -7,8 +7,11 @@ import (
)
// Suspend the display using xset
func Suspend() error {
// Xset monitors/controls the display using xset
type Xset struct {}
// Suspend the display
func (Xset) Suspend() error {
cmd := exec.Command("xset",
"dpms",
"force",
@ -18,7 +21,7 @@ func Suspend() error {
}
// IsOn determines if the display is on
func IsOn() (bool, error) {
func (Xset) IsOn() (bool, error) {
cmd := exec.Command("xset", "q")
outputBytes, err := cmd.CombinedOutput()
if err != nil {

View File

@ -1,4 +1,4 @@
package evdev
package keypressdetector
// #cgo CFLAGS: -g -Wall
// #include "evdev.h"
@ -11,7 +11,11 @@ import (
)
func BlockUntilKeypress(devicePath string) error {
// Evdev can detect keypresses on /dev/input devices
type Evdev struct {}
// BlockUntilKeypress waits until a key is pressed on the specified device
func (Evdev) BlockUntilKeypress(devicePath string) error {
path := C.CString(devicePath)
defer C.free(unsafe.Pointer(path))

View File

@ -6,8 +6,11 @@ import (
)
// XDG uses qdbus to monitor the freedesktop screensaver status
type XDG struct {}
// IsActive checks whether the screen is locked (checks if the screensaver is active)
func IsActive() (bool, error) {
func (XDG) IsActive() (bool, error) {
cmd := exec.Command("qdbus",
"org.kde.screensaver",
"/ScreenSaver",