Jump to content

MouseMove jumping erratically on 2nd monitor. - (Moved)


Recommended Posts

I created a basic program to check do a simple mouse jiggle every preset number of minutes based upon specific applications being actively running.  It moves 1 space to the right, then one to the left putting it right back where it started.

When the mouse is on my primary screen on my laptop it works perfectly.  When I have the mouse on the 2nd monitor which is on the left side of my laptop, the mouse movements jump quite far then a little back  Each time the action is performed moves it further until it is off of the screen (which is only a few jiggles).

Due to the monitor configuration I must note that the monitor that is to the left of my notebook shows a negative location for the X position of the mouse.  Position 0 is on the right side of the screen, not the left.

 

Quote

    $MousePosition = MouseGetPos()
        MouseMove($MousePosition[0]+1,$MousePosition[1],0) 
    Sleep(500)
    $MousePosition = MouseGetPos()
        MouseMove($MousePosition[0]-1,$MousePosition[1],0) 

 

Does anybody have any thoughts of what the cause is and how I can fix this.

 

Thank You in advance.

 

Link to post
Share on other sites
  • Moderators

Moved to the appropriate forum, as the Developer General Discussion forum very clearly states:

Quote

General development and scripting discussions.


Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums.

Moderation Team

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to post
Share on other sites

Hey TeddyBear,

I haven't looked at the topic Danp2 linked, however, seems when numbers are negative, mousemove behaves differently.

