Skip to content

Commit

Permalink
feat: add file drop position (#847)
Browse files Browse the repository at this point in the history
* feat: add file drop position

* Update src/webview/mod.rs

* Update src/webview/mod.rs
  • Loading branch information
amrbashir authored Jan 17, 2023
1 parent 87216c7 commit bce39e2
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changes/file-drop-cursor-position.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": "minor"
---

**Breaking** Add position of the drop to `FileDropEvent` struct.
5 changes: 0 additions & 5 deletions src/file_drop.rs

This file was deleted.

13 changes: 11 additions & 2 deletions src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use wkwebview::*;
pub(crate) mod webview2;
#[cfg(target_os = "windows")]
use self::webview2::*;
use crate::application::dpi::PhysicalPosition;
use crate::Result;
#[cfg(target_os = "windows")]
use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Controller;
Expand Down Expand Up @@ -822,9 +823,17 @@ impl WebView {
#[derive(Debug, Serialize, Clone)]
pub enum FileDropEvent {
/// The file(s) have been dragged onto the window, but have not been dropped yet.
Hovered(Vec<PathBuf>),
Hovered {
paths: Vec<PathBuf>,
/// The position of the mouse cursor.
position: PhysicalPosition<f64>,
},
/// The file(s) have been dropped onto the window.
Dropped(Vec<PathBuf>),
Dropped {
paths: Vec<PathBuf>,
/// The position of the mouse cursor.
position: PhysicalPosition<f64>,
},
/// The file drop was aborted.
Cancelled,
}
Expand Down
29 changes: 24 additions & 5 deletions src/webview/webkitgtk/file_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use std::{cell::Cell, path::PathBuf, rc::Rc};

use gtk::prelude::*;
use tao::dpi::LogicalPosition;
use webkit2gtk::WebView;

use crate::{application::window::Window, webview::FileDropEvent};
Expand All @@ -18,7 +19,7 @@ pub(crate) fn connect_drag_event(

let listener_ref = listener.clone();
let w = window.clone();
webview.connect_drag_data_received(move |_, _, _, _, data, info, _| {
webview.connect_drag_data_received(move |_, _, x, y, data, info, _| {
if info == 2 {
let uris = data
.uris()
Expand All @@ -28,20 +29,38 @@ pub(crate) fn connect_drag_event(
PathBuf::from(path.to_string().strip_prefix("file://").unwrap_or(path))
})
.collect::<Vec<PathBuf>>();

listener_ref.1.set(Some(uris.clone()));
listener_ref.0(&w, FileDropEvent::Hovered(uris));

let scale_factor = w.scale_factor();
let position = LogicalPosition::new(x, y).to_physical(scale_factor);

listener_ref.0(
&w,
FileDropEvent::Hovered {
paths: uris,
position,
},
);
} else {
// drag_data_received is called twice, so we can ignore this signal
}
});

let listener_ref = listener.clone();
let w = window.clone();
webview.connect_drag_drop(move |_, _, _, _, _| {
webview.connect_drag_drop(move |_, _, x, y, _| {
let uris = listener_ref.1.take();
if let Some(uris) = uris {
listener_ref.0(&w, FileDropEvent::Dropped(uris))
let scale_factor = w.scale_factor();
let position = LogicalPosition::new(x, y).to_physical(scale_factor);

listener_ref.0(
&w,
FileDropEvent::Dropped {
paths: uris,
position,
},
)
} else {
false
}
Expand Down
33 changes: 27 additions & 6 deletions src/webview/webview2/file_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use std::{
};

use windows::Win32::{
Foundation::{self as win32f, BOOL, DRAGDROP_E_INVALIDHWND, HWND, LPARAM, POINTL},
Foundation::{self as win32f, BOOL, DRAGDROP_E_INVALIDHWND, HWND, LPARAM, POINT, POINTL},
Graphics::Gdi::ScreenToClient,
System::{
Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL},
Ole::{
Expand All @@ -36,7 +37,9 @@ use windows::Win32::{

use windows_implement::implement;

use crate::application::window::Window;
use crate::application::{
dpi::PhysicalPosition, platform::windows::WindowExtWindows, window::Window,
};

pub(crate) struct FileDropController {
drop_targets: Vec<IDropTarget>,
Expand Down Expand Up @@ -188,7 +191,7 @@ impl IDropTarget_Impl for FileDropHandler {
&self,
pDataObj: &Option<IDataObject>,
_grfKeyState: u32,
_pt: &POINTL,
pt: &POINTL,
pdwEffect: *mut u32,
) -> windows::core::Result<()> {
let mut paths = Vec::new();
Expand All @@ -203,9 +206,18 @@ impl IDropTarget_Impl for FileDropHandler {
*pdwEffect = cursor_effect.0;
*self.hovered_is_valid.get() = hovered_is_valid;
*self.cursor_effect.get() = cursor_effect.0;

let mut pt = POINT { x: pt.x, y: pt.y };
ScreenToClient(HWND(self.window.hwnd() as _), &mut pt);
}

(self.listener)(&self.window, FileDropEvent::Hovered(paths));
(self.listener)(
&self.window,
FileDropEvent::Hovered {
paths,
position: PhysicalPosition::new(pt.x as _, pt.y as _),
},
);

Ok(())
}
Expand All @@ -231,7 +243,7 @@ impl IDropTarget_Impl for FileDropHandler {
&self,
pDataObj: &Option<IDataObject>,
_grfKeyState: u32,
_pt: &POINTL,
pt: &POINTL,
_pdwEffect: *mut u32,
) -> windows::core::Result<()> {
let mut paths = Vec::new();
Expand All @@ -240,9 +252,18 @@ impl IDropTarget_Impl for FileDropHandler {
if let Some(hdrop) = hdrop {
DragFinish(hdrop);
}

let mut pt = POINT { x: pt.x, y: pt.y };
ScreenToClient(HWND(self.window.hwnd() as _), &mut pt);
}

(self.listener)(&self.window, FileDropEvent::Dropped(paths));
(self.listener)(
&self.window,
FileDropEvent::Dropped {
paths,
position: PhysicalPosition::new(pt.x as _, pt.y as _),
},
);

Ok(())
}
Expand Down
22 changes: 18 additions & 4 deletions src/webview/wkwebview/file_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ use std::{
rc::Rc,
};

use cocoa::base::{id, BOOL, YES};
use cocoa::{
base::{id, BOOL, YES},
foundation::NSPoint,
};
use objc::{
declare::ClassDecl,
runtime::{class_getInstanceMethod, method_getImplementation, Object, Sel},
};
use once_cell::sync::Lazy;

use crate::{application::window::Window, webview::FileDropEvent};
use crate::{
application::{dpi::LogicalPosition, window::Window},
webview::FileDropEvent,
};

pub(crate) type NSDragOperation = cocoa::foundation::NSUInteger;
#[allow(non_upper_case_globals)]
Expand Down Expand Up @@ -109,7 +115,11 @@ extern "C" fn dragging_entered(this: &mut Object, sel: Sel, drag_info: id) -> NS
let listener = unsafe { get_handler(this) };
let paths = unsafe { collect_paths(drag_info) };

if !listener.0(&listener.1, FileDropEvent::Hovered(paths)) {
let dl: NSPoint = unsafe { msg_send![this, draggingLocation] };
let scale_factor = listener.1.scale_factor();
let position = LogicalPosition::<f64>::from((dl.x, dl.y)).to_physical(scale_factor);

if !listener.0(&listener.1, FileDropEvent::Hovered { paths, position }) {
// Reject the Wry file drop (invoke the OS default behaviour)
OBJC_DRAGGING_ENTERED(this, sel, drag_info)
} else {
Expand All @@ -121,7 +131,11 @@ extern "C" fn perform_drag_operation(this: &mut Object, sel: Sel, drag_info: id)
let listener = unsafe { get_handler(this) };
let paths = unsafe { collect_paths(drag_info) };

if !listener.0(&listener.1, FileDropEvent::Dropped(paths)) {
let dl: NSPoint = unsafe { msg_send![this, draggingLocation] };
let scale_factor = listener.1.scale_factor();
let position = LogicalPosition::<f64>::from((dl.x, dl.y)).to_physical(scale_factor);

if !listener.0(&listener.1, FileDropEvent::Dropped { paths, position }) {
// Reject the Wry file drop (invoke the OS default behaviour)
OBJC_PERFORM_DRAG_OPERATION(this, sel, drag_info)
} else {
Expand Down

0 comments on commit bce39e2

Please sign in to comment.