diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index 22cb3ba5dea4d357405f2e0d99b1e2efe6242d6a..d32344b0dbc8c2096d4527616316eef9a92e73bc 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -41,6 +41,7 @@ pub struct Keystroke { pub alt: bool, pub shift: bool, pub cmd: bool, + pub function: bool, pub key: String, } @@ -277,6 +278,7 @@ impl Keystroke { let mut alt = false; let mut shift = false; let mut cmd = false; + let mut function = false; let mut key = None; let mut components = source.split("-").peekable(); @@ -286,6 +288,7 @@ impl Keystroke { "alt" => alt = true, "shift" => shift = true, "cmd" => cmd = true, + "fn" => function = true, _ => { if let Some(component) = components.peek() { if component.is_empty() && source.ends_with('-') { @@ -306,6 +309,7 @@ impl Keystroke { alt, shift, cmd, + function, key: key.unwrap(), }) } @@ -464,6 +468,7 @@ mod tests { alt: false, shift: false, cmd: false, + function: false, } ); @@ -475,6 +480,7 @@ mod tests { alt: true, shift: true, cmd: false, + function: false, } ); @@ -486,6 +492,7 @@ mod tests { alt: false, shift: true, cmd: true, + function: false, } ); diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index e0e178aa8c0833471d5cfb7be37a2a516138bfa6..5aedc63b2e03caecf92d03dfc912263f4b6ca9ca 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -210,19 +210,24 @@ impl Event { unsafe fn parse_keystroke(native_event: id) -> Keystroke { use cocoa::appkit::*; + let mut chars_ignoring_modifiers = + CStr::from_ptr(native_event.charactersIgnoringModifiers().UTF8String() as *mut c_char) + .to_str() + .unwrap(); + let first_char = chars_ignoring_modifiers.chars().next().map(|ch| ch as u16); let modifiers = native_event.modifierFlags(); + let ctrl = modifiers.contains(NSEventModifierFlags::NSControlKeyMask); let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask); let mut shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask); let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask); - - let mut chars_ignoring_modifiers = - CStr::from_ptr(native_event.charactersIgnoringModifiers().UTF8String() as *mut c_char) - .to_str() - .unwrap(); + let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask) + && first_char.map_or(true, |ch| { + ch < NSUpArrowFunctionKey || ch > NSModeSwitchFunctionKey + }); #[allow(non_upper_case_globals)] - let key = match chars_ignoring_modifiers.chars().next().map(|ch| ch as u16) { + let key = match first_char { Some(SPACE_KEY) => "space", Some(BACKSPACE_KEY) => "backspace", Some(ENTER_KEY) | Some(NUMPAD_ENTER_KEY) => "enter", @@ -282,6 +287,7 @@ unsafe fn parse_keystroke(native_event: id) -> Keystroke { alt, shift, cmd, + function, key: key.into(), } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 86af181765e6a9f2dccf6a351a1bc350bfc26c90..05cc542b98d6fa8f66fe7fb00b3a1acc66c05508 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -711,14 +711,16 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let window_state = unsafe { get_window_state(this) }; let mut window_state_borrow = window_state.as_ref().borrow_mut(); - if key_equivalent { - window_state_borrow.performed_key_equivalent = true; - } else if window_state_borrow.performed_key_equivalent { - return NO; - } let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) }; if let Some(event) = event { + if key_equivalent { + window_state_borrow.performed_key_equivalent = true; + } else if window_state_borrow.performed_key_equivalent { + return NO; + } + + let function_is_held; window_state_borrow.pending_key_down = match event { Event::KeyDown(event) => { let keydown = event.keystroke.clone(); @@ -732,15 +734,18 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: window_state_borrow.last_fresh_keydown = Some(keydown); } + function_is_held = event.keystroke.function; Some((event, None)) } _ => return NO, }; drop(window_state_borrow); - unsafe { - let input_context: id = msg_send![this, inputContext]; - let _: BOOL = msg_send![input_context, handleEvent: native_event]; + if !function_is_held { + unsafe { + let input_context: id = msg_send![this, inputContext]; + let _: BOOL = msg_send![input_context, handleEvent: native_event]; + } } let mut handled = false; @@ -856,6 +861,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) { ctrl: false, alt: false, shift: false, + function: false, key: ".".into(), }; let event = Event::KeyDown(KeyDownEvent { diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index f88bfa927ac7f650251bd04c5762a71365562626..3ed46de459f2ed23ddc0cc5c8d9fa1a05fa105cf 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -311,6 +311,7 @@ mod test { alt: false, shift: false, cmd: false, + function: false, key: "🖖🏻".to_string(), //2 char string }; assert_eq!(to_esc_str(&ks, &TermMode::NONE), None);