Skip to content

Commit

Permalink
fix(windows/onivim#3157): Dead key fix (onivim#3166)
Browse files Browse the repository at this point in the history
__Issue:__ On Windows, pressing a dead key (like <kbd>'</kbd>) twice would not emit any output. Curiously, composing works correctly (<kbd>'</kbd> + <kbd>a</kbd> -> `á`), and a dead character + space worked correctly too.

__Defect:__ In our keyboard-layout helper, we were calling `ToUnicodeEx`, which, confusingly, is actually side-effectful - it can change the state of the keyboard, in particular dead keys: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tounicodeex#parameters

__Fix:__ There is a new flag introduced in Win10 >1607 that causes that particular API call to  not change the keyboard state. With that fix, the dead keys behave as expected.

Fixes onivim#3157
  • Loading branch information
bryphe authored Feb 20, 2021
1 parent 167ab9e commit 05ffe67
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES_CURRENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- #3146 - Vim: Fix command-line staying open when clicking the editor or file explorer (fixes #3031)
- #3161 - Configuration: Turn soft word-wrap on by default (fixes #3161)
- #3162 - Windows: Support opening UNC paths (fixes #3151)
- #3166 - Windows: Fix dead key input (fixes #3157)

### Performance

Expand Down
18 changes: 18 additions & 0 deletions manual_test/cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,24 @@ __Pass:__
- [ ] OSX
- [ ] Linux

## 7.4 Dead Keys

Regresion test for #3157

Prerequisite:
- Install ENG-INTL keyboard layout

- Switch keyboard layout to English (International)
- Run Onivim 2
- Enter dead key (') followed by space -> should type key
- Press dead key twice (") - platform dependent, should output one or two instances of the key
- Enter dead key (') followed by composing character (like a) - should get à

__Pass:__
- [ ] Win
- [ ] OSX
- [ ] Linux

# 8. Workspace

## 8.1 Open Workspace via Command Palette
Expand Down
8 changes: 7 additions & 1 deletion src/oni2-keyboard-layout/stubs/keyboard-layout-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#define SPACE_SCAN_CODE 0x0039

// Parameter to pass to ToUnicodeEx: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tounicodeex#parameters
#define DONT_CHANGE_KEYBOARD_STATE 4

#include <windows.h>
#include <stdint.h>

Expand Down Expand Up @@ -87,7 +90,10 @@ CAMLprim value oni2_KeyboardLayoutInit() {
int keyboardCharacterToUTF8(UINT keycode, UINT scancode, BYTE *keyboardState, char* dest, int destSize, HKL keyboardLayout) {
wchar_t destUtf16[UTF16_BUFFER_SIZE];

int utf16Count = ToUnicodeEx(keycode, scancode, keyboardState, destUtf16, UTF16_BUFFER_SIZE, 0, keyboardLayout);
// CAREFUL: ToUnicodeEx has the side-effect of resetting dead key state, as well as others - see:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tounicodeex#remarks
// Fix #3157, for Windows 10 >1607 by passing bit 2 to `wFlags`
int utf16Count = ToUnicodeEx(keycode, scancode, keyboardState, destUtf16, UTF16_BUFFER_SIZE, DONT_CHANGE_KEYBOARD_STATE, keyboardLayout);

if (utf16Count == -1) {
return -1;
Expand Down

0 comments on commit 05ffe67

Please sign in to comment.