1
0
Fork 0

Move DropTarget to its own module

This commit is contained in:
Jussi Viiri 2023-06-10 23:20:46 +03:00
parent b33398703f
commit cfa06f5b59
3 changed files with 292 additions and 265 deletions

266
src/win/drop_target.rs Normal file
View file

@ -0,0 +1,266 @@
use std::ffi::OsString;
use std::mem::transmute;
use std::os::windows::prelude::OsStringExt;
use std::ptr::null_mut;
use std::rc::{Weak, Rc};
use winapi::Interface;
use winapi::shared::guiddef::{REFIID, IsEqualIID};
use winapi::shared::minwindef::{DWORD, WPARAM};
use winapi::shared::ntdef::{HRESULT, ULONG};
use winapi::shared::windef::POINTL;
use winapi::shared::winerror::{S_OK, E_NOINTERFACE, E_UNEXPECTED};
use winapi::shared::wtypes::DVASPECT_CONTENT;
use winapi::um::objidl::{IDataObject, FORMATETC, TYMED_HGLOBAL, STGMEDIUM};
use winapi::um::oleidl::{IDropTarget, IDropTargetVtbl, DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK, DROPEFFECT_SCROLL, DROPEFFECT_NONE};
use winapi::um::shellapi::DragQueryFileW;
use winapi::um::unknwnbase::{IUnknownVtbl, IUnknown};
use winapi::um::winuser::CF_HDROP;
use crate::{Point, DropData, MouseEvent, Event, EventStatus, DropEffect, PhyPoint};
use super::WindowState;
// These function pointers have to be stored in a (const) variable before they can be transmuted
const DRAG_ENTER_PTR: unsafe extern "system" fn(this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drag_enter;
const DRAG_OVER_PTR: unsafe extern "system" fn(this: *mut IDropTarget, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drag_over;
const DROP_PTR: unsafe extern "system" fn(this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drop;
const DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl {
parent: IUnknownVtbl {
QueryInterface: DropTarget::query_interface,
AddRef: DropTarget::add_ref,
Release: DropTarget::release,
},
DragEnter: unsafe { transmute(DRAG_ENTER_PTR) },
DragOver: unsafe { transmute(DRAG_OVER_PTR) },
DragLeave: DropTarget::drag_leave,
Drop: unsafe { transmute(DROP_PTR) },
};
#[repr(C)]
pub(super) struct DropTarget {
base: IDropTarget,
window_state: Weak<WindowState>,
// These are cached since DragOver and DragLeave callbacks don't provide them,
// and handling drag move events gets awkward on the client end otherwise
drag_position: Point,
drop_data: DropData,
}
impl DropTarget {
pub(super) fn new(window_state: Weak<WindowState>) -> Self {
Self {
base: IDropTarget { lpVtbl: &DROP_TARGET_VTBL },
window_state,
drag_position: Point::new(0.0, 0.0),
drop_data: DropData::None,
}
}
fn on_event(&self, pdwEffect: Option<*mut DWORD>, event: MouseEvent) {
let Some(window_state) = self.window_state.upgrade() else {
return;
};
unsafe {
let mut window = window_state.create_window();
let mut window = crate::Window::new(&mut window);
let event = Event::Mouse(event);
let event_status = window_state.handler_mut().as_mut().unwrap().on_event(&mut window, event);
if let Some(pdwEffect) = pdwEffect {
match event_status {
EventStatus::AcceptDrop(DropEffect::Copy) => *pdwEffect = DROPEFFECT_COPY,
EventStatus::AcceptDrop(DropEffect::Move) => *pdwEffect = DROPEFFECT_MOVE,
EventStatus::AcceptDrop(DropEffect::Link) => *pdwEffect = DROPEFFECT_LINK,
EventStatus::AcceptDrop(DropEffect::Scroll) => *pdwEffect = DROPEFFECT_SCROLL,
_ => *pdwEffect = DROPEFFECT_NONE,
}
}
}
}
fn parse_coordinates(&mut self, pt: POINTL) {
let Some(window_state) = self.window_state.upgrade() else {
return;
};
let phy_point = PhyPoint::new(pt.x, pt.y);
self.drag_position = phy_point.to_logical(&window_state.window_info());
}
fn parse_drop_data(&mut self, data_object: &IDataObject) {
let format = FORMATETC {
cfFormat: CF_HDROP as u16,
ptd: null_mut(),
dwAspect: DVASPECT_CONTENT,
lindex: -1,
tymed: TYMED_HGLOBAL,
};
let mut medium = STGMEDIUM {
tymed: 0,
u: null_mut(),
pUnkForRelease: null_mut(),
};
unsafe {
let hresult = data_object.GetData(&format, &mut medium);
if hresult != S_OK {
self.drop_data = DropData::None;
return;
}
let hdrop = transmute((*medium.u).hGlobal());
let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, null_mut(), 0);
if item_count == 0 {
self.drop_data = DropData::None;
return;
}
let mut paths = Vec::with_capacity(item_count as usize);
for i in 0..item_count {
let characters = DragQueryFileW(hdrop, i, null_mut(), 0);
let buffer_size = characters as usize + 1;
let mut buffer = Vec::<u16>::with_capacity(buffer_size);
DragQueryFileW(hdrop, i, transmute(buffer.spare_capacity_mut().as_mut_ptr()), buffer_size as u32);
buffer.set_len(buffer_size);
paths.push(OsString::from_wide(&buffer[..characters as usize]).into())
}
self.drop_data = DropData::Files(paths);
}
}
unsafe extern "system" fn query_interface(
this: *mut IUnknown,
riid: REFIID,
ppvObject: *mut *mut winapi::ctypes::c_void,
) -> HRESULT
{
if IsEqualIID(&*riid, &IUnknown::uuidof()) || IsEqualIID(&*riid, &IDropTarget::uuidof()){
Self::add_ref(this);
*ppvObject = this as *mut winapi::ctypes::c_void;
return S_OK;
}
return E_NOINTERFACE;
}
unsafe extern "system" fn add_ref(this: *mut IUnknown) -> ULONG {
let arc = Rc::from_raw(this);
let result = Rc::strong_count(&arc) + 1;
let _ = Rc::into_raw(arc);
Rc::increment_strong_count(this);
result as ULONG
}
unsafe extern "system" fn release(this: *mut IUnknown) -> ULONG {
let arc = Rc::from_raw(this);
let result = Rc::strong_count(&arc) - 1;
let _ = Rc::into_raw(arc);
Rc::decrement_strong_count(this);
result as ULONG
}
unsafe extern "system" fn drag_enter(
this: *mut IDropTarget,
pDataObj: *const IDataObject,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
drop_target.parse_drop_data(&*pDataObj);
let event = MouseEvent::DragEntered {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
unsafe extern "system" fn drag_over(
this: *mut IDropTarget,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
let event = MouseEvent::DragMoved {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
unsafe extern "system" fn drag_leave(this: *mut IDropTarget) -> HRESULT {
let drop_target = &mut *(this as *mut DropTarget);
drop_target.on_event(None, MouseEvent::DragLeft);
S_OK
}
unsafe extern "system" fn drop(
this: *mut IDropTarget,
pDataObj: *const IDataObject,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
drop_target.parse_drop_data(&*pDataObj);
let event = MouseEvent::DragDropped {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
}

View file

@ -1,3 +1,4 @@
mod drop_target;
mod keyboard; mod keyboard;
mod window; mod window;

View file

@ -1,16 +1,9 @@
use winapi::Interface; use winapi::shared::guiddef::GUID;
use winapi::shared::guiddef::{GUID, REFIID, IsEqualIID}; use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM, DWORD}; use winapi::shared::windef::{HWND, RECT};
use winapi::shared::ntdef::{HRESULT, ULONG};
use winapi::shared::windef::{HWND, RECT, POINTL};
use winapi::shared::winerror::{S_OK, E_NOINTERFACE, E_UNEXPECTED};
use winapi::shared::wtypes::DVASPECT_CONTENT;
use winapi::um::combaseapi::CoCreateGuid; use winapi::um::combaseapi::CoCreateGuid;
use winapi::um::objidl::{IDataObject, STGMEDIUM, FORMATETC, TYMED_HGLOBAL};
use winapi::um::ole2::{RegisterDragDrop, OleInitialize, RevokeDragDrop}; use winapi::um::ole2::{RegisterDragDrop, OleInitialize, RevokeDragDrop};
use winapi::um::oleidl::{IDropTarget, IDropTargetVtbl, LPDROPTARGET, DROPEFFECT_COPY, DROPEFFECT_NONE, DROPEFFECT_MOVE, DROPEFFECT_LINK, DROPEFFECT_SCROLL}; use winapi::um::oleidl::LPDROPTARGET;
use winapi::um::shellapi::DragQueryFileW;
use winapi::um::unknwnbase::{IUnknownVtbl, IUnknown};
use winapi::um::winuser::{ use winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW,
@ -22,18 +15,16 @@ use winapi::um::winuser::{
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD,
WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
XBUTTON1, XBUTTON2, CF_HDROP, XBUTTON1, XBUTTON2,
}; };
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell, Ref, RefMut};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ffi::{c_void, OsStr, OsString}; use std::ffi::{c_void, OsStr};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute;
use std::os::windows::ffi::OsStrExt; use std::os::windows::ffi::OsStrExt;
use std::os::windows::prelude::OsStringExt;
use std::ptr::null_mut; use std::ptr::null_mut;
use std::rc::{Rc, Weak}; use std::rc::Rc;
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, Win32Handle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, Win32Handle};
@ -41,9 +32,10 @@ const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1;
use crate::{ use crate::{
Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, WindowEvent, Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, Size, WindowEvent,
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, DropEffect, EventStatus, DropData, Point, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy,
}; };
use super::drop_target::DropTarget;
use super::keyboard::KeyboardState; use super::keyboard::KeyboardState;
#[cfg(feature = "opengl")] #[cfg(feature = "opengl")]
@ -458,7 +450,7 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) {
/// because of the Windows message loops' reentrant nature. Care still needs to be taken to prevent /// because of the Windows message loops' reentrant nature. Care still needs to be taken to prevent
/// `handler` from indirectly triggering other events that would also need to be handled using /// `handler` from indirectly triggering other events that would also need to be handled using
/// `handler`. /// `handler`.
struct WindowState { pub(super) struct WindowState {
/// The HWND belonging to this window. The window's actual state is stored in the `WindowState` /// The HWND belonging to this window. The window's actual state is stored in the `WindowState`
/// struct associated with this HWND through `unsafe { GetWindowLongPtrW(self.hwnd, /// struct associated with this HWND through `unsafe { GetWindowLongPtrW(self.hwnd,
/// GWLP_USERDATA) } as *const WindowState`. /// GWLP_USERDATA) } as *const WindowState`.
@ -486,10 +478,22 @@ struct WindowState {
} }
impl WindowState { impl WindowState {
fn create_window(&self) -> Window { pub(super) fn create_window(&self) -> Window {
Window { state: self } Window { state: self }
} }
pub(super) fn window_info(&self) -> Ref<WindowInfo> {
self.window_info.borrow()
}
pub(super) fn keyboard_state(&self) -> Ref<KeyboardState> {
self.keyboard_state.borrow()
}
pub(super) fn handler_mut(&self) -> RefMut<Option<Box<dyn WindowHandler>>> {
self.handler.borrow_mut()
}
/// Handle a deferred task as described in [`Self::deferred_tasks /// Handle a deferred task as described in [`Self::deferred_tasks
pub(self) fn handle_deferred_task(&self, task: WindowTask) { pub(self) fn handle_deferred_task(&self, task: WindowTask) {
match task { match task {
@ -530,7 +534,7 @@ impl WindowState {
/// Tasks that must be deferred until the end of [`wnd_proc()`] to avoid reentrant `WindowState` /// Tasks that must be deferred until the end of [`wnd_proc()`] to avoid reentrant `WindowState`
/// borrows. See the docstring on [`WindowState::deferred_tasks`] for more information. /// borrows. See the docstring on [`WindowState::deferred_tasks`] for more information.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum WindowTask { pub(super) enum WindowTask {
/// Resize the window to the given size. The size is in logical pixels. DPI scaling is applied /// Resize the window to the given size. The size is in logical pixels. DPI scaling is applied
/// automatically. /// automatically.
Resize(Size), Resize(Size),
@ -787,247 +791,3 @@ unsafe impl HasRawWindowHandle for Window<'_> {
pub fn copy_to_clipboard(data: &str) { pub fn copy_to_clipboard(data: &str) {
todo!() todo!()
} }
// These function pointers have to be stored in a (const) variable before they can be transmuted
const DRAG_ENTER_PTR: unsafe extern "system" fn(this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drag_enter;
const DRAG_OVER_PTR: unsafe extern "system" fn(this: *mut IDropTarget, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drag_over;
const DROP_PTR: unsafe extern "system" fn(this: *mut IDropTarget, pDataObj: *const IDataObject, grfKeyState: DWORD, pt: POINTL, pdwEffect: *mut DWORD) -> HRESULT = DropTarget::drop;
const DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl {
parent: IUnknownVtbl {
QueryInterface: DropTarget::query_interface,
AddRef: DropTarget::add_ref,
Release: DropTarget::release,
},
DragEnter: unsafe { transmute(DRAG_ENTER_PTR) },
DragOver: unsafe { transmute(DRAG_OVER_PTR) },
DragLeave: DropTarget::drag_leave,
Drop: unsafe { transmute(DROP_PTR) },
};
#[repr(C)]
pub struct DropTarget {
base: IDropTarget,
window_state: Weak<WindowState>,
// These are cached since DragOver and DragLeave callbacks don't provide them,
// and handling drag move events gets awkward on the client end otherwise
drag_position: Point,
drop_data: DropData,
}
impl DropTarget {
fn new(window_state: Weak<WindowState>) -> Self {
Self {
base: IDropTarget { lpVtbl: &DROP_TARGET_VTBL },
window_state,
drag_position: Point::new(0.0, 0.0),
drop_data: DropData::None,
}
}
fn on_event(&self, pdwEffect: Option<*mut DWORD>, event: MouseEvent) {
let Some(window_state) = self.window_state.upgrade() else {
return;
};
unsafe {
let mut window = window_state.create_window();
let mut window = crate::Window::new(&mut window);
let event = Event::Mouse(event);
let event_status = window_state.handler.borrow_mut().as_mut().unwrap().on_event(&mut window, event);
if let Some(pdwEffect) = pdwEffect {
match event_status {
EventStatus::AcceptDrop(DropEffect::Copy) => *pdwEffect = DROPEFFECT_COPY,
EventStatus::AcceptDrop(DropEffect::Move) => *pdwEffect = DROPEFFECT_MOVE,
EventStatus::AcceptDrop(DropEffect::Link) => *pdwEffect = DROPEFFECT_LINK,
EventStatus::AcceptDrop(DropEffect::Scroll) => *pdwEffect = DROPEFFECT_SCROLL,
_ => *pdwEffect = DROPEFFECT_NONE,
}
}
}
}
fn parse_coordinates(&mut self, pt: POINTL) {
let Some(window_state) = self.window_state.upgrade() else {
return;
};
let phy_point = PhyPoint::new(pt.x, pt.y);
self.drag_position = phy_point.to_logical(&window_state.window_info.borrow());
}
fn parse_drop_data(&mut self, data_object: &IDataObject) {
let format = FORMATETC {
cfFormat: CF_HDROP as u16,
ptd: null_mut(),
dwAspect: DVASPECT_CONTENT,
lindex: -1,
tymed: TYMED_HGLOBAL,
};
let mut medium = STGMEDIUM {
tymed: 0,
u: null_mut(),
pUnkForRelease: null_mut(),
};
unsafe {
let hresult = data_object.GetData(&format, &mut medium);
if hresult != S_OK {
self.drop_data = DropData::None;
return;
}
let hdrop = transmute((*medium.u).hGlobal());
let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, null_mut(), 0);
if item_count == 0 {
self.drop_data = DropData::None;
return;
}
let mut paths = Vec::with_capacity(item_count as usize);
for i in 0..item_count {
let characters = DragQueryFileW(hdrop, i, null_mut(), 0);
let buffer_size = characters as usize + 1;
let mut buffer = Vec::<u16>::with_capacity(buffer_size);
DragQueryFileW(hdrop, i, transmute(buffer.spare_capacity_mut().as_mut_ptr()), buffer_size as u32);
buffer.set_len(buffer_size);
paths.push(OsString::from_wide(&buffer[..characters as usize]).into())
}
self.drop_data = DropData::Files(paths);
}
}
unsafe extern "system" fn query_interface(
this: *mut IUnknown,
riid: REFIID,
ppvObject: *mut *mut winapi::ctypes::c_void,
) -> HRESULT
{
if IsEqualIID(&*riid, &IUnknown::uuidof()) || IsEqualIID(&*riid, &IDropTarget::uuidof()){
Self::add_ref(this);
*ppvObject = this as *mut winapi::ctypes::c_void;
return S_OK;
}
return E_NOINTERFACE;
}
unsafe extern "system" fn add_ref(this: *mut IUnknown) -> ULONG {
let arc = Rc::from_raw(this);
let result = Rc::strong_count(&arc) + 1;
let _ = Rc::into_raw(arc);
Rc::increment_strong_count(this);
result as ULONG
}
unsafe extern "system" fn release(this: *mut IUnknown) -> ULONG {
let arc = Rc::from_raw(this);
let result = Rc::strong_count(&arc) - 1;
let _ = Rc::into_raw(arc);
Rc::decrement_strong_count(this);
result as ULONG
}
unsafe extern "system" fn drag_enter(
this: *mut IDropTarget,
pDataObj: *const IDataObject,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state.borrow().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
drop_target.parse_drop_data(&*pDataObj);
let event = MouseEvent::DragEntered {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
unsafe extern "system" fn drag_over(
this: *mut IDropTarget,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state.borrow().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
let event = MouseEvent::DragMoved {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
unsafe extern "system" fn drag_leave(this: *mut IDropTarget) -> HRESULT {
let drop_target = &mut *(this as *mut DropTarget);
drop_target.on_event(None, MouseEvent::DragLeft);
S_OK
}
unsafe extern "system" fn drop(
this: *mut IDropTarget,
pDataObj: *const IDataObject,
grfKeyState: DWORD,
pt: POINTL,
pdwEffect: *mut DWORD,
) -> HRESULT
{
let drop_target = &mut *(this as *mut DropTarget);
let Some(window_state) = drop_target.window_state.upgrade() else {
return E_UNEXPECTED;
};
let modifiers = window_state.keyboard_state.borrow().get_modifiers_from_mouse_wparam(grfKeyState as WPARAM);
drop_target.parse_coordinates(pt);
drop_target.parse_drop_data(&*pDataObj);
let event = MouseEvent::DragDropped {
position: drop_target.drag_position,
modifiers,
data: drop_target.drop_data.clone(),
};
drop_target.on_event(Some(pdwEffect), event);
S_OK
}
}