Skip to content

docs(windows): describe windows compliant app implementation with sequence diagram#2326

Open
rc-swag wants to merge 6 commits intomasterfrom
docs/windows/2061/non-compliant-apps
Open

docs(windows): describe windows compliant app implementation with sequence diagram#2326
rc-swag wants to merge 6 commits intomasterfrom
docs/windows/2061/non-compliant-apps

Conversation

@rc-swag
Copy link
Contributor

@rc-swag rc-swag commented Nov 10, 2025

Add a description of the Windows Text Services Framework and sequence diagram for compliant apps.

Fixes:#2061

@rc-swag rc-swag self-assigned this Nov 10, 2025
@github-actions github-actions bot added the docs label Nov 10, 2025
@rc-swag rc-swag added this to the A19S16 milestone Nov 10, 2025
@github-project-automation github-project-automation bot moved this to Todo in Keyman Nov 10, 2025
@keymanapp-test-bot
Copy link

User Test Results

Test specification and instructions

ERROR: user tests have not yet been defined

@keyman-server keyman-server modified the milestones: A19S16, A19S17 Nov 22, 2025
@rc-swag rc-swag changed the title docs(windows): intial TSF commit todo seq diag docs(windows): initial TSF commit todo seq diag Nov 24, 2025
@keyman-server keyman-server modified the milestones: A19S17, A19S18 Dec 6, 2025
@keyman-server keyman-server modified the milestones: A19S18, A19S19 Dec 21, 2025
@keyman-server keyman-server modified the milestones: A19S19, A19S20 Jan 3, 2026
@mcdurdin mcdurdin modified the milestones: A19S20, A19S21 Jan 25, 2026
@rc-swag rc-swag requested review from ermshiperete and mcdurdin March 3, 2026 07:29
@rc-swag rc-swag marked this pull request as ready for review March 3, 2026 07:30
@rc-swag rc-swag changed the title docs(windows): initial TSF commit todo seq diag docs(windows): describes windows compliant app implmentation with sequence diagram Mar 3, 2026
@ermshiperete ermshiperete changed the title docs(windows): describes windows compliant app implmentation with sequence diagram docs(windows): describe windows compliant app implementation with sequence diagram Mar 3, 2026
Keyman determines whether an application is compliant by inspecting the status returned by `ITfContext::GetStatus()`.

- **Compliant applications** provide a stable, non-transitory context and correctly implement the TSF APIs needed to retrieve context and modify text.
- **Non-compliant applications** may expose only a transitory context or fail to return reliable selection or text data.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can TSF API be used for non-compliant apps?

Copy link
Contributor Author

@rc-swag rc-swag Mar 5, 2026

Choose a reason for hiding this comment

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

Yes, to attempt to get context. It it is determined it is non compliant when attempting to get the context then it does not use the API to set selection.

Comment on lines +241 to +243
**`GetText()`** — Retrieves text from a specified range around the caret, giving Keyman the context needed to process complex keyboard rules.

**`SetText()`** — Replaces text in a specific range within the context.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see GetText and SetText on the linked MS docs for ITfContext.

Copy link
Contributor Author

@rc-swag rc-swag Mar 5, 2026

Choose a reason for hiding this comment

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

Yes that is correct I was not sure how much detail to go into. The API linked you make GetSelection call which will return a pointer to TF_SECTION. TF_SECTION in turn contains a ITfRange it is actually ITfRange that has methonds GetText and SetText. Even then Keyman for Windows provides wrapper functions DeleteLeftOfSelection and InsertTextAtSelection that use methods of ITfRange and the ITfContext to achieve the goals. I will have a go at updating this.


Note right of Keyman: Keyman applies keyboard rules and computes output

Keyman->>TSF: ITfContext.SetText()
Copy link
Contributor

Choose a reason for hiding this comment

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

Does SetText allow to specify whether to insert the text or replace the selection, or do we have to update the selection first?

- **Backspace key events** are used to delete previously typed characters
- **Synthetic key events** may be used to insert characters

These simulated events are asynchronous and are processed by the application in sequence. As a result, text deletion and insertion may not always behave exactly as intended, particularly when dealing with composed characters or surrogate pairs.
Copy link
Member

