Dealing with Display Scaling

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Sticky
Posts: 10
Joined: 12 Apr 2017, 22:08

Dealing with Display Scaling

21 Jun 2019, 19:28

Right now I am tweaking some "scroll using trackball" code, but this problem is generic, has occured in many other places.

I frequently use multiple displays with quite different sizes, pixel counts, and display scalings. For example, I am typing this with my Surface Book laptop plugged in to 3 external monitos (1 display port, 2 USB). The laptop is set to 200% scaling, my 30" display port monitor is set to 150% scaling, my 2 other monitors are set to 100% scaling/

The basic problem is that, while I would like/expect that
CoordMode,mouse,Screen ; relative to entire desktop
MouseGetPos->pos
MoveMouse<-pos
MouseGetPos->pos2
would give me pos == pos2,

in actuality it only does so reliably when all displays have the same 100% scaling. (I assume it also works when all have the same non-100% scaling, but I have not tried that.)

When I have non-uniform scaling, it appears that MouseFGetPos is using 100% scaling, but MouseSetPos is using 200% scaling - possibly the largest scaling used, or that of the primary monitor, or ...

E.g. for the simple code below that actually determines the MouseMove absolute coordinates needed to match a givwen MouseGetPos, example coordinates are

Monitor 4: MouseGetPos (-1174,-370) MouseSetPos (-587,-185) (2x, obviously)
Monitor 2: MouseGetPos (1253,-1753) MouseSetPos (940,-515)
Monitor 1: MouseGetPos == MouseSetPos (933,382)
Monitor 3: MouseGetPost (5644,352) MouseSetPos (2822,176) (again 2x)

You can probably figure out many of the monitor properties from the above. Even more if I provided two sample points per monitor: scaling, monitor UL coordinates and sizes in the entire desktop, etc.



The simple code below determines the MouseMove absolute coordinates needed to match a given MouseGetPos, but

a) it is very slow (which I can fix using standard techniques like gradient descent, with larger step sizes)

b) neither the simple code below which always uses unit steps +/- 1, nor a real gradient descent code, is guaranteed to work. I think that it is possible to construct monitor configuration s where my heuristics for determining which direction to move are invalid. Worse, in reality the function that we are trying to find the fixed point of has large regions that are perfectly flat - it seems that if the MouseMove coordinates map to a region completely outside a monitor, MouseGetPOs is pegged to point on a monitors boundary. I.e. the function is not differentiable.

c) as the mouse cursor moves, it can interfedre with other AHK scripts. E.g. I have an AHK script that looks at mouse position and jumps it across gaps in the display layout that occur because of monitor heterogeneity.



I could fix this by enumerating all monitors, determining which the original MouseGetPos is in, and which the MouseMove-MouseGetPos is in afterwards - and I will do so. But the code is getting complex, so I really want to ask this forum if there is a better way, or if somebody has already done it. Plus, IMHO it is worth reporting this behavior as a bug in AHK's handling of heterogenous monitors. IMHO MouseGetPos;MouseMove;MouseGetPos should always return the same MouseGetPos values.

Q1: is there some setting (other than uniform display scaling) so that
CoordMode,mouse,Screen ; relative to entire desktop
MouseGetPos->pos
MoveMouse<-pos
MouseGetPos->pos2
would give me pos == pos2,

i.e. a setting in AHK?

Q2: has anyone already worked out code for something like my Kluge_MouseGetPos below, that will work in all (or at least most reasonable) conditions?

Q3: what are the AHK callable DLLcalls that avoid these scaling issues?

However, if I do that, I might as well use a non-AHK approach for the problem at hand - something like MarbleScroll. That woukld also be a lot more power efficient - instead of a timer polling function, would just hook to the events that are produced when my mouse or trackball are actually moved.





Here's the example code that converges on the MouseGetPos/MouseMOve coordinates.

Code: Select all

