MouseUnSnag / MouseUnSnag

On a Windows system with multiple monitors, allow the mouse to move freely and not get stuck on corners or edges.
MIT License
147 stars 28 forks source link

Adjacent monitor jump issue #16

Closed Robin-S closed 2 years ago

Robin-S commented 2 years ago

Hi there,

This is a lovely tool and I just installed it on a new device. I found some unexpected behaviour in what I guess comes from the +j option for jumping the mouse cursor to adjacent monitors that aren't quite aligned with each other.

I've added a StartUp link that runs the .exe as follows:

C:\Users\<username>\.tools\MouseUnSnag\MouseUnSnag.exe +s +j -w

Let me illustrate the issue by showing my monitor setup and adding some arrows, like in the readme.

Expected behaviour: image The cursor moving along the top of screen 3 onto screen 4 should be moved from the top-right of screen 3 to the top-left of screen 4. Similarly, the cursor moving along the top of screen 2 onto screen 4 should be moved from the top-left of screen 2 to the top-right of screen 4.

Observed behaviour: image The cursor jumps from the top-right of screen 3 to the top-left of screen 1. Similarly, the cursor jumps from the top-left of screen 2 to the top-right of screen 1.

I tried to work around this by just disabling the 'Jump between monitors' option, but that will have the mouse snag in my Screen3-top-right and Screen2-top-left corners and not move to another screen at all.

Robin-S commented 2 years ago

Looking into the code, it looks like this is due to the DisplayList.ScreenInDirection implementation returning the first display that matches a directional criterion.

Assuming that's indeed the issue, the comment in that method already proposes the solution:

            // May want to update the above routine, which arbitrarily selects the monitor that
            // happens to come first in the for() loop. We should probably do a little extra work,
            // and select the monitor that is closest to the mouse position.
patricknelson commented 2 years ago

Unfortunately I can't seem to reproduce this with the 3 monitors that I have (2 external, 1 laptop). Are you able to reproduce with only 3 or does this require 4 monitors in order for the bug to appear? This is the arrangement I tried.

image

If you happen to have the coding ability to attempt a fix and issue a PR, I can try to compile and review it for you. As long as I can find a way to reproduce it. I'm not much of a C# dev myself (I only dabble), I just happen to be really proactive here since I also use this tool daily.

patricknelson commented 2 years ago

@GrantMoyer is this something you can repro with your setup?

Robin-S commented 2 years ago

Yes, I am able to reproduce with 3 monitors as well. Although the issue doesn't appear on every jump, maybe 30%-50% of the cursor jumps are to the wrong screen.

I'll have a go at running the program in debug mode over the weekend. And if that session confirms my hunch and points to the DisplayList.ScreenInDirection method, I'll have a stab at implementing the suggestion in the comment.

patricknelson commented 2 years ago

@Robin-S I asked broadly but didn't explicitly ask for steps to reproduce, sorry.

Do you have a specific arrangement of the monitors and/or a set of steps that you found that we (or I) can walk through to reproduce this bug (at least make it more likely to reproduce)? If so, let me know since I'd like to be able to at least get it to occur prior to review and merging a fix.

Also note that at the moment that there some other v2.2 milestones which are still apparently outstanding (partially my fault, largely just documentation) that should probably be addressed before we can actually push out the release that could contain this fix.

Robin-S commented 2 years ago

I did a little bit more testing to hopefully find something more specific, currently using 3 external monitors on my PC graphics card.

I found that I'm *not* able to reproduce the bug with this arrangement: afbeelding

I am moving the cursor along the very top edge of the screens. In doing so, I'm not only moving my mouse (the physical device) left and right, but also very slightly upwards - to keep the cursor at the top edge.

Interestingly, when I rearrange my displays like below, the bug *does* sometimes occur: afbeelding

And in fact, when I exaggerate that upwards movement of the mouse and hit Screen3 in the corner (something like a 6x6 px area), the cursor seems to jump to the wrong location much more consistently. afbeelding

Is that something you could try?

Robin-S commented 2 years ago

Trying it without the 'unstick' option now (so only jump enabled). My cursor is now jumping to the wrong location 100% of the time when I try to move it beyond the top-left corner of Screen3 in the last arrangement. afbeelding

GrantMoyer commented 2 years ago

I haven't reproduced this, but looking at the code you pointed out, it doesn't handle your case well.

The current algorithm is roughly:

  1. For each monitor in the same order the OS numbers them
    1. If the cursor moved off the current monitor horizontally (including if it also moved vertically, i.e. diagonally), and the monitor's edge lines up exactly with the current monitor, jump to that monitor
    2. if the cursor moved of the current monitor vertically, and the monitor's edge lines up exactly with the current monitor, jump to that monitor

This explains why you can only reproduce the issue when the erroneously jumped to monitor has a lower index than the more intuitive monitor to jump to.

A better algorithm might be:

  1. Filter the list of all monitors to just those in the direction the cursor left the current monitor.
  2. Jump to the monitor in the filtered list which is closest to where the cursor left the current monitor.