Skip to content

Commit cf2da6d

Browse files
committed
macos: get the layout once and not 100+ times in the loop
1 parent d55a94e commit cf2da6d

File tree

1 file changed

+50
-32
lines changed

1 file changed

+50
-32
lines changed

src/macos/macos_impl.rs

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,70 +1137,89 @@ impl TryFrom<Key> for core_graphics::event::CGKeyCode {
11371137
fn get_layoutdependent_keycode(string: &str) -> CGKeyCode {
11381138
let mut pressed_keycode = 0;
11391139

1140+
let layout = current_keyboard_layout().unwrap();
1141+
11401142
// loop through every keycode (0 - 127)
11411143
for keycode in 0..128 {
11421144
// no modifier
1143-
if let Ok(key_string) = keycode_to_string(keycode, 0x100) {
1145+
if let Ok(key_string) = keycode_to_string(keycode, 0x100, layout) {
11441146
// debug!("{:?}", string);
11451147
if string == key_string {
11461148
pressed_keycode = keycode;
11471149
}
11481150
}
11491151

11501152
// shift modifier
1151-
if let Ok(key_string) = keycode_to_string(keycode, 0x20102) {
1153+
if let Ok(key_string) = keycode_to_string(keycode, 0x20102, layout) {
11521154
// debug!("{:?}", string);
11531155
if string == key_string {
11541156
pressed_keycode = keycode;
11551157
}
11561158
}
11571159

11581160
// alt modifier
1159-
// if let Some(string) = keycode_to_string(keycode, 0x80120) {
1161+
// if let Some(string) = keycode_to_string(keycode, 0x80120, layout) {
11601162
// debug!("{:?}", string);
11611163
// }
11621164
// alt + shift modifier
1163-
// if let Some(string) = keycode_to_string(keycode, 0xa0122) {
1165+
// if let Some(string) = keycode_to_string(keycode, 0xa0122, layout) {
11641166
// debug!("{:?}", string);
11651167
// }
11661168
}
11671169

1170+
unsafe { CFRelease(layout.cast::<c_void>()) };
1171+
11681172
pressed_keycode
11691173
}
11701174

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

1217+
fn keycode_to_string(
1218+
keycode: u16,
1219+
modifier: u32,
1220+
layout_data: CFDataRef,
1221+
) -> Result<String, String> {
12021222
let keyboard_layout = unsafe { CFDataGetBytePtr(layout_data) };
1203-
12041223
let mut keys_down: UInt32 = 0;
12051224
let mut chars: [UniChar; 1] = [0];
12061225
let mut real_length = 0;
@@ -1218,7 +1237,6 @@ fn keycode_to_string(keycode: u16, modifier: u32) -> Result<String, String> {
12181237
chars.as_mut_ptr(),
12191238
)
12201239
};
1221-
unsafe { CFRelease(current_keyboard.cast::<c_void>()) };
12221240

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

0 commit comments

Comments
 (0)