Skip to content

Commit

Permalink
fix(linux): fix DragDropEvent::Drop never fired on wayland (#1408)
Browse files Browse the repository at this point in the history
* fix(linux): fix `DragDrop` never fired on wayland

closes tauri-apps/tauri#11282

* Update src/webkitgtk/drag_drop.rs
  • Loading branch information
amrbashir authored Nov 9, 2024
1 parent 6007608 commit c193e2a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changes/drag-drop-wayland.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": "patch"
---

Fix `DragDropEvent::Drop` event never fired on Wayland (and sometimes on X11).
41 changes: 29 additions & 12 deletions src/webkitgtk/drag_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ use webkit2gtk::WebView;

use crate::DragDropEvent;

#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
enum DragControllerState {
Entered,
Leaving,
Left,
}

struct DragDropController {
paths: UnsafeCell<Option<Vec<PathBuf>>>,
has_entered: Cell<bool>,
state: Cell<DragControllerState>,
position: Cell<(i32, i32)>,
handler: Box<dyn Fn(DragDropEvent) -> bool>,
}
Expand All @@ -25,7 +32,7 @@ impl DragDropController {
Self {
handler,
paths: UnsafeCell::new(None),
has_entered: Cell::new(false),
state: Cell::new(DragControllerState::Left),
position: Cell::new((0, 0)),
}
}
Expand All @@ -43,15 +50,19 @@ impl DragDropController {
}

fn enter(&self) {
self.has_entered.set(true);
self.state.set(DragControllerState::Entered);
}

fn has_entered(&self) -> bool {
self.has_entered.get()
fn leaving(&self) {
self.state.set(DragControllerState::Leaving);
}

fn leave(&self) {
self.has_entered.set(false);
self.state.set(DragControllerState::Left);
}

fn state(&self) -> DragControllerState {
self.state.get()
}

fn call(&self, event: DragDropEvent) -> bool {
Expand Down Expand Up @@ -81,7 +92,7 @@ pub(crate) fn connect_drag_event(webview: &WebView, handler: Box<dyn Fn(DragDrop
{
let controller = controller.clone();
webview.connect_drag_motion(move |_, _, x, y, _| {
if controller.has_entered() {
if controller.state() == DragControllerState::Entered {
controller.call(DragDropEvent::Over { position: (x, y) });
} else {
controller.store_position((x, y));
Expand All @@ -93,7 +104,7 @@ pub(crate) fn connect_drag_event(webview: &WebView, handler: Box<dyn Fn(DragDrop
{
let controller = controller.clone();
webview.connect_drag_drop(move |_, ctx, x, y, time| {
if controller.has_entered() {
if controller.state() == DragControllerState::Leaving {
if let Some(paths) = controller.take_paths() {
ctx.drop_finish(true, time);
controller.leave();
Expand All @@ -108,10 +119,16 @@ pub(crate) fn connect_drag_event(webview: &WebView, handler: Box<dyn Fn(DragDrop
});
}

webview.connect_drag_leave(move |_, _, time| {
if time == 0 {
controller.leave();
controller.call(DragDropEvent::Leave);
webview.connect_drag_leave(move |_w, _, _| {
if controller.state() != DragControllerState::Left {
controller.leaving();
let controller = controller.clone();
gtk::glib::idle_add_local_once(move || {
if controller.state() == DragControllerState::Leaving {
controller.leave();
controller.call(DragDropEvent::Leave);
}
});
}
});
}
Expand Down

0 comments on commit c193e2a

Please sign in to comment.