Title: [283619] trunk/Source
Revision
283619
Author
[email protected]
Date
2021-10-06 08:23:05 -0700 (Wed, 06 Oct 2021)

Log Message

Allow text selection to flip.
https://bugs.webkit.org/show_bug.cgi?id=231234
rdar://83889188

Reviewed by Wenson Hsieh.

Source/WebKit:

In order to bring webkit more in line with UIKit, allow text selection to flip.
This also requires a UIKit change tracked in rdar://83788439
This is currently guarded behind an off-by-default flag so that we can
test this new behavior before turning it on by default.

* Platform/spi/ios/UIKitSPI.h:
* Shared/ios/GestureTypes.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(toUIWKSelectionFlags):
(toSelectionFlags):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::updatePreferences):
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::selectionFlippingEnabled const):
(WebKit::WebPage::setSelectionFlippingEnabled):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::rangeForPointInRootViewCoordinates):
(WebKit::WebPage::updateSelectionWithTouches):

Source/WTF:

Add an internal flag to guard text selection flipping while
we test to make sure this is reasonable to turn on everywhere.

* Scripts/Preferences/WebPreferencesInternal.yaml:

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (283618 => 283619)


--- trunk/Source/WTF/ChangeLog	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WTF/ChangeLog	2021-10-06 15:23:05 UTC (rev 283619)
@@ -1,3 +1,16 @@
+2021-10-06  Megan Gardner  <[email protected]>
+
+        Allow text selection to flip.
+        https://bugs.webkit.org/show_bug.cgi?id=231234
+        rdar://83889188
+
+        Reviewed by Wenson Hsieh.
+
+        Add an internal flag to guard text selection flipping while
+        we test to make sure this is reasonable to turn on everywhere.
+
+        * Scripts/Preferences/WebPreferencesInternal.yaml:
+
 2021-10-05  Tim Horton  <[email protected]>
 
         Add an alternate style for form controls, and implement it for checkboxes and radio buttons

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml (283618 => 283619)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2021-10-06 15:23:05 UTC (rev 283619)
@@ -681,6 +681,15 @@
       default: true
     WebCore:
       default: true
+      
+SelectionFlippingEnabled:
+  type: bool
+  humanReadableName: "Selection Flipping"
+  humanReadableDescription: "Enable Selection Flipping"
+  webcoreBinding: none
+  defaultValue:
+    WebKit:
+      default: false
 
 # FIXME: This is not implemented for WebKitLegacy, so should be excluded from WebKitLegacy entirely.
 ServiceWorkersEnabled:

Modified: trunk/Source/WebKit/ChangeLog (283618 => 283619)


--- trunk/Source/WebKit/ChangeLog	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/ChangeLog	2021-10-06 15:23:05 UTC (rev 283619)
@@ -1,3 +1,30 @@
+2021-10-06  Megan Gardner  <[email protected]>
+
+        Allow text selection to flip.
+        https://bugs.webkit.org/show_bug.cgi?id=231234
+        rdar://83889188
+
+        Reviewed by Wenson Hsieh.
+
+        In order to bring webkit more in line with UIKit, allow text selection to flip.
+        This also requires a UIKit change tracked in rdar://83788439
+        This is currently guarded behind an off-by-default flag so that we can
+        test this new behavior before turning it on by default.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * Shared/ios/GestureTypes.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (toUIWKSelectionFlags):
+        (toSelectionFlags):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::updatePreferences):
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::selectionFlippingEnabled const):
+        (WebKit::WebPage::setSelectionFlippingEnabled):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::rangeForPointInRootViewCoordinates):
+        (WebKit::WebPage::updateSelectionWithTouches):
+
 2021-10-06  Chris Dumez  <[email protected]>
 
         IPC SimpleArgumentEncoder should static_assert(std::is_trivially_copyable<T>)

Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (283618 => 283619)


