Title: [207010] trunk
Revision
207010
Author
wenson_hs...@apple.com
Date
2016-10-10 11:30:03 -0700 (Mon, 10 Oct 2016)

Log Message

Support InputEvent.data for the new InputEvent spec
https://bugs.webkit.org/show_bug.cgi?id=163113
<rdar://problem/28681935>

Reviewed by Darin Adler.

Source/WebCore:

Introduces InputEvent.data, a string attribute that, if non-null, indicates the text to be inserted by an input
event. For text areas and text inputs, the 'insertText', 'insertFromPaste', 'insertFromDrop', and
'insertReplacementText' input types should cause subsequent `input` and `beforeinput` events to have non-null
data. However, for contenteditable areas, only 'insertText' leads to having data in resulting InputEvents.

To implement this, we introduce a new virtual method, CompositeEditCommand::inputEventData, which gives
composite editing commands the chance to vend a data string for input events they might fire (by default, this
is null).

Tests: fast/events/input-events-paste-data.html
       fast/events/input-events-typing-data.html

* dom/InputEvent.cpp:
(WebCore::InputEvent::InputEvent):
* dom/InputEvent.h:
* dom/InputEvent.idl:

Currently, our InputEventInit struct is wrong. According to the UI-Events spec at www.w3.org/TR/uievents/, the
init struct for an InputEvent should contain a data string (added in this patch) as well as an isComposing flag
(to be added in a future patch along with composition support). While adding support for the data attribute, we
tweak the InputEvent IDL and headers slightly to adjust for this.

* dom/Node.cpp:
(WebCore::Node::dispatchInputEvent):
* dom/Node.h:
* editing/CompositeEditCommand.h:
(WebCore::CompositeEditCommand::inputEventData):
* editing/EditCommand.cpp:
(WebCore::EditCommand::isEditingTextAreaOrTextInput):
* editing/EditCommand.h:
* editing/Editor.cpp:
(WebCore::dispatchBeforeInputEvent):
(WebCore::dispatchInputEvent):
(WebCore::dispatchBeforeInputEvents):
(WebCore::dispatchInputEvents):
(WebCore::Editor::willApplyEditing):
(WebCore::Editor::appliedEditing):
(WebCore::Editor::setBaseWritingDirection):
(WebCore::Editor::computeAndSetTypingStyle):
* editing/ReplaceRangeWithTextCommand.cpp:
(WebCore::ReplaceRangeWithTextCommand::inputEventData):
* editing/ReplaceRangeWithTextCommand.h:
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::inputEventData):
* editing/ReplaceSelectionCommand.h:
* editing/SpellingCorrectionCommand.cpp:
(WebCore::SpellingCorrectionCommand::inputEventData):
* editing/SpellingCorrectionCommand.h:
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::TypingCommand):
(WebCore::TypingCommand::inputEventData):
(WebCore::TypingCommand::willAddTypingToOpenCommand):
(WebCore::TypingCommand::insertTextRunWithoutNewlines):
* editing/TypingCommand.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::dispatchFormControlInputEvent):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setEditingValue):
(WebCore::HTMLInputElement::setValueFromRenderer):
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::listBoxOnChange):
(WebCore::HTMLSelectElement::dispatchChangeEventForMenuList):

LayoutTests:

Adds 2 new layout tests verifying the data attribute of `beforeinput` and `input` events when typing, pasting,
and selecting candidate replacements in plain text and contenteditable areas.

Also tweaks an existing test to ensure that `data` is an attribute of an InputEvent.

* fast/events/input-events-fired-when-typing-expected.txt:
* fast/events/input-events-fired-when-typing.html:
* fast/events/input-events-paste-data-expected.txt: Added.
* fast/events/input-events-paste-data.html: Added.
* fast/events/input-events-typing-data-expected.txt: Added.
* fast/events/input-events-typing-data.html: Added.
* platform/ios-simulator/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (207009 => 207010)


