- Revision
- 271817
- Author
- [email protected]
- Date
- 2021-01-25 14:10:36 -0800 (Mon, 25 Jan 2021)
Log Message
Cherry-pick r271386. rdar://problem/73426229
Double tap to select does not work if the page clears selections on tap, like grammarly.com does
https://bugs.webkit.org/show_bug.cgi?id=220454
Source/WebKit:
rdar://67757411
Reviewed by Wenson Hsieh.
Double tap to select content did not work on grammerly.com on iPad because this is a desktop website run on a touch-based device,
and there was a script running that would clear the selection on a mouseDown event. When we would send synthetic click events to the page
we would first update the selection and then on completion of the tap, we would dispatch a mouseDown and mouseUp event on iOS. On Mac, we
update the selection between the mouseDown and the mouseUp, so in order to bring us more in line with mac/mouse behaviors, we are now saving
the information needed to update the selection when we believe we are in the middle of a potential tap, and then setting the selection between
these two events. This makes for a more expected change of events, and does not let grammerly.com clear a valid selection based off of synthetic
clicks.
Test: fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::completeSyntheticClick):
(WebKit::WebPage::setSelectionRange):
(WebKit::WebPage::selectTextWithGranularityAtPoint):
LayoutTests:
Reviewed by Wenson Hsieh.
* fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt: Added.
* fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271386 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Modified Paths
Added Paths
Diff
Modified: branches/safari-611-branch/LayoutTests/ChangeLog (271816 => 271817)
--- branches/safari-611-branch/LayoutTests/ChangeLog 2021-01-25 22:10:32 UTC (rev 271816)
+++ branches/safari-611-branch/LayoutTests/ChangeLog 2021-01-25 22:10:36 UTC (rev 271817)
@@ -1,5 +1,53 @@
2021-01-25 Alan Coon <[email protected]>
+ Cherry-pick r271386. rdar://problem/73426229
+
+ Double tap to select does not work if the page clears selections on tap, like grammarly.com does
+ https://bugs.webkit.org/show_bug.cgi?id=220454
+ Source/WebKit:
+
+ rdar://67757411
+
+ Reviewed by Wenson Hsieh.
+
+ Double tap to select content did not work on grammerly.com on iPad because this is a desktop website run on a touch-based device,
+ and there was a script running that would clear the selection on a mouseDown event. When we would send synthetic click events to the page
+ we would first update the selection and then on completion of the tap, we would dispatch a mouseDown and mouseUp event on iOS. On Mac, we
+ update the selection between the mouseDown and the mouseUp, so in order to bring us more in line with mac/mouse behaviors, we are now saving
+ the information needed to update the selection when we believe we are in the middle of a potential tap, and then setting the selection between
+ these two events. This makes for a more expected change of events, and does not let grammerly.com clear a valid selection based off of synthetic
+ clicks.
+
+ Test: fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html
+
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::setSelectionRange):
+ (WebKit::WebPage::selectTextWithGranularityAtPoint):
+
+ LayoutTests:
+
+ Reviewed by Wenson Hsieh.
+
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt: Added.
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271386 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-01-11 Megan Gardner <[email protected]>
+
+ Double tap to select does not work if the page clears selections on tap, like grammarly.com does
+ https://bugs.webkit.org/show_bug.cgi?id=220454
+
+ Reviewed by Wenson Hsieh.
+
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt: Added.
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html: Added.
+
+2021-01-25 Alan Coon <[email protected]>
+
Cherry-pick r271367. rdar://problem/73469641
REGRESSION (r258321): CSS rules using :first-of-type are applied to any/all siblings in a group under certain circumstances
Added: branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt (0 => 271817)
--- branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt (rev 0)
+++ branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt 2021-01-25 22:10:36 UTC (rev 271817)
@@ -0,0 +1,3 @@
+PASS: Has Caret Selection
+PASS: Correct Selection
+
Added: branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html (0 => 271817)
--- branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html (rev 0)
+++ branches/safari-611-branch/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html 2021-01-25 22:10:36 UTC (rev 271817)
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <script src=""
+ <script>
+
+ function clearSelection()
+ {
+ var selection = window.getSelection() || document.selection;
+ selection.removeAllRanges();
+ }
+
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ async function runTest()
+ {
+ if (!testRunner.runUIScript)
+ return;
+
+ var output = '';
+ var editableTargetRect = document.getElementById('editable').getBoundingClientRect();
+ var firstTargetRect = document.getElementById('firstSelection').getBoundingClientRect();
+ var noneditableToEditableOffset = document.getElementById('editable').getBoundingClientRect().y - document.getElementById('noneditable').getBoundingClientRect().y;
+
+ var tapPointX = editableTargetRect.x + editableTargetRect.width / 2;
+ var tapPointY = editableTargetRect.y + editableTargetRect.height / 2;
+ var doubleTapPointX = firstTargetRect.x + firstTargetRect.width / 2;
+ var doubleTapPointY = firstTargetRect.y + firstTargetRect.height / 2 + noneditableToEditableOffset;
+
+ await tapAtPoint(tapPointX, tapPointY);
+ if (document.getSelection().type == "Caret")
+ output += 'PASS: Has Caret Selection';
+ else
+ output += 'FAIL: failed to activate caret as a result of a tap. Incorrect Selection: ' + document.getSelection().toString();
+ output += '<br>';
+
+ await didShowKeyboard();
+
+ await doubleTapAtPoint(doubleTapPointX, doubleTapPointY);
+ if (document.getSelection().toString() == "magna")
+ output += 'PASS: Correct Selection';
+ else
+ output += 'FAIL: failed to select a word as a result of a long press. Incorrect Selection: ' + document.getSelection().toString();
+ output += '<br>';
+
+ var noneditableElement = document.getElementById('noneditable');
+ noneditableElement.parentNode.removeChild(noneditableElement);
+ var editableElement = document.getElementById('editable');
+ editableElement.parentNode.removeChild(editableElement);
+ document.getElementById('target').innerHTML = output;
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', runTest, false);
+ </script>
+ <style>
+ #noneditable {
+ height: 200px;
+ width: 300px;
+ background-color: silver;
+ font-family: monospace;
+ font-size: 18px;
+ }
+ #editable {
+ height: 200px;
+ width: 300px;
+ background-color: silver;
+ font-family: monospace;
+ font-size: 18px;
+ }
+ #target {
+ height: 50px;
+ width: 300px;
+ background-color: silver;
+ font-family: monospace;
+ font-size: 18px;
+ }
+ </style>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+ <div id="noneditable">
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore <span id="firstSelection">magna</span> aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+ </div>
+ <div id="editable" contenteditable _onmousedown_="clearSelection()">
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+ </div>
+ <div id="target">
+ This test requires UIScriptController to run.
+ </div>
+</body>
+</html>
Modified: branches/safari-611-branch/Source/WebKit/ChangeLog (271816 => 271817)
--- branches/safari-611-branch/Source/WebKit/ChangeLog 2021-01-25 22:10:32 UTC (rev 271816)
+++ branches/safari-611-branch/Source/WebKit/ChangeLog 2021-01-25 22:10:36 UTC (rev 271817)
@@ -1,3 +1,65 @@
+2021-01-25 Alan Coon <[email protected]>
+
+ Cherry-pick r271386. rdar://problem/73426229
+
+ Double tap to select does not work if the page clears selections on tap, like grammarly.com does
+ https://bugs.webkit.org/show_bug.cgi?id=220454
+ Source/WebKit:
+
+ rdar://67757411
+
+ Reviewed by Wenson Hsieh.
+
+ Double tap to select content did not work on grammerly.com on iPad because this is a desktop website run on a touch-based device,
+ and there was a script running that would clear the selection on a mouseDown event. When we would send synthetic click events to the page
+ we would first update the selection and then on completion of the tap, we would dispatch a mouseDown and mouseUp event on iOS. On Mac, we
+ update the selection between the mouseDown and the mouseUp, so in order to bring us more in line with mac/mouse behaviors, we are now saving
+ the information needed to update the selection when we believe we are in the middle of a potential tap, and then setting the selection between
+ these two events. This makes for a more expected change of events, and does not let grammerly.com clear a valid selection based off of synthetic
+ clicks.
+
+ Test: fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html
+
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::setSelectionRange):
+ (WebKit::WebPage::selectTextWithGranularityAtPoint):
+
+ LayoutTests:
+
+ Reviewed by Wenson Hsieh.
+
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch-expected.txt: Added.
+ * fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271386 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-01-11 Megan Gardner <[email protected]>
+
+ Double tap to select does not work if the page clears selections on tap, like grammarly.com does
+ https://bugs.webkit.org/show_bug.cgi?id=220454
+ rdar://67757411
+
+ Reviewed by Wenson Hsieh.
+
+ Double tap to select content did not work on grammerly.com on iPad because this is a desktop website run on a touch-based device,
+ and there was a script running that would clear the selection on a mouseDown event. When we would send synthetic click events to the page
+ we would first update the selection and then on completion of the tap, we would dispatch a mouseDown and mouseUp event on iOS. On Mac, we
+ update the selection between the mouseDown and the mouseUp, so in order to bring us more in line with mac/mouse behaviors, we are now saving
+ the information needed to update the selection when we believe we are in the middle of a potential tap, and then setting the selection between
+ these two events. This makes for a more expected change of events, and does not let grammerly.com clear a valid selection based off of synthetic
+ clicks.
+
+ Test: fast/events/touch/ios/double-tap-on-editable-content-for-selection-with-clear-on-touch.html
+
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::setSelectionRange):
+ (WebKit::WebPage::selectTextWithGranularityAtPoint):
+
2021-01-14 Alan Coon <[email protected]>
Cherry-pick r271477. rdar://problem/73204264
Modified: branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/WebPage.h (271816 => 271817)
--- branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-01-25 22:10:32 UTC (rev 271816)
+++ branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-01-25 22:10:36 UTC (rev 271817)
@@ -1798,6 +1798,8 @@
Vector<RefPtr<SandboxExtension>> consumeSandboxExtensions(SandboxExtension::HandleArray&&);
void revokeSandboxExtensions(Vector<RefPtr<SandboxExtension>>& sandboxExtensions);
+
+ void setSelectionRange(const WebCore::IntPoint&, WebCore::TextGranularity, bool);
WebCore::PageIdentifier m_identifier;
@@ -1825,6 +1827,7 @@
HashMap<PDFPluginIdentifier, WeakPtr<PDFPlugin>> m_pdfPlugInsWithHUD;
#endif
+ WTF::Function<void()> m_selectionChangedHandler;
bool m_isInRedo { false };
bool m_isClosed { false };
bool m_tabToLinks { false };
Modified: branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (271816 => 271817)
--- branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2021-01-25 22:10:32 UTC (rev 271816)
+++ branches/safari-611-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2021-01-25 22:10:36 UTC (rev 271817)
@@ -853,6 +853,9 @@
if (m_isClosed)
return;
+ if (auto selectionChangedHandler = std::exchange(m_selectionChangedHandler, {}))
+ selectionChangedHandler();
+
tapWasHandled |= mainframe.eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType, pointerId));
if (m_isClosed)
return;
@@ -1166,6 +1169,9 @@
void WebPage::commitPotentialTapFailed()
{
+ if (auto selectionChangedHandler = std::exchange(m_selectionChangedHandler, {}))
+ selectionChangedHandler();
+
ContentChangeObserver::didCancelPotentialTap(m_page->mainFrame());
if (!m_page->focusController().focusedOrMainFrame().selection().selection().isContentEditable())
clearSelection();
@@ -1182,6 +1188,9 @@
void WebPage::cancelPotentialTapInFrame(WebFrame& frame)
{
+ if (auto selectionChangedHandler = std::exchange(m_selectionChangedHandler, {}))
+ selectionChangedHandler();
+
if (m_potentialTapNode) {
auto* potentialTapFrame = m_potentialTapNode->document().frame();
if (potentialTapFrame && !potentialTapFrame->tree().isDescendantOf(frame.coreFrame()))
@@ -2111,7 +2120,7 @@
m_page->focusController().setFocusedFrame(result.innerNodeFrame());
}
-void WebPage::selectTextWithGranularityAtPoint(const WebCore::IntPoint& point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, CompletionHandler<void()>&& completionHandler)
+void WebPage::setSelectionRange(const WebCore::IntPoint& point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement)
{
setFocusedFrameBeforeSelectingTextAtLocation(point);
@@ -2120,9 +2129,32 @@
if (range)
frame.selection().setSelectedRange(*range, Affinity::Upstream, WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
m_initialSelection = range;
- completionHandler();
}
+void WebPage::selectTextWithGranularityAtPoint(const WebCore::IntPoint& point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, CompletionHandler<void()>&& completionHandler)
+{
+ if (!m_potentialTapNode) {
+ setSelectionRange(point, granularity, isInteractingWithFocusedElement);
+ completionHandler();
+ return;
+ }
+
+ ASSERT(!m_selectionChangedHandler);
+ if (auto selectionChangedHandler = std::exchange(m_selectionChangedHandler, {}))
+ selectionChangedHandler();
+
+ m_selectionChangedHandler = [point, granularity, isInteractingWithFocusedElement, completionHandler = WTFMove(completionHandler), webPage = makeWeakPtr(*this), this]() mutable {
+ RefPtr<WebPage> strongPage = webPage.get();
+ if (!strongPage) {
+ completionHandler();
+ return;
+ }
+ setSelectionRange(point, granularity, isInteractingWithFocusedElement);
+ completionHandler();
+ };
+
+}
+
void WebPage::beginSelectionInDirection(WebCore::SelectionDirection direction, CallbackID callbackID)
{
m_selectionAnchor = direction == SelectionDirection::Left ? Start : End;