microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.33k stars 675 forks source link

Click WebView2 on UWP may hide cursor #6168

Closed zhuxinghan closed 2 years ago

zhuxinghan commented 2 years ago

Describe the bug

I combine WebView2 and native controls in my UWP app. When users click within WebView2, I show some native controls as overlay to let users do something. But I find that that's very likely that clicks in WebView2 may cause mouse cursor to hide, that's fine if I only use WebView2 because users can move the mouse and the cursor will reappear. But since I show an overlay as response to user click, and the overlay prevents cursor to appear, so when this happens, users can't see cursor on native control overlay anymore. I created a minimum project that can reproduce the problem: WebView2HideCursorOnNativeControls.zip

I have tested similar code with WinUI3 and it seems not have the same problem.

Steps to reproduce the bug

  1. Open the project I provided above. In the MainPage, there are a WebView2 and a rectangle on it, but the rectangle is initially hidden. The WebView2 is navigated to a simple string and has a Tapped handler.
  2. Click the WebView2, you can find the cursor may disappear, but when you moves mouse, the cursor will appear again. When you click the WebView2 content for more that 3 times, the handler shows the rectangle to mimic an overlay that lets users do something. At this time, cursor will not appear even if you move the mouse.
  3. The problem may not be 100% reproduceable. Sometimes it's fine.

Screenshots

动画

NuGet package version

2.8 prerelease

Windows app type

Additional context

I'm using Windows 11 22000.282

StephenLPeters commented 2 years ago

@krschau @codendone @jevansaks and @predavid FYI

jevansaks commented 2 years ago

I debugged the app and the problem is that while the mouse is over the control you are making another control visible over top of the WebView2. This means the WebView2 doesn’t get mouse messages anymore and so we never see the PointerLeave event and we’re unable to restore the cursor back to the way it should be.

The way we have to do the cursor for WebView2 in UWP is fragile (as you can see here), but hopefully we can suggest a different approach that doesn't run afoul of this problem.

For example if all you want to do is overlay some UI over top but not have it be interactive (as in your repro) then you can put IsHitTestVisible="false" on the Rectangle and it will work again.

If your real scenario is more complicated, please describe what your goal is and I can try to assist.

zhuxinghan commented 2 years ago

My scenario is when user click image in WebView2, the app shows a FlipView over WebView2 to provide an image carousel. Though I can use web technology to make an image carousel within WebView2, but native image control and carousel provides better performance and interactivity and I wouldn't like to change web content. I can see same scenario from some other UWP apps, such as some news apps, they use WebView (haven't migrate to WebView2) to display news articles, and if users click images within article, they shows a native image carousel over WebView.

When I used to use legacy EdgeHTML WebView, this scenario works fine. Recently I find WebView2 provides more useful API than WebView, so I migrate to WebView2 and encounter problems like this one.

I can understand that when native control overlays WebView2, it no longer receive mouse event. But I noticed that the hidden of cursor happens before the shown of native control. You can see from the screenshot gif, the first three clicks don't show the rectangle, only the fourth click shows the rectangle. The first click is good, but the second and the third click hide the cursor without showing the rectangle.

So the problems is when click WebView2, it may hide cursor. If nothing overlay WebView2, any mouse move will make cursor appear again, but if the click on WebView2 insert a native control between WebView2 and cursor, WebView2 will no longer receive mouse move event and it can't make cursor reappear. It isn't the native control who hide the cursor, native control only prevents cursor reappear.

The error is why click WebView2 may hide cursor? If cursor doesn't hide after click, then there will be no problem.

zhuxinghan commented 2 years ago

@jevansaks your reply inspired me, I can add these code when shows the rectangle, and the cursor will be sure to appear again on the rectangle:

FrameworkElementExtensions.SetCursor(rectangle, CoreCursorType.Hand);
FrameworkElementExtensions.SetCursor(rectangle, CoreCursorType.Arrow);

The code uses UWP Community Toolkit. You must first set the cursor to another type other than Arrow, then to Arrow.

But anyway, if the problem can be solved from WebView2 itself, that wouldn't be better.

jevansaks commented 2 years ago

Oh ... wait I think I might see the bug. In ResetPointerHelper we don't set m_isPointerOver back to false. Let me try that.

jevansaks commented 2 years ago

@zhuxinghan I believe I've fixed this, it works now with the repro you shared. Can you try the nuget package from my PR: https://dev.azure.com/ms/_apis/resources/Containers/15043044/drop?itemPath=drop%2FMicrosoft.UI.Xaml.2.8.0-pr.211112001.nupkg ?

zhuxinghan commented 2 years ago

@jevansaks that's great! I don't know how to use that package, it seems that I have no permission to access it, but I believe the issue was solved. I will wait for the fix to be released, and for now, I just use my workaround. Thank you again!

exotexot commented 1 year ago

I have a similar issue using WebView2 in UWP as a react native app.

Cursor is constantly hiding while clicking...

https://github.com/react-native-webview/react-native-webview/issues/3093