--- trunk/LayoutTests/ChangeLog	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/ChangeLog	2016-10-10 18:30:03 UTC (rev 207010)
@@ -1,3 +1,24 @@
+2016-10-10  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Support InputEvent.data for the new InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163113
+        <rdar://problem/28681935>
+
+        Reviewed by Darin Adler.
+
+        Adds 2 new layout tests verifying the data attribute of `beforeinput` and `input` events when typing, pasting,
+        and selecting candidate replacements in plain text and contenteditable areas.
+
+        Also tweaks an existing test to ensure that `data` is an attribute of an InputEvent.
+
+        * fast/events/input-events-fired-when-typing-expected.txt:
+        * fast/events/input-events-fired-when-typing.html:
+        * fast/events/input-events-paste-data-expected.txt: Added.
+        * fast/events/input-events-paste-data.html: Added.
+        * fast/events/input-events-typing-data-expected.txt: Added.
+        * fast/events/input-events-typing-data.html: Added.
+        * platform/ios-simulator/TestExpectations:
+
 2016-10-10  Ryan Haddad  <ryanhad...@apple.com>
 
         Marking storage/indexeddb/modern/abort-requests-cancelled* tests as flaky on mac.

Modified: trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt (207009 => 207010)


--- trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt	2016-10-10 18:30:03 UTC (rev 207010)
@@ -3,6 +3,7 @@
 TEST COMPLETE
 Fired `onbeforeinput`!
 PASS event.__lookupGetter__('inputType') is defined.
+PASS event.__lookupGetter__('data') is defined.
 PASS Object.getPrototypeOf(event) is InputEvent.prototype
 PASS event.target.id is expectedTargetID
 PASS event.bubbles is true
@@ -10,6 +11,7 @@
 PASS event.composed is true
 Fired `oninput`!
 PASS event.__lookupGetter__('inputType') is defined.
+PASS event.__lookupGetter__('data') is defined.
 PASS Object.getPrototypeOf(event) is InputEvent.prototype
 PASS event.target.id is expectedTargetID
 PASS event.bubbles is true
@@ -17,6 +19,7 @@
 PASS event.composed is true
 Fired `onbeforeinput`!
 PASS event.__lookupGetter__('inputType') is defined.
+PASS event.__lookupGetter__('data') is defined.
 PASS Object.getPrototypeOf(event) is InputEvent.prototype
 PASS event.target.id is expectedTargetID
 PASS event.bubbles is true
@@ -24,6 +27,7 @@
 PASS event.composed is true
 Fired `oninput`!
 PASS event.__lookupGetter__('inputType') is defined.
+PASS event.__lookupGetter__('data') is defined.
 PASS Object.getPrototypeOf(event) is InputEvent.prototype
 PASS event.target.id is expectedTargetID
 PASS event.bubbles is true

Modified: trunk/LayoutTests/fast/events/input-events-fired-when-typing.html (207009 => 207010)


