Skip to content

Commit

Permalink
Use objc2-core-foundation and objc2-core-graphics
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Jan 27, 2025
1 parent 2d731fa commit 45f4e45
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 418 deletions.
40 changes: 34 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,11 @@ ndk = { version = "0.9.0", features = ["rwh_06"], default-features = false }
# AppKit or UIKit
[target.'cfg(target_vendor = "apple")'.dependencies]
block2 = "0.6.0"
core-foundation = "0.9.3"
dispatch2 = { version = "0.2.0", default-features = false, features = ["std", "objc2"] }
objc2 = "0.6.0"
objc2-core-foundation = { version = "0.3.0", default-features = false, features = [
"std",
"CFCGTypes",
] }

# AppKit
[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.23.1"
objc2-app-kit = { version = "0.3.0", default-features = false, features = [
"std",
"objc2-core-foundation",
Expand Down Expand Up @@ -148,6 +142,33 @@ objc2-app-kit = { version = "0.3.0", default-features = false, features = [
"NSWindowScripting",
"NSWindowTabGroup",
] }
objc2-core-foundation = { version = "0.3.0", default-features = false, features = [
"std",
"block2",
"CFBase",
"CFCGTypes",
"CFData",
"CFRunLoop",
"CFString",
"CFUUID",
] }
objc2-core-graphics = { version = "0.3.0", default-features = false, features = [
"std",
"libc",
"CGDirectDisplay",
"CGDisplayConfiguration",
"CGDisplayFade",
"CGError",
"CGRemoteOperation",
"CGWindowLevel",
] }
objc2-core-video = { version = "0.3.0", default-features = false, features = [
"std",
"objc2-core-graphics",
"CVBase",
"CVReturn",
"CVDisplayLink",
] }
objc2-foundation = { version = "0.3.0", default-features = false, features = [
"std",
"block2",
Expand All @@ -173,6 +194,13 @@ objc2-foundation = { version = "0.3.0", default-features = false, features = [

# UIKit
[target.'cfg(all(target_vendor = "apple", not(target_os = "macos")))'.dependencies]
objc2-core-foundation = { version = "0.3.0", default-features = false, features = [
"std",
"CFCGTypes",
"CFBase",
"CFRunLoop",
"CFString",
] }
objc2-foundation = { version = "0.3.0", default-features = false, features = [
"std",
"block2",
Expand Down
42 changes: 18 additions & 24 deletions src/platform_impl/apple/appkit/event.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::ffi::c_void;
use std::ptr::NonNull;

use core_foundation::base::CFRelease;
use core_foundation::data::{CFDataGetBytePtr, CFDataRef};
use dispatch2::run_on_main;
use objc2::rc::Retained;
use objc2_app_kit::{NSEvent, NSEventModifierFlags, NSEventSubtype, NSEventType};
use objc2_core_foundation::{CFData, CFDataGetBytePtr, CFRetained};
use objc2_foundation::NSPoint;
use smol_str::SmolStr;

Expand All @@ -23,29 +22,27 @@ pub struct KeyEventExtra {

/// Ignores ALL modifiers.
pub fn get_modifierless_char(scancode: u16) -> Key {
let mut string = [0; 16];
let input_source;
let layout;
unsafe {
input_source = ffi::TISCopyCurrentKeyboardLayoutInputSource();
if input_source.is_null() {
tracing::error!("`TISCopyCurrentKeyboardLayoutInputSource` returned null ptr");
return Key::Unidentified(NativeKey::MacOS(scancode));
}
let layout_data =
ffi::TISGetInputSourceProperty(input_source, ffi::kTISPropertyUnicodeKeyLayoutData);
if layout_data.is_null() {
CFRelease(input_source as *mut c_void);
tracing::error!("`TISGetInputSourceProperty` returned null ptr");
return Key::Unidentified(NativeKey::MacOS(scancode));
}
layout = CFDataGetBytePtr(layout_data as CFDataRef) as *const ffi::UCKeyboardLayout;
}
let Some(ptr) = NonNull::new(unsafe { ffi::TISCopyCurrentKeyboardLayoutInputSource() }) else {
tracing::error!("`TISCopyCurrentKeyboardLayoutInputSource` returned null ptr");
return Key::Unidentified(NativeKey::MacOS(scancode));
};
let input_source = unsafe { CFRetained::from_raw(ptr) };

let layout_data = unsafe {
ffi::TISGetInputSourceProperty(&input_source, ffi::kTISPropertyUnicodeKeyLayoutData)
};
let Some(layout_data) = (unsafe { layout_data.cast::<CFData>().as_ref() }) else {
tracing::error!("`TISGetInputSourceProperty` returned null ptr");
return Key::Unidentified(NativeKey::MacOS(scancode));
};

let layout = unsafe { CFDataGetBytePtr(layout_data).cast() };
let keyboard_type = run_on_main(|_mtm| unsafe { ffi::LMGetKbdType() });

let mut result_len = 0;
let mut dead_keys = 0;
let modifiers = 0;
let mut string = [0; 16];
let translate_result = unsafe {
ffi::UCKeyTranslate(
layout,
Expand All @@ -60,9 +57,6 @@ pub fn get_modifierless_char(scancode: u16) -> Key {
string.as_mut_ptr(),
)
};
unsafe {
CFRelease(input_source as *mut c_void);
}
if translate_result != 0 {
tracing::error!("`UCKeyTranslate` returned with the non-zero value: {}", translate_result);
return Key::Unidentified(NativeKey::MacOS(scancode));
Expand Down
38 changes: 15 additions & 23 deletions src/platform_impl/apple/appkit/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::sync::Arc;
use std::time::{Duration, Instant};

use core_foundation::base::{CFIndex, CFRelease};
use core_foundation::runloop::{
kCFRunLoopCommonModes, CFRunLoopAddSource, CFRunLoopGetMain, CFRunLoopSourceContext,
CFRunLoopSourceCreate, CFRunLoopSourceRef, CFRunLoopSourceSignal, CFRunLoopWakeUp,
};
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::ProtocolObject;
use objc2::{available, msg_send, ClassType, MainThreadMarker};
use objc2_app_kit::{
NSApplication, NSApplicationActivationPolicy, NSApplicationDidFinishLaunchingNotification,
NSApplicationWillTerminateNotification, NSWindow,
};
use objc2_core_foundation::{
kCFRunLoopCommonModes, CFIndex, CFRetained, CFRunLoopAddSource, CFRunLoopGetMain,
CFRunLoopSource, CFRunLoopSourceContext, CFRunLoopSourceCreate, CFRunLoopSourceSignal,
CFRunLoopWakeUp,
};
use objc2_foundation::{NSNotificationCenter, NSObjectProtocol};
use rwh_06::HasDisplayHandle;

Expand Down Expand Up @@ -437,29 +437,21 @@ pub fn stop_app_on_panic<F: FnOnce() -> R + UnwindSafe, R>(
#[derive(Debug)]
pub struct EventLoopProxy {
pub(crate) wake_up: AtomicBool,
source: CFRunLoopSourceRef,
source: CFRetained<CFRunLoopSource>,
}

unsafe impl Send for EventLoopProxy {}
unsafe impl Sync for EventLoopProxy {}

impl Drop for EventLoopProxy {
fn drop(&mut self) {
unsafe {
CFRelease(self.source as _);
}
}
}

impl EventLoopProxy {
pub(crate) fn new() -> Self {
unsafe {
// just wake up the eventloop
extern "C" fn event_loop_proxy_handler(_: *const c_void) {}
extern "C-unwind" fn event_loop_proxy_handler(_context: *mut c_void) {}

// adding a Source to the main CFRunLoop lets us wake it up and
// process user events through the normal OS EventLoop mechanisms.
let rl = CFRunLoopGetMain();
let rl = CFRunLoopGetMain().unwrap();
let mut context = CFRunLoopSourceContext {
version: 0,
info: ptr::null_mut(),
Expand All @@ -470,11 +462,11 @@ impl EventLoopProxy {
hash: None,
schedule: None,
cancel: None,
perform: event_loop_proxy_handler,
perform: Some(event_loop_proxy_handler),
};
let source = CFRunLoopSourceCreate(ptr::null_mut(), CFIndex::MAX - 1, &mut context);
CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
CFRunLoopWakeUp(rl);
let source = CFRunLoopSourceCreate(None, CFIndex::MAX - 1, &mut context).unwrap();
CFRunLoopAddSource(&rl, Some(&source), kCFRunLoopCommonModes);
CFRunLoopWakeUp(&rl);

EventLoopProxy { wake_up: AtomicBool::new(false), source }
}
Expand All @@ -486,9 +478,9 @@ impl EventLoopProxyProvider for EventLoopProxy {
self.wake_up.store(true, AtomicOrdering::Relaxed);
unsafe {
// Let the main thread know there's a new event.
CFRunLoopSourceSignal(self.source);
let rl = CFRunLoopGetMain();
CFRunLoopWakeUp(rl);
CFRunLoopSourceSignal(&self.source);
let rl = CFRunLoopGetMain().unwrap();
CFRunLoopWakeUp(&rl);
}
}
}
Loading

0 comments on commit 45f4e45

Please sign in to comment.