Title: [208014] trunk
Revision
208014
Author
[email protected]
Date
2016-10-27 15:46:46 -0700 (Thu, 27 Oct 2016)

Log Message

Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
https://bugs.webkit.org/show_bug.cgi?id=163948
<rdar://problem/28921433>

Reviewed by Darin Adler.

Source/WebCore:

Implements support for "insertFromDrop" and "deleteByDrag" inputTypes. These are fired when dragging and
dropping text in editable areas. To do this, we introduce EditActionInsertFromDrop and EditActionDeleteByDrag
(renamed from EditActionDrag, which is no longer necessary after this patch).

When moving text from an editable element to another, we will use a DeleteSelectionCommand to delete the text
from the source element and a ReplaceSelectionCommand to insert the text into the destination element. This
means that we currently fire two input events on the source and destination elements (i.e. given by the start
and end selections) after both child editing commands of the MoveSelectionCommand have been applied. Instead, we
need to fire events in this order:

1. beforeinput ("deleteByDrag") on the source
2. Update DOM
3. input ("deleteByDrag") on the source

4. beforeinput ("insertFromDrop") on the destination
5. Update DOM
6. input ("insertFromDrop") on the destination

To accomplish this, we allow an edit command to defer dispatching input events to its child commands via
CompositeEditCommand::shouldDispatchInputEvents, which the MoveSelectionCommand overrides. Additionally,
when applying the MoveSelectionCommand, we now apply() the child DeleteSelectionCommand and
ReplaceSelectionCommand instead of using doApply(). This allows these children to separately dispatch input
events, and also handle preventDefault() separately.

Tests: fast/events/before-input-events-prevent-drag-and-drop.html
       fast/events/input-events-drag-and-drop.html
       fast/events/input-events-insert-by-drop.html

* editing/CompositeEditCommand.cpp:
(WebCore::CompositeEditCommand::apply):
(WebCore::CompositeEditCommand::composition):

Searches for the top-level command and returns its composition. Also ASSERTs that the m_command of all child
commands along the way is null. In places where we used to ASSERT that command.composition() should be null, we
now perform the assertion here instead.

* editing/CompositeEditCommand.h:
(WebCore::CompositeEditCommand::shouldDispatchInputEvents):

This is true by default, which means that if apply() is called for a composite edit command that does not
override this to return false, it will try to dispatch input events. In most cases, the parent command will call
on the child command to doApply(), bypassing this check.

(WebCore::CompositeEditCommand::composition): Deleted.
* editing/EditAction.h:
* editing/EditCommand.cpp:
(WebCore::inputTypeNameForEditingAction):
(WebCore::EditCommand::isEditingTextAreaOrTextInput):
(WebCore::EditCommand::setStartingSelection):
(WebCore::EditCommand::setEndingSelection):
(WebCore::EditCommand::setParent):
* editing/Editor.cpp:
(WebCore::Editor::willApplyEditing):
(WebCore::Editor::appliedEditing):

After applying editing, only adjust the current selection and notify clients of selection change if the applied
command was a top-level command; otherwise, these actions should wait until all child commands of the top-level
command have been applied. In particular, we should not register the applied command as an undo step.

* editing/MoveSelectionCommand.cpp:
(WebCore::MoveSelectionCommand::doApply):
(WebCore::MoveSelectionCommand::editingAction):
* editing/MoveSelectionCommand.h:
* page/DragController.cpp:
(WebCore::DragController::concludeEditDrag):

For the cases where we're not deleting text from the drag source (i.e. we're just applying a
ReplaceSelectionCommand) pass in EditActionInsertFromDrop as the EditAction when creating the command.

Source/WebKit/mac:

Add support for new drag and drop-related EditAction enum values.

* WebCoreSupport/WebEditorClient.mm:
(undoNameForEditAction):

Source/WebKit/win:

Add support for new drag and drop-related EditAction enum values.

* WebCoreSupport/WebEditorClient.cpp:
(undoNameForEditAction):

Source/WebKit2:

Add support for new drag and drop-related EditAction enum values.

* UIProcess/WebEditCommandProxy.cpp:
(WebKit::WebEditCommandProxy::nameForEditAction):

LayoutTests:

Adds 3 new layout tests verifying that when dragging and dropping (both from a contenteditable to another
contenteditable and from non-editable content into a contenteditable) beforeinput and input events are fired in
the right order with the right data and inputTypes, and that undoing/redoing still considers the drag and drop
command as a single unit. Also tests that both deleting text by dragging and inserting text by dropping are
preventable.

* fast/events/before-input-events-prevent-drag-and-drop-expected.txt: Added.
* fast/events/before-input-events-prevent-drag-and-drop.html: Added.
* fast/events/input-events-drag-and-drop-expected.txt: Added.
* fast/events/input-events-drag-and-drop.html: Added.
* fast/events/input-events-insert-by-drop-expected.txt: Added.
* fast/events/input-events-insert-by-drop.html: Added.
* platform/ios-simulator/TestExpectations:
* platform/mac-wk2/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (208013 => 208014)


