From e06da24c852788833581174e6febdde52056b677 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Wed, 6 Dec 2023 11:49:37 +0800 Subject: [PATCH 1/8] feat: add ondrop callback POC --- crates/drag/src/lib.rs | 9 ++ crates/drag/src/platform_impl/gtk/mod.rs | 92 ++++++++++++++++---- crates/drag/src/platform_impl/macos/mod.rs | 39 ++++++++- crates/drag/src/platform_impl/windows/mod.rs | 26 ++++-- crates/tauri-plugin/src/lib.rs | 11 ++- examples/tao/src/main.rs | 5 +- examples/winit/src/main.rs | 5 +- examples/wry/src/main.rs | 5 +- 8 files changed, 164 insertions(+), 28 deletions(-) diff --git a/crates/drag/src/lib.rs b/crates/drag/src/lib.rs index f075449..d5edab6 100644 --- a/crates/drag/src/lib.rs +++ b/crates/drag/src/lib.rs @@ -96,6 +96,15 @@ pub enum Error { #[cfg(target_os = "linux")] #[error("empty drag target list")] EmptyTargetList, + #[error("failed to drop items")] + FailedToDrop, +} + +#[cfg_attr(feature = "serde", derive(Debug, serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(untagged))] +pub enum DropResult { + Dropped, + Cancel, } /// Item to be dragged. diff --git a/crates/drag/src/platform_impl/gtk/mod.rs b/crates/drag/src/platform_impl/gtk/mod.rs index c240b13..591f2d6 100644 --- a/crates/drag/src/platform_impl/gtk/mod.rs +++ b/crates/drag/src/platform_impl/gtk/mod.rs @@ -2,8 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::{DragItem, Image}; -use gdkx11::gdk; +use std::{ + rc::Rc, + sync::{Arc, Mutex}, +}; + +use crate::{DragItem, DropResult, Image}; +use gdkx11::{ + gdk, + glib::{ObjectExt, SignalHandlerId}, +}; use gtk::{ gdk_pixbuf, prelude::{DragContextExtManual, PixbufLoaderExt, WidgetExt, WidgetExtManual}, @@ -13,28 +21,29 @@ pub fn start_drag( window: >k::ApplicationWindow, item: DragItem, image: Image, + on_drop_callback: Option>, ) -> crate::Result<()> { + let handler_ids: Arc>> = Arc::new(Mutex::new(vec![])); + window.drag_source_set(gdk::ModifierType::BUTTON1_MASK, &[], gdk::DragAction::COPY); match item { DragItem::Files(paths) => { window.drag_source_add_uri_targets(); - - window.connect_drag_data_get(move |_, _, data, _, _| { - let uris: Vec = paths - .iter() - .map(|path| format!("file://{}", path.display())) - .collect(); - let uris: Vec<&str> = uris.iter().map(|s| s.as_str()).collect(); - data.set_uris(&uris); - }); + handler_ids + .lock() + .unwrap() + .push(window.connect_drag_data_get(move |_, _, data, _, _| { + let uris: Vec = paths + .iter() + .map(|path| format!("file://{}", path.display())) + .collect(); + let uris: Vec<&str> = uris.iter().map(|s| s.as_str()).collect(); + data.set_uris(&uris); + })); } } - window.connect_drag_end(|this, _| { - this.drag_source_unset(); - }); - if let Some(target_list) = &window.drag_source_get_target_list() { if let Some(drag_context) = window.drag_begin_with_coordinates( target_list, @@ -44,6 +53,10 @@ pub fn start_drag( -1, -1, ) { + let callback = on_drop_callback.map(Rc::new); + on_drop_cancel(&callback, window, &handler_ids, &drag_context); + on_drop_performed(&callback, window, &handler_ids, &drag_context); + let icon_pixbuf: Option = match &image { Image::Raw(data) => image_binary_to_pixbuf(data), Image::File(path) => match std::fs::read(path) { @@ -73,3 +86,52 @@ fn image_binary_to_pixbuf(data: &[u8]) -> Option { .and_then(|_| loader.pixbuf().ok_or(())) .ok() } + +fn clear_signal_handlers(window: >k::ApplicationWindow, handler_ids: &mut Vec) { + for handler_id in handler_ids.drain(..) { + println!("disconnecting handler {:?}", handler_id); + window.disconnect(handler_id); + } +} + +fn on_drop_cancel( + callback: &Option>>, + window: >k::ApplicationWindow, + handler_ids: &Arc>>, + drag_context: &gdk::DragContext, +) { + let callback = callback.as_ref().cloned(); + let window = window.clone(); + let handler_ids = handler_ids.clone(); + + drag_context.connect_cancel(move |_, _| { + let handler_ids = &mut handler_ids.lock().unwrap(); + clear_signal_handlers(&window, handler_ids); + window.drag_source_unset(); + + if let Some(callback) = &callback { + callback(DropResult::Cancel); + } + }); +} + +fn on_drop_performed( + callback: &Option>>, + window: >k::ApplicationWindow, + handler_ids: &Arc>>, + drag_context: &gdk::DragContext, +) { + let callback = callback.as_ref().cloned(); + let window = window.clone(); + let handler_ids = handler_ids.clone(); + + drag_context.connect_drop_performed(move |_, _| { + let handler_ids = &mut handler_ids.lock().unwrap(); + clear_signal_handlers(&window, handler_ids); + window.drag_source_unset(); + + if let Some(callback) = &callback { + callback(DropResult::Dropped); + } + }); +} diff --git a/crates/drag/src/platform_impl/macos/mod.rs b/crates/drag/src/platform_impl/macos/mod.rs index da5271a..f8cf629 100644 --- a/crates/drag/src/platform_impl/macos/mod.rs +++ b/crates/drag/src/platform_impl/macos/mod.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use std::ffi::c_void; + use cocoa::{ appkit::{NSAlignmentOptions, NSApp, NSEvent, NSEventModifierFlags, NSEventType, NSImage}, base::{id, nil}, @@ -13,7 +15,7 @@ use objc::{ }; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use crate::{DragItem, Image}; +use crate::{DragItem, DropResult, Image}; const UTF8_ENCODING: usize = 4; @@ -33,6 +35,7 @@ pub fn start_drag( handle: &W, item: DragItem, image: Image, + on_drop_callback: Option>, ) -> crate::Result<()> { if let RawWindowHandle::AppKit(w) = handle.raw_window_handle() { unsafe { @@ -101,11 +104,17 @@ pub fn start_drag( let cls = ClassDecl::new("DragRsSource", class!(NSObject)); let cls = match cls { Some(mut cls) => { + cls.add_ivar::<*mut c_void>("on_drop_ptr"); cls.add_method( sel!(draggingSession:sourceOperationMaskForDraggingContext:), dragging_session as extern "C" fn(&Object, Sel, id, NSUInteger) -> NSUInteger, ); + cls.add_method( + sel!(draggingSession:endedAtPoint:operation:), + dragging_session_end + as extern "C" fn(&Object, Sel, id, NSPoint, NSUInteger), + ); extern "C" fn dragging_session( _this: &Object, @@ -122,6 +131,29 @@ pub fn start_drag( } } + extern "C" fn dragging_session_end( + this: &Object, + _: Sel, + _dragging_session: id, + _ended_at_point: NSPoint, + operation: NSUInteger, + ) { + unsafe { + let callback = this.get_ivar::<*mut c_void>("on_drop_ptr"); + if callback.is_null() { + return; + } + + let callback = &*(*callback as *mut Box); + if operation == 0 { + // NSDragOperationNone + callback(DropResult::Cancel); + } else { + callback(DropResult::Dropped); + } + } + } + cls.register() } None => Class::get("DragRsSource").expect("Failed to get the class definition"), @@ -130,6 +162,11 @@ pub fn start_drag( let source: id = msg_send![cls, alloc]; let source: id = msg_send![source, init]; + if let Some(callback) = on_drop_callback { + let callback_ptr = Box::into_raw(Box::new(callback)); + (*source).set_ivar("on_drop_ptr", callback_ptr as *mut _ as *mut c_void); + } + let _: () = msg_send![ns_view, beginDraggingSessionWithItems: file_items event: drag_event source: source]; } diff --git a/crates/drag/src/platform_impl/windows/mod.rs b/crates/drag/src/platform_impl/windows/mod.rs index d6eadcf..7bd493f 100644 --- a/crates/drag/src/platform_impl/windows/mod.rs +++ b/crates/drag/src/platform_impl/windows/mod.rs @@ -4,7 +4,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use crate::{DragItem, Image}; +use crate::{DragItem, DropResult, Image}; use std::{ ffi::c_void, @@ -20,13 +20,12 @@ use windows::{ Graphics::Gdi::{GetObjectW, BITMAP}, System::Com::*, System::Memory::*, - System::Ole::OleInitialize, + System::Ole::{DoDragDrop, OleInitialize}, System::Ole::{IDropSource, IDropSource_Impl, CF_HDROP, DROPEFFECT, DROPEFFECT_COPY}, System::SystemServices::{MK_LBUTTON, MODIFIERKEYS_FLAGS}, UI::Shell::{ BHID_DataObject, CLSID_DragDropHelper, Common, IDragSourceHelper, IShellItemArray, - SHCreateDataObject, SHCreateShellItemArrayFromIDLists, SHDoDragDrop, DROPFILES, - SHDRAGIMAGE, + SHCreateDataObject, SHCreateShellItemArrayFromIDLists, DROPFILES, SHDRAGIMAGE, }, }, }; @@ -189,6 +188,7 @@ pub fn start_drag( handle: &W, item: DragItem, image: Image, + on_drop_callback: Option>, ) -> crate::Result<()> { if let RawWindowHandle::Win32(_w) = handle.raw_window_handle() { match item { @@ -211,16 +211,26 @@ pub fn start_drag( } } - let _ = SHDoDragDrop( - HWND(_w.hwnd as isize), + let mut out_dropeffect = DROPEFFECT::default(); + let drop_result = DoDragDrop( &data_object, &drop_source, DROPEFFECT_COPY, + &mut out_dropeffect, ); - }; + + if let Some(callback) = on_drop_callback { + if drop_result == DRAGDROP_S_DROP { + callback(DropResult::Dropped); + } else if drop_result == DRAGDROP_S_CANCEL { + callback(DropResult::Cancel); + } else { + callback(DropResult::Cancel); + } + } + } } } - Ok(()) } else { Err(crate::Error::UnsupportedWindowHandle) diff --git a/crates/tauri-plugin/src/lib.rs b/crates/tauri-plugin/src/lib.rs index 3fb7d06..00a78eb 100644 --- a/crates/tauri-plugin/src/lib.rs +++ b/crates/tauri-plugin/src/lib.rs @@ -4,6 +4,7 @@ use std::sync::mpsc::channel; +use drag::DropResult; use serde::{ser::Serializer, Serialize}; use tauri::{ command, @@ -46,7 +47,15 @@ async fn start_drag( let raw_window = tauri::Result::Ok(window); let r = match raw_window { - Ok(w) => drag::start_drag(&w, item, image).map_err(Into::into), + Ok(w) => drag::start_drag( + &w, + item, + image, + Some(Box::new(|result: DropResult| { + println!("--> Drop Result: [{:?}]", result); + })), + ) + .map_err(Into::into), Err(e) => Err(e.into()), }; tx.send(r).unwrap(); diff --git a/examples/tao/src/main.rs b/examples/tao/src/main.rs index ad50f24..c3df1e0 100644 --- a/examples/tao/src/main.rs +++ b/examples/tao/src/main.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use drag::{start_drag, DragItem, Image}; +use drag::{start_drag, DragItem, DropResult, Image}; use tao::{ dpi::LogicalSize, event::{ElementState, Event, MouseButton, StartCause, WindowEvent}, @@ -52,6 +52,9 @@ fn main() { DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("../../icon.png".into()), + Some(Box::new(|result: DropResult| { + println!("--> Drop Result: [{:?}]", result); + })), ) .unwrap(); } diff --git a/examples/winit/src/main.rs b/examples/winit/src/main.rs index d39c40b..e387129 100644 --- a/examples/winit/src/main.rs +++ b/examples/winit/src/main.rs @@ -4,7 +4,7 @@ #![cfg(not(target_os = "linux"))] -use drag::{start_drag, DragItem, Image}; +use drag::{start_drag, DragItem, DropResult, Image}; use winit::{ dpi::LogicalSize, event::{DeviceEvent, ElementState, Event, StartCause, WindowEvent}, @@ -46,6 +46,9 @@ fn main() { ), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("../../icon.png".into()), + Some(Box::new(|result: DropResult| { + println!("--> Drop Result: [{:?}]", result); + })), ) .unwrap(); } diff --git a/examples/wry/src/main.rs b/examples/wry/src/main.rs index 0498d58..2ab67d3 100644 --- a/examples/wry/src/main.rs +++ b/examples/wry/src/main.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use drag::{start_drag, DragItem, Image}; +use drag::{start_drag, DragItem, DropResult, Image}; use wry::application::{ dpi::LogicalSize, event::{Event, StartCause, WindowEvent}, @@ -97,6 +97,9 @@ fn main() -> wry::Result<()> { ]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("../../icon.png".into()), + Some(Box::new(|result: DropResult| { + println!("--> Drop Result: [{:?}]", result); + })), ) .unwrap(); } From 5e2dd6e7187110b76e0cacd6454302c0369a33d7 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Thu, 7 Dec 2023 18:13:53 +0800 Subject: [PATCH 2/8] chore: clean up --- crates/drag/src/platform_impl/gtk/mod.rs | 1 - crates/tauri-plugin/src/lib.rs | 10 +--------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/drag/src/platform_impl/gtk/mod.rs b/crates/drag/src/platform_impl/gtk/mod.rs index 591f2d6..20e8455 100644 --- a/crates/drag/src/platform_impl/gtk/mod.rs +++ b/crates/drag/src/platform_impl/gtk/mod.rs @@ -89,7 +89,6 @@ fn image_binary_to_pixbuf(data: &[u8]) -> Option { fn clear_signal_handlers(window: >k::ApplicationWindow, handler_ids: &mut Vec) { for handler_id in handler_ids.drain(..) { - println!("disconnecting handler {:?}", handler_id); window.disconnect(handler_id); } } diff --git a/crates/tauri-plugin/src/lib.rs b/crates/tauri-plugin/src/lib.rs index 00a78eb..541e6c2 100644 --- a/crates/tauri-plugin/src/lib.rs +++ b/crates/tauri-plugin/src/lib.rs @@ -47,15 +47,7 @@ async fn start_drag( let raw_window = tauri::Result::Ok(window); let r = match raw_window { - Ok(w) => drag::start_drag( - &w, - item, - image, - Some(Box::new(|result: DropResult| { - println!("--> Drop Result: [{:?}]", result); - })), - ) - .map_err(Into::into), + Ok(w) => drag::start_drag(&w, item, image, None).map_err(Into::into), Err(e) => Err(e.into()), }; tx.send(r).unwrap(); From fc7b356097d04d99817d33c91ebb7c0fa286cf02 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 09:42:35 -0300 Subject: [PATCH 3/8] implement callback on tauri plugin --- crates/drag/src/lib.rs | 16 ++++++++--- crates/drag/src/platform_impl/gtk/mod.rs | 28 ++++++++------------ crates/drag/src/platform_impl/macos/mod.rs | 13 +++------ crates/drag/src/platform_impl/windows/mod.rs | 18 ++++++------- crates/tauri-plugin/src/api-iife.js | 2 +- crates/tauri-plugin/src/lib.rs | 13 +++++++-- examples/tao/src/main.rs | 4 +-- examples/tauri/index.html | 4 ++- examples/winit/src/main.rs | 22 ++++++++------- examples/wry/src/main.rs | 4 +-- packages/tauri-plugin-api/guest-js/index.ts | 12 ++++++--- 11 files changed, 77 insertions(+), 59 deletions(-) diff --git a/crates/drag/src/lib.rs b/crates/drag/src/lib.rs index 258c0fd..731ea55 100644 --- a/crates/drag/src/lib.rs +++ b/crates/drag/src/lib.rs @@ -35,6 +35,9 @@ //! &window, //! item, //! preview_icon, +//! |result| { +//! println!("drag result: {result:?}"); +//! } //! ); //! ``` //! @@ -57,6 +60,9 @@ //! &webview.window(), //! item, //! preview_icon, +//! |result| { +//! println!("drag result: {result:?}"); +//! } //! ); //! ``` //! @@ -69,7 +75,9 @@ //! let preview_icon = drag::Image::File("./examples/icon.png".into()); //! //! # #[cfg(not(target_os = "linux"))] -//! let _ = drag::start_drag(&window, item, preview_icon); +//! let _ = drag::start_drag(&window, item, preview_icon, |result| { +//! println!("drag result: {result:?}"); +//! }); //! ``` #[cfg(target_os = "macos")] @@ -104,14 +112,15 @@ pub enum Error { FailedToDrop, } -#[cfg_attr(feature = "serde", derive(Debug, serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(untagged))] +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum DropResult { Dropped, Cancel, } /// Item to be dragged. +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum DragItem { @@ -122,6 +131,7 @@ pub enum DragItem { } /// An image definition. +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum Image { diff --git a/crates/drag/src/platform_impl/gtk/mod.rs b/crates/drag/src/platform_impl/gtk/mod.rs index 20e8455..93ebdde 100644 --- a/crates/drag/src/platform_impl/gtk/mod.rs +++ b/crates/drag/src/platform_impl/gtk/mod.rs @@ -17,11 +17,11 @@ use gtk::{ prelude::{DragContextExtManual, PixbufLoaderExt, WidgetExt, WidgetExtManual}, }; -pub fn start_drag( +pub fn start_drag( window: >k::ApplicationWindow, item: DragItem, image: Image, - on_drop_callback: Option>, + on_drop_callback: F, ) -> crate::Result<()> { let handler_ids: Arc>> = Arc::new(Mutex::new(vec![])); @@ -53,9 +53,9 @@ pub fn start_drag( -1, -1, ) { - let callback = on_drop_callback.map(Rc::new); - on_drop_cancel(&callback, window, &handler_ids, &drag_context); - on_drop_performed(&callback, window, &handler_ids, &drag_context); + let callback = Rc::new(on_drop_callback); + on_drop_cancel(callback.clone(), window, &handler_ids, &drag_context); + on_drop_performed(callback, window, &handler_ids, &drag_context); let icon_pixbuf: Option = match &image { Image::Raw(data) => image_binary_to_pixbuf(data), @@ -93,13 +93,12 @@ fn clear_signal_handlers(window: >k::ApplicationWindow, handler_ids: &mut Vec< } } -fn on_drop_cancel( - callback: &Option>>, +fn on_drop_cancel( + callback: Rc, window: >k::ApplicationWindow, handler_ids: &Arc>>, drag_context: &gdk::DragContext, ) { - let callback = callback.as_ref().cloned(); let window = window.clone(); let handler_ids = handler_ids.clone(); @@ -108,19 +107,16 @@ fn on_drop_cancel( clear_signal_handlers(&window, handler_ids); window.drag_source_unset(); - if let Some(callback) = &callback { - callback(DropResult::Cancel); - } + callback(DropResult::Cancel); }); } -fn on_drop_performed( - callback: &Option>>, +fn on_drop_performed( + callback: Rc, window: >k::ApplicationWindow, handler_ids: &Arc>>, drag_context: &gdk::DragContext, ) { - let callback = callback.as_ref().cloned(); let window = window.clone(); let handler_ids = handler_ids.clone(); @@ -129,8 +125,6 @@ fn on_drop_performed( clear_signal_handlers(&window, handler_ids); window.drag_source_unset(); - if let Some(callback) = &callback { - callback(DropResult::Dropped); - } + callback(DropResult::Dropped); }); } diff --git a/crates/drag/src/platform_impl/macos/mod.rs b/crates/drag/src/platform_impl/macos/mod.rs index 89c4d3b..31dca16 100644 --- a/crates/drag/src/platform_impl/macos/mod.rs +++ b/crates/drag/src/platform_impl/macos/mod.rs @@ -31,11 +31,11 @@ unsafe fn new_nsstring(s: &str) -> id { ns_string } -pub fn start_drag( +pub fn start_drag( handle: &W, item: DragItem, image: Image, - on_drop_callback: Option>, + on_drop_callback: F, ) -> crate::Result<()> { if let RawWindowHandle::AppKit(w) = handle.raw_window_handle() { unsafe { @@ -142,9 +142,6 @@ pub fn start_drag( ) { unsafe { let callback = this.get_ivar::<*mut c_void>("on_drop_ptr"); - if callback.is_null() { - return; - } let callback = &*(*callback as *mut Box); if operation == 0 { @@ -164,10 +161,8 @@ pub fn start_drag( let source: id = msg_send![cls, alloc]; let source: id = msg_send![source, init]; - if let Some(callback) = on_drop_callback { - let callback_ptr = Box::into_raw(Box::new(callback)); - (*source).set_ivar("on_drop_ptr", callback_ptr as *mut _ as *mut c_void); - } + let callback_ptr = Box::into_raw(Box::new(on_drop_callback)); + (*source).set_ivar("on_drop_ptr", callback_ptr as *mut _ as *mut c_void); let _: () = msg_send![ns_view, beginDraggingSessionWithItems: file_items event: drag_event source: source]; } diff --git a/crates/drag/src/platform_impl/windows/mod.rs b/crates/drag/src/platform_impl/windows/mod.rs index 2f28cb0..0fa253b 100644 --- a/crates/drag/src/platform_impl/windows/mod.rs +++ b/crates/drag/src/platform_impl/windows/mod.rs @@ -183,11 +183,11 @@ impl IDataObject_Impl for DataObject { } } -pub fn start_drag( +pub fn start_drag( handle: &W, item: DragItem, image: Image, - on_drop_callback: Option>, + on_drop_callback: F, ) -> crate::Result<()> { if let RawWindowHandle::Win32(_w) = handle.raw_window_handle() { match item { @@ -224,14 +224,12 @@ pub fn start_drag( &mut out_dropeffect, ); - if let Some(callback) = on_drop_callback { - if drop_result == DRAGDROP_S_DROP { - callback(DropResult::Dropped); - } else if drop_result == DRAGDROP_S_CANCEL { - callback(DropResult::Cancel); - } else { - callback(DropResult::Cancel); - } + if drop_result == DRAGDROP_S_DROP { + on_drop_callback(DropResult::Dropped); + } else if drop_result == DRAGDROP_S_CANCEL { + on_drop_callback(DropResult::Cancel); + } else { + on_drop_callback(DropResult::Cancel); } } } diff --git a/crates/tauri-plugin/src/api-iife.js b/crates/tauri-plugin/src/api-iife.js index a90f2dd..6f2fd21 100644 --- a/crates/tauri-plugin/src/api-iife.js +++ b/crates/tauri-plugin/src/api-iife.js @@ -1 +1 @@ -if("__TAURI__"in window){var __TAURI_PLUGIN_DRAG__=function(e){"use strict";var r=Object.defineProperty;function t(e,r=!1){let t=window.crypto.getRandomValues(new Uint32Array(1))[0],n=`_${t}`;return Object.defineProperty(window,n,{value:t=>(r&&Reflect.deleteProperty(window,n),e?.(t)),writable:!1,configurable:!0}),t}async function n(e,r={}){return new Promise(((n,i)=>{let _=t((e=>{n(e),Reflect.deleteProperty(window,`_${o}`)}),!0),o=t((e=>{i(e),Reflect.deleteProperty(window,`_${_}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:_,error:o,...r})}))}function i(e,r="asset"){return window.__TAURI__.convertFileSrc(e,r)}return((e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})})({},{convertFileSrc:()=>i,invoke:()=>n,transformCallback:()=>t}),e.startDrag=async function(e){await n("plugin:drag|start_drag",{item:e.item,image:e.icon})},e}({});Object.defineProperty(window.__TAURI__,"drag",{value:__TAURI_PLUGIN_DRAG__})} +if("__TAURI__"in window){var __TAURI_PLUGIN_DRAG__=function(e){"use strict";var r=Object.defineProperty;function n(e,r=!1){let n=window.crypto.getRandomValues(new Uint32Array(1))[0],t=`_${n}`;return Object.defineProperty(window,t,{value:n=>(r&&Reflect.deleteProperty(window,t),e?.(n)),writable:!1,configurable:!0}),n}async function t(e,r={}){return new Promise(((t,i)=>{let _=n((e=>{t(e),Reflect.deleteProperty(window,`_${o}`)}),!0),o=n((e=>{i(e),Reflect.deleteProperty(window,`_${_}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:_,error:o,...r})}))}function i(e,r="asset"){return window.__TAURI__.convertFileSrc(e,r)}return((e,n)=>{for(var t in n)r(e,t,{get:n[t],enumerable:!0})})({},{convertFileSrc:()=>i,invoke:()=>t,transformCallback:()=>n}),e.startDrag=async function(e,r){await t("plugin:drag|start_drag",{item:e.item,image:e.icon,onEventFn:r?n(r):null})},e}({});Object.defineProperty(window.__TAURI__,"drag",{value:__TAURI_PLUGIN_DRAG__})} diff --git a/crates/tauri-plugin/src/lib.rs b/crates/tauri-plugin/src/lib.rs index 541e6c2..33e0ccb 100644 --- a/crates/tauri-plugin/src/lib.rs +++ b/crates/tauri-plugin/src/lib.rs @@ -4,9 +4,9 @@ use std::sync::mpsc::channel; -use drag::DropResult; use serde::{ser::Serializer, Serialize}; use tauri::{ + api::ipc::CallbackFn, command, plugin::{Builder, TauriPlugin}, AppHandle, Runtime, Window, @@ -37,6 +37,7 @@ async fn start_drag( window: Window, item: drag::DragItem, image: drag::Image, + on_event_fn: Option, ) -> Result<()> { let (tx, rx) = channel(); @@ -47,7 +48,15 @@ async fn start_drag( let raw_window = tauri::Result::Ok(window); let r = match raw_window { - Ok(w) => drag::start_drag(&w, item, image, None).map_err(Into::into), + Ok(w) => drag::start_drag(&w, item, image, move |result| { + if let Some(on_event_fn) = on_event_fn { + let js = tauri::api::ipc::format_callback(on_event_fn, &result) + .expect("unable to serialize DropResult"); + + let _ = window.eval(js.as_str()); + } + }) + .map_err(Into::into), Err(e) => Err(e.into()), }; tx.send(r).unwrap(); diff --git a/examples/tao/src/main.rs b/examples/tao/src/main.rs index 20c1182..5e6966b 100644 --- a/examples/tao/src/main.rs +++ b/examples/tao/src/main.rs @@ -52,9 +52,9 @@ fn main() { DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - Some(Box::new(|result: DropResult| { + |result: DropResult| { println!("--> Drop Result: [{:?}]", result); - })), + }, ) .unwrap(); } diff --git a/examples/tauri/index.html b/examples/tauri/index.html index bbf2553..90d4089 100644 --- a/examples/tauri/index.html +++ b/examples/tauri/index.html @@ -28,7 +28,9 @@ event.preventDefault(); const path = await window.__TAURI__.path.resolveResource('../icon.png') - window.__TAURI__.drag.startDrag({ item: [path], icon: path }); + window.__TAURI__.drag.startDrag({ item: [path], icon: path }, (result) => { + console.log(result); + }); }; diff --git a/examples/winit/src/main.rs b/examples/winit/src/main.rs index 05238f0..b36ffcb 100644 --- a/examples/winit/src/main.rs +++ b/examples/winit/src/main.rs @@ -2,17 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -#![cfg(not(target_os = "linux"))] - -use drag::{start_drag, DragItem, DropResult, Image}; -use winit::{ - dpi::LogicalSize, - event::{DeviceEvent, ElementState, Event, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - window::WindowBuilder, -}; +#[cfg(target_os = "linux")] +fn main() { + eprintln!("This example is not supported on Linux"); +} +#[cfg(not(target_os = "linux"))] fn main() { + use drag::{start_drag, DragItem, DropResult, Image}; + use winit::{ + dpi::LogicalSize, + event::{DeviceEvent, ElementState, Event, StartCause, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, + window::WindowBuilder, + }; + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_inner_size(LogicalSize::new(400., 100.)) diff --git a/examples/wry/src/main.rs b/examples/wry/src/main.rs index 5bac3ca..31f1df8 100644 --- a/examples/wry/src/main.rs +++ b/examples/wry/src/main.rs @@ -97,9 +97,9 @@ fn main() -> wry::Result<()> { ]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - Some(Box::new(|result: DropResult| { + |result: DropResult| { println!("--> Drop Result: [{:?}]", result); - })), + }, ) .unwrap(); } diff --git a/packages/tauri-plugin-api/guest-js/index.ts b/packages/tauri-plugin-api/guest-js/index.ts index 9783012..01d47df 100644 --- a/packages/tauri-plugin-api/guest-js/index.ts +++ b/packages/tauri-plugin-api/guest-js/index.ts @@ -1,12 +1,18 @@ -import { invoke } from '@tauri-apps/api/tauri' +import { invoke, transformCallback } from '@tauri-apps/api/tauri' export type DragItem = string[] +export type DragResult = 'Dropped' | 'Cancelled' + export interface Options { item: DragItem icon: string } -export async function startDrag(options: Options): Promise { - await invoke('plugin:drag|start_drag', { item: options.item, image: options.icon }) +export async function startDrag(options: Options, onEvent?: (result: DragResult) => void): Promise { + await invoke('plugin:drag|start_drag', { + item: options.item, + image: options.icon, + onEventFn: onEvent ? transformCallback(onEvent) : null + }) } From ee4f6ab89f47eb459e050175efc38e706a6c71cc Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 09:47:35 -0300 Subject: [PATCH 4/8] rename DropResult to DragResult --- crates/drag/src/lib.rs | 2 +- crates/drag/src/platform_impl/gtk/mod.rs | 12 ++++++------ crates/drag/src/platform_impl/macos/mod.rs | 10 +++++----- crates/drag/src/platform_impl/windows/mod.rs | 10 +++++----- crates/tauri-plugin/src/lib.rs | 2 +- examples/tao/src/main.rs | 4 ++-- examples/winit/src/main.rs | 4 ++-- examples/wry/src/main.rs | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/crates/drag/src/lib.rs b/crates/drag/src/lib.rs index 731ea55..5211e70 100644 --- a/crates/drag/src/lib.rs +++ b/crates/drag/src/lib.rs @@ -114,7 +114,7 @@ pub enum Error { #[derive(Debug)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub enum DropResult { +pub enum DragResult { Dropped, Cancel, } diff --git a/crates/drag/src/platform_impl/gtk/mod.rs b/crates/drag/src/platform_impl/gtk/mod.rs index 93ebdde..beaef96 100644 --- a/crates/drag/src/platform_impl/gtk/mod.rs +++ b/crates/drag/src/platform_impl/gtk/mod.rs @@ -7,7 +7,7 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::{DragItem, DropResult, Image}; +use crate::{DragItem, DragResult, Image}; use gdkx11::{ gdk, glib::{ObjectExt, SignalHandlerId}, @@ -17,7 +17,7 @@ use gtk::{ prelude::{DragContextExtManual, PixbufLoaderExt, WidgetExt, WidgetExtManual}, }; -pub fn start_drag( +pub fn start_drag( window: >k::ApplicationWindow, item: DragItem, image: Image, @@ -93,7 +93,7 @@ fn clear_signal_handlers(window: >k::ApplicationWindow, handler_ids: &mut Vec< } } -fn on_drop_cancel( +fn on_drop_cancel( callback: Rc, window: >k::ApplicationWindow, handler_ids: &Arc>>, @@ -107,11 +107,11 @@ fn on_drop_cancel( clear_signal_handlers(&window, handler_ids); window.drag_source_unset(); - callback(DropResult::Cancel); + callback(DragResult::Cancel); }); } -fn on_drop_performed( +fn on_drop_performed( callback: Rc, window: >k::ApplicationWindow, handler_ids: &Arc>>, @@ -125,6 +125,6 @@ fn on_drop_performed( clear_signal_handlers(&window, handler_ids); window.drag_source_unset(); - callback(DropResult::Dropped); + callback(DragResult::Dropped); }); } diff --git a/crates/drag/src/platform_impl/macos/mod.rs b/crates/drag/src/platform_impl/macos/mod.rs index 31dca16..579ec45 100644 --- a/crates/drag/src/platform_impl/macos/mod.rs +++ b/crates/drag/src/platform_impl/macos/mod.rs @@ -15,7 +15,7 @@ use objc::{ }; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use crate::{DragItem, DropResult, Image}; +use crate::{DragItem, DragResult, Image}; const UTF8_ENCODING: usize = 4; @@ -31,7 +31,7 @@ unsafe fn new_nsstring(s: &str) -> id { ns_string } -pub fn start_drag( +pub fn start_drag( handle: &W, item: DragItem, image: Image, @@ -143,12 +143,12 @@ pub fn start_drag( unsafe { let callback = this.get_ivar::<*mut c_void>("on_drop_ptr"); - let callback = &*(*callback as *mut Box); + let callback = &*(*callback as *mut Box); if operation == 0 { // NSDragOperationNone - callback(DropResult::Cancel); + callback(DragResult::Cancel); } else { - callback(DropResult::Dropped); + callback(DragResult::Dropped); } } } diff --git a/crates/drag/src/platform_impl/windows/mod.rs b/crates/drag/src/platform_impl/windows/mod.rs index 0fa253b..cfd434e 100644 --- a/crates/drag/src/platform_impl/windows/mod.rs +++ b/crates/drag/src/platform_impl/windows/mod.rs @@ -4,7 +4,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use crate::{DragItem, DropResult, Image}; +use crate::{DragItem, DragResult, Image}; use std::{ ffi::c_void, @@ -183,7 +183,7 @@ impl IDataObject_Impl for DataObject { } } -pub fn start_drag( +pub fn start_drag( handle: &W, item: DragItem, image: Image, @@ -225,11 +225,11 @@ pub fn start_drag( ); if drop_result == DRAGDROP_S_DROP { - on_drop_callback(DropResult::Dropped); + on_drop_callback(DragResult::Dropped); } else if drop_result == DRAGDROP_S_CANCEL { - on_drop_callback(DropResult::Cancel); + on_drop_callback(DragResult::Cancel); } else { - on_drop_callback(DropResult::Cancel); + on_drop_callback(DragResult::Cancel); } } } diff --git a/crates/tauri-plugin/src/lib.rs b/crates/tauri-plugin/src/lib.rs index 33e0ccb..1f1bf1e 100644 --- a/crates/tauri-plugin/src/lib.rs +++ b/crates/tauri-plugin/src/lib.rs @@ -51,7 +51,7 @@ async fn start_drag( Ok(w) => drag::start_drag(&w, item, image, move |result| { if let Some(on_event_fn) = on_event_fn { let js = tauri::api::ipc::format_callback(on_event_fn, &result) - .expect("unable to serialize DropResult"); + .expect("unable to serialize DragResult"); let _ = window.eval(js.as_str()); } diff --git a/examples/tao/src/main.rs b/examples/tao/src/main.rs index 5e6966b..0f26676 100644 --- a/examples/tao/src/main.rs +++ b/examples/tao/src/main.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use drag::{start_drag, DragItem, DropResult, Image}; +use drag::{start_drag, DragItem, DragResult, Image}; use tao::{ dpi::LogicalSize, event::{ElementState, Event, MouseButton, StartCause, WindowEvent}, @@ -52,7 +52,7 @@ fn main() { DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - |result: DropResult| { + |result: DragResult| { println!("--> Drop Result: [{:?}]", result); }, ) diff --git a/examples/winit/src/main.rs b/examples/winit/src/main.rs index b36ffcb..b3d24a5 100644 --- a/examples/winit/src/main.rs +++ b/examples/winit/src/main.rs @@ -9,7 +9,7 @@ fn main() { #[cfg(not(target_os = "linux"))] fn main() { - use drag::{start_drag, DragItem, DropResult, Image}; + use drag::{start_drag, DragItem, DragResult, Image}; use winit::{ dpi::LogicalSize, event::{DeviceEvent, ElementState, Event, StartCause, WindowEvent}, @@ -50,7 +50,7 @@ fn main() { ), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - Some(Box::new(|result: DropResult| { + Some(Box::new(|result: DragResult| { println!("--> Drop Result: [{:?}]", result); })), ) diff --git a/examples/wry/src/main.rs b/examples/wry/src/main.rs index 31f1df8..28cf814 100644 --- a/examples/wry/src/main.rs +++ b/examples/wry/src/main.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use drag::{start_drag, DragItem, DropResult, Image}; +use drag::{start_drag, DragItem, DragResult, Image}; use wry::application::{ dpi::LogicalSize, event::{Event, StartCause, WindowEvent}, @@ -97,7 +97,7 @@ fn main() -> wry::Result<()> { ]), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - |result: DropResult| { + |result: DragResult| { println!("--> Drop Result: [{:?}]", result); }, ) From 14490764de8ff50969a3f2299d204e44e091752e Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 09:47:49 -0300 Subject: [PATCH 5/8] add change files --- .changes/api-result-callback.md | 5 +++++ .changes/result-callback.md | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 .changes/api-result-callback.md create mode 100644 .changes/result-callback.md diff --git a/.changes/api-result-callback.md b/.changes/api-result-callback.md new file mode 100644 index 0000000..29a6148 --- /dev/null +++ b/.changes/api-result-callback.md @@ -0,0 +1,5 @@ +--- +"@crabnebula/tauri-plugin-drag": minor +--- + +The `startDrag` function now takes an argument for a callback function for the operation result (either `Dragged` or `Cancelled`). diff --git a/.changes/result-callback.md b/.changes/result-callback.md new file mode 100644 index 0000000..c4b0730 --- /dev/null +++ b/.changes/result-callback.md @@ -0,0 +1,6 @@ +--- +"drag": minor +"tauri-plugin-drag": minor +--- + +The `start_drag` function now takes a closure for the operation result (either `DragResult::Dropped` or `DragResult::Cancelled`). From d59e3108e81648f3c685aaafea96dc5be4dab097 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 10:33:38 -0300 Subject: [PATCH 6/8] fix build --- crates/tauri-plugin/src/lib.rs | 2 +- examples/winit/src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/tauri-plugin/src/lib.rs b/crates/tauri-plugin/src/lib.rs index 1f1bf1e..0217675 100644 --- a/crates/tauri-plugin/src/lib.rs +++ b/crates/tauri-plugin/src/lib.rs @@ -45,7 +45,7 @@ async fn start_drag( #[cfg(target_os = "linux")] let raw_window = window.gtk_window(); #[cfg(not(target_os = "linux"))] - let raw_window = tauri::Result::Ok(window); + let raw_window = tauri::Result::Ok(window.clone()); let r = match raw_window { Ok(w) => drag::start_drag(&w, item, image, move |result| { diff --git a/examples/winit/src/main.rs b/examples/winit/src/main.rs index b3d24a5..20ad79c 100644 --- a/examples/winit/src/main.rs +++ b/examples/winit/src/main.rs @@ -50,9 +50,9 @@ fn main() { ), Image::Raw(include_bytes!("../../icon.png").to_vec()), // Image::File("./examples/icon.png".into()), - Some(Box::new(|result: DragResult| { + |result: DragResult| { println!("--> Drop Result: [{:?}]", result); - })), + }, ) .unwrap(); } From 0731bfb45c59aee961d40cad81ac54f444ccc769 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 10:39:53 -0300 Subject: [PATCH 7/8] add ci --- .github/workflows/audit.yml | 33 +++++++++++++++ .github/workflows/check.yml | 81 +++++++++++++++++++++++++++++++++++++ deny.toml | 34 ++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 .github/workflows/audit.yml create mode 100644 .github/workflows/check.yml create mode 100644 deny.toml diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..3279753 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,33 @@ +name: Audit Rust + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + push: + branches: + - main + paths: + - ".github/workflows/audit.yml" + - "**/Cargo.lock" + - "**/Cargo.toml" + pull_request: + branches: + - main + paths: + - ".github/workflows/audit.yml" + - "**/Cargo.lock" + - "**/Cargo.toml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: rustsec/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..e555483 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,81 @@ +name: Check + +on: + push: + branches: + - main + paths: + - ".github/workflows/check.yml" + - "**/*.rs" + - "**/Cargo.toml" + pull_request: + branches: + - main + paths: + - ".github/workflows/check.yml" + - "**/*.rs" + - "**/Cargo.toml" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + rustfmt: + if: ${{ !startsWith(github.head_ref, 'renovate/') }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo fmt --all -- --check + + clippy: + if: ${{ !startsWith(github.head_ref, 'renovate/') }} + + strategy: + fail-fast: false + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - name: install webkit2gtk + if: matrix.platform == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y webkit2gtk-4.0 + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --workspace --all-targets --all-features -- -D warnings + + rust-test: + strategy: + fail-fast: false + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4 + - name: install webkit2gtk + if: matrix.platform == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y webkit2gtk-4.0 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - run: cargo test --workspace --lib --bins --tests --benches --all-features --no-fail-fast + + deny: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..db55af5 --- /dev/null +++ b/deny.toml @@ -0,0 +1,34 @@ +# Target triples to include when checking. This is essentially our supported target list. +targets = [ + { triple = "x86_64-unknown-linux-gnu" }, + { triple = "aarch64-unknown-linux-gnu" }, + { triple = "x86_64-pc-windows-msvc" }, + { triple = "i686-pc-windows-msvc" }, + { triple = "x86_64-apple-darwin" }, + { triple = "aarch64-apple-darwin" }, +] + +[licenses] +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "ISC", + # Apparently for us it's equivalent to BSD-3 which is considered compatible with MIT and Apache-2.0 + "Unicode-DFS-2016", + # Used by webpki-roots and option-ext which we are using without modifications in a larger work, therefore okay. + "MPL-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "Zlib", +] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = true From 5f99d870eaa8f1c899a8adf49c200a8c69be484f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 11 Dec 2023 10:50:55 -0300 Subject: [PATCH 8/8] windows clippy --- crates/drag/src/platform_impl/windows/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/drag/src/platform_impl/windows/mod.rs b/crates/drag/src/platform_impl/windows/mod.rs index cfd434e..bc0d610 100644 --- a/crates/drag/src/platform_impl/windows/mod.rs +++ b/crates/drag/src/platform_impl/windows/mod.rs @@ -226,9 +226,8 @@ pub fn start_drag( if drop_result == DRAGDROP_S_DROP { on_drop_callback(DragResult::Dropped); - } else if drop_result == DRAGDROP_S_CANCEL { - on_drop_callback(DragResult::Cancel); } else { + // DRAGDROP_S_CANCEL on_drop_callback(DragResult::Cancel); } }