Skip to content

Commit f37dde5

Browse files
authored
Create NotifyDropTargetAction.md
1 parent e7087aa commit f37dde5

1 file changed

Lines changed: 280 additions & 0 deletions

File tree

specs/NotifyDropTargetAction.md

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
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+
<!-- TEMPLATE
17+
Use this section to provide background context for the new API(s)
18+
in this spec.
19+
20+
This section and the appendix are the only sections that likely
21+
do not get copied into any official documentation, they're just an aid
22+
to reading this spec.
23+
24+
If you're modifying an existing API, included a link here to the
25+
existing page(s) or spec documentation.
26+
27+
For example, this section is a place to explain why you're adding this
28+
API rather than modifying an existing API.
29+
30+
For example, this is a place to provide a brief explanation of some dependent
31+
area, just explanation enough to understand this new API, rather than telling
32+
the reader "go read 100 pages of background information posted at ...".
33+
-->
34+
35+
This API will allow users to drop things such as images, text, and links into the WebView as part of a drag/drop operation.
36+
The reason that we need a separate API for this with composition hosting is because we don't have an HWND to call RegisterDragDrop on.
37+
The hosting app needs to call RegisterDragDrop on the HWND that contains the WebView and implement IDropTarget so it can forward the
38+
calls (IDropTarget::DragEnter, DragMove, DragLeave, and Drop) to the WebView.
39+
40+
Additionally, the hosting app also needs to call into IDropTargetHelper before forwarding those calls to us as documented here:
41+
https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-idroptargethelper
42+
43+
44+
# Description
45+
<!-- TEMPLATE
46+
Use this section to provide a brief description of the feature.
47+
48+
For an example, see the introduction to the PasswordBox control
49+
(http://docs.microsoft.com/windows/uwp/design/controls-and-patterns/password-box).
50+
-->
51+
52+
NotifyDropTargetAction is meant to provide a way for composition hosted WebViews to receive drop events as part of a drag/drop operation.
53+
It is the hosting application's responsibility to call RegisterDragDrop (https://docs.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-registerdragdrop)
54+
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)
55+
to receive the corresponding drop events from Ole32:
56+
57+
IDropTarget::DragEnter
58+
IDropTarget::DragMove
59+
IDropTarget::DragLeave
60+
IDropTarget::Drop
61+
62+
NotifyDropTargetAction consolidates these four functions into one and the COREWEBVIEW2_DROP_TARGET_ACTION enum
63+
specifies which correspondingIDropTarget function was called.
64+
65+
66+
# Examples
67+
<!-- TEMPLATE
68+
Use this section to explain the features of the API, showing
69+
example code with each description in both C# (for our WinRT API or .NET API) and
70+
in C++ for our COM API. Use snippets of the sample code you wrote for the sample apps.
71+
72+
The general format is:
73+
74+
## FirstFeatureName
75+
76+
Feature explanation text goes here, including why an app would use it, how it
77+
replaces or supplements existing functionality.
78+
79+
```c#
80+
void SampleMethod()
81+
{
82+
var show = new AnExampleOf();
83+
show.SomeMembers = AndWhyItMight(be, interesting)
84+
}
85+
```
86+
87+
```cpp
88+
void SampleClass::SampleMethod()
89+
{
90+
winrt::com_ptr<ICoreWebView2> webview2 = ...
91+
}
92+
```
93+
94+
## SecondFeatureName
95+
96+
Feature explanation text goes here, including why an app would use it, how it
97+
replaces or supplements existing functionality.
98+
99+
```c#
100+
void SampleMethod()
101+
{
102+
var show = new AnExampleOf();
103+
show.SomeMembers = AndWhyItMight(be, interesting)
104+
}
105+
```
106+
107+
```cpp
108+
void SampleClass::SampleMethod()
109+
{
110+
winrt::com_ptr<ICoreWebView2> webview2 = ...
111+
}
112+
```
113+
114+
As an example of this section, see the Examples section for the PasswordBox
115+
control (https://docs.microsoft.com/windows/uwp/design/controls-and-patterns/password-box#examples).
116+
-->
117+
118+
```c++
119+
// Initialized elsewhere
120+
wil::com_ptr<ICoreWebView2Controller> webViewController;
121+
122+
webViewCompositionController =
123+
webViewController.query<ICoreWebView2CompositionController>();
124+
125+
// Implementation for IDropTarget
126+
HRESULT DropTarget::DragEnter(IDataObject * data_object,
127+
DWORD key_state,
128+
POINTL cursor_position,
129+
DWORD* effect)
130+
{
131+
POINT point = {cursor_position.x, cursor_position.y};
132+
// Tell the helper that we entered so it can update the drag image and return
133+
// the allowed effects.
134+
IDropTargetHelper* drop_helper = DropHelper();
135+
if (drop_helper) {
136+
drop_helper->DragEnter(GetHWND(), data_object, &point, *effect);
137+
}
138+
// Convert the point to WebView client coordinates from screen coordinates
139+
// account for any offset.
140+
ConvertScreenPointToWebView(&point);
141+
return webViewCompositionController->NotifyDropTargetAction(
142+
COREWEBVIEW2_DRAG_ENTER, data_object, key_state, point, effect);
143+
}
144+
145+
HRESULT DropTarget::DragOver(DWORD key_state,
146+
POINTL cursor_position,
147+
DWORD * effect)
148+
{
149+
POINT point = {cursor_position.x, cursor_position.y};
150+
IDropTargetHelper* drop_helper = DropHelper();
151+
if (drop_helper)
152+
drop_helper->DragOver(&point, *effect);
153+
ConvertScreenPointToWebView(&point);
154+
return webViewCompositionController->NotifyDropTargetAction(
155+
COREWEBVIEW2_DRAG_OVER, nullptr, key_state, point, effect);
156+
}
157+
158+
HRESULT DropTarget::DragLeave()
159+
{
160+
IDropTargetHelper* drop_helper = DropHelper();
161+
if (drop_helper)
162+
drop_helper->DragLeave();
163+
return webViewCompositionController->NotifyDropTargetAction(
164+
COREWEBVIEW2_DRAG_LEAVE, nullptr, 0, {0, 0}, nullptr);
165+
}
166+
167+
HRESULT DropTarget::Drop(IDataObject * data_object,
168+
DWORD key_state,
169+
POINTL cursor_position,
170+
DWORD * effect)
171+
{
172+
POINT point = {cursor_position.x, cursor_position.y};
173+
IDropTargetHelper* drop_helper = DropHelper();
174+
if (drop_helper) {
175+
drop_helper->Drop(data_object, &point, *effect);
176+
}
177+
ConvertScreenPointToWebView(&point);
178+
return webViewCompositionController->NotifyDropTargetAction(
179+
COREWEBVIEW2_DROP, data_object, key_state, point, effect);
180+
}
181+
```
182+
183+
184+
# API Details
185+
<!-- TEMPLATE
186+
The exact API, in IDL format for our COM API and
187+
in MIDL3 format (https://docs.microsoft.com/en-us/uwp/midl-3/)
188+
when possible, or in C# if starting with an API sketch for our .NET and WinRT API.
189+
190+
Include every new or modified type but use // ... to remove any methods,
191+
properties, or events that are unchanged.
192+
193+
(GitHub's markdown syntax formatter does not (yet) know about MIDL3, so
194+
use ```c# instead even when writing MIDL3.)
195+
196+
Example:
197+
198+
```
199+
/// Event args for the NewWindowRequested event. The event is fired when content
200+
/// inside webview requested to open a new window (through window.open() and so on.)
201+
[uuid(34acb11c-fc37-4418-9132-f9c21d1eafb9), object, pointer_default(unique)]
202+
interface ICoreWebView2NewWindowRequestedEventArgs : IUnknown
203+
{
204+
// ...
205+
206+
/// Window features specified by the window.open call.
207+
/// These features can be considered for positioning and sizing of
208+
/// new webview windows.
209+
[propget] HRESULT WindowFeatures([out, retval] ICoreWebView2WindowFeatures** windowFeatures);
210+
}
211+
```
212+
213+
```c# (but really MIDL3)
214+
public class CoreWebView2NewWindowRequestedEventArgs
215+
{
216+
// ...
217+
218+
public CoreWebView2WindowFeatures WindowFeatures { get; }
219+
}
220+
```
221+
-->
222+
223+
```c++
224+
[v1_enum]
225+
typedef enum COREWEBVIEW2_DROP_TARGET_ACTION {
226+
COREWEBVIEW2_DRAG_ENTER,
227+
COREWEBVIEW2_DRAG_LEAVE,
228+
COREWEBVIEW2_DRAG_OVER,
229+
COREWEBVIEW2_DROP,
230+
} COREWEBVIEW2_DROP_TARGET_ACTION;
231+
```
232+
233+
```c++
234+
/// This function tells allows WebView2 to act as a drop target in composition
235+
/// hosting mode.
236+
///
237+
/// The hosting application needs to register as an IDropTarget and implement
238+
/// all of the functions in IDropTarget: DragEnter, DragOver, DragLeave, and
239+
/// Drop. See:
240+
/// https://docs.microsoft.com/en-us/windows/win32/api/oleidl/nn-oleidl-idroptarget
241+
/// In addition, the hosting application needs to create an IDropTargetHelper
242+
/// and call the corresponding functions on that object before forwarding the
243+
/// call to WebView. See:
244+
/// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-idroptargethelper
245+
/// This also allows the hosting application to modify the values of the
246+
/// effect parameter before passing it on to the WebView.
247+
///
248+
/// dropTargetAction is a WebView2 specific enum that should be set to
249+
/// correspond to the IDropTarget function that is currently being called.
250+
/// COREWEBVIEW2_DRAG_ENTER for IDropTarget::DragEnter
251+
/// COREWEBVIEW2_DRAG_OVER for IDropTarget::DragOver
252+
/// COREWEBVIEW2_DRAG_LEAVE for IDropTarget::DragLeave
253+
/// COREWEBVIEW2_DROP for IDropTarget::Drop
254+
///
255+
/// Note that unless COREWEBVIEW2_DRAG_LEAVE is specified for
256+
/// dropTargetAction, effect must be a valid pointer.
257+
///
258+
/// dataObject must also be a valid if COREWEBVIEW2_DRAG_ENTER or
259+
/// COREWEBVIEW2_DROP is specified as the dropTargetAction.
260+
///
261+
/// point parameter must be modified to include the WebView's offset and be in
262+
/// the WebView's client coordinates (Similar to how SendMouseInput works).
263+
HRESULT NotifyDropTargetAction(
264+
[in] COREWEBVIEW2_DROP_TARGET_ACTION dropTargetAction,
265+
[in] IDataObject* dataObject,
266+
[in] DWORD keyState,
267+
[in] POINT point,
268+
[out, retval] DWORD* effect);
269+
```
270+
271+
272+
# Appendix
273+
<!-- TEMPLATE
274+
Anything else that you want to write down for posterity, but
275+
that isn't necessary to understand the purpose and usage of the API.
276+
For example, implementation details or links to other resources.
277+
-->
278+
279+
A good resource to read about the whole Ole drag/drop is located here:
280+
https://docs.microsoft.com/en-us/cpp/mfc/drag-and-drop-ole?view=msvc-160#:~:text=You%20select%20the%20data%20from,than%20the%20copy%2Fpaste%20sequence.

0 commit comments

Comments
 (0)