Skip to content
Permalink
Browse files
Support InputEvent.isComposing
https://bugs.webkit.org/show_bug.cgi?id=170414

Reviewed by Wenson Hsieh.

Add isComposing boolean to InputEvent and InputEventInit.

* LayoutTests/fast/events/input-event-insert-replacement-expected.txt:
* LayoutTests/fast/events/input-event-insert-replacement.html:
* LayoutTests/fast/events/input-events-drag-and-drop-expected.txt:
* LayoutTests/fast/events/input-events-drag-and-drop.html:
* LayoutTests/fast/events/input-events-fired-when-typing-expected.txt:
* LayoutTests/fast/events/input-events-fired-when-typing.html:
* LayoutTests/fast/events/input-events-forecolor-data-expected.txt:
* LayoutTests/fast/events/input-events-forecolor-data.html:
* LayoutTests/fast/events/input-events-ime-composition-expected.txt:
* LayoutTests/fast/events/input-events-ime-composition.html:
* LayoutTests/fast/events/input-events-ime-recomposition-expected.txt:
* LayoutTests/fast/events/input-events-ime-recomposition.html:
* LayoutTests/fast/events/input-events-insert-by-drop.html:
* LayoutTests/fast/events/input-events-typing-data-expected.txt:
* LayoutTests/fast/events/input-events-typing-data.html:
* LayoutTests/imported/w3c/web-platform-tests/uievents/constructors/inputevent-constructor-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/uievents/idlharness.window-expected.txt:

* Source/WebCore/dom/InputEvent.cpp:
(WebCore::InputEvent::create):
(WebCore::InputEvent::InputEvent):
* Source/WebCore/dom/InputEvent.h:
* Source/WebCore/dom/InputEvent.idl:
* Source/WebCore/editing/CompositeEditCommand.cpp:
(WebCore::CompositeEditCommand::isInputMethodComposing const): Added.
* Source/WebCore/editing/CompositeEditCommand.h:
* Source/WebCore/editing/EditCommand.cpp:
(WebCore::isInputMethodComposingForEditingAction): Added.
* Source/WebCore/editing/EditCommand.h:
* Source/WebCore/editing/Editor.cpp:
(WebCore::dispatchBeforeInputEvent):
(WebCore::dispatchInputEvent):
(WebCore::Editor::applyStyle):
(WebCore::Editor::applyParagraphStyle):
(WebCore::dispatchBeforeInputEvents):
(WebCore::dispatchInputEvents):
(WebCore::Editor::willApplyEditing):
(WebCore::Editor::appliedEditing):
(WebCore::Editor::willUnapplyEditing const):
(WebCore::Editor::unappliedEditing):
(WebCore::Editor::willReapplyEditing const):
(WebCore::Editor::reappliedEditing):
(WebCore::Editor::setBaseWritingDirection):
* Source/WebCore/editing/TypingCommand.cpp:
(WebCore::TypingCommand::isInputMethodComposing const): Added.
* Source/WebCore/editing/TypingCommand.h:

Canonical link: https://commits.webkit.org/254131@main
  • Loading branch information
rniwa committed Sep 3, 2022
1 parent 1ee82a0 commit 1aeb3328d18ee0392e7a2942315d06cbbdc1b0e6
Show file tree
Hide file tree
Showing 27 changed files with 199 additions and 131 deletions.
@@ -5,19 +5,19 @@ Then insert a single emoji character. You should observe beforeinput/input event
Importantly, the inputType of these two events should be 'insertText'."

(1) Typing 'a'...
(editable): type=beforeinput, inputType=insertText, data=a, dataTransfer=null
(editable): type=input, inputType=insertText, data=a, dataTransfer=null
(editable): type=beforeinput, inputType=insertText, data=a, dataTransfer=null, isComposing=false
(editable): type=input, inputType=insertText, data=a, dataTransfer=null, isComposing=false
The value of the input is now: a
(2) Replacing 'a' with 'b'...
(editable): type=beforeinput, inputType=insertReplacementText, data=b, dataTransfer=null
(editable): type=input, inputType=insertReplacementText, data=b, dataTransfer=null
(editable): type=beforeinput, inputType=insertReplacementText, data=b, dataTransfer=null, isComposing=false
(editable): type=input, inputType=insertReplacementText, data=b, dataTransfer=null, isComposing=false
The value of the input is now: b
(3) Inserting 'c' after 'b'...
(editable): type=beforeinput, inputType=insertText, data=c, dataTransfer=null
(editable): type=input, inputType=insertText, data=c, dataTransfer=null
(editable): type=beforeinput, inputType=insertText, data=c, dataTransfer=null, isComposing=false
(editable): type=input, inputType=insertText, data=c, dataTransfer=null, isComposing=false
The value of the input is now: bc
(4) Selecting all and replacing with 'd'...
(editable): type=beforeinput, inputType=insertReplacementText, data=d, dataTransfer=null
(editable): type=input, inputType=insertReplacementText, data=d, dataTransfer=null
(editable): type=beforeinput, inputType=insertReplacementText, data=d, dataTransfer=null, isComposing=false
(editable): type=input, inputType=insertReplacementText, data=d, dataTransfer=null, isComposing=false
The value of the input is now: d

