microsoft / microsoft/microsoft-ui-xaml
Mouse cursor flicker with windowed popup
- Dominant language
- C++
- Stars
- 8.4k
- Forks
- 942
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 105
Description
### Describe the bug
In an unpackaged WinUI 3 desktop app, a windowed Popup (ShouldConstrainToRootBounds="False")
is sized by its content and has thin edge/corner grips that resize it on drag by setting the
content's Width/Height, plus the Popup's HorizontalOffset/VerticalOffset for the left and top
edges. Each grip sets its resize cursor from PointerEntered via InputPointerSource.Cursor on
the element's ContentIsland (UIElement.ProtectedCursor has no effect at all, so this is the
only mechanism available). While a grip is being dragged, the mouse cursor rapidly alternates
between the requested resize cursor and the default arrow for the whole duration of the drag,
instead of holding the resize cursor.
Bisected to the 2.0 major release: the identical code is steady on 1.7.250310001 and
1.8.260710003, and flickers on 2.0.1, 2.1.3 and 2.3.1. This is not a deployment-mode artifact
— 1.8.260710003 is steady both framework-dependent and self-contained, and 2.3.1 flickers in
both. (2.0.1 and 2.1.3 were tested self-contained because no matching framework runtime was
installed.)
Re-asserting the cursor on every PointerMoved while the pointer is captured does not fix it,
so there appears to be no in-app workaround.
[WinUICursorPopup-repro.zip](https://github.com/user-attachments/files/31201784/WinUICursorPopup-repro.zip)
### Why is this important?
I have an overlay that needs to be resized
### Steps to reproduce the bug
## Steps to reproduce
1. Build and run; open the popup.
2. Hover the popup's right edge. The cursor correctly becomes SizeWestEast.
3. Press and drag horizontally to resize the popup.
4. Observe the cursor for the duration of the drag.
Expected: the SizeWestEast cursor is held for the whole drag.
Actual: the cursor alternates rapidly between SizeWestEast and the default arrow
until the button is released.
## Version comparison
Change the PackageReference to 1.7.250310001, delete obj/ and bin/, rebuild: the cursor is
steady throughout the drag. No source changes.
Re-asserting the cursor on every PointerMoved while the pointer is captured does not fix the
2.3.1 behaviour.
### Actual behavior
On hover, the requested resize cursor appears immediately and stays stable for as long as the
pointer rests on the grip — hovering alone shows no problem.
As soon as the drag starts (pointer pressed and moving), the cursor begins alternating rapidly
between the requested resize cursor and the default arrow, and keeps doing so for the entire
duration of the drag. It is fast enough to read as a flicker rather than as distinct switches.
### Expected behavior
While a resize grip is being dragged, the cursor should remain the resize cursor the app set
(SizeWestEast for a left/right edge) for the entire drag, from pointer-press through to release,
with no reversion to the default arrow. This is the behaviour of standard window-edge resizing
and of the same code on WindowsAppSDK 1.7.250310001.
More generally: once an app assigns InputPointerSource.Cursor, that cursor should persist until
the app changes it. It should not be intermittently overwritten by the framework's default while
the pointer is captured by the element that set it — a captured pointer means the app owns the
interaction, including the cursor, until capture ends.
### Screenshots
_No response_
### NuGet package version
2.0.1
### Windows version
_No response_
### Additional context
_No response_
Contributor guide
Research direction
Start with the attached WinUICursorPopup reproduction and compare the cursor behavior between Windows App SDK 1.7.250310001 and 2.3.1 during a captured resize drag. Investigate how InputPointerSource.Cursor is handled for the Popup and its ContentIsland while the pointer is captured; done means the resize cursor remains steady until release.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- desktop-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100