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

feat(macOS): Add application show and hide methods #3689

Merged
merged 24 commits into from Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6a9345e
feat(macOS): Add `AppHandle::hide()`
probablykasper Oct 30, 2021
ba684a7
make macOS-only
probablykasper Oct 30, 2021
8101fa5
remove unnecessary mutability
probablykasper Oct 30, 2021
151899b
Merge branch 'next' into mac-app-hide
probablykasper Dec 6, 2021
7414f2c
Add `Apphandle::show()`
probablykasper Dec 7, 2021
03f0164
cargo fmt
probablykasper Dec 7, 2021
271f778
Merge branch 'tauri-apps:next' into mac-app-hide
probablykasper Dec 10, 2021
5d6f0d2
cargo update updater example
probablykasper Dec 11, 2021
567e625
Merge branch 'next' into mac-app-hide
probablykasper Dec 30, 2021
354acfb
Merge branch 'dev' into pr/2825
probablykasper Feb 13, 2022
2358923
Merge branch 'dev' into pr/2825
probablykasper Feb 19, 2022
0dffd05
Merge branch 'dev' into pr/2825
probablykasper Mar 12, 2022
6109a66
Merge branch 'dev' into mac-app-hide
probablykasper May 24, 2022
f690df9
Revert unrelated change
probablykasper May 24, 2022
98d26d0
Fix derive incorrectly added
probablykasper May 24, 2022
ade64c9
Mock runtime impls
probablykasper May 24, 2022
8a41e8b
Merge branch 'dev' into mac-app-hide
probablykasper Jun 19, 2022
c2ea19f
Merge remote-tracking branch 'origin/dev' into mac-app-hide
lucasfernog Oct 3, 2022
01b9646
feat: add to API
lucasfernog Oct 3, 2022
f338b99
also expose it on App struct
lucasfernog Oct 3, 2022
404c859
add change files
lucasfernog Oct 3, 2022
8e72691
fix tests
lucasfernog Oct 3, 2022
1c0f4de
fix conditional compilation
lucasfernog Oct 3, 2022
d3109d0
update schema [skip ci]
lucasfernog Oct 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/mac-app-hide-allowlist.md
@@ -0,0 +1,5 @@
---
"tauri-utils": minor
---

Added the `app` allowlist module.
5 changes: 5 additions & 0 deletions .changes/mac-app-hide-api.md
@@ -0,0 +1,5 @@
---
"api": minor
---

Added `show` and `hide` methods on the `app` module.
6 changes: 6 additions & 0 deletions .changes/mac-app-hide-runtime.md
@@ -0,0 +1,6 @@
---
"tauri-runtime-wry": minor
"tauri-runtime": minor
---

Added `Runtime::show()`, `RuntimeHandle::show()`, `Runtime::hide()`, `RuntimeHandle::hide()` for hiding/showing the entire application on macOS.
5 changes: 5 additions & 0 deletions .changes/mac-app-hide.md
@@ -0,0 +1,5 @@
---
"tauri": minor
---

Add `App::show()`, `AppHandle::show()`, `App::hide()` and `AppHandle::hide()` for hiding/showing the entire application on macOS.
46 changes: 46 additions & 0 deletions core/tauri-runtime-wry/src/lib.rs
Expand Up @@ -29,6 +29,8 @@ use webview2_com::FocusChangedEventHandler;
#[cfg(windows)]
use windows::Win32::{Foundation::HWND, System::WinRT::EventRegistrationToken};
#[cfg(target_os = "macos")]
use wry::application::platform::macos::EventLoopWindowTargetExtMacOS;
#[cfg(target_os = "macos")]
use wry::application::platform::macos::WindowBuilderExtMacOS;
#[cfg(target_os = "linux")]
use wry::application::platform::unix::{WindowBuilderExtUnix, WindowExtUnix};
Expand Down Expand Up @@ -1021,6 +1023,13 @@ unsafe impl Send for GtkWindow {}
pub struct RawWindowHandle(pub raw_window_handle::RawWindowHandle);
unsafe impl Send for RawWindowHandle {}

#[cfg(target_os = "macos")]
#[derive(Debug, Clone)]
pub enum ApplicationMessage {
Show,
Hide,
}

