mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-28 12:27:16 +03:00
refactor(core): global shortcut is now provided by tao
(#2031)
This commit is contained in:
parent
f7d21a4b86
commit
3280c4aa91
5
.changes/global-shortcut-refactor.md
Normal file
5
.changes/global-shortcut-refactor.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
**Breaking change**: The global shortcut API is now managed by `tao` so it cannot be accessed globally, the manager is now exposed on the `App` and `AppHandle` structs.
|
6
.changes/runtime-global-shortcut.md
Normal file
6
.changes/runtime-global-shortcut.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-runtime": patch
|
||||
"tauri-runtime-wry": patch
|
||||
---
|
||||
|
||||
Adds global shortcut interfaces.
|
@ -25,7 +25,7 @@ members = [
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
tao = { git = "https://github.com/tauri-apps/tao", rev = "66360eea4ec6af8a52afcebb7700f486a0092168" }
|
||||
tao = { git = "https://github.com/tauri-apps/tao", rev = "01fc43b05ea41463d512c0e3497971edc543ac9d" }
|
||||
|
||||
# default to small, optimized workspace release binaries
|
||||
[profile.release]
|
||||
|
@ -13,8 +13,8 @@ use tauri_runtime::{
|
||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||
DetachedWindow, PendingWindow, WindowEvent,
|
||||
},
|
||||
Dispatch, Error, Icon, Params, Result, RunEvent, RunIteration, Runtime, RuntimeHandle,
|
||||
UserAttentionType,
|
||||
Dispatch, Error, GlobalShortcutManager, Icon, Params, Result, RunEvent, RunIteration, Runtime,
|
||||
RuntimeHandle, UserAttentionType,
|
||||
};
|
||||
|
||||
#[cfg(feature = "menu")]
|
||||
@ -32,6 +32,7 @@ use tauri_utils::config::WindowConfig;
|
||||
use uuid::Uuid;
|
||||
use wry::{
|
||||
application::{
|
||||
accelerator::{Accelerator, AcceleratorId},
|
||||
dpi::{
|
||||
LogicalPosition as WryLogicalPosition, LogicalSize as WryLogicalSize,
|
||||
PhysicalPosition as WryPhysicalPosition, PhysicalSize as WryPhysicalSize,
|
||||
@ -40,6 +41,7 @@ use wry::{
|
||||
event::{Event, WindowEvent as WryWindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget},
|
||||
monitor::MonitorHandle,
|
||||
platform::global_shortcut::{GlobalShortcut, ShortcutManager as WryShortcutManager},
|
||||
window::{
|
||||
Fullscreen, Icon as WindowIcon, UserAttentionType as WryUserAttentionType, Window,
|
||||
WindowBuilder as WryWindowBuilder, WindowId,
|
||||
@ -76,6 +78,118 @@ type CreateWebviewHandler =
|
||||
Box<dyn FnOnce(&EventLoopWindowTarget<Message>) -> Result<WebviewWrapper> + Send>;
|
||||
type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
|
||||
type WindowEventListeners = Arc<Mutex<HashMap<Uuid, WindowEventHandler>>>;
|
||||
type GlobalShortcutListeners = Arc<Mutex<HashMap<AcceleratorId, Box<dyn Fn() + Send>>>>;
|
||||
|
||||
macro_rules! dispatcher_getter {
|
||||
($self: ident, $message: expr) => {{
|
||||
if current_thread().id() == $self.context.main_thread_id
|
||||
&& !$self.context.is_event_loop_running.load(Ordering::Relaxed)
|
||||
{
|
||||
panic!("This API cannot be called when the event loop is not running");
|
||||
}
|
||||
let (tx, rx) = channel();
|
||||
$self
|
||||
.context
|
||||
.proxy
|
||||
.send_event(Message::Window($self.window_id, $message(tx)))
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
rx.recv().unwrap()
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! shortcut_getter {
|
||||
($self: ident, $rx: expr, $message: expr) => {{
|
||||
if current_thread().id() == $self.context.main_thread_id
|
||||
&& !$self.context.is_event_loop_running.load(Ordering::Relaxed)
|
||||
{
|
||||
panic!("This API cannot be called when the event loop is not running");
|
||||
}
|
||||
$self
|
||||
.context
|
||||
.proxy
|
||||
.send_event($message)
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
$rx.recv().unwrap()
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct GlobalShortcutWrapper(GlobalShortcut);
|
||||
|
||||
unsafe impl Send for GlobalShortcutWrapper {}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct GlobalShortcutManagerContext {
|
||||
main_thread_id: ThreadId,
|
||||
is_event_loop_running: Arc<AtomicBool>,
|
||||
proxy: EventLoopProxy<Message>,
|
||||
}
|
||||
|
||||
/// Wrapper around [`WryShortcutManager`].
|
||||
#[derive(Clone)]
|
||||
pub struct GlobalShortcutManagerHandle {
|
||||
context: GlobalShortcutManagerContext,
|
||||
shortcuts: HashMap<String, (AcceleratorId, GlobalShortcutWrapper)>,
|
||||
listeners: GlobalShortcutListeners,
|
||||
}
|
||||
|
||||
impl GlobalShortcutManager for GlobalShortcutManagerHandle {
|
||||
fn is_registered(&self, accelerator: &str) -> Result<bool> {
|
||||
let (tx, rx) = channel();
|
||||
Ok(shortcut_getter!(
|
||||
self,
|
||||
rx,
|
||||
Message::GlobalShortcut(GlobalShortcutMessage::IsRegistered(
|
||||
accelerator.parse().expect("invalid accelerator"),
|
||||
tx
|
||||
))
|
||||
))
|
||||
}
|
||||
|
||||
fn register<F: Fn() + Send + 'static>(&mut self, accelerator: &str, handler: F) -> Result<()> {
|
||||
let wry_accelerator: Accelerator = accelerator.parse().expect("invalid accelerator");
|
||||
let id = wry_accelerator.clone().id();
|
||||
let (tx, rx) = channel();
|
||||
let shortcut = shortcut_getter!(
|
||||
self,
|
||||
rx,
|
||||
Message::GlobalShortcut(GlobalShortcutMessage::Register(wry_accelerator, tx))
|
||||
)?;
|
||||
|
||||
self.listeners.lock().unwrap().insert(id, Box::new(handler));
|
||||
self.shortcuts.insert(accelerator.into(), (id, shortcut));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unregister_all(&mut self) -> Result<()> {
|
||||
let (tx, rx) = channel();
|
||||
shortcut_getter!(
|
||||
self,
|
||||
rx,
|
||||
Message::GlobalShortcut(GlobalShortcutMessage::UnregisterAll(tx))
|
||||
)?;
|
||||
self.listeners.lock().unwrap().clear();
|
||||
self.shortcuts.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unregister(&mut self, accelerator: &str) -> Result<()> {
|
||||
if let Some((accelerator_id, shortcut)) = self.shortcuts.remove(accelerator) {
|
||||
let (tx, rx) = channel();
|
||||
shortcut_getter!(
|
||||
self,
|
||||
rx,
|
||||
Message::GlobalShortcut(GlobalShortcutMessage::Unregister(
|
||||
GlobalShortcutWrapper(shortcut.0),
|
||||
tx
|
||||
))
|
||||
)?;
|
||||
self.listeners.lock().unwrap().remove(&accelerator_id);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper around a [`wry::application::window::Icon`] that can be created from an [`Icon`].
|
||||
pub struct WryIcon(WindowIcon);
|
||||
@ -267,7 +381,7 @@ pub struct WindowBuilderWrapper {
|
||||
inner: WryWindowBuilder,
|
||||
center: bool,
|
||||
#[cfg(feature = "menu")]
|
||||
menu_items: HashMap<u32, WryCustomMenuItem>,
|
||||
menu_items: HashMap<u16, WryCustomMenuItem>,
|
||||
}
|
||||
|
||||
// safe since `menu_items` are read only here
|
||||
@ -510,7 +624,7 @@ enum WindowMessage {
|
||||
SetSkipTaskbar(bool),
|
||||
DragWindow,
|
||||
#[cfg(feature = "menu")]
|
||||
UpdateMenuItem(u32, menu::MenuUpdate),
|
||||
UpdateMenuItem(u16, menu::MenuUpdate),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -522,12 +636,20 @@ enum WebviewMessage {
|
||||
#[cfg(feature = "system-tray")]
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum TrayMessage {
|
||||
UpdateItem(u32, menu::MenuUpdate),
|
||||
UpdateItem(u16, menu::MenuUpdate),
|
||||
UpdateIcon(Icon),
|
||||
#[cfg(windows)]
|
||||
Remove,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum GlobalShortcutMessage {
|
||||
IsRegistered(Accelerator, Sender<bool>),
|
||||
Register(Accelerator, Sender<Result<GlobalShortcutWrapper>>),
|
||||
Unregister(GlobalShortcutWrapper, Sender<Result<()>>),
|
||||
UnregisterAll(Sender<Result<()>>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum Message {
|
||||
Task(MainTask),
|
||||
@ -536,6 +658,7 @@ pub(crate) enum Message {
|
||||
#[cfg(feature = "system-tray")]
|
||||
Tray(TrayMessage),
|
||||
CreateWebview(Arc<Mutex<Option<CreateWebviewHandler>>>, Sender<WindowId>),
|
||||
GlobalShortcut(GlobalShortcutMessage),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -555,23 +678,6 @@ pub struct WryDispatcher {
|
||||
context: DispatcherContext,
|
||||
}
|
||||
|
||||
macro_rules! dispatcher_getter {
|
||||
($self: ident, $message: expr) => {{
|
||||
if current_thread().id() == $self.context.main_thread_id
|
||||
&& !$self.context.is_event_loop_running.load(Ordering::Relaxed)
|
||||
{
|
||||
panic!("This API cannot be called when the event loop is not running");
|
||||
}
|
||||
let (tx, rx) = channel();
|
||||
$self
|
||||
.context
|
||||
.proxy
|
||||
.send_event(Message::Window($self.window_id, $message(tx)))
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
rx.recv().unwrap()
|
||||
}};
|
||||
}
|
||||
|
||||
impl Dispatch for WryDispatcher {
|
||||
type Runtime = Wry;
|
||||
type WindowBuilder = WindowBuilderWrapper;
|
||||
@ -959,7 +1065,7 @@ impl Dispatch for WryDispatcher {
|
||||
}
|
||||
|
||||
#[cfg(feature = "menu")]
|
||||
fn update_menu_item(&self, id: u32, update: menu::MenuUpdate) -> Result<()> {
|
||||
fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> Result<()> {
|
||||
self
|
||||
.context
|
||||
.proxy
|
||||
@ -983,7 +1089,7 @@ struct WebviewWrapper {
|
||||
label: String,
|
||||
inner: WebView,
|
||||
#[cfg(feature = "menu")]
|
||||
menu_items: HashMap<u32, WryCustomMenuItem>,
|
||||
menu_items: HashMap<u16, WryCustomMenuItem>,
|
||||
#[cfg(feature = "menu")]
|
||||
is_menu_visible: AtomicBool,
|
||||
}
|
||||
@ -991,6 +1097,8 @@ struct WebviewWrapper {
|
||||
/// A Tauri [`Runtime`] wrapper around wry.
|
||||
pub struct Wry {
|
||||
main_thread_id: ThreadId,
|
||||
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
|
||||
global_shortcut_manager_handle: GlobalShortcutManagerHandle,
|
||||
is_event_loop_running: Arc<AtomicBool>,
|
||||
event_loop: EventLoop<Message>,
|
||||
webviews: Arc<Mutex<HashMap<WindowId, WebviewWrapper>>>,
|
||||
@ -1050,14 +1158,30 @@ impl RuntimeHandle for WryHandle {
|
||||
impl Runtime for Wry {
|
||||
type Dispatcher = WryDispatcher;
|
||||
type Handle = WryHandle;
|
||||
type GlobalShortcutManager = GlobalShortcutManagerHandle;
|
||||
#[cfg(feature = "system-tray")]
|
||||
type TrayHandler = SystemTrayHandle;
|
||||
|
||||
fn new() -> Result<Self> {
|
||||
let event_loop = EventLoop::<Message>::with_user_event();
|
||||
let global_shortcut_manager = WryShortcutManager::new(&event_loop);
|
||||
let global_shortcut_listeners = GlobalShortcutListeners::default();
|
||||
let proxy = event_loop.create_proxy();
|
||||
let main_thread_id = current_thread().id();
|
||||
let is_event_loop_running = Arc::new(AtomicBool::default());
|
||||
Ok(Self {
|
||||
main_thread_id: current_thread().id(),
|
||||
is_event_loop_running: Default::default(),
|
||||
main_thread_id,
|
||||
global_shortcut_manager: Arc::new(Mutex::new(global_shortcut_manager)),
|
||||
global_shortcut_manager_handle: GlobalShortcutManagerHandle {
|
||||
context: GlobalShortcutManagerContext {
|
||||
main_thread_id,
|
||||
is_event_loop_running: is_event_loop_running.clone(),
|
||||
proxy,
|
||||
},
|
||||
shortcuts: Default::default(),
|
||||
listeners: global_shortcut_listeners,
|
||||
},
|
||||
is_event_loop_running,
|
||||
event_loop,
|
||||
webviews: Default::default(),
|
||||
window_event_listeners: Default::default(),
|
||||
@ -1081,6 +1205,10 @@ impl Runtime for Wry {
|
||||
}
|
||||
}
|
||||
|
||||
fn global_shortcut_manager(&self) -> Self::GlobalShortcutManager {
|
||||
self.global_shortcut_manager_handle.clone()
|
||||
}
|
||||
|
||||
fn create_window<P: Params<Runtime = Self>>(
|
||||
&self,
|
||||
pending: PendingWindow<P>,
|
||||
@ -1168,6 +1296,8 @@ impl Runtime for Wry {
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
#[cfg(feature = "system-tray")]
|
||||
let tray_context = self.tray_context.clone();
|
||||
let global_shortcut_manager = self.global_shortcut_manager.clone();
|
||||
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
|
||||
|
||||
let mut iteration = RunIteration::default();
|
||||
|
||||
@ -1186,6 +1316,8 @@ impl Runtime for Wry {
|
||||
callback: &callback,
|
||||
webviews: webviews.lock().expect("poisoned webview collection"),
|
||||
window_event_listeners: window_event_listeners.clone(),
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
global_shortcut_manager_handle: global_shortcut_manager_handle.clone(),
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: menu_event_listeners.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
@ -1206,6 +1338,8 @@ impl Runtime for Wry {
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
#[cfg(feature = "system-tray")]
|
||||
let tray_context = self.tray_context;
|
||||
let global_shortcut_manager = self.global_shortcut_manager.clone();
|
||||
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
|
||||
|
||||
self.event_loop.run(move |event, event_loop, control_flow| {
|
||||
handle_event_loop(
|
||||
@ -1216,6 +1350,8 @@ impl Runtime for Wry {
|
||||
callback: &callback,
|
||||
webviews: webviews.lock().expect("poisoned webview collection"),
|
||||
window_event_listeners: window_event_listeners.clone(),
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
global_shortcut_manager_handle: global_shortcut_manager_handle.clone(),
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: menu_event_listeners.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
@ -1230,6 +1366,8 @@ struct EventLoopIterationContext<'a> {
|
||||
callback: &'a (dyn Fn(RunEvent) + 'static),
|
||||
webviews: MutexGuard<'a, HashMap<WindowId, WebviewWrapper>>,
|
||||
window_event_listeners: WindowEventListeners,
|
||||
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
|
||||
global_shortcut_manager_handle: GlobalShortcutManagerHandle,
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: MenuEventListeners,
|
||||
#[cfg(feature = "system-tray")]
|
||||
@ -1246,6 +1384,8 @@ fn handle_event_loop(
|
||||
callback,
|
||||
mut webviews,
|
||||
window_event_listeners,
|
||||
global_shortcut_manager,
|
||||
global_shortcut_manager_handle,
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners,
|
||||
#[cfg(feature = "system-tray")]
|
||||
@ -1254,6 +1394,13 @@ fn handle_event_loop(
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match event {
|
||||
Event::GlobalShortcutEvent(accelerator_id) => {
|
||||
for (id, handler) in &*global_shortcut_manager_handle.listeners.lock().unwrap() {
|
||||
if accelerator_id == *id {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "menu")]
|
||||
Event::MenuEvent {
|
||||
menu_id,
|
||||
@ -1504,6 +1651,44 @@ fn handle_event_loop(
|
||||
}
|
||||
}
|
||||
},
|
||||
Message::GlobalShortcut(message) => match message {
|
||||
GlobalShortcutMessage::IsRegistered(accelerator, tx) => tx
|
||||
.send(
|
||||
global_shortcut_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.is_registered(&accelerator),
|
||||
)
|
||||
.unwrap(),
|
||||
GlobalShortcutMessage::Register(accelerator, tx) => tx
|
||||
.send(
|
||||
global_shortcut_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.register(accelerator)
|
||||
.map(GlobalShortcutWrapper)
|
||||
.map_err(|e| Error::GlobalShortcut(Box::new(e))),
|
||||
)
|
||||
.unwrap(),
|
||||
GlobalShortcutMessage::Unregister(shortcut, tx) => tx
|
||||
.send(
|
||||
global_shortcut_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.unregister(shortcut.0)
|
||||
.map_err(|e| Error::GlobalShortcut(Box::new(e))),
|
||||
)
|
||||
.unwrap(),
|
||||
GlobalShortcutMessage::UnregisterAll(tx) => tx
|
||||
.send(
|
||||
global_shortcut_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.unregister_all()
|
||||
.map_err(|e| Error::GlobalShortcut(Box::new(e))),
|
||||
)
|
||||
.unwrap(),
|
||||
},
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ pub type SystemTrayEventHandler = Box<dyn Fn(&SystemTrayEvent) + Send>;
|
||||
#[cfg(feature = "system-tray")]
|
||||
pub type SystemTrayEventListeners = Arc<Mutex<HashMap<Uuid, SystemTrayEventHandler>>>;
|
||||
#[cfg(feature = "system-tray")]
|
||||
pub type SystemTrayItems = Arc<Mutex<HashMap<u32, WryCustomMenuItem>>>;
|
||||
pub type SystemTrayItems = Arc<Mutex<HashMap<u16, WryCustomMenuItem>>>;
|
||||
|
||||
#[cfg(feature = "system-tray")]
|
||||
#[derive(Clone)]
|
||||
@ -61,7 +61,7 @@ impl TrayHandle for SystemTrayHandle {
|
||||
.send_event(Message::Tray(TrayMessage::UpdateIcon(icon)))
|
||||
.map_err(|_| Error::FailedToSendMessage)
|
||||
}
|
||||
fn update_item(&self, id: u32, update: MenuUpdate) -> Result<()> {
|
||||
fn update_item(&self, id: u16, update: MenuUpdate) -> Result<()> {
|
||||
self
|
||||
.proxy
|
||||
.send_event(Message::Tray(TrayMessage::UpdateItem(id, update)))
|
||||
@ -147,7 +147,7 @@ impl<'a, I: MenuId> From<&'a CustomMenuItem<I>> for MenuItemAttributesWrapper<'a
|
||||
.with_selected(item.selected)
|
||||
.with_id(WryMenuId(item.id_value()));
|
||||
if let Some(accelerator) = item.keyboard_accelerator.as_ref() {
|
||||
attributes = attributes.with_accelerators(accelerator);
|
||||
attributes = attributes.with_accelerators(&accelerator.parse().expect("invalid accelerator"));
|
||||
}
|
||||
Self(attributes)
|
||||
}
|
||||
@ -191,7 +191,7 @@ impl From<SystemTrayMenuItem> for MenuItemWrapper {
|
||||
|
||||
#[cfg(feature = "menu")]
|
||||
pub fn to_wry_menu<I: MenuId>(
|
||||
custom_menu_items: &mut HashMap<u32, WryCustomMenuItem>,
|
||||
custom_menu_items: &mut HashMap<u16, WryCustomMenuItem>,
|
||||
menu: Menu<I>,
|
||||
) -> MenuBar {
|
||||
let mut wry_menu = MenuBar::new();
|
||||
@ -224,7 +224,7 @@ pub fn to_wry_menu<I: MenuId>(
|
||||
|
||||
#[cfg(feature = "system-tray")]
|
||||
pub fn to_wry_context_menu<I: MenuId>(
|
||||
custom_menu_items: &mut HashMap<u32, WryCustomMenuItem>,
|
||||
custom_menu_items: &mut HashMap<u16, WryCustomMenuItem>,
|
||||
menu: SystemTrayMenu<I>,
|
||||
) -> WryContextMenu {
|
||||
let mut tray_menu = WryContextMenu::new();
|
||||
|
@ -116,6 +116,9 @@ pub enum Error {
|
||||
/// Failed to get monitor on window operation.
|
||||
#[error("failed to get monitor")]
|
||||
FailedToGetMonitor,
|
||||
/// Global shortcut error.
|
||||
#[error(transparent)]
|
||||
GlobalShortcut(Box<dyn std::error::Error + Send>),
|
||||
}
|
||||
|
||||
/// Result type.
|
||||
@ -193,7 +196,7 @@ pub enum RunEvent {
|
||||
|
||||
/// A system tray event.
|
||||
pub enum SystemTrayEvent {
|
||||
MenuItemClick(u32),
|
||||
MenuItemClick(u16),
|
||||
LeftClick {
|
||||
position: PhysicalPosition<f64>,
|
||||
size: PhysicalSize<f64>,
|
||||
@ -228,12 +231,53 @@ pub trait RuntimeHandle: Send + Sized + Clone + 'static {
|
||||
fn remove_system_tray(&self) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
/// A global shortcut manager.
|
||||
pub trait GlobalShortcutManager {
|
||||
/// Whether the application has registered the given `accelerator`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
|
||||
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
|
||||
fn is_registered(&self, accelerator: &str) -> crate::Result<bool>;
|
||||
|
||||
/// Register a global shortcut of `accelerator`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
|
||||
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
|
||||
fn register<F: Fn() + Send + 'static>(
|
||||
&mut self,
|
||||
accelerator: &str,
|
||||
handler: F,
|
||||
) -> crate::Result<()>;
|
||||
|
||||
/// Unregister all accelerators registered by the manager instance.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
|
||||
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
|
||||
fn unregister_all(&mut self) -> crate::Result<()>;
|
||||
|
||||
/// Unregister the provided `accelerator`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the app is not running yet, usually when called on the `tauri::Builder#setup` closure.
|
||||
/// You can spawn a task to use the API using the `tauri::async_runtime` to prevent the panic.
|
||||
fn unregister(&mut self, accelerator: &str) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
/// The webview runtime interface.
|
||||
pub trait Runtime: Sized + 'static {
|
||||
/// The message dispatcher.
|
||||
type Dispatcher: Dispatch<Runtime = Self>;
|
||||
/// The runtime handle type.
|
||||
type Handle: RuntimeHandle<Runtime = Self>;
|
||||
/// The global shortcut manager type.
|
||||
type GlobalShortcutManager: GlobalShortcutManager + Clone + Send;
|
||||
/// The tray handler type.
|
||||
#[cfg(feature = "system-tray")]
|
||||
type TrayHandler: menu::TrayHandle + Clone + Send;
|
||||
@ -244,6 +288,9 @@ pub trait Runtime: Sized + 'static {
|
||||
/// Gets a runtime handle.
|
||||
fn handle(&self) -> Self::Handle;
|
||||
|
||||
/// Gets the global shortcut manager.
|
||||
fn global_shortcut_manager(&self) -> Self::GlobalShortcutManager;
|
||||
|
||||
/// Create a new webview window.
|
||||
fn create_window<P: Params<Runtime = Self>>(
|
||||
&self,
|
||||
@ -436,5 +483,5 @@ pub trait Dispatch: Clone + Send + Sized + 'static {
|
||||
|
||||
/// Applies the specified `update` to the menu item associated with the given `id`.
|
||||
#[cfg(feature = "menu")]
|
||||
fn update_menu_item(&self, id: u32, update: menu::MenuUpdate) -> crate::Result<()>;
|
||||
fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> crate::Result<()>;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ pub enum MenuUpdate {
|
||||
|
||||
pub trait TrayHandle {
|
||||
fn set_icon(&self, icon: crate::Icon) -> crate::Result<()>;
|
||||
fn update_item(&self, id: u32, update: MenuUpdate) -> crate::Result<()>;
|
||||
fn update_item(&self, id: u16, update: MenuUpdate) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
/// A window menu.
|
||||
@ -248,10 +248,10 @@ impl<I: MenuId> CustomMenuItem<I> {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn id_value(&self) -> u32 {
|
||||
pub fn id_value(&self) -> u16 {
|
||||
let mut s = DefaultHasher::new();
|
||||
self.id.hash(&mut s);
|
||||
s.finish() as u32
|
||||
s.finish() as u16
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ pub enum WindowEvent {
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MenuEvent {
|
||||
pub menu_item_id: u32,
|
||||
pub menu_item_id: u16,
|
||||
}
|
||||
|
||||
/// A webview window that has yet to be built.
|
||||
|
@ -66,9 +66,6 @@ clap = { version = "=3.0.0-beta.2", optional = true }
|
||||
# Notifications
|
||||
notify-rust = { version = "4.5", optional = true }
|
||||
|
||||
# Global shortcut
|
||||
tauri-hotkey = { version = "0.1.2", optional = true }
|
||||
|
||||
# HTTP
|
||||
reqwest = { version = "0.11", features = [ "json", "multipart" ], optional = true }
|
||||
bytes = { version = "1", features = [ "serde" ], optional = true }
|
||||
@ -133,4 +130,4 @@ dialog-save = [ "raw-window-handle" ]
|
||||
http-all = [ ]
|
||||
http-request = [ ]
|
||||
notification-all = [ "notify-rust" ]
|
||||
global-shortcut-all = [ "tauri-hotkey" ]
|
||||
global-shortcut-all = [ ]
|
||||
|
@ -76,10 +76,6 @@ pub enum Error {
|
||||
#[cfg(feature = "cli")]
|
||||
#[error("failed to parse CLI arguments: {0}")]
|
||||
ParseCliArguments(#[from] clap::Error),
|
||||
/// Shortcut error.
|
||||
#[cfg(global_shortcut_all)]
|
||||
#[error("shortcut error: {0}")]
|
||||
Shortcut(#[from] tauri_hotkey::Error),
|
||||
/// Shell error.
|
||||
#[error("shell error: {0}")]
|
||||
Shell(String),
|
||||
|
@ -36,10 +36,6 @@ pub mod cli;
|
||||
#[cfg(feature = "cli")]
|
||||
pub use clap;
|
||||
|
||||
/// Global shortcuts interface.
|
||||
#[cfg(global_shortcut_all)]
|
||||
pub mod shortcuts;
|
||||
|
||||
/// The desktop notifications API module.
|
||||
#[cfg(notification_all)]
|
||||
pub mod notification;
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use tauri_hotkey::{parse_hotkey, HotkeyManager};
|
||||
|
||||
/// The shortcut manager builder.
|
||||
#[derive(Default)]
|
||||
pub struct ShortcutManager(HotkeyManager);
|
||||
|
||||
impl ShortcutManager {
|
||||
/// Initializes a new instance of the shortcut manager.
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Determines whether the given hotkey is registered or not.
|
||||
pub fn is_registered(&self, shortcut: String) -> crate::api::Result<bool> {
|
||||
let hotkey = parse_hotkey(&shortcut)?;
|
||||
Ok(self.0.is_registered(&hotkey))
|
||||
}
|
||||
|
||||
/// Registers a new shortcut handler.
|
||||
pub fn register<H: FnMut() + Send + 'static>(
|
||||
&mut self,
|
||||
shortcut: String,
|
||||
handler: H,
|
||||
) -> crate::api::Result<()> {
|
||||
let hotkey = parse_hotkey(&shortcut)?;
|
||||
self.0.register(hotkey, handler)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unregister a previously registered shortcut handler.
|
||||
pub fn unregister(&mut self, shortcut: String) -> crate::api::Result<()> {
|
||||
let hotkey = parse_hotkey(&shortcut)?;
|
||||
self.0.unregister(&hotkey)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unregisters all shortcuts registered by this application.
|
||||
pub fn unregister_all(&mut self) -> crate::api::Result<()> {
|
||||
self.0.unregister_all()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -113,6 +113,7 @@ crate::manager::default_args! {
|
||||
pub struct AppHandle<P: Params> {
|
||||
runtime_handle: <P::Runtime as Runtime>::Handle,
|
||||
manager: WindowManager<P>,
|
||||
global_shortcut_manager: <P::Runtime as Runtime>::GlobalShortcutManager,
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_handle: Option<tray::SystemTrayHandle<P>>,
|
||||
}
|
||||
@ -123,6 +124,7 @@ impl<P: Params> Clone for AppHandle<P> {
|
||||
Self {
|
||||
runtime_handle: self.runtime_handle.clone(),
|
||||
manager: self.manager.clone(),
|
||||
global_shortcut_manager: self.global_shortcut_manager.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_handle: self.tray_handle.clone(),
|
||||
}
|
||||
@ -147,6 +149,10 @@ impl<P: Params> ManagerBase<P> for AppHandle<P> {
|
||||
fn runtime(&self) -> RuntimeOrDispatch<'_, P> {
|
||||
RuntimeOrDispatch::RuntimeHandle(self.runtime_handle.clone())
|
||||
}
|
||||
|
||||
fn app_handle(&self) -> AppHandle<P> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
crate::manager::default_args! {
|
||||
@ -156,6 +162,7 @@ crate::manager::default_args! {
|
||||
pub struct App<P: Params> {
|
||||
runtime: Option<P::Runtime>,
|
||||
manager: WindowManager<P>,
|
||||
global_shortcut_manager: <P::Runtime as Runtime>::GlobalShortcutManager,
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_handle: Option<tray::SystemTrayHandle<P>>,
|
||||
handle: AppHandle<P>,
|
||||
@ -171,6 +178,10 @@ impl<P: Params> ManagerBase<P> for App<P> {
|
||||
fn runtime(&self) -> RuntimeOrDispatch<'_, P> {
|
||||
RuntimeOrDispatch::Runtime(self.runtime.as_ref().unwrap())
|
||||
}
|
||||
|
||||
fn app_handle(&self) -> AppHandle<P> {
|
||||
self.handle()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! shared_app_impl {
|
||||
@ -209,6 +220,11 @@ macro_rules! shared_app_impl {
|
||||
.expect("tray not configured; use the `Builder#system_tray` API first.")
|
||||
}
|
||||
|
||||
/// Gets a copy of the global shortcut manager instance.
|
||||
pub fn global_shortcut_manager(&self) -> <P::Runtime as Runtime>::GlobalShortcutManager {
|
||||
self.global_shortcut_manager.clone()
|
||||
}
|
||||
|
||||
/// The path resolver for the application.
|
||||
pub fn path_resolver(&self) -> PathResolver {
|
||||
PathResolver {
|
||||
@ -700,15 +716,18 @@ where
|
||||
|
||||
let runtime = R::new()?;
|
||||
let runtime_handle = runtime.handle();
|
||||
let global_shortcut_manager = runtime.global_shortcut_manager();
|
||||
|
||||
let mut app = App {
|
||||
runtime: Some(runtime),
|
||||
manager: manager.clone(),
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_handle: None,
|
||||
handle: AppHandle {
|
||||
runtime_handle,
|
||||
manager,
|
||||
global_shortcut_manager,
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_handle: None,
|
||||
},
|
||||
@ -726,9 +745,11 @@ where
|
||||
let mut main_window = None;
|
||||
|
||||
for pending in self.pending_windows {
|
||||
let pending = app.manager.prepare_window(pending, &pending_labels)?;
|
||||
let pending = app
|
||||
.manager
|
||||
.prepare_window(app.handle.clone(), pending, &pending_labels)?;
|
||||
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
|
||||
let _window = app.manager.attach_window(detached);
|
||||
let _window = app.manager.attach_window(app.handle(), detached);
|
||||
#[cfg(feature = "updater")]
|
||||
if main_window.is_none() {
|
||||
main_window = Some(_window);
|
||||
|
@ -13,7 +13,7 @@ pub use crate::{
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub(crate) fn get_menu_ids<I: MenuId>(map: &mut HashMap<u32, I>, menu: &SystemTrayMenu<I>) {
|
||||
pub(crate) fn get_menu_ids<I: MenuId>(map: &mut HashMap<u16, I>, menu: &SystemTrayMenu<I>) {
|
||||
for item in &menu.items {
|
||||
match item {
|
||||
SystemTrayMenuEntry::CustomItem(c) => {
|
||||
@ -78,7 +78,7 @@ pub enum SystemTrayEvent<I: MenuId> {
|
||||
crate::manager::default_args! {
|
||||
/// A handle to a system tray. Allows updating the context menu items.
|
||||
pub struct SystemTrayHandle<P: Params> {
|
||||
pub(crate) ids: Arc<HashMap<u32, P::SystemTrayMenuId>>,
|
||||
pub(crate) ids: Arc<HashMap<u16, P::SystemTrayMenuId>>,
|
||||
pub(crate) inner: <P::Runtime as Runtime>::TrayHandler,
|
||||
}
|
||||
}
|
||||
@ -95,7 +95,7 @@ impl<P: Params> Clone for SystemTrayHandle<P> {
|
||||
crate::manager::default_args! {
|
||||
/// A handle to a system tray menu item.
|
||||
pub struct SystemTrayMenuItemHandle<P: Params> {
|
||||
id: u32,
|
||||
id: u16,
|
||||
tray_handler: <P::Runtime as Runtime>::TrayHandler,
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,7 @@ use crate::{Params, Window};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg(global_shortcut_all)]
|
||||
use crate::{api::shortcuts::ShortcutManager, runtime::Dispatch};
|
||||
|
||||
#[cfg(global_shortcut_all)]
|
||||
type ShortcutManagerHandle = std::sync::Arc<std::sync::Mutex<ShortcutManager>>;
|
||||
|
||||
#[cfg(global_shortcut_all)]
|
||||
pub fn manager_handle() -> &'static ShortcutManagerHandle {
|
||||
use once_cell::sync::Lazy;
|
||||
static MANAGER: Lazy<ShortcutManagerHandle> = Lazy::new(Default::default);
|
||||
&MANAGER
|
||||
}
|
||||
use crate::runtime::{GlobalShortcutManager, Runtime};
|
||||
|
||||
/// The API descriptor.
|
||||
#[derive(Deserialize)]
|
||||
@ -39,16 +29,17 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
#[cfg(global_shortcut_all)]
|
||||
fn register_shortcut<D: Dispatch>(
|
||||
dispatcher: D,
|
||||
manager: &mut ShortcutManager,
|
||||
fn register_shortcut<P: Params>(
|
||||
window: Window<P>,
|
||||
manager: &mut <P::Runtime as Runtime>::GlobalShortcutManager,
|
||||
shortcut: String,
|
||||
handler: String,
|
||||
) -> crate::Result<()> {
|
||||
manager.register(shortcut.clone(), move || {
|
||||
let callback_string = crate::api::rpc::format_callback(handler.to_string(), &shortcut)
|
||||
let accelerator = shortcut.clone();
|
||||
manager.register(&shortcut, move || {
|
||||
let callback_string = crate::api::rpc::format_callback(handler.to_string(), &accelerator)
|
||||
.expect("unable to serialize shortcut string to json");
|
||||
let _ = dispatcher.eval_script(callback_string.as_str());
|
||||
let _ = window.eval(callback_string.as_str());
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
@ -67,34 +58,38 @@ impl Cmd {
|
||||
pub fn run<P: Params>(self, window: Window<P>) -> crate::Result<InvokeResponse> {
|
||||
match self {
|
||||
Self::Register { shortcut, handler } => {
|
||||
let dispatcher = window.dispatcher();
|
||||
let mut manager = manager_handle().lock().unwrap();
|
||||
register_shortcut(dispatcher, &mut manager, shortcut, handler)?;
|
||||
let mut manager = window.app_handle.global_shortcut_manager();
|
||||
register_shortcut(window, &mut manager, shortcut, handler)?;
|
||||
Ok(().into())
|
||||
}
|
||||
Self::RegisterAll { shortcuts, handler } => {
|
||||
let dispatcher = window.dispatcher();
|
||||
let mut manager = manager_handle().lock().unwrap();
|
||||
let mut manager = window.app_handle.global_shortcut_manager();
|
||||
for shortcut in shortcuts {
|
||||
let dispatch = dispatcher.clone();
|
||||
register_shortcut(dispatch, &mut manager, shortcut, handler.clone())?;
|
||||
register_shortcut(window.clone(), &mut manager, shortcut, handler.clone())?;
|
||||
}
|
||||
Ok(().into())
|
||||
}
|
||||
Self::Unregister { shortcut } => {
|
||||
let mut manager = manager_handle().lock().unwrap();
|
||||
manager.unregister(shortcut)?;
|
||||
window
|
||||
.app_handle
|
||||
.global_shortcut_manager()
|
||||
.unregister(&shortcut)?;
|
||||
Ok(().into())
|
||||
}
|
||||
Self::UnregisterAll => {
|
||||
let mut manager = manager_handle().lock().unwrap();
|
||||
manager.unregister_all()?;
|
||||
window
|
||||
.app_handle
|
||||
.global_shortcut_manager()
|
||||
.unregister_all()?;
|
||||
Ok(().into())
|
||||
}
|
||||
Self::IsRegistered { shortcut } => {
|
||||
let manager = manager_handle().lock().unwrap();
|
||||
Ok(manager.is_registered(shortcut)?.into())
|
||||
}
|
||||
Self::IsRegistered { shortcut } => Ok(
|
||||
window
|
||||
.app_handle
|
||||
.global_shortcut_manager()
|
||||
.is_registered(&shortcut)?
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ pub trait Manager<P: Params>: sealed::ManagerBase<P> {
|
||||
|
||||
/// Prevent implementation details from leaking out of the [`Manager`] trait.
|
||||
pub(crate) mod sealed {
|
||||
use crate::manager::WindowManager;
|
||||
use crate::{app::AppHandle, manager::WindowManager};
|
||||
use tauri_runtime::{Params, Runtime, RuntimeHandle};
|
||||
|
||||
/// A running [`Runtime`] or a dispatcher to it.
|
||||
@ -361,6 +361,7 @@ pub(crate) mod sealed {
|
||||
fn manager(&self) -> &WindowManager<P>;
|
||||
|
||||
fn runtime(&self) -> RuntimeOrDispatch<'_, P>;
|
||||
fn app_handle(&self) -> AppHandle<P>;
|
||||
|
||||
/// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
|
||||
fn create_new_window(
|
||||
@ -369,7 +370,9 @@ pub(crate) mod sealed {
|
||||
) -> crate::Result<crate::Window<P>> {
|
||||
use crate::runtime::Dispatch;
|
||||
let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
|
||||
let pending = self.manager().prepare_window(pending, &labels)?;
|
||||
let pending = self
|
||||
.manager()
|
||||
.prepare_window(self.app_handle(), pending, &labels)?;
|
||||
match self.runtime() {
|
||||
RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending).map_err(Into::into),
|
||||
RuntimeOrDispatch::RuntimeHandle(handle) => {
|
||||
@ -379,7 +382,7 @@ pub(crate) mod sealed {
|
||||
dispatcher.create_window(pending).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
.map(|window| self.manager().attach_window(window))
|
||||
.map(|window| self.manager().attach_window(self.app_handle(), window))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
path::{resolve_path, BaseDirectory},
|
||||
PackageInfo,
|
||||
},
|
||||
app::{GlobalWindowEvent, GlobalWindowEventListener},
|
||||
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener},
|
||||
event::{Event, EventHandler, Listeners},
|
||||
hooks::{InvokeHandler, OnPageLoad, PageLoadPayload},
|
||||
plugin::PluginStore,
|
||||
@ -101,7 +101,7 @@ crate::manager::default_args! {
|
||||
menu: Option<Menu<P::MenuId>>,
|
||||
/// Maps runtime id to a strongly typed menu id.
|
||||
#[cfg(feature = "menu")]
|
||||
menu_ids: HashMap<u32, P::MenuId>,
|
||||
menu_ids: HashMap<u16, P::MenuId>,
|
||||
/// Menu event listeners to all windows.
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: Arc<Vec<GlobalMenuEventListener<P>>>,
|
||||
@ -209,7 +209,7 @@ impl<P: Params> Clone for WindowManager<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "menu")]
|
||||
fn get_menu_ids<I: MenuId>(map: &mut HashMap<u32, I>, menu: &Menu<I>) {
|
||||
fn get_menu_ids<I: MenuId>(map: &mut HashMap<u16, I>, menu: &Menu<I>) {
|
||||
for item in &menu.items {
|
||||
match item {
|
||||
MenuEntry::CustomItem(c) => {
|
||||
@ -280,7 +280,7 @@ impl<P: Params> WindowManager<P> {
|
||||
|
||||
/// Get the menu ids mapper.
|
||||
#[cfg(feature = "menu")]
|
||||
pub(crate) fn menu_ids(&self) -> HashMap<u32, P::MenuId> {
|
||||
pub(crate) fn menu_ids(&self) -> HashMap<u16, P::MenuId> {
|
||||
self.inner.menu_ids.clone()
|
||||
}
|
||||
|
||||
@ -371,10 +371,10 @@ impl<P: Params> WindowManager<P> {
|
||||
Ok(pending)
|
||||
}
|
||||
|
||||
fn prepare_rpc_handler(&self) -> WebviewRpcHandler<P> {
|
||||
fn prepare_rpc_handler(&self, app_handle: AppHandle<P>) -> WebviewRpcHandler<P> {
|
||||
let manager = self.clone();
|
||||
Box::new(move |window, request| {
|
||||
let window = Window::new(manager.clone(), window);
|
||||
let window = Window::new(manager.clone(), window, app_handle.clone());
|
||||
let command = request.command.clone();
|
||||
|
||||
let arg = request
|
||||
@ -446,12 +446,13 @@ impl<P: Params> WindowManager<P> {
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_file_drop(&self) -> FileDropHandler<P> {
|
||||
fn prepare_file_drop(&self, app_handle: AppHandle<P>) -> FileDropHandler<P> {
|
||||
let manager = self.clone();
|
||||
Box::new(move |event, window| {
|
||||
let manager = manager.clone();
|
||||
let app_handle = app_handle.clone();
|
||||
crate::async_runtime::block_on(async move {
|
||||
let window = Window::new(manager.clone(), window);
|
||||
let window = Window::new(manager.clone(), window, app_handle);
|
||||
let _ = match event {
|
||||
FileDropEvent::Hovered(paths) => {
|
||||
window.emit(&tauri_event::<P::Event>("tauri://file-drop"), Some(paths))
|
||||
@ -604,6 +605,7 @@ impl<P: Params> WindowManager<P> {
|
||||
|
||||
pub fn prepare_window(
|
||||
&self,
|
||||
app_handle: AppHandle<P>,
|
||||
mut pending: PendingWindow<P>,
|
||||
pending_labels: &[P::Label],
|
||||
) -> crate::Result<PendingWindow<P>> {
|
||||
@ -627,19 +629,19 @@ impl<P: Params> WindowManager<P> {
|
||||
if is_local {
|
||||
let label = pending.label.clone();
|
||||
pending = self.prepare_pending_window(pending, label, pending_labels)?;
|
||||
pending.rpc_handler = Some(self.prepare_rpc_handler());
|
||||
pending.rpc_handler = Some(self.prepare_rpc_handler(app_handle.clone()));
|
||||
}
|
||||
|
||||
if pending.webview_attributes.file_drop_handler_enabled {
|
||||
pending.file_drop_handler = Some(self.prepare_file_drop());
|
||||
pending.file_drop_handler = Some(self.prepare_file_drop(app_handle));
|
||||
}
|
||||
pending.url = url;
|
||||
|
||||
Ok(pending)
|
||||
}
|
||||
|
||||
pub fn attach_window(&self, window: DetachedWindow<P>) -> Window<P> {
|
||||
let window = Window::new(self.clone(), window);
|
||||
pub fn attach_window(&self, app_handle: AppHandle<P>, window: DetachedWindow<P>) -> Window<P> {
|
||||
let window = Window::new(self.clone(), window, app_handle);
|
||||
|
||||
let window_ = window.clone();
|
||||
let window_event_listeners = self.inner.window_event_listeners.clone();
|
||||
|
@ -8,6 +8,7 @@ pub(crate) mod menu;
|
||||
|
||||
use crate::{
|
||||
api::config::WindowUrl,
|
||||
app::AppHandle,
|
||||
command::{CommandArg, CommandItem},
|
||||
event::{Event, EventHandler},
|
||||
manager::WindowManager,
|
||||
@ -85,11 +86,10 @@ crate::manager::default_args! {
|
||||
/// the same application.
|
||||
pub struct Window<P: Params> {
|
||||
/// The webview window created by the runtime.
|
||||
/// ok
|
||||
window: DetachedWindow<P>,
|
||||
|
||||
/// The manager to associate this webview window with.
|
||||
manager: WindowManager<P>,
|
||||
pub(crate) app_handle: AppHandle<P>,
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +98,7 @@ impl<P: Params> Clone for Window<P> {
|
||||
Self {
|
||||
window: self.window.clone(),
|
||||
manager: self.manager.clone(),
|
||||
app_handle: self.app_handle.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,6 +124,10 @@ impl<P: Params> ManagerBase<P> for Window<P> {
|
||||
&self.manager
|
||||
}
|
||||
|
||||
fn app_handle(&self) -> AppHandle<P> {
|
||||
self.app_handle.clone()
|
||||
}
|
||||
|
||||
fn runtime(&self) -> RuntimeOrDispatch<'_, P> {
|
||||
RuntimeOrDispatch::Dispatch(self.dispatcher())
|
||||
}
|
||||
@ -137,8 +142,16 @@ impl<'de, P: Params> CommandArg<'de, P> for Window<P> {
|
||||
|
||||
impl<P: Params> Window<P> {
|
||||
/// Create a new window that is attached to the manager.
|
||||
pub(crate) fn new(manager: WindowManager<P>, window: DetachedWindow<P>) -> Self {
|
||||
Self { window, manager }
|
||||
pub(crate) fn new(
|
||||
manager: WindowManager<P>,
|
||||
window: DetachedWindow<P>,
|
||||
app_handle: AppHandle<P>,
|
||||
) -> Self {
|
||||
Self {
|
||||
window,
|
||||
manager,
|
||||
app_handle,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new webview window.
|
||||
|
@ -27,7 +27,7 @@ impl<I: MenuId> MenuEvent<I> {
|
||||
crate::manager::default_args! {
|
||||
/// A handle to a system tray. Allows updating the context menu items.
|
||||
pub struct MenuHandle<P: Params> {
|
||||
pub(crate) ids: HashMap<u32, P::MenuId>,
|
||||
pub(crate) ids: HashMap<u16, P::MenuId>,
|
||||
pub(crate) dispatcher: <P::Runtime as Runtime>::Dispatcher,
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ impl<P: Params> Clone for MenuHandle<P> {
|
||||
crate::manager::default_args! {
|
||||
/// A handle to a system tray menu item.
|
||||
pub struct MenuItemHandle<P: Params> {
|
||||
id: u32,
|
||||
id: u16,
|
||||
dispatcher: <P::Runtime as Runtime>::Dispatcher,
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ describe('[CLI] cli.js template', () => {
|
||||
const manifestFile = readFileSync(manifestPath).toString()
|
||||
writeFileSync(
|
||||
manifestPath,
|
||||
`workspace = { }\n[patch.crates-io]\ntao = { git = "https://github.com/tauri-apps/tao", rev = "66360eea4ec6af8a52afcebb7700f486a0092168" }\n\n${manifestFile}`
|
||||
`workspace = { }\n[patch.crates-io]\ntao = { git = "https://github.com/tauri-apps/tao", rev = "01fc43b05ea41463d512c0e3497971edc543ac9d" }\n\n${manifestFile}`
|
||||
)
|
||||
|
||||
const { promise: buildPromise } = await build()
|
||||
|
Loading…
Reference in New Issue
Block a user