Skip to content

Commit 13df3b9

Browse files
committed
macos: get the layout once and not 100+ times in the loop
1 parent 34614e8 commit 13df3b9

File tree

1 file changed

+48
-32
lines changed

1 file changed

+48
-32
lines changed

src/macos/macos_impl.rs

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,70 +1130,87 @@ impl TryFrom<Key> for core_graphics::event::CGKeyCode {
11301130
fn get_layoutdependent_keycode(string: &str) -> CGKeyCode {
11311131
let mut pressed_keycode = 0;
11321132

1133+
let layout = current_keyboard_layout().unwrap();
1134+
11331135
// loop through every keycode (0 - 127)
11341136
for keycode in 0..128 {
11351137
// no modifier
1136-
if let Ok(key_string) = keycode_to_string(keycode, 0x100) {
1138+
if let Ok(key_string) = keycode_to_string(keycode, 0x100, layout) {
11371139
// debug!("{:?}", string);
11381140
if string == key_string {
11391141
pressed_keycode = keycode;
11401142
}
11411143
}
11421144

11431145
// shift modifier
1144-
if let Ok(key_string) = keycode_to_string(keycode, 0x20102) {
1146+
if let Ok(key_string) = keycode_to_string(keycode, 0x20102, layout) {
11451147
// debug!("{:?}", string);
11461148
if string == key_string {
11471149
pressed_keycode = keycode;
11481150
}
11491151
}
11501152

11511153
// alt modifier
1152-
// if let Some(string) = keycode_to_string(keycode, 0x80120) {
1154+
// if let Some(string) = keycode_to_string(keycode, 0x80120, layout) {
11531155
// debug!("{:?}", string);
11541156
// }
11551157
// alt + shift modifier
1156-
// if let Some(string) = keycode_to_string(keycode, 0xa0122) {
1158+
// if let Some(string) = keycode_to_string(keycode, 0xa0122, layout) {
11571159
// debug!("{:?}", string);
11581160
// }
11591161
}
11601162

11611163
pressed_keycode
11621164
}
11631165

1164-
fn keycode_to_string(keycode: u16, modifier: u32) -> Result<String, String> {
1165-
let mut current_keyboard = unsafe { TISCopyCurrentKeyboardInputSource() };
1166+
fn current_keyboard_layout() -> Result<CFDataRef, String> {
1167+
let current_keyboard = unsafe { TISCopyCurrentKeyboardInputSource() };
11661168
let mut layout_data =
11671169
unsafe { TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) };
1170+
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
1171+
1172+
if !layout_data.is_null() {
1173+
return Ok(layout_data);
1174+
}
1175+
1176+
debug!(
1177+
"TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) returned NULL"
1178+
);
1179+
1180+
// TISGetInputSourceProperty returns null with some keyboard layout.
1181+
// Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
1182+
// See also: https://github.com/microsoft/node-native-keymap/blob/089d802efd387df4dce1f0e31898c66e28b3f67f/src/keyboard_mac.mm#L90
1183+
let current_keyboard = unsafe { TISCopyCurrentKeyboardLayoutInputSource() };
1184+
layout_data =
1185+
unsafe { TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) };
1186+
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
1187+
1188+
if !layout_data.is_null() {
1189+
return Ok(layout_data);
1190+
}
1191+
1192+
debug!(
1193+
"TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) returned NULL again"
1194+
);
1195+
let current_keyboard = unsafe { TISCopyCurrentASCIICapableKeyboardLayoutInputSource() };
1196+
let layout_data =
1197+
unsafe { TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) };
1198+
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
1199+
11681200
if layout_data.is_null() {
1169-
debug!(
1170-
"TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) returned NULL"
1171-
);
1172-
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
1173-
1174-
// TISGetInputSourceProperty returns null with some keyboard layout.
1175-
// Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
1176-
// See also: https://github.com/microsoft/node-native-keymap/blob/089d802efd387df4dce1f0e31898c66e28b3f67f/src/keyboard_mac.mm#L90
1177-
current_keyboard = unsafe { TISCopyCurrentKeyboardLayoutInputSource() };
1178-
layout_data = unsafe {
1179-
TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData)
1180-
};
1181-
if layout_data.is_null() {
1182-
debug!(
1183-
"TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData) returned NULL again"
1184-
);
1185-
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
1186-
current_keyboard = unsafe { TISCopyCurrentASCIICapableKeyboardLayoutInputSource() };
1187-
layout_data = unsafe {
1188-
TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData)
1189-
};
1190-
debug_assert!(!layout_data.is_null());
1191-
debug!("Using layout of the TISCopyCurrentASCIICapableKeyboardLayoutInputSource");
1192-
}
1201+
Err("Failed to get the current keyboard layout".to_string())
1202+
} else {
1203+
debug!("Using layout of the TISCopyCurrentASCIICapableKeyboardLayoutInputSource");
1204+
Ok(layout_data)
11931205
}
1206+
}
11941207

1208+
fn keycode_to_string(
1209+
keycode: u16,
1210+
modifier: u32,
1211+
layout_data: CFDataRef,
1212+
) -> Result<String, String> {
11951213
let keyboard_layout = unsafe { CFDataGetBytePtr(layout_data) };
1196-
11971214
let mut keys_down: UInt32 = 0;
11981215
let mut chars: [UniChar; 1] = [0];
11991216
let mut real_length = 0;
@@ -1211,7 +1228,6 @@ fn keycode_to_string(keycode: u16, modifier: u32) -> Result<String, String> {
12111228
chars.as_mut_ptr(),
12121229
)
12131230
};
1214-
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
12151231

12161232
if status != 0 {
12171233
error!("UCKeyTranslate failed with status: {status}");

0 commit comments

Comments
 (0)