pub enum WindowMessage {
#[cfg(desktop)]
WithWebview(Box<dyn FnOnce(Webview) + Send>),
Expand Down Expand Up @@ -1126,6 +1135,8 @@ pub type CreateWebviewClosure<T> = Box<

pub enum Message<T: 'static> {
Task(Box<dyn FnOnce() + Send>),
#[cfg(target_os = "macos")]
Application(ApplicationMessage),
Window(WebviewId, WindowMessage),
Webview(WebviewId, WebviewMessage),
#[cfg(all(desktop, feature = "system-tray"))]
Expand Down Expand Up @@ -1786,6 +1797,22 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
fn raw_display_handle(&self) -> RawDisplayHandle {
self.context.main_thread.window_target.raw_display_handle()
}

#[cfg(target_os = "macos")]
fn show(&self) -> tauri_runtime::Result<()> {
send_user_message(
&self.context,
Message::Application(ApplicationMessage::Show),
)
}

#[cfg(target_os = "macos")]
fn hide(&self) -> tauri_runtime::Result<()> {
send_user_message(
&self.context,
Message::Application(ApplicationMessage::Hide),
)
}
}

impl<T: UserEvent> Wry<T> {
Expand Down Expand Up @@ -1995,6 +2022,16 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
});
}

#[cfg(target_os = "macos")]
fn show(&self) {
self.event_loop.show_application();
}

#[cfg(target_os = "macos")]
fn hide(&self) {
self.event_loop.hide_application();
}

#[cfg(desktop)]
fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
use wry::application::platform::run_return::EventLoopExtRunReturn;
Expand Down Expand Up @@ -2185,6 +2222,15 @@ fn handle_user_message<T: UserEvent>(
} = context;
match message {
Message::Task(task) => task(),
#[cfg(target_os = "macos")]
Message::Application(application_message) => match application_message {
ApplicationMessage::Show => {
event_loop.show_application();
}
ApplicationMessage::Hide => {
event_loop.hide_application();
}
},
Message::Window(id, window_message) => {
if let WindowMessage::UpdateMenuItem(item_id, update) = window_message {
if let Some(menu_items) = windows.borrow_mut().get_mut(&id).map(|w| &mut w.menu_items) {
Expand Down
20 changes: 20 additions & 0 deletions core/tauri-runtime/src/lib.rs
Expand Up @@ -352,6 +352,16 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
) -> Result<<Self::Runtime as Runtime<T>>::TrayHandler>;

fn raw_display_handle(&self) -> RawDisplayHandle;

/// Shows the application, but does not automatically focus it.
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn show(&self) -> Result<()>;

/// Hides the application.
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn hide(&self) -> Result<()>;
}

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

/// Shows the application, but does not automatically focus it.
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn show(&self);

/// Hides the application.
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn hide(&self);

/// Runs the one step of the webview runtime event loop and returns control flow to the caller.
#[cfg(desktop)]
fn run_iteration<F: Fn(RunEvent<T>) + 'static>(&mut self, callback: F) -> RunIteration;
Expand Down
44 changes: 44 additions & 0 deletions core/tauri-utils/src/config.rs
Expand Up @@ -2009,6 +2009,46 @@ impl Allowlist for ClipboardAllowlistConfig {
}
}

/// Allowlist for the app APIs.
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct AppAllowlistConfig {
/// Use this flag to enable all app APIs.
#[serde(default)]
pub all: bool,
/// Enables the app's `show` API.
#[serde(default)]
pub show: bool,
/// Enables the app's `hide` API.
#[serde(default)]
pub hide: bool,
}

impl Allowlist for AppAllowlistConfig {
fn all_features() -> Vec<&'static str> {
let allowlist = Self {
all: false,
show: true,
hide: true,
};
let mut features = allowlist.to_features();
features.push("app-all");
features
}

fn to_features(&self) -> Vec<&'static str> {
if self.all {
vec!["app-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, show, "app-show");
check_feature!(self, features, hide, "app-hide");
features
}
}
}

/// Allowlist configuration.
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
Expand Down Expand Up @@ -2053,6 +2093,9 @@ pub struct AllowlistConfig {
/// Clipboard APIs allowlist.
#[serde(default)]
pub clipboard: ClipboardAllowlistConfig,
/// App APIs allowlist.
#[serde(default)]
pub app: AppAllowlistConfig,
}

