Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch 0.28.6 release #10

Merged
merged 4 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust_version: ['1.60.0', stable, nightly]
rust_version: ['1.64.0', stable, nightly]
platform:
# Note: Make sure that we test all the `docs.rs` targets defined in Cargo.toml!
- { target: x86_64-pc-windows-msvc, os: windows-latest, }
Expand Down
18 changes: 18 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,21 @@ pub enum Event<'a, T: 'static> {
/// This is irreversible - if this event is emitted, it is guaranteed to be the last event that
/// gets emitted. You generally want to treat this as an "do on quit" event.
LoopDestroyed,

/// 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: Clone> Clone for Event<'static, T> {
Expand All @@ -251,6 +266,7 @@ impl<T: Clone> Clone for Event<'static, T> {
LoopDestroyed => LoopDestroyed,
Suspended => Suspended,
Resumed => Resumed,
PlatformSpecific(event) => PlatformSpecific(event.clone()),
}
}
}
Expand All @@ -269,6 +285,7 @@ impl<'a, T> Event<'a, T> {
LoopDestroyed => Ok(LoopDestroyed),
Suspended => Ok(Suspended),
Resumed => Ok(Resumed),
PlatformSpecific(event) => Ok(PlatformSpecific(event)),
}
}

Expand All @@ -289,6 +306,7 @@ impl<'a, T> Event<'a, T> {
LoopDestroyed => Some(LoopDestroyed),
Suspended => Some(Suspended),
Resumed => Some(Resumed),
PlatformSpecific(event) => Some(PlatformSpecific(event)),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ impl<T> EventLoopWindowTarget<T> {
/// Returns the list of all the monitors available on the system.
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
#[allow(clippy::useless_conversion)]
self.p
.available_monitors()
.into_iter()
Expand Down
59 changes: 59 additions & 0 deletions src/platform_impl/macos/app_delegate.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::runtime::Object;
use objc2::{class, sel};
use objc2::{declare_class, msg_send, msg_send_id, ClassType};

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

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

/// 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)]
Expand Down Expand Up @@ -46,6 +58,31 @@ declare_class!(
);
}

#[sel(applicationWillFinishLaunching:)]
fn will_finish_launching(&self, _sender: *const Object) {
trace!("Triggered `applicationWillFinishLaunching`");
unsafe {
let event_manager = class!(NSAppleEventManager);
let shared_manager: *mut Object = msg_send![event_manager, sharedAppleEventManager];
let () = msg_send![shared_manager,
setEventHandler: self,
andSelector: sel!(handleEvent:withReplyEvent:)
forEventClass: kInternetEventClass
andEventID: kAEGetURL
];
}
trace!("Completed `applicationWillFinishLaunching`");
}

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

#[sel(applicationWillTerminate:)]
fn will_terminate(&self, _sender: *const Object) {
trace_scope!("applicationWillTerminate:");
Expand All @@ -71,3 +108,25 @@ impl ApplicationDelegate {
}
}
}

fn parse_url(event: *mut Object) -> 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 Object = msg_send![event, paramDescriptorForKeyword: keyDirectObject];
let nsstring: *mut Object = 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
}
}
}
19 changes: 1 addition & 18 deletions src/platform_impl/macos/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,25 +281,8 @@ declare_class!(
proposed_options: NSApplicationPresentationOptions,
) -> NSApplicationPresentationOptions {
trace_scope!("window:willUseFullScreenPresentationOptions:");
// Generally, games will want to disable the menu bar and the dock. Ideally,
// this would be configurable by the user. Unfortunately because of our
// `CGShieldingWindowLevel() + 1` hack (see `set_fullscreen`), our window is
// placed on top of the menu bar in exclusive fullscreen mode. This looks
// broken so we always disable the menu bar in exclusive fullscreen. We may
// still want to make this configurable for borderless fullscreen. Right now
// we don't, for consistency. If we do, it should be documented that the
// user-provided options are ignored in exclusive fullscreen.
let mut options = proposed_options;
let shared_state = self
.window
.lock_shared_state("window_will_use_fullscreen_presentation_options");
if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen {
options = NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar;
}

options
proposed_options
}

/// Invoked when entered fullscreen
Expand Down
1 change: 1 addition & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,7 @@ impl Window {
/// [`EventLoopWindowTarget::available_monitors`]: crate::event_loop::EventLoopWindowTarget::available_monitors
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
#[allow(clippy::useless_conversion)]
self.window
.available_monitors()
.into_iter()
Expand Down
Loading