@@ -23,7 +23,7 @@

function logInputEvent(event)
{
write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=${event.data}, dataTransfer=${event.dataTransfer}`);
write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=${event.data}, dataTransfer=${event.dataTransfer}, isComposing=${event.isComposing}`);
}

async function runTest() {
@@ -2,16 +2,16 @@ To manually test this, drag the text in the first input into the second, then un


Performing drag and drop
(source): type=beforeinput, inputType=deleteByDrag, data=`null`
(destination): type=beforeinput, inputType=insertFromDrop, data=`Input events!`
(source): type=input, inputType=deleteByDrag, data=`null`
(destination): type=input, inputType=insertFromDrop, data=`Input events!`
(source): type=beforeinput, inputType=deleteByDrag, data=`null`, isComposing=false
(destination): type=beforeinput, inputType=insertFromDrop, data=`Input events!`, isComposing=false
(source): type=input, inputType=deleteByDrag, data=`null`, isComposing=false
(destination): type=input, inputType=insertFromDrop, data=`Input events!`, isComposing=false

Undoing drag and drop
(destination): type=beforeinput, inputType=historyUndo, data=`null`
(destination): type=input, inputType=historyUndo, data=`null`
(destination): type=beforeinput, inputType=historyUndo, data=`null`, isComposing=false
(destination): type=input, inputType=historyUndo, data=`null`, isComposing=false

Redoing drag and drop
(destination): type=beforeinput, inputType=historyRedo, data=`null`
(destination): type=input, inputType=historyRedo, data=`null`
(destination): type=beforeinput, inputType=historyRedo, data=`null`, isComposing=false
(destination): type=input, inputType=historyRedo, data=`null`, isComposing=false

@@ -52,7 +52,7 @@

function logInputEvent(event)
{
write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=\`${event.data}\``);
write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=\`${event.data}\`, isComposing=${event.isComposing}`);
}

function moveToCenter(element)
@@ -10,6 +10,7 @@ PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
@@ -19,6 +20,7 @@ PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
@@ -28,6 +30,7 @@ PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
@@ -37,5 +40,6 @@ PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
a

@@ -41,6 +41,7 @@
shouldBe("event.bubbles", "true");
shouldBe("event.cancelable", "false");
shouldBe("event.composed", "true");
shouldBe("event.isComposing", "false");
}

function checkBeforeInputEvent(event)
@@ -54,6 +55,7 @@
shouldBe("event.bubbles", "true");
shouldBe("event.cancelable", "true");
shouldBe("event.composed", "true");
shouldBe("event.isComposing", "false");
}
</script>
</head>
@@ -6,27 +6,35 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
event.type = beforeinput
event.inputType = formatFontColor
event.data = rgb(255, 255, 255)
event.isComposing = false
event.type = input
event.inputType = formatFontColor
event.data = rgb(255, 255, 255)
event.isComposing = false
event.type = beforeinput
event.inputType = formatFontColor
event.data = rgb(100, 255, 0)
event.isComposing = false
event.type = input
event.inputType = formatFontColor
event.data = rgb(100, 255, 0)
event.isComposing = false
event.type = beforeinput
event.inputType = formatFontColor
event.data = rgb(0, 0, 0)
event.isComposing = false
event.type = input
event.inputType = formatFontColor
event.data = rgb(0, 0, 0)
event.isComposing = false
event.type = beforeinput
event.inputType = formatFontColor
event.data = rgb(255, 0, 0)
event.isComposing = false
event.type = input
event.inputType = formatFontColor
event.data = rgb(255, 0, 0)
event.isComposing = false
PASS successfullyParsed is true

TEST COMPLETE
@@ -24,6 +24,7 @@
debug(`event.type = ${event.type}`);
debug(`event.inputType = ${event.inputType}`);
debug(`event.data = ${event.data}`);
debug(`event.isComposing = ${event.isComposing}`);
}
</script>
<script src="../../resources/js-test-post.js"></script>
@@ -4,55 +4,55 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE


