Skip to content

Commit 39bf895

Browse files
feat(macOS): Add application show and hide methods (#3689)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent 7c0fa1f commit 39bf895

File tree

20 files changed

+394
-46
lines changed

20 files changed

+394
-46
lines changed

.changes/mac-app-hide-allowlist.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-utils": minor
3+
---
4+
5+
Added the `app` allowlist module.

.changes/mac-app-hide-api.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"api": minor
3+
---
4+
5+
Added `show` and `hide` methods on the `app` module.

.changes/mac-app-hide-runtime.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-runtime-wry": minor
3+
"tauri-runtime": minor
4+
---
5+
6+
Added `Runtime::show()`, `RuntimeHandle::show()`, `Runtime::hide()`, `RuntimeHandle::hide()` for hiding/showing the entire application on macOS.

.changes/mac-app-hide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor
3+
---
4+
5+
Add `App::show()`, `AppHandle::show()`, `App::hide()` and `AppHandle::hide()` for hiding/showing the entire application on macOS.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use webview2_com::FocusChangedEventHandler;
2929
#[cfg(windows)]
3030
use windows::Win32::{Foundation::HWND, System::WinRT::EventRegistrationToken};
3131
#[cfg(target_os = "macos")]
32+
use wry::application::platform::macos::EventLoopWindowTargetExtMacOS;
33+
#[cfg(target_os = "macos")]
3234
use wry::application::platform::macos::WindowBuilderExtMacOS;
3335
#[cfg(target_os = "linux")]
3436
use wry::application::platform::unix::{WindowBuilderExtUnix, WindowExtUnix};
@@ -1021,6 +1023,13 @@ unsafe impl Send for GtkWindow {}
10211023
pub struct RawWindowHandle(pub raw_window_handle::RawWindowHandle);
10221024
unsafe impl Send for RawWindowHandle {}
10231025

1026+
#[cfg(target_os = "macos")]
1027+
#[derive(Debug, Clone)]
1028+
pub enum ApplicationMessage {
1029+
Show,
1030+
Hide,
1031+
}
1032+
10241033
pub enum WindowMessage {
10251034
#[cfg(desktop)]
10261035
WithWebview(Box<dyn FnOnce(Webview) + Send>),
@@ -1126,6 +1135,8 @@ pub type CreateWebviewClosure<T> = Box<
11261135

11271136
pub enum Message<T: 'static> {
11281137
Task(Box<dyn FnOnce() + Send>),
1138+
#[cfg(target_os = "macos")]
1139+
Application(ApplicationMessage),
11291140
Window(WebviewId, WindowMessage),
11301141
Webview(WebviewId, WebviewMessage),
11311142
#[cfg(all(desktop, feature = "system-tray"))]
@@ -1786,6 +1797,22 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
17861797
fn raw_display_handle(&self) -> RawDisplayHandle {
17871798
self.context.main_thread.window_target.raw_display_handle()
17881799
}
1800+
1801+
#[cfg(target_os = "macos")]
1802+
fn show(&self) -> tauri_runtime::Result<()> {
1803+
send_user_message(
1804+
&self.context,
1805+
Message::Application(ApplicationMessage::Show),
1806+
)
1807+
}
1808+
1809+
#[cfg(target_os = "macos")]
1810+
fn hide(&self) -> tauri_runtime::Result<()> {
1811+
send_user_message(
1812+
&self.context,
1813+
Message::Application(ApplicationMessage::Hide),
1814+
)
1815+
}
17891816
}
17901817

17911818
impl<T: UserEvent> Wry<T> {
@@ -1995,6 +2022,16 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
19952022
});
19962023
}
19972024

