Parse drop data
Only handling files for now
This commit is contained in:
parent
ef64cae538
commit
b5f3939930
|
@ -29,7 +29,7 @@ xcb-util = { version = "0.3", features = ["icccm"] }
|
|||
nix = "0.22.0"
|
||||
|
||||
[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 }
|
||||
|
||||
[target.'cfg(target_os="macos")'.dependencies]
|
||||
|
|
19
src/event.rs
19
src/event.rs
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use keyboard_types::{KeyboardEvent, Modifiers};
|
||||
|
||||
use crate::{Point, WindowInfo};
|
||||
|
@ -32,7 +34,7 @@ pub enum ScrollDelta {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum MouseEvent {
|
||||
/// The mouse cursor was moved
|
||||
CursorMoved {
|
||||
|
@ -77,10 +79,16 @@ pub enum MouseEvent {
|
|||
CursorLeft,
|
||||
|
||||
// TODO: Document
|
||||
DragEntered,
|
||||
DragEntered {
|
||||
data: Option<DropData>,
|
||||
},
|
||||
|
||||
DragMoved,
|
||||
DragLeft,
|
||||
DragDropped,
|
||||
|
||||
DragDropped {
|
||||
data: Option<DropData>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -106,6 +114,11 @@ pub enum DropEffect {
|
|||
Scroll,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DropData {
|
||||
Files(Vec<PathBuf>),
|
||||
}
|
||||
|
||||
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
|
||||
/// indicating whether the event was handled by your window or should be passed
|
||||
/// back to the platform.
|
||||
|
|
|
@ -4,10 +4,12 @@ use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM, DWOR
|
|||
use winapi::shared::ntdef::{HRESULT, ULONG};
|
||||
use winapi::shared::windef::{HWND, RECT, POINTL};
|
||||
use winapi::shared::winerror::{S_OK, E_NOINTERFACE};
|
||||
use winapi::shared::wtypes::DVASPECT_CONTENT;
|
||||
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::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::winuser::{
|
||||
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_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD,
|
||||
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::collections::VecDeque;
|
||||
use std::ffi::{c_void, OsStr};
|
||||
use std::ffi::{c_void, OsStr, OsString};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::transmute;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::os::windows::prelude::OsStringExt;
|
||||
use std::ptr::null_mut;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
@ -39,7 +42,7 @@ const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1;
|
|||
|
||||
use crate::{
|
||||
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;
|
||||
|
@ -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(
|
||||
this: *mut IUnknown,
|
||||
riid: REFIID,
|
||||
|
@ -888,7 +934,12 @@ impl DropTarget {
|
|||
pdwEffect: *mut DWORD,
|
||||
) -> 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
|
||||
}
|
||||
|
||||
|
@ -899,12 +950,13 @@ impl DropTarget {
|
|||
pdwEffect: *mut DWORD,
|
||||
) -> HRESULT
|
||||
{
|
||||
Self::on_event(this, Some(pdwEffect), MouseEvent::DragMoved {});
|
||||
let event = MouseEvent::DragMoved {};
|
||||
Self::on_event(this, Some(pdwEffect), event);
|
||||
S_OK
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -916,7 +968,12 @@ impl DropTarget {
|
|||
pdwEffect: *mut DWORD,
|
||||
) -> 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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue