Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3016 from VsVim/dev/nosami/fix-3015
Handle alternative keyboard layouts a little better.
- Loading branch information
Showing
5 changed files
with
173 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using AppKit; | ||
using Microsoft.VisualStudio.Text.Editor; | ||
|
||
namespace Vim.UI.Cocoa | ||
{ | ||
internal sealed class DeadCharHandler | ||
{ | ||
private bool _lastEventWasDeadChar; | ||
private bool _processingDeadChar; | ||
private string _convertedDeadCharacters; | ||
private readonly ITextView _textView; | ||
private InvisibleTextView _invisibleTextView; | ||
|
||
public DeadCharHandler(ITextView textView) | ||
{ | ||
_textView = textView; | ||
} | ||
|
||
public string ConvertedDeadCharacters => _convertedDeadCharacters; | ||
|
||
internal void SetConvertedDeadCharacters(string value) | ||
{ | ||
_convertedDeadCharacters = value; | ||
} | ||
|
||
public bool LastEventWasDeadChar => _lastEventWasDeadChar; | ||
public bool ProcessingDeadChar => _processingDeadChar; | ||
|
||
public void InterpretEvent(NSEvent keyPress) | ||
{ | ||
if (_convertedDeadCharacters != null) | ||
{ | ||
// reset state | ||
_convertedDeadCharacters = null; | ||
_processingDeadChar = false; | ||
} | ||
|
||
_lastEventWasDeadChar = _processingDeadChar; | ||
|
||
_processingDeadChar = KeyEventIsDeadChar(keyPress); | ||
|
||
if (!_processingDeadChar && !_lastEventWasDeadChar) | ||
{ | ||
return; | ||
} | ||
|
||
_invisibleTextView ??= new InvisibleTextView(this, _textView); | ||
// Send the cloned key press to the invisible NSTextView | ||
_invisibleTextView.InterpretEvent(keyPress); | ||
} | ||
|
||
private bool KeyEventIsDeadChar(NSEvent e) | ||
{ | ||
return string.IsNullOrEmpty(e.Characters); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using AppKit; | ||
using Foundation; | ||
using Microsoft.VisualStudio.Text; | ||
using Microsoft.VisualStudio.Text.Editor; | ||
|
||
namespace Vim.UI.Cocoa | ||
{ | ||
/// <summary> | ||
/// An invisible NSTextView used so we can leverage macOS to handle | ||
/// the conversion of keycodes and dead key presses into characters for | ||
/// any keyboard layout. | ||
/// </summary> | ||
internal sealed class InvisibleTextView : NSTextView | ||
{ | ||
private readonly DeadCharHandler _deadCharHandler; | ||
private readonly ITextBuffer _textBuffer; | ||
|
||
public InvisibleTextView(DeadCharHandler deadCharHandler, ITextView textView) | ||
{ | ||
_deadCharHandler = deadCharHandler; | ||
_textBuffer = textView.TextBuffer; | ||
textView.TextBuffer.Changing += TextBuffer_Changing; | ||
textView.Closed += TextView_Closed; | ||
} | ||
|
||
public void InterpretEvent(NSEvent keypress) | ||
{ | ||
InterpretKeyEvents(new[] { CloneEvent(keypress) }); | ||
} | ||
|
||
public override void InsertText(NSObject text, NSRange replacementRange) | ||
{ | ||
if (_deadCharHandler.LastEventWasDeadChar && !_deadCharHandler.ProcessingDeadChar) | ||
{ | ||
// This is where we find out how the combination of keypresses | ||
// has been interpreted. | ||
_deadCharHandler.SetConvertedDeadCharacters((text as NSString)?.ToString()); | ||
} | ||
} | ||
|
||
private void TextBuffer_Changing(object sender, TextContentChangingEventArgs e) | ||
{ | ||
if (_deadCharHandler.LastEventWasDeadChar || _deadCharHandler.ProcessingDeadChar) | ||
{ | ||
// We need the dead key press event to register in the editor so | ||
// that we get the correct subsequent keypress events, but we | ||
// don't want to modify the textbuffer contents. | ||
e.Cancel(); | ||
} | ||
} | ||
|
||
private void TextView_Closed(object sender, System.EventArgs e) | ||
{ | ||
_textBuffer.Changing -= TextBuffer_Changing; | ||
} | ||
|
||
private NSEvent CloneEvent(NSEvent keyPress) | ||
{ | ||
return NSEvent.KeyEvent( | ||
keyPress.Type, | ||
keyPress.LocationInWindow, | ||
keyPress.ModifierFlags, | ||
keyPress.Timestamp, | ||
keyPress.WindowNumber, | ||
keyPress.Context, | ||
keyPress.Characters, | ||
keyPress.CharactersIgnoringModifiers, | ||
keyPress.IsARepeat, | ||
keyPress.KeyCode); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters