go-vgo / robotgo

RobotGo, Go Native cross-platform RPA and GUI automation @vcaesar
Apache License 2.0
9.47k stars 862 forks source link

.Move() not placing the mouse where it should be! #594

Open the-hotmann opened 1 year ago

the-hotmann commented 1 year ago
  1. Please speak English (English only), this is the language everybody of us can speak and write.
  2. Please take a moment to search that an issue doesn't already exist.
  3. Please make sure Golang, GCC is installed correctly before installing RobotGo.
  4. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report.

You MUST delete the content above including this line before posting, otherwise your issue will be invalid.

https://go.dev/play/p/VnAAeXKkbk4


package main

import (
    "fmt"
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"

    "github.com/go-vgo/robotgo"
)

const (
    duration      = 1 * time.Second
    checkInterval = 10 * time.Millisecond
)

func moveMouse(x, y int) {

    // debug!
    testx_init, testy_init := robotgo.Location()
    fmt.Println("MOUSE IS AT:\t\t", testx_init, " ", testy_init)

    fmt.Println("SHOULD MOVE MOUSE TO:\t", x, " ", y)
    robotgo.Move(x, y)
    fmt.Println("MOUSE MOVED")

    // debug!
    testx_final, testy_final := robotgo.Location()
    fmt.Println("MOUSE IS AT:\t\t", testx_final, " ", testy_final)

}

// CheckForUserInput checks if there is any mouse input from the real user
func CheckForUserInput(checkX, checkY int) bool {
    x, y := robotgo.Location()
    time.Sleep(10 * time.Millisecond)
    if x != checkX || y != checkY {
        return true // Mouse position changed, indicating user interaction
    }
    return false
}

func main() {
    // Get screen resolution
    screenWidth, screenHeight := robotgo.Location()

    fmt.Println("SCREEN:", screenWidth, screenHeight)
    fmt.Println("")

    // Center the mouse in the screen
    centerX, centerY := screenWidth/2, screenHeight/2
    moveMouse(centerX, centerY)

    // Save current mouse position
    originalX, originalY := robotgo.Location()
    checkX, checkY := originalX, originalY

    // Define the directions for mouse movement
    directions := []struct {
        dx, dy int
    }{
        {-1, 0}, // Left
        {0, -1}, // Up
        {1, 0},  // Right
        {0, 1},  // Down
    }

    // Start moving the mouse
    stopChan := make(chan bool)
    ticker := time.NewTicker(checkInterval)

    go func() {

        time.Sleep(duration)

        for {

            for _, dir := range directions {
                // debug!
                fmt.Println("")

                newX, newY := checkX, checkY

                newX += dir.dx
                newY += dir.dy

                moveMouse(newX, newY)

                checkX, checkY = newX, newY

                // Define the ticker with the desired interval (e.g., 1 second)
                startTime := time.Now()

                for range ticker.C {

                    if time.Since(startTime) >= duration {
                        fmt.Println("break!")
                        break
                    }

                    if CheckForUserInput(checkX, checkY) {
                        stopChan <- true
                        return
                    }

                    <-ticker.C

                }

                time.Sleep(1 * time.Second)

            }

        }

    }()

    // Wait for termination signal
    exitChan := make(chan os.Signal, 1)
    signal.Notify(exitChan, os.Interrupt, syscall.SIGTERM)
    select {
    case <-exitChan:
        log.Println("Exiting...")
    case <-stopChan:
        fmt.Println("")
        log.Println("Mouse input detected. Exiting...")
    }

    // Restore the original mouse position
    //moveMouse(originalX, originalY)

    // Log the final state before exiting
    log.Println("Original mouse location:", originalX, originalY)
    finalX, finalY := robotgo.Location()
    log.Println("Final mouse location:", finalX, finalY)

    // Sleep for 5 seconds to allow reading the logs
    time.Sleep(20 * time.Second)
}

Description

I noticed, that when I move the mouse on windows, I will often not land where it is supposed to be. Since I check and terminate the app once it is at a wrong position (human interaction) this is critical.

I now worked around with 1 pixle tolerance, but this is just a hacky solution. after you execute robotgo.Move(x, y) the x & y value should be exactly the same as the return values of robotgo.Location(). But they are not!

If you want to test: it is in debug mode, so just check the output. Notice: the first movement is the centering of the mouse.

HaiboLee commented 7 months ago

windows11?