impl Allowlist for AllowlistConfig {
Expand All @@ -2070,6 +2113,7 @@ impl Allowlist for AllowlistConfig {
features.extend(ProtocolAllowlistConfig::all_features());
features.extend(ProcessAllowlistConfig::all_features());
features.extend(ClipboardAllowlistConfig::all_features());
features.extend(AppAllowlistConfig::all_features());
features
}

Expand Down
6 changes: 5 additions & 1 deletion core/tauri/Cargo.toml
Expand Up @@ -176,7 +176,8 @@ api-all = [
"process-all",
"protocol-all",
"shell-all",
"window-all"
"window-all",
"app-all"
]
clipboard-all = [ "clipboard-write-text", "clipboard-read-text" ]
clipboard-read-text = [ "clipboard" ]
Expand Down Expand Up @@ -283,6 +284,9 @@ window-set-cursor-position = [ ]
window-set-ignore-cursor-events = [ ]
window-start-dragging = [ ]
window-print = [ ]
app-all = [ "app-show", "app-hide" ]
app-show = [ ]
app-hide = [ ]
config-json5 = [ "tauri-macros/config-json5" ]
config-toml = [ "tauri-macros/config-toml" ]
icon-ico = [ "infer", "ico" ]
Expand Down
2 changes: 2 additions & 0 deletions core/tauri/build.rs
Expand Up @@ -131,6 +131,8 @@ fn main() {

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

alias_module("app", &["show", "hide"], api_all);

let checked_features_out_path =
Path::new(&std::env::var("OUT_DIR").unwrap()).join("checked_features");
std::fs::write(
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions core/tauri/src/app.rs
Expand Up @@ -734,6 +734,28 @@ macro_rules! shared_app_impl {
manager: self.manager.clone(),
}
}

/// Shows the application, but does not automatically focus it.
#[cfg(target_os = "macos")]
pub fn show(&self) -> crate::Result<()> {
match self.runtime() {
RuntimeOrDispatch::Runtime(r) => r.show(),
RuntimeOrDispatch::RuntimeHandle(h) => h.show()?,
_ => unreachable!(),
}
Ok(())
}

/// Hides the application.
#[cfg(target_os = "macos")]
pub fn hide(&self) -> crate::Result<()> {
match self.runtime() {
RuntimeOrDispatch::Runtime(r) => r.hide(),
RuntimeOrDispatch::RuntimeHandle(h) => h.hide()?,
_ => unreachable!(),
}
Ok(())
}
}
};
}
Expand Down
24 changes: 23 additions & 1 deletion core/tauri/src/endpoints/app.rs
Expand Up @@ -5,7 +5,7 @@
use super::InvokeContext;
use crate::Runtime;
use serde::Deserialize;
use tauri_macros::{command_enum, CommandModule};
use tauri_macros::{command_enum, module_command_handler, CommandModule};

/// The API descriptor.
#[command_enum]
Expand All @@ -19,6 +19,12 @@ pub enum Cmd {
GetAppName,
/// Get Tauri Version
GetTauriVersion,
/// Shows the application on macOS.
#[cmd(app_show, "app > show")]
Show,
/// Hides the application on macOS.
#[cmd(app_hide, "app > hide")]
Hide,
}

impl Cmd {
Expand All @@ -33,4 +39,20 @@ impl Cmd {
fn get_tauri_version<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
Ok(env!("CARGO_PKG_VERSION"))
}

#[module_command_handler(app_show)]
#[allow(unused_variables)]
fn show<R: Runtime>(context: InvokeContext<R>) -> super::Result<()> {
#[cfg(target_os = "macos")]
context.window.app_handle.show()?;
Ok(())
}

#[module_command_handler(app_hide)]
#[allow(unused_variables)]
fn hide<R: Runtime>(context: InvokeContext<R>) -> super::Result<()> {
#[cfg(target_os = "macos")]
context.window.app_handle.hide()?;
Ok(())
}
}
6 changes: 6 additions & 0 deletions core/tauri/src/lib.rs
Expand Up @@ -148,6 +148,12 @@
//! - **window-set-ignore-cursor-events**: Enables the [`setIgnoreCursorEvents` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setignorecursorevents).
//! - **window-start-dragging**: Enables the [`startDragging` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#startdragging).
//! - **window-print**: Enables the [`print` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#print).
//!
//! ### App allowlist
//!
//! - **app-all**: Enables all [App APIs](https://tauri.app/en/docs/api/js/modules/app).
//! - **app-show**: Enables the [`show` API](https://tauri.app/en/docs/api/js/modules/app#show).
//! - **app-hide**: Enables the [`hide` API](https://tauri.app/en/docs/api/js/modules/app#hide).

#![warn(missing_docs, rust_2018_idioms)]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
Expand Down
20 changes: 20 additions & 0 deletions core/tauri/src/test/mock_runtime.rs
Expand Up @@ -94,6 +94,18 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
unimplemented!()
}

/// Shows the application, but does not automatically focus it.
#[cfg(target_os = "macos")]
fn show(&self) -> Result<()> {
Ok(())
}

/// Hides the application.
#[cfg(target_os = "macos")]
fn hide(&self) -> Result<()> {
Ok(())
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -670,6 +682,14 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}

#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn show(&self) {}

#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn hide(&self) {}

#[cfg(any(
target_os = "macos",
windows,
Expand Down
2 changes: 1 addition & 1 deletion examples/api/dist/assets/index.css

Large diffs are not rendered by default.