Skip to content

fix(core): handle backspace decomposition#15488

Merged
mcdurdin merged 2 commits intomasterfrom
fix/core/15487-bksp
Feb 4, 2026
Merged

fix(core): handle backspace decomposition#15488
mcdurdin merged 2 commits intomasterfrom
fix/core/15487-bksp

Conversation

@mcdurdin
Copy link
Member

@mcdurdin mcdurdin commented Jan 24, 2026

Ensure that when a single backspace decomposes the last NFC character in the app context, the remainder of the 'cluster' is preserved, matching the implication of the CLDR keyboard specification.

This addresses the behavior in #15487 where the cached context became out of sync with the app context after deleting an entire NFC cluster such as ê, which caused a loop ending up with the entire context being deleted, at which point the loop exited with a fail-safe.

Note that the LDML keyboard tests (ldml.cpp) do not currently exercise the normalization code; this is a gap that should be addressed to ensure that we are testing final application behavior.

Fixes: #15487
Build-bot: release:windows,linux,mac
.

User Testing

Preparation: install the keyboard bksp_ldml.kmp from the archive below.

For these tests, always type the following key sequences:

  • E-ACUTE: abc     e/
  • D-ACUTE: abc     d/
  • A-UMLAUT: abc     '

GROUP_WINDOWS: Test on Windows 11
GROUP_MAC: Test on macOS
GROUP_LINUX: Test on Linux

  • TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT: In a compliant app, type the E-ACUTE sequence. Select the text, copy and paste it into a character viewer and verify that the last character is U+00E9.

  • TEST_COMPLIANT_E_ACUTE: In a compliant app, type the E-ACUTE sequence. Then press bksp. The result should be abc e.

  • TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT: In a non-compliant app, type the E-ACUTE sequence. Select the text, copy and paste it into a character viewer and verify that the last character is U+00E9.

  • TEST_NONCOMPLIANT_E_ACUTE: In a non-compliant app, type the E-ACUTE sequence. Then press bksp. The result should be abc e.


  • TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT: In a compliant app, type the D-ACUTE sequence. Select the text, copy and paste it into a character viewer and verify that the last two characters are U+0064 U+0301.

  • TEST_COMPLIANT_D_ACUTE: In a compliant app, type the D-ACUTE sequence. Then press bksp. The result should be abc d.

  • TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT: In a non-compliant app, type the D-ACUTE sequence. Select the text, copy and paste it into a character viewer and verify that the last two characters are U+0064 U+0301.

  • TEST_NONCOMPLIANT_D_ACUTE: In a non-compliant app, type the D-ACUTE sequence. Then press bksp. The result should be abc d.


  • TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT: In a compliant app, type the A-UMLAUT sequence. Select the text, copy and paste it into a character viewer and verify that the last character is U+00E4.

  • TEST_COMPLIANT_A_UMLAUT: In a compliant app, type the A-UMLAUT sequence. Then press bksp. The result should be abc a.

  • TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT: In a non-compliant app, type the A-UMLAUT sequence. Select the text, copy and paste it into a character viewer and verify that the last character is U+00E4.

  • TEST_NONCOMPLIANT_A_UMLAUT: In a non-compliant app, type the A-UMLAUT sequence. Then press bksp. The result should be abc a.

Note on compliant and non-compliant apps

  • Windows 11: Some compliant apps are Notepad, Word, Firefox. Some non-compliant apps are Text Editor (artifact on this PR), Chrome.
  • macOS: One compliant app is TextEdit. One non-compliant app is Chrome.
  • Linux: One compliant app is gEdit. One non-compliant app is Chrome.

Ensure that when a single backspace decomposes the last NFC character in
the app context, the remainder of the 'cluster' is preserved, matching
the implication of the CLDR keyboard specification.

This addresses the behavior in #15487 where the cached context became
out of sync with the app context after deleting an entire NFC cluster
such as ê, which caused a loop ending up with the entire context being
deleted, at which point the loop exited with a fail-safe.

Note that the LDML keyboard tests (ldml.cpp) do not currently exercise
the normalization code; this is a gap that should be addressed to ensure
that we are testing final application behavior.

Fixes: #15487
@github-project-automation github-project-automation bot moved this to Todo in Keyman Jan 24, 2026
@keymanapp-test-bot keymanapp-test-bot bot added the user-test-missing User tests have not yet been defined for the PR label Jan 24, 2026
@keymanapp-test-bot
Copy link

keymanapp-test-bot bot commented Jan 24, 2026

User Test Results

