windows: Use drop target helper (#33203)
It now utilises the [`IDropTargetHelper`](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-idroptargethelper) in drag and drop events to render the proper item drop cursor icon which includes the thumbnail when available and action text. Also swaps the drop effect from `DROPEFFECT_LINK` to `DROPEFFECT_COPY` to match other Windows application behaviour. Example of drop icon  Release Notes: - N/A --------- Co-authored-by: 张小白 <364772080@qq.com>
This commit is contained in:
parent
1a6c1b2159
commit
a067c16c82
2 changed files with 37 additions and 5 deletions
|
@ -42,6 +42,7 @@ pub(crate) struct WindowsPlatform {
|
|||
text_system: Arc<DirectWriteTextSystem>,
|
||||
windows_version: WindowsVersion,
|
||||
bitmap_factory: ManuallyDrop<IWICImagingFactory>,
|
||||
drop_target_helper: IDropTargetHelper,
|
||||
validation_number: usize,
|
||||
main_thread_id_win32: u32,
|
||||
}
|
||||
|
@ -103,6 +104,10 @@ impl WindowsPlatform {
|
|||
DirectWriteTextSystem::new(&bitmap_factory)
|
||||
.context("Error creating DirectWriteTextSystem")?,
|
||||
);
|
||||
let drop_target_helper: IDropTargetHelper = unsafe {
|
||||
CoCreateInstance(&CLSID_DragDropHelper, None, CLSCTX_INPROC_SERVER)
|
||||
.context("Error creating drop target helper.")?
|
||||
};
|
||||
let icon = load_icon().unwrap_or_default();
|
||||
let state = RefCell::new(WindowsPlatformState::new());
|
||||
let raw_window_handles = RwLock::new(SmallVec::new());
|
||||
|
@ -120,6 +125,7 @@ impl WindowsPlatform {
|
|||
text_system,
|
||||
windows_version,
|
||||
bitmap_factory,
|
||||
drop_target_helper,
|
||||
validation_number,
|
||||
main_thread_id_win32,
|
||||
})
|
||||
|
@ -177,6 +183,7 @@ impl WindowsPlatform {
|
|||
executor: self.foreground_executor.clone(),
|
||||
current_cursor: self.state.borrow().current_cursor,
|
||||
windows_version: self.windows_version,
|
||||
drop_target_helper: self.drop_target_helper.clone(),
|
||||
validation_number: self.validation_number,
|
||||
main_receiver: self.main_receiver.clone(),
|
||||
main_thread_id_win32: self.main_thread_id_win32,
|
||||
|
@ -728,6 +735,7 @@ pub(crate) struct WindowCreationInfo {
|
|||
pub(crate) executor: ForegroundExecutor,
|
||||
pub(crate) current_cursor: Option<HCURSOR>,
|
||||
pub(crate) windows_version: WindowsVersion,
|
||||
pub(crate) drop_target_helper: IDropTargetHelper,
|
||||
pub(crate) validation_number: usize,
|
||||
pub(crate) main_receiver: flume::Receiver<Runnable>,
|
||||
pub(crate) main_thread_id_win32: u32,
|
||||
|
|
|
@ -63,6 +63,7 @@ pub struct WindowsWindowState {
|
|||
pub(crate) struct WindowsWindowStatePtr {
|
||||
hwnd: HWND,
|
||||
this: Weak<Self>,
|
||||
drop_target_helper: IDropTargetHelper,
|
||||
pub(crate) state: RefCell<WindowsWindowState>,
|
||||
pub(crate) handle: AnyWindowHandle,
|
||||
pub(crate) hide_title_bar: bool,
|
||||
|
@ -210,6 +211,7 @@ impl WindowsWindowStatePtr {
|
|||
Ok(Rc::new_cyclic(|this| Self {
|
||||
hwnd,
|
||||
this: this.clone(),
|
||||
drop_target_helper: context.drop_target_helper.clone(),
|
||||
state,
|
||||
handle: context.handle,
|
||||
hide_title_bar: context.hide_title_bar,
|
||||
|
@ -331,6 +333,7 @@ struct WindowCreateContext<'a> {
|
|||
executor: ForegroundExecutor,
|
||||
current_cursor: Option<HCURSOR>,
|
||||
windows_version: WindowsVersion,
|
||||
drop_target_helper: IDropTargetHelper,
|
||||
validation_number: usize,
|
||||
main_receiver: flume::Receiver<Runnable>,
|
||||
gpu_context: &'a BladeContext,
|
||||
|
@ -349,6 +352,7 @@ impl WindowsWindow {
|
|||
executor,
|
||||
current_cursor,
|
||||
windows_version,
|
||||
drop_target_helper,
|
||||
validation_number,
|
||||
main_receiver,
|
||||
main_thread_id_win32,
|
||||
|
@ -394,6 +398,7 @@ impl WindowsWindow {
|
|||
executor,
|
||||
current_cursor,
|
||||
windows_version,
|
||||
drop_target_helper,
|
||||
validation_number,
|
||||
main_receiver,
|
||||
gpu_context,
|
||||
|
@ -831,8 +836,9 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
lindex: -1,
|
||||
tymed: TYMED_HGLOBAL.0 as _,
|
||||
};
|
||||
let cursor_position = POINT { x: pt.x, y: pt.y };
|
||||
if idata_obj.QueryGetData(&config as _) == S_OK {
|
||||
*pdweffect = DROPEFFECT_LINK;
|
||||
*pdweffect = DROPEFFECT_COPY;
|
||||
let Some(mut idata) = idata_obj.GetData(&config as _).log_err() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -847,7 +853,7 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
}
|
||||
});
|
||||
ReleaseStgMedium(&mut idata);
|
||||
let mut cursor_position = POINT { x: pt.x, y: pt.y };
|
||||
let mut cursor_position = cursor_position;
|
||||
ScreenToClient(self.0.hwnd, &mut cursor_position)
|
||||
.ok()
|
||||
.log_err();
|
||||
|
@ -864,6 +870,10 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
} else {
|
||||
*pdweffect = DROPEFFECT_NONE;
|
||||
}
|
||||
self.0
|
||||
.drop_target_helper
|
||||
.DragEnter(self.0.hwnd, idata_obj, &cursor_position, *pdweffect)
|
||||
.log_err();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -872,10 +882,15 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
&self,
|
||||
_grfkeystate: MODIFIERKEYS_FLAGS,
|
||||
pt: &POINTL,
|
||||
_pdweffect: *mut DROPEFFECT,
|
||||
pdweffect: *mut DROPEFFECT,
|
||||
) -> windows::core::Result<()> {
|
||||
let mut cursor_position = POINT { x: pt.x, y: pt.y };
|
||||
unsafe {
|
||||
*pdweffect = DROPEFFECT_COPY;
|
||||
self.0
|
||||
.drop_target_helper
|
||||
.DragOver(&cursor_position, *pdweffect)
|
||||
.log_err();
|
||||
ScreenToClient(self.0.hwnd, &mut cursor_position)
|
||||
.ok()
|
||||
.log_err();
|
||||
|
@ -894,6 +909,9 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
}
|
||||
|
||||
fn DragLeave(&self) -> windows::core::Result<()> {
|
||||
unsafe {
|
||||
self.0.drop_target_helper.DragLeave().log_err();
|
||||
}
|
||||
let input = PlatformInput::FileDrop(FileDropEvent::Exited);
|
||||
self.handle_drag_drop(input);
|
||||
|
||||
|
@ -902,13 +920,19 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
|
|||
|
||||
fn Drop(
|
||||
&self,
|
||||
_pdataobj: windows::core::Ref<IDataObject>,
|
||||
pdataobj: windows::core::Ref<IDataObject>,
|
||||
_grfkeystate: MODIFIERKEYS_FLAGS,
|
||||
pt: &POINTL,
|
||||
_pdweffect: *mut DROPEFFECT,
|
||||
pdweffect: *mut DROPEFFECT,
|
||||
) -> windows::core::Result<()> {
|
||||
let idata_obj = pdataobj.ok()?;
|
||||
let mut cursor_position = POINT { x: pt.x, y: pt.y };
|
||||
unsafe {
|
||||
*pdweffect = DROPEFFECT_COPY;
|
||||
self.0
|
||||
.drop_target_helper
|
||||
.Drop(idata_obj, &cursor_position, *pdweffect)
|
||||
.log_err();
|
||||
ScreenToClient(self.0.hwnd, &mut cursor_position)
|
||||
.ok()
|
||||
.log_err();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue