diff --git a/src/event.rs b/src/event.rs index 0412c98b01..37e033f2f7 100644 --- a/src/event.rs +++ b/src/event.rs @@ -58,6 +58,13 @@ pub enum Event<'a, T: 'static> { /// [`ControlFlow::WaitUntil`](crate::event_loop::ControlFlow::WaitUntil) has elapsed. NewEvents(StartCause), + /// Emitted if a user has requested to open an application specific URL that is registered with the OS + /// + /// # Portability + /// + /// This event is only ever delivered on MacOS currently + OpenURL { url: String }, + /// Emitted when the OS sends an event to a winit window. WindowEvent { window_id: WindowId, @@ -235,6 +242,7 @@ impl Clone for Event<'static, T> { fn clone(&self) -> Self { use self::Event::*; match self { + OpenURL { url } => OpenURL { url: url.clone() }, WindowEvent { window_id, event } => WindowEvent { window_id: *window_id, event: event.clone(), @@ -260,6 +268,7 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { UserEvent(_) => Err(self), + OpenURL { url } => Ok(OpenURL { url }), WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }), DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }), NewEvents(cause) => Ok(NewEvents(cause)), @@ -277,6 +286,7 @@ impl<'a, T> Event<'a, T> { pub fn to_static(self) -> Option> { use self::Event::*; match self { + OpenURL { url } => Some(OpenURL { url }), WindowEvent { window_id, event } => event .to_static() .map(|event| WindowEvent { window_id, event }), diff --git a/src/platform_impl/macos/app_delegate.rs b/src/platform_impl/macos/app_delegate.rs index 0c9eff1747..f98d387089 100644 --- a/src/platform_impl/macos/app_delegate.rs +++ b/src/platform_impl/macos/app_delegate.rs @@ -1,10 +1,32 @@ -use objc2::foundation::NSObject; +use objc2::foundation::{NSArray, NSObject, NSString}; use objc2::rc::{Id, Shared}; use objc2::runtime::Object; -use objc2::{declare_class, msg_send, msg_send_id, ClassType}; +use objc2::{declare_class, extern_class, extern_methods, msg_send, msg_send_id, ClassType}; + +use crate::event::Event; use super::app_state::AppState; use super::appkit::NSApplicationActivationPolicy; +use super::event::EventWrapper; + +extern_class!( + #[derive(Debug)] + struct NSURL; + unsafe impl ClassType for NSURL { + type Super = NSObject; + } +); + +unsafe impl Send for NSURL {} +unsafe impl Sync for NSURL {} + +extern_methods!( + unsafe impl NSURL { + pub fn absolute_string(&self) -> Option> { + unsafe { msg_send_id![self, absoluteString] } + } + } +); declare_class!( #[derive(Debug)] @@ -52,6 +74,17 @@ declare_class!( // TODO: Notify every window that it will be destroyed, like done in iOS? AppState::exit(); } + + #[sel(application:openURLs:)] + fn application_open_urls(&self, _application: &NSObject, urls: &NSArray) { + for url in urls { + if let Some(url) = url.absolute_string() { + AppState::queue_event(EventWrapper::StaticEvent(Event::OpenURL { + url: url.to_string(), + })); + } + } + } } ); diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 728f63a5df..644fcd0a22 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -4,8 +4,8 @@ use std::{boxed::Box, os::raw::*, ptr, str, sync::Mutex}; use objc2::declare::{Ivar, IvarDrop}; use objc2::foundation::{ - NSArray, NSAttributedString, NSAttributedStringKey, NSCopying, - NSMutableAttributedString, NSObject, NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger, + NSArray, NSAttributedString, NSAttributedStringKey, NSCopying, NSMutableAttributedString, + NSObject, NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger, }; use objc2::rc::{Id, Owned, Shared, WeakId}; use objc2::runtime::{Object, Sel};