fix(core): macos #5122 app.runtime panic in app.set_activation_policy (#8713)

* fix #5122 app.runtime panic in set_activation_policy

* allow setting the policy at runtime

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Jingyu 2024-02-02 20:40:10 +08:00 committed by GitHub
parent a35b416e38
commit 95da1a2747
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 56 additions and 15 deletions

View File

@ -0,0 +1,7 @@
---
"tauri": patch:bug
"tauri-runtime": patch:bug
"tauri-runtime-wry": patch:bug
---
Fix calling `set_activation_policy` when the event loop is running.

View File

@ -26,9 +26,7 @@ use tauri_runtime::{
};
#[cfg(target_os = "macos")]
use tao::platform::macos::EventLoopWindowTargetExtMacOS;
#[cfg(target_os = "macos")]
use tao::platform::macos::WindowBuilderExtMacOS;
use tao::platform::macos::{EventLoopWindowTargetExtMacOS, WindowBuilderExtMacOS};
#[cfg(target_os = "linux")]
use tao::platform::unix::{WindowBuilderExtUnix, WindowExtUnix};
#[cfg(windows)]
@ -431,6 +429,16 @@ pub fn map_theme(theme: &TaoTheme) -> Theme {
}
}
#[cfg(target_os = "macos")]
fn tao_activation_policy(activation_policy: ActivationPolicy) -> TaoActivationPolicy {
match activation_policy {
ActivationPolicy::Regular => TaoActivationPolicy::Regular,
ActivationPolicy::Accessory => TaoActivationPolicy::Accessory,
ActivationPolicy::Prohibited => TaoActivationPolicy::Prohibited,
_ => unimplemented!(),
}
}
impl<'a> From<&TaoWindowEvent<'a>> for WindowEventWrapper {
fn from(event: &TaoWindowEvent<'a>) -> Self {
let event = match event {
@ -1201,6 +1209,8 @@ pub type CreateWebviewClosure = Box<dyn FnOnce(&Window) -> Result<WebviewWrapper
pub enum Message<T: 'static> {
Task(Box<dyn FnOnce() + Send>),
#[cfg(target_os = "macos")]
SetActivationPolicy(ActivationPolicy),
RequestExit(i32),
#[cfg(target_os = "macos")]
Application(ApplicationMessage),
@ -1995,6 +2005,14 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
EventProxy(self.context.proxy.clone())
}
#[cfg(target_os = "macos")]
fn set_activation_policy(&self, activation_policy: ActivationPolicy) -> Result<()> {
send_user_message(
&self.context,
Message::SetActivationPolicy(activation_policy),
)
}
fn request_exit(&self, code: i32) -> Result<()> {
// NOTE: request_exit cannot use the `send_user_message` function because it accesses the event loop callback
self
@ -2296,12 +2314,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {
self
.event_loop
.set_activation_policy(match activation_policy {
ActivationPolicy::Regular => TaoActivationPolicy::Regular,
ActivationPolicy::Accessory => TaoActivationPolicy::Accessory,
ActivationPolicy::Prohibited => TaoActivationPolicy::Prohibited,
_ => unimplemented!(),
});
.set_activation_policy(tao_activation_policy(activation_policy));
}
#[cfg(target_os = "macos")]
@ -2446,6 +2459,10 @@ fn handle_user_message<T: UserEvent>(
} = context;
match message {
Message::Task(task) => task(),
#[cfg(target_os = "macos")]
Message::SetActivationPolicy(activation_policy) => {
event_loop.set_activation_policy_at_runtime(tao_activation_policy(activation_policy))
}
Message::RequestExit(_code) => panic!("cannot handle RequestExit on the main thread"),
#[cfg(target_os = "macos")]
Message::Application(application_message) => match application_message {

View File

@ -208,6 +208,11 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
/// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop.
fn create_proxy(&self) -> <Self::Runtime as Runtime<T>>::EventLoopProxy;
/// Sets the activation policy for the application.
#[cfg(target_os = "macos")]
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
fn set_activation_policy(&self, activation_policy: ActivationPolicy) -> Result<()>;
/// Requests an exit of the event loop.
fn request_exit(&self, code: i32) -> Result<()>;
@ -313,7 +318,7 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
fn primary_monitor(&self) -> Option<Monitor>;
fn available_monitors(&self) -> Vec<Monitor>;
/// Sets the activation policy for the application. It is set to `NSApplicationActivationPolicyRegular` by default.
/// Sets the activation policy for the application.
#[cfg(target_os = "macos")]
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
fn set_activation_policy(&mut self, activation_policy: ActivationPolicy);

View File

@ -876,11 +876,14 @@ impl<R: Runtime> App<R> {
#[cfg(target_os = "macos")]
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
pub fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {
self
.runtime
.as_mut()
.unwrap()
.set_activation_policy(activation_policy);
if let Some(runtime) = self.runtime.as_mut() {
runtime.set_activation_policy(activation_policy);
} else {
let _ = self
.app_handle()
.runtime_handle
.set_activation_policy(activation_policy);
}
}
/// Change the device event filter mode.

View File

@ -120,6 +120,15 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
EventProxy {}
}
#[cfg(target_os = "macos")]
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
fn set_activation_policy(
&self,
activation_policy: tauri_runtime::ActivationPolicy,
) -> Result<()> {
Ok(())
}
fn request_exit(&self, code: i32) -> Result<()> {
unimplemented!()
}