Skip to content

ScrollViewer children are silently losing pointer events after PointerExited with pen & touch #9290

Open

Description

Describe the bug

I'm implementing an item selection experience inside a ScrollViewer and have noticed some quirks with capturing the pointer and working around the ScrollViewer manipulation processing with pen & touch.

First, my child item needs PointerPresed, PointerMoved, and PointerReleased/PointerCaptureLost at a minimum. To get this working with mouse, I capture the pointer in the PointerPressed event and that ensures I still get Move & Released/Lost events outside the bounds of the child. With pen & touch, I had the additional requirement to listen for DirectManipulationStarted on the ScrollViewer parent and when that happens during a selection session, I call CancelDirectManipulations on the parent. This works great! Except, if the pointer leaves the child during the selection session, it gets the Exited event and then nothing else until the pointer returns inside its bounds. It's unclear exactly where the pointer capture is going because CaptureLost or CaptureCanceled aren't fired and neither is the DirectManipulationStarted. I can work around this issue be explicitly re-capturing the pointer in the PointerExited if I need to, but it's odd that this is necessary.

I've also found that this isn't a problem when the ScrollViewer doesn't have enough content to actually scroll, but as soon as it does this problem repros.

Steps to reproduce the bug

  1. Create a WinUI 3 C++/WinRT project (WASDK Version 1.3.230602002 if that helps)
  2. To the MainWindow, add a ScrollViewer containing a StackPanel, which in turn contains a Canvas and some filler Rectangles to ensure the ScrollViewer has enough to scroll through.
  3. On the Canvas, register for all the relevant pointer events. Define a selection "session" with an enum or bool that starts OnPressed and ends OnReleased/OnCaptureLost. Also in the Pressed handling, call CapturePointer(args.Pointer()).
  4. On the ScrollViewer, register for DirectManipulationStarted. Define a handler to invoke CancelDirectManipulations if a selection session is active.
  5. With pen or touch, press in the bounds of the Canvas and drag outside the bounds.

Expected behavior

Expected: Since the pointer is captured, you'd keep getting pointer events after OnExited.
Actual: You stop getting pointer events after OnExited until the pointer re-enters the bounds.

Screenshots

No response

NuGet package version

None

Windows version

No response

Additional context

There's also another problem where Tapped events with pen/touch also fire a single Moved between the Pressed & Released, but that's not a problem here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions