mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
macos: workaround weird CMD-. behavior
There are certain key combinations that macOS prefers to handle without giving the application much opportunity to process them. CTRL-ESC and CMD-. both cause doCommandBySelector(cancel:) to be called. The former we had already special cased but since we can't disambiguate the two things, we need a better way. performKeyEquivalent: is a method we can implement to have an opportunity to "do something" and prevent the default macOS behavior. So we implement that. What's interesting is that saying that we handled CMD-. results in no further processing at all by macOS, whereas saying that we handled CTRL-ESC results in macOS doing the normal key event dispatch. So we need to route that event for ourselves in that one case. Doesn't feel great! refs: https://github.com/wez/wezterm/issues/1867
This commit is contained in:
parent
e615720444
commit
e680cc848a
@ -1481,14 +1481,7 @@ impl WindowView {
|
|||||||
let selector = format!("{:?}", a_selector);
|
let selector = format!("{:?}", a_selector);
|
||||||
log::trace!("do_command_by_selector {:?}", selector);
|
log::trace!("do_command_by_selector {:?}", selector);
|
||||||
|
|
||||||
let (key, modifiers) = match selector.as_ref() {
|
match selector.as_ref() {
|
||||||
"cancel:" => {
|
|
||||||
// FIXME: this isn't scalable to various keys
|
|
||||||
// and we lose eg: SHIFT if that is also pressed at the same time.
|
|
||||||
// However, CTRL-ESC is processed BEFORE sending any other
|
|
||||||
// key events so we have no choice but to do it this way.
|
|
||||||
(KeyCode::Char('\x1b'), Modifiers::CTRL)
|
|
||||||
}
|
|
||||||
"scrollToBeginningOfDocument:"
|
"scrollToBeginningOfDocument:"
|
||||||
| "scrollToEndOfDocument:"
|
| "scrollToEndOfDocument:"
|
||||||
| "scrollPageUp:"
|
| "scrollPageUp:"
|
||||||
@ -1510,7 +1503,6 @@ impl WindowView {
|
|||||||
inner.ime_state = ImeDisposition::Continue;
|
inner.ime_state = ImeDisposition::Continue;
|
||||||
inner.ime_last_event.take();
|
inner.ime_last_event.take();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::warn!("UNHANDLED: IME: do_command_by_selector: {:?}", selector);
|
log::warn!("UNHANDLED: IME: do_command_by_selector: {:?}", selector);
|
||||||
@ -1520,24 +1512,7 @@ impl WindowView {
|
|||||||
inner.ime_state = ImeDisposition::Continue;
|
inner.ime_state = ImeDisposition::Continue;
|
||||||
inner.ime_last_event.take();
|
inner.ime_last_event.take();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let event = KeyEvent {
|
|
||||||
key,
|
|
||||||
modifiers,
|
|
||||||
repeat_count: 1,
|
|
||||||
key_is_down: true,
|
|
||||||
raw: None,
|
|
||||||
}
|
|
||||||
.normalize_shift();
|
|
||||||
|
|
||||||
if let Some(myself) = Self::get_this(this) {
|
|
||||||
let mut inner = myself.inner.borrow_mut();
|
|
||||||
inner.ime_state = ImeDisposition::Acted;
|
|
||||||
inner.ime_last_event.replace(event.clone());
|
|
||||||
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2338,6 +2313,38 @@ impl WindowView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn perform_key_equivalent(this: &mut Object, _sel: Sel, nsevent: id) -> BOOL {
|
||||||
|
let chars = unsafe { nsstring_to_str(nsevent.characters()) };
|
||||||
|
let modifier_flags = unsafe { nsevent.modifierFlags() };
|
||||||
|
let modifiers = key_modifiers(modifier_flags);
|
||||||
|
|
||||||
|
log::trace!(
|
||||||
|
"perform_key_equivalent: chars=`{}` modifiers=`{:?}`",
|
||||||
|
chars.escape_debug(),
|
||||||
|
modifiers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if chars == "." && modifiers == Modifiers::SUPER {
|
||||||
|
// Synthesize a key down event for this, because macOS will
|
||||||
|
// not do that, even though we tell it that we handled this event.
|
||||||
|
// <https://github.com/wez/wezterm/issues/1867>
|
||||||
|
Self::key_common(this, nsevent, true);
|
||||||
|
|
||||||
|
// Prevent macOS from calling doCommandBySelector(cancel:)
|
||||||
|
YES
|
||||||
|
} else if chars == "\u{1b}" && modifiers == Modifiers::CTRL {
|
||||||
|
// We don't need to synthesize a key down event for this,
|
||||||
|
// because macOS will do that once we return YES.
|
||||||
|
// We need to return YES to prevent macOS from calling
|
||||||
|
// doCommandBySelector(cancel:) on us.
|
||||||
|
YES
|
||||||
|
} else {
|
||||||
|
// Allow macOS to process built-in shortcuts like CMD-`
|
||||||
|
// to cycle though windows
|
||||||
|
NO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn key_down(this: &mut Object, _sel: Sel, nsevent: id) {
|
extern "C" fn key_down(this: &mut Object, _sel: Sel, nsevent: id) {
|
||||||
Self::key_common(this, nsevent, true);
|
Self::key_common(this, nsevent, true);
|
||||||
}
|
}
|
||||||
@ -2597,6 +2604,11 @@ impl WindowView {
|
|||||||
Self::key_up as extern "C" fn(&mut Object, Sel, id),
|
Self::key_up as extern "C" fn(&mut Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cls.add_method(
|
||||||
|
sel!(performKeyEquivalent:),
|
||||||
|
Self::perform_key_equivalent as extern "C" fn(&mut Object, Sel, id) -> BOOL,
|
||||||
|
);
|
||||||
|
|
||||||
cls.add_method(
|
cls.add_method(
|
||||||
sel!(acceptsFirstResponder),
|
sel!(acceptsFirstResponder),
|
||||||
Self::accepts_first_responder as extern "C" fn(&mut Object, Sel) -> BOOL,
|
Self::accepts_first_responder as extern "C" fn(&mut Object, Sel) -> BOOL,
|
||||||
|
Loading…
Reference in New Issue
Block a user