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 } } } } }