From 52f257bf4231a279edfdc4155fccbcf5b2c82fd3 Mon Sep 17 00:00:00 2001 From: Manmeet Maan <49202620+Maan2003@users.noreply.github.com> Date: Thu, 8 Jul 2021 07:05:20 +0530 Subject: [PATCH] Move Application:: hide_application, hide_others and set_menu to Mac platform extension (#1863) * Add MacApplicationExt * druid changes * Deprecate menu::sys::hide on other platforms * allow deprecated in menu::sys::mac::default() * Update CHANGELOG --- CHANGELOG.md | 2 + druid-shell/src/application.rs | 22 ----------- druid-shell/src/backend/mac/application.rs | 45 +++++++++++----------- druid-shell/src/menu.rs | 2 +- druid-shell/src/platform/mac.rs | 40 +++++++++++++++++++ druid-shell/src/platform/mod.rs | 3 ++ druid/src/command.rs | 12 +++++- druid/src/menu/sys.rs | 11 ++++++ druid/src/win_handler.rs | 12 ++++-- 9 files changed, 98 insertions(+), 51 deletions(-) create mode 100644 druid-shell/src/platform/mac.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 21d3c4e13f..d30bc2f95e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ You can find its changes [documented below](#070---2021-01-01). - Window size and positioning code is now in display points ([#1713] by [@jneem]) - Update look and feel of controls when disabled ([#1717] by [@xarvic]) - Change the signature of `add_idle_callback` ([#1787] by [@jneem]) +- Move macOS only function to Mac extension trait ([#1863] by [@Maan2003]) ### Deprecated @@ -742,6 +743,7 @@ Last release without a changelog :( [#1825]: https://github.com/linebender/druid/pull/1825 [#1843]: https://github.com/linebender/druid/pull/1843 [#1851]: https://github.com/linebender/druid/pull/1851 +[#1863]: https://github.com/linebender/druid/pull/1863 [Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master [0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0 diff --git a/druid-shell/src/application.rs b/druid-shell/src/application.rs index 017abd08b3..dbf48e78ba 100644 --- a/druid-shell/src/application.rs +++ b/druid-shell/src/application.rs @@ -170,28 +170,6 @@ impl Application { self.backend_app.quit() } - // TODO: do these three go in some kind of PlatformExt trait? - /// Hide the application this window belongs to. (cmd+H) - pub fn hide(&self) { - #[cfg(target_os = "macos")] - self.backend_app.hide() - } - - /// Hide all other applications. (cmd+opt+H) - pub fn hide_others(&self) { - #[cfg(target_os = "macos")] - self.backend_app.hide_others() - } - - /// Sets the global application menu, on platforms where there is one. - /// - /// On platforms with no global application menu, this has no effect. - #[allow(unused_variables)] - pub fn set_menu(&self, menu: crate::Menu) { - #[cfg(target_os = "macos")] - self.backend_app.set_menu(menu.into_inner()); - } - /// Returns a handle to the system clipboard. pub fn clipboard(&self) -> Clipboard { self.backend_app.clipboard().into() diff --git a/druid-shell/src/backend/mac/application.rs b/druid-shell/src/backend/mac/application.rs index 8417fc9b7a..bbde4678e9 100644 --- a/druid-shell/src/backend/mac/application.rs +++ b/druid-shell/src/backend/mac/application.rs @@ -32,7 +32,6 @@ use crate::application::AppHandler; use super::clipboard::Clipboard; use super::error::Error; -use super::menu::Menu; use super::util; static APP_HANDLER_IVAR: &str = "druidAppHandler"; @@ -102,28 +101,6 @@ impl Application { } } - /// Hide the application this window belongs to. (cmd+H) - pub fn hide(&self) { - unsafe { - let () = msg_send![self.ns_app, hide: nil]; - } - } - - /// Hide all other applications. (cmd+opt+H) - pub fn hide_others(&self) { - unsafe { - let workspace = class!(NSWorkspace); - let shared: id = msg_send![workspace, sharedWorkspace]; - let () = msg_send![shared, hideOtherApplications]; - } - } - - pub fn set_menu(&self, menu: Menu) { - unsafe { - NSApp().setMainMenu_(menu.menu); - } - } - pub fn clipboard(&self) -> Clipboard { Clipboard } @@ -142,6 +119,28 @@ impl Application { } } +impl crate::platform::mac::MacApplicationExt for crate::Application { + fn hide(&self) { + unsafe { + let () = msg_send![self.backend_app.ns_app, hide: nil]; + } + } + + fn hide_others(&self) { + unsafe { + let workspace = class!(NSWorkspace); + let shared: id = msg_send![workspace, sharedWorkspace]; + let () = msg_send![shared, hideOtherApplications]; + } + } + + fn set_menu(&self, menu: crate::Menu) { + unsafe { + NSApp().setMainMenu_(menu.0.menu); + } + } +} + struct DelegateState { handler: Option>, } diff --git a/druid-shell/src/menu.rs b/druid-shell/src/menu.rs index 7b7cb2e954..250778fe96 100644 --- a/druid-shell/src/menu.rs +++ b/druid-shell/src/menu.rs @@ -25,7 +25,7 @@ use crate::hotkey::HotKey; /// Currently, a menu and its items cannot be changed once created. If you need /// to change anything about a menu (for instance, disabling or selecting items) /// you need to create a new menu with the desired properties. -pub struct Menu(backend::Menu); +pub struct Menu(pub(crate) backend::Menu); impl Menu { /// Create a new empty window or application menu. diff --git a/druid-shell/src/platform/mac.rs b/druid-shell/src/platform/mac.rs new file mode 100644 index 0000000000..8011e96fa7 --- /dev/null +++ b/druid-shell/src/platform/mac.rs @@ -0,0 +1,40 @@ +// Copyright 2021 The Druid Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! macOS specific extensions. + +/// macOS specific extensions to [`Application`] +/// +/// [`Application`]: crate::Application +pub trait MacApplicationExt { + /// Hide the application this window belongs to. (cmd+H) + fn hide(&self); + + /// Hide all other applications. (cmd+opt+H) + fn hide_others(&self); + + /// Sets the global application menu, on platforms where there is one. + /// + /// On platforms with no global application menu, this has no effect. + fn set_menu(&self, menu: crate::Menu); +} + +#[cfg(test)] +mod test { + use crate::Application; + + use super::*; + use static_assertions as sa; + sa::assert_impl_all!(Application: MacApplicationExt); +} diff --git a/druid-shell/src/platform/mod.rs b/druid-shell/src/platform/mod.rs index 75f3adfefc..70b27a3de7 100644 --- a/druid-shell/src/platform/mod.rs +++ b/druid-shell/src/platform/mod.rs @@ -16,3 +16,6 @@ #[cfg(any(doc, target_os = "linux"))] pub mod linux; + +#[cfg(any(doc, target_os = "macos"))] +pub mod mac; diff --git a/druid/src/command.rs b/druid/src/command.rs index feadb24cc6..fa40d58dff 100644 --- a/druid/src/command.rs +++ b/druid/src/command.rs @@ -183,10 +183,18 @@ pub mod sys { /// Quit the running application. This command is handled by the druid library. pub const QUIT_APP: Selector = Selector::new("druid-builtin.quit-app"); - /// Hide the application. (mac only?) + /// Hide the application. (mac only) + #[cfg_attr( + not(target_os = "macos"), + deprecated = "HIDE_APPLICATION is only supported on macOS" + )] pub const HIDE_APPLICATION: Selector = Selector::new("druid-builtin.menu-hide-application"); - /// Hide all other applications. (mac only?) + /// Hide all other applications. (mac only) + #[cfg_attr( + not(target_os = "macos"), + deprecated = "HIDE_OTHERS is only supported on macOS" + )] pub const HIDE_OTHERS: Selector = Selector::new("druid-builtin.menu-hide-others"); /// The selector for a command to create a new window. diff --git a/druid/src/menu/sys.rs b/druid/src/menu/sys.rs index a3af20b239..1dfc42c73f 100644 --- a/druid/src/menu/sys.rs +++ b/druid/src/menu/sys.rs @@ -182,6 +182,7 @@ pub mod mac { /// The default Application menu. pub fn default() -> Menu { + #[allow(deprecated)] Menu::new(LocalizedString::new("macos-menu-application-menu")) .entry(about()) .separator() @@ -209,14 +210,24 @@ pub mod mac { } /// The 'Hide' builtin menu item. + #[cfg_attr( + not(target_os = "macos"), + deprecated = "hide does nothing on platforms other than macOS" + )] pub fn hide() -> MenuItem { + #[allow(deprecated)] MenuItem::new(LocalizedString::new("macos-menu-hide-app")) .command(commands::HIDE_APPLICATION) .hotkey(SysMods::Cmd, "h") } /// The 'Hide Others' builtin menu item. + #[cfg_attr( + not(target_os = "macos"), + deprecated = "hide_others does nothing on platforms other than macOS" + )] pub fn hide_others() -> MenuItem { + #[allow(deprecated)] MenuItem::new(LocalizedString::new("macos-menu-hide-others")) .command(commands::HIDE_OTHERS) .hotkey(SysMods::AltCmd, "h") diff --git a/druid/src/win_handler.rs b/druid/src/win_handler.rs index b0a8d3e246..823c09963f 100644 --- a/druid/src/win_handler.rs +++ b/druid/src/win_handler.rs @@ -474,6 +474,8 @@ impl Inner { #[cfg(target_os = "macos")] { + use druid_shell::platform::mac::MacApplicationExt; + let windows = &mut self.windows; let window = self.menu_window.and_then(|w| windows.get_mut(w)); if let Some(window) = window { @@ -652,7 +654,9 @@ impl AppState { match cmd.target() { // these are handled the same no matter where they come from _ if cmd.is(sys_cmd::QUIT_APP) => self.quit(), + #[cfg(target_os = "macos")] _ if cmd.is(sys_cmd::HIDE_APPLICATION) => self.hide_app(), + #[cfg(target_os = "macos")] _ if cmd.is(sys_cmd::HIDE_OTHERS) => self.hide_others(), _ if cmd.is(sys_cmd::NEW_WINDOW) => { if let Err(e) = self.new_window(cmd) { @@ -835,14 +839,16 @@ impl AppState { self.inner.borrow().app.quit() } + #[cfg(target_os = "macos")] fn hide_app(&self) { - #[cfg(target_os = "macos")] + use druid_shell::platform::mac::MacApplicationExt; self.inner.borrow().app.hide() } + #[cfg(target_os = "macos")] fn hide_others(&mut self) { - #[cfg(target_os = "macos")] - self.inner.borrow().app.hide_others() + use druid_shell::platform::mac::MacApplicationExt; + self.inner.borrow().app.hide_others(); } pub(crate) fn build_native_window(