Kluge_MouseGetPos()
{
	;; AHK bug: multimonitor systems with different scalings in different monitors
	;; seem to not handle display scaling

	;; Kluge_MouseGetPos - since
	;;     MouseGetPos->pos
	;;     MoveMouse<-pos
	;;     MouseGetPos->pos2
	;; does not result in pos2 == pos1,
	;; I am trying to find posAdj such that
	;;
	;;     MouseGetPos->pos
	;;     posAdj <- f(pos)
	;;     MoveMouse<-posAdj
	;;     MouseGetPos->pos2
	;;
	;; does result in pos2 == pos1,

	;; i.e. I am trying to correct for AHK's broken handling of multiple monitors with different scaling

	CoordMode,tooltip,Screen ; relative to entire desktop
	CoordMode,mouse,Screen ; relative to entire desktop
	MouseGetPos, ox, oy
	ToolTip, Start %ox% %oy%,,,18

	max_tries := 10000
	try_num := 0
	ox_try := ox
	oy_try := oy

	MouseMove (ox_try), (oy_try),0
	MouseGetPos, ox_got, oy_got

	Loop{
		try_num += 1
		MouseMove (ox_try), (oy_try),0
		MouseGetPos, ox_got, oy_got
		ToolTip, Try #%try_num% o: %ox% %oy%  o_try:%ox_try% %oy_try%  o_got: %ox_got% %oy_got%,0,0, 19
		;; TBD: create something that converges faster
		if( ox_got > ox ) {
			ox_try := ox_try - 1
		}
		if( ox_got < ox ) {
			ox_try := ox_try +1
		}
		if( oy_got > oy ) {
			oy_try := oy_try - 1
		}
		if( oy_got < oy ) {
			oy_try := oy_try +1
		}
	} Until ( (try_num >= max_tries) || ((ox_got == ox) && (oy_got == oy)) )
	return {x:(ox_try),y:(oy_try)}
}
Last edited by Sticky on 06 Jul 2022, 19:03, edited 1 time in total.
just me
Posts: 9495
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Dealing with Display Scaling

22 Jun 2019, 04:43

MouseMove -> Remarks
The following is an alternate way to move the mouse cursor that may work better in certain multi-monitor configurations:

Code: Select all

DllCall("SetCursorPos", "int", 100, "int", 400)  ; The first number is the X-coordinate and the second is the Y (relative to the screen).
?
Sticky
Posts: 10
Joined: 12 Apr 2017, 22:08

Re: Dealing with Display Scaling

18 Jun 2022, 02:31

BTW, I should have responded long ago:

No, the DllCall SetCursorPos does *not* cure the problem reliably.

I swear that sometimes it does... I had given up on both MouseMove and the SetCursorPos DllCall for most of the interval between my initial post and last week. Tried using SetCursorPos - it seemed to work - but then stopped.

Hasn't worked since a Windows update, but was working and then failed just before the update. I.e. the thing that makes it work or not... well, is probably related to my multidisplay settings, which change a lot - laptop connected to different multidisplay setups at two different places, plus I occasionally change on the fly according to whether I am sitting on a chair or walking on a treadmill, and according to eye fatigue.

I've basically been avoiding MouseMove type scripts, like "Jump mouse to the center of the next/previous monitor".

But I really want such scripts (to reduce computeritis/RMS by using speech commands to move the mouse around, rather than mouse/trackball.)

I am reviving the gradient descent approach, and will try storing the parameters in a file. I hope that the parameters stay the same even so long as the display config doesn't change, and/or that I can jump between two or three configurations by reloaded their saved configs, rather than by having to recalibrate the gradient descent.

I've started by manually selecting the UL and LR corners of my 4 displays.

But I think that I can automate completely by moving a window onto the displays one by one (or nearly), maximizing the window, searching for the edges of the window (which are the edges of the current display) (by activating the window under the mouse), etc.

Happily, at least setting window size and position works reliably on my multidisplay system with heterogenous display scaling. It is only MouseMove (and DllCall SetCursorPos) that is broken.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: mihai369 and 133 guests