Skip to content

fix(input): fix AccessKeyHandler when no descendant control has focus - #21920

Merged
MrJul merged 3 commits into
AvaloniaUI:mainfrom
AutumnYuanc:fix/issue-21806-menu-accesskey
Aug 7, 2026
Merged

fix(input): fix AccessKeyHandler when no descendant control has focus#21920
MrJul merged 3 commits into
AvaloniaUI:mainfrom
AutumnYuanc:fix/issue-21806-menu-accesskey

Conversation

@AutumnYuanc

Copy link
Copy Markdown
Contributor

What does the pull request do?

Fixes AccessKeyHandler so that Alt/mnemonic access keys work correctly even when no
descendant control has claimed keyboard focus yet — most notably right after a Window
is opened, before the user has pressed Tab or clicked anything.

What is the current behavior?

AccessKeyHandler.OnPreviewKeyDown / OnKeyDown guard their logic behind
IsFocusWithinOwner(_owner), which re-queries KeyboardDevice.Instance.FocusedElement
directly:

  • Right after startup, KeyboardDevice.Instance.FocusedElement is null (nothing has
    claimed focus yet), so the pattern match focusedElement is not InputElement fails
    and IsFocusWithinOwner returns false immediately.
  • Even once something does assign the owner/TopLevel itself as the focused element,
    Visual.IsVisualAncestorOf is a strict, non-reflexive ancestor check
    (x.IsVisualAncestorOf(x) is always false), so IsFocusWithinOwner still returns
    false when FocusedElement == owner.

In both cases OnPreviewKeyDown/OnKeyDown return early, so pressing Alt does nothing:
no access key underlines, no menu opening, no F10.

Meanwhile KeyboardDevice.ProcessRawEvent already resolves the effective focused
element as FocusedElement ?? e.Root.FocusRoot and uses that both as the routing target
and as KeyEventArgs.Source — so the event does correctly reach AccessKeyHandler's
handlers on _owner, it's only the internal guard that re-derives a different (and
incomplete) answer from scratch.

What is the updated/expected behavior with this PR?

Access keys (Alt + underline display, Alt+letter, F10/menu opening) work immediately
after a window opens, without requiring a prior Tab press or mouse click. Tests have
been added.

How was the solution implemented (if it's not obvious)?

IsFocusWithinOwner now takes the routed event's Source (already resolved by
KeyboardDevice.ProcessRawEvent using the same FocusedElement ?? e.Root.FocusRoot
fallback) instead of independently re-reading KeyboardDevice.Instance.FocusedElement.
This avoids duplicating focus-resolution logic and fixes both underlying issues at once:

  • Source is never null for a real key event, so the "nothing focused yet" case is
    handled correctly.
  • The check now also accepts ReferenceEquals(source, owner), fixing the
    IsVisualAncestorOf non-reflexivity issue for the case where the owner itself holds
    focus.

The shared KeyDown/KeyUp test helpers in AccessKeyHandlerTests have been updated to
populate Source the same way production code does
(KeyboardDevice.Instance?.FocusedElement ?? target), since they previously never set it.

Checklist

Breaking changes

None. IsFocusWithinOwner is a private method; its signature change is not observable
from outside AccessKeyHandler.

Obsoletions / Deprecations

None.

Fixed issues

Fixes #21806

@MrJul MrJul added bug backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Aug 4, 2026
- Update IsFocusWithinOwner to use routed event's Source instead of re-querying KeyboardDevice.Instance.FocusedElement
- Allow access keys (Alt/mnemonics) to work immediately after Window opens when FocusedElement is null or owner itself
- Update shared test helpers in AccessKeyHandlerTests to populate event Source

Fixes AvaloniaUI#21806
@AutumnYuanc
AutumnYuanc force-pushed the fix/issue-21806-menu-accesskey branch from 563e99b to a75ad36 Compare August 5, 2026 08:42
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0068103-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@cla-avalonia

cla-avalonia commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator
  • All contributors have signed the CLA.

@AutumnYuanc

Copy link
Copy Markdown
Contributor Author

@cla-avalonia agree

Comment thread src/Avalonia.Base/Input/AccessKeyHandler.cs Outdated
Comment thread src/Avalonia.Base/Input/AccessKeyHandler.cs Outdated
Comment thread tests/Avalonia.Base.UnitTests/Input/AccessKeyHandlerTests.cs
Comment thread tests/Avalonia.Base.UnitTests/Input/AccessKeyHandlerTests.cs Outdated
- Type IsFocusWithinOwner's owner parameter as InputElement (matching
  _owner) and drop the now-redundant `is Visual` check
- Fix indentation in IsFocusWithinOwner
- Add Should_Raise_AccessKey_When_Focus_Is_On_Descendant, covering the
  IsVisualAncestorOf branch by raising KeyDown/KeyUp on a descendant
  control instead of the owner
- Revert the no-op Source assignment in the KeyDown/KeyUp test helpers
- Shorten the comment in Should_Raise_Key_Events_For_Registered_Access_Key
@AutumnYuanc

Copy link
Copy Markdown
Contributor Author

Pushed a75ad36..9c0ffae addressing the review feedback:

  • IsFocusWithinOwner's owner parameter is now typed as InputElement
    (matching _owner), removing the redundant is Visual check
  • Fixed indentation
  • Added Should_Raise_AccessKey_When_Focus_Is_On_Descendant to cover the
    IsVisualAncestorOf branch (raises KeyDown/KeyUp on a descendant
    control instead of the owner)
  • Reverted the unused Source assignment in the KeyDown/KeyUp test
    helpers (it was being overwritten by EventRoute.RaiseEvent anyway)
  • Shortened the comment in Should_Raise_Key_Events_For_Registered_Access_Key

@MrJul PTAL

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0068175-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@MrJul
MrJul enabled auto-merge August 7, 2026 09:26
@MrJul
MrJul added this pull request to the merge queue Aug 7, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0068177-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

Merged via the queue into AvaloniaUI:main with commit 92ea5b7 Aug 7, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: Menu access keys do not work after startup until keyboard navigation is triggered

4 participants