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

Function ToggleKeyState

source/keyboard_mouse.cpp:2991–3042  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2989
2990
2991ToggleValueType ToggleKeyState(vk_type aVK, ToggleValueType aToggleValue)
2992// Toggle the given aVK into another state. For performance, it is the caller's responsibility to
2993// ensure that aVK is a toggleable key such as capslock, numlock, insert, or scrolllock.
2994// Returns the state the key was in before it was changed.
2995{
2996 // Can't use IsKeyDownAsync/GetAsyncKeyState() because it doesn't have this info:
2997 ToggleValueType starting_state = IsKeyToggledOn(aVK) ? TOGGLED_ON : TOGGLED_OFF;
2998 if (aToggleValue != TOGGLED_ON && aToggleValue != TOGGLED_OFF) // Shouldn't be called this way.
2999 return starting_state;
3000 if (starting_state == aToggleValue) // It's already in the desired state, so just return the state.
3001 return starting_state;
3002 //if (aVK == VK_NUMLOCK) // v1.1.22.05: This also applies to CapsLock and ScrollLock.
3003 {
3004 // If the key is being held down, sending a KEYDOWNANDUP won't change its toggle
3005 // state unless the key is "released" first. This has been confirmed for NumLock,
3006 // CapsLock and ScrollLock on Windows 2000 (in a VM) and Windows 10.
3007 // Examples where problems previously occurred:
3008 // ~CapsLock & x::Send abc ; Produced "ABC"
3009 // ~CapsLock::Send abc ; Alternated between "abc" and "ABC", even without {Blind}
3010 // ~ScrollLock::SetScrollLockState Off ; Failed to change state
3011 // The behaviour can still be observed by sending the keystrokes manually:
3012 // ~NumLock::Send {NumLock} ; No effect
3013 // ~NumLock::Send {NumLock up}{NumLock} ; OK
3014 // OLD COMMENTS:
3015 // Sending an extra up-event first seems to prevent the problem where the Numlock
3016 // key's indicator light doesn't change to reflect its true state (and maybe its
3017 // true state doesn't change either). This problem tends to happen when the key
3018 // is pressed while the hook is forcing it to be either ON or OFF (or it suppresses
3019 // it because it's a hotkey). Needs more testing on diff. keyboards & OSes:
3020 if (IsKeyDown(aVK))
3021 KeyEvent(KEYUP, aVK);
3022 }
3023 // Since it's not already in the desired state, toggle it:
3024 KeyEvent(KEYDOWNANDUP, aVK);
3025 // Fix for v1.0.40: IsKeyToggledOn()'s call to GetKeyState() relies on our thread having
3026 // processed messages. Confirmed necessary 100% of the time if our thread owns the active window.
3027 // v1.0.43: Extended the above fix to include all toggleable keys (not just Capslock) and to apply
3028 // to both directions (ON and OFF) since it seems likely to be needed for them all.
3029 bool our_thread_is_foreground;
3030 if (our_thread_is_foreground = (GetWindowThreadProcessId(GetForegroundWindow(), NULL) == g_MainThreadID)) // GetWindowThreadProcessId() tolerates a NULL hwnd.
3031 SLEEP_WITHOUT_INTERRUPTION(-1);
3032 if (aVK == VK_CAPITAL && aToggleValue == TOGGLED_OFF && IsKeyToggledOn(aVK))
3033 {
3034 // Fix for v1.0.36.06: Since it's Capslock and it didn't turn off as attempted, it's probably because
3035 // the OS is configured to turn Capslock off only in response to pressing the SHIFT key (via Ctrl Panel's
3036 // Regional settings). So send shift to do it instead:
3037 KeyEvent(KEYDOWNANDUP, VK_SHIFT);
3038 if (our_thread_is_foreground) // v1.0.43: Added to try to achieve 100% reliability in all situations.
3039 SLEEP_WITHOUT_INTERRUPTION(-1); // Check msg queue to put SHIFT's turning off of Capslock into effect from our thread's POV.
3040 }
3041 return starting_state;
3042}
3043
3044
3045/*

Callers 2

SendKeysFunction · 0.85
SetToggleStateMethod · 0.85

Calls 1

KeyEventFunction · 0.85

Tested by

no test coverage detected