Additional Windows keyboard input fixes (#42294)
- Enable Alt+Numpad input
- For this to be effective, the default keybindings for Alt+{Number}
will need to be unbound. This won't be needed once we gain the ability
to differentiate numpad digit keys from alphanumeric digit keys.
- Fixes https://github.com/zed-industries/zed/issues/40699
- Fix a number of edge cases with dead keys
Release Notes:
- N/A
This commit is contained in:
@@ -1332,21 +1332,13 @@ fn parse_normal_key(
|
||||
lparam: LPARAM,
|
||||
mut modifiers: Modifiers,
|
||||
) -> Option<(Keystroke, bool)> {
|
||||
let mut key_char = None;
|
||||
let (key_char, prefer_character_input) = process_key(vkey, lparam.hiword());
|
||||
|
||||
let key = parse_immutable(vkey).or_else(|| {
|
||||
let scan_code = lparam.hiword() & 0xFF;
|
||||
key_char = generate_key_char(
|
||||
vkey,
|
||||
scan_code as u32,
|
||||
modifiers.control,
|
||||
modifiers.shift,
|
||||
modifiers.alt,
|
||||
);
|
||||
get_keystroke_key(vkey, scan_code as u32, &mut modifiers)
|
||||
})?;
|
||||
|
||||
let prefer_character_input = should_prefer_character_input(vkey, lparam.hiword() & 0xFF);
|
||||
|
||||
Some((
|
||||
Keystroke {
|
||||
modifiers,
|
||||
@@ -1357,11 +1349,11 @@ fn parse_normal_key(
|
||||
))
|
||||
}
|
||||
|
||||
fn should_prefer_character_input(vkey: VIRTUAL_KEY, scan_code: u16) -> bool {
|
||||
fn process_key(vkey: VIRTUAL_KEY, scan_code: u16) -> (Option<String>, bool) {
|
||||
let mut keyboard_state = [0u8; 256];
|
||||
unsafe {
|
||||
if GetKeyboardState(&mut keyboard_state).is_err() {
|
||||
return false;
|
||||
return (None, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1372,21 +1364,25 @@ fn should_prefer_character_input(vkey: VIRTUAL_KEY, scan_code: u16) -> bool {
|
||||
scan_code as u32,
|
||||
Some(&keyboard_state),
|
||||
&mut buffer_c,
|
||||
0x5,
|
||||
0x4,
|
||||
)
|
||||
};
|
||||
if result_c < 0 {
|
||||
return false;
|
||||
|
||||
if result_c == 0 {
|
||||
return (None, false);
|
||||
}
|
||||
|
||||
let c = &buffer_c[..result_c as usize];
|
||||
if char::decode_utf16(c.iter().copied())
|
||||
.next()
|
||||
.and_then(|ch| ch.ok())
|
||||
.map(|ch| ch.is_control())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
return false;
|
||||
let c = &buffer_c[..result_c.unsigned_abs() as usize];
|
||||
let key_char = String::from_utf16(c)
|
||||
.ok()
|
||||
.filter(|s| !s.is_empty() && !s.chars().next().unwrap().is_control());
|
||||
|
||||
if result_c < 0 {
|
||||
return (key_char, true);
|
||||
}
|
||||
|
||||
if key_char.is_none() {
|
||||
return (None, false);
|
||||
}
|
||||
|
||||
// Workaround for some bug that makes the compiler think keyboard_state is still zeroed out
|
||||
@@ -1395,9 +1391,10 @@ fn should_prefer_character_input(vkey: VIRTUAL_KEY, scan_code: u16) -> bool {
|
||||
let alt_down = (keyboard_state[VK_MENU.0 as usize] & 0x80) != 0;
|
||||
let win_down = (keyboard_state[VK_LWIN.0 as usize] & 0x80) != 0
|
||||
|| (keyboard_state[VK_RWIN.0 as usize] & 0x80) != 0;
|
||||
|
||||
let has_modifiers = ctrl_down || alt_down || win_down;
|
||||
if !has_modifiers {
|
||||
return false;
|
||||
return (key_char, false);
|
||||
}
|
||||
|
||||
let mut state_no_modifiers = keyboard_state;
|
||||
@@ -1417,15 +1414,15 @@ fn should_prefer_character_input(vkey: VIRTUAL_KEY, scan_code: u16) -> bool {
|
||||
scan_code as u32,
|
||||
Some(&state_no_modifiers),
|
||||
&mut buffer_c_no_modifiers,
|
||||
0x5,
|
||||
0x4,
|
||||
)
|
||||
};
|
||||
if result_c_no_modifiers <= 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c_no_modifiers = &buffer_c_no_modifiers[..result_c_no_modifiers as usize];
|
||||
c != c_no_modifiers
|
||||
let c_no_modifiers = &buffer_c_no_modifiers[..result_c_no_modifiers.unsigned_abs() as usize];
|
||||
(
|
||||
key_char,
|
||||
result_c != result_c_no_modifiers || c != c_no_modifiers,
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_ime_composition_string(ctx: HIMC, comp_type: IME_COMPOSITION_STRING) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user