mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-17 11:50:26 +03:00
feat(ipc): enhance request URL checks, update wry, refactor file drop (#9100)
* feat(ipc): enhance request URL checks * actually use req url * fix windows, tests * wry 0.38, file drop refactor * wry 0.38.1 * adjust for windows [skip ci] * wry 0.38.2 [skip ci] * update to latest tao, wry, muda and tray-icon * change tag * serde * use published crates * downgrade cargo-platform to 0.1.7 --------- Co-authored-by: amrbashir <amr.bashir2015@gmail.com>
This commit is contained in:
parent
b78f90bc9c
commit
06833f4fa8
5
.changes/enhance-ipc-url-check.md
Normal file
5
.changes/enhance-ipc-url-check.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:enhance
|
||||||
|
---
|
||||||
|
|
||||||
|
Enhance the IPC URL check by using the Origin header on the custom protocol IPC and the new request URI field on the postMessage IPC instead of using `Webview::url()` which only returns the URL of the main frame and is not suitable for iframes (iframe URL fetch is still not supported on Android and on Linux when using the postMessage IPC).
|
7
.changes/http-v1.md
Normal file
7
.changes/http-v1.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
'tauri': 'patch:deps'
|
||||||
|
'tauri-runtime': 'patch'
|
||||||
|
'tauri-runtime-wry': 'patch'
|
||||||
|
---
|
||||||
|
|
||||||
|
Updated `http` crate to `1.1`
|
6
.changes/ipc-request-param-refactor.md
Normal file
6
.changes/ipc-request-param-refactor.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"tauri-runtime": patch:breaking
|
||||||
|
"tauri-runtime-wry": patch:breaking
|
||||||
|
---
|
||||||
|
|
||||||
|
The IPC handler closure now receives a `http::Request` instead of a String representing the request body.
|
5
.changes/rect-strcut.md
Normal file
5
.changes/rect-strcut.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'tauri': 'patch:feat'
|
||||||
|
---
|
||||||
|
|
||||||
|
Added `Rect` struct.
|
9
.changes/rename-file-drop.md
Normal file
9
.changes/rename-file-drop.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:breaking
|
||||||
|
"tauri-runtime": patch:breaking
|
||||||
|
"tauri-utils": patch:breaking
|
||||||
|
"tauri-runtime-wry": patch:breaking
|
||||||
|
"@tauri-apps/api": patch:breaking
|
||||||
|
---
|
||||||
|
|
||||||
|
Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names.
|
5
.changes/runtime-dpi-mod-moved.md
Normal file
5
.changes/runtime-dpi-mod-moved.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'tauri-runtime': 'major:breaking'
|
||||||
|
---
|
||||||
|
|
||||||
|
Moved `window::dpi` module to the root of the crate.
|
9
.changes/tray-rect.md
Normal file
9
.changes/tray-rect.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
'tauri': 'patch:breaking'
|
||||||
|
---
|
||||||
|
|
||||||
|
Refactored the tray icon event struct:
|
||||||
|
|
||||||
|
- Changed `TrayIconEvent.icon_rect` type to use the new `tauri::Rect` type.
|
||||||
|
- Removed `TrayIconEvent.x` and `TrayIconEvent.y` fields and combined them into `TrayIconEvent.position` field.
|
||||||
|
- Removed `tauri::tray::Rectangle` struct.
|
5
.changes/webview-bounds.md
Normal file
5
.changes/webview-bounds.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'tauri': 'minor:feat'
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `Webview::bounds` and `Webview::set_bounds` APIs.
|
5
.changes/wry-0.38.md
Normal file
5
.changes/wry-0.38.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"tauri-runtime-wry": patch:deps
|
||||||
|
---
|
||||||
|
|
||||||
|
Upgraded to `wry@0.38.0`
|
926
Cargo.lock
generated
926
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -221,8 +221,8 @@
|
|||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"fileDropEnabled": {
|
"dragDropEnabled": {
|
||||||
"description": "Whether the file drop is enabled or not on the webview. By default it is enabled.\n\nDisabling it is required to use drag and drop on the frontend on Windows.",
|
"description": "Whether the drag and drop is enabled or not on the webview. By default it is enabled.\n\nDisabling it is required to use HTML5 drag and drop on the frontend on Windows.",
|
||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -13,22 +13,22 @@ edition = { workspace = true }
|
|||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wry = { version = "0.37", default-features = false, features = [ "file-drop", "protocol", "os-webview" ] }
|
wry = { version = "0.39", default-features = false, features = [ "drag-drop", "protocol", "os-webview" ] }
|
||||||
tao = { version = "0.26", default-features = false, features = [ "rwh_06" ] }
|
tao = { version = "0.27", default-features = false, features = [ "rwh_06" ] }
|
||||||
tauri-runtime = { version = "2.0.0-beta.10", path = "../tauri-runtime" }
|
tauri-runtime = { version = "2.0.0-beta.10", path = "../tauri-runtime" }
|
||||||
tauri-utils = { version = "2.0.0-beta.10", path = "../tauri-utils" }
|
tauri-utils = { version = "2.0.0-beta.10", path = "../tauri-utils" }
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
http = "0.2"
|
http = "1.1"
|
||||||
url = "2"
|
url = "2"
|
||||||
tracing = { version = "0.1", optional = true }
|
tracing = { version = "0.1", optional = true }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
webview2-com = "0.28"
|
webview2-com = "0.29"
|
||||||
softbuffer = "0.4"
|
softbuffer = { version = "0.4", default-features = false }
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies.windows]
|
[target."cfg(windows)".dependencies.windows]
|
||||||
version = "0.52"
|
version = "0.54"
|
||||||
features = [ "Win32_Foundation" ]
|
features = [ "Win32_Foundation" ]
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||||
|
@ -11,14 +11,15 @@
|
|||||||
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
|
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
use http::Request;
|
||||||
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
||||||
|
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
|
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
monitor::Monitor,
|
monitor::Monitor,
|
||||||
webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler},
|
webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler},
|
||||||
window::{
|
window::{
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
CursorIcon, DetachedWindow, DragDropEvent, PendingWindow, RawWindow, WebviewEvent,
|
||||||
CursorIcon, DetachedWindow, FileDropEvent, PendingWindow, RawWindow, WebviewEvent,
|
|
||||||
WindowBuilder, WindowBuilderBase, WindowEvent, WindowId,
|
WindowBuilder, WindowBuilderBase, WindowEvent, WindowId,
|
||||||
},
|
},
|
||||||
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
|
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
|
||||||
@ -62,7 +63,7 @@ use tauri_utils::TitleBarStyle;
|
|||||||
use tauri_utils::{config::WindowConfig, Theme};
|
use tauri_utils::{config::WindowConfig, Theme};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use wry::{
|
use wry::{
|
||||||
FileDropEvent as WryFileDropEvent, ProxyConfig, ProxyEndpoint, WebContext, WebView,
|
DragDropEvent as WryDragDropEvent, ProxyConfig, ProxyEndpoint, WebContext, WebView,
|
||||||
WebViewBuilder,
|
WebViewBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub type WebviewId = u32;
|
pub type WebviewId = u32;
|
||||||
type IpcHandler = dyn Fn(String) + 'static;
|
type IpcHandler = dyn Fn(Request<String>) + 'static;
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
windows,
|
windows,
|
||||||
@ -415,6 +416,16 @@ impl From<DeviceEventFilter> for DeviceEventFilterWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RectWrapper(pub wry::Rect);
|
||||||
|
impl From<tauri_runtime::Rect> for RectWrapper {
|
||||||
|
fn from(value: tauri_runtime::Rect) -> Self {
|
||||||
|
RectWrapper(wry::Rect {
|
||||||
|
position: value.position,
|
||||||
|
size: value.size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around a [`tao::window::Icon`] that can be created from an [`Icon`].
|
/// Wrapper around a [`tao::window::Icon`] that can be created from an [`Icon`].
|
||||||
pub struct TaoIcon(pub TaoWindowIcon);
|
pub struct TaoIcon(pub TaoWindowIcon);
|
||||||
|
|
||||||
@ -1144,14 +1155,14 @@ pub enum WindowMessage {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SynthesizedWindowEvent {
|
pub enum SynthesizedWindowEvent {
|
||||||
Focused(bool),
|
Focused(bool),
|
||||||
FileDrop(FileDropEvent),
|
DragDrop(DragDropEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SynthesizedWindowEvent> for WindowEventWrapper {
|
impl From<SynthesizedWindowEvent> for WindowEventWrapper {
|
||||||
fn from(event: SynthesizedWindowEvent) -> Self {
|
fn from(event: SynthesizedWindowEvent) -> Self {
|
||||||
let event = match event {
|
let event = match event {
|
||||||
SynthesizedWindowEvent::Focused(focused) => WindowEvent::Focused(focused),
|
SynthesizedWindowEvent::Focused(focused) => WindowEvent::Focused(focused),
|
||||||
SynthesizedWindowEvent::FileDrop(event) => WindowEvent::FileDrop(event),
|
SynthesizedWindowEvent::DragDrop(event) => WindowEvent::DragDrop(event),
|
||||||
};
|
};
|
||||||
Self(Some(event))
|
Self(Some(event))
|
||||||
}
|
}
|
||||||
@ -1170,13 +1181,15 @@ pub enum WebviewMessage {
|
|||||||
Close,
|
Close,
|
||||||
SetPosition(Position),
|
SetPosition(Position),
|
||||||
SetSize(Size),
|
SetSize(Size),
|
||||||
|
SetBounds(tauri_runtime::Rect),
|
||||||
SetFocus,
|
SetFocus,
|
||||||
Reparent(WindowId),
|
Reparent(WindowId, Sender<Result<()>>),
|
||||||
SetAutoResize(bool),
|
SetAutoResize(bool),
|
||||||
// Getters
|
// Getters
|
||||||
Url(Sender<Url>),
|
Url(Sender<Result<Url>>),
|
||||||
Position(Sender<PhysicalPosition<i32>>),
|
Bounds(Sender<Result<tauri_runtime::Rect>>),
|
||||||
Size(Sender<PhysicalSize<u32>>),
|
Position(Sender<Result<PhysicalPosition<i32>>>),
|
||||||
|
Size(Sender<Result<PhysicalSize<u32>>>),
|
||||||
WithWebview(Box<dyn FnOnce(Webview) + Send>),
|
WithWebview(Box<dyn FnOnce(Webview) + Send>),
|
||||||
// Devtools
|
// Devtools
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
@ -1289,15 +1302,19 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
// Getters
|
// Getters
|
||||||
|
|
||||||
fn url(&self) -> Result<Url> {
|
fn url(&self) -> Result<Url> {
|
||||||
webview_getter!(self, WebviewMessage::Url)
|
webview_getter!(self, WebviewMessage::Url)?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounds(&self) -> Result<tauri_runtime::Rect> {
|
||||||
|
webview_getter!(self, WebviewMessage::Bounds)?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn position(&self) -> Result<PhysicalPosition<i32>> {
|
fn position(&self) -> Result<PhysicalPosition<i32>> {
|
||||||
webview_getter!(self, WebviewMessage::Position)
|
webview_getter!(self, WebviewMessage::Position)?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> Result<PhysicalSize<u32>> {
|
fn size(&self) -> Result<PhysicalSize<u32>> {
|
||||||
webview_getter!(self, WebviewMessage::Size)
|
webview_getter!(self, WebviewMessage::Size)?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
@ -1335,6 +1352,17 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_bounds(&self, bounds: tauri_runtime::Rect) -> Result<()> {
|
||||||
|
send_user_message(
|
||||||
|
&self.context,
|
||||||
|
Message::Webview(
|
||||||
|
*self.window_id.lock().unwrap(),
|
||||||
|
self.webview_id,
|
||||||
|
WebviewMessage::SetBounds(bounds),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn set_size(&self, size: Size) -> Result<()> {
|
fn set_size(&self, size: Size) -> Result<()> {
|
||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
@ -1370,15 +1398,18 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
|
|
||||||
fn reparent(&self, window_id: WindowId) -> Result<()> {
|
fn reparent(&self, window_id: WindowId) -> Result<()> {
|
||||||
let mut current_window_id = self.window_id.lock().unwrap();
|
let mut current_window_id = self.window_id.lock().unwrap();
|
||||||
|
let (tx, rx) = channel();
|
||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
*current_window_id,
|
*current_window_id,
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::Reparent(window_id),
|
WebviewMessage::Reparent(window_id, tx),
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
rx.recv().unwrap()?;
|
||||||
|
|
||||||
*current_window_id = window_id;
|
*current_window_id = window_id;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -2746,7 +2777,7 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
))]
|
))]
|
||||||
if let WebviewMessage::Reparent(new_parent_window_id) = webview_message {
|
if let WebviewMessage::Reparent(new_parent_window_id, tx) = webview_message {
|
||||||
let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| {
|
let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| {
|
||||||
w.webviews
|
w.webviews
|
||||||
.iter()
|
.iter()
|
||||||
@ -2762,16 +2793,13 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
.map(|w| (w.inner.clone(), &mut w.webviews))
|
.map(|w| (w.inner.clone(), &mut w.webviews))
|
||||||
{
|
{
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
let reparent_result = {
|
||||||
use wry::WebViewExtMacOS;
|
use wry::WebViewExtMacOS;
|
||||||
webview.inner.reparent(new_parent_window.ns_window() as _);
|
webview.inner.reparent(new_parent_window.ns_window() as _)
|
||||||
new_parent_window_webviews.push(webview);
|
};
|
||||||
}
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
let reparent_result = { webview.inner.reparent(new_parent_window.hwnd()) };
|
||||||
webview.inner.reparent(new_parent_window.hwnd());
|
|
||||||
new_parent_window_webviews.push(webview);
|
|
||||||
}
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
@ -2779,13 +2807,27 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
))]
|
))]
|
||||||
{
|
let reparent_result = {
|
||||||
if let Some(container) = new_parent_window.default_vbox() {
|
if let Some(container) = new_parent_window.default_vbox() {
|
||||||
webview.inner.reparent(container);
|
webview.inner.reparent(container)
|
||||||
|
} else {
|
||||||
|
Err(wry::Error::MessageSender)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match reparent_result {
|
||||||
|
Ok(_) => {
|
||||||
new_parent_window_webviews.push(webview);
|
new_parent_window_webviews.push(webview);
|
||||||
|
tx.send(Ok(())).unwrap();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("failed to reparent webview: {e}");
|
||||||
|
tx.send(Err(Error::FailedToSendMessage)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tx.send(Err(Error::FailedToSendMessage)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -2801,7 +2843,7 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
match webview_message {
|
match webview_message {
|
||||||
WebviewMessage::WebviewEvent(_) => { /* already handled */ }
|
WebviewMessage::WebviewEvent(_) => { /* already handled */ }
|
||||||
WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ }
|
WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ }
|
||||||
WebviewMessage::Reparent(_window_id) => { /* already handled */ }
|
WebviewMessage::Reparent(_window_id, _tx) => { /* already handled */ }
|
||||||
WebviewMessage::AddEventListener(id, listener) => {
|
WebviewMessage::AddEventListener(id, listener) => {
|
||||||
webview
|
webview
|
||||||
.webview_event_listeners
|
.webview_event_listeners
|
||||||
@ -2824,7 +2866,11 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
log::error!("{}", e);
|
log::error!("{}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WebviewMessage::Navigate(url) => webview.load_url(url.as_str()),
|
WebviewMessage::Navigate(url) => {
|
||||||
|
if let Err(e) = webview.load_url(url.as_str()) {
|
||||||
|
log::error!("failed to navigate to url {}: {}", url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
WebviewMessage::Print => {
|
WebviewMessage::Print => {
|
||||||
let _ = webview.print();
|
let _ = webview.print();
|
||||||
}
|
}
|
||||||
@ -2836,67 +2882,133 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
window
|
window
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
WebviewMessage::SetSize(size) => {
|
WebviewMessage::SetBounds(bounds) => {
|
||||||
let mut bounds = webview.bounds();
|
let bounds: RectWrapper = bounds.into();
|
||||||
let size = size.to_logical(window.scale_factor());
|
let bounds = bounds.0;
|
||||||
bounds.width = size.width;
|
|
||||||
bounds.height = size.height;
|
|
||||||
|
|
||||||
if let Some(b) = &mut *webview.bounds.lock().unwrap() {
|
if let Some(b) = &mut *webview.bounds.lock().unwrap() {
|
||||||
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
|
let scale_factor = window.scale_factor();
|
||||||
b.width_rate = size.width as f32 / window_size.width;
|
let size = bounds.size.to_logical::<f32>(scale_factor);
|
||||||
b.height_rate = size.height as f32 / window_size.height;
|
let position = bounds.position.to_logical::<f32>(scale_factor);
|
||||||
|
let window_size = window.inner_size().to_logical::<f32>(scale_factor);
|
||||||
|
b.width_rate = size.width / window_size.width;
|
||||||
|
b.height_rate = size.height / window_size.height;
|
||||||
|
b.x_rate = position.x / window_size.width;
|
||||||
|
b.y_rate = position.y / window_size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
webview.set_bounds(bounds);
|
if let Err(e) = webview.set_bounds(bounds) {
|
||||||
}
|
log::error!("failed to set webview size: {e}");
|
||||||
WebviewMessage::SetPosition(position) => {
|
|
||||||
let mut bounds = webview.bounds();
|
|
||||||
let position = position.to_logical(window.scale_factor());
|
|
||||||
bounds.x = position.x;
|
|
||||||
bounds.y = position.y;
|
|
||||||
|
|
||||||
if let Some(b) = &mut *webview.bounds.lock().unwrap() {
|
|
||||||
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
|
|
||||||
b.x_rate = position.x as f32 / window_size.width;
|
|
||||||
b.y_rate = position.y as f32 / window_size.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
webview.set_bounds(bounds);
|
|
||||||
}
|
}
|
||||||
|
WebviewMessage::SetSize(size) => match webview.bounds() {
|
||||||
|
Ok(mut bounds) => {
|
||||||
|
bounds.size = size;
|
||||||
|
|
||||||
|
let scale_factor = window.scale_factor();
|
||||||
|
let size = size.to_logical::<f32>(scale_factor);
|
||||||
|
|
||||||
|
if let Some(b) = &mut *webview.bounds.lock().unwrap() {
|
||||||
|
let window_size = window.inner_size().to_logical::<f32>(scale_factor);
|
||||||
|
b.width_rate = size.width / window_size.width;
|
||||||
|
b.height_rate = size.height / window_size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = webview.set_bounds(bounds) {
|
||||||
|
log::error!("failed to set webview size: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("failed to get webview bounds: {e}");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
WebviewMessage::SetPosition(position) => match webview.bounds() {
|
||||||
|
Ok(mut bounds) => {
|
||||||
|
bounds.position = position;
|
||||||
|
|
||||||
|
let scale_factor = window.scale_factor();
|
||||||
|
let position = position.to_logical::<f32>(scale_factor);
|
||||||
|
|
||||||
|
if let Some(b) = &mut *webview.bounds.lock().unwrap() {
|
||||||
|
let window_size = window.inner_size().to_logical::<f32>(scale_factor);
|
||||||
|
b.x_rate = position.x / window_size.width;
|
||||||
|
b.y_rate = position.y / window_size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = webview.set_bounds(bounds) {
|
||||||
|
log::error!("failed to set webview position: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("failed to get webview bounds: {e}");
|
||||||
|
}
|
||||||
|
},
|
||||||
// Getters
|
// Getters
|
||||||
WebviewMessage::Url(tx) => {
|
WebviewMessage::Url(tx) => {
|
||||||
tx.send(webview.url().parse().unwrap()).unwrap();
|
tx.send(
|
||||||
|
webview
|
||||||
|
.url()
|
||||||
|
.map(|u| u.parse().expect("invalid webview URL"))
|
||||||
|
.map_err(|_| Error::FailedToSendMessage),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
WebviewMessage::Bounds(tx) => {
|
||||||
|
tx.send(
|
||||||
|
webview
|
||||||
|
.bounds()
|
||||||
|
.map(|bounds| tauri_runtime::Rect {
|
||||||
|
size: bounds.size,
|
||||||
|
position: bounds.position,
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::FailedToSendMessage),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
WebviewMessage::Position(tx) => {
|
WebviewMessage::Position(tx) => {
|
||||||
let bounds = webview.bounds();
|
tx.send(
|
||||||
let position =
|
webview
|
||||||
LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor());
|
.bounds()
|
||||||
tx.send(position).unwrap();
|
.map(|bounds| bounds.position.to_physical(window.scale_factor()))
|
||||||
|
.map_err(|_| Error::FailedToSendMessage),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
WebviewMessage::Size(tx) => {
|
WebviewMessage::Size(tx) => {
|
||||||
let bounds = webview.bounds();
|
tx.send(
|
||||||
let size =
|
webview
|
||||||
LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor());
|
.bounds()
|
||||||
tx.send(size).unwrap();
|
.map(|bounds| bounds.size.to_physical(window.scale_factor()))
|
||||||
|
.map_err(|_| Error::FailedToSendMessage),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
WebviewMessage::SetFocus => {
|
WebviewMessage::SetFocus => {
|
||||||
webview.focus();
|
if let Err(e) = webview.focus() {
|
||||||
}
|
log::error!("failed to focus webview: {e}");
|
||||||
WebviewMessage::SetAutoResize(auto_resize) => {
|
}
|
||||||
let bounds = webview.bounds();
|
|
||||||
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
|
|
||||||
*webview.bounds.lock().unwrap() = if auto_resize {
|
|
||||||
Some(WebviewBounds {
|
|
||||||
x_rate: (bounds.x as f32) / window_size.width,
|
|
||||||
y_rate: (bounds.y as f32) / window_size.height,
|
|
||||||
width_rate: (bounds.width as f32) / window_size.width,
|
|
||||||
height_rate: (bounds.height as f32) / window_size.height,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
WebviewMessage::SetAutoResize(auto_resize) => match webview.bounds() {
|
||||||
|
Ok(bounds) => {
|
||||||
|
let scale_factor = window.scale_factor();
|
||||||
|
let window_size = window.inner_size().to_logical::<f32>(scale_factor);
|
||||||
|
*webview.bounds.lock().unwrap() = if auto_resize {
|
||||||
|
let size = bounds.size.to_logical::<f32>(scale_factor);
|
||||||
|
let position = bounds.position.to_logical::<f32>(scale_factor);
|
||||||
|
Some(WebviewBounds {
|
||||||
|
x_rate: position.x / window_size.width,
|
||||||
|
y_rate: position.y / window_size.height,
|
||||||
|
width_rate: size.width / window_size.width,
|
||||||
|
height_rate: size.height / window_size.height,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("failed to get webview bounds: {e}");
|
||||||
|
}
|
||||||
|
},
|
||||||
WebviewMessage::WithWebview(f) => {
|
WebviewMessage::WithWebview(f) => {
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
@ -3182,7 +3294,9 @@ fn handle_event_loop<T: UserEvent>(
|
|||||||
TaoTheme::Light => wry::Theme::Light,
|
TaoTheme::Light => wry::Theme::Light,
|
||||||
_ => wry::Theme::Light,
|
_ => wry::Theme::Light,
|
||||||
};
|
};
|
||||||
webview.set_theme(theme);
|
if let Err(e) = webview.set_theme(theme) {
|
||||||
|
log::error!("failed to set theme: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3216,12 +3330,14 @@ fn handle_event_loop<T: UserEvent>(
|
|||||||
let size = size.to_logical::<f32>(window.scale_factor());
|
let size = size.to_logical::<f32>(window.scale_factor());
|
||||||
for webview in &webviews {
|
for webview in &webviews {
|
||||||
if let Some(b) = &*webview.bounds.lock().unwrap() {
|
if let Some(b) = &*webview.bounds.lock().unwrap() {
|
||||||
webview.set_bounds(wry::Rect {
|
if let Err(e) = webview.set_bounds(wry::Rect {
|
||||||
x: (size.width * b.x_rate) as i32,
|
position: LogicalPosition::new(size.width * b.x_rate, size.height * b.y_rate)
|
||||||
y: (size.height * b.y_rate) as i32,
|
.into(),
|
||||||
width: (size.width * b.width_rate) as u32,
|
size: LogicalSize::new(size.width * b.width_rate, size.height * b.height_rate)
|
||||||
height: (size.height * b.height_rate) as u32,
|
.into(),
|
||||||
});
|
}) {
|
||||||
|
log::error!("failed to autoresize webview: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -3590,33 +3706,36 @@ fn create_webview<T: UserEvent>(
|
|||||||
webview_builder = webview_builder.with_initialization_script(undecorated_resizing::SCRIPT);
|
webview_builder = webview_builder.with_initialization_script(undecorated_resizing::SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if webview_attributes.file_drop_handler_enabled {
|
if webview_attributes.drag_drop_handler_enabled {
|
||||||
let proxy = context.proxy.clone();
|
let proxy = context.proxy.clone();
|
||||||
let window_id_ = window_id.clone();
|
let window_id_ = window_id.clone();
|
||||||
webview_builder = webview_builder.with_file_drop_handler(move |event| {
|
webview_builder = webview_builder.with_drag_drop_handler(move |event| {
|
||||||
let event = match event {
|
let event = match event {
|
||||||
WryFileDropEvent::Hovered {
|
WryDragDropEvent::Enter {
|
||||||
paths,
|
paths,
|
||||||
position: (x, y),
|
position: (x, y),
|
||||||
} => FileDropEvent::Hovered {
|
} => DragDropEvent::Dragged {
|
||||||
paths,
|
paths,
|
||||||
position: PhysicalPosition::new(x as _, y as _),
|
position: PhysicalPosition::new(x as _, y as _),
|
||||||
},
|
},
|
||||||
WryFileDropEvent::Dropped {
|
WryDragDropEvent::Over { position: (x, y) } => DragDropEvent::DragOver {
|
||||||
|
position: PhysicalPosition::new(x as _, y as _),
|
||||||
|
},
|
||||||
|
WryDragDropEvent::Drop {
|
||||||
paths,
|
paths,
|
||||||
position: (x, y),
|
position: (x, y),
|
||||||
} => FileDropEvent::Dropped {
|
} => DragDropEvent::Dropped {
|
||||||
paths,
|
paths,
|
||||||
position: PhysicalPosition::new(x as _, y as _),
|
position: PhysicalPosition::new(x as _, y as _),
|
||||||
},
|
},
|
||||||
WryFileDropEvent::Cancelled => FileDropEvent::Cancelled,
|
WryDragDropEvent::Leave => DragDropEvent::Cancelled,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = if kind == WebviewKind::WindowContent {
|
let message = if kind == WebviewKind::WindowContent {
|
||||||
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::FileDrop(event))
|
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::DragDrop(event))
|
||||||
} else {
|
} else {
|
||||||
WebviewMessage::WebviewEvent(WebviewEvent::FileDrop(event))
|
WebviewMessage::WebviewEvent(WebviewEvent::DragDrop(event))
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message));
|
let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message));
|
||||||
@ -3633,24 +3752,24 @@ fn create_webview<T: UserEvent>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let webview_bounds = if let Some((position, size)) = webview_attributes.bounds {
|
let webview_bounds = if let Some(bounds) = webview_attributes.bounds {
|
||||||
let size = size.to_logical(window.scale_factor());
|
let bounds: RectWrapper = bounds.into();
|
||||||
let position = position.to_logical(window.scale_factor());
|
let bounds = bounds.0;
|
||||||
webview_builder = webview_builder.with_bounds(wry::Rect {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y,
|
|
||||||
width: size.width,
|
|
||||||
height: size.height,
|
|
||||||
});
|
|
||||||
|
|
||||||
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
|
let scale_factor = window.scale_factor();
|
||||||
|
let position = bounds.position.to_logical::<f32>(scale_factor);
|
||||||
|
let size = bounds.size.to_logical::<f32>(scale_factor);
|
||||||
|
|
||||||
|
webview_builder = webview_builder.with_bounds(bounds);
|
||||||
|
|
||||||
|
let window_size = window.inner_size().to_logical::<f32>(scale_factor);
|
||||||
|
|
||||||
if webview_attributes.auto_resize {
|
if webview_attributes.auto_resize {
|
||||||
Some(WebviewBounds {
|
Some(WebviewBounds {
|
||||||
x_rate: (position.x as f32) / window_size.width,
|
x_rate: position.x / window_size.width,
|
||||||
y_rate: (position.y as f32) / window_size.height,
|
y_rate: position.y / window_size.height,
|
||||||
width_rate: (size.width as f32) / window_size.width,
|
width_rate: size.width / window_size.width,
|
||||||
height_rate: (size.height as f32) / window_size.height,
|
height_rate: size.height / window_size.height,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -3658,13 +3777,9 @@ fn create_webview<T: UserEvent>(
|
|||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
{
|
{
|
||||||
let window_size = window.inner_size().to_logical::<u32>(window.scale_factor());
|
|
||||||
|
|
||||||
webview_builder = webview_builder.with_bounds(wry::Rect {
|
webview_builder = webview_builder.with_bounds(wry::Rect {
|
||||||
x: 0,
|
position: LogicalPosition::new(0, 0).into(),
|
||||||
y: 0,
|
size: window.inner_size().into(),
|
||||||
width: window_size.width,
|
|
||||||
height: window_size.height,
|
|
||||||
});
|
});
|
||||||
Some(WebviewBounds {
|
Some(WebviewBounds {
|
||||||
x_rate: 0.,
|
x_rate: 0.,
|
||||||
|
@ -154,9 +154,9 @@ mod windows {
|
|||||||
pub fn handle_request<T: crate::UserEvent>(
|
pub fn handle_request<T: crate::UserEvent>(
|
||||||
context: crate::Context<T>,
|
context: crate::Context<T>,
|
||||||
window_id: crate::WindowId,
|
window_id: crate::WindowId,
|
||||||
request: &str,
|
request: &http::Request<String>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some(args) = request.strip_prefix(MESSAGE_MOUSEMOVE) {
|
if let Some(args) = request.body().strip_prefix(MESSAGE_MOUSEMOVE) {
|
||||||
if let Some(window) = context.main_thread.windows.0.borrow().get(&window_id) {
|
if let Some(window) = context.main_thread.windows.0.borrow().get(&window_id) {
|
||||||
if let Some(w) = window.inner.as_ref() {
|
if let Some(w) = window.inner.as_ref() {
|
||||||
if !w.is_decorated()
|
if !w.is_decorated()
|
||||||
@ -177,7 +177,7 @@ mod windows {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let Some(args) = request.strip_prefix(MESSAGE_MOUSEDOWN) {
|
if let Some(args) = request.body().strip_prefix(MESSAGE_MOUSEDOWN) {
|
||||||
if let Some(window) = context.main_thread.windows.0.borrow().get(&window_id) {
|
if let Some(window) = context.main_thread.windows.0.borrow().get(&window_id) {
|
||||||
if let Some(w) = window.inner.as_ref() {
|
if let Some(w) = window.inner.as_ref() {
|
||||||
if !w.is_decorated()
|
if !w.is_decorated()
|
||||||
|
@ -30,12 +30,13 @@ serde = { version = "1.0", features = [ "derive" ] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tauri-utils = { version = "2.0.0-beta.10", path = "../tauri-utils" }
|
tauri-utils = { version = "2.0.0-beta.10", path = "../tauri-utils" }
|
||||||
http = "0.2.4"
|
http = "1.1"
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
url = { version = "2" }
|
url = { version = "2" }
|
||||||
|
dpi = { version = "0.1", features = ["serde"] }
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies.windows]
|
[target."cfg(windows)".dependencies.windows]
|
||||||
version = "0.52"
|
version = "0.54"
|
||||||
features = [ "Win32_Foundation" ]
|
features = [ "Win32_Foundation" ]
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
|
||||||
use raw_window_handle::DisplayHandle;
|
use raw_window_handle::DisplayHandle;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{borrow::Cow, fmt::Debug, sync::mpsc::Sender};
|
use std::{borrow::Cow, fmt::Debug, sync::mpsc::Sender};
|
||||||
use tauri_utils::Theme;
|
use tauri_utils::Theme;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@ -24,11 +24,9 @@ pub mod monitor;
|
|||||||
pub mod webview;
|
pub mod webview;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
||||||
|
use dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||||
use monitor::Monitor;
|
use monitor::Monitor;
|
||||||
use window::{
|
use window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent};
|
||||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
|
||||||
CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent,
|
|
||||||
};
|
|
||||||
use window::{WindowBuilder, WindowId};
|
use window::{WindowBuilder, WindowId};
|
||||||
|
|
||||||
use http::{
|
use http::{
|
||||||
@ -37,9 +35,30 @@ use http::{
|
|||||||
status::InvalidStatusCode,
|
status::InvalidStatusCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// UI scaling utilities.
|
||||||
|
pub use dpi;
|
||||||
|
|
||||||
pub type WindowEventId = u32;
|
pub type WindowEventId = u32;
|
||||||
pub type WebviewEventId = u32;
|
pub type WebviewEventId = u32;
|
||||||
|
|
||||||
|
/// A rectangular region.
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
pub struct Rect {
|
||||||
|
/// Rect position.
|
||||||
|
pub position: dpi::Position,
|
||||||
|
/// Rect size.
|
||||||
|
pub size: dpi::Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Rect {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
position: Position::Logical((0, 0).into()),
|
||||||
|
size: Size::Logical((0, 0).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Progress bar status.
|
/// Progress bar status.
|
||||||
#[derive(Debug, Clone, Copy, Deserialize)]
|
#[derive(Debug, Clone, Copy, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@ -421,6 +440,9 @@ pub trait WebviewDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + '
|
|||||||
/// Returns the webview's current URL.
|
/// Returns the webview's current URL.
|
||||||
fn url(&self) -> Result<Url>;
|
fn url(&self) -> Result<Url>;
|
||||||
|
|
||||||
|
/// Returns the webview's bounds.
|
||||||
|
fn bounds(&self) -> Result<Rect>;
|
||||||
|
|
||||||
/// Returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the window.
|
/// Returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the window.
|
||||||
fn position(&self) -> Result<PhysicalPosition<i32>>;
|
fn position(&self) -> Result<PhysicalPosition<i32>>;
|
||||||
|
|
||||||
@ -438,6 +460,9 @@ pub trait WebviewDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + '
|
|||||||
/// Closes the webview.
|
/// Closes the webview.
|
||||||
fn close(&self) -> Result<()>;
|
fn close(&self) -> Result<()>;
|
||||||
|
|
||||||
|
/// Sets the webview's bounds.
|
||||||
|
fn set_bounds(&self, bounds: Rect) -> Result<()>;
|
||||||
|
|
||||||
/// Resizes the webview.
|
/// Resizes the webview.
|
||||||
fn set_size(&self, size: Size) -> Result<()>;
|
fn set_size(&self, size: Size) -> Result<()>;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use super::window::dpi::{PhysicalPosition, PhysicalSize};
|
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||||
|
|
||||||
/// Monitor descriptor.
|
/// Monitor descriptor.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -4,14 +4,9 @@
|
|||||||
|
|
||||||
//! A layer between raw [`Runtime`] webviews and Tauri.
|
//! A layer between raw [`Runtime`] webviews and Tauri.
|
||||||
//!
|
//!
|
||||||
use crate::{
|
use crate::{window::is_label_valid, Rect, Runtime, UserEvent};
|
||||||
window::{
|
|
||||||
dpi::{Position, Size},
|
|
||||||
is_label_valid,
|
|
||||||
},
|
|
||||||
Runtime, UserEvent,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use http::Request;
|
||||||
use tauri_utils::config::{WebviewUrl, WindowConfig, WindowEffectsConfig};
|
use tauri_utils::config::{WebviewUrl, WindowConfig, WindowEffectsConfig};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@ -202,14 +197,14 @@ pub struct WebviewAttributes {
|
|||||||
pub user_agent: Option<String>,
|
pub user_agent: Option<String>,
|
||||||
pub initialization_scripts: Vec<String>,
|
pub initialization_scripts: Vec<String>,
|
||||||
pub data_directory: Option<PathBuf>,
|
pub data_directory: Option<PathBuf>,
|
||||||
pub file_drop_handler_enabled: bool,
|
pub drag_drop_handler_enabled: bool,
|
||||||
pub clipboard: bool,
|
pub clipboard: bool,
|
||||||
pub accept_first_mouse: bool,
|
pub accept_first_mouse: bool,
|
||||||
pub additional_browser_args: Option<String>,
|
pub additional_browser_args: Option<String>,
|
||||||
pub window_effects: Option<WindowEffectsConfig>,
|
pub window_effects: Option<WindowEffectsConfig>,
|
||||||
pub incognito: bool,
|
pub incognito: bool,
|
||||||
pub transparent: bool,
|
pub transparent: bool,
|
||||||
pub bounds: Option<(Position, Size)>,
|
pub bounds: Option<Rect>,
|
||||||
pub auto_resize: bool,
|
pub auto_resize: bool,
|
||||||
pub proxy_url: Option<Url>,
|
pub proxy_url: Option<Url>,
|
||||||
}
|
}
|
||||||
@ -223,8 +218,8 @@ impl From<&WindowConfig> for WebviewAttributes {
|
|||||||
builder = builder.transparent(config.transparent);
|
builder = builder.transparent(config.transparent);
|
||||||
}
|
}
|
||||||
builder = builder.accept_first_mouse(config.accept_first_mouse);
|
builder = builder.accept_first_mouse(config.accept_first_mouse);
|
||||||
if !config.file_drop_enabled {
|
if !config.drag_drop_enabled {
|
||||||
builder = builder.disable_file_drop_handler();
|
builder = builder.disable_drag_drop_handler();
|
||||||
}
|
}
|
||||||
if let Some(user_agent) = &config.user_agent {
|
if let Some(user_agent) = &config.user_agent {
|
||||||
builder = builder.user_agent(user_agent);
|
builder = builder.user_agent(user_agent);
|
||||||
@ -250,7 +245,7 @@ impl WebviewAttributes {
|
|||||||
user_agent: None,
|
user_agent: None,
|
||||||
initialization_scripts: Vec::new(),
|
initialization_scripts: Vec::new(),
|
||||||
data_directory: None,
|
data_directory: None,
|
||||||
file_drop_handler_enabled: true,
|
drag_drop_handler_enabled: true,
|
||||||
clipboard: false,
|
clipboard: false,
|
||||||
accept_first_mouse: false,
|
accept_first_mouse: false,
|
||||||
additional_browser_args: None,
|
additional_browser_args: None,
|
||||||
@ -284,10 +279,10 @@ impl WebviewAttributes {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables the file drop handler. This is required to use drag and drop APIs on the front end on Windows.
|
/// Disables the drag and drop handler. This is required to use HTML5 drag and drop APIs on the frontend on Windows.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn disable_file_drop_handler(mut self) -> Self {
|
pub fn disable_drag_drop_handler(mut self) -> Self {
|
||||||
self.file_drop_handler_enabled = false;
|
self.drag_drop_handler_enabled = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,4 +348,4 @@ impl WebviewAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// IPC handler.
|
/// IPC handler.
|
||||||
pub type WebviewIpcHandler<T, R> = Box<dyn Fn(DetachedWebview<T, R>, String) + Send>;
|
pub type WebviewIpcHandler<T, R> = Box<dyn Fn(DetachedWebview<T, R>, Request<String>) + Send>;
|
||||||
|
@ -21,11 +21,6 @@ use std::{
|
|||||||
sync::mpsc::Sender,
|
sync::mpsc::Sender,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::dpi::PhysicalPosition;
|
|
||||||
|
|
||||||
/// UI scaling utilities.
|
|
||||||
pub mod dpi;
|
|
||||||
|
|
||||||
/// An event from a window.
|
/// An event from a window.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum WindowEvent {
|
pub enum WindowEvent {
|
||||||
@ -57,8 +52,8 @@ 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.
|
/// An event associated with the drag and drop action.
|
||||||
FileDrop(FileDropEvent),
|
DragDrop(DragDropEvent),
|
||||||
/// The system window theme has changed.
|
/// The system window theme has changed.
|
||||||
///
|
///
|
||||||
/// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme.
|
/// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme.
|
||||||
@ -68,27 +63,34 @@ pub enum WindowEvent {
|
|||||||
/// An event from a window.
|
/// An event from a window.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum WebviewEvent {
|
pub enum WebviewEvent {
|
||||||
/// An event associated with the file drop action.
|
/// An event associated with the drag and drop action.
|
||||||
FileDrop(FileDropEvent),
|
DragDrop(DragDropEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The file drop event payload.
|
/// The drag drop event payload.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum FileDropEvent {
|
pub enum DragDropEvent {
|
||||||
/// The file(s) have been dragged onto the window, but have not been dropped yet.
|
/// A drag operation started.
|
||||||
Hovered {
|
Dragged {
|
||||||
|
/// Paths of the files that are being dragged.
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
/// The position of the mouse cursor.
|
/// The position of the mouse cursor.
|
||||||
position: PhysicalPosition<f64>,
|
position: dpi::PhysicalPosition<f64>,
|
||||||
},
|
},
|
||||||
/// The file(s) have been dropped onto the window.
|
/// The files have been dragged onto the window, but have not been dropped yet.
|
||||||
|
DragOver {
|
||||||
|
/// The position of the mouse cursor.
|
||||||
|
position: dpi::PhysicalPosition<f64>,
|
||||||
|
},
|
||||||
|
/// The user dropped the operation.
|
||||||
Dropped {
|
Dropped {
|
||||||
|
/// Path of the files that were dropped.
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
/// The position of the mouse cursor.
|
/// The position of the mouse cursor.
|
||||||
position: PhysicalPosition<f64>,
|
position: dpi::PhysicalPosition<f64>,
|
||||||
},
|
},
|
||||||
/// The file drop was aborted.
|
/// The drag operation was cancelled.
|
||||||
Cancelled,
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,401 +0,0 @@
|
|||||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
pub trait Pixel: Copy + Into<f64> {
|
|
||||||
fn from_f64(f: f64) -> Self;
|
|
||||||
fn cast<P: Pixel>(self) -> P {
|
|
||||||
P::from_f64(self.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pixel for u8 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for u16 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as u16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for u32 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for i8 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as i8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for i16 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as i16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for i32 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f.round() as i32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for f32 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f as f32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pixel for f64 {
|
|
||||||
fn from_f64(f: f64) -> Self {
|
|
||||||
f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks that the scale factor is a normal positive `f64`.
|
|
||||||
///
|
|
||||||
/// All functions that take a scale factor assert that this will return `true`. If you're sourcing scale factors from
|
|
||||||
/// anywhere other than tao, it's recommended to validate them using this function before passing them to tao;
|
|
||||||
/// otherwise, you risk panics.
|
|
||||||
#[inline]
|
|
||||||
pub fn validate_scale_factor(scale_factor: f64) -> bool {
|
|
||||||
scale_factor.is_sign_positive() && scale_factor.is_normal()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A position represented in logical pixels.
|
|
||||||
///
|
|
||||||
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the
|
|
||||||
/// fractional part, which can cause noticeable issues. To help with that, an `Into<(i32, i32)>`
|
|
||||||
/// implementation is provided which does the rounding for you.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct LogicalPosition<P> {
|
|
||||||
pub x: P,
|
|
||||||
pub y: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> LogicalPosition<P> {
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(x: P, y: P) -> Self {
|
|
||||||
LogicalPosition { x, y }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> LogicalPosition<P> {
|
|
||||||
#[inline]
|
|
||||||
pub fn from_physical<T: Into<PhysicalPosition<X>>, X: Pixel>(
|
|
||||||
physical: T,
|
|
||||||
scale_factor: f64,
|
|
||||||
) -> Self {
|
|
||||||
physical.into().to_logical(scale_factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<X> {
|
|
||||||
assert!(validate_scale_factor(scale_factor));
|
|
||||||
let x = self.x.into() * scale_factor;
|
|
||||||
let y = self.y.into() * scale_factor;
|
|
||||||
PhysicalPosition::new(x, y).cast()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cast<X: Pixel>(&self) -> LogicalPosition<X> {
|
|
||||||
LogicalPosition {
|
|
||||||
x: self.x.cast(),
|
|
||||||
y: self.y.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalPosition<P> {
|
|
||||||
fn from((x, y): (X, X)) -> LogicalPosition<P> {
|
|
||||||
LogicalPosition::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for (X, X) {
|
|
||||||
fn from(pos: LogicalPosition<P>) -> Self {
|
|
||||||
(pos.x.cast(), pos.y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalPosition<P> {
|
|
||||||
fn from([x, y]: [X; 2]) -> LogicalPosition<P> {
|
|
||||||
LogicalPosition::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for [X; 2] {
|
|
||||||
fn from(pos: LogicalPosition<P>) -> Self {
|
|
||||||
[pos.x.cast(), pos.y.cast()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A position represented in physical pixels.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct PhysicalPosition<P> {
|
|
||||||
pub x: P,
|
|
||||||
pub y: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> PhysicalPosition<P> {
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(x: P, y: P) -> Self {
|
|
||||||
PhysicalPosition { x, y }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> PhysicalPosition<P> {
|
|
||||||
#[inline]
|
|
||||||
pub fn from_logical<T: Into<LogicalPosition<X>>, X: Pixel>(
|
|
||||||
logical: T,
|
|
||||||
scale_factor: f64,
|
|
||||||
) -> Self {
|
|
||||||
logical.into().to_physical(scale_factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalPosition<X> {
|
|
||||||
assert!(validate_scale_factor(scale_factor));
|
|
||||||
let x = self.x.into() / scale_factor;
|
|
||||||
let y = self.y.into() / scale_factor;
|
|
||||||
LogicalPosition::new(x, y).cast()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cast<X: Pixel>(&self) -> PhysicalPosition<X> {
|
|
||||||
PhysicalPosition {
|
|
||||||
x: self.x.cast(),
|
|
||||||
y: self.y.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalPosition<P> {
|
|
||||||
fn from((x, y): (X, X)) -> PhysicalPosition<P> {
|
|
||||||
PhysicalPosition::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for (X, X) {
|
|
||||||
fn from(pos: PhysicalPosition<P>) -> Self {
|
|
||||||
(pos.x.cast(), pos.y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalPosition<P> {
|
|
||||||
fn from([x, y]: [X; 2]) -> PhysicalPosition<P> {
|
|
||||||
PhysicalPosition::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for [X; 2] {
|
|
||||||
fn from(pos: PhysicalPosition<P>) -> Self {
|
|
||||||
[pos.x.cast(), pos.y.cast()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A size represented in logical pixels.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct LogicalSize<P> {
|
|
||||||
pub width: P,
|
|
||||||
pub height: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> LogicalSize<P> {
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(width: P, height: P) -> Self {
|
|
||||||
LogicalSize { width, height }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> LogicalSize<P> {
|
|
||||||
#[inline]
|
|
||||||
pub fn from_physical<T: Into<PhysicalSize<X>>, X: Pixel>(physical: T, scale_factor: f64) -> Self {
|
|
||||||
physical.into().to_logical(scale_factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalSize<X> {
|
|
||||||
assert!(validate_scale_factor(scale_factor));
|
|
||||||
let width = self.width.into() * scale_factor;
|
|
||||||
let height = self.height.into() * scale_factor;
|
|
||||||
PhysicalSize::new(width, height).cast()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cast<X: Pixel>(&self) -> LogicalSize<X> {
|
|
||||||
LogicalSize {
|
|
||||||
width: self.width.cast(),
|
|
||||||
height: self.height.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalSize<P> {
|
|
||||||
fn from((x, y): (X, X)) -> LogicalSize<P> {
|
|
||||||
LogicalSize::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for (X, X) {
|
|
||||||
fn from(size: LogicalSize<P>) -> Self {
|
|
||||||
(size.width.cast(), size.height.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalSize<P> {
|
|
||||||
fn from([x, y]: [X; 2]) -> LogicalSize<P> {
|
|
||||||
LogicalSize::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for [X; 2] {
|
|
||||||
fn from(size: LogicalSize<P>) -> Self {
|
|
||||||
[size.width.cast(), size.height.cast()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A size represented in physical pixels.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct PhysicalSize<P> {
|
|
||||||
pub width: P,
|
|
||||||
pub height: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> PhysicalSize<P> {
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(width: P, height: P) -> Self {
|
|
||||||
PhysicalSize { width, height }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> PhysicalSize<P> {
|
|
||||||
#[inline]
|
|
||||||
pub fn from_logical<T: Into<LogicalSize<X>>, X: Pixel>(logical: T, scale_factor: f64) -> Self {
|
|
||||||
logical.into().to_physical(scale_factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalSize<X> {
|
|
||||||
assert!(validate_scale_factor(scale_factor));
|
|
||||||
let width = self.width.into() / scale_factor;
|
|
||||||
let height = self.height.into() / scale_factor;
|
|
||||||
LogicalSize::new(width, height).cast()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cast<X: Pixel>(&self) -> PhysicalSize<X> {
|
|
||||||
PhysicalSize {
|
|
||||||
width: self.width.cast(),
|
|
||||||
height: self.height.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalSize<P> {
|
|
||||||
fn from((x, y): (X, X)) -> PhysicalSize<P> {
|
|
||||||
PhysicalSize::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for (X, X) {
|
|
||||||
fn from(size: PhysicalSize<P>) -> Self {
|
|
||||||
(size.width.cast(), size.height.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalSize<P> {
|
|
||||||
fn from([x, y]: [X; 2]) -> PhysicalSize<P> {
|
|
||||||
PhysicalSize::new(x.cast(), y.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for [X; 2] {
|
|
||||||
fn from(size: PhysicalSize<P>) -> Self {
|
|
||||||
[size.width.cast(), size.height.cast()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A size that's either physical or logical.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(tag = "type", content = "data")]
|
|
||||||
pub enum Size {
|
|
||||||
Physical(PhysicalSize<u32>),
|
|
||||||
Logical(LogicalSize<f64>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Size {
|
|
||||||
pub fn new<S: Into<Size>>(size: S) -> Size {
|
|
||||||
size.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalSize<P> {
|
|
||||||
match *self {
|
|
||||||
Size::Physical(size) => size.to_logical(scale_factor),
|
|
||||||
Size::Logical(size) => size.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalSize<P> {
|
|
||||||
match *self {
|
|
||||||
Size::Physical(size) => size.cast(),
|
|
||||||
Size::Logical(size) => size.to_physical(scale_factor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> From<PhysicalSize<P>> for Size {
|
|
||||||
#[inline]
|
|
||||||
fn from(size: PhysicalSize<P>) -> Size {
|
|
||||||
Size::Physical(size.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> From<LogicalSize<P>> for Size {
|
|
||||||
#[inline]
|
|
||||||
fn from(size: LogicalSize<P>) -> Size {
|
|
||||||
Size::Logical(size.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A position that's either physical or logical.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(tag = "type", content = "data")]
|
|
||||||
pub enum Position {
|
|
||||||
Physical(PhysicalPosition<i32>),
|
|
||||||
Logical(LogicalPosition<f64>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Position {
|
|
||||||
pub fn new<S: Into<Position>>(position: S) -> Position {
|
|
||||||
position.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalPosition<P> {
|
|
||||||
match *self {
|
|
||||||
Position::Physical(position) => position.to_logical(scale_factor),
|
|
||||||
Position::Logical(position) => position.cast(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<P> {
|
|
||||||
match *self {
|
|
||||||
Position::Physical(position) => position.cast(),
|
|
||||||
Position::Logical(position) => position.to_physical(scale_factor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> From<PhysicalPosition<P>> for Position {
|
|
||||||
#[inline]
|
|
||||||
fn from(position: PhysicalPosition<P>) -> Position {
|
|
||||||
Position::Physical(position.cast())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Pixel> From<LogicalPosition<P>> for Position {
|
|
||||||
#[inline]
|
|
||||||
fn from(position: LogicalPosition<P>) -> Position {
|
|
||||||
Position::Logical(position.cast())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1104,11 +1104,11 @@ pub struct WindowConfig {
|
|||||||
/// The user agent for the webview
|
/// The user agent for the webview
|
||||||
#[serde(alias = "user-agent")]
|
#[serde(alias = "user-agent")]
|
||||||
pub user_agent: Option<String>,
|
pub user_agent: Option<String>,
|
||||||
/// Whether the file drop is enabled or not on the webview. By default it is enabled.
|
/// Whether the drag and drop is enabled or not on the webview. By default it is enabled.
|
||||||
///
|
///
|
||||||
/// Disabling it is required to use drag and drop on the frontend on Windows.
|
/// Disabling it is required to use HTML5 drag and drop on the frontend on Windows.
|
||||||
#[serde(default = "default_true", alias = "file-drop-enabled")]
|
#[serde(default = "default_true", alias = "drag-drop-enabled")]
|
||||||
pub file_drop_enabled: bool,
|
pub drag_drop_enabled: bool,
|
||||||
/// Whether or not the window starts centered or not.
|
/// Whether or not the window starts centered or not.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub center: bool,
|
pub center: bool,
|
||||||
@ -1284,7 +1284,7 @@ impl Default for WindowConfig {
|
|||||||
label: default_window_label(),
|
label: default_window_label(),
|
||||||
url: WebviewUrl::default(),
|
url: WebviewUrl::default(),
|
||||||
user_agent: None,
|
user_agent: None,
|
||||||
file_drop_enabled: true,
|
drag_drop_enabled: true,
|
||||||
center: false,
|
center: false,
|
||||||
x: None,
|
x: None,
|
||||||
y: None,
|
y: None,
|
||||||
@ -2205,7 +2205,7 @@ mod build {
|
|||||||
let label = str_lit(&self.label);
|
let label = str_lit(&self.label);
|
||||||
let url = &self.url;
|
let url = &self.url;
|
||||||
let user_agent = opt_str_lit(self.user_agent.as_ref());
|
let user_agent = opt_str_lit(self.user_agent.as_ref());
|
||||||
let file_drop_enabled = self.file_drop_enabled;
|
let drag_drop_enabled = self.drag_drop_enabled;
|
||||||
let center = self.center;
|
let center = self.center;
|
||||||
let x = opt_lit(self.x.as_ref());
|
let x = opt_lit(self.x.as_ref());
|
||||||
let y = opt_lit(self.y.as_ref());
|
let y = opt_lit(self.y.as_ref());
|
||||||
@ -2249,7 +2249,7 @@ mod build {
|
|||||||
label,
|
label,
|
||||||
url,
|
url,
|
||||||
user_agent,
|
user_agent,
|
||||||
file_drop_enabled,
|
drag_drop_enabled,
|
||||||
center,
|
center,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
@ -57,10 +57,10 @@ tauri-runtime-wry = { version = "2.0.0-beta.10", path = "../tauri-runtime-wry",
|
|||||||
getrandom = "0.2"
|
getrandom = "0.2"
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
state = "0.6"
|
state = "0.6"
|
||||||
http = "0.2"
|
http = "1.1"
|
||||||
dirs-next = "2.0"
|
dirs-next = "2.0"
|
||||||
percent-encoding = "2.3"
|
percent-encoding = "2.3"
|
||||||
reqwest = { version = "0.11", default-features = false, features = [ "json", "stream" ] }
|
reqwest = { version = "0.12", default-features = false, features = [ "json", "stream" ] }
|
||||||
bytes = { version = "1", features = [ "serde" ] }
|
bytes = { version = "1", features = [ "serde" ] }
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
@ -75,8 +75,8 @@ heck = "0.4"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
|
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
|
||||||
muda = { version = "0.12", default-features = false, features = [ "serde" ] }
|
muda = { version = "0.13", default-features = false, features = [ "serde" ] }
|
||||||
tray-icon = { version = "0.12", default-features = false, features = [ "serde" ], optional = true }
|
tray-icon = { version = "0.13", default-features = false, features = [ "serde" ], optional = true }
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||||
gtk = { version = "0.18", features = [ "v3_24" ] }
|
gtk = { version = "0.18", features = [ "v3_24" ] }
|
||||||
@ -89,11 +89,11 @@ objc = "0.2"
|
|||||||
window-vibrancy = "0.5"
|
window-vibrancy = "0.5"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
webview2-com = "0.28"
|
webview2-com = "0.29"
|
||||||
window-vibrancy = "0.5"
|
window-vibrancy = "0.5"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies.windows]
|
[target."cfg(windows)".dependencies.windows]
|
||||||
version = "0.52"
|
version = "0.54"
|
||||||
features = [ "Win32_Foundation" ]
|
features = [ "Win32_Foundation" ]
|
||||||
|
|
||||||
[target."cfg(target_os = \"android\")".dependencies]
|
[target."cfg(target_os = \"android\")".dependencies]
|
||||||
|
File diff suppressed because one or more lines are too long
@ -35,10 +35,8 @@ use tauri_macros::default_runtime;
|
|||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
use tauri_runtime::EventLoopProxy;
|
use tauri_runtime::EventLoopProxy;
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
window::{
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
dpi::{PhysicalPosition, PhysicalSize},
|
window::DragDropEvent,
|
||||||
FileDropEvent,
|
|
||||||
},
|
|
||||||
RuntimeInitArgs,
|
RuntimeInitArgs,
|
||||||
};
|
};
|
||||||
use tauri_utils::PackageInfo;
|
use tauri_utils::PackageInfo;
|
||||||
@ -132,8 +130,8 @@ pub enum WindowEvent {
|
|||||||
/// The window inner size.
|
/// The window inner size.
|
||||||
new_inner_size: PhysicalSize<u32>,
|
new_inner_size: PhysicalSize<u32>,
|
||||||
},
|
},
|
||||||
/// An event associated with the file drop action.
|
/// An event associated with the drag and drop action.
|
||||||
FileDrop(FileDropEvent),
|
DragDrop(DragDropEvent),
|
||||||
/// The system window theme has changed. Only delivered if the window [`theme`](`crate::window::WindowBuilder#method.theme`) is `None`.
|
/// The system window theme has changed. Only delivered if the window [`theme`](`crate::window::WindowBuilder#method.theme`) is `None`.
|
||||||
///
|
///
|
||||||
/// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme.
|
/// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme.
|
||||||
@ -161,7 +159,7 @@ impl From<RuntimeWindowEvent> for WindowEvent {
|
|||||||
scale_factor,
|
scale_factor,
|
||||||
new_inner_size,
|
new_inner_size,
|
||||||
},
|
},
|
||||||
RuntimeWindowEvent::FileDrop(event) => Self::FileDrop(event),
|
RuntimeWindowEvent::DragDrop(event) => Self::DragDrop(event),
|
||||||
RuntimeWindowEvent::ThemeChanged(theme) => Self::ThemeChanged(theme),
|
RuntimeWindowEvent::ThemeChanged(theme) => Self::ThemeChanged(theme),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,14 +169,14 @@ impl From<RuntimeWindowEvent> for WindowEvent {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum WebviewEvent {
|
pub enum WebviewEvent {
|
||||||
/// An event associated with the file drop action.
|
/// An event associated with the drag and drop action.
|
||||||
FileDrop(FileDropEvent),
|
DragDrop(DragDropEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RuntimeWebviewEvent> for WebviewEvent {
|
impl From<RuntimeWebviewEvent> for WebviewEvent {
|
||||||
fn from(event: RuntimeWebviewEvent) -> Self {
|
fn from(event: RuntimeWebviewEvent) -> Self {
|
||||||
match event {
|
match event {
|
||||||
RuntimeWebviewEvent::FileDrop(e) => Self::FileDrop(e),
|
RuntimeWebviewEvent::DragDrop(e) => Self::DragDrop(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1392,7 +1390,7 @@ tauri::Builder::default()
|
|||||||
/// ```
|
/// ```
|
||||||
/// tauri::Builder::default()
|
/// tauri::Builder::default()
|
||||||
/// .on_webview_event(|window, event| match event {
|
/// .on_webview_event(|window, event| match event {
|
||||||
/// tauri::WebviewEvent::FileDrop(event) => {
|
/// tauri::WebviewEvent::DragDrop(event) => {
|
||||||
/// println!("{:?}", event);
|
/// println!("{:?}", event);
|
||||||
/// }
|
/// }
|
||||||
/// _ => {}
|
/// _ => {}
|
||||||
|
@ -11,8 +11,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use http::{
|
use http::{
|
||||||
header::{ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE},
|
header::{ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE},
|
||||||
HeaderValue, Method, StatusCode,
|
HeaderValue, Method, Request, StatusCode,
|
||||||
};
|
};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use super::{CallbackFn, InvokeBody, InvokeResponse};
|
use super::{CallbackFn, InvokeBody, InvokeResponse};
|
||||||
|
|
||||||
@ -161,11 +162,16 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, label: &str) {
|
fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager<R>, label: &str) {
|
||||||
if let Some(webview) = manager.get_webview(label) {
|
if let Some(webview) = manager.get_webview(label) {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
let _span =
|
let _span = tracing::trace_span!(
|
||||||
tracing::trace_span!("ipc::request", kind = "post-message", request = message).entered();
|
"ipc::request",
|
||||||
|
kind = "post-message",
|
||||||
|
uri = request.uri().to_string(),
|
||||||
|
body = request.body()
|
||||||
|
)
|
||||||
|
.entered();
|
||||||
|
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
@ -227,7 +233,7 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
|
|||||||
let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered();
|
let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered();
|
||||||
|
|
||||||
invoke_message.replace(
|
invoke_message.replace(
|
||||||
serde_json::from_str::<IsolationMessage<'_>>(&message)
|
serde_json::from_str::<IsolationMessage<'_>>(request.body())
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
.and_then(|message| {
|
.and_then(|message| {
|
||||||
Ok(Message {
|
Ok(Message {
|
||||||
@ -245,7 +251,7 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
|
|||||||
let message = invoke_message.unwrap_or_else(|| {
|
let message = invoke_message.unwrap_or_else(|| {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
let _span = tracing::trace_span!("ipc::request::deserialize").entered();
|
let _span = tracing::trace_span!("ipc::request::deserialize").entered();
|
||||||
serde_json::from_str::<Message>(&message).map_err(Into::into)
|
serde_json::from_str::<Message>(request.body()).map_err(Into::into)
|
||||||
});
|
});
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
@ -254,6 +260,7 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
|
|||||||
cmd: message.cmd,
|
cmd: message.cmd,
|
||||||
callback: message.callback,
|
callback: message.callback,
|
||||||
error: message.error,
|
error: message.error,
|
||||||
|
url: Url::parse(&request.uri().to_string()).expect("invalid IPC request URL"),
|
||||||
body: message.payload.into(),
|
body: message.payload.into(),
|
||||||
headers: message.options.map(|o| o.headers.0).unwrap_or_default(),
|
headers: message.options.map(|o| o.headers.0).unwrap_or_default(),
|
||||||
};
|
};
|
||||||
@ -389,6 +396,16 @@ fn parse_invoke_request<R: Runtime>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let url = Url::parse(
|
||||||
|
parts
|
||||||
|
.headers
|
||||||
|
.get("Origin")
|
||||||
|
.ok_or("missing Origin header")?
|
||||||
|
.to_str()
|
||||||
|
.map_err(|_| "Origin header value must be a string")?,
|
||||||
|
)
|
||||||
|
.map_err(|_| "Origin header is not a valid URL")?;
|
||||||
|
|
||||||
let callback = CallbackFn(
|
let callback = CallbackFn(
|
||||||
parts
|
parts
|
||||||
.headers
|
.headers
|
||||||
@ -412,7 +429,7 @@ fn parse_invoke_request<R: Runtime>(
|
|||||||
|
|
||||||
let content_type = parts
|
let content_type = parts
|
||||||
.headers
|
.headers
|
||||||
.get(reqwest::header::CONTENT_TYPE)
|
.get(http::header::CONTENT_TYPE)
|
||||||
.and_then(|h| h.to_str().ok())
|
.and_then(|h| h.to_str().ok())
|
||||||
.map(|mime| mime.parse())
|
.map(|mime| mime.parse())
|
||||||
.unwrap_or(Ok(mime::APPLICATION_OCTET_STREAM))
|
.unwrap_or(Ok(mime::APPLICATION_OCTET_STREAM))
|
||||||
@ -443,6 +460,7 @@ fn parse_invoke_request<R: Runtime>(
|
|||||||
cmd,
|
cmd,
|
||||||
callback,
|
callback,
|
||||||
error,
|
error,
|
||||||
|
url,
|
||||||
body,
|
body,
|
||||||
headers: parts.headers,
|
headers: parts.headers,
|
||||||
};
|
};
|
||||||
|
@ -217,12 +217,10 @@ pub use {
|
|||||||
},
|
},
|
||||||
self::manager::Asset,
|
self::manager::Asset,
|
||||||
self::runtime::{
|
self::runtime::{
|
||||||
|
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
|
||||||
webview::WebviewAttributes,
|
webview::WebviewAttributes,
|
||||||
window::{
|
window::{CursorIcon, DragDropEvent},
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
|
DeviceEventFilter, Rect, UserAttentionType,
|
||||||
CursorIcon, FileDropEvent,
|
|
||||||
},
|
|
||||||
DeviceEventFilter, UserAttentionType,
|
|
||||||
},
|
},
|
||||||
self::state::{State, StateManager},
|
self::state::{State, StateManager},
|
||||||
self::utils::{
|
self::utils::{
|
||||||
|
@ -14,7 +14,7 @@ use serde::Serialize;
|
|||||||
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
|
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
webview::{DetachedWebview, PendingWebview},
|
webview::{DetachedWebview, PendingWebview},
|
||||||
window::FileDropEvent,
|
window::DragDropEvent,
|
||||||
};
|
};
|
||||||
use tauri_utils::config::WebviewUrl;
|
use tauri_utils::config::WebviewUrl;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@ -29,7 +29,10 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
window::{FileDropPayload, DROP_CANCELLED_EVENT, DROP_EVENT, DROP_HOVER_EVENT},
|
window::{
|
||||||
|
DragDropPayload, DragOverPayload, DRAG_EVENT, DROP_CANCELLED_EVENT, DROP_EVENT,
|
||||||
|
DROP_HOVER_EVENT,
|
||||||
|
},
|
||||||
AppManager,
|
AppManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -654,12 +657,16 @@ impl<R: Runtime> Webview<R> {
|
|||||||
|
|
||||||
fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> crate::Result<()> {
|
fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> crate::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
WebviewEvent::FileDrop(event) => match event {
|
WebviewEvent::DragDrop(event) => match event {
|
||||||
FileDropEvent::Hovered { paths, position } => {
|
DragDropEvent::Dragged { paths, position } => {
|
||||||
let payload = FileDropPayload { paths, position };
|
let payload = DragDropPayload { paths, position };
|
||||||
|
webview.emit_to_webview(DRAG_EVENT, payload)?
|
||||||
|
}
|
||||||
|
DragDropEvent::DragOver { position } => {
|
||||||
|
let payload = DragOverPayload { position };
|
||||||
webview.emit_to_webview(DROP_HOVER_EVENT, payload)?
|
webview.emit_to_webview(DROP_HOVER_EVENT, payload)?
|
||||||
}
|
}
|
||||||
FileDropEvent::Dropped { paths, position } => {
|
DragDropEvent::Dropped { paths, position } => {
|
||||||
let scopes = webview.state::<Scopes>();
|
let scopes = webview.state::<Scopes>();
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
@ -668,10 +675,10 @@ fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> c
|
|||||||
let _ = scopes.allow_directory(path, false);
|
let _ = scopes.allow_directory(path, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let payload = FileDropPayload { paths, position };
|
let payload = DragDropPayload { paths, position };
|
||||||
webview.emit_to_webview(DROP_EVENT, payload)?
|
webview.emit_to_webview(DROP_EVENT, payload)?
|
||||||
}
|
}
|
||||||
FileDropEvent::Cancelled => webview.emit_to_webview(DROP_CANCELLED_EVENT, ())?,
|
DragDropEvent::Cancelled => webview.emit_to_webview(DROP_CANCELLED_EVENT, ())?,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,9 @@ use std::{
|
|||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
window::WindowBuilder,
|
window::WindowBuilder,
|
||||||
window::{
|
window::{DetachedWindow, DragDropEvent, PendingWindow},
|
||||||
dpi::{PhysicalPosition, PhysicalSize},
|
|
||||||
DetachedWindow, FileDropEvent, PendingWindow,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -31,9 +29,10 @@ const WINDOW_FOCUS_EVENT: &str = "tauri://focus";
|
|||||||
const WINDOW_BLUR_EVENT: &str = "tauri://blur";
|
const WINDOW_BLUR_EVENT: &str = "tauri://blur";
|
||||||
const WINDOW_SCALE_FACTOR_CHANGED_EVENT: &str = "tauri://scale-change";
|
const WINDOW_SCALE_FACTOR_CHANGED_EVENT: &str = "tauri://scale-change";
|
||||||
const WINDOW_THEME_CHANGED: &str = "tauri://theme-changed";
|
const WINDOW_THEME_CHANGED: &str = "tauri://theme-changed";
|
||||||
pub const DROP_EVENT: &str = "tauri://file-drop";
|
pub const DRAG_EVENT: &str = "tauri://drag";
|
||||||
pub const DROP_HOVER_EVENT: &str = "tauri://file-drop-hover";
|
pub const DROP_EVENT: &str = "tauri://drop";
|
||||||
pub const DROP_CANCELLED_EVENT: &str = "tauri://file-drop-cancelled";
|
pub const DROP_HOVER_EVENT: &str = "tauri://drop-over";
|
||||||
|
pub const DROP_CANCELLED_EVENT: &str = "tauri://drag-cancelled";
|
||||||
|
|
||||||
pub struct WindowManager<R: Runtime> {
|
pub struct WindowManager<R: Runtime> {
|
||||||
pub windows: Mutex<HashMap<String, Window<R>>>,
|
pub windows: Mutex<HashMap<String, Window<R>>>,
|
||||||
@ -145,11 +144,16 @@ impl<R: Runtime> Window<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct FileDropPayload<'a> {
|
pub struct DragDropPayload<'a> {
|
||||||
pub paths: &'a Vec<PathBuf>,
|
pub paths: &'a Vec<PathBuf>,
|
||||||
pub position: &'a PhysicalPosition<f64>,
|
pub position: &'a PhysicalPosition<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone)]
|
||||||
|
pub struct DragOverPayload<'a> {
|
||||||
|
pub position: &'a PhysicalPosition<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate::Result<()> {
|
fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::Resized(size) => window.emit_to_window(WINDOW_RESIZED_EVENT, size)?,
|
WindowEvent::Resized(size) => window.emit_to_window(WINDOW_RESIZED_EVENT, size)?,
|
||||||
@ -190,9 +194,18 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
|
|||||||
size: *new_inner_size,
|
size: *new_inner_size,
|
||||||
},
|
},
|
||||||
)?,
|
)?,
|
||||||
WindowEvent::FileDrop(event) => match event {
|
WindowEvent::DragDrop(event) => match event {
|
||||||
FileDropEvent::Hovered { paths, position } => {
|
DragDropEvent::Dragged { paths, position } => {
|
||||||
let payload = FileDropPayload { paths, position };
|
let payload = DragDropPayload { paths, position };
|
||||||
|
|
||||||
|
if window.is_webview_window() {
|
||||||
|
window.emit_to(EventTarget::labeled(window.label()), DRAG_EVENT, payload)?
|
||||||
|
} else {
|
||||||
|
window.emit_to_window(DRAG_EVENT, payload)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DragDropEvent::DragOver { position } => {
|
||||||
|
let payload = DragOverPayload { position };
|
||||||
if window.is_webview_window() {
|
if window.is_webview_window() {
|
||||||
window.emit_to(
|
window.emit_to(
|
||||||
EventTarget::labeled(window.label()),
|
EventTarget::labeled(window.label()),
|
||||||
@ -203,7 +216,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
|
|||||||
window.emit_to_window(DROP_HOVER_EVENT, payload)?
|
window.emit_to_window(DROP_HOVER_EVENT, payload)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileDropEvent::Dropped { paths, position } => {
|
DragDropEvent::Dropped { paths, position } => {
|
||||||
let scopes = window.state::<Scopes>();
|
let scopes = window.state::<Scopes>();
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
@ -212,7 +225,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
|
|||||||
let _ = scopes.allow_directory(path, true);
|
let _ = scopes.allow_directory(path, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let payload = FileDropPayload { paths, position };
|
let payload = DragDropPayload { paths, position };
|
||||||
|
|
||||||
if window.is_webview_window() {
|
if window.is_webview_window() {
|
||||||
window.emit_to(EventTarget::labeled(window.label()), DROP_EVENT, payload)?
|
window.emit_to(EventTarget::labeled(window.label()), DROP_EVENT, payload)?
|
||||||
@ -220,7 +233,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
|
|||||||
window.emit_to_window(DROP_EVENT, payload)?
|
window.emit_to_window(DROP_EVENT, payload)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileDropEvent::Cancelled => {
|
DragDropEvent::Cancelled => {
|
||||||
if window.is_webview_window() {
|
if window.is_webview_window() {
|
||||||
window.emit_to(
|
window.emit_to(
|
||||||
EventTarget::labeled(window.label()),
|
EventTarget::labeled(window.label()),
|
||||||
|
@ -40,7 +40,7 @@ impl<R: Runtime> ContextMenuBase for Menu<R> {
|
|||||||
window: crate::Window<T>,
|
window: crate::Window<T>,
|
||||||
position: Option<P>,
|
position: Option<P>,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let position = position.map(Into::into).map(super::into_position);
|
let position = position.map(Into::into);
|
||||||
run_item_main_thread!(self, move |self_: Self| {
|
run_item_main_thread!(self, move |self_: Self| {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if let Ok(view) = window.ns_view() {
|
if let Ok(view) = window.ns_view() {
|
||||||
|
@ -762,22 +762,3 @@ pub(crate) mod sealed {
|
|||||||
) -> crate::Result<()>;
|
) -> crate::Result<()>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_logical_position<P: crate::Pixel>(
|
|
||||||
p: crate::LogicalPosition<P>,
|
|
||||||
) -> muda::LogicalPosition<P> {
|
|
||||||
muda::LogicalPosition { x: p.x, y: p.y }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn into_physical_position<P: crate::Pixel>(
|
|
||||||
p: crate::PhysicalPosition<P>,
|
|
||||||
) -> muda::PhysicalPosition<P> {
|
|
||||||
muda::PhysicalPosition { x: p.x, y: p.y }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn into_position(p: crate::Position) -> muda::Position {
|
|
||||||
match p {
|
|
||||||
crate::Position::Physical(p) => muda::Position::Physical(into_physical_position(p)),
|
|
||||||
crate::Position::Logical(p) => muda::Position::Logical(into_logical_position(p)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tauri_runtime::window::dpi::Position;
|
use tauri_runtime::dpi::Position;
|
||||||
|
|
||||||
use super::{sealed::ContextMenuBase, *};
|
use super::{sealed::ContextMenuBase, *};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -32,7 +32,7 @@ impl<R: Runtime> ContextMenuBase for Submenu<R> {
|
|||||||
window: crate::Window<T>,
|
window: crate::Window<T>,
|
||||||
position: Option<P>,
|
position: Option<P>,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let position = position.map(Into::into).map(super::into_position);
|
let position = position.map(Into::into);
|
||||||
run_item_main_thread!(self, move |self_: Self| {
|
run_item_main_thread!(self, move |self_: Self| {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if let Ok(view) = window.ns_view() {
|
if let Ok(view) = window.ns_view() {
|
||||||
|
@ -6,12 +6,10 @@
|
|||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
monitor::Monitor,
|
monitor::Monitor,
|
||||||
webview::{DetachedWebview, PendingWebview},
|
webview::{DetachedWebview, PendingWebview},
|
||||||
window::{
|
window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WindowEvent, WindowId},
|
||||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
|
||||||
CursorIcon, DetachedWindow, PendingWindow, RawWindow, WindowEvent, WindowId,
|
|
||||||
},
|
|
||||||
window::{WindowBuilder, WindowBuilderBase},
|
window::{WindowBuilder, WindowBuilderBase},
|
||||||
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
|
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
|
||||||
Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent,
|
Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent,
|
||||||
@ -505,6 +503,10 @@ impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
|
|||||||
.map_err(|_| Error::FailedToReceiveMessage)
|
.map_err(|_| Error::FailedToReceiveMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounds(&self) -> Result<tauri_runtime::Rect> {
|
||||||
|
Ok(tauri_runtime::Rect::default())
|
||||||
|
}
|
||||||
|
|
||||||
fn position(&self) -> Result<PhysicalPosition<i32>> {
|
fn position(&self) -> Result<PhysicalPosition<i32>> {
|
||||||
Ok(PhysicalPosition { x: 0, y: 0 })
|
Ok(PhysicalPosition { x: 0, y: 0 })
|
||||||
}
|
}
|
||||||
@ -529,6 +531,10 @@ impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_bounds(&self, bounds: tauri_runtime::Rect) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_size(&self, _size: Size) -> Result<()> {
|
fn set_size(&self, _size: Size) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
//! cmd: "ping".into(),
|
//! cmd: "ping".into(),
|
||||||
//! callback: tauri::ipc::CallbackFn(0),
|
//! callback: tauri::ipc::CallbackFn(0),
|
||||||
//! error: tauri::ipc::CallbackFn(1),
|
//! error: tauri::ipc::CallbackFn(1),
|
||||||
|
//! url: "http://tauri.localhost".parse().unwrap(),
|
||||||
//! body: tauri::ipc::InvokeBody::default(),
|
//! body: tauri::ipc::InvokeBody::default(),
|
||||||
//! headers: Default::default(),
|
//! headers: Default::default(),
|
||||||
//! },
|
//! },
|
||||||
@ -186,6 +187,7 @@ pub fn mock_app() -> App<MockRuntime> {
|
|||||||
/// cmd: "ping".into(),
|
/// cmd: "ping".into(),
|
||||||
/// callback: tauri::ipc::CallbackFn(0),
|
/// callback: tauri::ipc::CallbackFn(0),
|
||||||
/// error: tauri::ipc::CallbackFn(1),
|
/// error: tauri::ipc::CallbackFn(1),
|
||||||
|
/// url: "http://tauri.localhost".parse().unwrap(),
|
||||||
/// body: tauri::ipc::InvokeBody::default(),
|
/// body: tauri::ipc::InvokeBody::default(),
|
||||||
/// headers: Default::default(),
|
/// headers: Default::default(),
|
||||||
/// },
|
/// },
|
||||||
@ -242,6 +244,7 @@ pub fn assert_ipc_response<
|
|||||||
/// cmd: "ping".into(),
|
/// cmd: "ping".into(),
|
||||||
/// callback: tauri::ipc::CallbackFn(0),
|
/// callback: tauri::ipc::CallbackFn(0),
|
||||||
/// error: tauri::ipc::CallbackFn(1),
|
/// error: tauri::ipc::CallbackFn(1),
|
||||||
|
/// url: "http://tauri.localhost".parse().unwrap(),
|
||||||
/// body: tauri::ipc::InvokeBody::default(),
|
/// body: tauri::ipc::InvokeBody::default(),
|
||||||
/// headers: Default::default(),
|
/// headers: Default::default(),
|
||||||
/// },
|
/// },
|
||||||
|
@ -12,24 +12,13 @@ use crate::app::{GlobalMenuEventListener, GlobalTrayIconEventListener};
|
|||||||
use crate::menu::ContextMenu;
|
use crate::menu::ContextMenu;
|
||||||
use crate::menu::MenuEvent;
|
use crate::menu::MenuEvent;
|
||||||
use crate::resources::Resource;
|
use crate::resources::Resource;
|
||||||
use crate::{image::Image, menu::run_item_main_thread, AppHandle, Manager, Runtime};
|
use crate::{
|
||||||
|
image::Image, menu::run_item_main_thread, AppHandle, Manager, PhysicalPosition, Rect, Runtime,
|
||||||
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
pub use tray_icon::TrayIconId;
|
pub use tray_icon::TrayIconId;
|
||||||
|
|
||||||
/// Describes a rectangle including position (x - y axis) and size.
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize)]
|
|
||||||
pub struct Rectangle {
|
|
||||||
/// The x-coordinate of the upper-left corner of the rectangle.
|
|
||||||
pub left: f64,
|
|
||||||
/// The y-coordinate of the upper-left corner of the rectangle.
|
|
||||||
pub top: f64,
|
|
||||||
/// The x-coordinate of the lower-right corner of the rectangle.
|
|
||||||
pub right: f64,
|
|
||||||
/// The y-coordinate of the lower-right corner of the rectangle.
|
|
||||||
pub bottom: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes the click type that triggered this tray icon event.
|
/// Describes the click type that triggered this tray icon event.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize)]
|
||||||
pub enum ClickType {
|
pub enum ClickType {
|
||||||
@ -58,12 +47,10 @@ impl Default for ClickType {
|
|||||||
pub struct TrayIconEvent {
|
pub struct TrayIconEvent {
|
||||||
/// Id of the tray icon which triggered this event.
|
/// Id of the tray icon which triggered this event.
|
||||||
pub id: TrayIconId,
|
pub id: TrayIconId,
|
||||||
/// Physical X Position of the click the triggered this event.
|
/// Physical Position of the click the triggered this event.
|
||||||
pub x: f64,
|
pub position: PhysicalPosition<f64>,
|
||||||
/// Physical Y Position of the click the triggered this event.
|
|
||||||
pub y: f64,
|
|
||||||
/// Position and size of the tray icon
|
/// Position and size of the tray icon
|
||||||
pub icon_rect: Rectangle,
|
pub icon_rect: Rect,
|
||||||
/// The click type that triggered this event.
|
/// The click type that triggered this event.
|
||||||
pub click_type: ClickType,
|
pub click_type: ClickType,
|
||||||
}
|
}
|
||||||
@ -75,17 +62,6 @@ impl TrayIconEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<tray_icon::Rectangle> for Rectangle {
|
|
||||||
fn from(value: tray_icon::Rectangle) -> Self {
|
|
||||||
Self {
|
|
||||||
bottom: value.bottom,
|
|
||||||
left: value.left,
|
|
||||||
top: value.top,
|
|
||||||
right: value.right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<tray_icon::ClickType> for ClickType {
|
impl From<tray_icon::ClickType> for ClickType {
|
||||||
fn from(value: tray_icon::ClickType) -> Self {
|
fn from(value: tray_icon::ClickType) -> Self {
|
||||||
match value {
|
match value {
|
||||||
@ -100,9 +76,11 @@ impl From<tray_icon::TrayIconEvent> for TrayIconEvent {
|
|||||||
fn from(value: tray_icon::TrayIconEvent) -> Self {
|
fn from(value: tray_icon::TrayIconEvent) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: value.id,
|
id: value.id,
|
||||||
x: value.x,
|
position: value.position,
|
||||||
y: value.y,
|
icon_rect: Rect {
|
||||||
icon_rect: value.icon_rect.into(),
|
position: value.icon_rect.position.into(),
|
||||||
|
size: value.icon_rect.size.into(),
|
||||||
|
},
|
||||||
click_type: value.click_type.into(),
|
click_type: value.click_type.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,15 @@ use http::HeaderMap;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tauri_macros::default_runtime;
|
use tauri_macros::default_runtime;
|
||||||
pub use tauri_runtime::webview::PageLoadEvent;
|
pub use tauri_runtime::webview::PageLoadEvent;
|
||||||
use tauri_runtime::{
|
|
||||||
webview::{DetachedWebview, PendingWebview, WebviewAttributes},
|
|
||||||
WebviewDispatch,
|
|
||||||
};
|
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
window::dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
WindowDispatch,
|
WindowDispatch,
|
||||||
};
|
};
|
||||||
|
use tauri_runtime::{
|
||||||
|
webview::{DetachedWebview, PendingWebview, WebviewAttributes},
|
||||||
|
Rect, WebviewDispatch,
|
||||||
|
};
|
||||||
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
||||||
pub use url::Url;
|
pub use url::Url;
|
||||||
|
|
||||||
@ -118,6 +118,8 @@ pub struct InvokeRequest {
|
|||||||
pub callback: CallbackFn,
|
pub callback: CallbackFn,
|
||||||
/// The error callback.
|
/// The error callback.
|
||||||
pub error: CallbackFn,
|
pub error: CallbackFn,
|
||||||
|
/// URL of the frame that requested this command.
|
||||||
|
pub url: Url,
|
||||||
/// The body of the request.
|
/// The body of the request.
|
||||||
pub body: InvokeBody,
|
pub body: InvokeBody,
|
||||||
/// The request headers.
|
/// The request headers.
|
||||||
@ -616,7 +618,7 @@ tauri::Builder::default()
|
|||||||
let mut pending =
|
let mut pending =
|
||||||
self.into_pending_webview(&window, window.label(), &window_labels, &webview_labels)?;
|
self.into_pending_webview(&window, window.label(), &window_labels, &webview_labels)?;
|
||||||
|
|
||||||
pending.webview_attributes.bounds = Some((position, size));
|
pending.webview_attributes.bounds = Some(Rect { size, position });
|
||||||
|
|
||||||
let webview = match &mut window.runtime() {
|
let webview = match &mut window.runtime() {
|
||||||
RuntimeOrDispatch::Dispatch(dispatcher) => dispatcher.create_webview(pending),
|
RuntimeOrDispatch::Dispatch(dispatcher) => dispatcher.create_webview(pending),
|
||||||
@ -714,10 +716,10 @@ fn main() {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables the file drop handler. This is required to use drag and drop APIs on the front end on Windows.
|
/// Disables the drag and drop handler. This is required to use HTML5 drag and drop APIs on the frontend on Windows.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn disable_file_drop_handler(mut self) -> Self {
|
pub fn disable_drag_drop_handler(mut self) -> Self {
|
||||||
self.webview_attributes.file_drop_handler_enabled = false;
|
self.webview_attributes.drag_drop_handler_enabled = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,6 +884,15 @@ impl<R: Runtime> Webview<R> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resizes this webview.
|
||||||
|
pub fn set_bounds(&self, bounds: Rect) -> crate::Result<()> {
|
||||||
|
self
|
||||||
|
.webview
|
||||||
|
.dispatcher
|
||||||
|
.set_bounds(bounds)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
/// Resizes this webview.
|
/// Resizes this webview.
|
||||||
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
|
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
|
||||||
self
|
self
|
||||||
@ -929,6 +940,11 @@ impl<R: Runtime> Webview<R> {
|
|||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the bounds of the webviews's client area.
|
||||||
|
pub fn bounds(&self) -> crate::Result<Rect> {
|
||||||
|
self.webview.dispatcher.bounds().map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the webview position.
|
/// Returns the webview position.
|
||||||
///
|
///
|
||||||
/// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window.
|
/// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window.
|
||||||
@ -1081,8 +1097,7 @@ fn main() {
|
|||||||
/// Handles this window receiving an [`InvokeRequest`].
|
/// Handles this window receiving an [`InvokeRequest`].
|
||||||
pub fn on_message(self, request: InvokeRequest, responder: Box<OwnedInvokeResponder<R>>) {
|
pub fn on_message(self, request: InvokeRequest, responder: Box<OwnedInvokeResponder<R>>) {
|
||||||
let manager = self.manager_owned();
|
let manager = self.manager_owned();
|
||||||
let current_url = self.url();
|
let is_local = self.is_local_url(&request.url);
|
||||||
let is_local = self.is_local_url(¤t_url);
|
|
||||||
|
|
||||||
let custom_responder = self.manager().webview.invoke_responder.clone();
|
let custom_responder = self.manager().webview.invoke_responder.clone();
|
||||||
|
|
||||||
@ -1118,7 +1133,7 @@ fn main() {
|
|||||||
Origin::Local
|
Origin::Local
|
||||||
} else {
|
} else {
|
||||||
Origin::Remote {
|
Origin::Remote {
|
||||||
url: current_url.clone(),
|
url: request.url.clone(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (resolved_acl, has_app_acl_manifest) = {
|
let (resolved_acl, has_app_acl_manifest) = {
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
mod desktop_commands {
|
mod desktop_commands {
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tauri_runtime::window::dpi::{Position, Size};
|
use tauri_runtime::dpi::{Position, Size};
|
||||||
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -28,7 +28,7 @@ mod desktop_commands {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
url: WebviewUrl,
|
url: WebviewUrl,
|
||||||
user_agent: Option<String>,
|
user_agent: Option<String>,
|
||||||
file_drop_enabled: Option<bool>,
|
drag_drop_enabled: Option<bool>,
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
width: f64,
|
width: f64,
|
||||||
@ -71,8 +71,8 @@ mod desktop_commands {
|
|||||||
let mut builder = crate::webview::WebviewBuilder::new(label, options.url);
|
let mut builder = crate::webview::WebviewBuilder::new(label, options.url);
|
||||||
|
|
||||||
builder.webview_attributes.user_agent = options.user_agent;
|
builder.webview_attributes.user_agent = options.user_agent;
|
||||||
builder.webview_attributes.file_drop_handler_enabled =
|
builder.webview_attributes.drag_drop_handler_enabled =
|
||||||
options.file_drop_enabled.unwrap_or(true);
|
options.drag_drop_enabled.unwrap_or(true);
|
||||||
builder.webview_attributes.transparent = options.transparent;
|
builder.webview_attributes.transparent = options.transparent;
|
||||||
builder.webview_attributes.accept_first_mouse = options.accept_first_mouse;
|
builder.webview_attributes.accept_first_mouse = options.accept_first_mouse;
|
||||||
builder.webview_attributes.window_effects = options.window_effects;
|
builder.webview_attributes.window_effects = options.window_effects;
|
||||||
@ -80,8 +80,8 @@ mod desktop_commands {
|
|||||||
|
|
||||||
window.add_child(
|
window.add_child(
|
||||||
builder,
|
builder,
|
||||||
tauri_runtime::window::dpi::LogicalPosition::new(options.x, options.y),
|
tauri_runtime::dpi::LogicalPosition::new(options.x, options.y),
|
||||||
tauri_runtime::window::dpi::LogicalSize::new(options.width, options.height),
|
tauri_runtime::dpi::LogicalSize::new(options.width, options.height),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -144,13 +144,9 @@ mod desktop_commands {
|
|||||||
getter!(
|
getter!(
|
||||||
webview_position,
|
webview_position,
|
||||||
position,
|
position,
|
||||||
tauri_runtime::window::dpi::PhysicalPosition<i32>
|
tauri_runtime::dpi::PhysicalPosition<i32>
|
||||||
);
|
|
||||||
getter!(
|
|
||||||
webview_size,
|
|
||||||
size,
|
|
||||||
tauri_runtime::window::dpi::PhysicalSize<u32>
|
|
||||||
);
|
);
|
||||||
|
getter!(webview_size, size, tauri_runtime::dpi::PhysicalSize<u32>);
|
||||||
//getter!(is_focused, bool);
|
//getter!(is_focused, bool);
|
||||||
|
|
||||||
setter!(print);
|
setter!(print);
|
||||||
|
@ -8,7 +8,7 @@ use std::{borrow::Cow, path::PathBuf, sync::Arc};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event::EventTarget,
|
event::EventTarget,
|
||||||
runtime::window::dpi::{PhysicalPosition, PhysicalSize},
|
runtime::dpi::{PhysicalPosition, PhysicalSize},
|
||||||
window::Monitor,
|
window::Monitor,
|
||||||
};
|
};
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
@ -16,10 +16,8 @@ use crate::{
|
|||||||
image::Image,
|
image::Image,
|
||||||
menu::{ContextMenu, Menu},
|
menu::{ContextMenu, Menu},
|
||||||
runtime::{
|
runtime::{
|
||||||
window::{
|
dpi::{Position, Size},
|
||||||
dpi::{Position, Size},
|
window::CursorIcon,
|
||||||
CursorIcon,
|
|
||||||
},
|
|
||||||
UserAttentionType,
|
UserAttentionType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -792,10 +790,10 @@ fn main() {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables the file drop handler. This is required to use drag and drop APIs on the front end on Windows.
|
/// Disables the drag and drop handler. This is required to use HTML5 drag and drop APIs on the frontend on Windows.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn disable_file_drop_handler(mut self) -> Self {
|
pub fn disable_drag_drop_handler(mut self) -> Self {
|
||||||
self.webview_builder = self.webview_builder.disable_file_drop_handler();
|
self.webview_builder = self.webview_builder.disable_drag_drop_handler();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
pub(crate) mod plugin;
|
pub(crate) mod plugin;
|
||||||
|
|
||||||
use tauri_runtime::{
|
use tauri_runtime::{
|
||||||
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
webview::PendingWebview,
|
webview::PendingWebview,
|
||||||
window::dpi::{PhysicalPosition, PhysicalSize},
|
|
||||||
};
|
};
|
||||||
pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState};
|
pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState};
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ use crate::{
|
|||||||
image::Image,
|
image::Image,
|
||||||
menu::{ContextMenu, Menu, MenuId},
|
menu::{ContextMenu, Menu, MenuId},
|
||||||
runtime::{
|
runtime::{
|
||||||
window::dpi::{Position, Size},
|
dpi::{Position, Size},
|
||||||
UserAttentionType,
|
UserAttentionType,
|
||||||
},
|
},
|
||||||
CursorIcon,
|
CursorIcon,
|
||||||
|
315
examples/api/src-tauri/Cargo.lock
generated
315
examples/api/src-tauri/Cargo.lock
generated
@ -110,12 +110,6 @@ dependencies = [
|
|||||||
"tiny_http",
|
"tiny_http",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "as-raw-xcb-connection"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ascii"
|
name = "ascii"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -240,20 +234,6 @@ name = "bytemuck"
|
|||||||
version = "1.14.3"
|
version = "1.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f"
|
checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f"
|
||||||
dependencies = [
|
|
||||||
"bytemuck_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bytemuck_derive"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.52",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
@ -726,51 +706,6 @@ dependencies = [
|
|||||||
"syn 2.0.52",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "downcast-rs"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "drm"
|
|
||||||
version = "0.11.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a0f8a69e60d75ae7dab4ef26a59ca99f2a89d4c142089b537775ae0c198bdcde"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.2",
|
|
||||||
"bytemuck",
|
|
||||||
"drm-ffi",
|
|
||||||
"drm-fourcc",
|
|
||||||
"rustix",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "drm-ffi"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6"
|
|
||||||
dependencies = [
|
|
||||||
"drm-sys",
|
|
||||||
"rustix",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "drm-fourcc"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "drm-sys"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2d09ff881f92f118b11105ba5e34ff8f4adf27b30dae8f12e28c193af1c83176"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys 0.6.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
@ -833,22 +768,6 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.3.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fastrand"
|
|
||||||
version = "2.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdeflate"
|
name = "fdeflate"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@ -1134,16 +1053,6 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gethostname"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-targets 0.48.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -1752,18 +1661,6 @@ dependencies = [
|
|||||||
"safemem",
|
"safemem",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0b5399f6804fbab912acbd8878ed3532d506b7c951b8f9f164ef90fef39e3f4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
@ -1845,15 +1742,6 @@ version = "2.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memmap2"
|
|
||||||
version = "0.9.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -1892,9 +1780,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "muda"
|
name = "muda"
|
||||||
version = "0.11.5"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453"
|
checksum = "3e27c56b8cb9b3214d196556227b0eaa12db8393b4f919a0a93ffb67ed17d185"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -2610,19 +2498,6 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.31"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.2",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys 0.4.13",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@ -2916,29 +2791,20 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "071916a85d1db274b4ed57af3a14afb66bd836ae7f82ebb6f1fd3455107830d9"
|
checksum = "071916a85d1db274b4ed57af3a14afb66bd836ae7f82ebb6f1fd3455107830d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as-raw-xcb-connection",
|
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg_aliases 0.2.0",
|
"cfg_aliases 0.2.0",
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"drm",
|
|
||||||
"fastrand",
|
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
|
||||||
"objc",
|
"objc",
|
||||||
"raw-window-handle 0.6.0",
|
"raw-window-handle 0.6.0",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"rustix",
|
|
||||||
"tiny-xlib",
|
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wayland-backend",
|
|
||||||
"wayland-client",
|
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
"x11rb",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3128,7 +2994,7 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
"windows 0.52.0",
|
"windows 0.52.0",
|
||||||
"windows-implement",
|
"windows-implement 0.52.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
]
|
]
|
||||||
@ -3152,7 +3018,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "2.0.0-beta.11"
|
version = "2.0.0-beta.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -3196,12 +3062,12 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"window-vibrancy",
|
"window-vibrancy",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-build"
|
name = "tauri-build"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
@ -3223,7 +3089,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.0",
|
"base64 0.22.0",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -3248,7 +3114,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -3260,7 +3126,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin"
|
name = "tauri-plugin"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"glob",
|
"glob",
|
||||||
@ -3286,7 +3152,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime"
|
name = "tauri-runtime"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@ -3297,12 +3163,12 @@ dependencies = [
|
|||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"url",
|
"url",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"gtk",
|
"gtk",
|
||||||
@ -3318,13 +3184,13 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-utils"
|
name = "tauri-utils"
|
||||||
version = "2.0.0-beta.9"
|
version = "2.0.0-beta.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -3446,18 +3312,6 @@ dependencies = [
|
|||||||
"time-core",
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tiny-xlib"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d4098d49269baa034a8d1eae9bd63e9fa532148d772121dace3bcd6a6c98eb6d"
|
|
||||||
dependencies = [
|
|
||||||
"as-raw-xcb-connection",
|
|
||||||
"ctor",
|
|
||||||
"libloading 0.8.1",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny_http"
|
name = "tiny_http"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -3644,9 +3498,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tray-icon"
|
name = "tray-icon"
|
||||||
version = "0.11.3"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a4d9ddd4a7c0f3b6862af1c4911b529a49db4ee89310d3a258859c2f5053fdd"
|
checksum = "454035ff34b8430638c894e6197748578d6b4d449c6edaf8ea854d94e2dd862b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
@ -3949,43 +3803,6 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wayland-backend"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"downcast-rs",
|
|
||||||
"rustix",
|
|
||||||
"scoped-tls",
|
|
||||||
"smallvec",
|
|
||||||
"wayland-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wayland-client"
|
|
||||||
version = "0.31.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.2",
|
|
||||||
"rustix",
|
|
||||||
"wayland-backend",
|
|
||||||
"wayland-scanner",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wayland-scanner"
|
|
||||||
version = "0.31.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quick-xml",
|
|
||||||
"quote",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
@ -3994,7 +3811,6 @@ checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4054,16 +3870,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webview2-com"
|
name = "webview2-com"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0ae9c7e420783826cf769d2c06ac9ba462f450eca5893bb8c6c6529a4e5dd33"
|
checksum = "38d5949fc3f537e90240c3e4f78dda2fa0431b671d50845a2f582173ef8a1201"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"webview2-com-macros",
|
"webview2-com-macros",
|
||||||
"webview2-com-sys",
|
"webview2-com-sys",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
"windows-core 0.52.0",
|
"windows-core 0.54.0",
|
||||||
"windows-implement",
|
"windows-implement 0.53.0",
|
||||||
"windows-interface",
|
"windows-interface 0.53.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4079,13 +3895,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webview2-com-sys"
|
name = "webview2-com-sys"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6ad85fceee6c42fa3d61239eba5a11401bf38407a849ed5ea1b407df08cca72"
|
checksum = "cd1eaa1be63d6fdcadf893c40d7d53c889a6342b3a94930d34e6964d5bb7e8db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
"windows-core 0.52.0",
|
"windows-core 0.54.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4139,8 +3955,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.52.0",
|
"windows-core 0.52.0",
|
||||||
"windows-implement",
|
"windows-implement 0.52.0",
|
||||||
"windows-interface",
|
"windows-interface 0.52.0",
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4154,6 +3970,18 @@ dependencies = [
|
|||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.54.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.54.0",
|
||||||
|
"windows-implement 0.53.0",
|
||||||
|
"windows-interface 0.53.0",
|
||||||
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -4173,6 +4001,16 @@ dependencies = [
|
|||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.54.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"
|
||||||
|
dependencies = [
|
||||||
|
"windows-result",
|
||||||
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-implement"
|
name = "windows-implement"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -4184,6 +4022,17 @@ dependencies = [
|
|||||||
"syn 2.0.52",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-interface"
|
name = "windows-interface"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -4195,6 +4044,17 @@ dependencies = [
|
|||||||
"syn 2.0.52",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -4442,9 +4302,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.37.0"
|
version = "0.38.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b717040ba9771fd88eb428c6ea6b555f8e734ff8534f02c13e8f10d97f5935e"
|
checksum = "741261f2571990873d0dd5953cff8087f39a16fb37550edd0acf7221b9c8d65b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"block",
|
"block",
|
||||||
@ -4461,7 +4321,6 @@ dependencies = [
|
|||||||
"jni",
|
"jni",
|
||||||
"kuchikiki",
|
"kuchikiki",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
@ -4470,8 +4329,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"raw-window-handle 0.6.0",
|
"raw-window-handle 0.6.0",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sha2",
|
"sha2",
|
||||||
"soup3",
|
"soup3",
|
||||||
"tao-macros",
|
"tao-macros",
|
||||||
@ -4479,8 +4336,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webkit2gtk-sys",
|
"webkit2gtk-sys",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows 0.52.0",
|
"windows 0.54.0",
|
||||||
"windows-implement",
|
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
]
|
]
|
||||||
@ -4505,24 +4361,3 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "x11rb"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a"
|
|
||||||
dependencies = [
|
|
||||||
"as-raw-xcb-connection",
|
|
||||||
"gethostname",
|
|
||||||
"libc",
|
|
||||||
"libloading 0.8.1",
|
|
||||||
"once_cell",
|
|
||||||
"rustix",
|
|
||||||
"x11rb-protocol",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "x11rb-protocol"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34"
|
|
||||||
|
@ -57,9 +57,10 @@ enum TauriEvent {
|
|||||||
WINDOW_THEME_CHANGED = 'tauri://theme-changed',
|
WINDOW_THEME_CHANGED = 'tauri://theme-changed',
|
||||||
WINDOW_CREATED = 'tauri://window-created',
|
WINDOW_CREATED = 'tauri://window-created',
|
||||||
WEBVIEW_CREATED = 'tauri://webview-created',
|
WEBVIEW_CREATED = 'tauri://webview-created',
|
||||||
FILE_DROP = 'tauri://file-drop',
|
DRAG = 'tauri://drag',
|
||||||
FILE_DROP_HOVER = 'tauri://file-drop-hover',
|
DROP = 'tauri://drop',
|
||||||
FILE_DROP_CANCELLED = 'tauri://file-drop-cancelled'
|
DROP_OVER = 'tauri://drop-over',
|
||||||
|
DROP_CANCELLED = 'tauri://drag-cancelled'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,16 +33,21 @@ import { invoke } from './core'
|
|||||||
import { Window, getCurrent as getCurrentWindow } from './window'
|
import { Window, getCurrent as getCurrentWindow } from './window'
|
||||||
import { WebviewWindow } from './webviewWindow'
|
import { WebviewWindow } from './webviewWindow'
|
||||||
|
|
||||||
interface FileDropPayload {
|
interface DragDropPayload {
|
||||||
paths: string[]
|
paths: string[]
|
||||||
position: PhysicalPosition
|
position: PhysicalPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The file drop event types. */
|
interface DragOverPayload {
|
||||||
type FileDropEvent =
|
position: PhysicalPosition
|
||||||
| ({ type: 'hover' } & FileDropPayload)
|
}
|
||||||
| ({ type: 'drop' } & FileDropPayload)
|
|
||||||
| { type: 'cancel' }
|
/** The drag and drop event types. */
|
||||||
|
type DragDropEvent =
|
||||||
|
| ({ type: 'dragged' } & DragDropPayload)
|
||||||
|
| ({ type: 'dragOver' } & DragOverPayload)
|
||||||
|
| ({ type: 'dropped' } & DragDropPayload)
|
||||||
|
| { type: 'cancelled' }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an instance of `Webview` for the current webview.
|
* Get an instance of `Webview` for the current webview.
|
||||||
@ -502,7 +507,7 @@ class Webview {
|
|||||||
* @example
|
* @example
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* import { getCurrent } from "@tauri-apps/api/webview";
|
* import { getCurrent } from "@tauri-apps/api/webview";
|
||||||
* const unlisten = await getCurrent().onFileDropEvent((event) => {
|
* const unlisten = await getCurrent().onDragDropEvent((event) => {
|
||||||
* if (event.payload.type === 'hover') {
|
* if (event.payload.type === 'hover') {
|
||||||
* console.log('User hovering', event.payload.paths);
|
* console.log('User hovering', event.payload.paths);
|
||||||
* } else if (event.payload.type === 'drop') {
|
* } else if (event.payload.type === 'drop') {
|
||||||
@ -519,16 +524,16 @@ class Webview {
|
|||||||
* @returns A promise resolving to a function to unlisten to the event.
|
* @returns A promise resolving to a function to unlisten to the event.
|
||||||
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
||||||
*/
|
*/
|
||||||
async onFileDropEvent(
|
async onDragDropEvent(
|
||||||
handler: EventCallback<FileDropEvent>
|
handler: EventCallback<DragDropEvent>
|
||||||
): Promise<UnlistenFn> {
|
): Promise<UnlistenFn> {
|
||||||
const unlistenFileDrop = await this.listen<FileDropPayload>(
|
const unlistenDrag = await this.listen<DragDropPayload>(
|
||||||
TauriEvent.FILE_DROP,
|
TauriEvent.DRAG,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({
|
handler({
|
||||||
...event,
|
...event,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'drop',
|
type: 'dragged',
|
||||||
paths: event.payload.paths,
|
paths: event.payload.paths,
|
||||||
position: mapPhysicalPosition(event.payload.position)
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
}
|
}
|
||||||
@ -536,13 +541,13 @@ class Webview {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const unlistenFileHover = await this.listen<FileDropPayload>(
|
const unlistenDrop = await this.listen<DragDropPayload>(
|
||||||
TauriEvent.FILE_DROP_HOVER,
|
TauriEvent.DROP,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({
|
handler({
|
||||||
...event,
|
...event,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'hover',
|
type: 'dropped',
|
||||||
paths: event.payload.paths,
|
paths: event.payload.paths,
|
||||||
position: mapPhysicalPosition(event.payload.position)
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
}
|
}
|
||||||
@ -550,16 +555,30 @@ class Webview {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const unlistenDragOver = await this.listen<DragDropPayload>(
|
||||||
|
TauriEvent.DROP_CANCELLED,
|
||||||
|
(event) => {
|
||||||
|
handler({
|
||||||
|
...event,
|
||||||
|
payload: {
|
||||||
|
type: 'dragOver',
|
||||||
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const unlistenCancel = await this.listen<null>(
|
const unlistenCancel = await this.listen<null>(
|
||||||
TauriEvent.FILE_DROP_CANCELLED,
|
TauriEvent.DROP_CANCELLED,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({ ...event, payload: { type: 'cancel' } })
|
handler({ ...event, payload: { type: 'cancelled' } })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unlistenFileDrop()
|
unlistenDrag()
|
||||||
unlistenFileHover()
|
unlistenDrop()
|
||||||
|
unlistenDragOver()
|
||||||
unlistenCancel()
|
unlistenCancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,11 +617,11 @@ interface WebviewOptions {
|
|||||||
*/
|
*/
|
||||||
transparent?: boolean
|
transparent?: boolean
|
||||||
/**
|
/**
|
||||||
* Whether the file drop is enabled or not on the webview. By default it is enabled.
|
* Whether the drag and drop is enabled or not on the webview. By default it is enabled.
|
||||||
*
|
*
|
||||||
* Disabling it is required to use drag and drop on the frontend on Windows.
|
* Disabling it is required to use HTML5 drag and drop on the frontend on Windows.
|
||||||
*/
|
*/
|
||||||
fileDropEnabled?: boolean
|
dragDropEnabled?: boolean
|
||||||
/**
|
/**
|
||||||
* Whether clicking an inactive webview also clicks through to the webview on macOS.
|
* Whether clicking an inactive webview also clicks through to the webview on macOS.
|
||||||
*/
|
*/
|
||||||
@ -633,4 +652,4 @@ interface WebviewOptions {
|
|||||||
|
|
||||||
export { Webview, getCurrent, getAll }
|
export { Webview, getCurrent, getAll }
|
||||||
|
|
||||||
export type { FileDropEvent, FileDropPayload, WebviewOptions }
|
export type { DragDropEvent, DragDropPayload, WebviewOptions }
|
||||||
|
@ -13,7 +13,7 @@ import { Window } from './window'
|
|||||||
import { listen, once } from './event'
|
import { listen, once } from './event'
|
||||||
import type { EventName, EventCallback, UnlistenFn } from './event'
|
import type { EventName, EventCallback, UnlistenFn } from './event'
|
||||||
import { invoke } from './core'
|
import { invoke } from './core'
|
||||||
import type { FileDropEvent, FileDropPayload } from './webview'
|
import type { DragDropEvent, DragDropPayload } from './webview'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an instance of `Webview` for the current webview window.
|
* Get an instance of `Webview` for the current webview window.
|
||||||
@ -231,4 +231,4 @@ function applyMixins(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { WebviewWindow, getCurrent, getAll }
|
export { WebviewWindow, getCurrent, getAll }
|
||||||
export type { FileDropEvent, FileDropPayload }
|
export type { DragDropEvent, DragDropPayload }
|
||||||
|
@ -35,7 +35,7 @@ import {
|
|||||||
} from './event'
|
} from './event'
|
||||||
import { invoke } from './core'
|
import { invoke } from './core'
|
||||||
import { WebviewWindow } from './webviewWindow'
|
import { WebviewWindow } from './webviewWindow'
|
||||||
import type { FileDropEvent, FileDropPayload } from './webview'
|
import type { DragDropEvent, DragDropPayload } from './webview'
|
||||||
import { Image, transformImage } from './image'
|
import { Image, transformImage } from './image'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1717,7 +1717,7 @@ class Window {
|
|||||||
* @example
|
* @example
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* import { getCurrent } from "@tauri-apps/api/webview";
|
* import { getCurrent } from "@tauri-apps/api/webview";
|
||||||
* const unlisten = await getCurrent().onFileDropEvent((event) => {
|
* const unlisten = await getCurrent().onDragDropEvent((event) => {
|
||||||
* if (event.payload.type === 'hover') {
|
* if (event.payload.type === 'hover') {
|
||||||
* console.log('User hovering', event.payload.paths);
|
* console.log('User hovering', event.payload.paths);
|
||||||
* } else if (event.payload.type === 'drop') {
|
* } else if (event.payload.type === 'drop') {
|
||||||
@ -1734,16 +1734,16 @@ class Window {
|
|||||||
* @returns A promise resolving to a function to unlisten to the event.
|
* @returns A promise resolving to a function to unlisten to the event.
|
||||||
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
||||||
*/
|
*/
|
||||||
async onFileDropEvent(
|
async onDragDropEvent(
|
||||||
handler: EventCallback<FileDropEvent>
|
handler: EventCallback<DragDropEvent>
|
||||||
): Promise<UnlistenFn> {
|
): Promise<UnlistenFn> {
|
||||||
const unlistenFileDrop = await this.listen<FileDropPayload>(
|
const unlistenDrag = await this.listen<DragDropPayload>(
|
||||||
TauriEvent.FILE_DROP,
|
TauriEvent.DRAG,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({
|
handler({
|
||||||
...event,
|
...event,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'drop',
|
type: 'dragged',
|
||||||
paths: event.payload.paths,
|
paths: event.payload.paths,
|
||||||
position: mapPhysicalPosition(event.payload.position)
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
}
|
}
|
||||||
@ -1751,13 +1751,13 @@ class Window {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const unlistenFileHover = await this.listen<FileDropPayload>(
|
const unlistenDrop = await this.listen<DragDropPayload>(
|
||||||
TauriEvent.FILE_DROP_HOVER,
|
TauriEvent.DROP,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({
|
handler({
|
||||||
...event,
|
...event,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'hover',
|
type: 'dropped',
|
||||||
paths: event.payload.paths,
|
paths: event.payload.paths,
|
||||||
position: mapPhysicalPosition(event.payload.position)
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
}
|
}
|
||||||
@ -1765,16 +1765,30 @@ class Window {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const unlistenDragOver = await this.listen<DragDropPayload>(
|
||||||
|
TauriEvent.DROP_OVER,
|
||||||
|
(event) => {
|
||||||
|
handler({
|
||||||
|
...event,
|
||||||
|
payload: {
|
||||||
|
type: 'dragOver',
|
||||||
|
position: mapPhysicalPosition(event.payload.position)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const unlistenCancel = await this.listen<null>(
|
const unlistenCancel = await this.listen<null>(
|
||||||
TauriEvent.FILE_DROP_CANCELLED,
|
TauriEvent.DROP_CANCELLED,
|
||||||
(event) => {
|
(event) => {
|
||||||
handler({ ...event, payload: { type: 'cancel' } })
|
handler({ ...event, payload: { type: 'cancelled' } })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unlistenFileDrop()
|
unlistenDrag()
|
||||||
unlistenFileHover()
|
unlistenDrop()
|
||||||
|
unlistenDragOver()
|
||||||
unlistenCancel()
|
unlistenCancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2264,6 +2278,6 @@ export type {
|
|||||||
ScaleFactorChanged,
|
ScaleFactorChanged,
|
||||||
WindowOptions,
|
WindowOptions,
|
||||||
Color,
|
Color,
|
||||||
FileDropEvent,
|
DragDropEvent,
|
||||||
FileDropPayload
|
DragDropPayload
|
||||||
}
|
}
|
||||||
|
@ -221,8 +221,8 @@
|
|||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"fileDropEnabled": {
|
"dragDropEnabled": {
|
||||||
"description": "Whether the file drop is enabled or not on the webview. By default it is enabled.\n\nDisabling it is required to use drag and drop on the frontend on Windows.",
|
"description": "Whether the drag and drop is enabled or not on the webview. By default it is enabled.\n\nDisabling it is required to use HTML5 drag and drop on the frontend on Windows.",
|
||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user