Dispatch application menu events if custom key equivalent wasn't found

This commit is contained in:
Antonio Scandurra 2022-07-27 11:46:47 +02:00
parent 5c5e7db587
commit d3f14fb1c2

View file

@ -154,6 +154,10 @@ unsafe fn build_classes() {
sel!(performKeyEquivalent:), sel!(performKeyEquivalent:),
handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL, handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,
); );
decl.add_method(
sel!(keyDown:),
handle_key_down as extern "C" fn(&Object, Sel, id),
);
decl.add_method( decl.add_method(
sel!(mouseDown:), sel!(mouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id), handle_view_event as extern "C" fn(&Object, Sel, id),
@ -275,7 +279,8 @@ struct WindowState {
should_close_callback: Option<Box<dyn FnMut() -> bool>>, should_close_callback: Option<Box<dyn FnMut() -> bool>>,
close_callback: Option<Box<dyn FnOnce()>>, close_callback: Option<Box<dyn FnOnce()>>,
input_handler: Option<Box<dyn InputHandler>>, input_handler: Option<Box<dyn InputHandler>>,
pending_key_down_event: Option<KeyDownEvent>, pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
performed_key_equivalent: bool,
synthetic_drag_counter: usize, synthetic_drag_counter: usize,
executor: Rc<executor::Foreground>, executor: Rc<executor::Foreground>,
scene_to_render: Option<Scene>, scene_to_render: Option<Scene>,
@ -287,6 +292,11 @@ struct WindowState {
previous_modifiers_changed_event: Option<Event>, previous_modifiers_changed_event: Option<Event>,
} }
struct InsertText {
replacement_range: Option<Range<usize>>,
text: String,
}
impl Window { impl Window {
pub fn open( pub fn open(
id: usize, id: usize,
@ -359,7 +369,8 @@ impl Window {
close_callback: None, close_callback: None,
activate_callback: None, activate_callback: None,
input_handler: None, input_handler: None,
pending_key_down_event: None, pending_key_down: None,
performed_key_equivalent: false,
synthetic_drag_counter: 0, synthetic_drag_counter: 0,
executor, executor,
scene_to_render: Default::default(), scene_to_render: Default::default(),
@ -689,13 +700,26 @@ extern "C" fn dealloc_view(this: &Object, _: Sel) {
} }
extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) -> BOOL { extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) -> BOOL {
handle_key_event(this, native_event, true)
}
extern "C" fn handle_key_down(this: &Object, _: Sel, native_event: id) {
handle_key_event(this, native_event, false);
}
extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: bool) -> BOOL {
let window_state = unsafe { get_window_state(this) }; let window_state = unsafe { get_window_state(this) };
let mut window_state_borrow = window_state.as_ref().borrow_mut(); 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())) }; let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) };
if let Some(event) = event { if let Some(event) = event {
window_state_borrow.pending_key_down_event = match event { window_state_borrow.pending_key_down = match event {
Event::KeyDown(event) => { Event::KeyDown(event) => {
let keydown = event.keystroke.clone(); let keydown = event.keystroke.clone();
// Ignore events from held-down keys after some of the initially-pressed keys // Ignore events from held-down keys after some of the initially-pressed keys
@ -708,7 +732,7 @@ extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) ->
window_state_borrow.last_fresh_keydown = Some(keydown); window_state_borrow.last_fresh_keydown = Some(keydown);
} }
Some(event) Some((event, None))
} }
_ => return NO, _ => return NO,
}; };
@ -719,8 +743,9 @@ extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) ->
let _: BOOL = msg_send![input_context, handleEvent: native_event]; let _: BOOL = msg_send![input_context, handleEvent: native_event];
} }
let mut handled = false;
let mut window_state_borrow = window_state.borrow_mut(); let mut window_state_borrow = window_state.borrow_mut();
if let Some(event) = window_state_borrow.pending_key_down_event.take() { if let Some((event, insert_text)) = window_state_borrow.pending_key_down.take() {
if let Some(mut callback) = window_state_borrow.event_callback.take() { if let Some(mut callback) = window_state_borrow.event_callback.take() {
drop(window_state_borrow); drop(window_state_borrow);
@ -729,14 +754,26 @@ extern "C" fn handle_key_equivalent(this: &Object, _: Sel, native_event: id) ->
.flatten() .flatten()
.is_some(); .is_some();
if !is_composing { if !is_composing {
callback(Event::KeyDown(event)); handled = callback(Event::KeyDown(event));
}
if !handled {
if let Some(insert) = insert_text {
handled = true;
with_input_handler(this, |input_handler| {
input_handler
.replace_text_in_range(insert.replacement_range, &insert.text)
});
}
} }
window_state.borrow_mut().event_callback = Some(callback); window_state.borrow_mut().event_callback = Some(callback);
} }
} else {
handled = true;
} }
YES handled as BOOL
} else { } else {
NO NO
} }
@ -837,6 +874,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
extern "C" fn send_event(this: &Object, _: Sel, native_event: id) { extern "C" fn send_event(this: &Object, _: Sel, native_event: id) {
unsafe { unsafe {
let () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event]; let () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event];
get_window_state(this).borrow_mut().performed_key_equivalent = false;
} }
} }
@ -1042,7 +1080,7 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS
unsafe { unsafe {
let window_state = get_window_state(this); let window_state = get_window_state(this);
let mut window_state_borrow = window_state.borrow_mut(); let mut window_state_borrow = window_state.borrow_mut();
let pending_key_down_event = window_state_borrow.pending_key_down_event.take(); let pending_key_down = window_state_borrow.pending_key_down.take();
drop(window_state_borrow); drop(window_state_borrow);
let is_attributed_string: BOOL = let is_attributed_string: BOOL =
@ -1062,24 +1100,17 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS
.flatten() .flatten()
.is_some(); .is_some();
if is_composing || text.chars().count() > 1 || pending_key_down_event.is_none() { if is_composing || text.chars().count() > 1 || pending_key_down.is_none() {
with_input_handler(this, |input_handler| { with_input_handler(this, |input_handler| {
input_handler.replace_text_in_range(replacement_range, text) input_handler.replace_text_in_range(replacement_range, text)
}); });
} else { } else {
let mut handled = false; let mut pending_key_down = pending_key_down.unwrap();
pending_key_down.1 = Some(InsertText {
let event_callback = window_state.borrow_mut().event_callback.take(); replacement_range,
if let Some(mut event_callback) = event_callback { text: text.to_string(),
handled = event_callback(Event::KeyDown(pending_key_down_event.unwrap())); });
window_state.borrow_mut().event_callback = Some(event_callback); window_state.borrow_mut().pending_key_down = Some(pending_key_down);
}
if !handled {
with_input_handler(this, |input_handler| {
input_handler.replace_text_in_range(replacement_range, text)
});
}
} }
} }
} }
@ -1092,10 +1123,7 @@ extern "C" fn set_marked_text(
replacement_range: NSRange, replacement_range: NSRange,
) { ) {
unsafe { unsafe {
get_window_state(this) get_window_state(this).borrow_mut().pending_key_down.take();
.borrow_mut()
.pending_key_down_event
.take();
let is_attributed_string: BOOL = let is_attributed_string: BOOL =
msg_send![text, isKindOfClass: [class!(NSAttributedString)]]; msg_send![text, isKindOfClass: [class!(NSAttributedString)]];