mirror of https://github.com/tauri-apps/tauri
parent
c40f640ddc
commit
07d1584cf0
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
"tauri-runtime": minor
|
||||||
|
"tauri-runtime-wry": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
The file drop event is now part of the `WindowEvent` enum instead of a having a dedicated handler.
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"tauri-runtime": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
**Breaking change:** Move the `FileDropEvent` struct to the `window` module.
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
"tauri": patch
|
||||||
|
"tauri-runtime": minor
|
||||||
|
"tauri-runtime-wry": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added the `WindowEvent::FileDrop` variant.
|
|
@ -11,10 +11,10 @@ use tauri_runtime::{
|
||||||
},
|
},
|
||||||
menu::{CustomMenuItem, Menu, MenuEntry, MenuHash, MenuId, MenuItem, MenuUpdate},
|
menu::{CustomMenuItem, Menu, MenuEntry, MenuHash, MenuId, MenuItem, MenuUpdate},
|
||||||
monitor::Monitor,
|
monitor::Monitor,
|
||||||
webview::{FileDropEvent, FileDropHandler, WebviewIpcHandler, WindowBuilder, WindowBuilderBase},
|
webview::{WebviewIpcHandler, WindowBuilder, WindowBuilderBase},
|
||||||
window::{
|
window::{
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
DetachedWindow, JsEventListenerKey, PendingWindow, WindowEvent,
|
DetachedWindow, FileDropEvent, JsEventListenerKey, PendingWindow, WindowEvent,
|
||||||
},
|
},
|
||||||
ClipboardManager, Dispatch, Error, ExitRequestedEventAction, GlobalShortcutManager, Result,
|
ClipboardManager, Dispatch, Error, ExitRequestedEventAction, GlobalShortcutManager, Result,
|
||||||
RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType, WindowIcon,
|
RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType, WindowIcon,
|
||||||
|
@ -2624,7 +2624,6 @@ fn create_webview(
|
||||||
uri_scheme_protocols,
|
uri_scheme_protocols,
|
||||||
mut window_builder,
|
mut window_builder,
|
||||||
ipc_handler,
|
ipc_handler,
|
||||||
file_drop_handler,
|
|
||||||
label,
|
label,
|
||||||
url,
|
url,
|
||||||
menu_ids,
|
menu_ids,
|
||||||
|
@ -2663,17 +2662,11 @@ fn create_webview(
|
||||||
.with_url(&url)
|
.with_url(&url)
|
||||||
.unwrap() // safe to unwrap because we validate the URL beforehand
|
.unwrap() // safe to unwrap because we validate the URL beforehand
|
||||||
.with_transparent(is_window_transparent);
|
.with_transparent(is_window_transparent);
|
||||||
|
if webview_attributes.file_drop_handler_enabled {
|
||||||
|
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(&context));
|
||||||
|
}
|
||||||
if let Some(handler) = ipc_handler {
|
if let Some(handler) = ipc_handler {
|
||||||
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
||||||
context.clone(),
|
|
||||||
label.clone(),
|
|
||||||
menu_ids.clone(),
|
|
||||||
js_event_listeners.clone(),
|
|
||||||
handler,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some(handler) = file_drop_handler {
|
|
||||||
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(
|
|
||||||
context,
|
context,
|
||||||
label.clone(),
|
label.clone(),
|
||||||
menu_ids,
|
menu_ids,
|
||||||
|
@ -2763,26 +2756,25 @@ fn create_ipc_handler(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a wry file drop handler from a tauri file drop handler.
|
/// Create a wry file drop handler.
|
||||||
fn create_file_drop_handler(
|
fn create_file_drop_handler(
|
||||||
context: Context,
|
context: &Context,
|
||||||
label: String,
|
|
||||||
menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
|
|
||||||
js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
|
|
||||||
handler: FileDropHandler<Wry>,
|
|
||||||
) -> Box<dyn Fn(&Window, WryFileDropEvent) -> bool + 'static> {
|
) -> Box<dyn Fn(&Window, WryFileDropEvent) -> bool + 'static> {
|
||||||
|
let window_event_listeners = context.window_event_listeners.clone();
|
||||||
Box::new(move |window, event| {
|
Box::new(move |window, event| {
|
||||||
handler(
|
let event: FileDropEvent = FileDropEventWrapper(event).into();
|
||||||
FileDropEventWrapper(event).into(),
|
let window_event = WindowEvent::FileDrop(event);
|
||||||
DetachedWindow {
|
let listeners = window_event_listeners.lock().unwrap();
|
||||||
dispatcher: WryDispatcher {
|
if let Some(window_listeners) = listeners.get(&window.id()) {
|
||||||
window_id: window.id(),
|
let listeners_map = window_listeners.lock().unwrap();
|
||||||
context: context.clone(),
|
let has_listener = !listeners_map.is_empty();
|
||||||
},
|
for listener in listeners_map.values() {
|
||||||
label: label.clone(),
|
listener(&window_event);
|
||||||
menu_ids: menu_ids.clone(),
|
}
|
||||||
js_event_listeners: js_event_listeners.clone(),
|
// block the default OS action on file drop if we had a listener
|
||||||
},
|
has_listener
|
||||||
)
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,21 +184,5 @@ pub trait WindowBuilder: WindowBuilderBase {
|
||||||
fn get_menu(&self) -> Option<&Menu>;
|
fn get_menu(&self) -> Option<&Menu>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The file drop event payload.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum FileDropEvent {
|
|
||||||
/// The file(s) have been dragged onto the window, but have not been dropped yet.
|
|
||||||
Hovered(Vec<PathBuf>),
|
|
||||||
/// The file(s) have been dropped onto the window.
|
|
||||||
Dropped(Vec<PathBuf>),
|
|
||||||
/// The file drop was aborted.
|
|
||||||
Cancelled,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// IPC handler.
|
/// IPC handler.
|
||||||
pub type WebviewIpcHandler<R> = Box<dyn Fn(DetachedWindow<R>, String) + Send>;
|
pub type WebviewIpcHandler<R> = Box<dyn Fn(DetachedWindow<R>, String) + Send>;
|
||||||
|
|
||||||
/// File drop handler callback
|
|
||||||
/// Return `true` in the callback to block the OS' default behavior of handling a file drop.
|
|
||||||
pub type FileDropHandler<R> = Box<dyn Fn(FileDropEvent, DetachedWindow<R>) -> bool + Send>;
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
http::{Request as HttpRequest, Response as HttpResponse},
|
http::{Request as HttpRequest, Response as HttpResponse},
|
||||||
menu::{Menu, MenuEntry, MenuHash, MenuId},
|
menu::{Menu, MenuEntry, MenuHash, MenuId},
|
||||||
webview::{FileDropHandler, WebviewAttributes, WebviewIpcHandler},
|
webview::{WebviewAttributes, WebviewIpcHandler},
|
||||||
Dispatch, Runtime, WindowBuilder,
|
Dispatch, Runtime, WindowBuilder,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
@ -16,6 +16,7 @@ use tauri_utils::config::WindowConfig;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
|
path::PathBuf,
|
||||||
sync::{mpsc::Sender, Arc, Mutex},
|
sync::{mpsc::Sender, Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +60,20 @@ pub enum WindowEvent {
|
||||||
/// The window inner size.
|
/// The window inner size.
|
||||||
new_inner_size: dpi::PhysicalSize<u32>,
|
new_inner_size: dpi::PhysicalSize<u32>,
|
||||||
},
|
},
|
||||||
|
/// An event associated with the file drop action.
|
||||||
|
FileDrop(FileDropEvent),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The file drop event payload.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum FileDropEvent {
|
||||||
|
/// The file(s) have been dragged onto the window, but have not been dropped yet.
|
||||||
|
Hovered(Vec<PathBuf>),
|
||||||
|
/// The file(s) have been dropped onto the window.
|
||||||
|
Dropped(Vec<PathBuf>),
|
||||||
|
/// The file drop was aborted.
|
||||||
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A menu event.
|
/// A menu event.
|
||||||
|
@ -96,9 +111,6 @@ pub struct PendingWindow<R: Runtime> {
|
||||||
/// How to handle IPC calls on the webview window.
|
/// How to handle IPC calls on the webview window.
|
||||||
pub ipc_handler: Option<WebviewIpcHandler<R>>,
|
pub ipc_handler: Option<WebviewIpcHandler<R>>,
|
||||||
|
|
||||||
/// How to handle a file dropping onto the webview window.
|
|
||||||
pub file_drop_handler: Option<FileDropHandler<R>>,
|
|
||||||
|
|
||||||
/// The resolved URL to load on the webview.
|
/// The resolved URL to load on the webview.
|
||||||
pub url: String,
|
pub url: String,
|
||||||
|
|
||||||
|
@ -143,7 +155,6 @@ impl<R: Runtime> PendingWindow<R> {
|
||||||
uri_scheme_protocols: Default::default(),
|
uri_scheme_protocols: Default::default(),
|
||||||
label,
|
label,
|
||||||
ipc_handler: None,
|
ipc_handler: None,
|
||||||
file_drop_handler: None,
|
|
||||||
url: "tauri://localhost".to_string(),
|
url: "tauri://localhost".to_string(),
|
||||||
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
||||||
js_event_listeners: Default::default(),
|
js_event_listeners: Default::default(),
|
||||||
|
@ -172,7 +183,6 @@ impl<R: Runtime> PendingWindow<R> {
|
||||||
uri_scheme_protocols: Default::default(),
|
uri_scheme_protocols: Default::default(),
|
||||||
label,
|
label,
|
||||||
ipc_handler: None,
|
ipc_handler: None,
|
||||||
file_drop_handler: None,
|
|
||||||
url: "tauri://localhost".to_string(),
|
url: "tauri://localhost".to_string(),
|
||||||
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
||||||
js_event_listeners: Default::default(),
|
js_event_listeners: Default::default(),
|
||||||
|
|
|
@ -213,7 +213,7 @@ pub use {
|
||||||
webview::{WebviewAttributes, WindowBuilder},
|
webview::{WebviewAttributes, WindowBuilder},
|
||||||
window::{
|
window::{
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
|
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
|
||||||
WindowEvent,
|
FileDropEvent, WindowEvent,
|
||||||
},
|
},
|
||||||
ClipboardManager, GlobalShortcutManager, RunIteration, Runtime, TrayIcon, UserAttentionType,
|
ClipboardManager, GlobalShortcutManager, RunIteration, Runtime, TrayIcon, UserAttentionType,
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,8 +39,8 @@ use crate::{
|
||||||
MimeType, Request as HttpRequest, Response as HttpResponse,
|
MimeType, Request as HttpRequest, Response as HttpResponse,
|
||||||
ResponseBuilder as HttpResponseBuilder,
|
ResponseBuilder as HttpResponseBuilder,
|
||||||
},
|
},
|
||||||
webview::{FileDropEvent, FileDropHandler, WebviewIpcHandler, WindowBuilder},
|
webview::{WebviewIpcHandler, WindowBuilder},
|
||||||
window::{dpi::PhysicalSize, DetachedWindow, PendingWindow, WindowEvent},
|
window::{dpi::PhysicalSize, DetachedWindow, FileDropEvent, PendingWindow, WindowEvent},
|
||||||
Runtime,
|
Runtime,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
|
@ -838,30 +838,6 @@ impl<R: Runtime> WindowManager<R> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_file_drop(&self, app_handle: AppHandle<R>) -> FileDropHandler<R> {
|
|
||||||
let manager = self.clone();
|
|
||||||
Box::new(move |event, window| {
|
|
||||||
let window = Window::new(manager.clone(), window, app_handle.clone());
|
|
||||||
let _ = match event {
|
|
||||||
FileDropEvent::Hovered(paths) => window.emit_and_trigger("tauri://file-drop-hover", paths),
|
|
||||||
FileDropEvent::Dropped(paths) => {
|
|
||||||
let scopes = window.state::<Scopes>();
|
|
||||||
for path in &paths {
|
|
||||||
if path.is_file() {
|
|
||||||
let _ = scopes.allow_file(path);
|
|
||||||
} else {
|
|
||||||
let _ = scopes.allow_directory(path, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.emit_and_trigger("tauri://file-drop", paths)
|
|
||||||
}
|
|
||||||
FileDropEvent::Cancelled => window.emit_and_trigger("tauri://file-drop-cancelled", ()),
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initialization_script(
|
fn initialization_script(
|
||||||
&self,
|
&self,
|
||||||
ipc_script: &str,
|
ipc_script: &str,
|
||||||
|
@ -1082,11 +1058,7 @@ impl<R: Runtime> WindowManager<R> {
|
||||||
app_handle.clone(),
|
app_handle.clone(),
|
||||||
web_resource_request_handler,
|
web_resource_request_handler,
|
||||||
)?;
|
)?;
|
||||||
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle.clone()));
|
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle));
|
||||||
}
|
|
||||||
|
|
||||||
if pending.webview_attributes.file_drop_handler_enabled {
|
|
||||||
pending.file_drop_handler = Some(self.prepare_file_drop(app_handle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// in `Windows`, we need to force a data_directory
|
// in `Windows`, we need to force a data_directory
|
||||||
|
@ -1291,6 +1263,22 @@ fn on_window_event<R: Runtime>(
|
||||||
size: *new_inner_size,
|
size: *new_inner_size,
|
||||||
},
|
},
|
||||||
)?,
|
)?,
|
||||||
|
WindowEvent::FileDrop(event) => match event {
|
||||||
|
FileDropEvent::Hovered(paths) => window.emit_and_trigger("tauri://file-drop-hover", paths)?,
|
||||||
|
FileDropEvent::Dropped(paths) => {
|
||||||
|
let scopes = window.state::<Scopes>();
|
||||||
|
for path in paths {
|
||||||
|
if path.is_file() {
|
||||||
|
let _ = scopes.allow_file(path);
|
||||||
|
} else {
|
||||||
|
let _ = scopes.allow_directory(path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.emit_and_trigger("tauri://file-drop", paths)?
|
||||||
|
}
|
||||||
|
FileDropEvent::Cancelled => window.emit_and_trigger("tauri://file-drop-cancelled", ())?,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue