diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 3c4c2804878464a057a69d1a5f951f61309e4c13..897bcc25ee44935ae56d272a7320f6ec2c253e5d 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -37,7 +37,6 @@ use smol::Timer; use std::{ any::Any, cell::{Cell, RefCell}, - cmp, convert::TryInto, ffi::{c_void, CStr}, mem, @@ -274,7 +273,7 @@ struct WindowState { should_close_callback: Option bool>>, close_callback: Option>, input_handler: Option>, - pending_key_event: Option, + pending_keydown_event: Option, synthetic_drag_counter: usize, executor: Rc, scene_to_render: Option, @@ -286,13 +285,6 @@ struct WindowState { previous_modifiers_changed_event: Option, } -#[derive(Default, Debug)] -struct PendingKeyEvent { - set_marked_text: Option<(String, Option>, Option>)>, - unmark_text: bool, - insert_text: Option, -} - impl Window { pub fn open( id: usize, @@ -369,7 +361,7 @@ impl Window { close_callback: None, activate_callback: None, input_handler: None, - pending_key_event: None, + pending_keydown_event: None, synthetic_drag_counter: 0, executor, scene_to_render: Default::default(), @@ -705,7 +697,7 @@ extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) -> let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) }; if let Some(event) = event { - let mut event = match event { + window_state_borrow.pending_keydown_event = match event { Event::KeyDown(event) => { let keydown = (event.keystroke.clone(), event.input.clone()); // Ignore events from held-down keys after some of the initially-pressed keys @@ -718,97 +710,30 @@ extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) -> window_state_borrow.last_fresh_keydown = Some(keydown); } - event + Some(event) } _ => return NO, }; - - // TODO: handle "live conversion" - window_state_borrow.pending_key_event = Some(Default::default()); drop(window_state_borrow); - let had_marked_text = - with_input_handler(this, |input_handler| input_handler.marked_text_range()) - .flatten() - .is_some(); - // TODO: - // Since Mac Eisu Kana keys cannot be handled by interpretKeyEvents to enable/ - // disable an IME, we need to pass the event to processInputKeyBindings. - // processInputKeyBindings is available at least on 10.11-11.0. - // if (keyCode == kVK_JIS_Eisu || keyCode == kVK_JIS_Kana) { - // if ([NSTextInputContext - // respondsToSelector:@selector(processInputKeyBindings:)]) { - // [NSTextInputContext performSelector:@selector(processInputKeyBindings:) - // withObject:theEvent]; - // } - // } else { unsafe { let input_context: id = msg_send![this, inputContext]; let _: BOOL = msg_send![input_context, handleEvent: native_event]; } - // } - - let pending_event = window_state.borrow_mut().pending_key_event.take().unwrap(); - - dbg!(&pending_event); - - let mut inserted_text = false; - let has_marked_text = pending_event.set_marked_text.is_some() - || with_input_handler(this, |input_handler| input_handler.marked_text_range()) - .flatten() - .is_some(); - if let Some(text) = pending_event.insert_text.as_ref() { - if !text.is_empty() { - with_input_handler(this, |input_handler| { - input_handler.replace_text_in_range(None, &text) - }); - inserted_text = true; - } - } - - with_input_handler(this, |input_handler| { - if let Some((text, new_selected_range, replacement_range)) = - pending_event.set_marked_text - { - input_handler.replace_and_mark_text_in_range( - replacement_range, - &text, - new_selected_range, - ) - } else if had_marked_text && !has_marked_text && !inserted_text { - if pending_event.unmark_text { - input_handler.finish_composition(); - } else { - input_handler.cancel_composition(); - } - } - }); - if has_marked_text { - YES - } else { - let mut handled = false; - let mut window_state_borrow = window_state.borrow_mut(); + let mut handled = false; + let mut window_state_borrow = window_state.borrow_mut(); + if let Some(event) = window_state_borrow.pending_keydown_event.take() { if let Some(mut callback) = window_state_borrow.event_callback.take() { drop(window_state_borrow); - - if inserted_text { - handled = true; - } else { - if let Some(text) = pending_event.insert_text { - if text.chars().count() == 1 { - event.keystroke.key = text; - } - } - - handled = callback(Event::KeyDown(event.clone())); - } - + handled = callback(Event::KeyDown(event.clone())); window_state.borrow_mut().event_callback = Some(callback); } - - handled as BOOL + } else { + handled = true; } + + handled as BOOL } else { NO } @@ -1090,6 +1015,11 @@ extern "C" fn first_rect_for_character_range(_: &Object, _: Sel, _: NSRange, _: extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NSRange) { unsafe { + let window_state = get_window_state(this); + let mut window_state_borrow = window_state.borrow_mut(); + let pending_keydown_event = window_state_borrow.pending_keydown_event.take(); + drop(window_state_borrow); + let is_attributed_string: BOOL = msg_send![text, isKindOfClass: [class!(NSAttributedString)]]; let text: id = if is_attributed_string == YES { @@ -1100,20 +1030,36 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS let text = CStr::from_ptr(text.UTF8String() as *mut c_char) .to_str() .unwrap(); + let replacement_range = replacement_range.to_range(); - let window_state = get_window_state(this); - let mut window_state = window_state.borrow_mut(); - if window_state.pending_key_event.is_some() && !replacement_range.is_valid() { - window_state.pending_key_event.as_mut().unwrap().insert_text = Some(text.to_string()); - drop(window_state); - } else { - drop(window_state); + let is_composing = + with_input_handler(this, |input_handler| input_handler.marked_text_range()) + .flatten() + .is_some(); + + if is_composing || text.chars().count() > 1 || pending_keydown_event.is_none() { with_input_handler(this, |input_handler| { - input_handler.replace_text_in_range(replacement_range.to_range(), text); + input_handler.replace_text_in_range(replacement_range, text) }); - } + } else { + let mut pending_keydown_event = pending_keydown_event.unwrap(); + pending_keydown_event.keystroke.key = text.into(); + let mut window_state_borrow = window_state.borrow_mut(); + let event_callback = window_state_borrow.event_callback.take(); + drop(window_state_borrow); - with_input_handler(this, |input_handler| input_handler.unmark_text()); + let mut handled = false; + if let Some(mut event_callback) = event_callback { + handled = event_callback(Event::KeyDown(pending_keydown_event)); + window_state.borrow_mut().event_callback = Some(event_callback); + } + + if !handled { + with_input_handler(this, |input_handler| { + input_handler.replace_text_in_range(replacement_range, text) + }); + } + } } } @@ -1126,6 +1072,11 @@ extern "C" fn set_marked_text( ) { println!("set_marked_text"); unsafe { + get_window_state(this) + .borrow_mut() + .pending_keydown_event + .take(); + let is_attributed_string: BOOL = msg_send![text, isKindOfClass: [class!(NSAttributedString)]]; let text: id = if is_attributed_string == YES {