--- trunk/LayoutTests/ChangeLog	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/LayoutTests/ChangeLog	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1,3 +1,26 @@
+2016-10-27  Wenson Hsieh  <[email protected]>
+
+        Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163948
+        <rdar://problem/28921433>
+
+        Reviewed by Darin Adler.
+
+        Adds 3 new layout tests verifying that when dragging and dropping (both from a contenteditable to another
+        contenteditable and from non-editable content into a contenteditable) beforeinput and input events are fired in
+        the right order with the right data and inputTypes, and that undoing/redoing still considers the drag and drop
+        command as a single unit. Also tests that both deleting text by dragging and inserting text by dropping are
+        preventable.
+
+        * fast/events/before-input-events-prevent-drag-and-drop-expected.txt: Added.
+        * fast/events/before-input-events-prevent-drag-and-drop.html: Added.
+        * fast/events/input-events-drag-and-drop-expected.txt: Added.
+        * fast/events/input-events-drag-and-drop.html: Added.
+        * fast/events/input-events-insert-by-drop-expected.txt: Added.
+        * fast/events/input-events-insert-by-drop.html: Added.
+        * platform/ios-simulator/TestExpectations:
+        * platform/mac-wk2/TestExpectations:
+
 2016-10-27  Devin Rousso  <[email protected]>
 
         Web Inspector: Create general model object Collection class

Added: trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop-expected.txt (0 => 208014)


--- trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop-expected.txt	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,10 @@
+To manually test this, drag the text in the first editing area into the second. The first area should retain the text, the second area should be blank, and the third area should show an HTML representation of the first area with style information.
+
+Source:
+
+input events
+Destination:
+
+HTML content:
+
+<span style="color: rgb(0, 0, 0); font-family: monospace; font-size: 108px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: center; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none;">input events</span>

Added: trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop.html (0 => 208014)


--- trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/before-input-events-prevent-drag-and-drop.html	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <style>
+    #source, #destination, #copy {
+        width: 100vw;
+        height: 20vh;
+        border: blue dashed 1px;
+        font-size: 18vh;
+        position: absolute;
+        opacity: 0.5;
+        text-align: center;
+    }
+    #source {
+        top: 0vh;
+    }
+    #destination {
+        top: 20vh;
+    }
+    </style>
+    <p>To manually test this, drag the text in the first editing area into the second. The first area should retain the
+    text, the second area should be blank, and the third area should show an HTML representation of the first area with
+    style information.</p>
+    <p>Source:</p>
+    <div id="source" contenteditable _onbeforeinput_=handleBeforeInput(event)><code>input events</code></div>
+    <p>Destination:</p>
+    <div id="destination" contenteditable _onbeforeinput_=handleBeforeInput(event)></div>
+    <p>HTML content:</p>
+    <div id="result"></div>
+    <script type="text/_javascript_">
+        if (window.internals && window.testRunner) {
+            internals.settings.setInputEventsEnabled(true);
+            testRunner.dumpAsText();
+        }
+
+        source.focus();
+        document.execCommand("selectAll");
+
+        if (window.eventSender) {
+            moveToCenter(source);
+            eventSender.leapForward(500);
+            eventSender.mouseDown();
+            eventSender.leapForward(1000);
+            moveToCenter(destination);
+            eventSender.leapForward(500);
+            eventSender.mouseUp();
+        }
+
+        function handleBeforeInput(event)
+        {
+            if (event.inputType === "insertFromDrop") {
+                result.textContent = event.dataTransfer.getData("text/html");
+                event.preventDefault();
+                return;
+            }
+
+            if (event.inputType === "deleteByDrag")
+                event.preventDefault();
+        }
+
+        function moveToCenter(element)
+        {
+            let x = element.offsetParent.offsetLeft + element.offsetLeft + element.offsetWidth / 2;
+            let y = element.offsetParent.offsetTop + element.offsetTop + element.offsetHeight / 2;
+            eventSender.mouseMoveTo(x, y);
+        }
+    </script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/input-events-drag-and-drop-expected.txt (0 => 208014)


--- trunk/LayoutTests/fast/events/input-events-drag-and-drop-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-drag-and-drop-expected.txt	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,17 @@
+To manually test this, drag the text in the first input into the second, then undo (cmd-z) and observe the output. You should see two deleteByDrag events (beforeinput and input) followed by two insertFromDrop events. After undoing, you should see two historyUndo events, and redoing should output two historyRedo events.
+
+
+Performing drag and drop
+(source): type=beforeinput, inputType=deleteByDrag, data=""
+(source): type=input, inputType=deleteByDrag, data=""
+(destination): type=beforeinput, inputType=insertFromDrop, data="" events!`
+(destination): type=input, inputType=insertFromDrop, data="" events!`
+
+Undoing drag and drop
+(destination): type=beforeinput, inputType=historyUndo, data=""
+(destination): type=input, inputType=historyUndo, data=""
+
+Redoing drag and drop
+(destination): type=beforeinput, inputType=historyRedo, data=""
+(destination): type=input, inputType=historyRedo, data=""
+

