-
Notifications
You must be signed in to change notification settings - Fork 743
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
Pointer Events not Invoked within ScrollViewer #4520
Comments
@dr1rrb Does it look familiar ? |
@robloo just to better understand, here you are trying to listen for pointer event directly on the |
@dr1rrb There have been some updates in understanding since this was first written. There are a few different cases where this issue is appearing (outlined below). The original issue is as described: A canvas was inside a ScrollViewer and the ScrollViewer was managing pan/zoom (which didn't seem to work). Then there were additional zoom buttons directly on top of the ScrollViewer + Canvas and the Click event also didn't work there. Since this issue was filed a ScrollViewer is no longer used in this portion of the UI. Instead, SKSwapChainPanel is used for rendering and overlaid directly on top is a Canvas to capture input and overtop yet again are buttons. Zoom and pan is then all calculated internally based on inputs. However, input events don't work at all (case 1).
XAML<Grid>
<!-- The skia canvas must have a non-zero size to trigger drawing events -->
<skia:SKSwapChainPanel
x:Name="DiagramSkiaCanvas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MinWidth="1"
MinHeight="1" />
<Canvas
x:Name="DiagramCanvas"
Background="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<Border
Background="White"
CornerRadius="0,0,12,0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<StackPanel
Orientation="Horizontal"
Margin="5">
<RepeatButton
x:Name="ZoomInButton"
Width="32"
Height="32"
CornerRadius="8,0,0,8"
Padding="0">
<RepeatButton.Content>
<FontIcon
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="20"
Glyph="" />
</RepeatButton.Content>
</RepeatButton>
<RepeatButton
x:Name="ZoomOutButton"
Width="32"
Height="32"
CornerRadius="0,8,8,0"
Padding="0">
<RepeatButton.Content>
<FontIcon
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="20"
Glyph="" />
</RepeatButton.Content>
</RepeatButton>
</StackPanel>
</Border>
</Grid>
|
@robloo I've tried to repro in a sample app (PtInScroll.zip), but I was unable to repro your issue When tapping directly on the
And when I tap on the
(The issue in that log is that I should not have receive the "exit" on the BTW if I remove the
And even if I add a |
@dr1rrb Interesting, I'll get more details ASAP and hopefully a repro. My guess is now that this has something to do with UserControls. Each case above occurs within a UserControl (the XAML example was heavily simplified).
The reason a Canvas is used in the App itself is not only for pointer input (although that is all that is relevant here). It also shows indicator guides for some of the charts. It is more efficient to render guides that move with the cursor on a canvas as a different layer than re-rendering the entire chart when the cursor moves. |
I found the root-cause enough to stop investigating. It isn't that this Xaml is within UserControls; it's that each of these controls was using a Loading control from the UWP community toolkit on top of everything else. That loading control doesn't work correctly with Uno and it was causing some yet-unknown issue with input. Apologies for not noticing earlier that the toolkit loading indicator was the issue. As it is entirely invisible in this error-state and should have been collapsed the thought didn't occur that it might be stealing input. The work around is simply to stop using the toolkit Loading control (that was planned anyway). As you don't support most toolkit controls this aspect is likely not worth further investigation. There were still more minor issues found with the latest testing though:
Separately, I'm getting crashes on PointerPressed now that input is working better over some controls. I'll have to investigate that separately but zoom in/out buttons over canvas (case 2 also works). |
@robloo You are facing what I usually refer as "the
If you want to take priority over the |
I have tested this again and Uno behaves differently than UWP. Although, I'm not sure if UWP is changing behavior for a touch screen in this case (I'm not testing with touch on desktop and have no experience with that). In UWP, if I have captured the pointer on a custom control within PointerPressed, moving the pointer up/down while continuing to press does not start a scroll. Releasing the pointer will fire events as expected. In Uno, as you said, capturing the pointer within a PointerPressed and then moving the pointer up/down will start scrolling and ignore the capture. PointerReleased/Exited are not invoked. Now, there is a good reason for this difference as you explained. The UWP app is running on a desktop and not being interacted with directly. It is much more intuitive on a desktop to scroll the mouse wheel or use the scroll bar. On a touch-first device I agree it is more intuitive for touch interactions up/down to start a scroll. Whether a button or a custom control, you can't have scrolling disabled as soon as PointerPressed is invoked as the user would just think things are broken. In my case it would actually disable scrolling from most places as most elements within the scrollviewer are interactive to some degree - so Uno is actually helping. That said, unless UWP modifies it's behavior in this case for touch, there is a difference and it probably should be documented some place in Uno if it's not already. I'll do more testing to see if I get the PointerCancelled event as you recommend and that should solve this particular issue.
I don't assume I get a PointerReleased for every PointerPressed; however, I do assume I get a PointerExited for every PointerEntered. In Microsoft's docs here it explicitly states "PointerExited is fired for any case where the pointer had at one time fired a PointerEntered event, but some UI state change happens where the pointer is no longer within that element." You are correct the events are not always paired and we discussed that a while ago in microsoft/microsoft-ui-xaml#1959. Microsoft agrees it's a bug though if PointerExited isn't invoked. Again, however, in UWP this code works correctly. It is only within the Uno Platform that the ScrollViewer is stealing the pointer and not firing the PointerExited or PointerReleased events. So the question is, did you test this specifically with touch interaction on UWP? Otherwise, I think there is a difference and Uno really should fire PointerExited as soon as the ScrollViewer steals focus. Thanks a lot for continuing to follow-up with this! |
@dr1rrb In both cases we were loosely discussing above, Uno invokes the PointerCaptureLost when the ScrollViewer steals focus. This allows me to clean things up correctly. Note that PointerCancelled is never invoked though. I still had to change the code from UWP so am not entirely sure behavior is the same. However, as mentioned above, I have never tested the base UWP on a touch device so it's also entirely possible it behaves the same there. I defer to your judgement on this. If it looks good to you (and I'm assuming it does based on no further comments) then it's good enough for me. You have a lot more experience with this and I trust your testing more than mine :) For all the issues discussed here I now have solutions so I'm closing this. Thanks a lot for taking a look! |
Hi @robloo, yes pointers with a touch device are signifcantly different than a mouse or a touchpad (what I assume you are testing with). A touchpad is really handled like a mouse, and if you "scroll" using 2 fingers for instance, it's actually raising some I've validated on my surface, and I confirm that, as arguable as it could be, we only get a
|
Current behavior
I have a ScrollViewer hosting a canvas control as the content. The Canvas seems to be rendered just fine inside the ScrollViewer. However, I cannot zoom or pan within the ScrollViewer. Zoom is handled by Buttons overtop of the ScrollViewer and pan is handled by UIElement Pointer events that should be coming from the ScrollViewer itself. However, none of the events work -- not even the zoom Button Click events.
Expected behavior
How to reproduce it (as minimally and precisely as possible)
Workaround
None found so far.
Environment
Nuget Package:
Nuget Package Version(s): 3.2.0
Affected platform(s):
IDE:
Relevant plugins:
Anything else we need to know?
The text was updated successfully, but these errors were encountered: