Fix the race condition when clicking fast on auto forward

This commit is contained in:
2026-01-02 18:10:56 +01:00
parent 3e72309de4
commit 31cf11cdd5

View File

@@ -44,6 +44,9 @@
AutoForwardToggleMode := Map() ; Map of group index => toggle mode setting
AutoForwardProcessedWindow := 0 ; Track which window hwnd already got its input processed
AutoForwardToggleVKCodes := [] ; Array of VK codes for toggle hotkeys
AutoForwardTimer := 0 ; Timer reference for TriggerAutoForward
AutoForwardRunning := false ; Flag to prevent re-entrancy
AutoForwardTimerPending := false ; Flag to prevent multiple timers from being scheduled
__New() {
@@ -398,7 +401,11 @@
; Enable and mark current window as first visited
This.AutoForwardEnabled[groupIdx] := true
This.AutoForwardVisited[groupIdx] := []
This.AutoForwardProcessedWindow := 0 ; Reset so current window can receive input
try {
currentHwnd := WinGetID("A")
This.AutoForwardProcessedWindow := currentHwnd
}
This.AutoForwardTimerPending := false ; Reset timer pending flag
try {
ActiveTitle := This.CleanTitle(WinGetTitle("A"))
This.AutoForwardVisited[groupIdx].Push(ActiveTitle)
@@ -418,19 +425,19 @@
LowLevelMouseProc(nCode, wParam, lParam) {
static WM_LBUTTONUP := 0x202, WM_RBUTTONUP := 0x205, WM_MBUTTONUP := 0x208
; Use mouse UP so the click registers in the window first
if (nCode >= 0 && (wParam = WM_LBUTTONUP || wParam = WM_RBUTTONUP || wParam = WM_MBUTTONUP)) {
if (This.IsAutoForwardActive()) {
try {
currentWindow := WinGetID("A")
; Only process if this window hasn't been processed yet
if (currentWindow != This.AutoForwardProcessedWindow) {
This.AutoForwardProcessedWindow := currentWindow
; Must defer out of hook context
SetTimer(ObjBindMethod(This, "TriggerAutoForward"), -1)
}
}
}
if (nCode < 0 || (wParam != WM_LBUTTONUP && wParam != WM_RBUTTONUP && wParam != WM_MBUTTONUP))
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
if (!This.IsAutoForwardActive())
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
try {
if (This.AutoForwardRunning || This.AutoForwardTimerPending)
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
This.AutoForwardTimerPending := true
This.AutoForwardTimer := ObjBindMethod(This, "TriggerAutoForward")
SetTimer(This.AutoForwardTimer, -1)
}
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
}
@@ -456,16 +463,16 @@
}
}
if (This.IsAutoForwardActive()) {
try {
currentWindow := WinGetID("A")
; Only process if this window hasn't been processed yet
if (currentWindow != This.AutoForwardProcessedWindow) {
This.AutoForwardProcessedWindow := currentWindow
; Must defer out of hook context - SetTimer -1 runs immediately after hook returns
SetTimer(ObjBindMethod(This, "TriggerAutoForward"), -1)
}
}
if (!This.IsAutoForwardActive())
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
try {
if (This.AutoForwardRunning || This.AutoForwardTimerPending)
return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
This.AutoForwardTimerPending := true
This.AutoForwardTimer := ObjBindMethod(This, "TriggerAutoForward")
SetTimer(This.AutoForwardTimer, -1)
}
}
; Always pass to next hook
@@ -490,52 +497,66 @@
; Check if current window should auto-forward and trigger it
TriggerAutoForward() {
if (This.AutoForwardRunning)
return
This.AutoForwardRunning := true
This.AutoForwardTimerPending := false
This.AutoForwardTimer := 0
try {
ActiveTitle := This.CleanTitle(WinGetTitle("A"))
for groupIdx, Arr in This.AutoForwardGroups {
if (!This.AutoForwardEnabled[groupIdx])
if (!This.AutoForwardEnabled[groupIdx] || !This.OnWinActive(Arr))
continue
if (This.OnWinActive(Arr)) {
for index, name in Arr {
if (name = ActiveTitle) {
This.Cycle_Hotkey_Groups(Arr, "ForwardsHotkey")
; Update processed window to the NEW window after cycling
try This.AutoForwardProcessedWindow := WinGetID("A")
; Track visited window
try {
newTitle := This.CleanTitle(WinGetTitle("A"))
alreadyVisited := false
for visited in This.AutoForwardVisited[groupIdx] {
if (visited = newTitle) {
alreadyVisited := true
break
}
}
if (!alreadyVisited) {
This.AutoForwardVisited[groupIdx].Push(newTitle)
}
; If not toggle mode, check if all windows visited
if (!This.AutoForwardToggleMode[groupIdx]) {
existingCount := 0
for n in Arr {
if (WinExist("EVE - " n " Ahk_Exe exefile.exe"))
existingCount++
}
if (This.AutoForwardVisited[groupIdx].Length >= existingCount) {
This.AutoForwardEnabled[groupIdx] := false
This.AutoForwardVisited[groupIdx] := []
}
}
for index, name in Arr {
if (name != ActiveTitle)
continue
This.Cycle_Hotkey_Groups(Arr, "ForwardsHotkey")
try {
newWindow := WinGetID("A")
This.AutoForwardProcessedWindow := newWindow
} catch {
This.AutoForwardRunning := false
return
}
try {
newTitle := This.CleanTitle(WinGetTitle("A"))
alreadyVisited := false
for visited in This.AutoForwardVisited[groupIdx] {
if (visited = newTitle) {
alreadyVisited := true
break
}
return
}
if (!alreadyVisited)
This.AutoForwardVisited[groupIdx].Push(newTitle)
}
if (!This.AutoForwardToggleMode[groupIdx]) {
existingCount := 0
for n in Arr {
if (WinExist("EVE - " n " Ahk_Exe exefile.exe"))
existingCount++
}
if (This.AutoForwardVisited[groupIdx].Length >= existingCount) {
This.AutoForwardEnabled[groupIdx] := false
This.AutoForwardVisited[groupIdx] := []
}
}
This.AutoForwardRunning := false
return
}
}
}
finally {
This.AutoForwardRunning := false
}
}
; The method to make it possible to cycle throw the EVE Windows. Used with the Hotkey Groups