<!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>[245062] 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/245062">245062</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2019-05-08 12:36:33 -0700 (Wed, 08 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Add a quirk to synthesize mouse events when modifying the selection
https://bugs.webkit.org/show_bug.cgi?id=197683
<rdar://problem/48003980>

Reviewed by Tim Horton.

Source/WebCore:

See WebKit ChangeLog for more details.

Test: editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html

* page/EventHandler.cpp:
(WebCore::EventHandler::handleMousePressEvent):
(WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):

Add some platform hooks to prevent mousemove events from updating the selection on iOS.

(WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):

Add some platform hooks to prevent drag and drop from kicking in when sending synthetic mousemove events to the
page on iOS (drag and drop is instead triggered by EventHandler::tryToBeginDragAtPoint).

(WebCore::EventHandler::updateSelectionForMouseDrag):
* page/EventHandler.h:
* page/Quirks.cpp:
(WebCore::Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):
* page/Quirks.h:

Add the new site-specific quirk.

* page/Settings.yaml:
* page/ios/EventHandlerIOS.mm:
(WebCore::EventHandler::tryToBeginDragAtPoint):
(WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):
(WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):
* testing/InternalSettings.cpp:
(WebCore::InternalSettings::Backup::Backup):
(WebCore::InternalSettings::Backup::restoreTo):
(WebCore::InternalSettings::setShouldDispatchSyntheticMouseEventsWhenModifyingSelection):
* testing/InternalSettings.h:
* testing/InternalSettings.idl:

Add an internal settings hook to opt into this quirk, for use in layout tests.

Source/WebKit:

Introduces support for dispatching synthetic mouse events when modifying the selection on some websites. See
below for more details.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::selectAll):
* UIProcess/WebPageProxy.h:

Instead of executing a "SelectAll" editing command using the generic WebPage::executeEditCommand method,
introduce a separate method for selectAll that executes the "SelectAll" edit command and then does some
platform-specific work. See platformDidSelectAll.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView selectAllForWebView:]):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::selectAll):
(WebKit::WebPage::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):

Add a helper method to determine whether the quirk should be enabled.

(WebKit::WebPage::platformDidSelectAll):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::elementRectInRootViewCoordinates):

Move this function closer to the top of the file so that it can be used in
dispatchSyntheticMouseEventsForSelectionGesture.

(WebKit::WebPage::clearSelection):
(WebKit::WebPage::dispatchSyntheticMouseEventsForSelectionGesture):

Add a helper method to dispatch a synthetic mouse event for a given selection gesture type. Used in several
places in WebPageIOS to synthesize and dispatch mouse events during selection.

(WebKit::WebPage::updateSelectionWithTouches):

When changing the selection with selection handles, fake mousedown when the user first touches down on the
selection handle; mousemove as the user is moving the handle around; and finally, mouseup when the user lets go.

(WebKit::WebPage::extendSelection):
(WebKit::WebPage::platformDidSelectAll):

When tapping "Select All" and/or "Select" in the callout menu, fake a mousedown at the selection start, then a
mousemove at selection end, and finally, a mouseup at selection end.

(WebKit::WebPage::getFocusedElementInformation):

LayoutTests:

Adds a new layout test to enable the site-specific quirk and verify that mouse events are dispatched when
changing selection, both via the callout menu and by moving the selection grabber using gestures.

* editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt: Added.
* editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForMenuToHide.return.new.Promise):
(window.UIHelper.waitForMenuToHide):