* * * First case: typing a new composition * * *
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'abc', cancelable = false)
input(inputType = 'insertCompositionText', data = 'abc', cancelable = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
beforeinput(inputType = 'insertFromComposition', data = 'abc', cancelable = true)
input(inputType = 'insertFromComposition', data = 'abc', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'abc', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'abc', cancelable = false, isComposing = true)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertFromComposition', data = 'abc', cancelable = true, isComposing = true)
input(inputType = 'insertFromComposition', data = 'abc', cancelable = false, isComposing = true)
compositionend(data = 'abc')
* * * Second case: canceling a new composition * * *
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = ' ', cancelable = false)
input(inputType = 'insertCompositionText', data = ' ', cancelable = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = ' ', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = ' ', cancelable = false, isComposing = true)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
compositionend(data = '')
* * * Third case: replacing a composition * * *
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'cde', cancelable = false)
input(inputType = 'insertCompositionText', data = 'cde', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'fg', cancelable = false)
input(inputType = 'insertCompositionText', data = 'fg', cancelable = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
beforeinput(inputType = 'insertFromComposition', data = 'fg', cancelable = true)
input(inputType = 'insertFromComposition', data = 'fg', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'ab', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'cde', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'cde', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'fg', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'fg', cancelable = false, isComposing = true)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertFromComposition', data = 'fg', cancelable = true, isComposing = true)
input(inputType = 'insertFromComposition', data = 'fg', cancelable = false, isComposing = true)
compositionend(data = 'fg')
* * * Fourth case: partially committing a composition * * *
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'aa', cancelable = false)
input(inputType = 'insertCompositionText', data = 'aa', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'aaa', cancelable = false)
input(inputType = 'insertCompositionText', data = 'aaa', cancelable = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
beforeinput(inputType = 'insertFromComposition', data = 'a', cancelable = true)
input(inputType = 'insertFromComposition', data = 'a', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'a', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'aa', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'aa', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertCompositionText', data = 'aaa', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'aaa', cancelable = false, isComposing = true)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = true)
beforeinput(inputType = 'insertFromComposition', data = 'a', cancelable = true, isComposing = true)
input(inputType = 'insertFromComposition', data = 'a', cancelable = false, isComposing = true)
compositionend(data = 'a')
beforeinput(inputType = 'insertCompositionText', data = 'aa', cancelable = false)
input(inputType = 'insertCompositionText', data = 'aa', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'aa', cancelable = false, isComposing = true)
input(inputType = 'insertCompositionText', data = 'aa', cancelable = false, isComposing = true)
PASS successfullyParsed is true

TEST COMPLETE
@@ -39,7 +39,7 @@

function logInputEvent(event)
{
debug(`${event.type}(inputType = '${event.inputType}', data = '${event.data}', cancelable = ${event.cancelable})`);
debug(`${event.type}(inputType = '${event.inputType}', data = '${event.data}', cancelable = ${event.cancelable}, isComposing = ${event.isComposing})`);
}

function logCompositionEvent(event)
@@ -3,18 +3,18 @@ To manually test this, recompose existing text via IME and observe the resulting
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


beforeinput(inputType = 'deleteByComposition', data = 'null', cancelable = true)
input(inputType = 'deleteByComposition', data = 'null', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'abc', cancelable = false)
input(inputType = 'insertCompositionText', data = 'abc', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'def', cancelable = false)
input(inputType = 'insertCompositionText', data = 'def', cancelable = false)
beforeinput(inputType = 'insertCompositionText', data = 'ghi', cancelable = false)
input(inputType = 'insertCompositionText', data = 'ghi', cancelable = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false)
beforeinput(inputType = 'insertFromComposition', data = 'ghi', cancelable = true)
input(inputType = 'insertFromComposition', data = 'ghi', cancelable = false)
beforeinput(inputType = 'deleteByComposition', data = 'null', cancelable = true, isComposing = true)
input(inputType = 'deleteByComposition', data = 'null', cancelable = false, isComposing = false)
beforeinput(inputType = 'insertCompositionText', data = 'abc', cancelable = false, isComposing = false)
input(inputType = 'insertCompositionText', data = 'abc', cancelable = false, isComposing = false)
beforeinput(inputType = 'insertCompositionText', data = 'def', cancelable = false, isComposing = false)
input(inputType = 'insertCompositionText', data = 'def', cancelable = false, isComposing = false)
beforeinput(inputType = 'insertCompositionText', data = 'ghi', cancelable = false, isComposing = false)
input(inputType = 'insertCompositionText', data = 'ghi', cancelable = false, isComposing = false)
beforeinput(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = false)
input(inputType = 'deleteCompositionText', data = 'null', cancelable = false, isComposing = false)
beforeinput(inputType = 'insertFromComposition', data = 'ghi', cancelable = true, isComposing = true)
input(inputType = 'insertFromComposition', data = 'ghi', cancelable = false, isComposing = false)
compositionend(data = 'ghi')
PASS successfullyParsed is true

@@ -21,7 +21,7 @@

function logInputEvent(event)
{
debug(`${event.type}(inputType = '${event.inputType}', data = '${event.data}', cancelable = ${event.cancelable})`);
debug(`${event.type}(inputType = '${event.inputType}', data = '${event.data}', cancelable = ${event.cancelable}, isComposing = ${event.cancelable})`);
}

function logCompositionEvent(event)
@@ -52,7 +52,7 @@

function logInputEvent(event)
{
output.innerHTML += `(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data="${event.data}" dataTransfer=${dataTransferToString(event.dataTransfer)}<br>`;
output.innerHTML += `(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data="${event.data}" dataTransfer=${dataTransferToString(event.dataTransfer)} isComposing=${dataTransferToString(event.isComposing)}<br>`;
}

function doubleClick() {

0 comments on commit 1aeb332

Please sign in to comment.