Skip to content

Commit 47b5622

Browse files
authored
Merge pull request #4900 from MicrosoftEdge/api-dragstarting
API Review: DragStarting Event API
2 parents d252b7f + 8a4130a commit 47b5622

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

specs/DragStarting.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
DragStarting
2+
===
3+
4+
# Background
5+
The WebView2 team has been asked to provide a way to override the default drag
6+
drop behavior when running in visual hosting mode. This event allows you to know
7+
when a drag is initiated in WebView2 and provides the state necessary to override
8+
the default WebView2 drag operation with your own logic.
9+
10+
## Note about .NET/WinRT projection
11+
The work to project this API to .NET and WinRT are yet to be completed. Overall
12+
usage of this API is expected to be uncommon. There are no known public asks for
13+
this. Further, this API is exposed on the CompositionController which is very
14+
rarely used in .NET apps.
15+
16+
# Examples
17+
## DragStarting
18+
Users can use `add_DragStarting` on the CompositionController to add an event
19+
handler that is invoked when drag is starting. They can use the event args
20+
to start their own drag. Notably the `Deferral` can be used to execute any async
21+
drag logic and call back into the WebView at a later time. The `Handled`
22+
property lets the WebView2 know whether to exercise its own drag logic or not.
23+
24+
## Override drag and drop
25+
```C++
26+
// Using DragStarting to simply make a synchronous DoDragDrop call instead of
27+
// having WebView2 do it.
28+
CHECK_FAILURE(m_compController5->add_DragStarting(
29+
Callback<ICoreWebView2DragStartingEventHandler>(
30+
[this](ICoreWebView2CompositionController5* sender,
31+
ICoreWebView2DragStartingEventArgs* args)
32+
{
33+
DWORD okEffects = COREWEBVIEW2_DROP_EFFECTS_NONE;
34+
wil::com_ptr<IDataObject> dragData;
35+
36+
CHECK_FAILURE(args->get_AllowedDropEffects(&okEffects));
37+
CHECK_FAILURE(args->get_Data(&dragData));
38+
39+
// This member refers to an implementation of IDropSource. It is an
40+
// OLE interface that is necessary to initiate drag in an application.
41+
// https://learn.microsoft.com/en-us/windows/win32/api/oleidl/nn-oleidl-idropsource
42+
if (!m_dropSource)
43+
{
44+
m_dropSource = Make<ScenarioDragDropOverrideDropSource>();
45+
}
46+
47+
DWORD effect = DROPEFFECT_NONE;
48+
HRESULT hr = DoDragDrop(
49+
dragData.get(), m_dropSource.get(), okEffects, &effect);
50+
args->put_Handled(SUCCEEDED(hr));
51+
52+
return hr;
53+
})
54+
.Get(),
55+
&m_dragStartingToken));
56+
```
57+
58+
## Disable drag and drop
59+
```C++
60+
// Using DragStarting to no-op a drag operation.
61+
CHECK_FAILURE(m_compController5->add_DragStarting(
62+
Callback<ICoreWebView2DragStartingEventHandler>(
63+
[this](ICoreWebView2CompositionController5* sender,
64+
ICoreWebView2DragStartingEventArgs* args)
65+
{
66+
// If the event is marked handled, WebView2 will not execute its
67+
// drag logic.
68+
args->put_Handled(TRUE);
69+
return S_OK;
70+
})
71+
.Get(),
72+
&m_dragStartingToken));
73+
```
74+
75+
# API Details
76+
```C++
77+
/// Event args for the `DragStarting` event.
78+
[uuid(edb6b243-334f-59d0-b3b3-de87dd401adc), object, pointer_default(unique)]
79+
interface ICoreWebView2DragStartingEventArgs : IUnknown {
80+
/// The [OLE DROPEFFECT](https://learn.microsoft.com/en-us/windows/win32/com/dropeffect-constants)
81+
/// values this drag data supports.
82+
[propget] HRESULT AllowedDropEffects(
83+
[out, retval] COREWEBVIEW2_DROP_EFFECTS* value);
84+
85+
86+
/// The data to be dragged.
87+
[propget] HRESULT Data([out, retval] IDataObject** value);
88+
89+
/// The position at which drag was detected given in WebView2 relative
90+
/// coordinates.
91+
[propget] HRESULT Position([out, retval] POINT* value);
92+
93+
94+
/// Gets the `Handled` property.
95+
[propget] HRESULT Handled([out, retval] BOOL* value);
96+
97+
98+
/// Indicates whether this event has been handled by the app. If the
99+
/// app handles this event, WebView2 will not initiate drag drop. If
100+
/// the app does not handle the event, WebView2 will initiate its own
101+
/// drag drop logic. The default value is FALSE.
102+
[propput] HRESULT Handled([in] BOOL value);
103+
104+
105+
106+
/// Returns an `ICoreWebView2Deferral` object. Use this operation to complete
107+
/// the CoreWebView2DragStartingEventArgs.
108+
///
109+
/// Until the deferral is completed, subsequent attempts to initiate drag
110+
/// in the WebView2 will fail and if the cursor was changed as part of
111+
/// drag it will not restore.
112+
HRESULT GetDeferral(
113+
[out, retval] ICoreWebView2Deferral** value);
114+
115+
116+
}
117+
118+
/// Receives `DragStarting` events.
119+
[uuid(3b149321-83c3-5d1f-b03f-a42899bc1c15), object, pointer_default(unique)]
120+
interface ICoreWebView2DragStartingEventHandler : IUnknown {
121+
/// Provides the event args for the corresponding event.
122+
HRESULT Invoke(
123+
[in] ICoreWebView2CompositionController5* sender,
124+
[in] ICoreWebView2DragStartingEventArgs* args);
125+
}
126+
127+
/// A continuation of the ICoreWebView2CompositionController4 interface.
128+
/// This interface includes an API which exposes the DragStarting event.
129+
[uuid(975d6824-6a02-5e98-ab7c-e4679d5357f4), object, pointer_default(unique)]
130+
interface ICoreWebView2CompositionController5 : IUnknown {
131+
/// Adds an event handler for the `DragStarting` event. `DragStarting` is
132+
/// a deferrable event that is raised when the WebView2 detects a drag started
133+
/// within the WebView2.
134+
/// WebView2's default drag behavior is to synchronously call DoDragDrop when
135+
/// it detects drag. This event's args expose the data WebView2 uses to call
136+
/// DoDragDrop to allow users to implement their own drag logic and override
137+
/// WebView2's.
138+
/// Handlers of this event must set the `Handled` event to true in order to
139+
/// override WebView2's default logic. When invoking drag logic asynchronously
140+
/// using a deferral, handlers must take care to follow these steps in order:
141+
/// * Invoke asynchronous drag logic
142+
/// * Set the event args `Handled` property true
143+
/// * Complete the deferral
144+
/// In the asynchronous case, WebView2 decides whether or not to invoke its
145+
/// default drag logic when the deferral completes. So the event args'
146+
/// `Handled` property must be true when the deferral is completed.
147+
HRESULT add_DragStarting(
148+
[in] ICoreWebView2DragStartingEventHandler* eventHandler,
149+
[out] EventRegistrationToken* token);
150+
151+
/// Removes an event handler previously added with `add_DragStarting`.
152+
HRESULT remove_DragStarting(
153+
[in] EventRegistrationToken token);
154+
155+
156+
}
157+
158+
/// Interop interface for the CoreWebView2CompositionController WinRT object to
159+
/// allow WinRT end developers to be able to access the COM interface arguments.
160+
/// This interface is implemented by the
161+
/// Microsoft.Web.WebView2.Core.CoreWebView2CompositionController runtime class.
162+
[uuid(7a4daef9-1701-463f-992d-2136460cf76e), object, pointer_default(unique)]
163+
interface ICoreWebView2CompositionControllerInterop3 : ICoreWebView2CompositionControllerInterop2 {
164+
/// Adds an event handler for the `DragStarting` event. `DragStarting` is
165+
/// raised when the WebView2 detects a drag started within the WebView2.
166+
/// This event can be used to override WebView2's default drag starting
167+
/// logic.
168+
HRESULT add_DragStarting(
169+
[in] ICoreWebView2DragStartingEventHandler* eventHandler,
170+
[out] EventRegistrationToken* token);
171+
172+
/// Removes an event handler previously added with `add_DragStarting`.
173+
HRESULT remove_DragStarting(
174+
[in] EventRegistrationToken token);
175+
176+
177+
}
178+
```

0 commit comments

Comments
 (0)