<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[208143] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/208143">208143</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2016-10-31 08:12:00 -0700 (Mon, 31 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Holding down a key to choose an accented character should fire &quot;insertReplacementText&quot; input events
https://bugs.webkit.org/show_bug.cgi?id=164209
&lt;rdar://problem/29019305&gt;

Reviewed by Darin Adler.

Source/WebCore:

For TypingCommands that correspond to &quot;insertReplacementText&quot; inputTypes, vend dataTransfers for resulting
beforeinput and input events if the edited area is not an input field or textarea. To do this, convert the plain
text representation of the content to be inserted to HTML text using a helper function,
MarkupAccumulator::appendCharactersReplacingEntities, that is used when creating markup for Text nodes.

Tests: fast/events/before-input-prevent-insert-replacement.html
       fast/events/input-event-insert-replacement.html

* editing/TypingCommand.cpp:
(WebCore::TypingCommand::inputEventData):
(WebCore::TypingCommand::inputEventDataTransfer):
* editing/TypingCommand.h:

Source/WebKit2:

When replacing text, call Editor::insertText with the correct TextEventInputType so that WebCore will know to
use EditActionInsertReplacement when creating and applying the corresponding TypingCommand. Additional minor
changes in order to support testing replacement text insertion.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _insertText:replacementRange:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::insertTextAsync):

Tools:

Adds test support for inserting replacement text on Mac. This is equivalent to holding down a vowel key (e.g.
'a') to bring up the menu containing accented version of the character, then selecting an accented character to
insert in place of the typed character. This is exposed via UIScriptController.insertText, which takes a string
and an insertion range.

* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::insertText):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:

Note that there is no callback argument to insertText, since UIScriptController::insertText is synchronous in
the UI process. The tests end when corresponding input events fired as a result of insertText have been received
in the web process. Please see the new layout tests for more detail.

* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::insertText):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::nsStringFromJSString):
(WTR::UIScriptController::insertText):

LayoutTests:

Adds 2 new layout tests to verify that inserting replacement text fires input events of inputType
&quot;insertReplacementText&quot; instead of the generic &quot;insertText&quot;, and that calling preventDefault() on the
beforeinput event prevents text from being inserted. Also checks that inserting replacement text in
contenteditable areas causes the dataTransfer attribute to be populated, and that the data attribute is null.