Introduce a new helper method to wait for the menu to hide (on iOS, this refers to the callout menu).</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsresourcesuihelperjs">trunk/LayoutTests/resources/ui-helper.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlercpp">trunk/Source/WebCore/page/EventHandler.cpp</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlerh">trunk/Source/WebCore/page/EventHandler.h</a></li>
<li><a href="#trunkSourceWebCorepageQuirkscpp">trunk/Source/WebCore/page/Quirks.cpp</a></li>
<li><a href="#trunkSourceWebCorepageQuirksh">trunk/Source/WebCore/page/Quirks.h</a></li>
<li><a href="#trunkSourceWebCorepageSettingsyaml">trunk/Source/WebCore/page/Settings.yaml</a></li>
<li><a href="#trunkSourceWebCorepageiosEventHandlerIOSmm">trunk/Source/WebCore/page/ios/EventHandlerIOS.mm</a></li>
<li><a href="#trunkSourceWebCoretestingInternalSettingscpp">trunk/Source/WebCore/testing/InternalSettings.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalSettingsh">trunk/Source/WebCore/testing/InternalSettings.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalSettingsidl">trunk/Source/WebCore/testing/InternalSettings.idl</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestseditingselectioniosdispatchmouseeventswhenmodifyingselectionquirkexpectedtxt">trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt</a></li>
<li><a href="#trunkLayoutTestseditingselectioniosdispatchmouseeventswhenmodifyingselectionquirkhtml">trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/LayoutTests/ChangeLog 2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2019-05-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Add a quirk to synthesize mouse events when modifying the selection
+        https://bugs.webkit.org/show_bug.cgi?id=197683
+        <rdar://problem/48003980>
+
+        Reviewed by Tim Horton.
+
+        Adds a new layout test to enable the site-specific quirk and verify that mouse events are dispatched when
+        changing selection, both via the callout menu and by moving the selection grabber using gestures.
+
+        * editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt: Added.
+        * editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForMenuToHide.return.new.Promise):
+        (window.UIHelper.waitForMenuToHide):
+
+        Introduce a new helper method to wait for the menu to hide (on iOS, this refers to the callout menu).
+
</ins><span class="cx"> 2019-05-07  Ryan Haddad  <ryanhaddad@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed test gardening for Mojave.
</span></span></pre></div>
<a id="trunkLayoutTestseditingselectioniosdispatchmouseeventswhenmodifyingselectionquirkexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt (0 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt                                (rev 0)
+++ trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt   2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+This test verifies that when the 'mouse event synthesis on selection' quirk is enabled, text selection dispatches mouse events that mimic the user selecting text. To run the test manually, use the callout menu to select text or selection handles, and verify that mousedown, mousemove and mouseup are dispatched and logged in the output area below.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Attempting to show the callout bar.
+Observed event type: mousedown
+Observed event type: mouseup
+Observed event type: mousedown
+Observed event type: mouseup
+PASS Displayed the callout bar.
+
+Attempting to select the last word.
+Observed event type: mousedown
+Observed event type: mousemove
+Observed event type: mouseup
+PASS Selected the last word.
+
+Attempting to dismiss the callout bar by executing 'SelectAll'.
+PASS Dismissed the callout bar.
+
+Attempting to move the selection grabber.
+Observed event type: mousedown
+Observed event type: mousemove
+Observed event type: mouseup
+PASS Moved the selection grabber.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestseditingselectioniosdispatchmouseeventswhenmodifyingselectionquirkhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html (0 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html                                (rev 0)
+++ trunk/LayoutTests/editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html   2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+<!DOCTYPE html><!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<script src="../../../resources/ui-helper.js"></script>
+<script src="../../../resources/basic-gestures.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<style>
+body, html {
+    margin: 0;
+}
+.editor {
+    border: 2px solid tomato;
+    width: 300px;
+    height: 300px;
+    box-sizing: border-box;
+    font-size: 32px;
+    padding: 10px;
+}
+
+#console, #description {
+    width: 300px;
+    height: 100px;
+    overflow: scroll;
+}
+</style>
+<script>
+if (window.internals)
+    internals.settings.setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(true);
+
+lastEvent = null;
+jsTestIsAsync = true;
+
+function recordEvent() {
+    if (!lastEvent || event.type !== lastEvent.type)
+        debug(`Observed event type: ${event.type}`);
+    lastEvent = event;
+}
+
+addEventListener("mousedown", recordEvent);
+addEventListener("mousemove", recordEvent);
+addEventListener("mouseup", recordEvent);
+
+async function waitForSelectionToAppear()
+{
+    while (true) {
+        const rects = await UIHelper.getUISelectionViewRects();
+        if (rects.length)
+            return rects;
+    }
+}
+
+function midPointOfRect(rect) {
+    return [rect.left + (rect.width / 2), rect.top + (rect.height / 2)];
+}
+
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    description("This test verifies that when the 'mouse event synthesis on selection' quirk is enabled, text selection dispatches mouse events that mimic the user selecting text. To run the test manually, use the callout menu to select text or selection handles, and verify that mousedown, mousemove and mouseup are dispatched and logged in the output area below.");
+
+    debug("\nAttempting to show the callout bar.");
+    const editor = document.querySelector(".editor");
+    await UIHelper.activateElementAndWaitForInputSession(editor);
+    await UIHelper.activateElement(editor);
+    await UIHelper.waitForMenuToShow();
+    testPassed("Displayed the callout bar.");
+
+    debug("\nAttempting to select the last word.");
+    await UIHelper.chooseMenuAction("Select");
+    const rects = await waitForSelectionToAppear();
+    testPassed("Selected the last word.");
+
+    debug("\nAttempting to dismiss the callout bar by executing 'SelectAll'.");
+    document.execCommand("SelectAll");
+    await UIHelper.waitForMenuToHide();
+    testPassed("Dismissed the callout bar.");
+
+    debug("\nAttempting to move the selection grabber.");
+    const [grabberX, grabberY] = midPointOfRect(await UIHelper.getSelectionEndGrabberViewRect());
+    const touchDestinationX = grabberX - rects[0].width;
+
+    await touchAndDragFromPointToPoint(grabberX, grabberY, touchDestinationX, grabberY);
+    await liftUpAtPoint(touchDestinationX, grabberY);
+    testPassed("Moved the selection grabber.");
+
+    document.querySelector(".editor").remove();
+    finishJSTest();
+});
+</script>
+</head>
+<body>
+<div class="editor" contenteditable>The quick brown fox jumped over the lazy dog.</div>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsresourcesuihelperjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/resources/ui-helper.js (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/resources/ui-helper.js 2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/LayoutTests/resources/ui-helper.js    2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -827,6 +827,19 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static waitForMenuToHide()
+    {
+        return new Promise(resolve => {
+            testRunner.runUIScript(`
+                (function() {
+                    if (uiController.isShowingMenu)
+                        uiController.didHideMenuCallback = () => uiController.uiScriptComplete();
+                    else
+                        uiController.uiScriptComplete();
+                })()`, resolve);
+        });
+    }
+
</ins><span class="cx">     static isShowingMenu()
</span><span class="cx">     {
</span><span class="cx">         return new Promise(resolve => {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/ChangeLog      2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2019-05-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Add a quirk to synthesize mouse events when modifying the selection
+        https://bugs.webkit.org/show_bug.cgi?id=197683
+        <rdar://problem/48003980>
+
+        Reviewed by Tim Horton.
+
+        See WebKit ChangeLog for more details.
+
+        Test: editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMousePressEvent):
+        (WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):
+
+        Add some platform hooks to prevent mousemove events from updating the selection on iOS.
+
+        (WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):
+
+        Add some platform hooks to prevent drag and drop from kicking in when sending synthetic mousemove events to the
+        page on iOS (drag and drop is instead triggered by EventHandler::tryToBeginDragAtPoint).
+
+        (WebCore::EventHandler::updateSelectionForMouseDrag):
+        * page/EventHandler.h:
+        * page/Quirks.cpp:
+        (WebCore::Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):
+        * page/Quirks.h:
+
+        Add the new site-specific quirk.
+
+        * page/Settings.yaml:
+        * page/ios/EventHandlerIOS.mm:
+        (WebCore::EventHandler::tryToBeginDragAtPoint):
+        (WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):
+        (WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):
+        * testing/InternalSettings.cpp:
+        (WebCore::InternalSettings::Backup::Backup):
+        (WebCore::InternalSettings::Backup::restoreTo):
+        (WebCore::InternalSettings::setShouldDispatchSyntheticMouseEventsWhenModifyingSelection):
+        * testing/InternalSettings.h:
+        * testing/InternalSettings.idl:
+
+        Add an internal settings hook to opt into this quirk, for use in layout tests.
+
</ins><span class="cx"> 2019-05-08  Simon Fraser  <simon.fraser@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Implement backing-sharing in compositing layers, allowing overlap layers to paint into the backing store of another layer
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.cpp (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.cpp       2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/EventHandler.cpp  2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -776,7 +776,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Single mouse down on links or images can always trigger drag-n-drop.
</span><span class="cx">     bool isMouseDownOnLinkOrImage = event.isOverLink() || event.hitTestResult().image();
</span><del>-    m_mouseDownMayStartDrag = singleClick && (!event.event().shiftKey() || isMouseDownOnLinkOrImage);
</del><ins>+    m_mouseDownMayStartDrag = singleClick && (!event.event().shiftKey() || isMouseDownOnLinkOrImage) && shouldAllowMouseDownToStartDrag();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     m_mouseDownWasSingleClickInSelection = false;
</span><span class="lines">@@ -847,6 +847,21 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DRAG_SUPPORT)
</span><ins>+
+#if !PLATFORM(IOS_FAMILY)
+
+bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const
+{
+    return true;
+}
+
+bool EventHandler::shouldAllowMouseDownToStartDrag() const
+{
+    return true;
+}
+
+#endif
+
</ins><span class="cx"> bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis)
</span><span class="cx"> {
</span><span class="cx">     if (!m_mousePressed)
</span><span class="lines">@@ -926,6 +941,9 @@
</span><span class="cx"> 
</span><span class="cx"> void EventHandler::updateSelectionForMouseDrag()
</span><span class="cx"> {
</span><ins>+    if (!supportsSelectionUpdatesOnMouseDrag())
+        return;
+
</ins><span class="cx">     FrameView* view = m_frame.view();
</span><span class="cx">     if (!view)
</span><span class="cx">         return;
</span><span class="lines">@@ -941,6 +959,9 @@
</span><span class="cx"> 
</span><span class="cx"> void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult)
</span><span class="cx"> {
</span><ins>+    if (!supportsSelectionUpdatesOnMouseDrag())
+        return;
+
</ins><span class="cx">     if (!m_mouseDownMayStartSelect)
</span><span class="cx">         return;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.h (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.h 2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/EventHandler.h    2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -365,6 +365,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DRAG_SUPPORT)
</span><span class="cx">     bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&, CheckDragHysteresis = ShouldCheckDragHysteresis);
</span><ins>+    bool shouldAllowMouseDownToStartDrag() const;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
</span><span class="lines">@@ -457,6 +458,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DRAG_SUPPORT)
</span><span class="cx">     DragSourceAction updateDragSourceActionsAllowed() const;
</span><ins>+    bool supportsSelectionUpdatesOnMouseDrag() const;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     // The following are called at the beginning of handleMouseUp and handleDrag.  
</span><span class="lines">@@ -616,6 +618,10 @@
</span><span class="cx">     bool m_didStartDrag { false };
</span><span class="cx">     bool m_isHandlingWheelEvent { false };
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS_FAMILY)
+    bool m_shouldAllowMouseDownToStartDrag { false };
+#endif
+
</ins><span class="cx"> #if ENABLE(CURSOR_VISIBILITY)
</span><span class="cx">     Timer m_autoHideCursorTimer;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorepageQuirkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Quirks.cpp (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Quirks.cpp     2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/Quirks.cpp        2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -237,6 +237,24 @@
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+bool Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
+{
+    if (m_document->settings().shouldDispatchSyntheticMouseEventsWhenModifyingSelection())
+        return true;
+
+    if (!needsQuirks())
+        return false;
+
+    auto host = m_document->topDocument().url().host();
+    if (equalLettersIgnoringASCIICase(host, "medium.com") || host.endsWithIgnoringASCIICase(".medium.com"))
+        return true;
+
+    if (equalLettersIgnoringASCIICase(host, "weebly.com") || host.endsWithIgnoringASCIICase(".weebly.com"))
+        return true;
+
+    return false;
+}
+
</ins><span class="cx"> bool Quirks::shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const
</span><span class="cx"> {
</span><span class="cx">     if (!needsQuirks())
</span></span></pre></div>
<a id="trunkSourceWebCorepageQuirksh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Quirks.h (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Quirks.h       2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/Quirks.h  2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">     bool shouldDisablePointerEventsQuirk() const;
</span><span class="cx">     bool needsInputModeNoneImplicitly(const HTMLElement&) const;
</span><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT bool shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const;
</ins><span class="cx">     WEBCORE_EXPORT bool shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const;
</span><span class="cx">     WEBCORE_EXPORT bool isTouchBarUpdateSupressedForHiddenContentEditable() const;
</span><span class="cx">     WEBCORE_EXPORT bool isNeverRichlyEditableForTouchBar() const;
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingsyaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.yaml (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.yaml  2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/Settings.yaml     2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -834,6 +834,9 @@
</span><span class="cx"> shouldDecidePolicyBeforeLoadingQuickLookPreview:
</span><span class="cx">   initial: false
</span><span class="cx"> 
</span><ins>+shouldDispatchSyntheticMouseEventsWhenModifyingSelection:
+  initial: false
+
</ins><span class="cx"> # Deprecated
</span><span class="cx"> 
</span><span class="cx"> iceCandidateFilteringEnabled:
</span></span></pre></div>
<a id="trunkSourceWebCorepageiosEventHandlerIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/ios/EventHandlerIOS.mm (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/ios/EventHandlerIOS.mm 2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/page/ios/EventHandlerIOS.mm    2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -671,6 +671,8 @@
</span><span class="cx">     if (!document)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    SetForScope<bool> shouldAllowMouseDownToStartDrag { m_shouldAllowMouseDownToStartDrag, true };
+
</ins><span class="cx">     document->updateLayoutIgnorePendingStylesheets();
</span><span class="cx"> 
</span><span class="cx">     FloatPoint adjustedClientPositionAsFloatPoint(clientPosition);
</span><span class="lines">@@ -699,8 +701,18 @@
</span><span class="cx">     return handledDrag;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const
+{
+    return false;
+}
</ins><span class="cx"> 
</span><ins>+bool EventHandler::shouldAllowMouseDownToStartDrag() const
+{
+    return m_shouldAllowMouseDownToStartDrag;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#endif // ENABLE(DRAG_SUPPORT)
+
+}
+
</ins><span class="cx"> #endif // PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalSettingscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/InternalSettings.cpp (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/InternalSettings.cpp        2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/testing/InternalSettings.cpp   2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -100,6 +100,7 @@
</span><span class="cx">     , m_deferredCSSParserEnabled(settings.deferredCSSParserEnabled())
</span><span class="cx">     , m_inputEventsEnabled(settings.inputEventsEnabled())
</span><span class="cx">     , m_incompleteImageBorderEnabled(settings.incompleteImageBorderEnabled())
</span><ins>+    , m_shouldDispatchSyntheticMouseEventsWhenModifyingSelection(settings.shouldDispatchSyntheticMouseEventsWhenModifyingSelection())
</ins><span class="cx">     , m_shouldDeactivateAudioSession(PlatformMediaSessionManager::shouldDeactivateAudioSession())
</span><span class="cx">     , m_userInterfaceDirectionPolicy(settings.userInterfaceDirectionPolicy())
</span><span class="cx">     , m_systemLayoutDirection(settings.systemLayoutDirection())
</span><span class="lines">@@ -207,6 +208,7 @@
</span><span class="cx">     FontCache::singleton().setShouldMockBoldSystemFontForAccessibility(m_shouldMockBoldSystemFontForAccessibility);
</span><span class="cx">     settings.setFrameFlattening(m_frameFlattening);
</span><span class="cx">     settings.setIncompleteImageBorderEnabled(m_incompleteImageBorderEnabled);
</span><ins>+    settings.setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(m_shouldDispatchSyntheticMouseEventsWhenModifyingSelection);
</ins><span class="cx">     PlatformMediaSessionManager::setShouldDeactivateAudioSession(m_shouldDeactivateAudioSession);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INDEXED_DATABASE_IN_WORKERS)
</span><span class="lines">@@ -926,6 +928,14 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ExceptionOr<void> InternalSettings::setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(bool shouldDispatch)
+{
+    if (!m_page)
+        return Exception { InvalidAccessError };
+    settings().setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(shouldDispatch);
+    return { };
+}
+
</ins><span class="cx"> static InternalSettings::ForcedAccessibilityValue settingsToInternalSettingsValue(Settings::ForcedAccessibilityValue value)
</span><span class="cx"> {
</span><span class="cx">     switch (value) {
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalSettingsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/InternalSettings.h (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/InternalSettings.h  2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/testing/InternalSettings.h     2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx">     ExceptionOr<void> setShouldManageAudioSessionCategory(bool);
</span><span class="cx">     ExceptionOr<void> setCustomPasteboardDataEnabled(bool);
</span><span class="cx">     ExceptionOr<void> setIncompleteImageBorderEnabled(bool);
</span><ins>+    ExceptionOr<void> setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(bool);
</ins><span class="cx"> 
</span><span class="cx">     using FrameFlatteningValue = FrameFlattening;
</span><span class="cx">     ExceptionOr<void> setFrameFlattening(FrameFlatteningValue);
</span><span class="lines">@@ -198,6 +199,7 @@
</span><span class="cx">         bool m_deferredCSSParserEnabled;
</span><span class="cx">         bool m_inputEventsEnabled;
</span><span class="cx">         bool m_incompleteImageBorderEnabled;
</span><ins>+        bool m_shouldDispatchSyntheticMouseEventsWhenModifyingSelection;
</ins><span class="cx">         bool m_shouldDeactivateAudioSession;
</span><span class="cx">         UserInterfaceDirectionPolicy m_userInterfaceDirectionPolicy;
</span><span class="cx">         TextDirection m_systemLayoutDirection;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalSettingsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/InternalSettings.idl (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/InternalSettings.idl        2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebCore/testing/InternalSettings.idl   2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -88,6 +88,7 @@
</span><span class="cx">     [MayThrowException] void setInlineMediaPlaybackRequiresPlaysInlineAttribute(boolean requires);
</span><span class="cx">     [MayThrowException] void setFrameFlattening(FrameFlatteningValue frameFlattening);
</span><span class="cx">     [MayThrowException] void setIncompleteImageBorderEnabled(boolean enabled);
</span><ins>+    [MayThrowException] void setShouldDispatchSyntheticMouseEventsWhenModifyingSelection(boolean shouldDispatch);
</ins><span class="cx"> 
</span><span class="cx">     // RuntimeEnabledFeatures.
</span><span class="cx">     void setIndexedDBWorkersEnabled(boolean enabled);
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/ChangeLog       2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2019-05-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Add a quirk to synthesize mouse events when modifying the selection
+        https://bugs.webkit.org/show_bug.cgi?id=197683
+        <rdar://problem/48003980>
+
+        Reviewed by Tim Horton.
+
+        Introduces support for dispatching synthetic mouse events when modifying the selection on some websites. See
+        below for more details.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::selectAll):
+        * UIProcess/WebPageProxy.h:
+
+        Instead of executing a "SelectAll" editing command using the generic WebPage::executeEditCommand method,
+        introduce a separate method for selectAll that executes the "SelectAll" edit command and then does some
+        platform-specific work. See platformDidSelectAll.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView selectAllForWebView:]):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::selectAll):
+        (WebKit::WebPage::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):
+
+        Add a helper method to determine whether the quirk should be enabled.
+
+        (WebKit::WebPage::platformDidSelectAll):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::elementRectInRootViewCoordinates):
+
+        Move this function closer to the top of the file so that it can be used in
+        dispatchSyntheticMouseEventsForSelectionGesture.
+
+        (WebKit::WebPage::clearSelection):
+        (WebKit::WebPage::dispatchSyntheticMouseEventsForSelectionGesture):
+
+        Add a helper method to dispatch a synthetic mouse event for a given selection gesture type. Used in several
+        places in WebPageIOS to synthesize and dispatch mouse events during selection.
+
+        (WebKit::WebPage::updateSelectionWithTouches):
+
+        When changing the selection with selection handles, fake mousedown when the user first touches down on the
+        selection handle; mousemove as the user is moving the handle around; and finally, mouseup when the user lets go.
+
+        (WebKit::WebPage::extendSelection):
+        (WebKit::WebPage::platformDidSelectAll):
+
+        When tapping "Select All" and/or "Select" in the callout menu, fake a mousedown at the selection start, then a
+        mousemove at selection end, and finally, a mouseup at selection end.
+
+        (WebKit::WebPage::getFocusedElementInformation):
+
</ins><span class="cx"> 2019-05-08  Alexander Mikhaylenko  <exalm7659@gmail.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK] Pinch Zooming has no maximum
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -2014,6 +2014,14 @@
</span><span class="cx">     m_process->send(Messages::WebPage::ScheduleFullEditorStateUpdate(), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::selectAll()
+{
+    if (!hasRunningProcess())
+        return;
+
+    m_process->send(Messages::WebPage::SelectAll(), m_pageID);
+}
+
</ins><span class="cx"> void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
</span><span class="cx"> {
</span><span class="cx">     if (!hasRunningProcess()) {
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -595,6 +595,7 @@
</span><span class="cx"> 
</span><span class="cx">     void addMIMETypeWithCustomContentProvider(const String& mimeType);
</span><span class="cx"> 
</span><ins>+    void selectAll();
</ins><span class="cx">     void executeEditCommand(const String& commandName, const String& argument = String());
</span><span class="cx">     void validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&&);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm    2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm       2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -3079,7 +3079,7 @@
</span><span class="cx"> - (void)selectAllForWebView:(id)sender
</span><span class="cx"> {
</span><span class="cx">     [_textSelectionAssistant selectAll:sender];
</span><del>-    _page->executeEditCommand("selectAll"_s);
</del><ins>+    _page->selectAll();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)toggleBoldfaceForWebView:(id)sender
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp       2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp  2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -1101,6 +1101,26 @@
</span><span class="cx">     send(Messages::WebPageProxy::VoidCallback(callbackID));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::selectAll()
+{
+    executeEditingCommand("SelectAll"_s, { });
+    platformDidSelectAll();
+}
+
+bool WebPage::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
+{
+    auto* document = m_page->mainFrame().document();
+    return document && document->quirks().shouldDispatchSyntheticMouseEventsWhenModifyingSelection();
+}
+
+#if !PLATFORM(IOS_FAMILY)
+
+void WebPage::platformDidSelectAll()
+{
+}
+
+#endif // !PLATFORM(IOS_FAMILY)
+
</ins><span class="cx"> void WebPage::updateEditorStateAfterLayoutIfEditabilityChanged()
</span><span class="cx"> {
</span><span class="cx">     // FIXME: We should update EditorStateIsContentEditable to track whether the state is richly
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -599,6 +599,7 @@
</span><span class="cx">     void disabledAdaptationsDidChange(const OptionSet<WebCore::DisabledAdaptations>&);
</span><span class="cx">     void viewportPropertiesDidChange(const WebCore::ViewportArguments&);
</span><span class="cx">     void executeEditCommandWithCallback(const String&, const String& argument, CallbackID);
</span><ins>+    void selectAll();
</ins><span class="cx"> 
</span><span class="cx">     void textInputContextsInRect(WebCore::FloatRect, CompletionHandler<void(const Vector<WebKit::TextInputContext>&)>&&);
</span><span class="cx">     void focusTextInputContext(const TextInputContext&, CompletionHandler<void(bool)>&&);
</span><span class="lines">@@ -1228,6 +1229,7 @@
</span><span class="cx">     void resetTextAutosizing();
</span><span class="cx">     WebCore::VisiblePosition visiblePositionInFocusedNodeForPoint(const WebCore::Frame&, const WebCore::IntPoint&, bool isInteractingWithFocusedElement);
</span><span class="cx">     RefPtr<WebCore::Range> rangeForGranularityAtPoint(WebCore::Frame&, const WebCore::IntPoint&, uint32_t granularity, bool isInteractingWithFocusedElement);
</span><ins>+    void dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch, const WebCore::IntPoint&);
</ins><span class="cx"> 
</span><span class="cx">     void sendPositionInformation(InteractionInformationAtPosition&&);
</span><span class="cx">     InteractionInformationAtPosition positionInformation(const InteractionInformationRequest&);
</span><span class="lines">@@ -1466,6 +1468,9 @@
</span><span class="cx">     void capitalizeWord();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    bool shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const;
+    void platformDidSelectAll();
+
</ins><span class="cx"> #if ENABLE(CONTEXT_MENUS)
</span><span class="cx">     void didSelectItemFromActiveContextMenu(const WebContextMenuItemData&);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -202,6 +202,7 @@
</span><span class="cx">     RunJavaScriptInFrame(uint64_t frameID, String script, bool forceUserGesture, WebKit::CallbackID callbackID)
</span><span class="cx">     ForceRepaint(WebKit::CallbackID callbackID)
</span><span class="cx"> 
</span><ins>+    SelectAll()
</ins><span class="cx">     ScheduleFullEditorStateUpdate()
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (245061 => 245062)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-05-08 18:18:42 UTC (rev 245061)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm    2019-05-08 19:36:33 UTC (rev 245062)
</span><span class="lines">@@ -1479,12 +1479,61 @@
</span><span class="cx">     return (base < extent) ? Range::create(*frame->document(), base, extent) : Range::create(*frame->document(), extent, base);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPage::clearSelection(){
</del><ins>+static IntRect elementRectInRootViewCoordinates(const Element& element)
+{
+    auto* frame = element.document().frame();
+    if (!frame)
+        return { };
+
+    auto* view = frame->view();
+    if (!view)
+        return { };
+
+    auto* renderer = element.renderer();
+    if (!renderer)
+        return { };
+
+    return view->contentsToRootView(renderer->absoluteBoundingBoxRect());
+}
+
+void WebPage::clearSelection()
+{
</ins><span class="cx">     m_startingGestureRange = nullptr;
</span><span class="cx">     m_currentBlockSelection = nullptr;
</span><span class="cx">     m_page->focusController().focusedOrMainFrame().selection().clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch touch, const IntPoint& point)
+{
+    auto frame = makeRef(m_page->focusController().focusedOrMainFrame());
+    if (!frame->selection().selection().isContentEditable())
+        return;
+
+    IntRect focusedElementRect;
+    if (m_focusedElement)
+        focusedElementRect = elementRectInRootViewCoordinates(*m_focusedElement);
+
+    if (focusedElementRect.isEmpty())
+        return;
+
+    auto adjustedPoint = point.constrainedBetween(focusedElementRect.minXMinYCorner(), focusedElementRect.maxXMaxYCorner());
+    auto& eventHandler = m_page->mainFrame().eventHandler();
+    switch (touch) {
+    case SelectionTouch::Started:
+        eventHandler.handleMousePressEvent({ adjustedPoint, adjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, NoTap });
+        break;
+    case SelectionTouch::Moved:
+        eventHandler.dispatchSyntheticMouseMove({ adjustedPoint, adjustedPoint, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, NoTap });
+        break;
+    case SelectionTouch::Ended:
+    case SelectionTouch::EndedMovingForward:
+    case SelectionTouch::EndedMovingBackward:
+    case SelectionTouch::EndedNotMoving:
+        eventHandler.handleMouseReleaseEvent({ adjustedPoint, adjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, NoTap });
+        break;
+    }
+}
+
</ins><span class="cx"> void WebPage::updateSelectionWithTouches(const IntPoint& point, uint32_t touches, bool baseIsStart, CallbackID callbackID)
</span><span class="cx"> {
</span><span class="cx">     Frame& frame = m_page->focusController().focusedOrMainFrame();
</span><span class="lines">@@ -1499,7 +1548,11 @@
</span><span class="cx">     VisiblePosition result;
</span><span class="cx">     SelectionFlags flags = None;
</span><span class="cx"> 
</span><del>-    switch (static_cast<SelectionTouch>(touches)) {
</del><ins>+    auto selectionTouch = static_cast<SelectionTouch>(touches);
+    if (shouldDispatchSyntheticMouseEventsWhenModifyingSelection())
+        dispatchSyntheticMouseEventsForSelectionGesture(selectionTouch, point);
+
+    switch (selectionTouch) {
</ins><span class="cx">     case SelectionTouch::Started:
</span><span class="cx">     case SelectionTouch::EndedNotMoving:
</span><span class="cx">         break;
</span><span class="lines">@@ -1557,9 +1610,38 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     VisiblePosition position = frame.selection().selection().start();
</span><del>-    frame.selection().setSelectedRange(wordRangeFromPosition(position).get(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
</del><ins>+    auto wordRange = wordRangeFromPosition(position);
+    if (!wordRange)
+        return;
+
+    IntPoint endLocationForSyntheticMouseEvents;
+    bool shouldDispatchMouseEvents = shouldDispatchSyntheticMouseEventsWhenModifyingSelection();
+    if (shouldDispatchMouseEvents) {
+        auto startLocationForSyntheticMouseEvents = frame.view()->contentsToRootView(VisiblePosition(wordRange->startPosition()).absoluteCaretBounds()).center();
+        endLocationForSyntheticMouseEvents = frame.view()->contentsToRootView(VisiblePosition(wordRange->endPosition()).absoluteCaretBounds()).center();
+        dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Started, startLocationForSyntheticMouseEvents);
+        dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Moved, endLocationForSyntheticMouseEvents);
+    }
+
+    frame.selection().setSelectedRange(wordRange.get(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
+
+    if (shouldDispatchMouseEvents)
+        dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Ended, endLocationForSyntheticMouseEvents);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::platformDidSelectAll()
+{
+    if (!shouldDispatchSyntheticMouseEventsWhenModifyingSelection())
+        return;
+
+    auto frame = makeRef(m_page->focusController().focusedOrMainFrame());
+    auto startCaretRect = frame->view()->contentsToRootView(VisiblePosition(frame->selection().selection().start()).absoluteCaretBounds());
+    auto endCaretRect = frame->view()->contentsToRootView(VisiblePosition(frame->selection().selection().end()).absoluteCaretBounds());
+    dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Started, startCaretRect.center());
+    dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Moved, endCaretRect.center());
+    dispatchSyntheticMouseEventsForSelectionGesture(SelectionTouch::Ended, endCaretRect.center());
+}
+
</ins><span class="cx"> void WebPage::selectWordBackward()
</span><span class="cx"> {
</span><span class="cx">     Frame& frame = m_page->focusController().focusedOrMainFrame();
</span><span class="lines">@@ -2584,19 +2666,6 @@
</span><span class="cx">     send(Messages::WebPageProxy::VoidCallback(callbackID));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static IntRect elementRectInRootViewCoordinates(const Node& node, const Frame& frame)
-{
-    auto* view = frame.view();
-    if (!view)
-        return { };
-
-    auto* renderer = node.renderer();
-    if (!renderer)
-        return { };
-
-    return view->contentsToRootView(renderer->absoluteBoundingBoxRect());
-}
-
</del><span class="cx"> void WebPage::getFocusedElementInformation(FocusedElementInformation& information)
</span><span class="cx"> {
</span><span class="cx">     layoutIfNeeded();
</span><span class="lines">@@ -2604,8 +2673,7 @@
</span><span class="cx">     information.lastInteractionLocation = m_lastInteractionLocation;
</span><span class="cx"> 
</span><span class="cx">     if (auto* renderer = m_focusedElement->renderer()) {
</span><del>-        auto& elementFrame = m_page->focusController().focusedOrMainFrame();
-        information.elementRect = elementRectInRootViewCoordinates(*m_focusedElement, elementFrame);
</del><ins>+        information.elementRect = elementRectInRootViewCoordinates(*m_focusedElement);
</ins><span class="cx">         information.nodeFontSize = renderer->style().fontDescription().computedSize();
</span><span class="cx"> 
</span><span class="cx">         bool inFixed = false;
</span><span class="lines">@@ -2621,13 +2689,11 @@
</span><span class="cx">     information.allowsUserScaling = m_viewportConfiguration.allowsUserScaling();
</span><span class="cx">     information.allowsUserScalingIgnoringAlwaysScalable = m_viewportConfiguration.allowsUserScalingIgnoringAlwaysScalable();
</span><span class="cx">     if (auto* nextElement = nextAssistableElement(m_focusedElement.get(), *m_page, true)) {
</span><del>-        if (auto* frame = nextElement->document().frame())
-            information.nextNodeRect = elementRectInRootViewCoordinates(*nextElement, *frame);
</del><ins>+        information.nextNodeRect = elementRectInRootViewCoordinates(*nextElement);
</ins><span class="cx">         information.hasNextNode = true;
</span><span class="cx">     }
</span><span class="cx">     if (auto* previousElement = nextAssistableElement(m_focusedElement.get(), *m_page, false)) {
</span><del>-        if (auto* frame = previousElement->document().frame())
-            information.previousNodeRect = elementRectInRootViewCoordinates(*previousElement, *frame);
</del><ins>+        information.previousNodeRect = elementRectInRootViewCoordinates(*previousElement);
</ins><span class="cx">         information.hasPreviousNode = true;
</span><span class="cx">     }
</span><span class="cx">     information.focusedElementIdentifier = m_currentFocusedElementIdentifier;
</span></span></pre>
</div>
</div>

</body>
</html>