Added: trunk/LayoutTests/fast/events/input-events-drag-and-drop.html (0 => 208014)


--- trunk/LayoutTests/fast/events/input-events-drag-and-drop.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-drag-and-drop.html	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <style>
+    #source, #destination {
+        width: 100vw;
+        height: 50vh;
+        border: blue dashed 1px;
+        font-size: 40vh;
+        position: absolute;
+        opacity: 0.5;
+    }
+    #source {
+        top: 0vh;
+    }
+    #destination {
+        top: 50vh;
+    }
+    </style>
+    <p>To manually test this, drag the text in the first input into the second, then undo (cmd-z) and observe the
+    output. You should see two deleteByDrag events (beforeinput and input) followed by two insertFromDrop events. After
+    undoing, you should see two historyUndo events, and redoing should output two historyRedo events.</p>
+    <input id="source" _onbeforeinput_=logInputEvent(event) _oninput_=logInputEvent(event) value="Input events!"></input>
+    <input id="destination" _onbeforeinput_=logInputEvent(event) _oninput_=logInputEvent(event)></input>
+    <div id="output"></div>
+    <script type="text/_javascript_">
+        let write = s => output.innerHTML += s + "<br>";
+        if (window.internals && window.testRunner) {
+            internals.settings.setInputEventsEnabled(true);
+            testRunner.dumpAsText();
+        }
+
+        source.focus();
+        document.execCommand("selectAll");
+
+        if (window.eventSender) {
+            write("Performing drag and drop");
+            moveToCenter(source);
+            eventSender.leapForward(500);
+            eventSender.mouseDown();
+            eventSender.leapForward(1000);
+            moveToCenter(destination);
+            eventSender.leapForward(500);
+            eventSender.mouseUp();
+
+            write("");
+            write("Undoing drag and drop");
+            document.execCommand("Undo");
+
+            write("");
+            write("Redoing drag and drop");
+            document.execCommand("Redo");
+        }
+
+        function logInputEvent(event)
+        {
+            write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=""
+        }
+
+        function moveToCenter(element)
+        {
+            let x = element.offsetParent.offsetLeft + element.offsetLeft + element.offsetWidth / 2;
+            let y = element.offsetParent.offsetTop + element.offsetTop + element.offsetHeight / 2;
+            eventSender.mouseMoveTo(x, y);
+        }
+    </script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/input-events-insert-by-drop-expected.txt (0 => 208014)


--- trunk/LayoutTests/fast/events/input-events-insert-by-drop-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-insert-by-drop-expected.txt	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,10 @@
+To manually test this, drag the text into the contenteditable, and then into the textarea. Observe the output. You should see a pair of insertFromDrop events dispatched on richDestination followed by another pair of insertFromDrop events dispatched on plainDestination.
+
+WebKit
+WebKit
+
+(richDestination): type=beforeinput, inputType=insertFromDrop, data="" dataTransfer={rich:WebKit plain:WebKit}
+(richDestination): type=input, inputType=insertFromDrop, data="" dataTransfer={rich:WebKit plain:WebKit}
+(plainDestination): type=beforeinput, inputType=insertFromDrop, data="" dataTransfer=(null)
+(plainDestination): type=input, inputType=insertFromDrop, data="" dataTransfer=(null)
+

Added: trunk/LayoutTests/fast/events/input-events-insert-by-drop.html (0 => 208014)


