Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): ldml processor touch support 🙀 #8093

Open
srl295 opened this issue Jan 25, 2023 · 4 comments
Open

feat(core): ldml processor touch support 🙀 #8093

srl295 opened this issue Jan 25, 2023 · 4 comments
Assignees
Labels
core/ Keyman Core epic-ldml feat m:osk On Screen Keyboard or Touch Keyboard, all platforms
Milestone

Comments

@srl295
Copy link
Member

srl295 commented Jan 25, 2023

@mcdurdin this is somewhat of an umbrella ticket. Trying to capture the discussion in issues for planning.

Support Touch Layouts in LDML.

  • Waiting on Joshua's 📜 merges

  • WASM working well, but need more WASM API endpoints into Core

  • main blocker: Q: how to implement core into KMFW?

  • Divergence in other platforms

  • May be able to do some test scaffolding for touch (prior to KMFW intergration)

  • Q: how to link to processEvent in a lightweight way but without breaking predictive text?

  • Note: Core in KMFW is not in v17.

  • 🙀 spec(core): LDML KeyboardProcessor 🙀  #5015

@srl295 srl295 added this to the 18.0 milestone Jan 25, 2023
@srl295 srl295 self-assigned this Jan 25, 2023
@darcywong00 darcywong00 added the core/ Keyman Core label Jan 26, 2023
@jahorton
Copy link
Contributor

jahorton commented Jul 11, 2023

  • Q: how to link to processEvent in a lightweight way but without breaking predictive text?

Sounds like it's time for a whirlwind tour of common/web/keyboard-processor.

OutputTarget

common/web/keyboard-processor/src/text/outputTarget.ts

This is the common base class for all forms of context supported by the Keyman Engine for Web. It includes deadkey / marker tracking:

deadkeys(): DeadkeyTracker {
return this._dks;
}

Even predictive-text context extends this base class: the Mock class from the same file supports fully synthetic contexts and context 'cloning'.

The per-deadkey struct:

