Skip to content

Commit 2dcb70a

Browse files
authored
Merge pull request #1276 from MicrosoftEdge/api-notifydroptargetaction
API Review for the Drag and Drop API for composition hosting
2 parents 1d33cfc + ec7b350 commit 2dcb70a

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed

specs/NotifyDropTargetAction.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<!-- TEMPLATE
2+
The purpose of this spec is to describe a new WebView2 feature and its APIs.
3+
4+
There are two audiences for the spec. The first are people
5+
that want to evaluate and give feedback on the API, as part of
6+
the submission process. When it's complete
7+
it will be incorporated into the public documentation at
8+
docs.microsoft.com (https://docs.microsoft.com/en-us/microsoft-edge/webview2/).
9+
Hopefully we'll be able to copy it mostly verbatim.
10+
So the second audience is everyone that reads there to learn how
11+
and why to use this API.
12+
-->
13+
14+
15+
# Background
16+
These APIs will allow users to drop things such as images, text, and links into the WebView as part of a drag/drop operation.
17+
The reason that we need separate APIs for this with composition hosting is because we don't have an HWND to call RegisterDragDrop on.
18+
The hosting app needs to call RegisterDragDrop on the HWND that contains the WebView and implement IDropTarget so it can forward the
19+
calls (IDropTarget::DragEnter, DragMove, DragLeave, and Drop) to the WebView. Other UI frameworks have their own ways to register.
20+
For example, Xaml require setting event handler for DragEnter, DragOver, DragLeave, and Drop on the corresponding UIElement.
21+
22+
For API reviewers, We want a unified API surface between COM and WinRT that works in both UWP and Win32.
23+
24+
We could:
25+
1. Have one API focusing on Win32 types and require the end dev to convert from UWP types to Win32 (which we've done).
26+
2. Have one API focusing on UWP types and require the end dev to convert Win32 to UWP.
27+
3. Have two sets of methods one for Win32 and one for UWP types.
28+
Or we could do (1) or (2) and provide a conversion function.
29+
Because the conversion is simple and we have a large Win32 user base we chose (1) and provided a conversion function.
30+
31+
32+
# Description
33+
DragEnter, DragOver, DragLeave, and Drop are functions meant to provide a way for composition hosted WebViews to receive drop events as part of a drag/drop operation.
34+
For win32, it is the hosting application's responsibility to call [RegisterDragDrop](https://docs.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-registerdragdrop)
35+
on the HWND that contains any composition hosted WebViews and to implement [IDropTarget](https://docs.microsoft.com/en-us/windows/win32/api/oleidl/nn-oleidl-idroptarget)
36+
to receive the corresponding drop events from Ole32:
37+
38+
- IDropTarget::DragEnter
39+
- IDropTarget::DragMove
40+
- IDropTarget::DragLeave
41+
- IDropTarget::Drop
42+
43+
The HWND doesn't have to be the immediate parent of the WebView2 but it does have to convert the POINTL argument in the above functions from screen coordinates to client coordinates of the WebView2.
44+
45+
For WinRT, it is the hosting applications responsibility to register as a drop target via [CoreDragDropManager](https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.datatransfer.dragdrop.core.coredragdropmanager)
46+
on CoreDragDropManager.TargetRequested and to call [CoreDropOperationTargetRequestedEventArgs.SetTarget(ICoreDropOperationTarget)](https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.datatransfer.dragdrop.core.coredropoperationtargetrequestedeventargs)
47+
on an implementation of [ICoreDropOperationTarget](https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.DataTransfer.DragDrop.Core.ICoreDropOperationTarget).
48+
49+
# Examples
50+
## Win32
51+
```c++
52+
// Win32 Sample
53+
54+
// Implementation for IDropTarget
55+
HRESULT DropTarget::DragEnter(IDataObject* dataObject,
56+
DWORD keyState,
57+
POINTL cursorPosition,
58+
DWORD* effect)
59+
{
60+
POINT point = { cursorPosition.x, cursorPosition.y };
61+
62+
// Convert the screen point to client coordinates add the WebView's offset.
63+
m_viewComponent->OffsetPointToWebView(&point);
64+
return m_webViewCompositionController2->DragEnter(
65+
dataObject, keyState, point, effect);
66+
}
67+
68+
HRESULT DropTarget::DragOver(DWORD keyState,
69+
POINTL cursorPosition,
70+
DWORD* effect)
71+
{
72+
POINT point = { cursorPosition.x, cursorPosition.y };
73+
74+
// Convert the screen point to client coordinates add the WebView's offset.
75+
// This returns whether the resultant point is over the WebView visual.
76+
m_viewComponent->OffsetPointToWebView(&point);
77+
return m_webViewCompositionController2->DragOver(
78+
keyState, point, effect);
79+
}
80+
81+
HRESULT DropTarget::DragLeave()
82+
{
83+
return m_webViewCompositionController2->DragLeave();
84+
}
85+
86+
HRESULT DropTarget::Drop(IDataObject* dataObject,
87+
DWORD keyState,
88+
POINTL cursorPosition,
89+
DWORD* effect)
90+
{
91+
POINT point = { cursorPosition.x, cursorPosition.y };
92+
93+
// Convert the screen point to client coordinates add the WebView's offset.
94+
// This returns whether the resultant point is over the WebView visual.
95+
m_viewComponent->OffsetPointToWebView(&point);
96+
return m_webViewCompositionController2->Drop(
97+
dataObject, keyState, point, effect);
98+
}
99+
```
100+
101+
## WinRT
102+
```c#
103+
// WinRT Sample
104+
IAsyncOperation<DataPackageOperation> ICoreDropOperationTarget.EnterAsync(CoreDragInfo dragInfo, CoreDragUIOverride dragUIOverride)
105+
{
106+
return compositionController.DragEnter(dragInfo, dragUIOverride);
107+
}
108+
109+
IAsyncOperation<DataPackageOperation> ICoreDropOperationTarget.OverAsync(CoreDragInfo dragInfo, CoreDragUIOverride dragUIOverride)
110+
{
111+
return compositionController.DragOver(dragInfo, dragUIOverride);
112+
}
113+
114+
IAsyncAction ICoreDropOperationTarget.LeaveAsync(CoreDragInfo dragInfo)
115+
{
116+
return compositionController.DragLeave(dragInfo);
117+
}
118+
119+
IAsyncOperation<DataPackageOperation> ICoreDropOperationTarget.DropAsync(CoreDragInfo dragInfo)
120+
{
121+
return compositionController.Drop(dragInfo);
122+
}
123+
```
124+
125+
126+
# API Details
127+
## Win32
128+
```c++
129+
interface ICoreWebView2CompositionController2 : ICoreWebView2CompositionController {
130+
/// This set of APIs (DragEnter, DragLeave, DragOver, and Drop) will allow
131+
/// users to drop things such as images, text, and links into the WebView as
132+
/// part of a drag/drop operation. The reason that we need a separate API for
133+
/// this with composition hosting is because we don't have an HWND to call
134+
/// RegisterDragDrop on. The hosting app needs to call RegisterDragDrop on the
135+
/// HWND that contains the WebView and implement IDropTarget so it can forward
136+
/// the calls (IDropTarget::DragEnter, DragMove, DragLeave, and Drop) to the
137+
/// WebView.
138+
///
139+
/// This function corresponds to IDropTarget::DragEnter
140+
///
141+
/// The hosting application must register as an IDropTarget and implement
142+
/// and forward DragEnter calls to this function.
143+
///
144+
/// In addition, the hosting application needs to create an IDropTargetHelper
145+
/// and call the corresponding IDropTargetHelper::DragEnter function on that
146+
/// object before forwarding the call to WebView.
147+
///
148+
/// point parameter must be modified to include the WebView's offset and be in
149+
/// the WebView's client coordinates (Similar to how SendMouseInput works).
150+
HRESULT DragEnter(
151+
[in] IDataObject* dataObject,
152+
[in] DWORD keyState,
153+
[in] POINT point,
154+
[out, retval] DWORD* effect);
155+
156+
/// Please refer to DragEnter for more information on how Drag/Drop works with
157+
/// WebView2.
158+
///
159+
/// This function corresponds to IDropTarget::DragLeave
160+
///
161+
/// The hosting application must register as an IDropTarget and implement
162+
/// and forward DragLeave calls to this function.
163+
///
164+
/// In addition, the hosting application needs to create an IDropTargetHelper
165+
/// and call the corresponding IDropTargetHelper::DragLeave function on that
166+
/// object before forwarding the call to WebView.
167+
HRESULT DragLeave();
168+
169+
/// Please refer to DragEnter for more information on how Drag/Drop works with
170+
/// WebView2.
171+
///
172+
/// This function corresponds to IDropTarget::DragOver
173+
///
174+
/// The hosting application must register as an IDropTarget and implement
175+
/// and forward DragOver calls to this function.
176+
///
177+
/// In addition, the hosting application needs to create an IDropTargetHelper
178+
/// and call the corresponding IDropTargetHelper::DragOver function on that
179+
/// object before forwarding the call to WebView.
180+
///
181+
/// point parameter must be modified to include the WebView's offset and be in
182+
/// the WebView's client coordinates (Similar to how SendMouseInput works).
183+
HRESULT DragOver(
184+
[in] DWORD keyState,
185+
[in] POINT point,
186+
[out, retval] DWORD* effect);
187+
188+
/// Please refer to DragEnter for more information on how Drag/Drop works with
189+
/// WebView2.
190+
///
191+
/// This function corresponds to IDropTarget::Drop
192+
///
193+
/// The hosting application must register as an IDropTarget and implement
194+
/// and forward Drop calls to this function.
195+
///
196+
/// In addition, the hosting application needs to create an IDropTargetHelper
197+
/// and call the corresponding IDropTargetHelper::Drop function on that
198+
/// object before forwarding the call to WebView.
199+
///
200+
/// point parameter must be modified to include the WebView's offset and be in
201+
/// the WebView's client coordinates (Similar to how SendMouseInput works).
202+
HRESULT Drop(
203+
[in] IDataObject* dataObject,
204+
[in] DWORD keyState,
205+
[in] POINT point,
206+
[out, retval] DWORD* effect);
207+
}
208+
```
209+
210+
## WinRT
211+
```c#
212+
namespace Microsoft.Web.WebView2.Core
213+
{
214+
public sealed class CoreWebView2CompositionController : CoreWebView2Controller, ICoreWebView2CompositionController2
215+
{
216+
// New APIs
217+
Windows.ApplicationModel.DataTransfer.DataPackageOperation DragEnter(
218+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragInfo dragInfo,
219+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragUIOverride dragUIOverride);
220+
221+
Windows.ApplicationModel.DataTransfer.DataPackageOperation DragLeave(
222+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragInfo dragInfo);
223+
224+
Windows.ApplicationModel.DataTransfer.DataPackageOperation DragOver(
225+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragInfo dragInfo,
226+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragUIOverride dragUIOverride);
227+
228+
Windows.ApplicationModel.DataTransfer.DataPackageOperation Drop(
229+
Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragInfo dragInfo);
230+
}
231+
}
232+
```
233+
234+
# Appendix
235+
A good resource to read about the whole Ole drag/drop is located here:
236+
[OLE Drag and Drop](https://docs.microsoft.com/en-us/cpp/mfc/drag-and-drop-ole?view=msvc-160)

0 commit comments

Comments
 (0)