From 31cf11cdd5e925e260cbb174d8c2fc6e6a5f31cd Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Fri, 2 Jan 2026 18:10:56 +0100 Subject: [PATCH] Fix the race condition when clicking fast on auto forward --- src/Main_Class.ahk | 141 ++++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 60 deletions(-) diff --git a/src/Main_Class.ahk b/src/Main_Class.ahk index 2db165b..8837e6e 100644 --- a/src/Main_Class.ahk +++ b/src/Main_Class.ahk @@ -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