automatic-mouse-mover/pkg/mousemover/mouseMover.go

119 lines
2.6 KiB
Go

package mousemover
import (
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/go-vgo/robotgo"
"github.com/prashantgupta24/activity-tracker/pkg/tracker"
"github.com/prashantgupta24/automatic-mouse-mover/pkg/notify"
)
var instance *MouseMover
//MouseMover is the main struct for the app
type MouseMover struct {
quit chan struct{}
mutex sync.RWMutex
runningStatus bool
}
const (
timeout = 100 //ms
)
//Start the main app
func (m *MouseMover) Start() {
if m.isRunning() {
return
}
m.quit = make(chan struct{})
frequency := 60 //value always in seconds
activityTracker := &tracker.Instance{
Frequency: frequency,
//LogLevel: "debug", //if we want verbose logging
}
heartbeatCh := activityTracker.Start()
go func(m *MouseMover) {
m.updateRunningStatus(true)
movePixel := 10
for {
select {
case heartbeat := <-heartbeatCh:
if !heartbeat.WasAnyActivity {
mouseMoveSuccessCh := make(chan bool)
go moveAndCheck(movePixel, mouseMoveSuccessCh)
select {
case wasMouseMoveSuccess := <-mouseMoveSuccessCh:
if wasMouseMoveSuccess {
log.Infof("moved mouse at : %v\n\n", time.Now())
movePixel *= -1
} else {
msg := "Mouse pointer cannot be moved. See README for details."
log.Errorf(msg)
notify.SendMessage(msg)
}
case <-time.After(timeout * time.Millisecond):
//timeout, do nothing
log.Errorf("timeout happened after %vms while trying to move mouse", timeout)
}
}
case <-m.quit:
log.Infof("stopping mouse mover")
m.updateRunningStatus(false)
activityTracker.Quit()
return
}
}
}(m)
}
func (m *MouseMover) isRunning() bool {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.runningStatus
}
func (m *MouseMover) updateRunningStatus(isRunning bool) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.runningStatus = isRunning
}
func moveAndCheck(movePixel int, mouseMoveSuccessCh chan bool) {
currentX, currentY := robotgo.GetMousePos()
moveToX := currentX + movePixel
moveToY := currentY + movePixel
robotgo.MoveMouse(moveToX, moveToY)
//check if mouse moved. Sometimes mac users need to give
//extra permission for controlling the mouse
movedX, movedY := robotgo.GetMousePos()
if movedX == currentX && movedY == currentY {
mouseMoveSuccessCh <- false
} else {
mouseMoveSuccessCh <- true
}
}
//Quit the app
func (m *MouseMover) Quit() {
//making it idempotent
if m != nil && m.isRunning() {
m.quit <- struct{}{}
}
}
//GetInstance gets the singleton instance for mouse mover app
func GetInstance() *MouseMover {
if instance == nil {
instance = &MouseMover{}
}
return instance
}