Skip to content

Commit

Permalink
Handle URLs for macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
derezzedex authored and hecrj committed Jan 4, 2024
1 parent 6eb79f0 commit a26208f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,21 @@ pub enum Event<T: 'static> {
///
/// - **macOS / Wayland / Windows / Orbital:** Unsupported.
MemoryWarning,

/// Emitted when the event loop receives an event that only occurs on some specific platform.
PlatformSpecific(PlatformSpecific),
}

/// Describes an event from some specific platform.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PlatformSpecific {
MacOS(MacOS),
}

/// Describes an event that only happens in `MacOS`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MacOS {
ReceivedUrl(String),
}

impl<T> Event<T> {
Expand All @@ -267,6 +282,7 @@ impl<T> Event<T> {
Suspended => Ok(Suspended),
Resumed => Ok(Resumed),
MemoryWarning => Ok(MemoryWarning),
PlatformSpecific(event) => Ok(PlatformSpecific(event)),
}
}
}
Expand Down
61 changes: 60 additions & 1 deletion src/platform_impl/macos/app_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ use icrate::Foundation::NSObject;
use objc2::declare::{IvarBool, IvarEncode};
use objc2::rc::Id;
use objc2::runtime::AnyObject;
use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType};
use objc2::{class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType};

use crate::event::{Event, MacOS, PlatformSpecific};

use super::app_state::AppState;
use super::appkit::NSApplicationActivationPolicy;

/// Apple constants
#[allow(non_upper_case_globals)]
pub const kInternetEventClass: u32 = 0x4755524c;
#[allow(non_upper_case_globals)]
pub const kAEGetURL: u32 = 0x4755524c;
#[allow(non_upper_case_globals)]
pub const keyDirectObject: u32 = 0x2d2d2d2d;

declare_class!(
#[derive(Debug)]
pub(super) struct ApplicationDelegate {
Expand Down Expand Up @@ -52,6 +62,33 @@ declare_class!(
);
}

#[method(applicationWillFinishLaunching:)]
fn will_finish_launching(&self, _sender: Option<&AnyObject>) {
trace_scope!("applicationWillFinishLaunching");

unsafe {
let event_manager = class!(NSAppleEventManager);
let shared_manager: *mut AnyObject =
msg_send![event_manager, sharedAppleEventManager];

let () = msg_send![shared_manager,
setEventHandler: self
andSelector: sel!(handleEvent:withReplyEvent:)
forEventClass: kInternetEventClass
andEventID: kAEGetURL
];
}
}

#[method(handleEvent:withReplyEvent:)]
fn handle_url(&self, event: *mut AnyObject, _reply: u64) {
if let Some(string) = parse_url(event) {
AppState::queue_event(Event::PlatformSpecific(PlatformSpecific::MacOS(
MacOS::ReceivedUrl(string),
)));
}
}

#[method(applicationWillTerminate:)]
fn will_terminate(&self, _sender: Option<&AnyObject>) {
trace_scope!("applicationWillTerminate:");
Expand All @@ -77,3 +114,25 @@ impl ApplicationDelegate {
}
}
}

fn parse_url(event: *mut AnyObject) -> Option<String> {
unsafe {
let class: u32 = msg_send![event, eventClass];
let id: u32 = msg_send![event, eventID];
if class != kInternetEventClass || id != kAEGetURL {
return None;
}
let subevent: *mut AnyObject = msg_send![event, paramDescriptorForKeyword: keyDirectObject];
let nsstring: *mut AnyObject = msg_send![subevent, stringValue];
let cstr: *const i8 = msg_send![nsstring, UTF8String];
if !cstr.is_null() {
Some(
std::ffi::CStr::from_ptr(cstr)
.to_string_lossy()
.into_owned(),
)
} else {
None
}
}
}

0 comments on commit a26208f

Please sign in to comment.