2025+
#[cfg(target_os = "macos")]
2026+
fn show(&self) {
2027+
self.event_loop.show_application();
2028+
}
2029+
2030+
#[cfg(target_os = "macos")]
2031+
fn hide(&self) {
2032+
self.event_loop.hide_application();
2033+
}
2034+
19982035
#[cfg(desktop)]
19992036
fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
20002037
use wry::application::platform::run_return::EventLoopExtRunReturn;
@@ -2185,6 +2222,15 @@ fn handle_user_message<T: UserEvent>(
21852222
} = context;
21862223
match message {
21872224
Message::Task(task) => task(),
2225+
#[cfg(target_os = "macos")]
2226+
Message::Application(application_message) => match application_message {
2227+
ApplicationMessage::Show => {
2228+
event_loop.show_application();
2229+
}
2230+
ApplicationMessage::Hide => {
2231+
event_loop.hide_application();
2232+
}
2233+
},
21882234
Message::Window(id, window_message) => {
21892235
if let WindowMessage::UpdateMenuItem(item_id, update) = window_message {
21902236
if let Some(menu_items) = windows.borrow_mut().get_mut(&id).map(|w| &mut w.menu_items) {

core/tauri-runtime/src/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,16 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
352352
) -> Result<<Self::Runtime as Runtime<T>>::TrayHandler>;
353353

354354
fn raw_display_handle(&self) -> RawDisplayHandle;
355+
356+
/// Shows the application, but does not automatically focus it.
357+
#[cfg(target_os = "macos")]
358+
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
359+
fn show(&self) -> Result<()>;
360+
361+
/// Hides the application.
362+
#[cfg(target_os = "macos")]
363+
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
364+
fn hide(&self) -> Result<()>;
355365
}
356366

357367
/// A global shortcut manager.
@@ -441,6 +451,16 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
441451
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
442452
fn set_activation_policy(&mut self, activation_policy: ActivationPolicy);
443453

454+
/// Shows the application, but does not automatically focus it.
455+
#[cfg(target_os = "macos")]
456+
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
457+
fn show(&self);
458+
459+
/// Hides the application.
460+
#[cfg(target_os = "macos")]
461+
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
462+
fn hide(&self);
463+
444464
/// Runs the one step of the webview runtime event loop and returns control flow to the caller.
445465
#[cfg(desktop)]
446466
fn run_iteration<F: Fn(RunEvent<T>) + 'static>(&mut self, callback: F) -> RunIteration;

core/tauri-utils/src/config.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,46 @@ impl Allowlist for ClipboardAllowlistConfig {
20092009
}
20102010
}
20112011

2012+
/// Allowlist for the app APIs.
2013+
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
2014+
#[cfg_attr(feature = "schema", derive(JsonSchema))]
2015+
#[serde(rename_all = "camelCase", deny_unknown_fields)]
2016+
pub struct AppAllowlistConfig {
2017+
/// Use this flag to enable all app APIs.
2018+
#[serde(default)]
2019+
pub all: bool,
2020+
/// Enables the app's `show` API.
2021+
#[serde(default)]
2022+
pub show: bool,
2023+
/// Enables the app's `hide` API.
2024+
#[serde(default)]
2025+
pub hide: bool,
2026+
}
2027+
2028+
impl Allowlist for AppAllowlistConfig {
2029+
fn all_features() -> Vec<&'static str> {
2030+
let allowlist = Self {
2031+
all: false,
2032+
show: true,
2033+
hide: true,
2034+
};
2035+
let mut features = allowlist.to_features();
2036+
features.push("app-all");
2037+
features
2038+
}
2039+
2040+
fn to_features(&self) -> Vec<&'static str> {
2041+
if self.all {
2042+
vec!["app-all"]
2043+
} else {
2044+
let mut features = Vec::new();
2045+
check_feature!(self, features, show, "app-show");
2046+
check_feature!(self, features, hide, "app-hide");
2047+
features
2048+
}
2049+
}
2050+
}
2051+
20122052
/// Allowlist configuration.
20132053
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
20142054
#[cfg_attr(feature = "schema", derive(JsonSchema))]
@@ -2053,6 +2093,9 @@ pub struct AllowlistConfig {
20532093
/// Clipboard APIs allowlist.
20542094
#[serde(default)]
20552095
pub clipboard: ClipboardAllowlistConfig,
2096+
/// App APIs allowlist.
2097+
#[serde(default)]
2098+
pub app: AppAllowlistConfig,
20562099
}
20572100

20582101
impl Allowlist for AllowlistConfig {
@@ -2070,6 +2113,7 @@ impl Allowlist for AllowlistConfig {
20702113
features.extend(ProtocolAllowlistConfig::all_features());
20712114
features.extend(ProcessAllowlistConfig::all_features());
20722115
features.extend(ClipboardAllowlistConfig::all_features());
2116+
features.extend(AppAllowlistConfig::all_features());
20732117
features
20742118
}
20752119

core/tauri/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ api-all = [
176176
"process-all",
177177
"protocol-all",
178178
"shell-all",
179-
"window-all"
179+
"window-all",
180+
"app-all"
180181
]
181182
clipboard-all = [ "clipboard-write-text", "clipboard-read-text" ]
182183
clipboard-read-text = [ "clipboard" ]
@@ -283,6 +284,9 @@ window-set-cursor-position = [ ]
283284
window-set-ignore-cursor-events = [ ]
284285
window-start-dragging = [ ]
285286
window-print = [ ]
287+
app-all = [ "app-show", "app-hide" ]
288+
app-show = [ ]
289+
app-hide = [ ]
286290
config-json5 = [ "tauri-macros/config-json5" ]
287291
config-toml = [ "tauri-macros/config-toml" ]
288292
icon-ico = [ "infer", "ico" ]

core/tauri/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ fn main() {
131131

132132
alias_module("clipboard", &["write-text", "read-text"], api_all);
133133

134+
alias_module("app", &["show", "hide"], api_all);
135+
134136
let checked_features_out_path =
135137
Path::new(&std::env::var("OUT_DIR").unwrap()).join("checked_features");
136138
std::fs::write(

core/tauri/scripts/bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)