Diff
Modified: trunk/LayoutTests/ChangeLog (208089 => 208090)
--- trunk/LayoutTests/ChangeLog 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/LayoutTests/ChangeLog 2016-10-29 01:06:13 UTC (rev 208090)
@@ -1,3 +1,19 @@
+2016-10-28 Wenson Hsieh <wenson_hs...@apple.com>
+
+ iOS autocorrection does not trigger an input event of inputType "insertReplacementText"
+ https://bugs.webkit.org/show_bug.cgi?id=164077
+ <rdar://problem/28987810>
+
+ Reviewed by Simon Fraser.
+
+ Adds 2 new unit tests verifying that candidate text insertion can be prevented via beforeinput events, and that
+ beforeinput and input events of type "insertReplacementText" are fired when inserting candidate text on iOS.
+
+ * fast/events/ios/before-input-events-prevent-candidate-insertion-expected.txt: Added.
+ * fast/events/ios/before-input-events-prevent-candidate-insertion.html: Added.
+ * fast/events/ios/input-events-insert-replacement-text-expected.txt: Added.
+ * fast/events/ios/input-events-insert-replacement-text.html: Added.
+
2016-10-28 Alex Christensen <achristen...@webkit.org>
Partially revert 207805 after resolution in URL spec issue 87
Added: trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion-expected.txt (0 => 208090)
--- trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion-expected.txt 2016-10-29 01:06:13 UTC (rev 208090)
@@ -0,0 +1,5 @@
+
+To manually test, type 't' into the contenteditable and try to select a candidate. The replacement text should not be inserted.
+
+PASS: The replacement text was prevented.
+
Added: trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion.html (0 => 208090)
--- trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion.html (rev 0)
+++ trunk/LayoutTests/fast/events/ios/before-input-events-prevent-candidate-insertion.html 2016-10-29 01:06:13 UTC (rev 208090)
@@ -0,0 +1,92 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+
+<head>
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
+ <script id="ui-script" type="text/plain">
+ (function() {
+ uiController.didShowKeyboardCallback = function() {
+ uiController.typeCharacterUsingHardwareKeyboard("t", function() {
+ uiController.selectTextCandidateAtIndex(1, function() {
+ uiController.uiScriptComplete();
+ });
+ });
+ }
+ uiController.singleTapAtPoint($x, $y, function() {});
+ })();
+ </script>
+
+ <script>
+ var progress = 0;
+ var replacementText = "";
+ let write = (message) => output.innerHTML += (message + "<br>");
+ function getUIScript() {
+ let rect = editable.getBoundingClientRect();
+ let script = document.getElementById("ui-script").text;
+ script = script.replace("$x", rect.left + rect.width / 2);
+ return script.replace("$y", rect.top + rect.height / 2);
+ }
+
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ internals.settings.setInputEventsEnabled(true);
+ }
+
+ function incrementProgress()
+ {
+ progress++;
+ if (!window.testRunner || progress !== 2)
+ return;
+
+ setTimeout(function() {
+ if (editable.value.indexOf(replacementText) == -1)
+ write(`PASS: The replacement text was prevented.`);
+ else
+ write(`FAIL: The input value ${editable.value} should not contain replacement text ${replacementText}.`);
+ testRunner.notifyDone();
+ }, 0);
+ }
+
+ function runTest()
+ {
+ editable.addEventListener("beforeinput", preventBeforeInput);
+ if (!window.testRunner || !testRunner.runUIScript)
+ return;
+
+ testRunner.runUIScript(getUIScript(), function(result) {
+ incrementProgress();
+ });
+ }
+
+ function preventBeforeInput(event)
+ {
+ if (event.inputType === "insertReplacementText") {
+ replacementText = event.data;
+ if (!replacementText)
+ write("FAIL: The replacement text input event lacks data.");
+ event.preventDefault();
+ incrementProgress();
+ }
+ }
+
+ </script>
+ <style>
+ #editable {
+ width: 200px;
+ height: 100px;
+ top: 0;
+ left: 0;
+ position: absolute;
+ }
+ </style>
+</head>
+
+<body style="margin: 0;" _onload_=runTest()>
+ <input contenteditable id="editable"></input>
+ <p>To manually test, type 't' into the contenteditable and try to select a candidate. The replacement text should not be inserted.</p>
+ <div id="output"></div>
+</body>
+
+</html>
Added: trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text-expected.txt (0 => 208090)
--- trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text-expected.txt 2016-10-29 01:06:13 UTC (rev 208090)
@@ -0,0 +1,5 @@
+To manually test, type 't' into the contenteditable and try to select a candidate. The output should indicate that the beforeinput and input events for the text replacement were handled, and that the range of the beforeinput event is from 0 to 1.
+
+PASS: Handled text replacement before input event with range: [0, 1].
+PASS: Handled text replacement input event.
+
Added: trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text.html (0 => 208090)
--- trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text.html (rev 0)
+++ trunk/LayoutTests/fast/events/ios/input-events-insert-replacement-text.html 2016-10-29 01:06:13 UTC (rev 208090)
@@ -0,0 +1,90 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+
+<head>
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
+ <script id="ui-script" type="text/plain">
+ (function() {
+ uiController.didShowKeyboardCallback = function() {
+ uiController.typeCharacterUsingHardwareKeyboard("t", function() {
+ uiController.selectTextCandidateAtIndex(1, function() {
+ uiController.uiScriptComplete();
+ });
+ });
+ }
+ uiController.singleTapAtPoint($x, $y, function() {});
+ })();
+ </script>
+
+ <script>
+ var progress = 0;
+ let write = (message) => output.innerHTML += (message + "<br>");
+ function getUIScript() {
+ let rect = editable.getBoundingClientRect();
+ let script = document.getElementById("ui-script").text;
+ script = script.replace("$x", rect.left + rect.width / 2);
+ return script.replace("$y", rect.top + rect.height / 2);
+ }
+
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ internals.settings.setInputEventsEnabled(true);
+ }
+
+ function incrementProgress()
+ {
+ progress++;
+ if (!window.testRunner || progress !== 3)
+ return;
+
+ setTimeout(function() {
+ editable.textContent = "";
+ testRunner.notifyDone();
+ }, 0);
+ }
+
+ function runTest()
+ {
+ editable.addEventListener("input", logInputEvent);
+ editable.addEventListener("beforeinput", logInputEvent);
+ if (!window.testRunner || !testRunner.runUIScript)
+ return;
+
+ testRunner.runUIScript(getUIScript(), function(result) {
+ incrementProgress();
+ });
+ }
+
+ function logInputEvent(event)
+ {
+ if (event.inputType !== "insertReplacementText")
+ return;
+
+ if (event.type === "beforeinput") {
+ let firstRange = event.getTargetRanges()[0];
+ write(`PASS: Handled text replacement before input event with range: [${firstRange.startOffset}, ${firstRange.endOffset}].`);
+ } else
+ write(`PASS: Handled text replacement input event.`);
+ incrementProgress();
+ }
+ </script>
+ <style>
+ #editable {
+ width: 200px;
+ height: 200px;
+ top: 0;
+ left: 0;
+ position: absolute;
+ }
+ </style>
+</head>
+
+<body style="margin: 0;" _onload_=runTest()>
+ <div contenteditable id="editable"></div>
+ <p>To manually test, type 't' into the contenteditable and try to select a candidate. The output should indicate that the beforeinput and input events for the text replacement were handled, and that the range of the beforeinput event is from 0 to 1.</p>
+ <div id="output"></div>
+</body>
+
+</html>
Modified: trunk/Source/WebCore/ChangeLog (208089 => 208090)
--- trunk/Source/WebCore/ChangeLog 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/ChangeLog 2016-10-29 01:06:13 UTC (rev 208090)
@@ -1,3 +1,49 @@
+2016-10-28 Wenson Hsieh <wenson_hs...@apple.com>
+
+ iOS autocorrection does not trigger an input event of inputType "insertReplacementText"
+ https://bugs.webkit.org/show_bug.cgi?id=164077
+ <rdar://problem/28987810>
+
+ Reviewed by Simon Fraser.
+
+ Fixes candidate insertion on iOS, so that it fires input events of type "insertReplacementText" and adds two
+ iOS unit tests covering this change as well as the test infrastructure needed to support these tests. See
+ comments below for more details.
+
+ Tests: fast/events/ios/before-input-events-prevent-candidate-insertion.html
+ fast/events/ios/input-events-insert-replacement-text.html
+
+ * dom/TextEvent.h:
+
+ Adds isAutocompletion() to TextEvent, as well as the TextEventInputAutocompletion text input type. When the
+ Editor handles this TextEvent, it will use this information when creating or modifying the corresponding typing
+ command.
+
+ * dom/TextEventInputType.h:
+ * editing/Editor.cpp:
+ (WebCore::Editor::insertText):
+ (WebCore::Editor::insertTextWithoutSendingTextEvent):
+ * editing/Editor.h:
+ * editing/TypingCommand.cpp:
+ (WebCore::editActionForTypingCommand):
+
+ Now takes whether the command is autocorrection into account. If so, the corresponding edit action should be
+ EditActionInsertReplacement rather than EditActionTypingInsertText.
+
+ (WebCore::TypingCommand::TypingCommand):
+ (WebCore::TypingCommand::deleteSelection):
+ (WebCore::TypingCommand::deleteKeyPressed):
+ (WebCore::TypingCommand::forwardDeleteKeyPressed):
+ (WebCore::TypingCommand::insertText):
+ (WebCore::TypingCommand::insertLineBreak):
+ (WebCore::TypingCommand::insertParagraphSeparatorInQuotedContent):
+ (WebCore::TypingCommand::insertParagraphSeparator):
+ (WebCore::TypingCommand::inputEventData):
+ (WebCore::TypingCommand::willAddTypingToOpenCommand):
+ * editing/TypingCommand.h:
+
+ Adds a new TypingCommand option, IsAutocompletion.
+
2016-10-28 Commit Queue <commit-qu...@webkit.org>
Unreviewed, rolling out r207700.
Modified: trunk/Source/WebCore/dom/TextEvent.h (208089 => 208090)
--- trunk/Source/WebCore/dom/TextEvent.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/dom/TextEvent.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -59,6 +59,7 @@
bool isPaste() const { return m_inputType == TextEventInputPaste; }
bool isDrop() const { return m_inputType == TextEventInputDrop; }
bool isDictation() const { return m_inputType == TextEventInputDictation; }
+ bool isAutocompletion() const { return m_inputType == TextEventInputAutocompletion; }
bool shouldSmartReplace() const { return m_shouldSmartReplace; }
bool shouldMatchStyle() const { return m_shouldMatchStyle; }
Modified: trunk/Source/WebCore/dom/TextEventInputType.h (208089 => 208090)
--- trunk/Source/WebCore/dom/TextEventInputType.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/dom/TextEventInputType.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -30,6 +30,7 @@
enum TextEventInputType {
TextEventInputKeyboard, // any newline characters in the text are line breaks only, not paragraph separators.
+ TextEventInputAutocompletion,
TextEventInputLineBreak, // any tab characters in the text are backtabs.
TextEventInputComposition,
TextEventInputBackTab,
Modified: trunk/Source/WebCore/editing/Editor.cpp (208089 => 208090)
--- trunk/Source/WebCore/editing/Editor.cpp 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/editing/Editor.cpp 2016-10-29 01:06:13 UTC (rev 208090)
@@ -1213,9 +1213,9 @@
m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
}
-bool Editor::insertText(const String& text, Event* triggeringEvent)
+bool Editor::insertText(const String& text, Event* triggeringEvent, TextEventInputType inputType)
{
- return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent);
+ return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent, inputType);
}
bool Editor::insertTextForConfirmedComposition(const String& text)
@@ -1269,6 +1269,8 @@
options |= TypingCommand::SelectInsertedText;
if (autocorrectionWasApplied)
options |= TypingCommand::RetainAutocorrectionIndicator;
+ if (triggeringEvent && triggeringEvent->isAutocompletion())
+ options |= TypingCommand::IsAutocompletion;
TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionFinal : TypingCommand::TextCompositionNone);
}
Modified: trunk/Source/WebCore/editing/Editor.h (208089 => 208090)
--- trunk/Source/WebCore/editing/Editor.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/editing/Editor.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -36,6 +36,7 @@
#include "FindOptions.h"
#include "FrameSelection.h"
#include "TextChecking.h"
+#include "TextEventInputType.h"
#include "TextIteratorBehavior.h"
#include "VisibleSelection.h"
#include "WritingDirection.h"
@@ -239,7 +240,7 @@
Command command(const String& commandName, EditorCommandSource);
WEBCORE_EXPORT static bool commandIsSupportedFromMenuOrKeyBinding(const String& commandName); // Works without a frame.
- WEBCORE_EXPORT bool insertText(const String&, Event* triggeringEvent);
+ WEBCORE_EXPORT bool insertText(const String&, Event* triggeringEvent, TextEventInputType = TextEventInputKeyboard);
bool insertTextForConfirmedComposition(const String& text);
WEBCORE_EXPORT bool insertDictatedText(const String&, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent);
bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, TextEvent* triggeringEvent);
Modified: trunk/Source/WebCore/editing/TypingCommand.cpp (208089 => 208090)
--- trunk/Source/WebCore/editing/TypingCommand.cpp 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/editing/TypingCommand.cpp 2016-10-29 01:06:13 UTC (rev 208090)
@@ -77,7 +77,7 @@
const String& m_text;
};
-static inline EditAction editActionForTypingCommand(TypingCommand::ETypingCommand command, TextGranularity granularity, TypingCommand::TextCompositionType compositionType)
+static inline EditAction editActionForTypingCommand(TypingCommand::ETypingCommand command, TextGranularity granularity, TypingCommand::TextCompositionType compositionType, bool isAutocompletion)
{
if (compositionType == TypingCommand::TextCompositionPending) {
if (command == TypingCommand::InsertText)
@@ -112,7 +112,7 @@
return EditActionTypingDeleteLineForward;
return EditActionTypingDeleteForward;
case TypingCommand::InsertText:
- return EditActionTypingInsertText;
+ return isAutocompletion ? EditActionInsertReplacement : EditActionTypingInsertText;
case TypingCommand::InsertLineBreak:
return EditActionTypingInsertLineBreak;
case TypingCommand::InsertParagraphSeparator:
@@ -140,7 +140,7 @@
}
TypingCommand::TypingCommand(Document& document, ETypingCommand commandType, const String &textToInsert, Options options, TextGranularity granularity, TextCompositionType compositionType)
- : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity, compositionType))
+ : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity, compositionType, options & IsAutocompletion))
, m_commandType(commandType)
, m_textToInsert(textToInsert)
, m_currentTextToInsert(textToInsert)
@@ -150,6 +150,7 @@
, m_granularity(granularity)
, m_compositionType(compositionType)
, m_shouldAddToKillRing(options & AddsToKillRing)
+ , m_isAutocompletion(options & IsAutocompletion)
, m_openedByBackwardDelete(false)
, m_shouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator)
, m_shouldPreventSpellChecking(options & PreventSpellChecking)
@@ -167,6 +168,7 @@
return;
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(compositionType);
lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
lastTypingCommand->deleteSelection(options & SmartDelete);
@@ -181,6 +183,7 @@
if (granularity == CharacterGranularity) {
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document.frame());
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(TextCompositionNone);
lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
lastTypingCommand->deleteKeyPressed(granularity, options & AddsToKillRing);
@@ -198,6 +201,7 @@
if (granularity == CharacterGranularity) {
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*frame)) {
updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame);
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(TextCompositionNone);
lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
lastTypingCommand->forwardDeleteKeyPressed(granularity, options & AddsToKillRing);
@@ -251,6 +255,7 @@
lastTypingCommand->setEndingSelection(selectionForInsertion);
}
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(compositionType);
lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
@@ -265,6 +270,7 @@
void TypingCommand::insertLineBreak(Document& document, Options options)
{
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(TextCompositionNone);
lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
lastTypingCommand->insertLineBreakAndNotifyAccessibility();
@@ -277,6 +283,7 @@
void TypingCommand::insertParagraphSeparatorInQuotedContent(Document& document)
{
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+ lastTypingCommand->setIsAutocompletion(false);
lastTypingCommand->setCompositionType(TextCompositionNone);
lastTypingCommand->insertParagraphSeparatorInQuotedContentAndNotifyAccessibility();
return;
@@ -288,6 +295,7 @@
void TypingCommand::insertParagraphSeparator(Document& document, Options options)
{
if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(*document.frame())) {
+ lastTypingCommand->setIsAutocompletion(options & IsAutocompletion);
lastTypingCommand->setCompositionType(TextCompositionNone);
lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
lastTypingCommand->insertParagraphSeparatorAndNotifyAccessibility();
@@ -398,6 +406,7 @@
{
switch (m_currentTypingEditAction) {
case EditActionTypingInsertText:
+ case EditActionInsertReplacement:
case EditActionTypingInsertPendingComposition:
case EditActionTypingInsertFinalComposition:
return m_currentTextToInsert;
@@ -469,7 +478,7 @@
bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity, const String& text, RefPtr<Range>&& range)
{
m_currentTextToInsert = text;
- m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity, m_compositionType);
+ m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity, m_compositionType, m_isAutocompletion);
if (!shouldDeferWillApplyCommandUntilAddingTypingCommand())
return true;
Modified: trunk/Source/WebCore/editing/TypingCommand.h (208089 => 208090)
--- trunk/Source/WebCore/editing/TypingCommand.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebCore/editing/TypingCommand.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -53,7 +53,8 @@
AddsToKillRing = 1 << 1,
RetainAutocorrectionIndicator = 1 << 2,
PreventSpellChecking = 1 << 3,
- SmartDelete = 1 << 4
+ SmartDelete = 1 << 4,
+ IsAutocompletion = 1 << 5,
};
typedef unsigned Options;
@@ -79,6 +80,7 @@
void forwardDeleteKeyPressed(TextGranularity, bool shouldAddToKillRing);
void deleteSelection(bool smartDelete);
void setCompositionType(TextCompositionType type) { m_compositionType = type; }
+ void setIsAutocompletion(bool isAutocompletion) { m_isAutocompletion = isAutocompletion; }
#if PLATFORM(IOS)
void setEndingSelectionOnLastInsertCommand(const VisibleSelection& selection);
@@ -151,6 +153,7 @@
TextCompositionType m_compositionType;
bool m_shouldAddToKillRing;
bool m_preservesTypingStyle;
+ bool m_isAutocompletion;
// Undoing a series of backward deletes will restore a selection around all of the
// characters that were deleted, but only if the typing command being undone
Modified: trunk/Source/WebKit2/ChangeLog (208089 => 208090)
--- trunk/Source/WebKit2/ChangeLog 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebKit2/ChangeLog 2016-10-29 01:06:13 UTC (rev 208090)
@@ -1,3 +1,16 @@
+2016-10-28 Wenson Hsieh <wenson_hs...@apple.com>
+
+ iOS autocorrection does not trigger an input event of inputType "insertReplacementText"
+ https://bugs.webkit.org/show_bug.cgi?id=164077
+ <rdar://problem/28987810>
+
+ Reviewed by Simon Fraser.
+
+ Small tweak to mark text insertion when autocorrecting as such, as opposed to regular keyboard input.
+
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::syncApplyAutocorrection):
+
2016-10-28 Megan Gardner <megan_gard...@apple.com>
Rename SharedMemoryMac to SharedMemoryCocoa
Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (208089 => 208090)
--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm 2016-10-29 01:06:13 UTC (rev 208090)
@@ -2171,7 +2171,7 @@
frame.selection().setSelectedRange(range.get(), UPSTREAM, true);
if (correction.length())
- frame.editor().insertText(correction, 0);
+ frame.editor().insertText(correction, 0, originalText.isEmpty() ? TextEventInputKeyboard : TextEventInputAutocompletion);
else
frame.editor().deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
correctionApplied = true;
Modified: trunk/Tools/ChangeLog (208089 => 208090)
--- trunk/Tools/ChangeLog 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/ChangeLog 2016-10-29 01:06:13 UTC (rev 208090)
@@ -1,3 +1,30 @@
+2016-10-28 Wenson Hsieh <wenson_hs...@apple.com>
+
+ iOS autocorrection does not trigger an input event of inputType "insertReplacementText"
+ https://bugs.webkit.org/show_bug.cgi?id=164077
+ <rdar://problem/28987810>
+
+ Reviewed by Simon Fraser.
+
+ Adds test support for inserting text candidates on iOS in the form of
+ UIScriptController.selectTextCandidateAtIndex(index, callback), which selects the text candidate at a given
+ index (this needs to be a value between 0-2 on iOS) and fires the callback when done.
+
+ To implement this, we wait for the text prediction view to have predictions (we determine this by polling at a
+ given interval) and then tap the center of the text prediction view at the given index.
+
+ * DumpRenderTree/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptController::selectTextCandidateAtIndex):
+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+ * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+ (WTR::UIScriptController::selectTextCandidateAtIndex):
+ (WTR::UIScriptController::waitForTextPredictionsViewAndSelectCandidateAtIndex):
+ * TestRunnerShared/UIScriptContext/UIScriptController.h:
+ * WebKitTestRunner/ios/UIKitSPI.h:
+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptController::selectTextCandidateAtIndex):
+ (WTR::UIScriptController::waitForTextPredictionsViewAndSelectCandidateAtIndex):
+
2016-10-28 Commit Queue <commit-qu...@webkit.org>
Unreviewed, rolling out r207700.
Modified: trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm (208089 => 208090)
--- trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2016-10-29 01:06:13 UTC (rev 208090)
@@ -116,6 +116,10 @@
{
}
+void UIScriptController::selectTextCandidateAtIndex(long, JSValueRef)
+{
+}
+
void UIScriptController::keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
{
}
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (208089 => 208090)
--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2016-10-29 01:06:13 UTC (rev 208090)
@@ -49,6 +49,8 @@
void keyDownUsingHardwareKeyboard(DOMString character, object callback);
void keyUpUsingHardwareKeyboard(DOMString character, object callback);
+ void selectTextCandidateAtIndex(long index, object callback);
+
// eventsJSON describes a series of user events in JSON form. For the keys, see HIDEventGenerator.mm.
// For example, this JSON describes a touch down followed by a touch up (i.e. a single tap).
// {
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp (208089 => 208090)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2016-10-29 01:06:13 UTC (rev 208090)
@@ -214,6 +214,14 @@
{
}
+void UIScriptController::selectTextCandidateAtIndex(long, JSValueRef)
+{
+}
+
+void UIScriptController::waitForTextPredictionsViewAndSelectCandidateAtIndex(long, unsigned, float)
+{
+}
+
void UIScriptController::keyDownUsingHardwareKeyboard(JSStringRef, JSValueRef)
{
}
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (208089 => 208090)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -70,6 +70,8 @@
void keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
void keyUpUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
+ void selectTextCandidateAtIndex(long index, JSValueRef callback);
+
void keyboardAccessoryBarNext();
void keyboardAccessoryBarPrevious();
@@ -136,6 +138,7 @@
JSClassRef wrapperClass() final;
JSObjectRef objectFromRect(const WebCore::FloatRect&) const;
+ void waitForTextPredictionsViewAndSelectCandidateAtIndex(long index, unsigned callbackID, float interval);
UIScriptContext* m_context;
};
Modified: trunk/Tools/WebKitTestRunner/ios/UIKitSPI.h (208089 => 208090)
--- trunk/Tools/WebKitTestRunner/ios/UIKitSPI.h 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/WebKitTestRunner/ios/UIKitSPI.h 2016-10-29 01:06:13 UTC (rev 208090)
@@ -37,6 +37,11 @@
#import <UIKit/UIApplication_Private.h>
#import <UIKit/UIWindow_Private.h>
+@interface UIKeyboardPredictionView : UIView
++ (UIKeyboardPredictionView *)activeInstance;
+- (BOOL)hasPredictions;
+@end
+
#else
#import "IOKitSPI.h"
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (208089 => 208090)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-10-29 00:31:42 UTC (rev 208089)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-10-29 01:06:13 UTC (rev 208090)
@@ -255,6 +255,46 @@
}];
}
+void UIScriptController::selectTextCandidateAtIndex(long index, JSValueRef callback)
+{
+#if USE(APPLE_INTERNAL_SDK)
+ static const float textPredictionsPollingInterval = 0.1;
+ unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+ waitForTextPredictionsViewAndSelectCandidateAtIndex(index, callbackID, textPredictionsPollingInterval);
+#else
+ // FIXME: This is a no-op on non-internal builds due to UIKeyboardPredictionView being unavailable. Ideally, there should be a better way to
+ // retrieve information and interact with the predictive text view that will be compatible with OpenSource.
+ UNUSED_PARAM(index);
+ UNUSED_PARAM(callback);
+#endif
+}
+
+void UIScriptController::waitForTextPredictionsViewAndSelectCandidateAtIndex(long index, unsigned callbackID, float interval)
+{
+#if USE(APPLE_INTERNAL_SDK)
+ if (![UIKeyboardPredictionView activeInstance].hasPredictions) {
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^() {
+ waitForTextPredictionsViewAndSelectCandidateAtIndex(index, callbackID, interval);
+ });
+ return;
+ }
+
+ PlatformWKView webView = TestController::singleton().mainWebView()->platformView();
+ CGRect predictionViewFrame = [UIKeyboardPredictionView activeInstance].frame;
+ // This assumes there are 3 predicted text cells of equal width, which is the case on iOS.
+ float offsetX = (index * 2 + 1) * CGRectGetWidth(predictionViewFrame) / 6;
+ float offsetY = CGRectGetHeight(webView.window.frame) - CGRectGetHeight([UIKeyboardPredictionView activeInstance].superview.frame) + CGRectGetHeight(predictionViewFrame) / 2;
+ [[HIDEventGenerator sharedHIDEventGenerator] tap:CGPointMake(offsetX, offsetY) completionBlock:^{
+ if (m_context)
+ m_context->asyncTaskComplete(callbackID);
+ }];
+#else
+ UNUSED_PARAM(index);
+ UNUSED_PARAM(callbackID);
+ UNUSED_PARAM(interval);
+#endif
+}
+
void UIScriptController::dismissFormAccessoryView()
{
TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();