--- trunk/LayoutTests/fast/events/input-events-insert-by-drop.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-insert-by-drop.html	2016-10-27 22:46:46 UTC (rev 208014)
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <style>
+        #source, #richDestination, #plainDestination {
+            font-size: 30px;
+            border: 1px blue dashed;
+            width: 100px;
+        }
+    </style>
+    <p>To manually test this, drag the text into the contenteditable, and then into the textarea. Observe the output.
+    You should see a pair of insertFromDrop events dispatched on richDestination followed by another pair of
+    insertFromDrop events dispatched on plainDestination.</p>
+    <div id="source">WebKit</div>
+    <div id="richDestination" contenteditable _onbeforeinput_=logInputEvent(event) _oninput_=logInputEvent(event)></div>
+    <textarea id="plainDestination" _onbeforeinput_=logInputEvent(event) _oninput_=logInputEvent(event)></textarea>
+    <div id="output"></div>
+    <script type="text/_javascript_">
+        if (window.internals && window.testRunner) {
+            internals.settings.setInputEventsEnabled(true);
+            testRunner.dumpAsText();
+        }
+
+        if (window.eventSender) {
+            moveToCenter(source);
+            doubleClick();
+            eventSender.leapForward(1000);
+
+            eventSender.mouseDown();
+            eventSender.leapForward(1000);
+            moveToCenter(richDestination);
+            eventSender.leapForward(1000);
+            eventSender.mouseUp();
+            eventSender.leapForward(1000);
+
+            moveToCenter(source);
+            doubleClick();
+            eventSender.leapForward(1000);
+
+            eventSender.mouseDown();
+            eventSender.leapForward(1000);
+            moveToCenter(plainDestination);
+            eventSender.leapForward(1000);
+            eventSender.mouseUp();
+        }
+
+        function dataTransferToString(dataTransfer)
+        {
+            if (!dataTransfer)
+                return "(null)"
+
+            return `{rich:${dataTransfer.getData("text/html")} plain:${dataTransfer.getData("text/plain")}}`;
+        }
+
+        function logInputEvent(event)
+        {
+            output.innerHTML += `(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data="" dataTransfer=${dataTransferToString(event.dataTransfer)}<br>`;
+        }
+
+        function doubleClick() {
+            eventSender.mouseDown();
+            eventSender.mouseUp();
+            eventSender.leapForward(100);
+            eventSender.mouseDown();
+            eventSender.mouseUp();
+        }
+
+        function moveToCenter(element)
+        {
+            let x = element.offsetParent.offsetLeft + element.offsetLeft + element.offsetWidth / 2;
+            let y = element.offsetParent.offsetTop + element.offsetTop + element.offsetHeight / 2;
+            eventSender.mouseMoveTo(x, y);
+        }
+    </script>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (208013 => 208014)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1205,6 +1205,8 @@
 fast/events/frame-tab-focus.html [ Failure ]
 fast/events/ime-composition-events-001.html [ Failure ]
 fast/events/inputText-never-fired-on-keydown-cancel.html [ Failure ]
+fast/events/input-events-drag-and-drop.html [ Failure ]
+fast/events/input-events-insert-by-drop.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 ]
@@ -1226,6 +1228,7 @@
 fast/events/before-input-delete-empty-list-target-ranges.html [ Failure ]
 fast/events/before-input-events-prevent-recomposition.html [ Failure ]
 fast/events/before-input-events-prevent-insert-composition.html [ Failure ]
+fast/events/before-input-events-prevent-drag-and-drop.html [ Failure ]
 fast/events/key-events-in-input-button.html [ Failure ]
 fast/events/keydown-1.html [ Failure ]
 fast/events/keydown-leftright-keys.html [ Failure ]

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (208013 => 208014)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2016-10-27 22:46:46 UTC (rev 208014)
@@ -173,6 +173,10 @@
 fast/events/drag-selects-image.html
 fast/events/remove-target-with-shadow-in-drag.html
 
+fast/events/before-input-events-prevent-drag-and-drop.html [ Failure ]
+fast/events/input-events-drag-and-drop.html [ Failure ]
+fast/events/input-events-insert-by-drop.html [ Failure ]
+
 webkit.org/b/81833 fast/events/drag-and-drop-link-into-focused-contenteditable.html [ Failure ]
 
 # Missing functionality of textInputController

Modified: trunk/Source/WebCore/ChangeLog (208013 => 208014)


