Skip to content

Commit

Permalink
inital work for menu wrapper types
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir committed Jul 31, 2023
1 parent 80f4f2e commit 0b235db
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 181 deletions.
2 changes: 1 addition & 1 deletion core/tauri-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ raw-window-handle = "0.5"
rand = "0.8"
url = { version = "2" }
muda = { git = "https://github.com/tauri-apps/muda", default-features = false }
tray-icon = { git = "https://github.com/tauri-apps/tray-icon", default-features = false }
tray-icon = { path = "../../../tray-icon", default-features = false }

[target."cfg(windows)".dependencies.windows]
version = "0.48"
Expand Down
80 changes: 36 additions & 44 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use crate::scope::FsScope;
use raw_window_handle::HasRawDisplayHandle;
use tauri_macros::default_runtime;
use tauri_runtime::{
menu::{Menu, MenuEvent},
tray::{TrayIcon, TrayIconBuilder, TrayIconEvent},
window::{
dpi::{PhysicalPosition, PhysicalSize},
Expand All @@ -46,7 +45,10 @@ use std::{
sync::{mpsc::Sender, Arc, Weak},
};

use crate::runtime::RuntimeHandle;
use crate::{
menu::{Menu, MenuEvent},
runtime::RuntimeHandle,
};

#[cfg(target_os = "macos")]
use crate::ActivationPolicy;
Expand Down Expand Up @@ -545,15 +547,15 @@ macro_rules! shared_app_impl {
}

/// Returns the app-wide menu.
pub fn menu(&self) -> Option<Menu> {
pub fn menu(&self) -> Option<Menu<R>> {
self.manager.menu_lock().clone()
}

/// Sets the app-wide menu and returns the previous one.
///
/// If a window was not created with an explicit menu or had one set explicitly,
/// this menu will be assigned to it.
pub fn set_menu(&self, menu: Menu) -> crate::Result<Option<Menu>> {
pub fn set_menu(&self, menu: Menu<R>) -> crate::Result<Option<Menu<R>>> {
let prev_menu = self.remove_menu()?;

self.manager.insert_menu_into_stash(&menu);
Expand All @@ -564,9 +566,10 @@ macro_rules! shared_app_impl {
for window in self.manager.windows_lock().values() {
let mut window_menu = window.menu_lock();
if window_menu.as_ref().map(|m| m.0).unwrap_or(true) {
// TODO(muda-migration): make it thread-safe
#[cfg(windows)]
{
let _ = menu.init_for_hwnd(window.hwnd().unwrap().0);
let _ = menu.inner().init_for_hwnd(window.hwnd().unwrap().0);
}
#[cfg(any(
target_os = "linux",
Expand All @@ -576,7 +579,9 @@ macro_rules! shared_app_impl {
target_os = "openbsd"
))]
{
let _ = menu.init_for_gtk_window(&window.gtk_window().unwrap());
let _ = menu
.inner()
.init_for_gtk_window(&window.gtk_window().unwrap());
}
window_menu.replace((true, menu.clone()));
}
Expand All @@ -593,7 +598,7 @@ macro_rules! shared_app_impl {
///
/// If a window was not created with an explicit menu or had one set explicitly,
/// this will remove the menu from it.
pub fn remove_menu(&self) -> crate::Result<Option<Menu>> {
pub fn remove_menu(&self) -> crate::Result<Option<Menu<R>>> {
let mut current_menu = self.manager.menu_lock();

// remove from windows that have the app-wide menu
Expand All @@ -602,7 +607,7 @@ macro_rules! shared_app_impl {
if window.has_app_wide_menu() {
#[cfg(windows)]
{
let _ = menu.remove_for_hwnd(window.hwnd()?.0);
let _ = menu.inner().remove_for_hwnd(window.hwnd()?.0);
}
#[cfg(any(
target_os = "linux",
Expand All @@ -612,7 +617,7 @@ macro_rules! shared_app_impl {
target_os = "openbsd"
))]
{
let _ = menu.remove_for_gtk_window(&window.gtk_window()?);
let _ = menu.inner().remove_for_gtk_window(&window.gtk_window()?);
}
*window.menu_lock() = None;
}
Expand All @@ -629,7 +634,7 @@ macro_rules! shared_app_impl {

self
.manager
.remove_menu_from_stash_by_id(prev_menu.as_ref().map(|m| m.id()));
.remove_menu_from_stash_by_id(prev_menu.as_ref().and_then(|m| m.id().ok()));

Ok(prev_menu)
}
Expand All @@ -644,7 +649,7 @@ macro_rules! shared_app_impl {
if window.has_app_wide_menu() {
#[cfg(windows)]
{
let _ = menu.hide_for_hwnd(window.hwnd()?.0);
let _ = menu.inner().hide_for_hwnd(window.hwnd()?.0);
}
#[cfg(any(
target_os = "linux",
Expand All @@ -654,7 +659,7 @@ macro_rules! shared_app_impl {
target_os = "openbsd"
))]
{
let _ = menu.hide_for_gtk_window(&window.gtk_window()?);
let _ = menu.inner().hide_for_gtk_window(&window.gtk_window()?);
}
}
}
Expand All @@ -673,7 +678,7 @@ macro_rules! shared_app_impl {
if window.has_app_wide_menu() {
#[cfg(windows)]
{
let _ = menu.show_for_hwnd(window.hwnd()?.0);
let _ = menu.inner().show_for_hwnd(window.hwnd()?.0);
}
#[cfg(any(
target_os = "linux",
Expand All @@ -683,7 +688,7 @@ macro_rules! shared_app_impl {
target_os = "openbsd"
))]
{
let _ = menu.show_for_gtk_window(&window.gtk_window()?);
let _ = menu.inner().show_for_gtk_window(&window.gtk_window()?);
}
}
}
Expand Down Expand Up @@ -905,10 +910,10 @@ pub struct Builder<R: Runtime> {
state: StateManager,

/// The menu set to all windows.
menu: Option<Menu>,
menu: Option<Menu<R>>,

/// A closure that returns the menu set to all windows.
menu_with: Option<Box<dyn FnOnce(&Config) -> Menu>>,
menu_with: Option<Box<dyn FnOnce(&Config) -> Menu<R>>>,

/// Enable macOS default menu creation.
#[allow(unused)]
Expand Down Expand Up @@ -1219,28 +1224,12 @@ impl<R: Runtime> Builder<R> {
/// ]));
/// ```
#[must_use]
pub fn menu(mut self, menu: Menu) -> Self {
pub fn menu(mut self, menu: Menu<R>) -> Self {
self.menu_with = None;
self.menu.replace(menu);
self
}

/// Sets a closure to construct the menu to use on all windows.
///
/// # Examples
/// ```
/// use tauri::{MenuEntry, Submenu, MenuItem, Menu, CustomMenuItem};
///
/// tauri::Builder::default()
/// .menu_with(tauri::menu::default);
/// ```
#[must_use]
pub fn menu_with<F: FnOnce(&Config) -> Menu + 'static>(mut self, f: F) -> Self {
self.menu_with.replace(Box::new(move |c| f(c)));
self.menu = None;
self
}

/// Enable or disable the default menu on macOS. Enabled by default.
///
/// # Examples
Expand Down Expand Up @@ -1428,12 +1417,9 @@ impl<R: Runtime> Builder<R> {
}

if let Some(menu) = &menu {
manager
.inner
.menus
.lock()
.unwrap()
.insert(menu.id(), menu.clone());
if let Ok(id) = menu.id() {
manager.inner.menus.lock().unwrap().insert(id, menu.clone());
}
}

let runtime_args = RuntimeInitArgs {
Expand All @@ -1445,7 +1431,8 @@ impl<R: Runtime> Builder<R> {
unsafe {
let msg = msg as *const MSG;
for menu in menus.lock().unwrap().values() {
let translated = TranslateAcceleratorW((*msg).hwnd, HACCEL(menu.haccel()), msg);
let translated =
TranslateAcceleratorW((*msg).hwnd, HACCEL(menu.inner().haccel()), msg);
if translated == 1 {
return true;
}
Expand Down Expand Up @@ -1599,10 +1586,15 @@ fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
let pending = app
.manager
.prepare_window(app.handle.clone(), pending, &window_labels)?;
let menu = pending
.menu()
.cloned()
.map(|m| (pending.has_app_wide_menu, m));
let menu = pending.menu().cloned().map(|m| {
(
pending.has_app_wide_menu,
Menu {
inner: m,
app_handle: app.handle(),
},
)
});
let window_effects = pending.webview_attributes.window_effects.clone();
let detached = if let RuntimeOrDispatch::RuntimeHandle(runtime) = app.handle().runtime() {
runtime.create_window(pending)?
Expand Down
9 changes: 9 additions & 0 deletions core/tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,13 @@ pub enum Error {
#[cfg(target_os = "android")]
#[error("jni error: {0}")]
Jni(#[from] jni::errors::Error),
/// Failed to receive message .
#[error("failed to receive message")]
FailedToReceiveMessage,
/// Menu error.
#[error("menu error: {0}")]
Menu(#[from] tauri_runtime::menu::Error),
/// Tray icon error.
#[error("tray icon error: {0}")]
Tray(#[from] tauri_runtime::tray::Error),
}
6 changes: 5 additions & 1 deletion core/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ pub type Result<T> = std::result::Result<T, Error>;
pub type SyncTask = Box<dyn FnOnce() + Send>;

use serde::Serialize;
use std::{collections::HashMap, fmt, sync::Arc};
use std::{
collections::HashMap,
fmt::{self, Debug},
sync::Arc,
};

// Export types likely to be used by the application.
pub use runtime::http;
Expand Down
38 changes: 21 additions & 17 deletions core/tauri/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ use std::{
sync::{Arc, Mutex, MutexGuard},
};

use crate::menu::Menu;
use serde::Serialize;
use serde_json::Value as JsonValue;
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
use tauri_runtime::{menu::Menu, tray::TrayIcon};
use tauri_runtime::tray::TrayIcon;
use url::Url;

use tauri_macros::default_runtime;
Expand Down Expand Up @@ -225,9 +226,9 @@ pub struct InnerWindowManager<R: Runtime> {
///
/// This should be mainly used to acceess [`Menu::haccel`]
/// to setup the accelerator handling in the event loop
pub menus: Arc<Mutex<HashMap<u32, Menu>>>,
pub menus: Arc<Mutex<HashMap<u32, Menu<R>>>>,
/// The menu set to all windows.
pub(crate) menu: Arc<Mutex<Option<Menu>>>,
pub(crate) menu: Arc<Mutex<Option<Menu<R>>>>,
/// Menu event listeners to all windows.
pub(crate) menu_event_listeners: Arc<Mutex<Vec<GlobalMenuEventListener<AppHandle<R>>>>>,
/// Menu event listeners to specific windows.
Expand Down Expand Up @@ -312,7 +313,7 @@ impl<R: Runtime> WindowManager<R> {
state: StateManager,
window_event_listeners: Vec<GlobalWindowEventListener<R>>,
(menu, menu_event_listeners, window_menu_event_listeners): (
Option<Menu>,
Option<Menu<R>>,
Vec<GlobalMenuEventListener<AppHandle<R>>>,
HashMap<String, GlobalMenuEventListener<Window<R>>>,
),
Expand Down Expand Up @@ -370,26 +371,28 @@ impl<R: Runtime> WindowManager<R> {
}

/// App-wide menu.
pub(crate) fn menu_lock(&self) -> MutexGuard<'_, Option<Menu>> {
pub(crate) fn menu_lock(&self) -> MutexGuard<'_, Option<Menu<R>>> {
self.inner.menu.lock().expect("poisoned window manager")
}

/// Menus stash.
pub(crate) fn menus_stash_lock(&self) -> MutexGuard<'_, HashMap<u32, Menu>> {
pub(crate) fn menus_stash_lock(&self) -> MutexGuard<'_, HashMap<u32, Menu<R>>> {
self.inner.menus.lock().expect("poisoned window manager")
}

pub(crate) fn is_menu_in_use(&self, id: u32) -> bool {
self
.menu_lock()
.as_ref()
.map(|m| m.id() == id)
.map(|m| m.id().map(|i| i == id).unwrap_or(false))
.unwrap_or(false)
}

/// Menus stash.
pub(crate) fn insert_menu_into_stash(&self, menu: &Menu) {
self.menus_stash_lock().insert(menu.id(), menu.clone());
pub(crate) fn insert_menu_into_stash(&self, menu: &Menu<R>) {
if let Ok(id) = menu.id() {
self.menus_stash_lock().insert(id, menu.clone());
}
}

pub(crate) fn remove_menu_from_stash_by_id(&self, id: Option<u32>) {
Expand Down Expand Up @@ -1176,16 +1179,17 @@ impl<R: Runtime> WindowManager<R> {
}));

if let Some(menu) = &*self.inner.menu.lock().unwrap() {
pending = pending.set_app_menu(menu.clone());
pending = pending.set_app_menu(menu.inner().clone());
}

if let Some(menu) = pending.menu() {
self
.inner
.menus
.lock()
.unwrap()
.insert(menu.id(), menu.clone());
self.inner.menus.lock().unwrap().insert(
menu.id(),
Menu {
inner: menu.clone(),
app_handle: app_handle.clone(),
},
);
}

Ok(pending)
Expand All @@ -1195,7 +1199,7 @@ impl<R: Runtime> WindowManager<R> {
&self,
app_handle: AppHandle<R>,
window: DetachedWindow<EventLoopMessage, R>,
menu: Option<(bool, Menu)>,
menu: Option<(bool, Menu<R>)>,
) -> Window<R> {
let window = Window::new(self.clone(), window, app_handle, menu);

Expand Down
Loading

0 comments on commit 0b235db

Please sign in to comment.