Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for not providing the correct information on Ctrl-[ and CTRL-] in Windows #3696

Open
wants to merge 1 commit into
base: v0.29.x
Choose a base branch
from

Conversation

zbyna
Copy link

@zbyna zbyna commented May 14, 2024

This fixes #3621 .
I tested it in neovide OS: Windows 10 Pro 22H2, Neovide Version 0.12.2
with Czech, German and English layout:

TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        ControlLeft,
    ),
    logical_key: Named(
        Control,
    ),
    text: None,
    location: Left,
    state: Pressed,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: None,
        key_without_modifiers: Named(
            Control,
        ),
    },
}
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        BracketRight,
    ),
    logical_key: Character(
        ")",
    ),
    text: Some(
        "]",
    ),
    location: Standard,
    state: Pressed,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: Some(
            "\u{1d}",
        ),
        key_without_modifiers: Character(
            ")",
        ),
    },
}
TRACE [neovide::window::keyboard_manager] Key pressed <C-]> ModifiersState(CONTROL)
TRACE [neovide::channel_utils] UICommand Serial(Keyboard("<C-]>"))
TRACE [neovide::bridge::ui_commands] In Serial Command
TRACE [neovide::bridge::ui_commands] Keyboard Input Sent: <C-]>
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        BracketRight,
    ),
    logical_key: Character(
        ")",
    ),
    text: None,
    location: Standard,
    state: Released,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: None,
        key_without_modifiers: Character(
            ")",
        ),
    },
}
TRACE [neovide::window::keyboard_manager] Modifiers { state: ModifiersState(0x0), pressed_mods: ModifiersKeys(0x0) }
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        ControlLeft,
    ),
    logical_key: Named(
        Control,
    ),
    text: None,
    location: Left,
    state: Released,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: None,
        key_without_modifiers: Named(
            Control,
        ),
    },
}
TRACE [neovide::window::keyboard_manager] Modifiers { state: ModifiersState(CONTROL), pressed_mods: ModifiersKeys(0x0) }
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        ControlLeft,
    ),
    logical_key: Named(
        Control,
    ),
    text: None,
    location: Left,
    state: Pressed,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: None,
        key_without_modifiers: Named(
            Control,
        ),
    },
}
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        BracketLeft,
    ),
    logical_key: Character(
        "ú",
    ),
    text: Some(
        "[",
    ),
    location: Standard,
    state: Pressed,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: Some(
            "\u{1b}",
        ),
        key_without_modifiers: Character(
            "ú",
        ),
    },
}
TRACE [neovide::window::keyboard_manager] Key pressed <C-[> ModifiersState(CONTROL)
TRACE [neovide::channel_utils] UICommand Serial(Keyboard("<C-[>"))
TRACE [neovide::bridge::ui_commands] In Serial Command
TRACE [neovide::bridge::ui_commands] Keyboard Input Sent: <C-[>
TRACE [neovide::bridge::handler] Neovim notification: "redraw"
...
TRACE [neovide::window::keyboard_manager] KeyEvent {
    physical_key: Code(
        BracketLeft,
    ),
    logical_key: Character(
        "ú",
    ),
    text: None,
    location: Standard,
    state: Released,
    repeat: false,
    platform_specific: KeyEventExtra {
        text_with_all_modifers: None,
        key_without_modifiers: Character(
            "ú",
        ),
    },
}
DEBUG [neovide::renderer] zindex: 18446744073709551615, base: 0

I am new in Rust, so please be patient 🙂 Thank you for possible merge.

src/platform_impl/windows/keyboard.rs Outdated Show resolved Hide resolved
@zbyna
Copy link
Author

zbyna commented May 29, 2024

I have a feeling it is needed to describe better (possibly 🙂 ) what I try to achieve in this PR.

The goal is to force two keys with scan codes 1A and 1B to behave as control characters ^[ and ^]

DEC HEX Symbol Description Caret notaion
27 1B ESC Escape ^[
29 1D GS   Group Separator ^]

image

Now I will dive in to how windows handle keys when pressed with CTRL It is a little bit mess in my opinion that is
why I consider it to be important.

  1. All (English) alphabetic keys (from A to Z all included) get mapped to their control codes (ASCII 1 to 26) in WM_CHAR.
    That means that if you press Ctrl-M, your program will receive a nice WM_CHAR message with the 13 code, usually corresponding to the RETURN key.

  2. Further you can generate WM_CHAR with:

    • ASCII code 27, that is, ESC, can be both generated by the ESC key and by the CTRL-[ combination.
    • ASCII 28 with CTRL-\ ,
    • ASCII 29 with CTRL-],
    • ASCII 30 with CTRL-SHIFT-6 (which is more like CTRL-^), and
    • ASCII 31 with CTRL-SHIFT-hyphen (which should be read as CTRL-_).
    • ASCII 127 DEL character with CTRL-BACKSPACE
    • ASCII 10 with CTRL-Return

    I usually use a non-US keyboard, for which I can tell you that the ASCII mapping is a bit lousier than for the US mapping, the ‘[]^' symbols are moved around to other keys but Windows still performs the mapping as if the keyboard had US keytops,

    Means scan codes 1A 1B generates WM_KEYDOWN and WM_CHAR message witth ascii control code 27 and 29 no matter what local characters are printed on their top apparently by design decision you know whom:

    • Czech Layout cs-CZ
      image

    • German Layout de-DE
      image

    This fact is the main reason for the first commit: c29f9ad to alter KeyEvent.Text in WM_CHAR event.

  3. Other non-alphabetic keys don't get an WM_CHAR when pressed together with CTRL, only WM_KEYDOWN.

    • iin Dvorak layout another design decision by you know whom caused that keys for ascii control codes 27 and 29 were moved from scan codes 1A, 1B to 0C, 0D means on the row above, and it also means that WM_CHAR is not fired
    • Dvorak Layout
      image

    This was the reason for the second commit: 54328ca to alter KeyEvent.logical_key in WM_KEYDOWN event.

Not regarding this PR and only in my humble opinion, control codes should be treated in WM_CHAR message using caret notation this way:

  • KeyEvent.logical_key fill with the second char from caret notation and assign the whole caret notion to KeyEvent.text .
  • ^[
    KeyEvent.logical_key = '['
    KeyEvent.text = "^["

Fix  for rust-windowing#3621 part 2

Discard part 1 and part 2

Fix  for rust-windowing#3621 adjusted
@zbyna
Copy link
Author

zbyna commented May 30, 2024

After digging info from kbdlayout.info - only 98 from 215 keyboards use this key:
obrazek
I prepared a new version based on ASCII code emitted by WM_CHAR.

Tested as working in:

  • Dvorak Right-Hand US English Keyboard Layout
  • German Keyboard Layout
  • Czech Keyboard Layout
  • United Kingdom Keyboard Layout
  • Russia(Typewriter) Keyboard Layout

@zbyna zbyna requested a review from kchibisov May 30, 2024 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

3 participants