--- trunk/Source/WebCore/ChangeLog	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/ChangeLog	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1,3 +1,80 @@
+2016-10-27  Wenson Hsieh  <[email protected]>
+
+        Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163948
+        <rdar://problem/28921433>
+
+        Reviewed by Darin Adler.
+
+        Implements support for "insertFromDrop" and "deleteByDrag" inputTypes. These are fired when dragging and
+        dropping text in editable areas. To do this, we introduce EditActionInsertFromDrop and EditActionDeleteByDrag
+        (renamed from EditActionDrag, which is no longer necessary after this patch).
+
+        When moving text from an editable element to another, we will use a DeleteSelectionCommand to delete the text
+        from the source element and a ReplaceSelectionCommand to insert the text into the destination element. This
+        means that we currently fire two input events on the source and destination elements (i.e. given by the start
+        and end selections) after both child editing commands of the MoveSelectionCommand have been applied. Instead, we
+        need to fire events in this order:
+
+        1. beforeinput ("deleteByDrag") on the source
+        2. Update DOM
+        3. input ("deleteByDrag") on the source
+
+        4. beforeinput ("insertFromDrop") on the destination
+        5. Update DOM
+        6. input ("insertFromDrop") on the destination
+
+        To accomplish this, we allow an edit command to defer dispatching input events to its child commands via
+        CompositeEditCommand::shouldDispatchInputEvents, which the MoveSelectionCommand overrides. Additionally,
+        when applying the MoveSelectionCommand, we now apply() the child DeleteSelectionCommand and
+        ReplaceSelectionCommand instead of using doApply(). This allows these children to separately dispatch input
+        events, and also handle preventDefault() separately.
+
+        Tests: fast/events/before-input-events-prevent-drag-and-drop.html
+               fast/events/input-events-drag-and-drop.html
+               fast/events/input-events-insert-by-drop.html
+
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::apply):
+        (WebCore::CompositeEditCommand::composition):
+
+        Searches for the top-level command and returns its composition. Also ASSERTs that the m_command of all child
+        commands along the way is null. In places where we used to ASSERT that command.composition() should be null, we
+        now perform the assertion here instead.
+
+        * editing/CompositeEditCommand.h:
+        (WebCore::CompositeEditCommand::shouldDispatchInputEvents):
+
+        This is true by default, which means that if apply() is called for a composite edit command that does not
+        override this to return false, it will try to dispatch input events. In most cases, the parent command will call
+        on the child command to doApply(), bypassing this check.
+
+        (WebCore::CompositeEditCommand::composition): Deleted.
+        * editing/EditAction.h:
+        * editing/EditCommand.cpp:
+        (WebCore::inputTypeNameForEditingAction):
+        (WebCore::EditCommand::isEditingTextAreaOrTextInput):
+        (WebCore::EditCommand::setStartingSelection):
+        (WebCore::EditCommand::setEndingSelection):
+        (WebCore::EditCommand::setParent):
+        * editing/Editor.cpp:
+        (WebCore::Editor::willApplyEditing):
+        (WebCore::Editor::appliedEditing):
+
+        After applying editing, only adjust the current selection and notify clients of selection change if the applied
+        command was a top-level command; otherwise, these actions should wait until all child commands of the top-level
+        command have been applied. In particular, we should not register the applied command as an undo step.
+
+        * editing/MoveSelectionCommand.cpp:
+        (WebCore::MoveSelectionCommand::doApply):
+        (WebCore::MoveSelectionCommand::editingAction):
+        * editing/MoveSelectionCommand.h:
+        * page/DragController.cpp:
+        (WebCore::DragController::concludeEditDrag):
+
+        For the cases where we're not deleting text from the drag source (i.e. we're just applying a
+        ReplaceSelectionCommand) pass in EditActionInsertFromDrop as the EditAction when creating the command.
+
 2016-10-27  Per Arne Vollan  <[email protected]>
 
         [Win][Direct2D] Implement GraphicsContext::releaseWindowsContext.

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.cpp (208013 => 208014)


--- trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -343,12 +343,13 @@
         case EditActionTypingInsertPendingComposition:
         case EditActionTypingInsertFinalComposition:
         case EditActionPaste:
-        case EditActionDrag:
+        case EditActionDeleteByDrag:
         case EditActionSetWritingDirection:
         case EditActionCut:
         case EditActionUnspecified:
         case EditActionInsert:
         case EditActionInsertReplacement:
+        case EditActionInsertFromDrop:
         case EditActionDelete:
         case EditActionDictation:
             break;
@@ -405,6 +406,17 @@
     return nullptr;
 }
 