* fast/events/before-input-prevent-insert-replacement-expected.txt: Added.
* fast/events/before-input-prevent-insert-replacement.html: Added.
* fast/events/input-event-insert-replacement-expected.txt: Added.
* fast/events/input-event-insert-replacement.html: Added.
* platform/ios-simulator/TestExpectations:
* platform/mac-wk1/TestExpectations:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsplatformmacwk1TestExpectations">trunk/LayoutTests/platform/mac-wk1/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreeditingTypingCommandcpp">trunk/Source/WebCore/editing/TypingCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingTypingCommandh">trunk/Source/WebCore/editing/TypingCommand.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreemacUIScriptControllerMacmm">trunk/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm</a></li>
<li><a href="#trunkToolsTestRunnerSharedUIScriptContextBindingsUIScriptControlleridl">trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl</a></li>
<li><a href="#trunkToolsTestRunnerSharedUIScriptContextUIScriptControllercpp">trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp</a></li>
<li><a href="#trunkToolsTestRunnerSharedUIScriptContextUIScriptControllerh">trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnermacUIScriptControllerMacmm">trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasteventsbeforeinputpreventinsertreplacementexpectedtxt">trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeinputpreventinsertreplacementhtml">trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventinsertreplacementexpectedtxt">trunk/LayoutTests/fast/events/input-event-insert-replacement-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventinsertreplacementhtml">trunk/LayoutTests/fast/events/input-event-insert-replacement.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/LayoutTests/ChangeLog        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2016-10-31  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Holding down a key to choose an accented character should fire &quot;insertReplacementText&quot; input events
+        https://bugs.webkit.org/show_bug.cgi?id=164209
+        &lt;rdar://problem/29019305&gt;
+
+        Reviewed by Darin Adler.
+
+        Adds 2 new layout tests to verify that inserting replacement text fires input events of inputType
+        &quot;insertReplacementText&quot; instead of the generic &quot;insertText&quot;, and that calling preventDefault() on the
+        beforeinput event prevents text from being inserted. Also checks that inserting replacement text in
+        contenteditable areas causes the dataTransfer attribute to be populated, and that the data attribute is null.
+
+        * fast/events/before-input-prevent-insert-replacement-expected.txt: Added.
+        * fast/events/before-input-prevent-insert-replacement.html: Added.
+        * fast/events/input-event-insert-replacement-expected.txt: Added.
+        * fast/events/input-event-insert-replacement.html: Added.
+        * platform/ios-simulator/TestExpectations:
+        * platform/mac-wk1/TestExpectations:
+
</ins><span class="cx"> 2016-10-30  Gyuyoung Kim  &lt;gyuyoung.kim@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Skip media tests because timeout happens on many media tests.
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeinputpreventinsertreplacementexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement-expected.txt (0 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement-expected.txt        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+a
+Typing 'a'...
+(editable): type=beforeinput, inputType=insertText, data=`a`, dataTransfer=`null`
+(editable): type=input, inputType=insertText, data=`a`, dataTransfer=`null`
+Attempting to replace 'a' with 'b'...
+(editable): type=beforeinput, inputType=insertReplacementText, data=`null`, dataTransfer=`plain:&quot;b&quot;, html:&quot;b&quot;`
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeinputpreventinsertreplacementhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement.html (0 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/before-input-prevent-insert-replacement.html        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+    &lt;div id=&quot;editable&quot; onbeforeinput=handleInputEvent(event) oninput=handleInputEvent(event) contenteditable&gt;&lt;/div&gt;
+    &lt;div id=&quot;output&quot;&gt;&lt;/div&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;
+        let write = s =&gt; output.innerHTML += s + &quot;&lt;br&gt;&quot;;
+        var progress = 0;
+        editable.focus();
+
+        if (window.internals &amp;&amp; window.testRunner) {
+            internals.settings.setInputEventsEnabled(true);
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+            if (window.eventSender &amp;&amp; testRunner.runUIScript) {
+                write(&quot;Typing 'a'...&quot;);
+                eventSender.keyDown(&quot;a&quot;);
+                write(&quot;Attempting to replace 'a' with 'b'...&quot;);
+                testRunner.runUIScript(getUIScript(), (result) =&gt; incrementProgress());
+            }
+        } else {
+            write(&quot;To manually test, press and hold down 'a' and select one of the accented characters.&quot;);
+            write(&quot;You should observe that the replacement accented character does not replace 'a'.&quot;);
+        }
+
+        function incrementProgress()
+        {
+            progress++;
+            if (progress == 2)
+                testRunner.notifyDone();
+        }
+
+        function handleInputEvent(event)
+        {
+            write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=\`${event.data}\`, dataTransfer=\`${dataTransferAsString(event.dataTransfer)}\``);
+            if (event.inputType === &quot;insertReplacementText&quot;) {
+                event.preventDefault();
+                incrementProgress();
+            }
+        }
+
+        function dataTransferAsString(dataTransfer)
+        {
+            if (!dataTransfer)
+                return &quot;null&quot;;
+
+            return `plain:&quot;${dataTransfer.getData('text/plain')}&quot;, html:&quot;${dataTransfer.getData('text/html')}&quot;`;
+        }
+
+        function getUIScript()
+        {
+            return `
+            (function() {
+                uiController.insertText(&quot;b&quot;, 0, 1);
+                uiController.uiScriptComplete();
+            })();`
+        }
+    &lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventinsertreplacementexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-event-insert-replacement-expected.txt (0 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-event-insert-replacement-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-event-insert-replacement-expected.txt        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+
+Typing 'a'...
+(editable): type=beforeinput, inputType=insertText, data=`a`, dataTransfer=`null`
+(editable): type=input, inputType=insertText, data=`a`, dataTransfer=`null`
+The value of the input is now: a
+
+Replacing 'a' with 'b'...
+(editable): type=beforeinput, inputType=insertReplacementText, data=`b`, dataTransfer=`null`
+(editable): type=input, inputType=insertReplacementText, data=`b`, dataTransfer=`null`
+The value of the input is now: b
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventinsertreplacementhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-event-insert-replacement.html (0 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-event-insert-replacement.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-event-insert-replacement.html        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+    &lt;input id=&quot;editable&quot; onbeforeinput=logInputEvent(event) oninput=logInputEvent(event)&gt;&lt;/input&gt;
+    &lt;div id=&quot;output&quot;&gt;&lt;/div&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;
+        let write = s =&gt; output.innerHTML += s + &quot;&lt;br&gt;&quot;;
+        var progress = 0;
+        editable.focus();
+
+        if (window.internals &amp;&amp; window.testRunner) {
+            internals.settings.setInputEventsEnabled(true);
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+            if (window.eventSender &amp;&amp; testRunner.runUIScript) {
+                write(&quot;Typing 'a'...&quot;);
+                eventSender.keyDown(&quot;a&quot;);
+                write(`The value of the input is now: ${editable.value}`);
+                write(&quot;&quot;);
+                write(&quot;Replacing 'a' with 'b'...&quot;);
+                testRunner.runUIScript(getUIScript(), (result) =&gt; incrementProgress());
+            }
+        } else {
+            write(&quot;To manually test, press and hold down 'a' and select one of the accented characters.&quot;);
+            write(&quot;You should observe a pair of beforeinput/input events for both 'a' and the replacement accented character.&quot;);
+            write(&quot;Importantly, the inputType of the last two events should be 'insertReplacementText'.&quot;);
+        }
+
+        function incrementProgress()
+        {
+            progress++;
+            if (progress != 5)
+                return;
+
+            write(`The value of the input is now: ${editable.value}`);
+            testRunner.notifyDone();
+        }
+
+        function logInputEvent(event)
+        {
+            write(`(${event.target.id}): type=${event.type}, inputType=${event.inputType}, data=\`${event.data}\`, dataTransfer=\`${event.dataTransfer}\``);
+            incrementProgress();
+        }
+
+        function getUIScript()
+        {
+            return `
+            (function() {
+                uiController.insertText(&quot;b&quot;, 0, 1);
+                uiController.uiScriptComplete();
+            })();`
+        }
+    &lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -1202,6 +1202,7 @@
</span><span class="cx"> fast/events/frame-tab-focus.html [ Failure ]
</span><span class="cx"> fast/events/ime-composition-events-001.html [ Failure ]
</span><span class="cx"> fast/events/inputText-never-fired-on-keydown-cancel.html [ Failure ]
</span><ins>+fast/events/input-event-insert-replacement.html [ Failure ]
</ins><span class="cx"> fast/events/input-events-drag-and-drop.html [ Failure ]
</span><span class="cx"> fast/events/input-events-insert-by-drop.html [ Failure ]
</span><span class="cx"> fast/events/input-events-fired-when-typing.html [ Failure ]
</span><span class="lines">@@ -1212,6 +1213,7 @@
</span><span class="cx"> fast/events/input-events-ime-composition.html [ Failure ]
</span><span class="cx"> fast/events/input-events-paste-rich-datatransfer.html [ Failure ]
</span><span class="cx"> fast/events/input-events-spell-checking-datatransfer.html [ Failure ]
</span><ins>+fast/events/before-input-prevent-insert-replacement.html [ Failure ]
</ins><span class="cx"> fast/events/before-input-events-prevent-default.html [ Failure ]
</span><span class="cx"> fast/events/before-input-events-prevent-default-in-textfield.html [ Failure ]
</span><span class="cx"> fast/events/before-input-events-different-start-end-elements.html [ Failure ]
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacwk1TestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-wk1/TestExpectations        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -84,6 +84,10 @@
</span><span class="cx"> # WK1 and WK2 mousemove events are subtly different in ways that break this test on WK1.
</span><span class="cx"> fast/events/ghostly-mousemoves-in-subframe.html [ Skip ]
</span><span class="cx"> 
</span><ins>+# Test support for inserting special characters is not yet implemented on WK1.
+fast/events/before-input-prevent-insert-replacement.html [ Skip ]
+fast/events/input-event-insert-replacement.html [ Skip ]
+
</ins><span class="cx"> # Media Stream API testing is not supported for WK1 yet.
</span><span class="cx"> fast/mediastream
</span><span class="cx"> http/tests/media/media-stream
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebCore/ChangeLog        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-10-31  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Holding down a key to choose an accented character should fire &quot;insertReplacementText&quot; input events
+        https://bugs.webkit.org/show_bug.cgi?id=164209
+        &lt;rdar://problem/29019305&gt;
+
+        Reviewed by Darin Adler.
+
+        For TypingCommands that correspond to &quot;insertReplacementText&quot; inputTypes, vend dataTransfers for resulting
+        beforeinput and input events if the edited area is not an input field or textarea. To do this, convert the plain
+        text representation of the content to be inserted to HTML text using a helper function,
+        MarkupAccumulator::appendCharactersReplacingEntities, that is used when creating markup for Text nodes.
+
+        Tests: fast/events/before-input-prevent-insert-replacement.html
+               fast/events/input-event-insert-replacement.html
+
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::inputEventData):
+        (WebCore::TypingCommand::inputEventDataTransfer):
+        * editing/TypingCommand.h:
+
</ins><span class="cx"> 2016-10-30  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CSS Parser] Miscellaneous bug fixes
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTypingCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TypingCommand.cpp (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TypingCommand.cpp        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebCore/editing/TypingCommand.cpp        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AXObjectCache.h&quot;
</span><span class="cx"> #include &quot;BreakBlockquoteCommand.h&quot;
</span><ins>+#include &quot;DataTransfer.h&quot;
</ins><span class="cx"> #include &quot;DeleteSelectionCommand.h&quot;
</span><span class="cx"> #include &quot;Document.h&quot;
</span><span class="cx"> #include &quot;Editor.h&quot;
</span><span class="lines">@@ -39,6 +40,7 @@
</span><span class="cx"> #include &quot;InsertParagraphSeparatorCommand.h&quot;
</span><span class="cx"> #include &quot;InsertTextCommand.h&quot;
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><ins>+#include &quot;MarkupAccumulator.h&quot;
</ins><span class="cx"> #include &quot;MathMLElement.h&quot;
</span><span class="cx"> #include &quot;RenderElement.h&quot;
</span><span class="cx"> #include &quot;StaticRange.h&quot;
</span><span class="lines">@@ -406,15 +408,26 @@
</span><span class="cx"> {
</span><span class="cx">     switch (m_currentTypingEditAction) {
</span><span class="cx">     case EditActionTypingInsertText:
</span><del>-    case EditActionInsertReplacement:
</del><span class="cx">     case EditActionTypingInsertPendingComposition:
</span><span class="cx">     case EditActionTypingInsertFinalComposition:
</span><span class="cx">         return m_currentTextToInsert;
</span><ins>+    case EditActionInsertReplacement:
+        return isEditingTextAreaOrTextInput() ? m_currentTextToInsert : String();
</ins><span class="cx">     default:
</span><span class="cx">         return CompositeEditCommand::inputEventData();
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr&lt;DataTransfer&gt; TypingCommand::inputEventDataTransfer() const
+{
+    if (m_currentTypingEditAction != EditActionInsertReplacement || isEditingTextAreaOrTextInput())
+        return nullptr;
+
+    StringBuilder htmlText;
+    MarkupAccumulator::appendCharactersReplacingEntities(htmlText, m_currentTextToInsert, 0, m_currentTextToInsert.length(), EntityMaskInHTMLPCDATA);
+    return DataTransfer::createForInputEvent(m_currentTextToInsert, htmlText.toString());
+}
+
</ins><span class="cx"> void TypingCommand::didApplyCommand()
</span><span class="cx"> {
</span><span class="cx">     // TypingCommands handle applied editing separately (see TypingCommand::typingAddedToOpenCommand).
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTypingCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TypingCommand.h (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TypingCommand.h        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebCore/editing/TypingCommand.h        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -120,6 +120,7 @@
</span><span class="cx"> 
</span><span class="cx">     String inputEventTypeName() const final;
</span><span class="cx">     String inputEventData() const final;
</span><ins>+    RefPtr&lt;DataTransfer&gt; inputEventDataTransfer() const final;
</ins><span class="cx">     bool isBeforeInputEventCancelable() const final;
</span><span class="cx"> 
</span><span class="cx">     static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Frame*);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebKit2/ChangeLog        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-10-31  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Holding down a key to choose an accented character should fire &quot;insertReplacementText&quot; input events
+        https://bugs.webkit.org/show_bug.cgi?id=164209
+        &lt;rdar://problem/29019305&gt;
+
+        Reviewed by Darin Adler.
+
+        When replacing text, call Editor::insertText with the correct TextEventInputType so that WebCore will know to
+        use EditActionInsertReplacement when creating and applying the corresponding TypingCommand. Additional minor
+        changes in order to support testing replacement text insertion.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _insertText:replacementRange:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::insertTextAsync):
+
</ins><span class="cx"> 2016-10-30  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move Element, NamedNodeMap, and DOMStringMap from ExceptionCode to Exception
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -4650,6 +4650,11 @@
</span><span class="cx"> {
</span><span class="cx">     // Overridden by subclasses.
</span><span class="cx"> }
</span><ins>+
+- (void)_insertText:(id)string replacementRange:(NSRange)replacementRange
+{
+    [self insertText:string replacementRange:replacementRange];
+}
</ins><span class="cx"> #endif // PLATFORM(MAC)
</span><span class="cx"> 
</span><span class="cx"> - (void)_setPageScale:(CGFloat)scale withOrigin:(CGPoint)origin
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -290,6 +290,8 @@
</span><span class="cx"> @property (nonatomic, readonly) BOOL _shouldRequestCandidates WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</span><span class="cx"> - (void)_requestActiveNowPlayingSessionInfo WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</span><span class="cx"> - (void)_handleActiveNowPlayingSessionInfoResponse:(BOOL)hasActiveSession title:(NSString *)title duration:(double)duration elapsedTime:(double)elapsedTime WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</span><ins>+
+- (void)_insertText:(id)string replacementRange:(NSRange)replacementRange WK_API_AVAILABLE(macosx(WK_MAC_TBA));
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> - (void)_setPageScale:(CGFloat)scale withOrigin:(CGPoint)origin WK_API_AVAILABLE(ios(WK_IOS_TBA));
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -4625,11 +4625,13 @@
</span><span class="cx"> {
</span><span class="cx">     Frame&amp; frame = m_page-&gt;focusController().focusedOrMainFrame();
</span><span class="cx"> 
</span><ins>+    bool replacesText = false;
</ins><span class="cx">     if (replacementEditingRange.location != notFound) {
</span><span class="cx">         RefPtr&lt;Range&gt; replacementRange = rangeFromEditingRange(frame, replacementEditingRange, static_cast&lt;EditingRangeIsRelativeTo&gt;(editingRangeIsRelativeTo));
</span><span class="cx">         if (replacementRange) {
</span><span class="cx">             TemporaryChange&lt;bool&gt; isSelectingTextWhileInsertingAsynchronously(m_isSelectingTextWhileInsertingAsynchronously, suppressSelectionUpdate);
</span><span class="cx">             frame.selection().setSelection(VisibleSelection(*replacementRange, SEL_DEFAULT_AFFINITY));
</span><ins>+            replacesText = true;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -4639,7 +4641,7 @@
</span><span class="cx">     if (!frame.editor().hasComposition()) {
</span><span class="cx">         // An insertText: might be handled by other responders in the chain if we don't handle it.
</span><span class="cx">         // One example is space bar that results in scrolling down the page.
</span><del>-        frame.editor().insertText(text, nullptr);
</del><ins>+        frame.editor().insertText(text, nullptr, replacesText ? TextEventInputAutocompletion : TextEventInputKeyboard);
</ins><span class="cx">     } else
</span><span class="cx">         frame.editor().confirmComposition(text);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/ChangeLog        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2016-10-31  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Holding down a key to choose an accented character should fire &quot;insertReplacementText&quot; input events
+        https://bugs.webkit.org/show_bug.cgi?id=164209
+        &lt;rdar://problem/29019305&gt;
+
+        Reviewed by Darin Adler.
+
+        Adds test support for inserting replacement text on Mac. This is equivalent to holding down a vowel key (e.g.
+        'a') to bring up the menu containing accented version of the character, then selecting an accented character to
+        insert in place of the typed character. This is exposed via UIScriptController.insertText, which takes a string
+        and an insertion range.
+
+        * DumpRenderTree/mac/UIScriptControllerMac.mm:
+        (WTR::UIScriptController::insertText):
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+
+        Note that there is no callback argument to insertText, since UIScriptController::insertText is synchronous in
+        the UI process. The tests end when corresponding input events fired as a result of insertText have been received
+        in the web process. Please see the new layout tests for more detail.
+
+        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+        (WTR::UIScriptController::insertText):
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        * WebKitTestRunner/mac/UIScriptControllerMac.mm:
+        (WTR::nsStringFromJSString):
+        (WTR::UIScriptController::insertText):
+
</ins><span class="cx"> 2016-10-30  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebIDL] Restructure IDLParser structs to better match modern WebIDL concepts
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacUIScriptControllerMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -43,6 +43,10 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UIScriptController::insertText(JSStringRef, int, int)
+{
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif // PLATFORM(MAC)
</span></span></pre></div>
<a id="trunkToolsTestRunnerSharedUIScriptContextBindingsUIScriptControlleridl"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -156,5 +156,7 @@
</span><span class="cx"> 
</span><span class="cx">     readonly attribute object selectionRangeViewRects; // An array of objects with 'left', 'top', 'width', and 'height' properties.
</span><span class="cx"> 
</span><ins>+    void insertText(DOMString text, long location, long length);
+
</ins><span class="cx">     void uiScriptComplete(DOMString result);
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkToolsTestRunnerSharedUIScriptContextUIScriptControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -317,6 +317,14 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if !PLATFORM(MAC)
+
+void UIScriptController::insertText(JSStringRef, int, int)
+{
+}
+
+#endif
+
</ins><span class="cx"> void UIScriptController::uiScriptComplete(JSStringRef result)
</span><span class="cx"> {
</span><span class="cx">     m_context-&gt;requestUIScriptCompletion(result);
</span></span></pre></div>
<a id="trunkToolsTestRunnerSharedUIScriptContextUIScriptControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -117,6 +117,8 @@
</span><span class="cx">     
</span><span class="cx">     JSObjectRef selectionRangeViewRects() const;
</span><span class="cx"> 
</span><ins>+    void insertText(JSStringRef, int location, int length);
+
</ins><span class="cx">     void uiScriptComplete(JSStringRef result);
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnermacUIScriptControllerMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm (208142 => 208143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm        2016-10-31 15:01:18 UTC (rev 208142)
+++ trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm        2016-10-31 15:12:00 UTC (rev 208143)
</span><span class="lines">@@ -26,10 +26,20 @@
</span><span class="cx"> #import &quot;config.h&quot;
</span><span class="cx"> #import &quot;UIScriptController.h&quot;
</span><span class="cx"> 
</span><ins>+#import &quot;PlatformWebView.h&quot;
+#import &quot;TestController.h&quot;
+#import &quot;TestRunnerWKWebView.h&quot;
</ins><span class="cx"> #import &quot;UIScriptContext.h&quot;
</span><ins>+#import &lt;JavaScriptCore/JSStringRefCF.h&gt;
+#import &lt;WebKit/WKWebViewPrivate.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WTR {
</span><span class="cx"> 
</span><ins>+NSString *nsString(JSStringRef string)
+{
+    return (NSString *)adoptCF(JSStringCopyCFString(kCFAllocatorDefault, string)).autorelease();
+}
+
</ins><span class="cx"> void UIScriptController::doAsyncTask(JSValueRef callback)
</span><span class="cx"> {
</span><span class="cx">     unsigned callbackID = m_context-&gt;prepareForAsyncTask(callback, CallbackTypeNonPersistent);
</span><span class="lines">@@ -41,4 +51,19 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UIScriptController::insertText(JSStringRef text, int location, int length)
+{
+#if WK_API_ENABLED
+    if (location == -1)
+        location = NSNotFound;
+
+    auto* webView = TestController::singleton().mainWebView()-&gt;platformView();
+    [webView _insertText:nsString(text) replacementRange:NSMakeRange(location, length)];
+#else
+    UNUSED_PARAM(text);
+    UNUSED_PARAM(location);
+    UNUSED_PARAM(length);
+#endif
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre>
</div>
</div>

</body>
</html>