TextCommandBarFlyout: close an empty flyout before it renders - #11718
Draft
Martin Zikmund (MartinZikmund) wants to merge 2 commits into
Draft
TextCommandBarFlyout: close an empty flyout before it renders#11718Martin Zikmund (MartinZikmund) wants to merge 2 commits into
Martin Zikmund (MartinZikmund) wants to merge 2 commits into
Conversation
Right-clicking an empty, editable TextBox with an empty clipboard leaves TextCommandBarFlyout with no commands at all, so it closed itself from its Opened handler. CommandBarFlyout's Closing handler cancels every close to play the ClosingOpacityStoryboard, so instead of never appearing the empty flyout was drawn and then faded out over ~140 ms. The composition-rendering callback queued from Opening runs after Opened, so it also expanded the command bar, opening the overflow popup on the way out. Opened is raised after layout but before the frame is rendered, so closing there is early enough - it just must not animate. CommandBarFlyout now asks ShouldCloseWithoutShowing() before starting the open animation or raising MenuOpened, and remembers that decision so the Closing handler skips the close animation and the queued callback stops expanding a flyout that has already given up. TextCommandBarFlyout's existing "no UI to show" condition moves into that override unchanged, which keeps it at Opened where apps that add commands from their own Opening handler have already run. Measured on the Extra CommandBarFlyout test page: 13 rendered frames with the flyout popup open before, 0 after. Fixes microsoft#10994 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WmxyEHhAWkPxRDbqGHX76Z
…rendered ValidateRightClickOnEmptyTextBoxDoesNotShowFlyout could not catch microsoft#10994 for three reasons, all fixed here. It only counted popups after everything had settled, which is 0 whether or not the flyout flickered on the way. ExtraCommandBarFlyoutPage now counts the frames the flyout was actually on screen for: it subscribes to CompositionTarget.Rendering while the flyout is alive and increments when a popup is open. Rendering is raised right before the frame is drawn, so an open popup there is one the user is about to see. It also never opened the flyout in the first place. InputHelper.RightClick defaults to offset (0,0), which is the element's top-left corner rather than its centre; on a TextBox that lands on the border and no context menu is requested. It now right-clicks inside the text. Finally, the test app disables long animations at startup, which swaps in a CommandBarFlyoutCommandBar style with the storyboards stripped - and the flicker only existed while the close animation played. The test re-enables animations and restores the setting in a finally. Verified red/green against the same test binary with only the product DLL swapped: 13 rendered frames without the fix, 0 with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WmxyEHhAWkPxRDbqGHX76Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes
Fixes #10994
PR Type
Description
Right-clicking an empty, editable
TextBoxwith an empty clipboard leavesTextCommandBarFlyoutwith no commands at all, so it closed itself from itsOpenedhandler. ButCommandBarFlyout'sClosinghandler cancels every close in order to playClosingOpacityStoryboardfirst — so instead of never appearing, the empty flyout was drawn and then faded out over ~140 ms. The composition-rendering callback queued fromOpeningruns afterOpened, so it also expanded the command bar, opening the overflow popup on the way out.Openedis raised after layout but before the frame is rendered, so closing there is early enough — it just must not animate.CommandBarFlyoutnow asks a new protected virtualShouldCloseWithoutShowing()before starting the open animation or raisingMenuOpened, and remembers that decision (m_isClosingWithoutShowing) so that:Closinghandler skips the close animation, andTextCommandBarFlyout's existing "no UI to show" condition moves into that override unchanged, which keeps the check atOpened— where apps that add commands from their ownOpeninghandler have already run.Current Behavior
The empty flyout is rendered and visibly flickers for the duration of the close animation, briefly expanding as it goes.
New Behavior
The empty flyout is never rendered at all. No popup, no flicker.
Customer Impact
User-facing. Fixes the visual glitch reported in #10994 (reproducible in WinUI Gallery's
TextBoxsample): right-clicking an emptyTextBoxwith an empty clipboard no longer flashes a context menu.Regression Potential
ShouldCloseWithoutShowing()defaults tofalse, so everyCommandBarFlyoutother thanTextCommandBarFlyoutbehaves exactly as before. ForTextCommandBarFlyoutthe condition itself is unchanged and still evaluated at the same point in the lifecycle — only the way the flyout closes changes (no animation, and the pending expand callback is skipped).How Has This Been Tested?
The existing
ValidateRightClickOnEmptyTextBoxDoesNotShowFlyoutinteraction test could not catch this bug for three reasons, all fixed in the second commit:0whether or not the flyout flickered on the way.ExtraCommandBarFlyoutPagenow counts the frames the flyout was actually on screen for: it subscribes toCompositionTarget.Renderingwhile the flyout is alive and increments when a popup is open.Renderingis raised right before the frame is drawn, so an open popup there is one the user is about to see.InputHelper.RightClickdefaults to offset(0,0), the element's top-left corner rather than its centre; on aTextBoxthat lands on the border and no context menu is requested. It now right-clicks inside the text.CommandBarFlyoutCommandBarstyle with the storyboards stripped — and the flicker only existed while the close animation played. The test re-enables animations and restores the setting in afinally.Verified red/green against the same test binary with only the product DLL swapped: 13 rendered frames without the fix, 0 with it.