1
0
Fork 0

Parse drop data

Only handling files for now
This commit is contained in:
Jussi Viiri 2023-06-04 23:43:10 +03:00
parent ef64cae538
commit b5f3939930
3 changed files with 82 additions and 12 deletions

View file

@ -29,7 +29,7 @@ xcb-util = { version = "0.3", features = ["icccm"] }
nix = "0.22.0" nix = "0.22.0"
[target.'cfg(target_os="windows")'.dependencies] [target.'cfg(target_os="windows")'.dependencies]
winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi", "ole2", "oleidl", "winerror"] } winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi", "ole2", "oleidl", "shellapi", "winerror"] }
uuid = { version = "0.8", features = ["v4"], optional = true } uuid = { version = "0.8", features = ["v4"], optional = true }
[target.'cfg(target_os="macos")'.dependencies] [target.'cfg(target_os="macos")'.dependencies]

View file

@ -1,3 +1,5 @@
use std::path::PathBuf;
use keyboard_types::{KeyboardEvent, Modifiers}; use keyboard_types::{KeyboardEvent, Modifiers};
use crate::{Point, WindowInfo}; use crate::{Point, WindowInfo};
@ -32,7 +34,7 @@ pub enum ScrollDelta {
}, },
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum MouseEvent { pub enum MouseEvent {
/// The mouse cursor was moved /// The mouse cursor was moved
CursorMoved { CursorMoved {
@ -77,10 +79,16 @@ pub enum MouseEvent {
CursorLeft, CursorLeft,
// TODO: Document // TODO: Document
DragEntered, DragEntered {
data: Option<DropData>,
},
DragMoved, DragMoved,
DragLeft, DragLeft,
DragDropped,
DragDropped {
data: Option<DropData>,
},
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -106,6 +114,11 @@ pub enum DropEffect {
Scroll, Scroll,
} }
#[derive(Debug, Clone, PartialEq)]
pub enum DropData {
Files(Vec<PathBuf>),
}
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`), /// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
/// indicating whether the event was handled by your window or should be passed /// indicating whether the event was handled by your window or should be passed
/// back to the platform. /// back to the platform.

View file

@ -4,10 +4,12 @@ use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM, DWOR
use winapi::shared::ntdef::{HRESULT, ULONG}; use winapi::shared::ntdef::{HRESULT, ULONG};
use winapi::shared::windef::{HWND, RECT, POINTL}; use winapi::shared::windef::{HWND, RECT, POINTL};
use winapi::shared::winerror::{S_OK, E_NOINTERFACE}; use winapi::shared::winerror::{S_OK, E_NOINTERFACE};
use winapi::shared::wtypes::DVASPECT_CONTENT;
use winapi::um::combaseapi::CoCreateGuid; use winapi::um::combaseapi::CoCreateGuid;
use winapi::um::objidl::IDataObject; use winapi::um::objidl::{IDataObject, STGMEDIUM, FORMATETC, TYMED_HGLOBAL};
use winapi::um::ole2::{RegisterDragDrop, OleInitialize}; use winapi::um::ole2::{RegisterDragDrop, OleInitialize};
use winapi::um::oleidl::{IDropTarget, IDropTargetVtbl, LPDROPTARGET, DROPEFFECT_COPY, DROPEFFECT_NONE, DROPEFFECT_MOVE, DROPEFFECT_LINK, DROPEFFECT_SCROLL}; use winapi::um::oleidl::{IDropTarget, IDropTargetVtbl, LPDROPTARGET, DROPEFFECT_COPY, DROPEFFECT_NONE, DROPEFFECT_MOVE, DROPEFFECT_LINK, DROPEFFECT_SCROLL};
use winapi::um::shellapi::DragQueryFileW;
use winapi::um::unknwnbase::{IUnknownVtbl, IUnknown}; use winapi::um::unknwnbase::{IUnknownVtbl, IUnknown};
use winapi::um::winuser::{ use winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
@ -20,15 +22,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, XBUTTON1, XBUTTON2, CF_HDROP,
}; };
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ffi::{c_void, OsStr}; use std::ffi::{c_void, OsStr, OsString};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute; 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; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -39,7 +42,7 @@ 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, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, DropEffect, EventStatus, DropData,
}; };
use super::keyboard::KeyboardState; use super::keyboard::KeyboardState;
@ -843,6 +846,49 @@ impl DropTarget {
} }
} }
fn parse_drop_data(data_object: &IDataObject) -> Option<DropData> {
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);
assert!(hresult == S_OK); // TODO: Error handling
let hdrop = transmute((*medium.u).hGlobal());
let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, null_mut(), 0);
if item_count == 0 {
return None;
}
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())
}
Some(DropData::Files(paths))
}
}
unsafe extern "system" fn query_interface( unsafe extern "system" fn query_interface(
this: *mut IUnknown, this: *mut IUnknown,
riid: REFIID, riid: REFIID,
@ -888,7 +934,12 @@ impl DropTarget {
pdwEffect: *mut DWORD, pdwEffect: *mut DWORD,
) -> HRESULT ) -> HRESULT
{ {
Self::on_event(this, Some(pdwEffect), MouseEvent::DragEntered {}); let data = Self::parse_drop_data(&*pDataObj);
let event = MouseEvent::DragEntered {
data
};
Self::on_event(this, Some(pdwEffect), event);
S_OK S_OK
} }
@ -899,12 +950,13 @@ impl DropTarget {
pdwEffect: *mut DWORD, pdwEffect: *mut DWORD,
) -> HRESULT ) -> HRESULT
{ {
Self::on_event(this, Some(pdwEffect), MouseEvent::DragMoved {}); let event = MouseEvent::DragMoved {};
Self::on_event(this, Some(pdwEffect), event);
S_OK S_OK
} }
unsafe extern "system" fn drag_leave(this: *mut IDropTarget) -> HRESULT { unsafe extern "system" fn drag_leave(this: *mut IDropTarget) -> HRESULT {
Self::on_event(this, None, MouseEvent::DragLeft {}); Self::on_event(this, None, MouseEvent::DragLeft);
S_OK S_OK
} }
@ -916,7 +968,12 @@ impl DropTarget {
pdwEffect: *mut DWORD, pdwEffect: *mut DWORD,
) -> HRESULT ) -> HRESULT
{ {
Self::on_event(this, Some(pdwEffect), MouseEvent::DragDropped {}); let data = Self::parse_drop_data(&*pDataObj);
let event = MouseEvent::DragDropped {
data
};
Self::on_event(this, Some(pdwEffect), event);
S_OK S_OK
} }
} }