(Edit: I haven't tested my comment about removing the two lines in the 2nd code box, and idk if the correction needs to be adjusted if different resolutions/scaling is used)

A correction for when mousepos is negative fixes that. Test function.

test()


func test()

    local $aMousePosition = MouseGetPos()
    local $iDisplacementCorrection

     $iDisplacementCorrection = ($aMousePosition[0] = abs($aMousePosition[0])) ? (0) : (1)

    consolewrite("before: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    MouseMove($aMousePosition[0] + 1 - $iDisplacementCorrection, $aMousePosition[1], 0)

    sleep(1000)

    $aMousePosition = MouseGetPos()

    consolewrite("after 1st: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    MouseMove($aMousePosition[0] - 1 - $iDisplacementCorrection, $aMousePosition[1], 0)

    $aMousePosition = MouseGetPos()

    consolewrite("after 2nd: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

EndFunc

And your code would be something like:

; Get initial mouse position
Local $aMousePosition = MouseGetPos()
Local $iDisplacementCorrection

; Find DisplacementCorrection
$iDisplacementCorrection = ($aMousePosition[0] = abs($aMousePosition[0])) ? (0) : (1)

; Move mouse to right
MouseMove($aMousePosition[0] + 1 - $iDisplacementCorrection, $aMousePosition[1], 0)

sleep(500)

; Get current mouse position (seems unneeded though)
$aMousePosition = MouseGetPos()

; Move mouse back to original position
MouseMove($aMousePosition[0] - 1 - $iDisplacementCorrection, $aMousePosition[1], 0)

; Maybe remove the two lines above and use this instead? Since we already know the original location
;MouseMove($aMousePosition[0] - $iDisplacementCorrection, $aMousePosition[1], 0)

 

Edited by GokAy
Added a disclaimer
Link to post
Share on other sites

Interesting, before trying to understand x axis, why the movement on y axis?

Btw, my test rig:

Laptop display (primary, 1920x1080, 100% scaling)

External HDMI (secondary, 1920x1080, 100% scaling), on the right normally, but used display settings to drag it to left for the test)

 

Can you test this please? Ideally, mouse shouldn't move at all, right? In my situation, it would move by 1 on x axis, each time mousemove was issued.

test()


func test()

    local $aMousePosition = MouseGetPos()

    consolewrite("before: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    MouseMove($aMousePosition[0], $aMousePosition[1], 0)

    sleep(500)

    $aMousePosition = MouseGetPos()

    consolewrite("after 1st: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    MouseMove($aMousePosition[0], $aMousePosition[1], 0)

    $aMousePosition = MouseGetPos()

    consolewrite("after 2nd: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

EndFunc

 

Link to post
Share on other sites

I completely agree with you.  The Y position should not move at all.   

 

Test below from your most recent post. 
 

Additional Monitor

Quote

before: -678 - 226
after 1st: -1083 - 362
after 2nd: -1536 - 580

 

Laptop Screen

Quote

before: 328 - 177
after 1st: 329 - 178
after 2nd: 330 - 179

Windows 10 Laptop 2560 x 1440 at 200% Scale.  Monitor to the left of the laptop is 1920 x 1200 at 125% Scale.

 

 

Link to post
Share on other sites

Hey again,

I might have solved the mystery :) 

Problem is MouseGetPos() and MouseMove() use different calculation methods. And everything is dependant on Scaling and Resolutions involved. Monitor positions also affect the calculation.

After a lot of testing, I did come up with something that "should" work. It works on my laptop. 

Primary: Laptop display (1920 x 1080)

Secondary: HDMI External (1920 x 1080)

Tried as much combination possible, but still ...

* Haven't given much thought but should work with up to 3 monitors at this state I believe if center is primary (slight possibility, maybe even up to 6). Just need to add variables for height/width/scaling for 3rd (left monitor) and change 2nd monitor variables to 3rd within "If MousePositions < 0 then" part.

I am posting the code with all the mess in case we need more testing. Can remove consolewrite's later.

Sometimes it does move a pixel to right/left of intended position initially (I guess due to some rounding), but settles at a certain point in 1 or 2 consecutive runs of the script.

Also, I searched for getting the info for displays with code, but don't have the time to implement at the moment. And to be honest, I don't know if they would give reliable results for all setups. Linking them as a fyi:

1. AutoIt documentation for: _WinAPI_EnumDisplayMonitors()

2. InnI's post below

 

_MoveMouse()


Func _MoveMouse()

    Local $i_Hor_Displacement = 2 ;Jiggle n pixels
    
    ; Primary display
    Local $i_Height_1st = 1080
    Local $i_Width_1st = 1920
    Local $i_Scaling_1st = 100

    ; Secondary display, either left or right
    Local $i_Height_2nd = 1080
    Local $i_Width_2nd = 1920
    Local $i_Scaling_2nd = 100

    Local $iPos_x
    Local $iPos_y

    Local $i_RightMost_1st = $i_Width_1st / ($i_Scaling_1st / 100) - 1
    Local $i_LeftMost_2nd

    ConsoleWrite("RightMost: " & $i_RightMost_1st & @crlf)

    Local $i_MousePosRelativeTo2nd

    Local $aMousePosition = MouseGetPos()

    ConsoleWrite("Before: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    If $aMousePosition[0] < 0 Then
        ; Display is positioned to the left
        Local $i_LeftMost = $i_Width_2nd * ((100/$i_Scaling_2nd) - 1) - $i_Width_1st * ((100/$i_Scaling_1st) - 1) - 1
        ConsoleWrite("LeftMost (-): " & $i_LeftMost & @CRLF)

        $iPos_x = Floor(($aMousePosition[0]) / $i_Scaling_1st * $i_Scaling_2nd) - 1

        ;$iPos_x = Floor(($aMousePosition[0]- $i_LeftMost - 1) * $i_Scaling_2nd / $i_Scaling_1st) ; Subtract 1 since 1st pixel on the right is -1
        ConsoleWrite("Pos_x: " & $iPos_x & @crlf)

        $iPos_y = Floor(($aMousePosition[1]) * ($i_Scaling_2nd / $i_Scaling_1st))
        ConsoleWrite("Pos_y: " & $iPos_y & @CRLF)

    ElseIf $aMousePosition[0] >= 0 and $aMousePosition[0] < $i_Width_1st / ($i_Scaling_1st/100)  Then
        ; Display is 1st
        ; No conversion necessary
        $iPos_x = $aMousePosition[0]
        $iPos_y = $aMousePosition[1] - Ceiling (1 * ($i_Scaling_1st-100)/100)

    ElseIf $aMousePosition[0] >= $i_Width_1st / ($i_Scaling_1st/100) Then
        ; Display is positioned to the right
        If $i_Scaling_1st = $i_Scaling_2nd Then
            $i_LeftMost_2nd = $i_Width_1st / ($i_Scaling_1st / 100)
            ConsoleWrite("LeftMost (=) : " & $i_LeftMost_2nd & @crlf)

            $i_MousePosRelativeTo2nd = ($aMousePosition[0] - $i_LeftMost_2nd) / ($i_Scaling_1st / $i_Scaling_2nd)
            $iPos_x = Floor($i_RightMost_1st + $i_MousePosRelativeTo2nd + 1)
            ConsoleWrite("RelPos: " & $i_MousePosRelativeTo2nd & " > Pos_x: " & $iPos_x & @crlf)

            $iPos_y = Floor(($aMousePosition[1]) * ($i_Scaling_2nd / $i_Scaling_1st))
            ConsoleWrite("Pos_y: " & $iPos_y & @CRLF)

        ElseIf $i_Scaling_1st > $i_Scaling_2nd Then
            $i_LeftMost_2nd = $i_Width_1st / ($i_Scaling_2nd/100)
            ConsoleWrite("LeftMost (>): " & $i_LeftMost_2nd & @crlf)

            $i_MousePosRelativeTo2nd = ($aMousePosition[0] - $i_LeftMost_2nd) / ($i_Scaling_1st / $i_Scaling_2nd)
            $iPos_x = Floor($i_RightMost_1st + $i_MousePosRelativeTo2nd + 1)
            ConsoleWrite("RelPos: " & $i_MousePosRelativeTo2nd & " > Pos_x: " & $iPos_x & @crlf)

            $iPos_y = Floor(($aMousePosition[1]) * ($i_Scaling_2nd/$i_Scaling_1st))
            ConsoleWrite("Pos_y: " & $iPos_y & @CRLF)

        ElseIf $i_Scaling_1st < $i_Scaling_2nd Then
            $i_LeftMost_2nd = $i_Width_1st / ($i_Scaling_1st / 100)
            ConsoleWrite("LeftMost (<): " & $i_LeftMost_2nd & @crlf)

            $i_MousePosRelativeTo2nd = ($aMousePosition[0] - $i_LeftMost_2nd) / ($i_Scaling_1st / $i_Scaling_2nd)
            $iPos_x = Floor($i_RightMost_1st + $i_MousePosRelativeTo2nd + 1)
            ConsoleWrite("RelPos: " & $i_MousePosRelativeTo2nd & " > Pos_x: " & $iPos_x & @crlf)

            $iPos_y = Floor(($aMousePosition[1]) * ($i_Scaling_2nd / $i_Scaling_1st))
            ConsoleWrite("Pos_y: " & $iPos_y & @CRLF)

        EndIf
    EndIf

    Local $iPos_y_Correction = ($iPos_y < 0 ) ? (-1) : (0) ; May need a scaling, didn't test, only if 2nd monitor is positioned above
    ConsoleWrite("Pos_y: " & $iPos_y & " > Correction: " & $iPos_y_Correction & @CRLF)

    MouseMove($iPos_x + ($i_Hor_Displacement * $i_Scaling_2nd / $i_Scaling_1st), $iPos_y + $iPos_y_Correction, 0)

    sleep(500)

    $aMousePosition = MouseGetPos()

    ConsoleWrite("After 1: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

    MouseMove($iPos_x, $iPos_y + $iPos_y_Correction, 0)

    $aMousePosition = MouseGetPos()

    ConsoleWrite("After 1: " & $aMousePosition[0] & " - " & $aMousePosition[1] & @CRLF)

EndFunc

Time to get some sleep 😛 

Edited by GokAy
Link to post
Share on other sites

Sorry for the delay and I appreciate all the help.

This is the results.

Laptop Screen:

Quote

RightMost: 1919
Before: 697 - 323
Pos_y: 323 > Correction: 0
After 1: 700 - 324
After 1: 698 - 324

 

Additional Monitor:

Quote

RightMost: 1919
Before: -338 - 567
LeftMost (-): -1
Pos_x: -339
Pos_y: 567
Pos_y: 567 > Correction: 0
After 1: -538 - 908
After 1: -541 - 908

The additional monitor I am watching a huge jump on location of the mouse.  I am using ScITE and pressing Shift-F5 on the keyboard to make sure I don't move my mouse at all.

Looking at the Before and After on the Additional monitor you can see there is a huge movement.  I just cannot figure out a way around it.

 

The biggest reason this becomes a huge issue for me is I have some virtual KVM software running and I created a small app that when I scroll off the screen from one computer to the next, my application will automatically change the monitor input port to the other computer.  This is set up to work both ways so the screen follows the mouse from computer to computer.  

 

With the big jumps of the mouse it ends up going off the edge of the screen  causing my screen to change the inputs for the other computer.

 

My work computer without my mouse jiggler program will go to lock the screen when I am not active on it, and we cannot change that setting.  It is locked by administration.    I have tested the mouse jiggler with my monitor changing program and the virtual KVM not running in the background and the mouse jiggler issue is still the same.  So I eliminated those issues.

 

 

 

 

Edited by teddybear69
Link to post
Share on other sites

Hey,

Did you change the variables for Resolution and scaling according to your setup?

You said in an earlier post, "Windows 10 Laptop 2560 x 1440 at 200% Scale.  Monitor to the left of the laptop is 1920 x 1200 at 125% Scale." So, the next part should be like:

    ; Primary display
    Local $i_Height_1st = 1440
    Local $i_Width_1st = 2560
    Local $i_Scaling_1st = 200

    ; Secondary display, either left or right
    Local $i_Height_2nd = 1200
    Local $i_Width_2nd = 1920
    Local $i_Scaling_2nd = 125
Edited by GokAy
Link to post
Share on other sites

Ok... that was a HUGE difference.  Silly me for not noticing where to make a change.

 

Laptop Monitor:

Quote

RightMost: 1279
Before: 728 - 199
Pos_y: 198 > Correction: 0
After 1: 730 - 199
After 1: 729 - 199

 

Additional Monitor: 

Quote

RightMost: 1279
Before: -451 - 320
LeftMost (-): 895
Pos_x: -283
Pos_y: 200
Pos_y: 200 > Correction: 0
After 1: -448 - 321
After 1: -451 - 321

 

That is DRAMATICALLY better. 

I notice that the slight difference between monitors on the distance it moving.  Just needs a little fine tuning from here.  I'm trying to figure out why right now.  

AWESOME WORK!!!  

Link to post
Share on other sites

Nice to hear,

You can play with these 2 to adjust the tiny movement:

1st line inside function

Local $i_Hor_Displacement = 2 ;Jiggle n pixels

And, just before sleep(500), you can replace ($i_Hor_Displacement * $i_Scaling_2nd / $i_Scaling_1st) with $i_Hor_Displacement only

    MouseMove($iPos_x + ($i_Hor_Displacement * $i_Scaling_2nd / $i_Scaling_1st), $iPos_y + $iPos_y_Correction, 0)

Depending on the scaling and resolution sometimes 1 px isn't enough to get an actual move.

By the way, the initial misplacement of 1 pixels corrects itself and settles after 1 or 2 runs. Try to observe it by running the script a few times as you do from within SciTe.

And, I guess the 1 px misplacement in the 1st run is because of some rounding going on.

Link to post
Share on other sites

@JockoDundee Well, I haven't tested on a single monitor setup, however, even if there are 2 monitors, regardless of res/scaling (as long as it's the primary display), there is no problem using mousemove with the position obtained from mousegetpos, since the right-most pixel is always:

(res / (scaling / 100)) -1

For a dual-monitor setup (or tripple where center is primary, untested): When, the scaling is same, it doesn't become an issue, as far as I can tell. Since, there is no gap between the right-most of primary display and left-most of secondary display. Here is a table showing the results of mousegetpos from different scaling scenarios.

(1) is primary, (2) is secondary positioned to the right

res 1920   res 1920            
scale1 scaled   scale 2 scaled   1 top-right   2 top-left   2 top-right
100% 1920   100% 1920   1919   1920   3839
125% 1536   100% 1920   1535   1920   3839
150% 1280   100% 1920   1279   1920   3839
                     
100% 1920   125% 1536   1919   1920   3455
125% 1536   125% 1536   1535   1536   3071
150% 1280   125% 1536   1279   1536   3071
                     
100% 1920   150% 1280   1919   1920   3199
125% 1536   150% 1280   1535   1536   2815
150% 1280   150% 1280   1279   1280   2559

 

 

Link to post
Share on other sites
  • 5 weeks later...

For future googlers like me who found this topic because of the scaling issues:
I was able to fix my problem by using DllCall and SetCursorPos. That matches with the numbers I get from MouseGetPos().

So instead of:
MouseMove($x, $y)
I used:
DllCall("user32.dll", "bool", "SetCursorPos", "int", $x, "int", $y)

Link to post
Share on other sites
  • 2 weeks later...

voidfoo... This worked perfectly and was very easy to implement.  Thank you very much.

 

Please note that this does not reset the Timer for _Timer_GetIdleTime().  

If you need this reset, I found in a solution for that in another post by EmilyLove at:  

 

Quote

Send("{asc 0}");sends nothing but still resets the Timer. ASC 0 is the Null Character. Reference: http://www.asciitable.com/

 

Thank you everybody for you assistance.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...