Test specification and instructions

  • ✅ GROUP_WINDOWS: Test on Windows 11

    12 tests PASSED
  • 🟩 GROUP_MAC: Test on macOS

  • ✅ GROUP_LINUX: Test on Linux

    12 tests PASSED
    • TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED): verified ok with Text Editor
    • TEST_COMPLIANT_E_ACUTE (PASSED): no problems encountered
    • TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED): verified ok with Chrome
    • TEST_NONCOMPLIANT_E_ACUTE (PASSED): no problems encountered
    • TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED): verified ok with Text Editor
    • TEST_COMPLIANT_D_ACUTE (PASSED): no problems encountered
    • TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED): verified ok with Chrome
    • TEST_NONCOMPLIANT_D_ACUTE (PASSED): no problems encountered
    • TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED): verified ok with Text Editor
    • TEST_COMPLIANT_A_UMLAUT (PASSED): no problems encountered
    • TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED): verified ok with Chrome
    • TEST_NONCOMPLIANT_A_UMLAUT (PASSED): no problems encountered (notes)

Test Artifacts

@keymanapp-test-bot keymanapp-test-bot bot added this to the A19S21 milestone Jan 24, 2026
@github-actions github-actions bot added core/ Keyman Core fix labels Jan 24, 2026
@keymanapp-test-bot keymanapp-test-bot bot added has-user-test user-test-required User tests have not been completed and removed user-test-missing User tests have not yet been defined for the PR labels Jan 24, 2026
Copy link
Member Author

Choose a reason for hiding this comment

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

Fix is entirely in this file; other changes are additional unit tests and enabling correct logging of keystrokes in the unit test log files.

@mcdurdin mcdurdin marked this pull request as ready for review January 25, 2026 20:17
@mcdurdin
Copy link
Member Author

@rc-swag @sgschantz @ermshiperete given this change is a significant fix to Keyman Core, I would like to request review from all of you. @srl295, feel free to ignore; just as you have capacity to take a look.

@@expected: abce
Comment: #15487: bksp will delete just acute (even though it will have combined to NFC, internally we do NFD bksp)

TODO: this seems to be working NFD on app context side also, do we need to set a flag? this may break other tests so care is needed
Copy link
Member Author

Choose a reason for hiding this comment

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

TODO: this seems to be working NFD on app context side also, do we need to set a flag? this may break other tests so care is needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

See #15491

mcdurdin added a commit that referenced this pull request Jan 26, 2026
Ensure that when a single backspace decomposes the last NFC character in
the app context, the remainder of the 'cluster' is preserved, matching
the implication of the CLDR keyboard specification.

This addresses the behavior in #15487 where the cached context became
out of sync with the app context after deleting an entire NFC cluster
such as ê, which caused a loop ending up with the entire context being
deleted, at which point the loop exited with a fail-safe.

Note that the LDML keyboard tests (ldml.cpp) do not currently exercise
the normalization code; this is a gap that should be addressed to ensure
that we are testing final application behavior.

This cherry-pick only adds the direct normalization patch and unit test
and skips the additional changes for logging.