export class Deadkey {
p: number; // Position of deadkey
d: number; // Numerical id of the deadkey
o: number; // Ordinal value of the deadkey (resolves same-place conflicts)
matched: number;

ordinal: if two deadkeys are in the same "virtual" position, this field resolves which came first.
matched: used during keyboard-rule processing.

Note that we do NOT actually insert the deadkeys into the raw text-context! Web's pattern here is different. More on that later in this comment; we do have a deadkey-inlining method that may make a useful reference.

KeyEvent

common/web/keyboard-processor/src/text/keyEvent.ts

Any and all forms of keystroke events are preprocessed into instances of that class; these instances are then passed into the Web engine's version of the KeyboardProcessor, likely similar to what would exist for core.

Note that for fat-finger correction, we pass key events that weren't pressed into the rule processing engine as well, backed by a Mock-cloned context copy.

isSynthetic

isSynthetic - true if generated through interaction with an on-screen-keyboard or for fat-finger simulation. Only false if sending the basic key-event data through to the destination, without rule processing, leads to default handling picking up the slack.

For applications of false, consider a hardware K_ENTER keystroke - this could be interpreted as a "submit form" / "search" command depending on the context.

When true, we simulate the results of "standard" default key-event handling because nothing else can handle it. At present, we don't attempt to force / synthesize an event that could trigger the "true" default.

KeyboardProcessor

processKeystroke(keyEvent: KeyEvent, outputTarget: OutputTarget): RuleBehavior {

The method linked above is the primary entrypoint for rule processing of individual, preprocessed KeyEvents. I doubt you'll need to inspect its internals much. It's named after Core's equivalent class, as it pretty much fills the same role. I'm almost certain this is the top-level class that an LDML engine would need to replace.

Noting the specified return type...

RuleBehavior

common/web/keyboard-processor/src/text/ruleBehavior.ts

This fellow provides a metadata perspective on what the effects of keyboard-rule processing for the KeyEvent were. As Keyman keyboards do include a few aspects of state - "variable stores", in particular - we have to keep those from taking effect for predictive-text keystrokes. They're "committed" by the next layer up from that "primary entrypoint" function, which knows which key events are real and which ones are synthesized fat-finger simulation events.

The predictionPromise field is set by that "next layer up" as well, not by keyboard rule processing.

triggerKeyDefault relates to how we handle things like word-final sigma in Greek.

I believe that it also relates to things like simple K_ENTER presses from hardware keyboards, since K_ENTER can often serve as a command-key in certain contexts. (We don't yet handle changing the intent of the OSK K_ENTER.) When embedded in the mobile apps, the mobile apps know the true context, and not the Web engine, so we rely on the host-app to make the final call on how to interpret such a keystroke. History on this aspect can be found at #5553 and its links should it prove relevant. (If it does, this'd probably be the trickiest aspect to deal with for integration with the Web engine.)

Predictive-text integration

The next layer up from KeyboardProcessor is currently named InputProcessor.

common/web/input-processor/src/text/inputProcessor.ts

This layer is the primary predictive-text driver, responsible for fat-finger emulation and forwarding of new post-keystroke context to the predictive-text engine.

This is the method that most directly receives all KeyEvent instances before forwarding them to KeyboardProcessor:

private _processKeyEvent(keyEvent: KeyEvent, outputTarget: OutputTarget): RuleBehavior {

It calls this one in order to do fat-finger simulation:

private buildAlternates(ruleBehavior: RuleBehavior, keyEvent: KeyEvent, preInputMock: Mock): Alternate[] {

Both directly include calls to the primary KeyboardProcessor instance.

On inlining deadkeys

You may find this method to be of use in regard to deadkeys:

/**
* Builds the *cached or uncached* keyboard context for a specified range, relative to caret
*
* @param {number} n Number of characters to move back from caret
* @param {number} ln Number of characters to return
* @param {Object} Pelem Element to work with (must be currently focused element)
* @return {Array} Context array (of strings and numbers)
*/
private _BuildExtendedContext(n: number, ln: number, outputTarget: OutputTarget): CachedExEntry {

We use this to create the 'inlined' equivalent for keyboard rules that need it, broken down into array form. For a quick example used in unit testing...

// Match condition for rule
rule: ['a', {t:'d', d: 0}, {t:'d', d: 1}, 'b'],
// Start of context relative to cursor
n: 5,
ln: 4,
// Resulting context map
contextCache: ['a', 0, 1, 'b'],

{t: 'd', ...} says "match a deadkey" here. contextCache is what the _BuildExtendedContext function will produce for a context matching the loose rule definition.

  • Visible string: ab
  • The two deadkeys (id 0, id 1) exist between a and b in that specific order.

Other notes

One aspect of predictive-text that might be relevant, but probably isn't: application of a predictive-text suggestion or reversion is capable of rewinding the context to restore the "correct" context that it matches. The Transcription class (also in common/web/keyboard-processor/src/text/outputTarget.ts) is at the core of this mechanism.

@mcdurdin mcdurdin added the m:osk On Screen Keyboard or Touch Keyboard, all platforms label Sep 16, 2023
@mcdurdin mcdurdin modified the milestones: 18.0, A18S7 Apr 29, 2024
@darcywong00 darcywong00 modified the milestones: A18S7, A18S8 Aug 2, 2024
@darcywong00 darcywong00 modified the milestones: A18S8, A18S9 Aug 17, 2024
@mcdurdin mcdurdin added this to Keyman Aug 19, 2024
@ermshiperete ermshiperete moved this to Todo in Keyman Aug 19, 2024
ermshiperete added a commit that referenced this issue Aug 30, 2024
- loading a keyboard from a BLOB
- getting the on-screen keyboard layout from Core. This is an internal-
  only API because of it's use of C++.

Part-of: #11293
Part-of: #8093
@darcywong00 darcywong00 modified the milestones: A18S9, A18S10 Aug 31, 2024
@darcywong00 darcywong00 modified the milestones: A18S10, A18S11 Sep 14, 2024
@darcywong00 darcywong00 modified the milestones: A18S11, A18S12 Sep 28, 2024
@mcdurdin
Copy link
Member

mcdurdin commented Oct 9, 2024

#8093 (comment) could be added to web internal docs

@darcywong00 darcywong00 modified the milestones: A18S12, A18S13 Oct 11, 2024
@ermshiperete
Copy link
Contributor

@mcdurdin Since I won't get to this in the current sprint I'll move it to the end of the scheduled web-core work.

@ermshiperete ermshiperete modified the milestones: A18S13, A18S23 Oct 14, 2024
@mcdurdin
Copy link
Member

mcdurdin commented Oct 16, 2024

This is a key part of web-core work; moving to S19 to review after Christmas

@mcdurdin mcdurdin modified the milestones: A18S23, A18S19 Oct 22, 2024
@ermshiperete ermshiperete modified the milestones: A18S19, 19.0 Nov 25, 2024
ermshiperete added a commit that referenced this issue Nov 27, 2024
- split keyboard loading into loading KMX file into blob and then
  loading the keyboard processor from the blob.
- deprecate `km_core_keyboard_load`
- move file access next to deprecated method. This is now the only place
  that loads a file in Core; unit tests have some more places that
  load files.
- introduce GTest and add unit tests for loading from blob

Cherry-picked from `epic/web-core` branch.

Cherry-Pick-Commit: 1deaa32
Cherry-Pick-Commit: 59019cc
Cherry-Pick-Commit: bc46458
Cherry-Pick-Commit: d06aa29
Cherry-Pick-Commit: 1c88166
Cherry-Pick-Commit: 069cd21
Cherry-Pick-Commit: 052ae2e
Cherry-Pick-Commit: 11a2a3b

Part-of: #11293
Part-of: #8093
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core/ Keyman Core epic-ldml feat m:osk On Screen Keyboard or Touch Keyboard, all platforms
Projects
Status: Todo
Development

No branches or pull requests

5 participants