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);
}