Fix: Windows File Drag-N-Drop (#3046)
* fix: windows file drop * update: tokio + fix eval
This commit is contained in:
1 parent
519ec9d294
commit
0995b5d2c5
17 files changed
+143
-20
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user