| 3056 | |
| 3057 | |
| 3058 | void 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 |
no test coverage detected