--- trunk/LayoutTests/fast/events/input-events-fired-when-typing.html	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/fast/events/input-events-fired-when-typing.html	2016-10-10 18:30:03 UTC (rev 207010)
@@ -35,6 +35,7 @@
         {
             debug("Fired `oninput`!");
             shouldBeDefined("event.__lookupGetter__('inputType')");
+            shouldBeDefined("event.__lookupGetter__('data')");
             shouldBe("Object.getPrototypeOf(event)", "InputEvent.prototype");
             shouldBe("event.target.id", "expectedTargetID");
             shouldBe("event.bubbles", "true");
@@ -46,6 +47,7 @@
         {
             debug("Fired `onbeforeinput`!");
             shouldBeDefined("event.__lookupGetter__('inputType')");
+            shouldBeDefined("event.__lookupGetter__('data')");
             shouldBe("Object.getPrototypeOf(event)", "InputEvent.prototype");
             shouldBe("event.target.id", "expectedTargetID");
             shouldBe("event.bubbles", "true");

Added: trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt (0 => 207010)


--- trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt	2016-10-10 18:30:03 UTC (rev 207010)
@@ -0,0 +1,16 @@
+To manually test this, copy the word 'testing' and paste into both the textarea and contenteditable. Verify that two PASS messages are printed out per paste (one for the beforeinput, the other for input).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+pasting 'testing' in the plain textarea. data should be nonnull
+PASS event.data is 'testing'
+PASS event.data is 'testing'
+pasting 'testing' in the rich contenteditable. data should be null
+PASS event.data is null
+PASS event.data is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+testing

Added: trunk/LayoutTests/fast/events/input-events-paste-data.html (0 => 207010)


--- trunk/LayoutTests/fast/events/input-events-paste-data.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-paste-data.html	2016-10-10 18:30:03 UTC (rev 207010)
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+</head>
+<body>
+    <textarea _onfocus_=handleFocus() id="plain" _onbeforeinput_=handlePlainInput(event,true) _oninput_=handlePlainInput(event,false)>testing</textarea>
+    <div id="rich" contenteditable _onbeforeinput_=handleRichInput(event,true) _oninput_=handleRichInput(event,false)></div>
+    <script type="text/_javascript_">
+        description(`To manually test this, copy the word 'testing' and paste into both the textarea and contenteditable. Verify that two PASS messages are printed out per paste (one for the beforeinput, the other for input).`);
+        (function() {
+            if (!window.internals || !window.eventSender || !window.testRunner)
+                return;
+
+            internals.settings.setInputEventsEnabled(true);
+            document.querySelector("#plain").focus();
+        })();
+
+        function handleFocus()
+        {
+            document.querySelector("#plain").select();
+            testRunner.execCommand("Cut");
+
+            debug("pasting 'testing' in the plain textarea. data should be nonnull");
+            testRunner.execCommand("Paste");
+
+            document.querySelector("#rich").focus();
+            debug("pasting 'testing' in the rich contenteditable. data should be null");
+            testRunner.execCommand("Paste");
+        }
+
+        function handleRichInput(event, isbefore)
+        {
+            if (event.inputType === "insertFromPaste")
+                shouldBeNull("event.data");
+        }
+
+        function handlePlainInput(event, isbefore)
+        {
+            if (event.inputType === "insertFromPaste")
+                shouldBe("event.data", "'testing'");
+        }
+    </script>
+    <script src=""
+</body>
+
+</html>

Added: trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt (0 => 207010)


--- trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt	2016-10-10 18:30:03 UTC (rev 207010)
@@ -0,0 +1,30 @@
+To manually test this, type in both the rich contenteditable and plain textarea and/or insert candidates/autocorrections. Both elements should have data when typing normally, but only the plain textarea should have data when inserting a replacement.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'h'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'h'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'e'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'e'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'l'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'l'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'o'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'o'
+Plain textarea received 'beforeinput' with inputType: 'insertReplacementText' and data: 'hello'
+Plain textarea received 'input' with inputType: 'insertReplacementText' and data: 'hello'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'h'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'h'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'e'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'e'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'l'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'l'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'o'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'o'
+Rich contenteditable received 'beforeinput' with inputType: 'insertReplacementText' and data: 'null'
+Rich contenteditable received 'input' with inputType: 'insertReplacementText' and data: 'null'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+hello

Added: trunk/LayoutTests/fast/events/input-events-typing-data.html (0 => 207010)


--- trunk/LayoutTests/fast/events/input-events-typing-data.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-typing-data.html	2016-10-10 18:30:03 UTC (rev 207010)
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+</head>
+<body>
+    <textarea id="plain" _onbeforeinput_=handlePlainInput(event) _oninput_=handlePlainInput(event)></textarea>
+    <div id="rich" contenteditable _onbeforeinput_=handleRichInput(event) _oninput_=handleRichInput(event)></div>
+    <script type="text/_javascript_">
+        description(`To manually test this, type in both the rich contenteditable and plain textarea and/or insert candidates/autocorrections.
+            Both elements should have data when typing normally, but only the plain textarea should have data when inserting a replacement.`);
+        (function() {
+            if (!window.internals || !window.eventSender || !window.testRunner)
+                return;
+
+            internals.settings.setInputEventsEnabled(true);
+
+            document.querySelector("#plain").focus();
+            simulateTypingWithReplacement(false);
+
+            document.querySelector("#rich").focus();
+            simulateTypingWithReplacement(true);
+        })();
+
+        function simulateTypingWithReplacement(isRich)
+        {
+            eventSender.keyDown("h", []);
+            eventSender.keyDown("e", []);
+            eventSender.keyDown("l", []);
+            eventSender.keyDown("o", []);
+            internals.handleAcceptedCandidate("hello", 0, 4);
+        }
+
+        function handleRichInput(event)
+        {
+            if (event.inputType === "insertText" || event.inputType === "insertReplacementText")
+                debug(`Rich contenteditable received '${event.type}' with inputType: '${event.inputType}' and data: '${event.data}'`);
+        }
+
+        function handlePlainInput(event)
+        {
+            if (event.inputType === "insertText" || event.inputType === "insertReplacementText")
+                debug(`Plain textarea received '${event.type}' with inputType: '${event.inputType}' and data: '${event.data}'`);
+        }
+    </script>
+    <script src=""
+</body>
+
+</html>

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (207009 => 207010)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-10-10 18:30:03 UTC (rev 207010)
@@ -1198,6 +1198,8 @@
 fast/events/ime-composition-events-001.html [ Failure ]
 fast/events/inputText-never-fired-on-keydown-cancel.html [ Failure ]
 fast/events/input-events-fired-when-typing.html [ Failure ]
+fast/events/input-events-paste-data.html [ Failure ]
+fast/events/input-events-typing-data.html [ Failure ]
 fast/events/before-input-events-prevent-default.html [ Failure ]
 fast/events/before-input-events-prevent-default-in-textfield.html [ Failure ]
 fast/events/before-input-events-different-start-end-elements.html [ Failure ]

Modified: trunk/Source/WebCore/ChangeLog (207009 => 207010)


--- trunk/Source/WebCore/ChangeLog	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/ChangeLog	2016-10-10 18:30:03 UTC (rev 207010)
@@ -1,3 +1,74 @@
+2016-10-10  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Support InputEvent.data for the new InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163113
+        <rdar://problem/28681935>
+
+        Reviewed by Darin Adler.
+
+        Introduces InputEvent.data, a string attribute that, if non-null, indicates the text to be inserted by an input
+        event. For text areas and text inputs, the 'insertText', 'insertFromPaste', 'insertFromDrop', and
+        'insertReplacementText' input types should cause subsequent `input` and `beforeinput` events to have non-null
+        data. However, for contenteditable areas, only 'insertText' leads to having data in resulting InputEvents.
+
+        To implement this, we introduce a new virtual method, CompositeEditCommand::inputEventData, which gives
+        composite editing commands the chance to vend a data string for input events they might fire (by default, this
+        is null).
+
+        Tests: fast/events/input-events-paste-data.html
+               fast/events/input-events-typing-data.html
+
+        * dom/InputEvent.cpp:
+        (WebCore::InputEvent::InputEvent):
+        * dom/InputEvent.h:
+        * dom/InputEvent.idl:
+
+        Currently, our InputEventInit struct is wrong. According to the UI-Events spec at www.w3.org/TR/uievents/, the
+        init struct for an InputEvent should contain a data string (added in this patch) as well as an isComposing flag
+        (to be added in a future patch along with composition support). While adding support for the data attribute, we
+        tweak the InputEvent IDL and headers slightly to adjust for this.
+
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchInputEvent):
+        * dom/Node.h:
+        * editing/CompositeEditCommand.h:
+        (WebCore::CompositeEditCommand::inputEventData):
+        * editing/EditCommand.cpp:
+        (WebCore::EditCommand::isEditingTextAreaOrTextInput):
+        * editing/EditCommand.h:
+        * editing/Editor.cpp:
+        (WebCore::dispatchBeforeInputEvent):
+        (WebCore::dispatchInputEvent):
+        (WebCore::dispatchBeforeInputEvents):
+        (WebCore::dispatchInputEvents):
+        (WebCore::Editor::willApplyEditing):
+        (WebCore::Editor::appliedEditing):
+        (WebCore::Editor::setBaseWritingDirection):
+        (WebCore::Editor::computeAndSetTypingStyle):
+        * editing/ReplaceRangeWithTextCommand.cpp:
+        (WebCore::ReplaceRangeWithTextCommand::inputEventData):
+        * editing/ReplaceRangeWithTextCommand.h:
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::inputEventData):
+        * editing/ReplaceSelectionCommand.h:
+        * editing/SpellingCorrectionCommand.cpp:
+        (WebCore::SpellingCorrectionCommand::inputEventData):
+        * editing/SpellingCorrectionCommand.h:
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::TypingCommand):
+        (WebCore::TypingCommand::inputEventData):
+        (WebCore::TypingCommand::willAddTypingToOpenCommand):
+        (WebCore::TypingCommand::insertTextRunWithoutNewlines):
+        * editing/TypingCommand.h:
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::dispatchFormControlInputEvent):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setEditingValue):
+        (WebCore::HTMLInputElement::setValueFromRenderer):
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::listBoxOnChange):
+        (WebCore::HTMLSelectElement::dispatchChangeEventForMenuList):
+
 2016-10-10  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r206972.

