Bug 325166
| Summary: | [GTK][WPE] Input method delete-surrounding deletes the wrong text in contenteditable | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | Simon Pena <spena> |
| Component: | WebKitGTK | Assignee: | Simon Pena <spena> |
| Status: | RESOLVED FIXED | ||
| Severity: | Normal | CC: | bugs-noreply |
| Priority: | P2 | ||
| Version: | WebKit Nightly Build | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| See Also: |
https://bugs.webkit.org/show_bug.cgi?id=324967 https://bugs.webkit.org/show_bug.cgi?id=250208 |
||
Simon Pena
When the input method asks WebKit to delete text around the caret (the delete-surrounding signal), WebKit can select and delete the wrong text in a contenteditable element.
The offset from the input method is relative to the caret. WebPage::deleteSurrounding turns it into a position counted from the start of the editable element. It then looks that position up in the whole tree scope instead of the editable element. For <input> and <textarea> the two are the same, because the text lives in the element's own shadow tree. For a contenteditable element in the document they are not the same: the position is shifted by all the text in the document before the element.
Steps to reproduce:
1. Load <h1>Title</h1><div contenteditable></div>.
2. Type :-) in the div.
3. From the input method, send delete-surrounding(-3, 3), then commit 😀.
Expected: the div contains 😀.
Actual: "Tit" in the heading is selected. Nothing is deleted, because the heading is not editable. The commit does not appear. The div still contains :-).
Log from WPE MiniBrowser with --log-input-method (from https://bugs.webkit.org/show_bug.cgi?id=324967), with the input method doing step 3. The first block is a <textarea>, which works. The second is the contenteditable:
input-method: surrounding: 3 bytes, cursor=3, selection=3
input-method: replacing :-) with delete-surrounding(-3, 3) and a commit
input-method: surrounding: 0 bytes, cursor=0, selection=0
input-method: surrounding: 7 bytes, cursor=7, selection=7
...
input-method: surrounding: 3 bytes, cursor=3, selection=3
input-method: replacing :-) with delete-surrounding(-3, 3) and a commit
input-method: surrounding: 0 bytes, cursor=0, selection=0
There is a second, smaller problem in the same function. If the offset goes further back than the start of the element, characterCount(...) + offset wraps round, because the count is unsigned. The caret then jumps to the end of the scope. This can happen when the input method's copy of the surrounding text is out of date.
Plan for the fix:
- Look the range up inside the root editable element, the same way EditingRange::toRange does for the Cocoa ports.
- Do nothing if the offset goes past the start of the element. This matches GtkText in GTK, which rejects a negative start position.
- Add API tests to TestInputMethodContext: one for the contenteditable case, and one for an offset past the start. Without the fix, the first test times out rather than failing an assertion.
Tested on WPE. The code is shared, so GTK should be affected too, but I have not checked it there.
| Attachments | ||
|---|---|---|
| Add attachment proposed patch, testcase, etc. |
Simon Pena
Pull request: https://github.com/WebKit/WebKit/pull/74911
EWS
Committed 322039@main (391642161045): <https://commits.webkit.org/322039@main>
Reviewed commits have been landed. Closing PR #74911 and removing active labels.