Skip to content

[Windows][IME] Capture IMM32 composition state at notification time - #6428

Merged
akleshchev merged 2 commits into
secondlife:developfrom
SaoriSuwa:fix/windows-ime-composition-snapshot
Oct 15, 2026
Merged

akleshchev merged 2 commits into
secondlife:developfrom
SaoriSuwa:fix/windows-ime-composition-snapshot

Conversation

@SaoriSuwa

Copy link
Copy Markdown
Contributor

Summary

Capture the Windows IMM32 composition data synchronously when WM_IME_COMPOSITION is received, then pass that immutable snapshot to the queued main-thread handler instead of re-reading mutable IME state later.

Fixes #6406.

Problem

The current Windows IME path queues only the WM_IME_COMPOSITION flags:

WINDOW_IMP_POST(window_imp->handleCompositionMessage((U32)l_param));

handleCompositionMessage() then calls ImmGetCompositionString() later on the queued application/main-thread callback.

IMM32 composition state is mutable. If another IME notification arrives before the queued callback runs, the older notification can be combined with a newer composition/result/attribute/clause/cursor state.

With Microsoft Japanese IME this can present as delayed preedit updates, bursts, dropped or duplicated characters, or apparent rollback to an earlier composition state.

Change

  • Capture result string, composition string, attributes, clauses, and cursor position while handling the original WM_IME_COMPOSITION.
  • Store those values in an immutable LLImeCompositionSnapshot.
  • Queue the snapshot to the main-thread handler.
  • Do not re-read IMM32 composition state from the queued handler.
  • Preserve successful empty result/composition updates.
  • Treat failed second reads as unavailable rather than applying them as successful empty captures.
  • Keep the existing indexes == 0 reset behavior.

This intentionally does not change the pre-existing cursor bounds condition in handleCompositionMessage(); that is separate from the notification/state-correlation issue.

Validation

The runtime instrumentation and user-visible reproduction were performed in Firestorm 7.2.4.80712 on Windows 11 with Microsoft Japanese IME.

Firestorm inherits the affected WM_IME_COMPOSITION / LLWindowWin32::handleCompositionMessage() path from the Second Life viewer.

A/B instrumentation over the same Nearby Chat workload showed:

Current / dequeue-time behavior

  • 56 paired composition events
  • 46 notification/dequeue state drifts
  • Applied state matched notification-time state: 10/56
  • Applied state matched dequeue-time state: 56/56

Notification-time snapshot behavior

  • 56 paired composition events
  • 45 notification/dequeue state drifts
  • Applied state matched notification-time state: 56/56
  • Applied state matched dequeue-time state: 11/56

Result-string cases

  • 3/3 captured result-string/commit cases matched between notification and dequeue

The equivalent Firestorm fix was built successfully and then used normally for approximately one week without recurrence of the original Japanese input lag / rollback / dropped-or-duplicated-character symptom.

I have not independently reproduced the user-visible symptom in an official Second Life Viewer binary.

The contribution is based on the identical affected upstream code path plus the Firestorm runtime evidence above.

Current upstream base

This PR is based on current develop at:

d36d6a2fc4

The patch applies cleanly and git diff --check passes.

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@SaoriSuwa

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

Copilot AI 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.

🟡 Changes recommended

Fix the second-read validation so partial or zero-length reads are treated as unavailable.

1 open finding
What changed in this PR

Captures IMM32 composition data when WM_IME_COMPOSITION arrives, preventing queued callbacks from reading newer IME state.

Changes:

  • Adds immutable IME composition snapshots.
  • Queues snapshots instead of composition flags.
  • Applies captured data on the main thread.
  • Preserves empty and reset handling.
File Summary
indra/​llwindow/​llwindowwin32.h Updates the composition handler interface for snapshots.
indra/​llwindow/​llwindowwin32.cpp Captures and processes IME snapshots; second reads should require an exact-length result before being considered available.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread indra/llwindow/llwindowwin32.cpp Outdated

Copilot AI 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.

🔵 Needs a closer look

This timing-sensitive Windows IME change warrants final human review.

0 open findings

1 resolved since last review

🧠 Review effort: Lite

@akleshchev

Copy link
Copy Markdown
Contributor

Thank you, merging!

@akleshchev
akleshchev merged commit 3fe5763 into secondlife:develop Oct 15, 2026
16 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows][IME] Queued WM_IME_COMPOSITION handling can read a newer IMM32 state, causing stale/mismatched preedit text

3 participants