Fix: Windows File Drag-N-Drop (#3046)

* fix: windows file drop
* update: tokio + fix eval
This commit is contained in:
Miles Murgaw authored and GitHub committed 2024-10-14 11:00:11 -07:00
1 parent 519ec9d294
commit 0995b5d2c5
17 files changed
+143 -20

No files matched your search

+5 -3
View File
@@ -308,11 +308,13 @@ impl App {
let view = self.webviews.get_mut(&window).unwrap();
let event = dioxus_core::Event::new(data as Rc<dyn Any>, event_bubbles);
let runtime = view.dom.runtime();
if event_name == "change&input" {
view.dom.runtime().handle_event("input", event.clone(), id);
view.dom.runtime().handle_event("change", event, id);
runtime.handle_event("input", event.clone(), id);
runtime.handle_event("change", event, id);
} else {
view.dom.runtime().handle_event(event_name, event, id);
runtime.handle_event(event_name, event, id);
}
}
+9 -1
View File
@@ -15,12 +15,20 @@ pub enum UserWindowEvent {
Poll(WindowId),
/// Handle an ipc message eminating from the window.postMessage of a given webview
Ipc { id: WindowId, msg: IpcMessage },
Ipc {
id: WindowId,
msg: IpcMessage,
},
/// Handle a hotreload event, basically telling us to update our templates
#[cfg(all(feature = "devtools", debug_assertions))]
HotReloadEvent(dioxus_devtools::DevserverMsg),
// Windows-only drag-n-drop fix events.
WindowsDragDrop(WindowId),
WindowsDragOver(WindowId, i32, i32),
WindowsDragLeave(WindowId),
/// Create a new window
NewWindow,
+39
View File
@@ -4,6 +4,7 @@ use crate::{
ipc::{IpcMethod, UserWindowEvent},
};
use dioxus_core::*;
use dioxus_document::eval;
use std::any::Any;
use tao::event::{Event, StartCause, WindowEvent};
@@ -44,6 +45,44 @@ pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Conf
#[cfg(all(feature = "devtools", debug_assertions))]
UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
// Windows-only drag-n-drop fix events. We need to call the interpreter drag-n-drop code.
UserWindowEvent::WindowsDragDrop(id) => {
if let Some(webview) = app.webviews.get(&id) {
webview.dom.in_runtime(|| {
ScopeId::ROOT.in_runtime(|| {
eval("window.interpreter.handleWindowsDragDrop();");
});
});
}
}
UserWindowEvent::WindowsDragLeave(id) => {
if let Some(webview) = app.webviews.get(&id) {
webview.dom.in_runtime(|| {
ScopeId::ROOT.in_runtime(|| {
eval("window.interpreter.handleWindowsDragLeave();");
});
});
}
}
UserWindowEvent::WindowsDragOver(id, x_pos, y_pos) => {
if let Some(webview) = app.webviews.get(&id) {
webview.dom.in_runtime(|| {
ScopeId::ROOT.in_runtime(|| {
let e = eval(
r#"
const xPos = await dioxus.recv();
const yPos = await dioxus.recv();
window.interpreter.handleWindowsDragOver(xPos, yPos)
"#,
);
_ = e.send(x_pos);
_ = e.send(y_pos);
});
});
}
}
UserWindowEvent::Ipc { id, msg } => match msg.method() {
IpcMethod::Initialize => app.handle_initialize_msg(id),
IpcMethod::FileDialog => app.handle_file_dialog_msg(msg, id),
+34 -2
View File
@@ -20,7 +20,7 @@ use futures_util::{pin_mut, FutureExt};
use std::cell::OnceCell;
use std::sync::Arc;
use std::{rc::Rc, task::Waker};
use wry::{RequestAsyncResponder, WebContext, WebViewBuilder};
use wry::{DragDropEvent, RequestAsyncResponder, WebContext, WebViewBuilder};
#[derive(Clone)]
pub(crate) struct WebviewEdits {
@@ -236,10 +236,42 @@ impl WebviewInstance {
let file_drop_handler = {
to_owned![file_hover];
move |evt| {
#[cfg(windows)]
let (proxy, window_id) = (shared.proxy.to_owned(), window.id());
move |evt: DragDropEvent| {
// Update the most recent file drop event - when the event comes in from the webview we can use the
// most recent event to build a new event with the files in it.
#[cfg(not(windows))]
file_hover.set(evt);
// Windows webview blocks HTML-native events when the drop handler is provided.
// The problem is that the HTML-native events don't provide the file, so we need this.
// Solution: this glue code to mimic drag drop events.
#[cfg(windows)]
{
file_hover.set(evt.clone());
match evt {
wry::DragDropEvent::Drop {
paths: _,
position: _,
} => {
_ = proxy.send_event(UserWindowEvent::WindowsDragDrop(window_id));
}
wry::DragDropEvent::Over { position } => {
_ = proxy.send_event(UserWindowEvent::WindowsDragOver(
window_id, position.0, position.1,
));
}
wry::DragDropEvent::Leave => {
_ = proxy.send_event(UserWindowEvent::WindowsDragLeave(window_id));
}
_ => {}
}
}
false
}
};