Modified: trunk/Source/WebCore/dom/InputEvent.cpp (207009 => 207010)


--- trunk/Source/WebCore/dom/InputEvent.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -34,15 +34,17 @@
 
 namespace WebCore {
 
-InputEvent::InputEvent(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow* view, int detail)
+InputEvent::InputEvent(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow* view, const String& data, int detail)
     : UIEvent(eventType, canBubble, cancelable, view, detail)
     , m_inputType(inputType)
+    , m_data(data)
 {
 }
 
 InputEvent::InputEvent(const AtomicString& eventType, const InputEventInit& initializer)
     : UIEvent(eventType, initializer)
-    , m_inputType(initializer.inputType)
+    , m_inputType(emptyString())
+    , m_data(initializer.data)
 {
 }
 

Modified: trunk/Source/WebCore/dom/InputEvent.h (207009 => 207010)


--- trunk/Source/WebCore/dom/InputEvent.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -32,15 +32,16 @@
 class DOMWindow;
 class DataTransfer;
 
-struct InputEventInit : public UIEventInit {
-    String inputType;
+struct InputEventInit : UIEventInit {
+    String data;
+    bool isComposing;
 };
 
 class InputEvent final : public UIEvent {
 public:
-    static Ref<InputEvent> create(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow* view, int detail)
+    static Ref<InputEvent> create(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow* view, const String& data, int detail)
     {
-        return adoptRef(*new InputEvent(eventType, inputType, canBubble, cancelable, view, detail));
+        return adoptRef(*new InputEvent(eventType, inputType, canBubble, cancelable, view, data, detail));
     }
 
     static Ref<InputEvent> createForBindings(const AtomicString& type, const InputEventInit& initializer)
@@ -48,7 +49,7 @@
         return adoptRef(*new InputEvent(type, initializer));
     }
 
-    InputEvent(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow*, int detail);
+    InputEvent(const AtomicString& eventType, const String& inputType, bool canBubble, bool cancelable, DOMWindow*, const String& data, int detail);
     InputEvent(const AtomicString& eventType, const InputEventInit&);
 
     virtual ~InputEvent() { }
@@ -55,10 +56,12 @@
 
     bool isInputEvent() const override { return true; }
     EventInterface eventInterface() const final { return InputEventInterfaceType; }
-    String inputType() const { return m_inputType; }
+    const String& inputType() const { return m_inputType; }
+    const String& data() const { return m_data; }
 
 private:
     String m_inputType;
+    String m_data;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/InputEvent.idl (207009 => 207010)


--- trunk/Source/WebCore/dom/InputEvent.idl	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.idl	2016-10-10 18:30:03 UTC (rev 207010)
@@ -26,5 +26,6 @@
 [
     ConstructorTemplate=Event
 ] interface InputEvent : UIEvent {
-    [InitializedByEventConstructor] readonly attribute DOMString inputType;
+    readonly attribute DOMString inputType;
+    [InitializedByEventConstructor] readonly attribute DOMString? data;
 };

Modified: trunk/Source/WebCore/dom/Node.cpp (207009 => 207010)


--- trunk/Source/WebCore/dom/Node.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/Node.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -2198,13 +2198,9 @@
     return !beforeLoadEvent->defaultPrevented();
 }
 
-void Node::dispatchInputEvent(const String& inputType)
+void Node::dispatchInputEvent()
 {
-    auto* settings = document().settings();
-    if (settings && settings->inputEventsEnabled())
-        dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, true, false, document().defaultView(), 0));
-    else
-        dispatchScopedEvent(Event::create(eventNames().inputEvent, true, false));
+    dispatchScopedEvent(Event::create(eventNames().inputEvent, true, false));
 }
 
 void Node::defaultEventHandler(Event& event)

