Closed Bug 2031427 Opened 2 months ago Closed 1 month ago

[TSF] Mail compose box rejects input from IME on initial focus when messenger.compose.setComposeDetails is called.

Categories

(Thunderbird :: Add-Ons: Extensions API, defect)

defect

Tracking

(Not tracked)

RESOLVED FIXED
152 Branch

People

(Reporter: chariri, Assigned: chariri)

References

Details

(Keywords: inputmethod)

Attachments

(3 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36

Steps to reproduce:

On Windows 11, a WebExtension that updates the reply body via compose.setComposeDetails() can leave the HTML reply editor in a bad IME state. The message body looks correct, but Chinese/Japanese IME input cannot start properly until focus leaves the compose body and returns.

I believe this is a TB-side issue because the extension does not manipulate focus directly; it only uses the standard compose API, yet the focus and IME broke.

Environment

  • TB: 149.0.2 stable and Nightly 2026/04/13
  • Extension: https://github.com/jeevatkm/ReplyWithHeader-Thunderbird/ (This is the key to reproduce), with default settings, version v3.3.1
  • OS: Windows 11 25H2 26300.8170, Simplified Chinese
  • IME: Weasel (trunk, also happens on 0.17.4 and all past versions I've used), Microsoft Wubi, Microsoft Pinyin, Microsoft Japanese IME

Steps

  1. Select a received E-Mail in the INBOX of the main window.
  2. Click "Reply" button at the top of the E-Mail details
  3. The compose dialog should open, with the title and recipient already populated. The focus should be in the compose text area. The compose window should contains the original message prepended with an RWH-augmented reply header. Suppose the IME is activated.
  4. Type a letter.

Actual results:

  1. If I directly begin typing after the window opens, the IME candidate window will pop up normally and will be positioned at the compose box. However, no pre-edit is shown in the box, and when I press space, no text is committed.
  2. After I click on the compose text box (without touching any other parts), the input sequence is directly committed into the compose text box without opening up the IME.
  3. If I deactivate the text box or the window by clicking on the title box, or switch to another window, and then focus on the text box again, the issue solves.

When I hooked up a debugger on Weasel using a debug build of Weasel, I noticed ITfContextComposition::StartComposition is returning an E_FAIL when RWH header is prepended, and no ITfComposition is returned. After deactivate-reactivate, the function returns an S_OK normally.

The call-stack to setComposeDetails (a few async/await issues can be spotted in the RWH extension, but fixing them didn't resolve the issue):

manifest.json ->
background.js load -> init() -> r
whTabs.register('messageCompose', async (tab) => await rwhCompose.process(tab)) ->
messenger.tabs.onCreated -> tabListeners'messageCompose' ->
rwhCompose.process(tab) -> new ReplyWithHeader(...).init() ->
rwh.process(tab) -> _processHtml() or _processPlainText() ->
messenger.compose.setComposeDetails(tab.id, result).

Expected results:

IME input should work on the initial focus of the compose window, even after setComposeDetails is called in a hook.

Keywords: inputmethod
Component: Untriaged → Add-Ons: Extensions API
Attached file log-ime
Attached file suggested-patch

I cloned the mozilla-central + comm-central and tried a few test build with debuggers attached, as well as using codex to suggest a fix. Here's the discovery.

When the issue is triggered (i.e. the committed text does not land in the composition window), I got lots of warnings (uploaded into an attachment log-ime). This suggested that mRootElement in the IMEStateManager is stale after the setComposeDetails (which in turn calls editor.document.documentElement.innerHTML = newValues.body in the composition API implementation) is called. The editor's root element is updated, so the IME event failed. Although at https://searchfox.org/firefox-main/source/editor/libeditor/HTMLEditorMutationObserver.cpp#285 , IMEStateManager::OnUpdateHTMLEditorRootElement is called to reflect the change on the HTML root element in the editor, the latter function early-returned due to sFocusedElement already set (because when opening a reply window, the default focus is at the composition window).

Codex suggested removing the shortcut behavior and carry on the old sFocusedElement into GetNewIMEState, SetIMEState and CreateIMEContentObserver in place of the current nullptr, if the pres context is not changed.

I tested a build with the suggested patch, and the issue was gone. I wonder should I post this changeset into Phabricator for a review - since I don't know who to request the review - @masayuki -san maybe?

Please submit the patch through phabricator. https://developer.thunderbird.net/thunderbird-development/fixing-a-bug#submitting-a-patch
(Yes, for reviewer you can try that, he'll give it to someone else if there's someone better suited.)

Replacing documentElement.innerHTML in a focused designMode editor can
recreate the editor root without a DOM focus change for the IME state.
An example is calling setComposeDetails in Thunderbird to replace the
living HTML Editor body.

This fix prevents IMEStateManager from skipping the root change even
when sFocusedElement was set, so the observer attachs to the new root.

Assignee: nobody → chariri
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Status: ASSIGNED → RESOLVED
Closed: 1 month ago
Resolution: --- → FIXED
Target Milestone: --- → 152 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: