-
Notifications
You must be signed in to change notification settings - Fork 674
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
PointerExited event not always fired (when pointer captured) #1959
Comments
PointerExited should always fire if PointerEntered did, if it doesn't that's a bug.
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.uielement.pointerexited |
@benstevens48 definitely a bug if these events aren't paired. Can you give more detail on your specific configuration for this? I'm unable to reproduce this so far. To reproduce I tried setting up something like this:
I can never get the event counts to drift apart. Can you clarify what more is essential for the repro? |
@chrisglein - it actually seems to be related to pointer capture. Try this instead.
Click on the red square then drag outside the beige container and release. This is presumably due to the way pointer capture works. In my opinion the PointerExited event still needs to fire at some point though. Either when the pointer leaves the grid or when the pointer capture is released outside the grid (but in that case it would differ from the behavior of adding all the events to the containing grid itself so I'm not sure which is best - possibly you could change the behavior of PointerExited not to fire until pointer capture is lost even on the element that has pointer capture, because in a sense the pointer is still inside the element until then). |
Gotcha. Thanks for the details on that @benstevens48, much appreciated! |
@chrisglein - it turns out there are other scenarios when the PointerExited event does not fire. I have discovered this while trying to implement a drag and drop. Suppose we have a FrameworkElement A that undergoes the follow events: PointerEntered, PointerPressed, pointer capture is taken by some other FrameworkElement B outside element A, then the pointer is moved outside element A, then the pointer is released. The pointer exited event for element A is never fired. it should probably be fired at the point pointer capture is taken by element B. I would also like to confirm that in the previous scenario where a sub-element captures the pointer, it would make most sense for PointerExited not to fire when the pointer moves outside the sub-element if the element has pointer capture. The PointerExited event for the sub-element should fire on pointer capture lost instead (if the pointer is not over the sub-element at that point), This it because PointerMoved events still fire for the sub-element (which is essential for e.g. dragging), and one would expect PointerExited to fire after any PointerMoved events. Finally, I would like to mention that there are serious problems with the built-in drag and drop functionality regarding events like pointer released etc. It seems that at the time when dragstarting occurs, pointer capture is taken away from the app entirely. So even if you add pointer pressed and pointer released event handlers to the core window, you will not see a pointer released event when the drag completes (and possibly this includes when the dragstarting is canceled - I can't remember). In my opinion, it ought to be possible to determine when the pointer is released. I struggled for a very long time working out the sequence of events and what is being given pointer capture (if you add CanDrag to an element then it will be given pointer capture on PointerPressed or something which will then be taken away on dragstarting), and which events fire and which events are missed out, and along with trying to deal with this bug #1540, which occurs if you set CanDrag to false between PointerPressed and DragStarting, it ended up taking my entire day and was somewhat frustrating! At the very least it would be nice if the sequence of pointer events that occur when doing drag and drop could be documented. |
Also, this doesn't just apply to mouse (I don't know if the 'area-Mouse' label added to this issue includes touch as well), because the PointerEntered and Exited events will fire for touch too (when in contact). |
This behavior is called out in the docs:
|
@Felix-Dev OK, but we need an event that is guaranteed to fire after pointer entered else how are we supposed to do things like set a different cursor or visual state on hover? If pointer exited never fires then the cursor or visual state will be changed permanently. The quote you mentioned seems to be in contradiction to the following quote lower down the page.
|
I don't think there is a contradiction here:
The case mentioned in the docs above is about another element capturing the pointer, and not one of the UI state changes listed in the paragraph you are quoting. |
Ok, well regardless of what it says in the docs there needs to be a reliable way of changing visual state and cursor on hover without the change being permanent. |
Is this going to be fixed in WinUI 3? This is a serious flaw regardless what docs say. |
I can confirm this happens (PointerExited event not fired), even when the mouse is NOT captured. I capture PointerExited on the left. It's sent probably 5% of the time. The workaround for me is to capture PointerEntered for the right pane. It's quite sad. LATER EDIT: Let me be clear: nor PointerCancelled, nor PointerCaptureLost events are raised |
Need to check this has been fixed in WinUI3. Would also be good if it was fixed in system XAML. |
If I mouse over a control (so PointerEntered is fired), press, then drag outside the control, the PointerExited event does not fire in at least some cases. I didn't spend a long time testing but it definitely occurs when ManipulationStarted is triggered (and maybe even if not - I didn't test it). It would be useful if we could guarantee the PointerExited event fires. This is important because, for example, we might change the cursor or control style when the pointer is over a specific elements etc, and without this event firing the change is permanent. (It would also be useful if controls had IsPointerOver and IsPointerPressed properties, but that's another issue). The PointerExited event should probably fire when the pointer is released outside the control and also if the control is unloaded before the pointer leaves the control. I assume all built-in controls use the PointerEntered/Exited events for transitioning to/from the PointerOver visual state, so this bug potentially effects that as well.
Also, it would be nice if PointerReleased was always called after PointerPressed, rather than having to listen to PointerReleased, PointerCanceled and PointerCaptureLost (I think all 3 are necessary currently), but maybe that's necessary due to the design of pointer capture and manipulation.
I've put together the following workaround which provides the desired behaviour (if you listen to its IsPointerOverChanged event), but it would be good if I didn't need this workaround - https://github.com/Pictureflect/pictureflect-parital-source/blob/master/PictureflectPartialSource/PointerOverManager.cs.
The text was updated successfully, but these errors were encountered: