mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-05 10:13:00 +02:00
* refactor(core): window id * fixes * reintroduce send_tao_window_event * cleanup code * add change file * fix: windows build * add getter * fix windows build
This commit is contained in:
committed by
GitHub
parent
c4ca80f919
commit
7cd39c70c9
5
.changes/simplify-window-creation.md
Normal file
5
.changes/simplify-window-creation.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-runtime-wry": minor
|
||||
---
|
||||
|
||||
Use a random window id instead of `tao::window::WindowId` to not block the thread waiting for the event loop to process the window creation.
|
||||
@@ -17,6 +17,7 @@ wry = { version = "0.13.3", default-features = false, features = [ "file-drop",
|
||||
tauri-runtime = { version = "0.3.3", path = "../tauri-runtime" }
|
||||
tauri-utils = { version = "1.0.0-rc.3", path = "../tauri-utils" }
|
||||
uuid = { version = "0.8.2", features = [ "v4" ] }
|
||||
rand = "0.8"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
webview2-com = "0.13.0"
|
||||
|
||||
@@ -70,7 +70,7 @@ use wry::{
|
||||
|
||||
pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder, WindowId};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg(windows)]
|
||||
use wry::webview::WebviewExtWindows;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -96,6 +96,8 @@ use std::{
|
||||
thread::{current as current_thread, ThreadId},
|
||||
};
|
||||
|
||||
type WebviewId = u64;
|
||||
|
||||
#[cfg(feature = "system-tray")]
|
||||
mod system_tray;
|
||||
#[cfg(feature = "system-tray")]
|
||||
@@ -105,14 +107,27 @@ type WebContextStore = Arc<Mutex<HashMap<Option<PathBuf>, WebContext>>>;
|
||||
// window
|
||||
type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
|
||||
type WindowEventListenersMap = Arc<Mutex<HashMap<Uuid, WindowEventHandler>>>;
|
||||
type WindowEventListeners = Arc<Mutex<HashMap<WindowId, WindowEventListenersMap>>>;
|
||||
type WindowEventListeners = Arc<Mutex<HashMap<WebviewId, WindowEventListenersMap>>>;
|
||||
// global shortcut
|
||||
type GlobalShortcutListeners = Arc<Mutex<HashMap<AcceleratorId, Box<dyn Fn() + Send>>>>;
|
||||
// menu
|
||||
pub type MenuEventHandler = Box<dyn Fn(&MenuEvent) + Send>;
|
||||
pub type MenuEventListeners = Arc<Mutex<HashMap<WindowId, WindowMenuEventListeners>>>;
|
||||
pub type MenuEventListeners = Arc<Mutex<HashMap<WebviewId, WindowMenuEventListeners>>>;
|
||||
pub type WindowMenuEventListeners = Arc<Mutex<HashMap<Uuid, MenuEventHandler>>>;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct WebviewIdStore(Arc<Mutex<HashMap<WindowId, WebviewId>>>);
|
||||
|
||||
impl WebviewIdStore {
|
||||
fn insert(&self, w: WindowId, id: WebviewId) {
|
||||
self.0.lock().unwrap().insert(w, id);
|
||||
}
|
||||
|
||||
fn get(&self, w: &WindowId) -> WebviewId {
|
||||
*self.0.lock().unwrap().get(w).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! getter {
|
||||
($self: ident, $rx: expr, $message: expr) => {{
|
||||
send_user_message(&$self.context, $message)?;
|
||||
@@ -154,6 +169,7 @@ fn send_user_message<T: UserEvent>(context: &Context<T>, message: Message<T>) ->
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Context<T: UserEvent> {
|
||||
webview_id_map: WebviewIdStore,
|
||||
main_thread_id: ThreadId,
|
||||
proxy: WryEventLoopProxy<Message<T>>,
|
||||
window_event_listeners: WindowEventListeners,
|
||||
@@ -161,13 +177,60 @@ struct Context<T: UserEvent> {
|
||||
main_thread: DispatcherMainThreadContext<T>,
|
||||
}
|
||||
|
||||
impl<T: UserEvent> Context<T> {
|
||||
fn prepare_window(&self, window_id: WebviewId) {
|
||||
self
|
||||
.window_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window_id, WindowEventListenersMap::default());
|
||||
|
||||
self
|
||||
.menu_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window_id, WindowMenuEventListeners::default());
|
||||
}
|
||||
|
||||
fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> {
|
||||
let label = pending.label.clone();
|
||||
let menu_ids = pending.menu_ids.clone();
|
||||
let js_event_listeners = pending.js_event_listeners.clone();
|
||||
let context = self.clone();
|
||||
let window_id = rand::random();
|
||||
|
||||
self.prepare_window(window_id);
|
||||
|
||||
self
|
||||
.proxy
|
||||
.send_event(Message::CreateWebview(
|
||||
window_id,
|
||||
Box::new(move |event_loop, web_context| {
|
||||
create_webview(window_id, event_loop, web_context, context, pending)
|
||||
}),
|
||||
))
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
|
||||
let dispatcher = WryDispatcher {
|
||||
window_id,
|
||||
context: self.clone(),
|
||||
};
|
||||
Ok(DetachedWindow {
|
||||
label,
|
||||
dispatcher,
|
||||
menu_ids,
|
||||
js_event_listeners,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct DispatcherMainThreadContext<T: UserEvent> {
|
||||
window_target: EventLoopWindowTarget<Message<T>>,
|
||||
web_context: WebContextStore,
|
||||
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
|
||||
clipboard_manager: Arc<Mutex<Clipboard>>,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: TrayContext,
|
||||
}
|
||||
@@ -827,7 +890,7 @@ impl WindowBuilder for WindowBuilderWrapper {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
#[cfg(any(windows, target_os = "linux"))]
|
||||
fn skip_taskbar(mut self, skip: bool) -> Self {
|
||||
self.inner = self.inner.with_skip_taskbar(skip);
|
||||
self
|
||||
@@ -996,12 +1059,13 @@ pub type CreateWebviewClosure<T> = Box<
|
||||
|
||||
pub enum Message<T: 'static> {
|
||||
Task(Box<dyn FnOnce() + Send>),
|
||||
Window(WindowId, WindowMessage),
|
||||
Webview(WindowId, WebviewMessage),
|
||||
Window(WebviewId, WindowMessage),
|
||||
Webview(WebviewId, WebviewMessage),
|
||||
#[cfg(feature = "system-tray")]
|
||||
Tray(TrayMessage),
|
||||
CreateWebview(CreateWebviewClosure<T>, Sender<WindowId>),
|
||||
CreateWebview(WebviewId, CreateWebviewClosure<T>),
|
||||
CreateWindow(
|
||||
WebviewId,
|
||||
Box<dyn FnOnce() -> (String, WryWindowBuilder) + Send>,
|
||||
Sender<Result<Weak<Window>>>,
|
||||
),
|
||||
@@ -1028,7 +1092,7 @@ impl<T: UserEvent> Clone for Message<T> {
|
||||
/// The Tauri [`Dispatch`] for [`Wry`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WryDispatcher<T: UserEvent> {
|
||||
window_id: WindowId,
|
||||
window_id: WebviewId,
|
||||
context: Context<T>,
|
||||
}
|
||||
|
||||
@@ -1198,33 +1262,7 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
|
||||
&mut self,
|
||||
pending: PendingWindow<T, Self::Runtime>,
|
||||
) -> Result<DetachedWindow<T, Self::Runtime>> {
|
||||
let (tx, rx) = channel();
|
||||
let label = pending.label.clone();
|
||||
let menu_ids = pending.menu_ids.clone();
|
||||
let js_event_listeners = pending.js_event_listeners.clone();
|
||||
let context = self.context.clone();
|
||||
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::CreateWebview(
|
||||
Box::new(move |event_loop, web_context| {
|
||||
create_webview(event_loop, web_context, context, pending)
|
||||
}),
|
||||
tx,
|
||||
),
|
||||
)?;
|
||||
let window_id = rx.recv().unwrap();
|
||||
|
||||
let dispatcher = WryDispatcher {
|
||||
window_id,
|
||||
context: self.context.clone(),
|
||||
};
|
||||
Ok(DetachedWindow {
|
||||
label,
|
||||
dispatcher,
|
||||
menu_ids,
|
||||
js_event_listeners,
|
||||
})
|
||||
self.context.create_webview(pending)
|
||||
}
|
||||
|
||||
fn set_resizable(&self, resizable: bool) -> Result<()> {
|
||||
@@ -1475,7 +1513,8 @@ pub struct Wry<T: UserEvent> {
|
||||
clipboard_manager: Arc<Mutex<Clipboard>>,
|
||||
clipboard_manager_handle: ClipboardManagerWrapper<T>,
|
||||
event_loop: EventLoop<Message<T>>,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
|
||||
webview_id_map: WebviewIdStore,
|
||||
web_context: WebContextStore,
|
||||
window_event_listeners: WindowEventListeners,
|
||||
menu_event_listeners: MenuEventListeners,
|
||||
@@ -1520,10 +1559,25 @@ impl<T: UserEvent> WryHandle<T> {
|
||||
f: F,
|
||||
) -> Result<Weak<Window>> {
|
||||
let (tx, rx) = channel();
|
||||
send_user_message(&self.context, Message::CreateWindow(Box::new(f), tx))?;
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::CreateWindow(rand::random(), Box::new(f), tx),
|
||||
)?;
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
|
||||
/// Gets the [`WebviewId'] associated with the given [`WindowId`].
|
||||
pub fn window_id(&self, window_id: WindowId) -> WebviewId {
|
||||
*self
|
||||
.context
|
||||
.webview_id_map
|
||||
.0
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&window_id)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Send a message to the event loop.
|
||||
pub fn send_event(&self, message: Message<T>) -> Result<()> {
|
||||
self
|
||||
@@ -1548,32 +1602,7 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
|
||||
&self,
|
||||
pending: PendingWindow<T, Self::Runtime>,
|
||||
) -> Result<DetachedWindow<T, Self::Runtime>> {
|
||||
let (tx, rx) = channel();
|
||||
let label = pending.label.clone();
|
||||
let menu_ids = pending.menu_ids.clone();
|
||||
let js_event_listeners = pending.js_event_listeners.clone();
|
||||
let context = self.context.clone();
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::CreateWebview(
|
||||
Box::new(move |event_loop, web_context| {
|
||||
create_webview(event_loop, web_context, context, pending)
|
||||
}),
|
||||
tx,
|
||||
),
|
||||
)?;
|
||||
let window_id = rx.recv().unwrap();
|
||||
|
||||
let dispatcher = WryDispatcher {
|
||||
window_id,
|
||||
context: self.context.clone(),
|
||||
};
|
||||
Ok(DetachedWindow {
|
||||
label,
|
||||
dispatcher,
|
||||
menu_ids,
|
||||
js_event_listeners,
|
||||
})
|
||||
self.context.create_webview(pending)
|
||||
}
|
||||
|
||||
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
|
||||
@@ -1595,6 +1624,7 @@ impl<T: UserEvent> Wry<T> {
|
||||
let global_shortcut_manager = Arc::new(Mutex::new(WryShortcutManager::new(&event_loop)));
|
||||
let clipboard_manager = Arc::new(Mutex::new(Clipboard::new()));
|
||||
let windows = Arc::new(Mutex::new(HashMap::default()));
|
||||
let webview_id_map = WebviewIdStore::default();
|
||||
let window_event_listeners = WindowEventListeners::default();
|
||||
let menu_event_listeners = MenuEventListeners::default();
|
||||
|
||||
@@ -1602,6 +1632,7 @@ impl<T: UserEvent> Wry<T> {
|
||||
let tray_context = TrayContext::default();
|
||||
|
||||
let event_loop_context = Context {
|
||||
webview_id_map: webview_id_map.clone(),
|
||||
main_thread_id,
|
||||
proxy,
|
||||
window_event_listeners: window_event_listeners.clone(),
|
||||
@@ -1634,6 +1665,7 @@ impl<T: UserEvent> Wry<T> {
|
||||
clipboard_manager_handle,
|
||||
event_loop,
|
||||
windows,
|
||||
webview_id_map,
|
||||
web_context,
|
||||
window_event_listeners,
|
||||
menu_event_listeners,
|
||||
@@ -1674,6 +1706,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
fn handle(&self) -> Self::Handle {
|
||||
WryHandle {
|
||||
context: Context {
|
||||
webview_id_map: self.webview_id_map.clone(),
|
||||
main_thread_id: self.main_thread_id,
|
||||
proxy: self.event_loop.create_proxy(),
|
||||
window_event_listeners: self.window_event_listeners.clone(),
|
||||
@@ -1704,89 +1737,38 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
let menu_ids = pending.menu_ids.clone();
|
||||
let js_event_listeners = pending.js_event_listeners.clone();
|
||||
let proxy = self.event_loop.create_proxy();
|
||||
let webview = create_webview(
|
||||
&self.event_loop,
|
||||
&self.web_context,
|
||||
Context {
|
||||
main_thread_id: self.main_thread_id,
|
||||
proxy: proxy.clone(),
|
||||
window_event_listeners: self.window_event_listeners.clone(),
|
||||
menu_event_listeners: self.menu_event_listeners.clone(),
|
||||
main_thread: DispatcherMainThreadContext {
|
||||
window_target: self.event_loop.deref().clone(),
|
||||
web_context: self.web_context.clone(),
|
||||
global_shortcut_manager: self.global_shortcut_manager.clone(),
|
||||
clipboard_manager: self.clipboard_manager.clone(),
|
||||
windows: self.windows.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: self.tray_context.clone(),
|
||||
},
|
||||
},
|
||||
pending,
|
||||
)?;
|
||||
let window_id = rand::random();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let id = webview.inner.window().id();
|
||||
if let WindowHandle::Webview(ref webview) = webview.inner {
|
||||
if let Some(controller) = webview.controller() {
|
||||
let proxy = self.event_loop.create_proxy();
|
||||
let mut token = EventRegistrationToken::default();
|
||||
unsafe {
|
||||
controller.GotFocus(
|
||||
FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||
let _ = proxy.send_event(Message::Webview(
|
||||
id,
|
||||
WebviewMessage::WebviewEvent(WebviewEvent::Focused(true)),
|
||||
));
|
||||
Ok(())
|
||||
})),
|
||||
&mut token,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
let proxy = self.event_loop.create_proxy();
|
||||
unsafe {
|
||||
controller.LostFocus(
|
||||
FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||
let _ = proxy.send_event(Message::Webview(
|
||||
id,
|
||||
WebviewMessage::WebviewEvent(WebviewEvent::Focused(false)),
|
||||
));
|
||||
Ok(())
|
||||
})),
|
||||
&mut token,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dispatcher = WryDispatcher {
|
||||
window_id: webview.inner.window().id(),
|
||||
context: Context {
|
||||
main_thread_id: self.main_thread_id,
|
||||
proxy,
|
||||
window_event_listeners: self.window_event_listeners.clone(),
|
||||
menu_event_listeners: self.menu_event_listeners.clone(),
|
||||
main_thread: DispatcherMainThreadContext {
|
||||
window_target: self.event_loop.deref().clone(),
|
||||
web_context: self.web_context.clone(),
|
||||
global_shortcut_manager: self.global_shortcut_manager.clone(),
|
||||
clipboard_manager: self.clipboard_manager.clone(),
|
||||
windows: self.windows.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: self.tray_context.clone(),
|
||||
},
|
||||
let context = Context {
|
||||
webview_id_map: self.webview_id_map.clone(),
|
||||
main_thread_id: self.main_thread_id,
|
||||
proxy,
|
||||
window_event_listeners: self.window_event_listeners.clone(),
|
||||
menu_event_listeners: self.menu_event_listeners.clone(),
|
||||
main_thread: DispatcherMainThreadContext {
|
||||
window_target: self.event_loop.deref().clone(),
|
||||
web_context: self.web_context.clone(),
|
||||
global_shortcut_manager: self.global_shortcut_manager.clone(),
|
||||
clipboard_manager: self.clipboard_manager.clone(),
|
||||
windows: self.windows.clone(),
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: self.tray_context.clone(),
|
||||
},
|
||||
};
|
||||
|
||||
self
|
||||
.windows
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(webview.inner.window().id(), webview);
|
||||
context.prepare_window(window_id);
|
||||
|
||||
let webview = create_webview(
|
||||
window_id,
|
||||
&self.event_loop,
|
||||
&self.web_context,
|
||||
context.clone(),
|
||||
pending,
|
||||
)?;
|
||||
|
||||
let dispatcher = WryDispatcher { window_id, context };
|
||||
|
||||
self.windows.lock().unwrap().insert(window_id, webview);
|
||||
|
||||
Ok(DetachedWindow {
|
||||
label,
|
||||
@@ -1861,6 +1843,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
|
||||
use wry::application::platform::run_return::EventLoopExtRunReturn;
|
||||
let windows = self.windows.clone();
|
||||
let webview_id_map = self.webview_id_map.clone();
|
||||
let web_context = &self.web_context;
|
||||
let window_event_listeners = self.window_event_listeners.clone();
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
@@ -1886,6 +1869,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
EventLoopIterationContext {
|
||||
callback: &mut callback,
|
||||
windows: windows.clone(),
|
||||
webview_id_map: webview_id_map.clone(),
|
||||
window_event_listeners: &window_event_listeners,
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
global_shortcut_manager_handle: &global_shortcut_manager_handle,
|
||||
@@ -1903,6 +1887,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
|
||||
fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
|
||||
let windows = self.windows.clone();
|
||||
let webview_id_map = self.webview_id_map.clone();
|
||||
let web_context = self.web_context;
|
||||
let window_event_listeners = self.window_event_listeners.clone();
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
@@ -1919,6 +1904,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
control_flow,
|
||||
EventLoopIterationContext {
|
||||
callback: &mut callback,
|
||||
webview_id_map: webview_id_map.clone(),
|
||||
windows: windows.clone(),
|
||||
window_event_listeners: &window_event_listeners,
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
@@ -1936,7 +1922,8 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
||||
|
||||
pub struct EventLoopIterationContext<'a, T: UserEvent> {
|
||||
callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
webview_id_map: WebviewIdStore,
|
||||
windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
|
||||
window_event_listeners: &'a WindowEventListeners,
|
||||
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
|
||||
global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle<T>,
|
||||
@@ -1951,7 +1938,7 @@ struct UserMessageContext<'a> {
|
||||
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
|
||||
clipboard_manager: Arc<Mutex<Clipboard>>,
|
||||
menu_event_listeners: &'a MenuEventListeners,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: &'a TrayContext,
|
||||
}
|
||||
@@ -2081,7 +2068,7 @@ fn handle_user_message<T: UserEvent>(
|
||||
window.set_window_icon(Some(icon));
|
||||
}
|
||||
WindowMessage::SetSkipTaskbar(_skip) => {
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
#[cfg(any(windows, target_os = "linux"))]
|
||||
window.set_skip_taskbar(_skip);
|
||||
}
|
||||
WindowMessage::DragWindow => {
|
||||
@@ -2147,34 +2134,30 @@ fn handle_user_message<T: UserEvent>(
|
||||
}
|
||||
}
|
||||
},
|
||||
Message::CreateWebview(handler, sender) => match handler(event_loop, web_context) {
|
||||
Message::CreateWebview(window_id, handler) => match handler(event_loop, web_context) {
|
||||
Ok(webview) => {
|
||||
let window_id = webview.inner.window().id();
|
||||
windows
|
||||
.lock()
|
||||
.expect("poisoned webview collection")
|
||||
.insert(window_id, webview);
|
||||
sender.send(window_id).unwrap();
|
||||
}
|
||||
Err(e) => {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
},
|
||||
Message::CreateWindow(handler, sender) => {
|
||||
Message::CreateWindow(window_id, handler, sender) => {
|
||||
let (label, builder) = handler();
|
||||
if let Ok(window) = builder.build(event_loop) {
|
||||
let window_id = window.id();
|
||||
|
||||
window_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window.id(), WindowEventListenersMap::default());
|
||||
.insert(window_id, WindowEventListenersMap::default());
|
||||
|
||||
menu_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window.id(), WindowMenuEventListeners::default());
|
||||
.insert(window_id, WindowMenuEventListeners::default());
|
||||
|
||||
let w = Arc::new(window);
|
||||
|
||||
@@ -2299,6 +2282,7 @@ fn handle_event_loop<T: UserEvent>(
|
||||
) -> RunIteration {
|
||||
let EventLoopIterationContext {
|
||||
callback,
|
||||
webview_id_map,
|
||||
windows,
|
||||
window_event_listeners,
|
||||
global_shortcut_manager,
|
||||
@@ -2347,6 +2331,7 @@ fn handle_event_loop<T: UserEvent>(
|
||||
menu_item_id: menu_id.0,
|
||||
};
|
||||
let window_menu_event_listeners = {
|
||||
let window_id = webview_id_map.get(&window_id);
|
||||
let listeners = menu_event_listeners.lock().unwrap();
|
||||
listeners.get(&window_id).cloned().unwrap_or_default()
|
||||
};
|
||||
@@ -2390,6 +2375,7 @@ fn handle_event_loop<T: UserEvent>(
|
||||
Event::WindowEvent {
|
||||
event, window_id, ..
|
||||
} => {
|
||||
let window_id = webview_id_map.get(&window_id);
|
||||
// NOTE(amrbashir): we handle this event here instead of `match` statement below because
|
||||
// we want to focus the webview as soon as possible, especially on windows.
|
||||
if event == WryWindowEvent::Focused(true) {
|
||||
@@ -2496,8 +2482,8 @@ fn handle_event_loop<T: UserEvent>(
|
||||
|
||||
fn on_close_requested<'a, T: UserEvent>(
|
||||
callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
|
||||
window_id: WindowId,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
window_id: WebviewId,
|
||||
windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
|
||||
control_flow: &mut ControlFlow,
|
||||
window_event_listeners: &WindowEventListeners,
|
||||
menu_event_listeners: MenuEventListeners,
|
||||
@@ -2545,8 +2531,8 @@ fn on_close_requested<'a, T: UserEvent>(
|
||||
|
||||
fn on_window_close<'a, T: UserEvent>(
|
||||
callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
|
||||
window_id: WindowId,
|
||||
mut windows: MutexGuard<'a, HashMap<WindowId, WindowWrapper>>,
|
||||
window_id: WebviewId,
|
||||
mut windows: MutexGuard<'a, HashMap<WebviewId, WindowWrapper>>,
|
||||
control_flow: &mut ControlFlow,
|
||||
#[cfg(target_os = "linux")] window_event_listeners: &WindowEventListeners,
|
||||
menu_event_listeners: MenuEventListeners,
|
||||
@@ -2641,6 +2627,7 @@ fn to_wry_menu(
|
||||
}
|
||||
|
||||
fn create_webview<T: UserEvent>(
|
||||
window_id: WebviewId,
|
||||
event_loop: &EventLoopWindowTarget<Message<T>>,
|
||||
web_context: &WebContextStore,
|
||||
context: Context<T>,
|
||||
@@ -2658,6 +2645,9 @@ fn create_webview<T: UserEvent>(
|
||||
js_event_listeners,
|
||||
..
|
||||
} = pending;
|
||||
let webview_id_map = context.webview_id_map.clone();
|
||||
#[cfg(windows)]
|
||||
let proxy = context.proxy.clone();
|
||||
|
||||
let is_window_transparent = window_builder.inner.window.transparent;
|
||||
let menu_items = if let Some(menu) = window_builder.menu {
|
||||
@@ -2670,18 +2660,6 @@ fn create_webview<T: UserEvent>(
|
||||
};
|
||||
let window = window_builder.inner.build(event_loop).unwrap();
|
||||
|
||||
context
|
||||
.window_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window.id(), WindowEventListenersMap::default());
|
||||
|
||||
context
|
||||
.menu_event_listeners
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(window.id(), WindowMenuEventListeners::default());
|
||||
|
||||
if window_builder.center {
|
||||
let _ = center_window(&window, window.inner_size());
|
||||
}
|
||||
@@ -2753,6 +2731,42 @@ fn create_webview<T: UserEvent>(
|
||||
.build()
|
||||
.map_err(|e| Error::CreateWebview(Box::new(e)))?;
|
||||
|
||||
webview_id_map.insert(webview.window().id(), window_id);
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(controller) = webview.controller() {
|
||||
let proxy_ = proxy.clone();
|
||||
let mut token = EventRegistrationToken::default();
|
||||
unsafe {
|
||||
controller.GotFocus(
|
||||
FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||
let _ = proxy_.send_event(Message::Webview(
|
||||
window_id,
|
||||
WebviewMessage::WebviewEvent(WebviewEvent::Focused(true)),
|
||||
));
|
||||
Ok(())
|
||||
})),
|
||||
&mut token,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
unsafe {
|
||||
controller.LostFocus(
|
||||
FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||
let _ = proxy.send_event(Message::Webview(
|
||||
window_id,
|
||||
WebviewMessage::WebviewEvent(WebviewEvent::Focused(false)),
|
||||
));
|
||||
Ok(())
|
||||
})),
|
||||
&mut token,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(WindowWrapper {
|
||||
label,
|
||||
inner: WindowHandle::Webview(webview),
|
||||
@@ -2772,7 +2786,13 @@ fn create_ipc_handler<T: UserEvent>(
|
||||
handler(
|
||||
DetachedWindow {
|
||||
dispatcher: WryDispatcher {
|
||||
window_id: window.id(),
|
||||
window_id: *context
|
||||
.webview_id_map
|
||||
.0
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&window.id())
|
||||
.unwrap(),
|
||||
context: context.clone(),
|
||||
},
|
||||
label: label.clone(),
|
||||
@@ -2789,11 +2809,12 @@ fn create_file_drop_handler<T: UserEvent>(
|
||||
context: &Context<T>,
|
||||
) -> Box<dyn Fn(&Window, WryFileDropEvent) -> bool + 'static> {
|
||||
let window_event_listeners = context.window_event_listeners.clone();
|
||||
let webview_id_map = context.webview_id_map.clone();
|
||||
Box::new(move |window, event| {
|
||||
let event: FileDropEvent = FileDropEventWrapper(event).into();
|
||||
let window_event = WindowEvent::FileDrop(event);
|
||||
let listeners = window_event_listeners.lock().unwrap();
|
||||
if let Some(window_listeners) = listeners.get(&window.id()) {
|
||||
if let Some(window_listeners) = listeners.get(&webview_id_map.get(&window.id())) {
|
||||
let listeners_map = window_listeners.lock().unwrap();
|
||||
let has_listener = !listeners_map.is_empty();
|
||||
for listener in listeners_map.values() {
|
||||
|
||||
@@ -51,7 +51,7 @@ uuid = { version = "0.8", features = [ "v4" ] }
|
||||
url = { version = "2.2" }
|
||||
anyhow = "1.0"
|
||||
thiserror = "1.0"
|
||||
once_cell = "1.9"
|
||||
once_cell = "1.10"
|
||||
tauri-runtime = { version = "0.3.3", path = "../tauri-runtime" }
|
||||
tauri-macros = { version = "1.0.0-rc.3", path = "../tauri-macros" }
|
||||
tauri-utils = { version = "1.0.0-rc.3", path = "../tauri-utils" }
|
||||
|
||||
@@ -247,7 +247,10 @@ impl AppHandle<crate::Wry> {
|
||||
) -> crate::Result<()> {
|
||||
self
|
||||
.runtime_handle
|
||||
.send_event(tauri_runtime_wry::Message::Window(window_id, message))
|
||||
.send_event(tauri_runtime_wry::Message::Window(
|
||||
self.runtime_handle.window_id(window_id),
|
||||
message,
|
||||
))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user