+EditCommandComposition* CompositeEditCommand::composition() const
+{
+    for (auto* command = this; command; command = command->parent()) {
+        if (auto composition = command->m_composition) {
+            ASSERT(!command->parent());
+            return composition.get();
+        }
+    }
+    return nullptr;
+}
+
 EditCommandComposition* CompositeEditCommand::ensureComposition()
 {
     CompositeEditCommand* command = this;

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.h (208013 => 208014)


--- trunk/Source/WebCore/editing/CompositeEditCommand.h	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.h	2016-10-27 22:46:46 UTC (rev 208014)
@@ -105,7 +105,7 @@
 
     void apply();
     bool isFirstCommand(EditCommand* command) { return !m_commands.isEmpty() && m_commands.first() == command; }
-    EditCommandComposition* composition() { return m_composition.get(); }
+    EditCommandComposition* composition() const;
     EditCommandComposition* ensureComposition();
 
     virtual bool isCreateLinkCommand() const;
@@ -118,6 +118,7 @@
     virtual String inputEventTypeName() const;
     virtual String inputEventData() const { return { }; }
     virtual bool isBeforeInputEventCancelable() const { return true; }
+    virtual bool shouldDispatchInputEvents() const { return true; }
     Vector<RefPtr<StaticRange>> targetRangesForBindings() const;
     virtual RefPtr<DataTransfer> inputEventDataTransfer() const;
 

Modified: trunk/Source/WebCore/editing/EditAction.h (208013 => 208014)


--- trunk/Source/WebCore/editing/EditAction.h	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/EditAction.h	2016-10-27 22:46:46 UTC (rev 208014)
@@ -31,6 +31,7 @@
         EditActionUnspecified,
         EditActionInsert,
         EditActionInsertReplacement,
+        EditActionInsertFromDrop,
         EditActionSetColor,
         EditActionSetBackgroundColor,
         EditActionTurnOffKerning,
@@ -55,7 +56,7 @@
         EditActionUnderline,
         EditActionOutline,
         EditActionUnscript,
-        EditActionDrag,
+        EditActionDeleteByDrag,
         EditActionCut,
         EditActionBold,
         EditActionItalics,

Modified: trunk/Source/WebCore/editing/EditCommand.cpp (208013 => 208014)


--- trunk/Source/WebCore/editing/EditCommand.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/EditCommand.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -58,7 +58,7 @@
         return ASCIILiteral("formatUnderline");
     case EditActionSetColor:
         return ASCIILiteral("formatForeColor");
-    case EditActionDrag:
+    case EditActionDeleteByDrag:
         return ASCIILiteral("deleteByDrag");
     case EditActionCut:
         return ASCIILiteral("deleteByCut");
@@ -92,6 +92,8 @@
         return ASCIILiteral("insertText");
     case EditActionInsertReplacement:
         return ASCIILiteral("insertReplacementText");
+    case EditActionInsertFromDrop:
+        return ASCIILiteral("insertFromDrop");
     case EditActionTypingInsertLineBreak:
         return ASCIILiteral("insertLineBreak");
     case EditActionTypingInsertParagraph:
@@ -178,10 +180,8 @@
 void EditCommand::setStartingSelection(const VisibleSelection& s)
 {
     for (EditCommand* cmd = this; ; cmd = cmd->m_parent) {
-        if (EditCommandComposition* composition = compositionIfPossible(cmd)) {
-            ASSERT(cmd->isTopLevelCommand());
+        if (auto* composition = compositionIfPossible(cmd))
             composition->setStartingSelection(s);
-        }
         cmd->m_startingSelection = s;
         if (!cmd->m_parent || cmd->m_parent->isFirstCommand(cmd))
             break;
@@ -191,10 +191,8 @@
 void EditCommand::setEndingSelection(const VisibleSelection &s)
 {
     for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) {
-        if (EditCommandComposition* composition = compositionIfPossible(cmd)) {
-            ASSERT(cmd->isTopLevelCommand());
+        if (auto* composition = compositionIfPossible(cmd))
             composition->setEndingSelection(s);
-        }
         cmd->m_endingSelection = s;
     }
 }
@@ -202,7 +200,6 @@
 void EditCommand::setParent(CompositeEditCommand* parent)
 {
     ASSERT((parent && !m_parent) || (!parent && m_parent));
-    ASSERT(!parent || !isCompositeEditCommand() || !toCompositeEditCommand(this)->composition());
     m_parent = parent;
     if (parent) {
         m_startingSelection = parent->m_endingSelection;

Modified: trunk/Source/WebCore/editing/Editor.cpp (208013 => 208014)


--- trunk/Source/WebCore/editing/Editor.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/Editor.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1083,6 +1083,9 @@
 
 bool Editor::willApplyEditing(CompositeEditCommand& command, Vector<RefPtr<StaticRange>>&& targetRanges) const
 {
+    if (!command.shouldDispatchInputEvents())
+        return true;
+
     auto* composition = command.composition();
     if (!composition)
         return true;
@@ -1102,31 +1105,36 @@
 
     notifyTextFromControls(composition->startingRootEditableElement(), composition->endingRootEditableElement());
 
-    // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
-    FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
-    
-    changeSelectionAfterCommand(newSelection, options);
-    dispatchInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), cmd->inputEventTypeName(), cmd->inputEventData(), cmd->inputEventDataTransfer());
+    if (cmd->isTopLevelCommand()) {
+        // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
+        FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
 
-    updateEditorUINowIfScheduled();
-    
-    m_alternativeTextController->respondToAppliedEditing(cmd.get());
+        changeSelectionAfterCommand(newSelection, options);
+    }
 
-    if (!cmd->preservesTypingStyle())
-        m_frame.selection().clearTypingStyle();
+    if (cmd->shouldDispatchInputEvents())
+        dispatchInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), cmd->inputEventTypeName(), cmd->inputEventData(), cmd->inputEventDataTransfer());
 
-    // Command will be equal to last edit command only in the case of typing
-    if (m_lastEditCommand.get() == cmd)
-        ASSERT(cmd->isTypingCommand());
-    else {
-        // Only register a new undo command if the command passed in is
-        // different from the last command
-        m_lastEditCommand = cmd;
-        if (client())
-            client()->registerUndoStep(m_lastEditCommand->ensureComposition());
+    if (cmd->isTopLevelCommand()) {
+        updateEditorUINowIfScheduled();
+
+        m_alternativeTextController->respondToAppliedEditing(cmd.get());
+
+        if (!cmd->preservesTypingStyle())
+            m_frame.selection().clearTypingStyle();
+
+        // Command will be equal to last edit command only in the case of typing
+        if (m_lastEditCommand.get() == cmd)
+            ASSERT(cmd->isTypingCommand());
+        else {
+            // Only register a new undo command if the command passed in is
+            // different from the last command
+            m_lastEditCommand = cmd;
+            if (client())
+                client()->registerUndoStep(m_lastEditCommand->ensureComposition());
+        }
+        respondToChangedContents(newSelection);
     }
-
-    respondToChangedContents(newSelection);
 }
 
 bool Editor::willUnapplyEditing(const EditCommandComposition& composition) const

Modified: trunk/Source/WebCore/editing/MoveSelectionCommand.cpp (208013 => 208014)


--- trunk/Source/WebCore/editing/MoveSelectionCommand.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/MoveSelectionCommand.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "MoveSelectionCommand.h"
 
+#include "DeleteSelectionCommand.h"
 #include "DocumentFragment.h"
 #include "ReplaceSelectionCommand.h"
 
@@ -60,7 +61,12 @@
             pos.moveToOffset(pos.offsetInContainerNode() + selectionStart.offsetInContainerNode());
     }
 