Modified: trunk/Source/WebCore/dom/Node.h (207009 => 207010)


--- trunk/Source/WebCore/dom/Node.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/Node.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -525,7 +525,7 @@
 
     bool dispatchBeforeLoadEvent(const String& sourceURL);
 
-    virtual void dispatchInputEvent(const String& inputType);
+    void dispatchInputEvent();
 
     // Perform the default action for an event.
     virtual void defaultEventHandler(Event&);

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/CompositeEditCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -114,6 +114,7 @@
     virtual void setShouldRetainAutocorrectionIndicator(bool);
     virtual bool shouldStopCaretBlinking() const { return false; }
     virtual String inputEventTypeName() const;
+    virtual String inputEventData() const { return { }; }
 
 protected:
     explicit CompositeEditCommand(Document&, EditAction = EditActionUnspecified);

Modified: trunk/Source/WebCore/editing/EditCommand.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/EditCommand.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/EditCommand.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -33,6 +33,8 @@
 #include "Element.h"
 #include "EventNames.h"
 #include "Frame.h"
+#include "HTMLInputElement.h"
+#include "HTMLTextAreaElement.h"
 #include "NodeTraversal.h"
 #include "htmlediting.h"
 
@@ -140,6 +142,23 @@
     return toCompositeEditCommand(command)->composition();
 }
 