--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2021-10-06 15:23:05 UTC (rev 283619)
@@ -139,6 +139,9 @@
 #import <UIKit/UIPointerStyle_Private.h>
 #endif
 
+// FIXME: STAGING for rdar://75546704 Remove later.
+#define UIWKSelectionFlipped 2
+
 #else // USE(APPLE_INTERNAL_SDK)
 
 #if ENABLE(DRAG_SUPPORT)
@@ -682,6 +685,7 @@
 typedef NS_ENUM(NSInteger, UIWKSelectionFlags) {
     UIWKNone = 0,
     UIWKWordIsNearTap = 1,
+    UIWKSelectionFlipped = 2,
     UIWKPhraseBoundaryChanged = 4,
 };
 

Modified: trunk/Source/WebKit/Shared/ios/GestureTypes.h (283618 => 283619)


--- trunk/Source/WebKit/Shared/ios/GestureTypes.h	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/Shared/ios/GestureTypes.h	2021-10-06 15:23:05 UTC (rev 283619)
@@ -65,7 +65,8 @@
 
 enum SelectionFlags : uint8_t {
     WordIsNearTap = 1 << 0,
-    PhraseBoundaryChanged = 1 << 1,
+    SelectionFlipped = 1 << 1,
+    PhraseBoundaryChanged = 1 << 2,
 };
 
 enum class RespectSelectionAnchor : bool {
@@ -107,6 +108,7 @@
     using values = EnumValues<
         WebKit::SelectionFlags,
         WebKit::SelectionFlags::WordIsNearTap,
+        WebKit::SelectionFlags::SelectionFlipped,
         WebKit::SelectionFlags::PhraseBoundaryChanged
     >;
 };

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (283618 => 283619)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-10-06 15:23:05 UTC (rev 283619)
@@ -4273,6 +4273,8 @@
     NSInteger uiFlags = UIWKNone;
     if (flags.contains(WebKit::WordIsNearTap))
         uiFlags |= UIWKWordIsNearTap;
+    if (flags.contains(WebKit::SelectionFlipped))
+        uiFlags |= UIWKSelectionFlipped;
     if (flags.contains(WebKit::PhraseBoundaryChanged))
         uiFlags |= UIWKPhraseBoundaryChanged;
 
@@ -4284,6 +4286,8 @@
     OptionSet<WebKit::SelectionFlags> flags;
     if (uiFlags & UIWKWordIsNearTap)
         flags.add(WebKit::WordIsNearTap);
+    if (uiFlags & UIWKSelectionFlipped)
+        flags.add(WebKit::SelectionFlipped);
     if (uiFlags & UIWKPhraseBoundaryChanged)
         flags.add(WebKit::PhraseBoundaryChanged);
     return flags;

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (283618 => 283619)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-06 15:23:05 UTC (rev 283619)
@@ -3981,6 +3981,8 @@
 
 #if PLATFORM(COCOA)
     m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey());
+    
+    m_selectionFlippingEnabled = store.getBoolValueForKey(WebPreferencesKey::selectionFlippingEnabledKey());
 #endif
 #if ENABLE(PAYMENT_REQUEST)
     settings.setPaymentRequestEnabled(store.getBoolValueForKey(WebPreferencesKey::applePayEnabledKey()));

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (283618 => 283619)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-10-06 15:23:05 UTC (rev 283619)
@@ -1133,6 +1133,9 @@
 #if PLATFORM(COCOA)
     bool pdfPluginEnabled() const { return m_pdfPluginEnabled; }
     void setPDFPluginEnabled(bool enabled) { m_pdfPluginEnabled = enabled; }
+    
+    bool selectionFlippingEnabled() const { return m_selectionFlippingEnabled; }
+    void setSelectionFlippingEnabled(bool enabled) { m_selectionFlippingEnabled = enabled; }
 
     NSDictionary *dataDetectionContext() const { return m_dataDetectionContext.get(); }
 #endif
