Skip to content

Commit 324dd5f

Browse files
emilkkchibisov
authored andcommitted
On macOS, reported shifted key with shift+Ctrl/Cmd
Fixes #3078.
1 parent fdedda3 commit 324dd5f

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Unreleased` header.
1414
- On X11, fix `NotSupported` error not propagated when creating event loop.
1515
- On Wayland, fix resize not issued when scale changes
1616
- On X11 and Wayland, fix arrow up on keypad reported as `ArrowLeft`.
17+
- On macOS, report correct logical key when Ctrl or Cmd is pressed.
1718

1819
# 0.29.8
1920

src/platform_impl/macos/event.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ impl KeyEventExtModifierSupplement for KeyEvent {
3939
}
4040
}
4141

42+
/// Ignores ALL modifiers.
4243
pub fn get_modifierless_char(scancode: u16) -> Key {
4344
let mut string = [0; 16];
4445
let input_source;
@@ -97,6 +98,7 @@ pub fn get_modifierless_char(scancode: u16) -> Key {
9798
Key::Character(SmolStr::new(chars))
9899
}
99100

101+
// Ignores all modifiers except for SHIFT (yes, even ALT is ignored).
100102
fn get_logical_key_char(ns_event: &NSEvent, modifierless_chars: &str) -> Key {
101103
let string = ns_event
102104
.charactersIgnoringModifiers()
@@ -126,6 +128,13 @@ pub(crate) fn create_key_event(
126128
let mut physical_key =
127129
key_override.unwrap_or_else(|| PhysicalKey::from_scancode(scancode as u32));
128130

131+
// NOTE: The logical key should heed both SHIFT and ALT if possible.
132+
// For instance:
133+
// * Pressing the A key: logical key should be "a"
134+
// * Pressing SHIFT A: logical key should be "A"
135+
// * Pressing CTRL SHIFT A: logical key should also be "A"
136+
// This is not easy to tease out of `NSEvent`, but we do our best.
137+
129138
let text_with_all_modifiers: Option<SmolStr> = if key_override.is_some() {
130139
None
131140
} else {
@@ -146,21 +155,29 @@ pub(crate) fn create_key_event(
146155

147156
let key_from_code = code_to_key(physical_key, scancode);
148157
let (logical_key, key_without_modifiers) = if matches!(key_from_code, Key::Unidentified(_)) {
158+
// `get_modifierless_char/key_without_modifiers` ignores ALL modifiers.
149159
let key_without_modifiers = get_modifierless_char(scancode);
150160

151161
let modifiers = NSEvent::modifierFlags(ns_event);
152162
let has_ctrl = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
163+
let has_cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
153164

154165
let logical_key = match text_with_all_modifiers.as_ref() {
155-
// Only checking for ctrl here, not checking for alt because we DO want to
166+
// Only checking for ctrl and cmd here, not checking for alt because we DO want to
156167
// include its effect in the key. For example if -on the Germay layout- one
157168
// presses alt+8, the logical key should be "{"
158169
// Also not checking if this is a release event because then this issue would
159170
// still affect the key release.
160-
Some(text) if !has_ctrl => Key::Character(text.clone()),
171+
Some(text) if !has_ctrl && !has_cmd => {
172+
// Character heeding both SHIFT and ALT.
173+
Key::Character(text.clone())
174+
}
175+
161176
_ => match key_without_modifiers.as_ref() {
177+
// Character heeding just SHIFT, ignoring ALT.
162178
Key::Character(ch) => get_logical_key_char(ns_event, ch),
163-
// Don't try to get text for events which likely don't have it.
179+
180+
// Character ignoring ALL modifiers.
164181
_ => key_without_modifiers.clone(),
165182
},
166183
};

0 commit comments

Comments
 (0)