+bool EditCommand::isEditingTextAreaOrTextInput() const
+{
+    auto* frame = m_document->frame();
+    if (!frame)
+        return false;
+
+    auto* container = frame->selection().selection().start().containerNode();
+    if (!container)
+        return false;
+
+    auto* ancestor = container->shadowHost();
+    if (!ancestor)
+        return false;
+
+    return is<HTMLTextAreaElement>(*ancestor) || (is<HTMLInputElement>(*ancestor) && downcast<HTMLInputElement>(*ancestor).isText());
+}
+
 void EditCommand::setStartingSelection(const VisibleSelection& s)
 {
     for (EditCommand* cmd = this; ; cmd = cmd->m_parent) {

Modified: trunk/Source/WebCore/editing/EditCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/EditCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/EditCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -72,6 +72,8 @@
     void setStartingSelection(const VisibleSelection&);
     WEBCORE_EXPORT void setEndingSelection(const VisibleSelection&);
 
+    bool isEditingTextAreaOrTextInput() const;
+
     void postTextStateChangeNotification(AXTextEditType, const String&);
     void postTextStateChangeNotification(AXTextEditType, const String&, const VisiblePosition&);
 

Modified: trunk/Source/WebCore/editing/Editor.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/Editor.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/Editor.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -111,18 +111,27 @@
 
 namespace WebCore {
 
-static bool dispatchBeforeInputEvent(Element& element, const AtomicString& inputType)
+static bool dispatchBeforeInputEvent(Element& element, const AtomicString& inputType, const String& data = { })
 {
     auto* settings = element.document().settings();
     if (!settings || !settings->inputEventsEnabled())
         return true;
 
-    auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, true, true, element.document().defaultView(), 0);
+    auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, true, true, element.document().defaultView(), data, 0);
     element.dispatchScopedEvent(event);
 
     return !event->defaultPrevented();
 }
 
+static void dispatchInputEvent(Element& element, const AtomicString& inputType, const String& data = { })
+{
+    auto* settings = element.document().settings();
+    if (settings && settings->inputEventsEnabled())
+        element.dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, true, false, element.document().defaultView(), data, 0));
+    else
+        element.dispatchInputEvent();
+}
+
 class ClearTextCommand : public DeleteSelectionCommand {
 public:
     ClearTextCommand(Document& document);
@@ -1043,22 +1052,22 @@
         endingTextControl->didEditInnerTextValue();
 }
 
-static bool dispatchBeforeInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName)
+static bool dispatchBeforeInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { })
 {
     bool continueWithDefaultBehavior = true;
     if (startRoot)
-        continueWithDefaultBehavior &= dispatchBeforeInputEvent(*startRoot, inputTypeName);
+        continueWithDefaultBehavior &= dispatchBeforeInputEvent(*startRoot, inputTypeName, data);
     if (endRoot && endRoot != startRoot)
-        continueWithDefaultBehavior &= dispatchBeforeInputEvent(*endRoot, inputTypeName);
+        continueWithDefaultBehavior &= dispatchBeforeInputEvent(*endRoot, inputTypeName, data);
     return continueWithDefaultBehavior;
 }
 
