MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / Eval

Method Eval

source/script.cpp:10659–10720  ·  view source on GitHub ↗

Evaluate an #HotIf expression or callback function. This is called by MainWindowProc when it receives an AHK_HOT_IF_EVAL message.

Source from the content-addressed store, hash-verified

10657// Evaluate an #HotIf expression or callback function.
10658// This is called by MainWindowProc when it receives an AHK_HOT_IF_EVAL message.
10659ResultType HotkeyCriterion::Eval(LPTSTR aHotkeyName)
10660{
10661 // Initialize a new quasi-thread to evaluate the expression. This may not be necessary for simple
10662 // expressions, but expressions which call user-defined functions may otherwise interfere with
10663 // whatever quasi-thread is running when the hook thread requests that this expression be evaluated.
10664
10665 // Based on parts of MsgMonitor(). See there for comments.
10666
10667 if (g_nThreads >= g_MaxThreadsTotal)
10668 return CONDITION_FALSE;
10669
10670 bool prev_defer_messages = g_DeferMessagesForUnderlyingPump;
10671 // Force the use of PeekMessage() within MsgSleep() since GetMessage() is known to stall while
10672 // the system is waiting for our keyboard hook to return (last confirmed on Windows 10.0.18356).
10673 // This might relate to WM_TIMER being lower priority than the input hardware processing
10674 // performed by GetMessage(). MsgSleep() relies on WM_TIMER acting as a timeout for GetMessage().
10675 g_DeferMessagesForUnderlyingPump = true;
10676
10677 // See MsgSleep() for comments about the following section.
10678 // Critical seems to improve reliability, either because the thread completes faster (i.e. before the timeout) or because we check for messages less often.
10679 InitNewThread(0, false, true, true);
10680 ResultType result;
10681
10682 // Let HotIf default to the criterion currently being evaluated, in case Hotkey() is called.
10683 g->HotCriterion = this;
10684
10685 // Update A_ThisHotkey, useful if #HotIf calls a function to do its dirty work.
10686 LPTSTR prior_hotkey_name[] = { g_script.mThisHotkeyName, g_script.mPriorHotkeyName };
10687 DWORD prior_hotkey_time[] = { g_script.mThisHotkeyStartTime, g_script.mPriorHotkeyStartTime };
10688 g_script.mPriorHotkeyName = g_script.mThisHotkeyName; // For consistency
10689 g_script.mPriorHotkeyStartTime = g_script.mThisHotkeyStartTime; //
10690 g_script.mThisHotkeyName = aHotkeyName;
10691 g_script.mThisHotkeyStartTime = // Updated for consistency.
10692 g_script.mLastPeekTime = GetTickCount();
10693
10694 // CALL THE CALLBACK
10695 ExprTokenType param = aHotkeyName;
10696 __int64 retval;
10697 result = IObjectPtr(Callback)->ExecuteInNewThread(_T("#HotIf"), &param, 1, &retval);
10698 if (result != FAIL)
10699 result = retval ? CONDITION_TRUE : CONDITION_FALSE;
10700
10701
10702 // The following allows the expression to set the Last Found Window for the
10703 // hotkey function.
10704 // There may be some rare cases where the wrong hotkey gets this HWND (perhaps
10705 // if there are multiple hotkey messages in the queue), but there doesn't seem
10706 // to be any easy way around that.
10707 g_HotExprLFW = g->hWndLastUsed; // Even if above failed, for simplicity.
10708
10709 // A_ThisHotkey must be restored else A_PriorHotkey will get an incorrect value later.
10710 g_script.mThisHotkeyName = prior_hotkey_name[0];
10711 g_script.mThisHotkeyStartTime = prior_hotkey_time[0];
10712 g_script.mPriorHotkeyName = prior_hotkey_name[1];
10713 g_script.mPriorHotkeyStartTime = prior_hotkey_time[1];
10714
10715 ResumeUnderlyingThread();
10716

Callers 1

MainWindowProcFunction · 0.80

Calls 4

InitNewThreadFunction · 0.85
IObjectPtrClass · 0.85
ResumeUnderlyingThreadFunction · 0.85
ExecuteInNewThreadMethod · 0.80

Tested by

no test coverage detected