diff --git a/afterlock/afterlock.go b/afterlock/afterlock.go new file mode 100644 index 0000000..6ca3360 --- /dev/null +++ b/afterlock/afterlock.go @@ -0,0 +1,101 @@ +package afterlock + +import( + "after-lock/evdev" + "after-lock/lockscreen" + "after-lock/display" + "after-lock/atomicflag" + "time" + "sync" + "errors" +) + + +// AfterLock suspends the display when the lockscreen is active +type AfterLock struct { + InitialDelay uint + LoopDelay uint + keyboardDeviceNode string + wg sync.WaitGroup + stopFlag *atomicflag.AtomicFlag + keypressFlag *atomicflag.AtomicFlag +} + +// New constructs a new AfterLock instance +func New(keyboardDeviceNode string) *AfterLock { + return &AfterLock{ + keyboardDeviceNode: keyboardDeviceNode, + stopFlag: atomicflag.New(false), + keypressFlag: atomicflag.New(false), + } +} + +// Start starts monitoring the lockscreen/keyboard status to determine +// when to suspend the display. +// Exits after the computer is unlocked +func (af *AfterLock) Start() { + af.checkDelaysConfigured() + + af.wg.Add(1) + go af.detectKeypresses() + + time.Sleep(time.Duration(af.InitialDelay) * time.Second) + af.hybernateDisplayLoop() +} + +func (af *AfterLock) checkDelaysConfigured() { + if af.InitialDelay == 0 { + panic(errors.New("InitialDelay not configured")) + } + if af.LoopDelay == 0 { + panic(errors.New("LoopDelay not configured")) + } +} + +func (af *AfterLock) detectKeypresses() { + for { + err := evdev.BlockUntilKeypress(af.keyboardDeviceNode) + if err != nil { + panic(err) + } + if af.stopFlag.Get() { + af.wg.Done() + return + } + af.keypressFlag.Set(true) + } +} + +func (af *AfterLock) hybernateDisplayLoop() { + for { + screenLocked, err := lockscreen.IsActive() + if err != nil { + panic(err) + } + if !screenLocked { + af.stopFlag.Set(true) + af.wg.Wait() + return + } + + displayOn, err := display.IsOn() + if err != nil { + panic(err) + } + if displayOn { + err := display.Suspend() + if err != nil { + panic(err) + } + for { + time.Sleep(time.Duration(af.LoopDelay) * time.Second) + if af.keypressFlag.Get() { + af.keypressFlag.Set(false) + continue + } else { + break + } + } + } + } +} \ No newline at end of file diff --git a/cmd/after-lock/after-lock.go b/cmd/after-lock/after-lock.go new file mode 100644 index 0000000..c7af146 --- /dev/null +++ b/cmd/after-lock/after-lock.go @@ -0,0 +1,20 @@ +package main + +import ( + "after-lock/afterlock" +) + +const ( + initialDelay = 3 + loopDelay = 6 + keyboardDeviceNode = "/dev/input/by-id/usb-Dell_Dell_USB_Entry_Keyboard-event-kbd" +) + + +func main() { + al := afterlock.New(keyboardDeviceNode) + al.InitialDelay = initialDelay + al.LoopDelay = loopDelay + + al.Start() +} \ No newline at end of file diff --git a/main.go b/main.go deleted file mode 100644 index 9ad82b8..0000000 --- a/main.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -import( - "after-lock/evdev" - "after-lock/lockscreen" - "after-lock/display" - "after-lock/atomicflag" - "time" - "sync" -) - -const ( - initialDelay = 3 - loopDelay = 6 - keyboardDeviceNode = "/dev/input/by-id/usb-Dell_Dell_USB_Entry_Keyboard-event-kbd" -) - - -func main() { - al := newAfterLock() - al.start() -} - -type afterLock struct { - wg sync.WaitGroup - stopFlag *atomicflag.AtomicFlag - keypressFlag *atomicflag.AtomicFlag -} - -func newAfterLock() *afterLock { - return &afterLock{ - stopFlag: atomicflag.New(false), - keypressFlag: atomicflag.New(false), - } -} - -func (af *afterLock) start() { - af.wg.Add(1) - - go af.detectKeypresses() - time.Sleep(initialDelay * time.Second) - af.hybernateDisplayLoop() -} - -func (af *afterLock) detectKeypresses() { - for { - err := evdev.BlockUntilKeypress(keyboardDeviceNode) - if err != nil { - panic(err) - } - if af.stopFlag.Get() { - af.wg.Done() - return - } - af.keypressFlag.Set(true) - } -} - -func (af *afterLock) hybernateDisplayLoop() { - for { - screenLocked, err := lockscreen.IsActive() - if err != nil { - panic(err) - } - if !screenLocked { - af.stopFlag.Set(true) - af.wg.Wait() - return - } - - displayOn, err := display.IsOn() - if err != nil { - panic(err) - } - if displayOn { - err := display.Suspend() - if err != nil { - panic(err) - } - for { - time.Sleep(loopDelay * time.Second) - if af.keypressFlag.Get() { - af.keypressFlag.Set(false) - continue - } else { - break - } - } - } - } -} \ No newline at end of file