|
| 1 | +# Background |
| 2 | + |
| 3 | +When an app is using composition hosting to host WebView, the current cursor |
| 4 | +image cannot be determined easily by the hosting application. For example, if |
| 5 | +the cursor over the WebView is also over a textbox inside of the WebView, the |
| 6 | +cursor should usually be IDC_IBEAM. And by default, the cursor is IDC_ARROW. |
| 7 | +Currently, we return the what the cursor should be as an HCURSOR object (After |
| 8 | +calling LoadCursor on those IDC values). The hosting application can then use |
| 9 | +the HCURSOR object to change the current cursor to the correct image. |
| 10 | + |
| 11 | +However, Office already has a well established way of using cursors internally |
| 12 | +by using IDC_* values and there is no easy way to convert the HCURSOR object we |
| 13 | +are returning into an IDC value after it's been created. |
| 14 | + |
| 15 | +This new API is to enable hosting applications like Office to get the current |
| 16 | +IDC value of the cursor instead of the HCURSOR as an option. |
| 17 | + |
| 18 | +Note that this is a COM and .NET spec as WinRT uses a separate enum structure to |
| 19 | +identify cursor IDs. |
| 20 | + |
| 21 | + |
| 22 | +# Description |
| 23 | + |
| 24 | +The `SystemCursorId` property will return the current system cursor ID reported |
| 25 | +by the underlying rendering engine for WebView2. It is not meant to return a |
| 26 | +value for any custom cursors, such as those defined by CSS. |
| 27 | + |
| 28 | +It can be used at any time but will only change after a `CursorChanged` event. |
| 29 | + |
| 30 | +Note that developers should generally use the `Cursor` property to support cases |
| 31 | +where there may be custom cursors. |
| 32 | + |
| 33 | + |
| 34 | +# Examples |
| 35 | + |
| 36 | +```cpp |
| 37 | +CHECK_FAILURE(m_compositionController->add_CursorChanged( |
| 38 | + Callback<ICoreWebView2ExperimentalCursorChangedEventHandler>( |
| 39 | + [this](ICoreWebView2ExperimentalCompositionController* sender, IUnknown* args) |
| 40 | + -> HRESULT { |
| 41 | + HRESULT hr = S_OK; |
| 42 | + HCURSOR cursor; |
| 43 | + UINT32 cursorId; |
| 44 | + wil::com_ptr<ICoreWebView2ExperimentalCompositionController2> compositionController2 = |
| 45 | + m_controller.query<ICoreWebView2ExperimentalCompositionController2>(); |
| 46 | + CHECK_FAILURE(compositionController2->get_SystemCursorId(&cursorId)); |
| 47 | + cursor = ::LoadCursor(nullptr, MAKEINTRESOURCE(cursorId)); |
| 48 | + if (cursor == nullptr) |
| 49 | + { |
| 50 | + hr = HRESULT_FROM_WIN32(GetLastError()); |
| 51 | + } |
| 52 | + |
| 53 | + if (SUCCEEDED(hr)) |
| 54 | + { |
| 55 | + SetClassLongPtr( |
| 56 | + m_appWindow->GetMainWindow() /* HWND */, GCLP_HCURSOR, (LONG_PTR)cursor); |
| 57 | + } |
| 58 | + return hr; |
| 59 | + }) |
| 60 | + .Get(), |
| 61 | + &m_cursorChangedToken)); |
| 62 | + |
| 63 | + |
| 64 | +# API Notes |
| 65 | + |
| 66 | +See [API Details](#api-details) section below for API reference. |
| 67 | + |
| 68 | + |
| 69 | +# API Details |
| 70 | + |
| 71 | +```cpp |
| 72 | +/// This interface is continuation of the |
| 73 | +/// ICoreWebView2CompositionController interface. |
| 74 | +[uuid(279ae616-b7cb-4946-8da3-dc853645d2ba), object, pointer_default(unique)] |
| 75 | +interface ICoreWebView2CompositionController2 : ICoreWebView2CompositionController { |
| 76 | + /// The current system cursor ID reported by the underlying rendering engine |
| 77 | + /// for WebView. For example, most of the time, when the cursor is over text, |
| 78 | + /// this will return the int value for IDC_IBEAM. The systemCursorId is only |
| 79 | + /// valid if the rendering engine reports a default Windows cursor resource |
| 80 | + /// value. See: |
| 81 | + /// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadcursorw |
| 82 | + /// Otherwise, if custom CSS cursors are being used, this will return 0. |
| 83 | + /// To actually use systemCursorId in LoadCursor or LoadImage, |
| 84 | + /// MAKEINTRESOURCE must be called on it first. |
| 85 | + /// |
| 86 | + /// \snippet ViewComponent.cpp SystemCursorId |
| 87 | + [propget] HRESULT SystemCursorId([out, retval] UINT32* systemCursorId); |
| 88 | +} |
| 89 | + |
| 90 | +```c# |
| 91 | +namespace Microsoft.Web.WebView2.Core |
| 92 | +{ |
| 93 | + // |
| 94 | + // Summary: |
| 95 | + // This class is an extension of the CoreWebView2CompositionController class to support composition |
| 96 | + // hosting. |
| 97 | + public class CoreWebView2CompositionController2 |
| 98 | + { |
| 99 | + // |
| 100 | + // Summary: |
| 101 | + // The current system cursor ID that WebView thinks it should be. |
| 102 | + // |
| 103 | + // Remarks: |
| 104 | + // The current system cursor ID reported by the underlying rendering engine |
| 105 | + // for WebView. For example, most of the time, when the cursor is over text, |
| 106 | + // this will return the int value for IDC_IBEAM. The SystemCursorId is only |
| 107 | + // valid if the rendering engine reports a default Windows cursor resource |
| 108 | + // value. See: |
| 109 | + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadcursorw |
| 110 | + // Otherwise, if custom CSS cursors are being used, this will return 0. |
| 111 | + // To create a Cursor object, create an IntPtr from the returned uint to |
| 112 | + // pass into the constructor |
| 113 | + public Uint32 SystemCursorId { get; } |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | +# Appendix |
| 118 | + |
| 119 | +I expect that most apps will use the get_Cursor API which returns an HCURSOR (Or |
| 120 | +the UWP equivalent that will be implemented in the future that will return a |
| 121 | +CoreCursor) outside of Office as HCURSOR is more comprehensive and covers the |
| 122 | +scenarios in which custom cursors are used. |
0 commit comments