-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API Review: DragStarting Event API #4900
Changes from 7 commits
b2b2634
74e7ca0
ec4af35
d7bfa12
58f6596
042c2b4
8c06cb6
b3dc1e3
8a4130a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
DragStarting | ||
=== | ||
|
||
# Background | ||
The WebView2 team has been asked to provide a way to override the default drag | ||
drop behavior when running in visual hosting mode. This event allows you to know | ||
when a drag is initiated in WebView2 and provides the state necessary to override | ||
the default WebView2 drag operation with your own logic. | ||
|
||
## Note about .NET/WinRT projection | ||
The work to project this API to .NET and WinRT are yet to be completed. Overall | ||
usage of this API is expected to be uncommon. There are no known public asks for | ||
this. Further, this API is exposed on the CompositionController which is very | ||
rarely used in .NET apps. | ||
|
||
# Examples | ||
## DragStarting | ||
Users can use `add_DragStarting` on the CompositionController to add an event | ||
handler that is invoked when drag is starting. They can use the the event args | ||
to start their own drag. Notably the `Deferral` can be used to execute any async | ||
drag logic and call back into the WebView at a later time. The `Handled` | ||
property lets the WebView2 know whether to exercise its own drag logic or not. | ||
|
||
## Override drag and drop | ||
```C++ | ||
// Using DragStarting to simply make a synchronous DoDragDrop call instead of | ||
// having WebView2 do it. | ||
CHECK_FAILURE(m_compController5->add_DragStarting( | ||
Callback<ICoreWebView2DragStartingEventHandler>( | ||
[this](ICoreWebView2CompositionController5* sender, | ||
ICoreWebView2DragStartingEventArgs* args) | ||
{ | ||
COREWEBVIEW2_DRAG_EFFECTS allowedEffects = | ||
COREWEBVIEW2_DRAG_EFFECTS_NONE; | ||
POINT dragPosition = {0, 0}; | ||
wil::com_ptr<IDataObject> dragData; | ||
|
||
CHECK_FAILURE(args->get_AllowedOperations(&allowedEffects)); | ||
CHECK_FAILURE(args->get_Position(&dragPosition)); | ||
CHECK_FAILURE(args->get_Data(&dragData)); | ||
|
||
if (!m_dropSource) | ||
{ | ||
m_dropSource = Make<ScenarioDragDropOverrideDropSource>(); | ||
johna-ms marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
DWORD effect; | ||
DWORD okEffects = DROPEFFECT_NONE; | ||
if (allowedEffects & COREWEBVIEW2_DRAG_EFFECTS_COPY) | ||
{ | ||
okEffects |= DROPEFFECT_COPY; | ||
} | ||
if (allowedEffects & COREWEBVIEW2_DRAG_EFFECTS_MOVE) | ||
{ | ||
okEffects |= DROPEFFECT_MOVE; | ||
} | ||
if (allowedEffects & COREWEBVIEW2_DRAG_EFFECTS_LINK) | ||
{ | ||
okEffects |= DROPEFFECT_LINK; | ||
} | ||
|
||
HRESULT hr = DoDragDrop( | ||
dragData.get(), m_dropSource.get(), okEffects, &effect); | ||
|
||
args->put_Handled(SUCCEEDED(hr)); | ||
|
||
return hr; | ||
}) | ||
.Get(), | ||
&m_dragStartingToken)); | ||
``` | ||
|
||
## Disable drag and drop | ||
```C++ | ||
// Using DragStarting to no-op a drag operation. | ||
CHECK_FAILURE(m_compController5->add_DragStarting( | ||
Callback<ICoreWebView2DragStartingEventHandler>( | ||
[this](ICoreWebView2CompositionController5* sender, | ||
ICoreWebView2DragStartingEventArgs* args) | ||
{ | ||
// If the event is marked handled, WebView2 will not execute its | ||
// drag logic. | ||
args->put_Handled(TRUE); | ||
return S_OK; | ||
}) | ||
.Get(), | ||
&m_dragStartingToken)); | ||
``` | ||
|
||
# API Details | ||
```C++ | ||
/// Flags enum that represents the effects that a given WebView2 drag drop | ||
/// operation can have. The values of this enum align with the ole DROPEFFECT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a link to any public doc here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please fix. (Also ole -> OLE) |
||
/// constant with the exception of DROPEFFECT_SCROLL which is only relevant for | ||
/// drop and therefore unsupported. | ||
[v1_enum] | ||
typedef enum COREWEBVIEW2_DRAG_EFFECTS { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing CompositionController APIs for DragEnter, DragOver, and Drop use DWORD* for the DROPEFFECT. Should we follow that existing pattern? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes let's use a DWORD here. It simplifies expected usage of the API and is consistent with our existing drag/drop WebView2 APIs. |
||
/// Drag operation supports no effect. | ||
COREWEBVIEW2_DRAG_EFFECTS_NONE = 0x0, | ||
/// Drag operation supports copying data. | ||
COREWEBVIEW2_DRAG_EFFECTS_COPY = 0x1, | ||
/// Drag operation supports moving data. | ||
COREWEBVIEW2_DRAG_EFFECTS_MOVE = 0x2, | ||
/// Drag operation supports linking data. | ||
COREWEBVIEW2_DRAG_EFFECTS_LINK = 0x4, | ||
} COREWEBVIEW2_DRAG_EFFECTS; | ||
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(COREWEBVIEW2_DRAG_EFFECTS)") | ||
|
||
/// Event args for the `DragStarting` event. | ||
[uuid(edb6b243-334f-59d0-b3b3-de87dd401adc), object, pointer_default(unique)] | ||
interface ICoreWebView2DragStartingEventArgs : IUnknown { | ||
johna-ms marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// The operations this drag data supports. | ||
[propget] HRESULT AllowedOperations( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please change to |
||
[out, retval] COREWEBVIEW2_DRAG_EFFECTS* value); | ||
|
||
|
||
/// The data being dragged. | ||
[propget] HRESULT Data([out, retval] IDataObject** value); | ||
|
||
/// The position at which drag was detected. This position is given in | ||
/// screen pixel coordinates as opposed to WebView2 relative coordinates. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update docs to explain DPI story. It should be WebView2 client coord space like what DragOver does |
||
[propget] HRESULT Position([out, retval] POINT* value); | ||
johna-ms marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
/// Gets the `Handled` property. | ||
[propget] HRESULT Handled([out, retval] BOOL* value); | ||
|
||
|
||
/// Indicates whether this event has been handled by the app. If the | ||
/// app handles this event, WebView2 will not initiate drag drop. If | ||
/// the app does not handle the event, WebView2 will initiate its own | ||
/// drag drop logic. The default value is FALSE. | ||
[propput] HRESULT Handled([in] BOOL value); | ||
|
||
|
||
|
||
/// Returns an `ICoreWebView2Deferral` object. Use this operation to complete | ||
/// the CoreWebView2DragStartingEventArgs. | ||
/// | ||
/// Until the deferral is completed, subsequent attempts to initiate drag | ||
/// in the WebView2 will fail and if the cursor was changed as part of | ||
/// drag it will not restore. | ||
HRESULT GetDeferral( | ||
[out, retval] ICoreWebView2Deferral** value); | ||
|
||
|
||
} | ||
|
||
/// Receives `DragStarting` events. | ||
[uuid(3b149321-83c3-5d1f-b03f-a42899bc1c15), object, pointer_default(unique)] | ||
interface ICoreWebView2DragStartingEventHandler : IUnknown { | ||
/// Provides the event args for the corresponding event. | ||
HRESULT Invoke( | ||
[in] ICoreWebView2CompositionController5* sender, | ||
[in] ICoreWebView2DragStartingEventArgs* args); | ||
} | ||
|
||
/// A continuation of the ICoreWebView2CompositionController4 interface. | ||
/// This interface includes an API which exposes the DragStarting event. | ||
[uuid(975d6824-6a02-5e98-ab7c-e4679d5357f4), object, pointer_default(unique)] | ||
interface ICoreWebView2CompositionController5 : IUnknown { | ||
/// Adds an event handler for the `DragStarting` event. `DragStarting` is | ||
/// raised when the WebView2 detects a drag started within the WebView2. | ||
/// WebView2's default drag behavior is to synchronously call DoDragDrop when | ||
/// it detects drag. This event's args expose the data WebView2 uses to call | ||
/// DoDragDrop to allow users to implement their own drag logic and override | ||
/// WebView2's. | ||
johna-ms marked this conversation as resolved.
Show resolved
Hide resolved
|
||
HRESULT add_DragStarting( | ||
[in] ICoreWebView2DragStartingEventHandler* eventHandler, | ||
[out] EventRegistrationToken* token); | ||
|
||
/// Removes an event handler previously added with `add_DragStarting`. | ||
HRESULT remove_DragStarting( | ||
[in] EventRegistrationToken token); | ||
|
||
|
||
} | ||
|
||
/// Interop interface for the CoreWebView2CompositionController WinRT object to | ||
/// allow WinRT end developers to be able to access the COM interface arguments. | ||
/// This interface is implemented by the | ||
/// Microsoft.Web.WebView2.Core.CoreWebView2CompositionController runtime class. | ||
[uuid(7a4daef9-1701-463f-992d-2136460cf76e), object, pointer_default(unique)] | ||
interface ICoreWebView2StagingCompositionControllerInterop : IUnknown { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please fix. |
||
/// Adds an event handler for the `DragStarting` event. `DragStarting` is | ||
/// raised when the WebView2 detects a drag started within the WebView2. | ||
/// This event can be used to override WebView2's default drag starting | ||
/// logic. | ||
HRESULT add_DragStarting( | ||
[in] ICoreWebView2StagingDragStartingEventHandler* eventHandler, | ||
[out] EventRegistrationToken* token); | ||
|
||
/// Removes an event handler previously added with `add_DragStarting`. | ||
HRESULT remove_DragStarting( | ||
[in] EventRegistrationToken token); | ||
|
||
|
||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix