Repository navigation
Add press-and-hold activation mode to Quick Accent - #48937
Merged
Clint Rutkas (crutkas) merged 4 commits intoJul 3, 2026
Merged
Conversation
Add an opt-in iOS/macOS-style activation mode where holding an accent-capable letter (e.g. "a") opens the accent picker automatically after a configurable hold duration, with no separate trigger key. - KeyboardListener (C++): append PressAndHold to the activation enum, add a holdDuration setting plus an UpdateHoldDuration projection, arm the picker in OnKeyDown on the held letter (typing the base letter immediately and swallowing auto-repeat), and use the hold duration as the release threshold in OnKeyUp. Ctrl/Alt/AltGr/Win Budugs do not arm. - Settings model: append PressAndHold to PowerAccentActivationKey and add a hold_duration_ms property (default 500 ms). - PowerAccent.Core: read and forward the hold duration, and use it as the popup delay when PressAndHold is active. - Settings UI: add the "Press and hold the letter" option and a "Hold duration (ms)" control shown only for that mode. - Docs: document the new activation mode. The base letter types immediately and is replaced when an accent is picked; a quick tap types just the letter. Existing trigger-key modes (Space / arrows / both) and serialized settings values are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes from a 3-model code review of the press-and-hold activation mode: - Don't treat the picker as interactive until the hold duration elapses, so Space/arrow pass through during the pre-popup window instead of being swallowed and silently navigating an invisible menu. - Let the letter key-up pass through on a press-and-hold false start to avoid a perceived stuck key, and only react to the key-up of the letter that owns the toolbar so a second held letter can't cancel or commit it. - Gate the legacy trigger-key show path off in press-and-hold mode (it could still open the picker after a modifier-blocked press). - Show the press-and-hold activation label on the Settings Dashboard; the switch was missing the case (and a default), leaving it blank. - Hide the now-unused "Input delay" card while press-and-hold is active. - Defer the character/description build until the popup actually renders so quick taps stay off the keystroke hot path. - Drop redundant explicit OnPropertyChanged calls (keeping RaisePropertyChanged, which also persists settings over IPC), reuse the cached letter-key cast, and trim verbose comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Collaborator
|
In terms of related issues, this would partly fulfil #20429. Also #24780 asks for Quick Accent to support Space to trigger whitespace character mappings. We've traditionally used other keys for these mappings, as Space is used to activate the application, but an alternative hold-to-activate mode like this would give us the opportunity to duplicate those whitespace mappings to Space. It would have to be additive to accommodate both activation methods, but sounds useful. |
Apply two remaining Quick Accent press-and-hold review items: - Convert SettingsService.HoldDuration to an auto-property, dropping the redundant backing field and trivial get/set wrapper. - Add iOS to the spell-check expect list; macOS is already recognized by the software-terms dictionary but iOS is not, so the new doc/resource references would otherwise fail check-spelling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Collaborator
Yu Leng (moooyo)
pushed a commit
that referenced
this pull request
Jul 1, 2026
## Summary Quick Accent's ShowToolbar queues a delayed render of the accent menu through Task.Delay(...).ContinueWith(...). The continuation only checked _visible before rendering, so a timer started by an earlier key press could still fire for a **newer** summon — or one that had already been hidden — popping the accent menu earlier than the configured delay intended. This was surfaced while reviewing the press-and-hold work in #48937, but it is a pre-existing race independent of that feature, so it ships on its own. ## Fix - Tag each `ShowToolbar` summon with an incrementing `_showGeneration` id and capture it in the local closure. - The delayed continuation now renders only when it is still the most recent summon (`generation == _showGeneration`) **and** `_visible`. - Bump the generation when the toolbar hides, so any in-flight timer queued before the hide is cancelled. Everything runs on the UI thread (the dispatcher marshals `ShowToolbar`/hide and the continuation uses `FromCurrentSynchronizationContext`), so the counter needs no locking. ## Validation - Built `PowerAccent.UI` (C++ hook + Core) Debug|x64 — 0 warnings, 0 errors. - Manual: rapid repeated taps of an accent-capable letter no longer flash the menu early from a leftover timer; normal hold-to-open and navigation/commit are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… guard main's #48944 added the _showGeneration race guard to ShowToolbar; this branch refactored ShowToolbar to defer character building into PrepareCharacters() off the keystroke hot path. Resolved the overlap by keeping both the isPressAndHold branch and the generation id, and dropping main's now-redundant inline _characters/_characterDescriptions/ _showUnicodeDescription assignments (superseded by PrepareCharacters()). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clint Rutkas (crutkas)
enabled auto-merge (squash)
July 3, 2026 03:28
Clint Rutkas (crutkas)
deleted the
user/crutkas/quickaccent-press-and-hold
branch
July 3, 2026 03:43
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.
Summary of the Pull Request
Adds an opt-in press-and-hold activation mode to Quick Accent, like iOS / macOS: hold an accent-capable letter (e.g.
a) and after a short, configurable delay the accent picker opens automatically — no separate trigger key (Space/arrows) required.This is purely additive. The existing trigger-key modes (
Left/Right arrow,Space,Both) and all serialized settings values are unchanged.Recording.2026-06-26.175015.mp4
What it does
Ctrl/Alt/AltGr/Win+ letter combinations are left untouched, so shortcuts likeCtrl+Astill work.PR Checklist
Settings.UI/Strings/en-us/Resources.reswwith translator comments.doc/devdocs/modules/quickaccent.mdupdated with the new mode.Detailed Description of the Pull Request / Additional comments
PowerAccentKeyboardService(C++ hook):PressAndHoldto the internalPowerAccentActivationKeyenum (value3, appended to preserve serialized0/1/2).holdDurationsetting andUpdateHoldDuration(Int32)to the WinRT projection (.idl).OnKeyDown, arm the picker on the held letter itself; the base letter still types on first press and auto-repeat is swallowed (reuses the existingm_toolbarVisiblerepeat guard from Quick Accent not properly working when using on-screen keyboard #36853).OnKeyUp, use the hold duration as the minimum-hold release threshold for this mode (trigger modes keep usinginputTime).Settings.UI.Library): appendPressAndHoldtoPowerAccentActivationKey; addhold_duration_ms(IntProperty, default 500). Existingsettings.jsonwithout the field falls back to the 500 ms default.PowerAccent.Core: read and forward the hold duration to the hook, and use it as the popup delay whenPressAndHoldis active.Enum sync note
PowerAccentActivationKeyexists in both the C++ hook and the managed settings library and is kept in sync by integer value.PressAndHoldwas appended (never reordered) so existing serialized settings (0/1/2) keep their meaning.Coordination with #48891 (Quick Accent WinUI migration)
This lands as its own atomic change on
main. The overlap with the in-progress WinUI migration (#48891) is tiny: onlyPowerAccent.cs's mode-aware popup delay (a singleTask.Delayline). The C++ hook, settings enum/model, and Settings UI are not touched by #48891, so it can rebase onto this with minimal effort.Validation Steps Performed
Debug|x64:PowerAccent.UI.csproj→ rebuilds the C++PowerAccentKeyboardServiceprojection (incl.UpdateHoldDuration) +PowerAccent.Core+Settings.UI.Library. 0 errors.PowerToys.Settings.csproj→ Settings UI XAML / ViewModel /.resw(XamlIndexBuilder search index regenerated). 0 errors.PowerToys.PowerAccent.exe) withactivation_key = 3:a→ base letter types immediately; picker opens after ~500 ms; arrows/Space navigate; releasing inserts the accent (replacing the base letter).Ctrl+A/Alt+letter unaffected.