Skip to content

Commit d496de8

Browse files
authored
Merge pull request #497 from MicrosoftEdge/api-systemcursorid
Api SystemCursorId
2 parents 718ab38 + 0275700 commit d496de8

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

specs/SystemCursorId.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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, the `ICoreWebView2CompositionController.Cursor` property returns what
8+
the cursor should be as an HCURSOR object, which the hosting application can
9+
then use the 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+
// Handler for WM_SETCURSOR window message.
38+
bool OnSetCursor()
39+
{
40+
POINT point;
41+
if (m_compositionController && GetCursorPos(&point))
42+
{
43+
// Calculate if the point lies in the WebView visual for composition hosting
44+
// as it may not cover the whole HWND it's under.
45+
if (PtInRect(&m_webViewBounds, point))
46+
{
47+
HCURSOR cursor;
48+
UINT32 cursorId;
49+
wil::com_ptr<ICoreWebView2CompositionController2> compositionController2 =
50+
m_compositionController.query<ICoreWebView2CompositionController2>();
51+
CHECK_FAILURE(compositionController2->get_SystemCursorId(&cursorId));
52+
cursor = ::LoadCursor(nullptr, MAKEINTRESOURCE(cursorId));
53+
54+
if (cursor)
55+
{
56+
::SetCursor(cursor);
57+
return true;
58+
}
59+
}
60+
}
61+
return false;
62+
}
63+
64+
CHECK_FAILURE(m_compositionController->add_CursorChanged(
65+
Callback<ICoreWebView2CursorChangedEventHandler>(
66+
[this](ICoreWebView2CompositionController* sender, IUnknown* args)
67+
-> HRESULT {
68+
// No need to do hit testing here as the WM_SETCURSOR handler will have
69+
// to calculate if the point is within the WebView anyways.
70+
SendMessage(m_appWindow->GetMainWindow(), WM_SETCURSOR,
71+
(WPARAM)m_appWindow->GetMainWindow(), MAKELPARAM(HTCLIENT, WM_MOUSEMOVE));
72+
return S_OK;
73+
})
74+
.Get(),
75+
&m_cursorChangedToken));
76+
77+
78+
# API Notes
79+
80+
See [API Details](#api-details) section below for API reference.
81+
82+
83+
# API Details
84+
85+
```cpp
86+
/// This interface is continuation of the
87+
/// ICoreWebView2CompositionController interface.
88+
[uuid(279ae616-b7cb-4946-8da3-dc853645d2ba), object, pointer_default(unique)]
89+
interface ICoreWebView2CompositionController2 : ICoreWebView2CompositionController {
90+
/// The current system cursor ID reported by the underlying rendering engine
91+
/// for WebView. For example, most of the time, when the cursor is over text,
92+
/// this will return the int value for IDC_IBEAM. The systemCursorId is only
93+
/// valid if the rendering engine reports a default Windows cursor resource
94+
/// value. See:
95+
/// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadcursorw
96+
/// Otherwise, if custom CSS cursors are being used, this will return 0.
97+
/// To actually use systemCursorId in LoadCursor or LoadImage,
98+
/// MAKEINTRESOURCE must be called on it first.
99+
/// If possible, use the Cursor property rather than the SystemCursorId
100+
/// property because the Cursor property can express custom CSS cursors.
101+
///
102+
/// \snippet ViewComponent.cpp SystemCursorId
103+
[propget] HRESULT SystemCursorId([out, retval] UINT32* systemCursorId);
104+
}
105+
```
106+
107+
```c#
108+
namespace Microsoft.Web.WebView2.Core
109+
{
110+
//
111+
// Summary:
112+
// This class is an extension of the CoreWebView2CompositionController class to support composition
113+
// hosting.
114+
public class CoreWebView2CompositionController2
115+
{
116+
//
117+
// Summary:
118+
// The current system cursor ID that WebView thinks it should be.
119+
//
120+
// Remarks:
121+
// The current system cursor ID reported by the underlying rendering engine
122+
// for WebView. For example, most of the time, when the cursor is over text,
123+
// this will return the int value for IDC_IBEAM. The SystemCursorId is only
124+
// valid if the rendering engine reports a default Windows cursor resource
125+
// value. See:
126+
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadcursorw
127+
// Otherwise, if custom CSS cursors are being used, this will return 0.
128+
// To create a Cursor object, create an IntPtr from the returned uint to
129+
// pass into the constructor
130+
// If possible, use the Cursor property rather than the SystemCursorId
131+
// property because the Cursor property can express custom CSS cursors.
132+
public Uint32 SystemCursorId { get; }
133+
}
134+
}
135+
```
136+
137+
# Appendix
138+
139+
I expect that most apps will use the get_Cursor API which returns an HCURSOR (Or
140+
the UWP equivalent that will be implemented in the future that will return a
141+
CoreCursor) outside of Office as HCURSOR is more comprehensive and covers the
142+
scenarios in which custom cursors are used.

0 commit comments

Comments
 (0)