|
| 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