-static void dispatchInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName)
+static void dispatchInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { })
 {
     if (startRoot)
-        startRoot->dispatchInputEvent(inputTypeName);
+        dispatchInputEvent(*startRoot, inputTypeName, data);
     if (endRoot && endRoot != startRoot)
-        endRoot->dispatchInputEvent(inputTypeName);
+        dispatchInputEvent(*endRoot, inputTypeName, data);
 }
 
 bool Editor::willApplyEditing(CompositeEditCommand& command) const
@@ -1067,7 +1076,7 @@
     if (!composition)
         return true;
 
-    return dispatchBeforeInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), command.inputEventTypeName());
+    return dispatchBeforeInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), command.inputEventTypeName(), command.inputEventData());
 }
 
 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
@@ -1086,7 +1095,7 @@
     FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
     
     changeSelectionAfterCommand(newSelection, options);
-    dispatchInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), cmd->inputEventTypeName());
+    dispatchInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), cmd->inputEventTypeName(), cmd->inputEventData());
 
     updateEditorUINowIfScheduled();
     
@@ -1705,7 +1714,7 @@
         if (direction == NaturalWritingDirection)
             return;
         downcast<HTMLTextFormControlElement>(*focusedElement).setAttributeWithoutSynchronization(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
-        focusedElement->dispatchInputEvent(emptyString());
+        focusedElement->dispatchInputEvent();
         document().updateStyleIfNeeded();
         return;
     }
@@ -3116,7 +3125,7 @@
         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
 
     if (element)
-        element->dispatchInputEvent(inputTypeName);
+        dispatchInputEvent(*element, inputTypeName);
 
     // Set the remaining style as the typing style.
     m_frame.selection().setTypingStyle(typingStyle);

Modified: trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -65,4 +65,12 @@
     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), ReplaceSelectionCommand::MatchStyle, EditActionPaste));
 }
 
+String ReplaceRangeWithTextCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_text;
+
+    return CompositeEditCommand::inputEventData();
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -40,6 +40,7 @@
 private:
     ReplaceRangeWithTextCommand(RefPtr<Range> rangeToBeReplaced, const String& text);
     void doApply() override;
+    String inputEventData() const final;
 
     RefPtr<Range> m_rangeToBeReplaced;
     String m_text;

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -1254,6 +1254,14 @@
     completeHTMLReplacement(lastPositionToSelect);
 }
 
+String ReplaceSelectionCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_documentFragment->textContent();
+
+    return CompositeEditCommand::inputEventData();
+}
+
 bool ReplaceSelectionCommand::shouldRemoveEndBR(Node* endBR, const VisiblePosition& originalVisPosBeforeEndBR)
 {
     if (!endBR || !endBR->inDocument())

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -58,6 +58,7 @@
 private:
     ReplaceSelectionCommand(Document&, RefPtr<DocumentFragment>&&, CommandOptions, EditAction);
 
+    String inputEventData() const final;
     virtual void doApply();
 
     class InsertedNodes {

Modified: trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -111,6 +111,14 @@
     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), ReplaceSelectionCommand::MatchStyle, EditActionPaste));
 }
 
+String SpellingCorrectionCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_correction;
+
+    return CompositeEditCommand::inputEventData();
+}
+
 bool SpellingCorrectionCommand::shouldRetainAutocorrectionIndicator() const
 {
     return true;

Modified: trunk/Source/WebCore/editing/SpellingCorrectionCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/SpellingCorrectionCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/SpellingCorrectionCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -42,6 +42,8 @@
     void doApply() override;
     bool shouldRetainAutocorrectionIndicator() const override;
 
+    String inputEventData() const final;
+
     RefPtr<Range> m_rangeToBeCorrected;
     VisibleSelection m_selectionToBeCorrected;
     String m_corrected;

Modified: trunk/Source/WebCore/editing/TypingCommand.cpp (207009 => 207010)


--- trunk/Source/WebCore/editing/TypingCommand.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/TypingCommand.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -110,6 +110,7 @@
     : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity))
     , m_commandType(commandType)
     , m_textToInsert(textToInsert)
+    , m_currentTextToInsert(textToInsert)
     , m_openForMoreTyping(true)
     , m_selectInsertedText(options & SelectInsertedText)
     , m_smartDelete(options & SmartDelete)
@@ -344,6 +345,14 @@
     return inputTypeNameForEditingAction(m_currentTypingEditAction);
 }
 
