CoordMode needs a pause to update

Report problems with documented functionality
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

CoordMode needs a pause to update

17 Oct 2017, 15:30

I was testing some code relating to CoordMode: client/screen/window, and noticed that A_CaretX and A_CaretY were not updating unless I added a pause after using the CoordMode command.

Perhaps this is similar in nature to an issue where DetectHiddenWindows did not update immediately.

DetectHiddenWindows bug? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 14&t=30010

Code: Select all

q:: ;CoordMode needs a pause to update
WinGet, hWnd, ID, A
vOutput := ""
vSleep := 0 ;incorrect: all results will be the same
;vSleep := 1 ;correct: results will vary
vList := "Client,Screen,Window"
Loop, Parse, vList, % ","
{
	CoordMode, Caret, % A_LoopField
	Sleep, % vSleep
	vOutput .= (A_Index=1?"":"`r`n") A_CaretX " " A_CaretY
}
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: CoordMode needs a pause to update

17 Oct 2017, 16:32

It has nothing to do with DetectHiddenWindows. AHK records a static timestamp and doesn't update unless the previous call to the function (BIV_Caret) was made more than 5 ms ago. Comment says,

Code: Select all

// These static variables are used to keep the X and Y coordinates in sync with each other, as a snapshot
// of where the caret was at one precise instant in time.  This is because the X and Y vars are resolved
// separately by the script, and due to split second timing, they might otherwise not be accurate with
// respect to each other.  This method also helps performance since it avoids unnecessary calls to
// GetGUIThreadInfo().
It seems easy to fix by also storing the caret coord mode as a static variable, I will not bother submitting the fix, instead I think it would be nicer to have something like CaretGetPos(OutputVarX, OutputVarY), for v2 that is.

Cheers
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: CoordMode needs a pause to update

17 Oct 2017, 17:36

Thank you Helgef. But then does that mean that Sleep, 5, as a workaround, will definitely always work?

I found the following information:

GetTickCount function (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.
Sleep function (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time.

Code: Select all

q:: ;get min/max supported resolutions (in milliseconds)
VarSetCapacity(TIMECAPS, 8, 0)
DllCall("winmm\timeGetDevCaps", Ptr,&TIMECAPS, UInt,8)
vMin := NumGet(&TIMECAPS, 0, "UInt") ;wPeriodMin
vMax := NumGet(&TIMECAPS, 0, "UInt") ;wPeriodMax
MsgBox, % vMin " " vMax ;1 1
return
==================================================

[EDIT:] Well, if you're desperate, you can create that function now:
convert coordinates between Client/Screen/Window modes - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=38472

Hmm, yes, your suggested function would be more reliable and avoid needing a 5-millisecond workaround or equivalent. The issue is reminiscent of A_Now and A_MSec, that I talk about in my documentation extension tutorial.

jeeswg's documentation extension tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=33596
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: CoordMode needs a pause to update

18 Oct 2017, 13:19

does that mean that Sleep, 5, as a workaround, will definitely always work?
The condition to update was if more than 5 (> 5) ms had elapsed. So you need to sleep at least 6 ms, and add one times the resolution of the clock. Consider this test script,

Code: Select all

tr:=getTimerResolution()
n := 6+tr
loop {
	t1:=QPC()
	dllcall("Sleep","uint", n)
	;Sleep n
	t2:=QPC()
	if t2-t1 < 6	;  Fail
		msgbox t2-t1 "`n" A_Index 
}
getTimerResolution() {
	DllCall("ntdll.dll\NtQueryTimerResolution", "UPtr*", MinimumResolution, "UPtr*", MaximumResolution, "UPtr*", CurrentResolution)
	return CurrentResolution/10000 ; Resolutions are reported as 100-nanoseconds
}
;-------------------------------------------------------------------------------
QPC() { ; microseconds precision, borrowed from wolf_II
;-------------------------------------------------------------------------------
    static Freq, init := DllCall("QueryPerformanceFrequency", "Int64P", Freq)

    DllCall("QueryPerformanceCounter", "Int64P", Count)
    Return (Count / Freq)*1000
}
Result with the ahk sleep,

Code: Select all

5.99718266725540161
1009
I got no fail with the dllcall sleep. (Limited testing ofc.)
Note that 5.9 is more than 5 ( :shh: ), but getTickCount() which is used by BIV_Caret, reports in integers, so 5.9 might be truncated to 5, which is not more than 5 :crazy:
Additional note, running the test script from your first post, never seem to aquire the same coords subsequently when useing sleep 1, modified to doing it in a loop that is, try yourself.

Your functions to get the coords seems like the better option, I will take a closer look later :thumbup:

Cheers.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 26 guests