T08: Tab and F6 pass Ely's focus keys; each kitty flag reshapes only what it names; Cmd is Super; repeats and Command key-ups come from AppKit; IME commits stay UTF-8, as in kitty and Ghostty; key.zig out; the line rule reads every text file
This commit is contained in:
14 files changed
+505
-1147
No files matched your search
+53
-5
@@ -1,6 +1,7 @@
|
||||
use block::ConcreteBlock;
|
||||
use objc::{
|
||||
class, msg_send,
|
||||
runtime::{NO, Object},
|
||||
runtime::{BOOL, NO, Object},
|
||||
sel, sel_impl,
|
||||
};
|
||||
|
||||
@@ -8,23 +9,40 @@ use objc::{
|
||||
const KEY_DOWN: u64 = 10;
|
||||
const KEY_UP: u64 = 11;
|
||||
|
||||
/// The Command key's bit in an event's modifier flags.
|
||||
const COMMAND: u64 = 1 << 20;
|
||||
|
||||
/// The device bits of the left and right Option keys in an event's modifier flags.
|
||||
const LEFT_OPTION: u64 = 0x20;
|
||||
const RIGHT_OPTION: u64 = 0x40;
|
||||
|
||||
/// Which Option keys are down in the key event AppKit is handling: left, then right.
|
||||
pub fn option_sides() -> anyhow::Result<(bool, bool)> {
|
||||
/// What gpui drops from the key event AppKit is handling.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct KeyFacts {
|
||||
pub left_option: bool,
|
||||
pub right_option: bool,
|
||||
/// Held down; gpui loses this for keys AppKit routes through commands.
|
||||
pub repeat: bool,
|
||||
}
|
||||
|
||||
/// The facts of the key event AppKit is handling now.
|
||||
pub fn key_facts() -> anyhow::Result<KeyFacts> {
|
||||
unsafe {
|
||||
let app: *mut Object = msg_send![class!(NSApplication), sharedApplication];
|
||||
let event: *mut Object = msg_send![app, currentEvent];
|
||||
anyhow::ensure!(!event.is_null(), "macOS: no key event to read Option from");
|
||||
anyhow::ensure!(!event.is_null(), "macOS: no key event to read");
|
||||
let kind: u64 = msg_send![event, type];
|
||||
anyhow::ensure!(
|
||||
kind == KEY_DOWN || kind == KEY_UP,
|
||||
"macOS: the current event is type {kind}, not a key"
|
||||
);
|
||||
let flags: u64 = msg_send![event, modifierFlags];
|
||||
Ok((flags & LEFT_OPTION != 0, flags & RIGHT_OPTION != 0))
|
||||
let repeat: BOOL = msg_send![event, isARepeat];
|
||||
Ok(KeyFacts {
|
||||
left_option: flags & LEFT_OPTION != 0,
|
||||
right_option: flags & RIGHT_OPTION != 0,
|
||||
repeat: repeat != NO,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,3 +61,33 @@ pub fn repeat_held_keys() {
|
||||
}
|
||||
log::info!("macOS: held keys repeat");
|
||||
}
|
||||
|
||||
/// Hands the focused view the Command key-ups AppKit swallows, as Ghostty does.
|
||||
pub fn deliver_command_key_ups() -> anyhow::Result<()> {
|
||||
let handler = ConcreteBlock::new(|event: *mut Object| -> *mut Object {
|
||||
unsafe {
|
||||
let flags: u64 = msg_send![event, modifierFlags];
|
||||
let window: *mut Object = msg_send![event, window];
|
||||
if flags & COMMAND == 0 || window.is_null() {
|
||||
return event;
|
||||
}
|
||||
let view: *mut Object = msg_send![window, firstResponder];
|
||||
let _: () = msg_send![view, keyUp: event];
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
})
|
||||
.copy();
|
||||
unsafe {
|
||||
let monitor: *mut Object = msg_send![
|
||||
class!(NSEvent),
|
||||
addLocalMonitorForEventsMatchingMask: 1u64 << KEY_UP
|
||||
handler: &*handler
|
||||
];
|
||||
anyhow::ensure!(
|
||||
!monitor.is_null(),
|
||||
"macOS: AppKit refused the key-up monitor"
|
||||
);
|
||||
}
|
||||
log::info!("macOS: Command key-ups reach the focused view");
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user