-    deleteSelection(m_smartDelete);
+    {
+        auto deleteSelection = DeleteSelectionCommand::create(document(), m_smartDelete, true, false, true, true, EditActionDeleteByDrag);
+        deleteSelection->setParent(this);
+        deleteSelection->apply();
+        m_commands.append(WTFMove(deleteSelection));
+    }
 
     // If the node for the destination has been removed as a result of the deletion,
     // set the destination to the ending point after the deletion.
@@ -72,6 +78,7 @@
     cleanupAfterDeletion(pos);
 
     setEndingSelection(VisibleSelection(pos, endingSelection().affinity(), endingSelection().isDirectional()));
+    setStartingSelection(endingSelection());
     if (!pos.anchorNode()->inDocument()) {
         // Document was modified out from under us.
         return;
@@ -79,12 +86,18 @@
     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
     if (m_smartInsert)
         options |= ReplaceSelectionCommand::SmartReplace;
-    applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(m_fragment), options));
+
+    {
+        auto replaceSelection = ReplaceSelectionCommand::create(document(), WTFMove(m_fragment), options, EditActionInsertFromDrop);
+        replaceSelection->setParent(this);
+        replaceSelection->apply();
+        m_commands.append(WTFMove(replaceSelection));
+    }
 }
 
 EditAction MoveSelectionCommand::editingAction() const
 {
-    return EditActionDrag;
+    return EditActionDeleteByDrag;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/MoveSelectionCommand.h (208013 => 208014)


--- trunk/Source/WebCore/editing/MoveSelectionCommand.h	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/editing/MoveSelectionCommand.h	2016-10-27 22:46:46 UTC (rev 208014)
@@ -44,6 +44,7 @@
 
     virtual void doApply();
     virtual EditAction editingAction() const;
+    bool shouldDispatchInputEvents() const final { return false; }
     
     RefPtr<DocumentFragment> m_fragment;
     Position m_position;

Modified: trunk/Source/WebCore/page/DragController.cpp (208013 => 208014)


--- trunk/Source/WebCore/page/DragController.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebCore/page/DragController.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -532,7 +532,7 @@
                     options |= ReplaceSelectionCommand::SmartReplace;
                 if (chosePlainText)
                     options |= ReplaceSelectionCommand::MatchStyle;
-                applyCommand(ReplaceSelectionCommand::create(*m_documentUnderMouse, WTFMove(fragment), options));
+                applyCommand(ReplaceSelectionCommand::create(*m_documentUnderMouse, WTFMove(fragment), options, EditActionInsertFromDrop));
             }
         }
     } else {
@@ -543,7 +543,7 @@
 
         m_client.willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
         if (setSelectionToDragCaret(innerFrame.get(), dragCaret, range, point))
-            applyCommand(ReplaceSelectionCommand::create(*m_documentUnderMouse, createFragmentFromText(*range, text),  ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting));
+            applyCommand(ReplaceSelectionCommand::create(*m_documentUnderMouse, createFragmentFromText(*range, text),  ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting, EditActionInsertFromDrop));
     }
 
     if (rootEditableElement) {

Modified: trunk/Source/WebKit/mac/ChangeLog (208013 => 208014)


--- trunk/Source/WebKit/mac/ChangeLog	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit/mac/ChangeLog	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1,3 +1,16 @@
+2016-10-27  Wenson Hsieh  <[email protected]>
+
+        Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163948
+        <rdar://problem/28921433>
+
+        Reviewed by Darin Adler.
+
+        Add support for new drag and drop-related EditAction enum values.
+
+        * WebCoreSupport/WebEditorClient.mm:
+        (undoNameForEditAction):
+
 2016-10-27  Dan Bernstein  <[email protected]>
 
         Reapplied the configuration changes from r207934 without breaking iOS builds.

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm (208013 => 208014)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm	2016-10-27 22:46:46 UTC (rev 208014)
@@ -564,6 +564,7 @@
         case EditActionUnspecified: return nil;
         case EditActionInsert: return nil;
         case EditActionInsertReplacement: return nil;
+        case EditActionInsertFromDrop: return nil;
         case EditActionSetColor: return UI_STRING_KEY_INTERNAL("Set Color", "Set Color (Undo action name)", "Undo action name");
         case EditActionSetBackgroundColor: return UI_STRING_KEY_INTERNAL("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
         case EditActionTurnOffKerning: return UI_STRING_KEY_INTERNAL("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
@@ -588,7 +589,7 @@
         case EditActionUnderline: return UI_STRING_KEY_INTERNAL("Underline", "Underline (Undo action name)", "Undo action name");
         case EditActionOutline: return UI_STRING_KEY_INTERNAL("Outline", "Outline (Undo action name)", "Undo action name");
         case EditActionUnscript: return UI_STRING_KEY_INTERNAL("Unscript", "Unscript (Undo action name)", "Undo action name");
-        case EditActionDrag: return UI_STRING_KEY_INTERNAL("Drag", "Drag (Undo action name)", "Undo action name");
+        case EditActionDeleteByDrag: return UI_STRING_KEY_INTERNAL("Drag", "Drag (Undo action name)", "Undo action name");
         case EditActionCut: return UI_STRING_KEY_INTERNAL("Cut", "Cut (Undo action name)", "Undo action name");
         case EditActionPaste: return UI_STRING_KEY_INTERNAL("Paste", "Paste (Undo action name)", "Undo action name");
         case EditActionPasteFont: return UI_STRING_KEY_INTERNAL("Paste Font", "Paste Font (Undo action name)", "Undo action name");

Modified: trunk/Source/WebKit/win/ChangeLog (208013 => 208014)


--- trunk/Source/WebKit/win/ChangeLog	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit/win/ChangeLog	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1,3 +1,16 @@
+2016-10-27  Wenson Hsieh  <[email protected]>
+
+        Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163948
+        <rdar://problem/28921433>
+
+        Reviewed by Darin Adler.
+
+        Add support for new drag and drop-related EditAction enum values.
+
+        * WebCoreSupport/WebEditorClient.cpp:
+        (undoNameForEditAction):
+
 2016-10-26  Brian Burg  <[email protected]>
 
         Web Inspector: remove unused bool return value from FrontendChannel::sendMessageToFrontend

Modified: trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp (208013 => 208014)


--- trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -592,7 +592,7 @@
     case EditActionUnderline: return WEB_UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
     case EditActionOutline: return WEB_UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
     case EditActionUnscript: return WEB_UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
-    case EditActionDrag: return WEB_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
+    case EditActionDeleteByDrag: return WEB_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
     case EditActionCut: return WEB_UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
     case EditActionPaste: return WEB_UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
     case EditActionPasteFont: return WEB_UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");

Modified: trunk/Source/WebKit2/ChangeLog (208013 => 208014)


--- trunk/Source/WebKit2/ChangeLog	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit2/ChangeLog	2016-10-27 22:46:46 UTC (rev 208014)
@@ -1,3 +1,16 @@
+2016-10-27  Wenson Hsieh  <[email protected]>
+
+        Support "insertFromDrop" and "deleteByDrag" for the InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163948
+        <rdar://problem/28921433>
+
+        Reviewed by Darin Adler.
+
+        Add support for new drag and drop-related EditAction enum values.
+
+        * UIProcess/WebEditCommandProxy.cpp:
+        (WebKit::WebEditCommandProxy::nameForEditAction):
+
 2016-10-26  Chris Dumez  <[email protected]>
 
         Replace IDBKeyPath with a WTF::Variant

Modified: trunk/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp (208013 => 208014)


--- trunk/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp	2016-10-27 22:37:21 UTC (rev 208013)
+++ trunk/Source/WebKit2/UIProcess/WebEditCommandProxy.cpp	2016-10-27 22:46:46 UTC (rev 208014)
@@ -73,10 +73,9 @@
     // FIXME: This is identical to code in WebKit's WebEditorClient class; would be nice to share the strings instead of having two copies.
     switch (editAction) {
     case EditActionUnspecified:
-        return String();
     case EditActionInsert:
-        return String();
     case EditActionInsertReplacement:
+    case EditActionInsertFromDrop:
         return String();
     case EditActionSetColor:
         return WEB_UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
@@ -126,7 +125,7 @@
         return WEB_UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
     case EditActionUnscript:
         return WEB_UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
-    case EditActionDrag:
+    case EditActionDeleteByDrag:
         return WEB_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
     case EditActionCut:
         return WEB_UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to