@@ -1996,6 +1999,7 @@
 #if PLATFORM(COCOA)
     bool m_pdfPluginEnabled { false };
     bool m_hasCachedWindowFrame { false };
+    bool m_selectionFlippingEnabled { false };
 
     // The frame of the containing window in screen coordinates.
     WebCore::FloatRect m_windowFrameInScreenCoordinates;

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (283618 => 283619)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2021-10-06 15:21:31 UTC (rev 283618)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2021-10-06 15:23:05 UTC (rev 283619)
@@ -161,6 +161,8 @@
 
 namespace WebKit {
 
+enum class SelectionWasFlipped : bool { No, Yes };
+
 // FIXME: Unclear if callers in this file are correctly choosing which of these two functions to use.
 
 static String plainTextForContext(const SimpleRange& range)
@@ -1503,7 +1505,7 @@
     completionHandler(point, gestureType, gestureState, flags);
 }
 
-static std::optional<SimpleRange> rangeForPointInRootViewCoordinates(Frame& frame, const IntPoint& pointInRootViewCoordinates, bool baseIsStart)
+static std::pair<std::optional<SimpleRange>, SelectionWasFlipped> rangeForPointInRootViewCoordinates(Frame& frame, const IntPoint& pointInRootViewCoordinates, bool baseIsStart, bool selectionFlippingEnabled)
 {
     VisibleSelection existingSelection = frame.selection().selection();
     VisiblePosition selectionStart = existingSelection.visibleStart();
@@ -1511,27 +1513,29 @@
 
     auto pointInDocument = frame.view()->rootViewToContents(pointInRootViewCoordinates);
 
-    auto node = selectionStart.deepEquivalent().containerNode();
-    if (node && node->renderStyle() && node->renderStyle()->isVerticalWritingMode()) {
-        if (baseIsStart) {
-            int startX = selectionStart.absoluteCaretBounds().center().x();
-            if (pointInDocument.x() > startX)
-                pointInDocument.setX(startX);
+    if (!selectionFlippingEnabled) {
+        auto node = selectionStart.deepEquivalent().containerNode();
+        if (node && node->renderStyle() && node->renderStyle()->isVerticalWritingMode()) {
+            if (baseIsStart) {
+                int startX = selectionStart.absoluteCaretBounds().center().x();
+                if (pointInDocument.x() > startX)
+                    pointInDocument.setX(startX);
+            } else {
+                int endX = selectionEnd.absoluteCaretBounds().center().x();
+                if (pointInDocument.x() < endX)
+                    pointInDocument.setX(endX);
+            }
         } else {
-            int endX = selectionEnd.absoluteCaretBounds().center().x();
-            if (pointInDocument.x() < endX)
-                pointInDocument.setX(endX);
+            if (baseIsStart) {
+                int startY = selectionStart.absoluteCaretBounds().center().y();
+                if (pointInDocument.y() < startY)
+                    pointInDocument.setY(startY);
+            } else {
+                int endY = selectionEnd.absoluteCaretBounds().center().y();
+                if (pointInDocument.y() > endY)
+                    pointInDocument.setY(endY);
+            }
         }
-    } else {
-        if (baseIsStart) {
-            int startY = selectionStart.absoluteCaretBounds().center().y();
-            if (pointInDocument.y() < startY)
-                pointInDocument.setY(startY);
-        } else {
-            int endY = selectionEnd.absoluteCaretBounds().center().y();
-            if (pointInDocument.y() > endY)
-                pointInDocument.setY(endY);
-        }
     }
 
     auto hitTest = frame.eventHandler().hitTestResultAtPoint(pointInDocument, {
@@ -1542,10 +1546,11 @@
 
     RefPtr targetNode = hitTest.targetNode();
     if (targetNode && !HTMLElement::shouldExtendSelectionToTargetNode(*targetNode, existingSelection))
-        return std::nullopt;
+        return { std::nullopt, SelectionWasFlipped::No };
 
+    VisiblePosition result;
     std::optional<SimpleRange> range;
-    VisiblePosition result;
+    SelectionWasFlipped selectionFlipped = SelectionWasFlipped::No;
 
     if (targetNode)
         result = frame.eventHandler().selectionExtentRespectingEditingBoundary(frame.selection().selection(), hitTest.localPoint(), targetNode.get()).deepEquivalent();
@@ -1553,25 +1558,37 @@
         result = frame.visiblePositionForPoint(pointInDocument).deepEquivalent();
     
     if (baseIsStart) {
-        if (result <= selectionStart)
+        bool flipSelection = result < selectionStart;
+
+        if ((flipSelection && !selectionFlippingEnabled) || result == selectionStart)
             result = selectionStart.next();
         else if (RefPtr containerNode = selectionStart.deepEquivalent().containerNode(); containerNode && targetNode && &containerNode->treeScope() != &targetNode->treeScope())
             result = VisibleSelection::adjustPositionForEnd(result.deepEquivalent(), containerNode.get());
-
-        range = makeSimpleRange(selectionStart, result);
+        
+        if (selectionFlippingEnabled && flipSelection) {
+            range = makeSimpleRange(result, selectionStart);
+            selectionFlipped = SelectionWasFlipped::Yes;
+        } else
+            range = makeSimpleRange(selectionStart, result);
     } else {
-        if (selectionEnd <= result)
+        bool flipSelection = selectionEnd < result;
+        
+        if ((flipSelection && !selectionFlippingEnabled) || result == selectionEnd)
             result = selectionEnd.previous();
         else if (RefPtr containerNode = selectionEnd.deepEquivalent().containerNode(); containerNode && targetNode && &containerNode->treeScope() != &targetNode->treeScope())
             result = VisibleSelection::adjustPositionForStart(result.deepEquivalent(), containerNode.get());
 
-        range = makeSimpleRange(result, selectionEnd);
+        if (selectionFlippingEnabled && flipSelection) {
+            range = makeSimpleRange(selectionEnd, result);
+            selectionFlipped = SelectionWasFlipped::Yes;
+        } else
+            range = makeSimpleRange(result, selectionEnd);
     }
     
     if (range && HTMLElement::isInsideImageOverlay(*range))
-        return expandForImageOverlay(*range);
+        return { expandForImageOverlay(*range), SelectionWasFlipped::No };
 
-    return range;
+    return { range, selectionFlipped };
 }
 
 static std::optional<SimpleRange> rangeAtWordBoundaryForPosition(Frame* frame, const VisiblePosition& position, bool baseIsStart)
@@ -1743,6 +1760,7 @@
 
     std::optional<SimpleRange> range;
     OptionSet<SelectionFlags> flags;
+    SelectionWasFlipped selectionFlipped = SelectionWasFlipped::No;
 
     switch (selectionTouch) {
     case SelectionTouch::Started:
@@ -1753,7 +1771,7 @@
         if (frame->selection().selection().isContentEditable())
             range = makeSimpleRange(closestWordBoundaryForPosition(position));
         else
-            range = rangeForPointInRootViewCoordinates(frame, point, baseIsStart);
+            std::tie(range, selectionFlipped) = rangeForPointInRootViewCoordinates(frame, point, baseIsStart, selectionFlippingEnabled());
         break;
 
     case SelectionTouch::EndedMovingForward:
@@ -1762,12 +1780,15 @@
         break;
 
     case SelectionTouch::Moved:
-        range = rangeForPointInRootViewCoordinates(frame, point, baseIsStart);
+        std::tie(range, selectionFlipped) = rangeForPointInRootViewCoordinates(frame, point, baseIsStart, selectionFlippingEnabled());
         break;
     }
 
     if (range)
         frame->selection().setSelectedRange(range, position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
+    
+    if (selectionFlipped == SelectionWasFlipped::Yes)
+        flags = SelectionFlipped;
 
     completionHandler(point, selectionTouch, flags);
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to