Fixes: #15487
Cherry-pick-of: #15488
@Meng-Heng Meng-Heng self-assigned this Jan 26, 2026
Comment on lines +145 to +146
if(app_context_nfd == cached_context_string.substr(0, app_context_nfd.length())) {
context_final = cached_context_string.substr(app_context_nfd.length());
Copy link
Member

Choose a reason for hiding this comment

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

maybe want some more comments here.
What we're trying to say is, if the app context matches the beginning of the cache,
break but remember if there was any content that was added after the cache.

So context_final will now have any 'suffix' that is NOT reflected in the app context.

*/

auto output_nfc = output;
auto output_nfc = context_final + output;
Copy link
Member

Choose a reason for hiding this comment

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

Here, any of that 'final' suffix that was NOT already in the app context, needs to be prepended to the output.

so the full picture before the insertion point is:

<app_context><context_final><output>|

@srl295
Copy link
Member

srl295 commented Jan 26, 2026

looks good! i think it could be good to add some comments and even put the case into the comments (the example case) to document what context_final is doing. but that could be a later step.

Co-authored-by: srl295@gmail.com
@sgschantz
Copy link
Contributor

@mcdurdin For the E-ACUTE test cases, shouldn't the final unicode value be U+00E9?

@mcdurdin
Copy link
Member Author

@mcdurdin For the E-ACUTE test cases, shouldn't the final unicode value be U+00E9?

Thank you, good catch -- I had started with A-ACUTE... but then wanted to differentiate.

mcdurdin added a commit that referenced this pull request Jan 28, 2026
When normalizing, we need to stop processing on an NFC boundary, not an
NFD boundary, to support normalizations such as in Bengali, where
appending `U+09D7` to a context of `U+0995 U+09C7` should result in
`U+0995 U+09CC`.

The specification is unclear on this; see https://unicode-org.atlassian.net/browse/CLDR-19218

This also updates the ldml keyboard unit test suite to support running
in full NFC mode (used in all Engine implementations) as well retaining
the NFD mode (now only used by the debugger).

Side note: the Bengali normalization failure case was picked up by the
improvements to the unit test suite, proving once again that good tests
are so valuable.

Fixes: #15491
Fixes: #15505
Follows: #15488
Relates-to: CLDR-19218
mcdurdin added a commit that referenced this pull request Jan 28, 2026
When normalizing, we need to stop processing on an NFC boundary, not an
NFD boundary, to support normalizations such as in Bengali, where
appending `U+09D7` to a context of `U+0995 U+09C7` should result in
`U+0995 U+09CC`.

The specification is unclear on this; see https://unicode-org.atlassian.net/browse/CLDR-19218

This also updates the ldml keyboard unit test suite to support running
in full NFC mode (used in all Engine implementations) as well retaining
the NFD mode (now only used by the debugger).

Side note: the Bengali normalization failure case was picked up by the
improvements to the unit test suite, proving once again that good tests
are so valuable.

Fixes: #15491
Fixes: #15505
Follows: #15488
Relates-to: CLDR-19218
mcdurdin added a commit that referenced this pull request Jan 28, 2026
When normalizing, we need to stop processing on an NFC boundary, not an
NFD boundary, to support normalizations such as in Bengali, where
appending `U+09D7` to a context of `U+0995 U+09C7` should result in
`U+0995 U+09CC`.

The specification is unclear on this; see https://unicode-org.atlassian.net/browse/CLDR-19218

This also updates the ldml keyboard unit test suite to support running
in full NFC mode (used in all Engine implementations) as well retaining
the NFD mode (now only used by the debugger).

Side note: the Bengali normalization failure case was picked up by the
improvements to the unit test suite, proving once again that good tests
are so valuable.

Fixes: #15491
Fixes: #15505
Follows: #15488
Relates-to: CLDR-19218
test_actions_normalize(
"One backspace to delete last NFD character (#15487)",
/* app context pre transform: */ u"abcê", // NFC
/* cached context post transform: */ u"abce",
Copy link
Contributor

Choose a reason for hiding this comment

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

If the app context pre transform is the same as l.327 (both have NFC \u00EA),
shouldn't cached context post transform match l.328? (u"abce\u0323\u0302")

Copy link
Member Author

Choose a reason for hiding this comment

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

No, because the action line is different, for l.319, we have no output (U""), but for l.330, we have U"\u0323\u0302"

@Meng-Heng
Copy link
Contributor

Meng-Heng commented Jan 29, 2026

Prerequisite

  1. Uninstall active Keyman
  2. Install Keyman 19.0.193-alpha-test-15488
  3. Install the bksp_ldml keyboard
  4. Character view: https://unicode.scarfboy.com/
  5. Sequences:
    • E-ACUTE: abc e/
    • D-ACUTE: abc d/
    • A-UMLAUT: abc '

GROUP_MAC:

Test Specs

  • MacBook Intel macOS Sequoia
  • TextEdit v1.20
  • Chrome v144.0.7559.110

TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED):

  1. In TextEdit
  2. Type the E-ACUTE sequence
  3. Paste the last character into the character viewer
  4. Verified: The last character is “é” (U+00E9).

TEST_COMPLIANT_E_ACUTE (PASSED):

  1. In TextEdit
  2. Type the E-ACUTE sequence
  3. Press backspace
  4. Verified: The result is abc e.

TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED):

  1. In Chrome, Google docs
  2. Type the E-ACUTE sequence
  3. Paste the last character into the character viewer
  4. Verified: The last character is “é” (U+00E9)

