/// <summary> /// This maps letters which are pressed to a KeyInput value by looking at the virtual /// key vs the textual input. When Visual Studio is processing key mappings it's doing /// so in PreTraslateMessage and using the virtual key codes. We need to simulate this /// as best as possible when forwarding keys /// </summary> private bool TryConvertLetterToKeyInput(KeyEventArgs keyEventArgs, out KeyInput keyInput) { keyInput = KeyInput.DefaultValue; var keyboardDevice = keyEventArgs.Device as KeyboardDevice; var keyModifiers = keyboardDevice != null ? _keyUtil.GetKeyModifiers(keyboardDevice.Modifiers) : VimKeyModifiers.Alt; if (keyModifiers == VimKeyModifiers.None) { return(false); } var key = keyEventArgs.Key; if (key < Key.A || key > Key.Z) { return(false); } var c = (char)('a' + (key - Key.A)); keyInput = KeyInputUtil.ApplyKeyModifiersToChar(c, keyModifiers); return(true); }
/// <summary> /// Try and convert the Visual Studio command to it's equivalent KeyInput /// </summary> internal bool TryConvert(Guid commandGroup, uint commandId, IntPtr variantIn, out EditCommand editCommand) { editCommand = null; // Don't ever process a command when we are in an automation function. Doing so will cause VsVim to // intercept items like running Macros and certain wizard functionality if (_vsAdapter.InAutomationFunction) { return(false); } // Don't intercept commands while incremental search is active. Don't want to interfere with it if (_vsAdapter.IsIncrementalSearchActive(_vimBuffer.TextView)) { return(false); } var modifiers = _keyUtil.GetKeyModifiers(_vsAdapter.KeyboardDevice.Modifiers); if (!OleCommandUtil.TryConvert(commandGroup, commandId, variantIn, modifiers, out editCommand)) { return(false); } // Don't process Visual Studio commands. If the key sequence is mapped to a Visual Studio command // then that command wins. if (editCommand.EditCommandKind == EditCommandKind.VisualStudioCommand) { return(false); } return(true); }
/// <summary> /// Last chance at custom handling of user input. At this point we have the /// advantage that WPF has properly converted the user input into a char which /// can be effeciently mapped to a KeyInput value. /// </summary> public override void TextInput(TextCompositionEventArgs args) { VimTrace.TraceInfo("VimKeyProcessor::TextInput Text={0} ControlText={1} SystemText={2}", StringUtil.GetDisplayString(args.Text), StringUtil.GetDisplayString(args.ControlText), StringUtil.GetDisplayString(args.SystemText)); var handled = false; var text = args.Text; if (string.IsNullOrEmpty(text)) { text = args.ControlText; } if (!string.IsNullOrEmpty(text)) { // In the case of a failed dead key mapping (pressing the accent key twice for // example) we will recieve a multi-length string here. One character for every // one of the mappings. Make sure to handle each of them for (var i = 0; i < text.Length; i++) { var keyInput = KeyInputUtil.CharToKeyInput(text[i]); handled = TryProcess(keyInput); } } else if (!string.IsNullOrEmpty(args.SystemText)) { // The system text needs to be processed differently than normal text. When 'a' // is pressed with control it will come in as control text as the proper control // character. When 'a' is pressed with Alt it will come in as simply 'a' and we // have to rely on the currently pressed key modifiers to determine the appropriate // character var keyboardDevice = args.Device as KeyboardDevice; var keyModifiers = keyboardDevice != null ? _keyUtil.GetKeyModifiers(keyboardDevice.Modifiers) : VimKeyModifiers.Alt; text = args.SystemText; for (var i = 0; i < text.Length; i++) { var keyInput = KeyInputUtil.ApplyKeyModifiers(KeyInputUtil.CharToKeyInput(text[i]), keyModifiers); handled = TryProcess(keyInput); } } VimTrace.TraceInfo("VimKeyProcessor::TextInput Handled={0}", handled); args.Handled = handled; base.TextInput(args); }