Choose a reason for hiding this comment

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

This may need a little more elaboration. The main reason text deletion may not behave as expected is because there is no fixed definition of how many codepoints should be deleted in a Backspace key event -- one code point, a grapheme cluster, or something else. As a result, applications may have varied behavior here.

Very old applications may not handle surrogate pairs correctly and split them apart, but this is now rare.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have decided to add link to the wiki to go into the weeds on the deletions you mention here.

- Using shortcut keys or menu commands to edit text
- Switching to another application or document

When such an action occurs, Keyman discards its internal context and assumes an empty context. If this happens in the middle of typing a multi-character sequence, the sequence may not be recognized correctly and may need to be retyped.
Copy link
Member

Choose a reason for hiding this comment

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

In Keyman, there is no real concept of a multi-character sequence. (Did you mean multi-keystroke sequence?) Each key event is isolated. We should be careful not to imply a state mechanism that does not exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did mean character, however I realise character is an overloaded term with when thinking about unicode points vs charcater etc.
It was refernce back to the intro of this KB https://github.com/keymanapp/help.keyman.com/pull/2326/changes#diff-0bc53b3e68388acdad32bd067b6f9940b76087f855f1ebbbe14b4c204ba5ac2fL43

I have reworked this whole section because it was repeating what had already been said in the preamble. I have now just tried to emphasise the Windows specific work. I have also added link back to the start fo the document rather than repeating it.

Each key event is isolated. We should be careful not to imply a state mechanism that does not exist.

Huh? Each key event is not isolatated that is what the KB is about. It is processed against the context (whether tracked internal or read from context aware) this is state. When that state is lost the keyboard rule cannot work. We haven't mentioned deadkeys or markers in this KB but that information in our internal context is state and a keystroke is dependent on that state.

Back to the multi-character vs multi-keystroke sequence - both have problems with causing confusion. Because the Keyboard rules are actually based on the "charcaters" in the context NOT the keystrokes that preceeded the current keystroke, they have already been turned into a character/s or a deadkey. That's is why compliant apps can work because the read the context and get the characters.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, you are right -- there is state, but not in the form of a key sequence. The problem is people think of Keyman keyboards as describing key sequences, but they don't. They describe key + context transforms. Even deadkeys are implemented as invisible marker characters with a position in the context text stream.

In the ideal case -- apart from deadkeys -- this can be described as 'stateless': we don't carry information from keystroke to keystroke. You can position the text caret anywhere in a document and the keystroke will work with the context that it finds already there.

Historically, in a much earlier version of Keyman for Windows, we even inserted deadkeys as invisible 'embeds' into the text stream. This worked well in Word, but the vast majority of even TSF-aware apps didn't support embedding data objects, so we stripped that back out again. (And it turns out that that was better because deadkeys work best as ephemeral state-carrying markers!) But in that scenario, Keyman carried no state at all between keystrokes but queried the document every keystroke to determine the full context.

I'm not sure if I am articulating what I mean clearly though!

rc-swag and others added 2 commits March 5, 2026 22:36
Co-authored-by: Eberhard Beilharz <ermshiperete@users.noreply.github.com>
- **Non-compliant applications** may expose only a transitory context or fail to return reliable selection or text data.

If the `TF_SS_TRANSITORY` flag is present or context cannot not be read as expected, Keyman treats the application as non-compliant and falls back to legacy behavior, maintaining its own internal context buffer and simulating text operations where possible.
Note: For both compliant and non-compliant apps. When there is a highlighted section of text if backspace is the determined action from processing the keystroke on Windows Keyman will emit the key (backspace), allowing the application to handle clearing selected text in the correct manner.
Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence is hard to read and understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. Reading it again, it is hard to understand.
The point I was trying to make in the in the higlighted text selection case when backspace is pressed, Keyman doesn't use SetSelection instead it emits the keystroke and leaves it up to the application to handle. I think this might be unique to Windows. However, I'm not sure it adds anything to this knowedge base which is more concerned with on complaint vs non-complaint behaviour. It is probably best not to mention it at all.

Copy link
Member

Choose a reason for hiding this comment

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

This is an interesting point which should be carried into our compatibility matrix discussion!

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.

4 participants