Skip to content

Use PhysicalKey for shortcut Oem* keys on non-US layouts (#11082)#11100

Merged
niksedk merged 2 commits into
mainfrom
shortcut-physical-key-11082
May 22, 2026
Merged

Use PhysicalKey for shortcut Oem* keys on non-US layouts (#11082)#11100
niksedk merged 2 commits into
mainfrom
shortcut-physical-key-11082

Conversation

@niksedk
Copy link
Copy Markdown
Member

@niksedk niksedk commented May 22, 2026

Summary

  • Bug: on a Swedish (and other non-US) keyboard, Shift+. and Shift+, both detect as OemSemicolon because Avalonia derives Key.Oem* from the produced character against a US-keyboard table. The two physical keys collide on one token and the second-bound shortcut silently wins. The Swedish < next to Z lands on the same path and reports as OemComma.
  • Fix: when Key.ToString() starts with Oem, fall back to PhysicalKey.ToString() in ShortcutManager.GetShortcutKeyName. PhysicalKey is the layout-independent physical position — each physical key now gets a unique, stable token.
  • Migration: existing user shortcut JSON stores the old Oem* tokens. MigrateLegacyOemKeys rewrites the SeShortCut.Keys list in place when a ShortCut is constructed, so old bindings keep working and the modern names get persisted on the next save.

Closes #11082.

Test plan

  • Existing 226 UI tests still pass.
  • New tests cover the Swedish collision (Shift+. vs Shift+, produce different tokens), the < mis-report case, and the legacy migration mapping.
  • On a Swedish-layout Mac: assign Shift+Ctrl+. to one action and Shift+Ctrl+, to another — both should fire independently.
  • Existing users with OemPeriod/OemComma saved shortcuts should still trigger after upgrade.

🤖 Generated with Claude Code

Avalonia derives Key.Oem* values from the produced character mapped
against a US-keyboard table. On a Swedish layout Shift+. produces ':',
which Avalonia reports as Key.OemSemicolon (since ':' is shift+; on US),
and Shift+, also reports as OemSemicolon. Two distinct physical keys
end up sharing a token and one shortcut silently overwrites the other.
The Swedish '<' next to Z hits the same path and shows up as OemComma.

Fall back to the layout-independent PhysicalKey whenever Key.ToString
starts with "Oem". Existing user shortcut files use the old Oem* tokens,
so add a one-shot migration that rewrites the SeShortCut.Keys list in
place — the modern names then get persisted on the next save.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes shortcut-key collisions on non‑US keyboard layouts (e.g., Swedish on macOS) caused by Avalonia deriving Key.Oem* values from produced characters using a US layout mapping. The fix makes shortcut tokens stable and layout-independent by using PhysicalKey names for Oem* keys, and includes a migration so existing user shortcut JSON continues to work.

Changes:

  • Update ShortcutManager.GetShortcutKeyName to return PhysicalKey.ToString() for Oem* keys, avoiding layout-based collisions.
  • Add legacy migration (MigrateLegacyOemKeys) to rewrite stored Oem* tokens to the new PhysicalKey-based tokens when constructing ShortCut.
  • Add UI tests covering the Swedish collision cases and legacy token migration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/UI/Logic/ShortcutManagerTests.cs Adds regression tests for Oem* key collisions on non‑US layouts and tests for legacy token migration.
src/ui/Logic/ShortcutManager.cs Switches Oem* token generation to PhysicalKey and adds a legacy Oem* → physical-key token migration map.
src/ui/Logic/Shortcut.cs Runs legacy Oem* migration when ShortCut instances are constructed so existing saved shortcuts keep working.

Comment on lines +113 to +122
// as OemComma for the same reason. Fall back to the layout-independent
// PhysicalKey so each physical key gets a unique, stable token.
if (key.ToString().StartsWith("Oem", StringComparison.Ordinal))
{
return physicalKey.ToString();
}

return key.ToString();
}

The shortcut picker dropdown was built from Avalonia's Key enum and
listed legacy Oem* names (OemPeriod, OemComma, ...) — after the
PhysicalKey switch in GetShortcutKeyName, the capture path emits
"Period", "Comma", "IntlBackslash" etc., so the dropdown could not
produce a value that matched the captured token. Drop the Oem* entries
and append the physical-key punctuation tokens that capture emits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@niksedk niksedk merged commit d81b680 into main May 22, 2026
1 of 3 checks passed
@niksedk niksedk deleted the shortcut-physical-key-11082 branch May 22, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Beta-29 MacOS: Colon is not assignable as shortcut on Swedish keyboard

2 participants