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

Function SetModifierLRState

source/keyboard_mouse.cpp:3058–3497  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3056
3057
3058void SetModifierLRState(modLR_type aModifiersLRnew, modLR_type aModifiersLRnow, HWND aTargetWindow
3059 , bool aDisguiseDownWinAlt, bool aDisguiseUpWinAlt, DWORD aExtraInfo)
3060// This function is designed to be called from only the main thread; it's probably not thread-safe.
3061// Puts modifiers into the specified state, releasing or pressing down keys as needed.
3062// The modifiers are released and pressed down in a very delicate order due to their interactions with
3063// each other and their ability to show the Start Menu, activate the menu bar, or trigger the OS's language
3064// bar hotkeys. Side-effects like these would occur if a more simple approach were used, such as releasing
3065// all modifiers that are going up prior to pushing down the ones that are going down.
3066// When the target layout has an altgr key, it is tempting to try to simplify things by removing MOD_LCONTROL
3067// from aModifiersLRnew whenever aModifiersLRnew contains MOD_RALT. However, this a careful review how that
3068// would impact various places below where sTargetLayoutHasAltGr is checked indicates that it wouldn't help.
3069// Note that by design and as documented for ControlSend, aTargetWindow is not used as the target for the
3070// various calls to KeyEvent() here. It is only used as a workaround for the GUI window issue described
3071// at the bottom.
3072{
3073 if (aModifiersLRnow == aModifiersLRnew) // They're already in the right state, so avoid doing all the checks.
3074 return; // Especially avoids the aTargetWindow check at the bottom.
3075
3076 // Notes about modifier key behavior on Windows XP (these probably apply to NT/2k also, and has also
3077 // been tested to be true on Win98): The WIN and ALT keys are the problem keys, because if either is
3078 // released without having modified something (even another modifier), the WIN key will cause the
3079 // Start Menu to appear, and the ALT key will activate the menu bar of the active window (if it has one).
3080 // For example, a hook hotkey such as "$#c::Send text" (text must start with a lowercase letter
3081 // to reproduce the issue, because otherwise WIN would be auto-disguised as a side effect of the SHIFT
3082 // keystroke) would cause the Start Menu to appear if the disguise method below weren't used.
3083 //
3084 // Here are more comments formerly in SetModifierLRStateSpecific(), which has since been eliminated
3085 // because this function is sufficient:
3086 // To prevent it from activating the menu bar, the release of the ALT key should be disguised
3087 // unless a CTRL key is currently down. This is because CTRL always seems to avoid the
3088 // activation of the menu bar (unlike SHIFT, which sometimes allows the menu to be activated,
3089 // though this is hard to reproduce on XP). Another reason not to use SHIFT is that the OS
3090 // uses LAlt+Shift as a hotkey to switch languages. Such a hotkey would be triggered if SHIFT
3091 // were pressed down to disguise the release of LALT.
3092 //
3093 // Alt-down events are also disguised whenever they won't be accompanied by a Ctrl-down.
3094 // This is necessary whenever our caller does not plan to disguise the key itself. For example,
3095 // if "!a::Send Test" is a registered hotkey, two things must be done to avoid complications:
3096 // 1) Prior to sending the word test, ALT must be released in a way that does not activate the
3097 // menu bar. This is done by sandwiching it between a CTRL-down and a CTRL-up.
3098 // 2) After the send is complete, SendKeys() will restore the ALT key to the down position if
3099 // the user is still physically holding ALT down (this is done to make the logical state of
3100 // the key match its physical state, which allows the same hotkey to be fired twice in a row
3101 // without the user having to release and press down the ALT key physically).
3102 // The #2 case above is the one handled below by ctrl_wont_be_down. It is especially necessary
3103 // when the user releases the ALT key prior to releasing the hotkey suffix, which would otherwise
3104 // cause the menu bar (if any) of the active window to be activated.
3105 //
3106 // Some of the same comments above for ALT key apply to the WIN key. More about this issue:
3107 // Although the disguise of the down-event is usually not needed, it is needed in the rare case
3108 // where the user releases the WIN or ALT key prior to releasing the hotkey's suffix.
3109 // Although the hook could be told to disguise the physical release of ALT or WIN in these
3110 // cases, it's best not to rely on the hook since it is not always installed.
3111 //
3112 // Registered WIN and ALT hotkeys that don't use the Send command work okay except ALT hotkeys,
3113 // which if the user releases ALT prior the hotkey's suffix key, cause the menu bar to be activated.
3114 // Since it is unusual for users to do this and because it is standard behavior for ALT hotkeys
3115 // registered in the OS, fixing it via the hook seems like a low priority, and perhaps isn't worth

Callers 5

DialogPrepFunction · 0.85
SendUnicodeCharFunction · 0.85
SendKeysFunction · 0.85
SendKeyFunction · 0.85
SendASCFunction · 0.85

Calls 3

KeyEventMenuMaskFunction · 0.85
KeyEventFunction · 0.85
DoKeyDelayFunction · 0.85

Tested by

no test coverage detected