TEST_NONCOMPLIANT_E_ACUTE (FAILED):

  1. In Chrome, Google docs
  2. Type the E-ACUTE sequence
  3. Press backspace
  4. Failed: The result is abce.
  • TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In TextEdit
  2. Type the D-ACUTE sequence
  3. Paste d́ into the character viewer
  4. Verified: The last two characters' unicode points are U+0064 U+0301.
  • TEST_COMPLIANT_D_ACUTE (FAILED):
  1. In TextEdit
  2. Type the D-ACUTE sequence
  3. Press backspace
  4. Failed: the result is abc .
  • TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In Chrome, Google docs
  2. Type the D-ACUTE sequence
  3. Paste d́ into the character viewer
  4. Verified: The last two characters' unicode points are U+0064 U+0301.
  • TEST_NONCOMPLIANT_D_ACUTE (PASSED):
  1. In Chrome, Google docs
  2. Type the D-ACUTE sequence
  3. Press backspace
  4. Verified: the result is abc d.
  • TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED):
  1. In TextEdit
  2. Type the A-UMLAUT sequence
  3. Paste ä into the character viewer
  4. Verified: The last character’s unicode point is U+00E4.
  • TEST_COMPLIANT_A_UMLAUT (PASSED):
  1. In TextEdit
  2. Type the A-UMLAUT sequence
  3. Press backspace
  4. Verified: The result is abc a.
  • TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED):
  1. In Chrome, Google docs
  2. Type the A-UMLAUT sequence
  3. Paste ä into the character viewer
  4. Verified: The last character’s unicode point is U+00E4.
  • TEST_NONCOMPLIANT_A_UMLAUT (FAILED):
  1. In Chrome, Google docs
  2. Type the A-UMLAUT sequence
  3. Press backspace
  4. Failed: The result is abca.

GROUP_WINDOWS:

Test Specs

  • macOS Virtualbox
  • Windows 11 AMD64
  • Notepad v11.2510
  • Chrome v144.0.7559.110
  • TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In Notepad
  2. Type the E-ACUTE sequence
  3. Paste the last character into the character viewer
  4. Verified: The last character is “é” (U+00E9)
  • TEST_COMPLIANT_E_ACUTE (PASSED):
  1. In Notepad
  2. Type the E-ACUTE sequence
  3. Press backspace
  4. Verified: The result is abc e.
  • TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In Chrome, Google docs
  2. Type the E-ACUTE sequence
  3. Paste the last character into the character viewer
  4. Verified: The last character is “é” (U+00E9)
  • TEST_NONCOMPLIANT_E_ACUTE (PASSED):
  1. In Chrome, Google docs
  2. Type the E-ACUTE sequence
  3. Press backspace
  4. Verified: The result is abc e.
  • TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In Notepad
  2. Type the D-ACUTE sequence
  3. Paste d́ into the character viewer
  4. Verified: The last two characters' unicode points are U+0064 U+0301.
  • TEST_COMPLIANT_D_ACUTE (PASSED):
  1. In Notepad
  2. Type the D-ACUTE sequence
  3. Press backspace
  4. Verified: the result is abc d.
  • TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASSED):
  1. In Chrome, Google docs
  2. Type the D-ACUTE sequence
  3. Paste d́ into the character viewer
  4. Verified: The last two characters' unicode points are U+0064 U+0301.
  • TEST_NONCOMPLIANT_D_ACUTE (PASSED):
  1. In Chrome, Google docs
  2. Type the D-ACUTE sequence
  3. Press backspace
  4. Verified: the result is abc d.
  • TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED):
  1. In Notepad
  2. Type the A-UMLAUT sequence
  3. Paste ä into the character viewer
  4. Verified: The last character’s unicode point is U+00E4.
  • TEST_COMPLIANT_A_UMLAUT (PASSED):
  1. In Notepad
  2. Type the A-UMLAUT sequence
  3. Press backspace
  4. Verified: The result is abc a.
  • TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASSED):
  1. In Chrome, Google docs
  2. Type the A-UMLAUT sequence
  3. Paste ä into the character viewer
  4. Verified: The last character’s unicode point is U+00E4.
  • TEST_NONCOMPLIANT_A_UMLAUT (PASSED):
  1. In Chrome, Google docs
  2. Type the A-UMLAUT sequence
  3. Press backspace
  4. Verified: The result is abc a.

@mcdurdin
Copy link
Member Author

@Meng-Heng could you run all the tests for mac with the .kmn based keyboard attached below, and report back on results (not as a user test, just as a comment):
bksp_kmn.zip

I would like to try and isolate the cause of the failure on macOS -- whether it is something in the LDML core implementation or a separate compatibility issue. Thanks!

@Meng-Heng
Copy link
Contributor

@mcdurdin, hopefully this is easy to follow:

