Skip to content

fix(windows): simplify keyboard refresh and make it more on-demand - #16435

Open
mcdurdin wants to merge 2 commits into
masterfrom
fix/windows/15333-simplify-keyboard-refresh
Open

fix(windows): simplify keyboard refresh and make it more on-demand#16435
mcdurdin wants to merge 2 commits into
masterfrom
fix/windows/15333-simplify-keyboard-refresh

Conversation

@mcdurdin

Copy link
Copy Markdown
Member

Clean up the keyboard refresh process. Keyman COM API will post a wm_keyman_refresh, KR_REQUEST_REFRESH message when changes have been made to the list of installed keyboards (or some other keyboard-related settings change).

Keyman Engine (any arch) will handle this message, in any process, and post a message to the master controller (keyman.exe, TfrmKeyman7Main), wm_keyman_refresh, KR_PRE_REFRESH.

Keyman Engine (keyman32) will handle this message in the master controller thread context, and increment the global refresh tag. It also asks the other architecture host process(es) to update their global refresh counter to the same value (by posting wm_keyman_refresh, KM_PRE_REFRESH to those process(es).)

This refresh tag is then compared on-demand in each thread to the thread's current refresh tag value, when a keyboard activation is received, on set focus, or on a keystroke, and the keyboard list is refreshed at that point.

This means that keyboard installation no longer triggers a large amount of activity reloading all the keyboards on all windowed threads, but rather they will gradually reload as the user interacts with them. It also fixes #15333, which related to having threads with only child windows -- that is, that were parented by top-level windows from other threads -- which thus never received the global broadcast in the earlier design. For example, VSCode, Notepad in Win11, Chrome.

Finally, include some cleanup of unused wm_keyman_control and wm_keyman_refresh values, and some other unused messages, which were making the implementation harder to understand.

Fixes: #15333

User Testing

  • TEST_BASIC_USE: Verify that Keyman continues to work as normal in everyday use - switching apps, keyboards, typing, installing new keyboards. Watch for unexpected glitches.

  • TEST_TEXT_EDITOR: Open the Keyman text editor. While it is open, install a new keyboard. Verify that the text editor refreshes its list of available fonts after a keyboard is installed.

@github-project-automation github-project-automation Bot moved this to Todo in Keyman Aug 25, 2026
@keymanapp-test-bot keymanapp-test-bot Bot added has-user-test user-test-required User tests have not been completed labels Aug 25, 2026
@keymanapp-test-bot

keymanapp-test-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

User Test Results

Test specification and instructions

Test Artifacts

/**
* Read the keyboard switch hotkeys, and base layout settings
*/
void LoadKeyboardSettings() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Factored out of RefreshKeyboards

@mcdurdin
mcdurdin force-pushed the fix/windows/15333-simplify-keyboard-refresh branch from 1ca00cd to 3778fa2 Compare August 25, 2026 13:56
@Meng-Heng Meng-Heng self-assigned this Aug 25, 2026
@Meng-Heng

Meng-Heng commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Test Specs

  1. Windows 10 Bootcamp
  2. Keyman for Windows 19.0.274-alpha-version-16435
  3. Notepad, MS Word, and Keyman's Text Editor

Test Results

  • TEST_BASIC_USE (PASSED):
  1. After installing Keyman successfully
  2. Install, remove, and type with Keyman keyboards work as expected in Notepad, MS Word
  3. Install GFF Amharic keyboard while both apps are active
  4. Return to type with Keyman keyboards work as expected
  5. Switch apps and keyboards do not cause any issues.
  • TEST_TEXT_EDITOR (PASSED):
  1. Open the Keyman text editor, Type some random character
  2. Install EuroLatin (SIL) while the text editor is open
  3. After installing the keyboard, the font plus other tools in the ribbon flashes.

@keymanapp-test-bot keymanapp-test-bot Bot added user-test-failed and removed user-test-required User tests have not been completed labels Aug 25, 2026
@Meng-Heng Meng-Heng removed their assignment Aug 25, 2026
@mcdurdin
mcdurdin force-pushed the fix/windows/15333-simplify-keyboard-refresh branch from 3778fa2 to 1a09e3e Compare August 25, 2026 15:36
case Message.wParam of
skHKL, // A windows language has been selected so select the most appropriate Keyman keyboard
skSelectHKL: // Select the requested Windows language (and therefore the most appropriate Keyman keyboard)
FLastHKL := Message.lParam;

@rc-swag rc-swag Aug 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I may answer this later in the review but marking it so I don't forget. This deleted message seems unrelated to the new code.

Clean up the keyboard refresh process. Keyman COM API will post a
`wm_keyman_refresh`, `KR_REQUEST_REFRESH` message when changes have been
made to the list of installed keyboards (or some other keyboard-related
settings change).

Keyman Engine (any arch) will handle this message, in any process, and
post a message to the master controller (keyman.exe, TfrmKeyman7Main),
`wm_keyman_refresh`, `KR_PRE_REFRESH`.

Keyman Engine (keyman32) will handle _this_ message in the master
controller thread context, and increment the global refresh tag. It also
asks the other architecture host process(es) to update their global
refresh counter to the same value (by posting `wm_keyman_refresh`,
`KM_PRE_REFRESH` to those process(es).)

This refresh tag is then compared on-demand in each thread to the
thread's current refresh tag value, when a keyboard activation is
received, on set focus, or on a keystroke, and the keyboard list is
refreshed at that point.

This means that keyboard installation no longer triggers a large amount
of activity reloading all the keyboards on all windowed threads, but
rather they will gradually reload as the user interacts with them. It
also fixes #15333, which related to having threads with only child
windows -- that is, that were parented by top-level windows from other
threads -- which thus never received the global broadcast in the earlier
design. For example, VSCode, Notepad in Win11, Chrome.

Fixes: #15333

@rc-swag rc-swag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

if(Globals::get_hwndHostARM64() != NULL) {
PostMessage(Globals::get_hwndHostARM64(), wm_keyman_refresh, KR_PRE_REFRESH, Globals::get_RefreshTag());
}
#else

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#else
#else

Co-authored-by: Ross Cruickshank <rc-swag@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

bug(windows)ː selecting a just installed keyboard with an already open application only outputs the base keyboard

3 participants