+String TypingCommand::inputEventData() const
+{
+    if (m_currentTypingEditAction == EditActionTypingInsertText)
+        return m_currentTextToInsert;
+
+    return CompositeEditCommand::inputEventData();
+}
+
 void TypingCommand::didApplyCommand()
 {
     // TypingCommands handle applied editing separately (see TypingCommand::typingAddedToOpenCommand).
@@ -404,13 +413,12 @@
     }
 }
 
-bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity)
+bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity, const String& text)
 {
     if (m_isHandlingInitialTypingCommand)
         return true;
 
-    // FIXME: Use the newly added typing command and granularity to ensure that an InputEvent with the
-    // correct inputType is dispatched.
+    m_currentTextToInsert = text;
     m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity);
     return frame().editor().willApplyEditing(*this);
 }
@@ -456,7 +464,7 @@
 
 void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText)
 {
-    if (!willAddTypingToOpenCommand(InsertText, CharacterGranularity))
+    if (!willAddTypingToOpenCommand(InsertText, CharacterGranularity, text))
         return;
 
     RefPtr<InsertTextCommand> command = InsertTextCommand::create(document(), text, selectInsertedText,

Modified: trunk/Source/WebCore/editing/TypingCommand.h (207009 => 207010)


--- trunk/Source/WebCore/editing/TypingCommand.h	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/TypingCommand.h	2016-10-10 18:30:03 UTC (rev 207010)
@@ -117,11 +117,12 @@
     void setShouldPreventSpellChecking(bool prevent) { m_shouldPreventSpellChecking = prevent; }
 
     String inputEventTypeName() const final;
+    String inputEventData() const final;
 
     static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Frame*);
 
     void updatePreservesTypingStyle(ETypingCommand);
-    bool willAddTypingToOpenCommand(ETypingCommand, TextGranularity);
+    bool willAddTypingToOpenCommand(ETypingCommand, TextGranularity, const String& = emptyString());
     void markMisspellingsAfterTyping(ETypingCommand);
     void typingAddedToOpenCommand(ETypingCommand);
     bool makeEditableRootEmpty();
@@ -138,6 +139,7 @@
     ETypingCommand m_commandType;
     EditAction m_currentTypingEditAction;
     String m_textToInsert;
+    String m_currentTextToInsert;
     bool m_openForMoreTyping;
     bool m_selectInsertedText;
     bool m_smartDelete;

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (207009 => 207010)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -326,7 +326,7 @@
 void HTMLFormControlElement::dispatchFormControlInputEvent()
 {
     setChangedSinceLastFormControlChangeEvent(true);
-    HTMLElement::dispatchInputEvent(emptyString());
+    HTMLElement::dispatchInputEvent();
 }
 
 bool HTMLFormControlElement::isDisabledFormControl() const

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (207009 => 207010)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -1015,7 +1015,7 @@
     else
         cacheSelectionInResponseToSetValue(max);
 
-    dispatchInputEvent(emptyString());
+    dispatchInputEvent();
 }
 
 void HTMLInputElement::setValue(const String& value, ExceptionCode& ec, TextFieldEventBehavior eventBehavior)
@@ -1095,7 +1095,7 @@
 
     // Input event is fired by the Node::defaultEventHandler for editable controls.
     if (!isTextField())
-        dispatchInputEvent(emptyString());
+        dispatchInputEvent();
 
     updateValidity();
 

Modified: trunk/Source/WebCore/html/HTMLSelectElement.cpp (207009 => 207010)


--- trunk/Source/WebCore/html/HTMLSelectElement.cpp	2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLSelectElement.cpp	2016-10-10 18:30:03 UTC (rev 207010)
@@ -669,7 +669,7 @@
     }
 
     if (fireOnChange) {
-        dispatchInputEvent(emptyString());
+        dispatchInputEvent();
         dispatchFormControlChangeEvent();
     }
 }
@@ -682,7 +682,7 @@
     if (m_lastOnChangeIndex != selected && m_isProcessingUserDrivenChange) {
         m_lastOnChangeIndex = selected;
         m_isProcessingUserDrivenChange = false;
-        dispatchInputEvent(emptyString());
+        dispatchInputEvent();
         dispatchFormControlChangeEvent();
     }
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to