Test Name Expected Previous test result KMN test result
TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT abc é abc é abc é
TEST_COMPLIANT_E_ACUTE abc e abc e abc
TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT abc é abc é abc é
TEST_NONCOMPLIANT_E_ACUTE abc e abca abc
TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT abc d́ abc d́ abc d́
TEST_COMPLIANT_D_ACUTE abc d abc abc
TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT abc d́ abc d́ abc d́
TEST_NONCOMPLIANT_D_ACUTE abc d abc d abc d
TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT abc ä abc ä abc ä
TEST_COMPLIANT_A_UMLAUT abc a abc a abc
TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT abc ä abc ä abc ä
TEST_NONCOMPLIANT_A_UMLAUT abc a abca abc

Keyman 19.0193-alpha-test-15488

@keyman-server keyman-server modified the milestones: A19S21, A19S22 Jan 31, 2026
@mcdurdin
Copy link
Member Author

@mcdurdin, hopefully this is easy to follow:

@Meng-Heng thanks, this is great -- although it's sad that there are failures. I will follow up with @sgschantz; looks like it's probably a mac-specific issue rather than anything relating to this PR.

@mcdurdin
Copy link
Member Author

mcdurdin commented Feb 3, 2026

Test Results

GROUP_LINUX: Test on Linux

Tests run on Ubuntu 24.04 under X11.

Two issues noted on Wayland which do not pertain to this PR:

For compliant app, used Gnome Text Editor 46.3. For non-compliant app, used Chrome 144.0.7559.109.

  • TEST_COMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASS): verified ok with Text Editor
  • TEST_COMPLIANT_E_ACUTE (PASS): no problems encountered
  • TEST_NONCOMPLIANT_E_ACUTE_VERIFY_CONTEXT (PASS): verified ok with Chrome
  • TEST_NONCOMPLIANT_E_ACUTE (PASS): no problems encountered
  • TEST_COMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASS): verified ok with Text Editor
  • TEST_COMPLIANT_D_ACUTE (PASS): no problems encountered
  • TEST_NONCOMPLIANT_D_ACUTE_VERIFY_CONTEXT (PASS): verified ok with Chrome
  • TEST_NONCOMPLIANT_D_ACUTE (PASS): no problems encountered
  • TEST_COMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASS): verified ok with Text Editor
  • TEST_COMPLIANT_A_UMLAUT (PASS): no problems encountered
  • TEST_NONCOMPLIANT_A_UMLAUT_VERIFY_CONTEXT (PASS): verified ok with Chrome
  • TEST_NONCOMPLIANT_A_UMLAUT (PASS): no problems encountered

Performance in non-compliant apps was very slow under X11, but this may have been a configuration issue on my test machine? (@ermshiperete FYI)

@keymanapp-test-bot keymanapp-test-bot bot removed the user-test-required User tests have not been completed label Feb 3, 2026
@mcdurdin
Copy link
Member Author

mcdurdin commented Feb 3, 2026

Test-bot: retest GROUP_MAC TEST_NONCOMPLIANT_E_ACUTE TEST_COMPLIANT_D_ACUTE TEST_NONCOMPLIANT_A_UMLAUT

@keymanapp-test-bot keymanapp-test-bot bot added user-test-required User tests have not been completed and removed user-test-failed labels Feb 3, 2026
@mcdurdin
Copy link
Member Author

mcdurdin commented Feb 3, 2026

Test Results

GROUP_MAC: Test on macOS

@keymanapp-test-bot keymanapp-test-bot bot removed the user-test-required User tests have not been completed label Feb 3, 2026
mcdurdin added a commit that referenced this pull request Feb 3, 2026
When normalizing, we need to stop processing on an NFC boundary, not an
NFD boundary, to support normalizations such as in Bengali, where
appending `U+09D7` to a context of `U+0995 U+09C7` should result in
`U+0995 U+09CC`.

The specification is unclear on this; see https://unicode-org.atlassian.net/browse/CLDR-19218

This also updates the ldml keyboard unit test suite to support running
in full NFC mode (used in all Engine implementations) as well retaining
the NFD mode (now only used by the debugger).

Side note: the Bengali normalization failure case was picked up by the
improvements to the unit test suite, proving once again that good tests
are so valuable.

Fixes: #15491
Fixes: #15505
Follows: #15488
Cherry-pick-of: #15506
Relates-to: CLDR-19218
@mcdurdin mcdurdin merged commit 30f3d35 into master Feb 4, 2026
23 checks passed
@mcdurdin mcdurdin deleted the fix/core/15487-bksp branch February 4, 2026 02:53
@github-project-automation github-project-automation bot moved this from Todo to Done in Keyman Feb 4, 2026
@keyman-server
Copy link
Collaborator

Changes in this pull request will be available for download in Keyman version 19.0.198-alpha

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

bug(core): backspace with LDML keyboard deletes entire context

7 participants