Diff
Modified: trunk/Source/WebKit/ChangeLog (230525 => 230526)
--- trunk/Source/WebKit/ChangeLog 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/ChangeLog 2018-04-11 16:01:31 UTC (rev 230526)
@@ -1,3 +1,15 @@
+2018-04-11 Ryan Haddad <ryanhad...@apple.com>
+
+ Unreviewed, rolling out r230508.
+
+ Breaks internal builds.
+
+ Reverted changeset:
+
+ "Remove block selection code"
+ https://bugs.webkit.org/show_bug.cgi?id=184470
+ https://trac.webkit.org/changeset/230508
+
2018-04-11 Antoine Quint <grao...@apple.com>
[Web Animations] Turn Web Animations on by default
Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (230525 => 230526)
--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -540,6 +540,9 @@
@end
@interface UIWKSelectionAssistant ()
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)blockSelectionChangedWithTouch:(UIWKSelectionTouch)touch withFlags:(UIWKSelectionFlags)flags growThreshold:(CGFloat)grow shrinkThreshold:(CGFloat)shrink;
+#endif
- (BOOL)shouldHandleSingleTapAtPoint:(CGPoint)point;
- (void)selectionChangedWithGestureAt:(CGPoint)point withGesture:(UIWKGestureType)gestureType withState:(UIGestureRecognizerState)gestureState withFlags:(UIWKSelectionFlags)flags;
- (void)selectionChangedWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch withFlags:(UIWKSelectionFlags)flags;
@@ -589,6 +592,15 @@
@property (nonatomic, readonly, assign) UITapGestureRecognizer *singleTapGesture;
@end
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+typedef NS_ENUM(NSInteger, UIWKHandlePosition) {
+ UIWKHandleTop = 0,
+ UIWKHandleRight = 1,
+ UIWKHandleBottom = 2,
+ UIWKHandleLeft = 3,
+};
+#endif
+
@protocol UIWKInteractionViewProtocol
- (void)changeSelectionWithGestureAt:(CGPoint)point withGesture:(UIWKGestureType)gestureType withState:(UIGestureRecognizerState)state;
- (void)changeSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch baseIsStart:(BOOL)baseIsStart withFlags:(UIWKSelectionFlags)flags;
@@ -613,6 +625,10 @@
- (void)_cancelLongPressGestureRecognizer;
@optional
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)changeBlockSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch forHandle:(UIWKHandlePosition)handle;
+#endif
+
- (void)clearSelection;
- (void)replaceDictatedText:(NSString *)oldText withText:(NSString *)newText;
- (void)requestDictationContext:(void (^)(NSString *selectedText, NSString *prefixText, NSString *postfixText))completionHandler;
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -295,6 +295,9 @@
virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) = 0;
virtual void positionInformationDidChange(const InteractionInformationAtPosition&) = 0;
virtual void saveImageToLibrary(Ref<WebCore::SharedBuffer>&&) = 0;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ virtual void didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold) = 0;
+#endif
virtual void showPlaybackTargetPicker(bool hasVideo, const WebCore::IntRect& elementRect) = 0;
virtual void disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID) = 0;
virtual double minimumZoomScale() const = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -554,6 +554,9 @@
void selectWithGesture(const WebCore::IntPoint, WebCore::TextGranularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)>&&);
void updateSelectionWithTouches(const WebCore::IntPoint, uint32_t touches, bool baseIsStart, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, CallbackBase::Error)>&&);
void selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)>&&);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ void updateBlockSelectionWithTouch(const WebCore::IntPoint, uint32_t touch, uint32_t handlePosition);
+#endif
void extendSelection(WebCore::TextGranularity);
void selectWordBackward();
void moveSelectionByOffset(int32_t offset, WTF::Function<void (CallbackBase::Error)>&&);
@@ -578,6 +581,9 @@
void stopInteraction();
void performActionOnElement(uint32_t action);
void saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ void didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold);
+#endif
void focusNextAssistedNode(bool isForward, WTF::Function<void (CallbackBase::Error)>&& = [] (auto) { });
void setAssistedNodeValue(const String&);
void setAssistedNodeValueAsNumber(double);
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2018-04-11 16:01:31 UTC (rev 230526)
@@ -184,6 +184,9 @@
SelectionContextCallback(String selectedText, String beforeText, String afterText, WebKit::CallbackID callbackID)
InterpretKeyEvent(struct WebKit::EditorState state, bool isCharEvent) -> (bool handled)
DidReceivePositionInformation(struct WebKit::InteractionInformationAtPosition information)
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ DidUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
+#endif
SaveImageToLibrary(WebKit::SharedMemory::Handle handle, uint64_t size)
ShowPlaybackTargetPicker(bool hasVideo, WebCore::IntRect elementRect)
CommitPotentialTapFailed()
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -132,6 +132,9 @@
bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) override;
void positionInformationDidChange(const InteractionInformationAtPosition&) override;
void saveImageToLibrary(Ref<WebCore::SharedBuffer>&&) override;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ void didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold) override;
+#endif
void showPlaybackTargetPicker(bool hasVideo, const WebCore::IntRect& elementRect) override;
bool handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, API::OpenPanelParameters*, WebOpenPanelResultListenerProxy*) override;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2018-04-11 16:01:31 UTC (rev 230526)
@@ -561,6 +561,14 @@
{
[m_contentView _stopAssistingNode];
}
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+void PageClientImpl::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
+{
+ [m_contentView _didUpdateBlockSelectionWithTouch:(SelectionTouch)touch withFlags:(SelectionFlags)flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
+}
+#endif
+
void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
{
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -316,6 +316,9 @@
- (void)_didEndScrollingOrZooming;
- (void)_overflowScrollingWillBegin;
- (void)_overflowScrollingDidEnd;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)_didUpdateBlockSelectionWithTouch:(WebKit::SelectionTouch)touch withFlags:(WebKit::SelectionFlags)flags growThreshold:(CGFloat)growThreshold shrinkThreshold:(CGFloat)shrinkThreshold;
+#endif
- (void)_showPlaybackTargetPicker:(BOOL)hasVideo fromRect:(const WebCore::IntRect&)elementRect;
- (void)_showRunOpenPanel:(API::OpenPanelParameters*)parameters resultListener:(WebKit::WebOpenPanelResultListenerProxy*)listener;
- (void)accessoryDone;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2018-04-11 16:01:31 UTC (rev 230526)
@@ -2634,6 +2634,22 @@
return static_cast<UIWKSelectionFlags>(uiFlags);
}
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+static inline SelectionHandlePosition toSelectionHandlePosition(UIWKHandlePosition position)
+{
+ switch (position) {
+ case UIWKHandleTop:
+ return SelectionHandlePosition::Top;
+ case UIWKHandleRight:
+ return SelectionHandlePosition::Right;
+ case UIWKHandleBottom:
+ return SelectionHandlePosition::Bottom;
+ case UIWKHandleLeft:
+ return SelectionHandlePosition::Left;
+ }
+}
+#endif
+
static inline WebCore::TextGranularity toWKTextGranularity(UITextGranularity granularity)
{
switch (granularity) {
@@ -2692,6 +2708,15 @@
[(UIWKTextInteractionAssistant *)[view interactionAssistant] selectionChangedWithTouchAt:(CGPoint)point withSelectionTouch:toUIWKSelectionTouch((SelectionTouch)touch) withFlags:static_cast<UIWKSelectionFlags>(flags)];
}
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)_didUpdateBlockSelectionWithTouch:(SelectionTouch)touch withFlags:(SelectionFlags)flags growThreshold:(CGFloat)growThreshold shrinkThreshold:(CGFloat)shrinkThreshold
+{
+ [_webSelectionAssistant blockSelectionChangedWithTouch:toUIWKSelectionTouch(touch) withFlags:toUIWKSelectionFlags(flags) growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
+ if (touch != SelectionTouch::Started && touch != SelectionTouch::Moved)
+ _usingGestureForSelection = NO;
+}
+#endif
+
- (BOOL)_isInteractingWithAssistedNode
{
return _textSelectionAssistant != nil;
@@ -2712,6 +2737,13 @@
});
}
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)changeSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch baseIsStart:(BOOL)baseIsStart
+{
+ [self changeSelectionWithTouchAt:point withSelectionTouch:touch baseIsStart:baseIsStart withFlags:UIWKNone];
+}
+#endif
+
- (void)changeSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch baseIsStart:(BOOL)baseIsStart withFlags:(UIWKSelectionFlags)flags
{
_usingGestureForSelection = YES;
@@ -2732,6 +2764,19 @@
});
}
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+- (void)changeBlockSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch forHandle:(UIWKHandlePosition)handle
+{
+ // This was only readded to avoid a crash due to incompatibilities with certain version of UIKit.
+ // This should be removed ASAP.
+ // The selection will be properly updated with the next update, selection still functions
+ // without this function doing anything.
+
+ _usingGestureForSelection = YES;
+ _page->updateBlockSelectionWithTouch(WebCore::IntPoint(point), static_cast<uint32_t>(toSelectionTouch(touch)), static_cast<uint32_t>(toSelectionHandlePosition(handle)));
+}
+#endif
+
- (void)moveByOffset:(NSInteger)offset
{
if (!offset)
Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (230525 => 230526)
--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2018-04-11 16:01:31 UTC (rev 230526)
@@ -673,6 +673,18 @@
auto buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
m_pageClient.saveImageToLibrary(WTFMove(buffer));
}
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+void WebPageProxy::updateBlockSelectionWithTouch(const WebCore::IntPoint point, uint32_t touch, uint32_t handlePosition)
+{
+ m_process->send(Messages::WebPage::UpdateBlockSelectionWithTouch(point, touch, handlePosition), m_pageID);
+}
+
+void WebPageProxy::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
+{
+ m_pageClient.didUpdateBlockSelectionWithTouch(touch, flags, growThreshold, shrinkThreshold);
+}
+#endif
void WebPageProxy::applicationDidEnterBackground()
{
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (230525 => 230526)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-04-11 16:01:31 UTC (rev 230526)
@@ -580,6 +580,9 @@
void requestAssistedNodeInformation(CallbackID);
void selectWithGesture(const WebCore::IntPoint&, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, CallbackID);
void updateSelectionWithTouches(const WebCore::IntPoint&, uint32_t touches, bool baseIsStart, CallbackID);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ void updateBlockSelectionWithTouch(const WebCore::IntPoint&, uint32_t touch, uint32_t handlePosition);
+#endif
void selectWithTwoTouches(const WebCore::IntPoint& from, const WebCore::IntPoint& to, uint32_t gestureType, uint32_t gestureState, CallbackID);
void extendSelection(uint32_t granularity);
void selectWordBackward();
@@ -1104,6 +1107,12 @@
static void convertSelectionRectsToRootView(WebCore::FrameView*, Vector<WebCore::SelectionRect>&);
RefPtr<WebCore::Range> rangeForWebSelectionAtPosition(const WebCore::IntPoint&, const WebCore::VisiblePosition&, SelectionFlags&);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ RefPtr<WebCore::Range> rangeForBlockAtPoint(const WebCore::IntPoint&);
+ void computeExpandAndShrinkThresholdsForHandle(const WebCore::IntPoint&, SelectionHandlePosition, float& growThreshold, float& shrinkThreshold);
+ Ref<WebCore::Range> expandedRangeFromHandle(WebCore::Range&, SelectionHandlePosition);
+ Ref<WebCore::Range> contractedRangeFromHandle(WebCore::Range& currentRange, SelectionHandlePosition, SelectionFlags&);
+#endif
void getAssistedNodeInformation(AssistedNodeInformation&);
void platformInitializeAccessibility();
void handleSyntheticClick(WebCore::Node* nodeRespondingToClick, const WebCore::FloatPoint& location);
@@ -1112,7 +1121,10 @@
void resetTextAutosizing();
WebCore::VisiblePosition visiblePositionInFocusedNodeForPoint(const WebCore::Frame&, const WebCore::IntPoint&, bool isInteractingWithAssistedNode);
RefPtr<WebCore::Range> rangeForGranularityAtPoint(WebCore::Frame&, const WebCore::IntPoint&, uint32_t granularity, bool isInteractingWithAssistedNode);
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ RefPtr<WebCore::Range> changeBlockSelection(const WebCore::IntPoint&, SelectionHandlePosition, float& growThreshold, float& shrinkThreshold, SelectionFlags&);
#endif
+#endif
#if PLATFORM(IOS) && ENABLE(DATA_INTERACTION)
void requestStartDataInteraction(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (230525 => 230526)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-04-11 16:01:31 UTC (rev 230526)
@@ -57,6 +57,9 @@
BlurAssistedNode()
SelectWithGesture(WebCore::IntPoint point, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, WebKit::CallbackID callbackID)
UpdateSelectionWithTouches(WebCore::IntPoint point, uint32_t touches, bool baseIsStart, WebKit::CallbackID callbackID)
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+ UpdateBlockSelectionWithTouch(WebCore::IntPoint point, uint32_t touch, uint32_t handlePosition)
+#endif
SelectWithTwoTouches(WebCore::IntPoint from, WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, WebKit::CallbackID callbackID)
ExtendSelection(uint32_t granularity)
SelectWordBackward()
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (230525 => 230526)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2018-04-11 15:58:43 UTC (rev 230525)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2018-04-11 16:01:31 UTC (rev 230526)
@@ -1075,6 +1075,364 @@
return range->collapsed() ? nullptr : range;
}
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+static bool canShrinkToTextSelection(Range& range)
+{
+ if (range.startContainer().isTextNode() && range.endContainer().isTextNode())
+ return true;
+ return canShrinkToTextSelection(range.commonAncestorContainer());
+}
+static const int maxHitTests = 10;
+
+static inline float distanceBetweenRectsForPosition(IntRect& first, IntRect& second, SelectionHandlePosition handlePosition)
+{
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ return abs(first.y() - second.y());
+ case SelectionHandlePosition::Right:
+ return abs(first.maxX() - second.maxX());
+ case SelectionHandlePosition::Bottom:
+ return abs(first.maxY() - second.maxY());
+ case SelectionHandlePosition::Left:
+ return abs(first.x() - second.x());
+ }
+}
+
+static inline bool rectsEssentiallyTheSame(IntRect& first, IntRect& second, float allowablePercentDifference)
+{
+ const float minMagnitudeRatio = 1.0 - allowablePercentDifference;
+ const float maxDisplacementRatio = allowablePercentDifference;
+
+ float xOriginShiftRatio = abs(first.x() - second.x()) / std::min(first.width(), second.width());
+ float yOriginShiftRatio = abs(first.y() - second.y()) / std::min(first.height(), second.height());
+
+ float widthRatio = std::min(first.width() / second.width(), second.width() / first.width());
+ float heightRatio = std::min(first.height() / second.height(), second.height() / first.height());
+ return ((widthRatio > minMagnitudeRatio && xOriginShiftRatio < maxDisplacementRatio) && (heightRatio > minMagnitudeRatio && yOriginShiftRatio < maxDisplacementRatio));
+}
+
+static inline RefPtr<Range> unionDOMRanges(Range* rangeA, Range* rangeB)
+{
+ if (!rangeB)
+ return rangeA;
+ if (!rangeA)
+ return rangeB;
+
+ auto startToStartComparison = rangeA->compareBoundaryPoints(Range::START_TO_START, *rangeB);
+ if (startToStartComparison.hasException())
+ return nullptr;
+
+ auto endToEndComparison = rangeA->compareBoundaryPoints(Range::END_TO_END, *rangeB);
+ if (endToEndComparison.hasException())
+ return nullptr;
+
+ auto* start = startToStartComparison.releaseReturnValue() <= 0 ? rangeA : rangeB;
+ auto* end = endToEndComparison.releaseReturnValue() <= 0 ? rangeB : rangeA;
+
+ return Range::create(rangeA->ownerDocument(), &start->startContainer(), start->startOffset(), &end->endContainer(), end->endOffset());
+}
+
+static inline IntPoint computeEdgeCenter(const IntRect& box, SelectionHandlePosition handlePosition)
+{
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ return IntPoint(box.x() + box.width() / 2, box.y());
+ case SelectionHandlePosition::Right:
+ return IntPoint(box.maxX(), box.y() + box.height() / 2);
+ case SelectionHandlePosition::Bottom:
+ return IntPoint(box.x() + box.width() / 2, box.maxY());
+ case SelectionHandlePosition::Left:
+ return IntPoint(box.x(), box.y() + box.height() / 2);
+ }
+}
+
+Ref<Range> WebPage::expandedRangeFromHandle(Range& currentRange, SelectionHandlePosition handlePosition)
+{
+ IntRect currentBox = selectionBoxForRange(¤tRange);
+ IntPoint edgeCenter = computeEdgeCenter(currentBox, handlePosition);
+ static const float maxDistance = 1000;
+ const float multiple = powf(maxDistance, 1.0 / (maxHitTests - 1));
+ float distance = 1;
+
+ RefPtr<Range> bestRange;
+ IntRect bestRect;
+
+ while (distance < maxDistance) {
+ if (bestRange) {
+ if (distanceBetweenRectsForPosition(bestRect, currentBox, handlePosition) < distance) {
+ // Break early, we're unlikely to do any better.
+ break;
+ }
+ }
+
+ IntPoint testPoint = edgeCenter;
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ testPoint.move(0, -distance);
+ break;
+ case SelectionHandlePosition::Right:
+ testPoint.move(distance, 0);
+ break;
+ case SelectionHandlePosition::Bottom:
+ testPoint.move(0, distance);
+ break;
+ case SelectionHandlePosition::Left:
+ testPoint.move(-distance, 0);
+ break;
+ }
+
+ distance = ceilf(distance * multiple);
+
+ RefPtr<Range> newRange;
+ RefPtr<Range> rangeAtPosition = rangeForBlockAtPoint(testPoint);
+ if (!rangeAtPosition || ¤tRange.ownerDocument() != &rangeAtPosition->ownerDocument())
+ continue;
+
+ if (rangeAtPosition->contains(currentRange))
+ newRange = rangeAtPosition;
+ else if (currentRange.contains(*rangeAtPosition.get()))
+ newRange = ¤tRange;
+ else
+ newRange = unionDOMRanges(¤tRange, rangeAtPosition.get());
+
+ IntRect copyRect = selectionBoxForRange(newRange.get());
+
+ // Is it different and bigger than the current?
+ bool isBetterChoice = !(rectsEssentiallyTheSame(copyRect, currentBox, .05));
+ if (isBetterChoice) {
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ isBetterChoice = (copyRect.height() > currentBox.height());
+ break;
+ case SelectionHandlePosition::Right:
+ case SelectionHandlePosition::Left:
+ isBetterChoice = (copyRect.width() > currentBox.width());
+ break;
+ }
+
+ }
+
+ if (bestRange && isBetterChoice) {
+ // Furtherore, is it smaller than the best we've found so far?
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ isBetterChoice = (copyRect.height() < bestRect.height());
+ break;
+ case SelectionHandlePosition::Right:
+ case SelectionHandlePosition::Left:
+ isBetterChoice = (copyRect.width() < bestRect.width());
+ break;
+ }
+ }
+
+ if (isBetterChoice) {
+ bestRange = newRange;
+ bestRect = copyRect;
+ }
+ }
+
+ if (bestRange)
+ return bestRange.releaseNonNull();
+
+ return currentRange;
+}
+
+Ref<Range> WebPage::contractedRangeFromHandle(Range& currentRange, SelectionHandlePosition handlePosition, SelectionFlags& flags)
+{
+ // Shrinking with a base and extent will always give better results. If we only have a single element,
+ // see if we can break that down to a base and extent. Shrinking base and extent is comparatively straightforward.
+ // Shrinking down to another element is unlikely to move just one edge, but we can try that as a fallback.
+
+ IntRect currentBox = selectionBoxForRange(¤tRange);
+ IntPoint edgeCenter = computeEdgeCenter(currentBox, handlePosition);
+
+ float maxDistance;
+
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ maxDistance = currentBox.height();
+ break;
+ case SelectionHandlePosition::Right:
+ case SelectionHandlePosition::Left:
+ maxDistance = currentBox.width();
+ break;
+ }
+
+ const float multiple = powf(maxDistance - 1, 1.0 / (maxHitTests - 1));
+ float distance = 1;
+ RefPtr<Range> bestRange;
+ IntRect bestRect;
+
+ while (distance < maxDistance) {
+ if (bestRange) {
+ float shrankDistance;
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ shrankDistance = abs(currentBox.height() - bestRect.height());
+ break;
+ case SelectionHandlePosition::Right:
+ case SelectionHandlePosition::Left:
+ shrankDistance = abs(currentBox.width() - bestRect.width());
+ break;
+ }
+ if (shrankDistance > distance) {
+ // Certainly not going to do any better than that.
+ break;
+ }
+ }
+
+ IntPoint testPoint = edgeCenter;
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ testPoint.move(0, distance);
+ break;
+ case SelectionHandlePosition::Right:
+ testPoint.move(-distance, 0);
+ break;
+ case SelectionHandlePosition::Bottom:
+ testPoint.move(0, -distance);
+ break;
+ case SelectionHandlePosition::Left:
+ testPoint.move(distance, 0);
+ break;
+ }
+
+ distance *= multiple;
+
+ RefPtr<Range> newRange = rangeForBlockAtPoint(testPoint);
+ if (!newRange || &newRange->ownerDocument() != ¤tRange.ownerDocument())
+ continue;
+
+ if (handlePosition == SelectionHandlePosition::Top || handlePosition == SelectionHandlePosition::Left)
+ newRange = Range::create(newRange->startContainer().document(), newRange->endPosition(), currentRange.endPosition());
+ else
+ newRange = Range::create(newRange->startContainer().document(), currentRange.startPosition(), newRange->startPosition());
+
+ IntRect copyRect = selectionBoxForRange(newRange.get());
+ if (copyRect.isEmpty()) {
+ // If the new range is an empty rectangle, we try the block at the current point
+ // and see if that has a rectangle that is a better choice.
+ newRange = rangeForBlockAtPoint(testPoint);
+ copyRect = selectionBoxForRange(newRange.get());
+ }
+ bool isBetterChoice;
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ isBetterChoice = (copyRect.height() < currentBox.height());
+ if (copyRect.height() == currentBox.height())
+ isBetterChoice = canShrinkToTextSelection(*newRange.get());
+ break;
+ case SelectionHandlePosition::Left:
+ case SelectionHandlePosition::Right:
+ isBetterChoice = (copyRect.width() > bestRect.width());
+ break;
+ }
+
+ isBetterChoice = isBetterChoice && !areRangesEqual(newRange.get(), ¤tRange);
+ if (bestRange && isBetterChoice) {
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ case SelectionHandlePosition::Bottom:
+ isBetterChoice = (copyRect.height() > bestRect.height());
+ break;
+ case SelectionHandlePosition::Left:
+ case SelectionHandlePosition::Right:
+ isBetterChoice = (copyRect.width() > bestRect.width());
+ break;
+ }
+ }
+ if (isBetterChoice) {
+ bestRange = newRange;
+ bestRect = copyRect;
+ }
+
+ }
+
+ if (!bestRange)
+ bestRange = ¤tRange;
+
+ // If we can shrink down to text only, the only reason we wouldn't is that
+ // there are multiple sub-element blocks beneath us. If we didn't find
+ // multiple sub-element blocks, don't shrink to a sub-element block.
+
+ if (canShrinkToTextSelection(*bestRange.get()))
+ flags = None;
+
+ return bestRange.releaseNonNull();
+}
+
+void WebPage::computeExpandAndShrinkThresholdsForHandle(const IntPoint& point, SelectionHandlePosition handlePosition, float& growThreshold, float& shrinkThreshold)
+{
+ Frame& frame = m_page->focusController().focusedOrMainFrame();
+ RefPtr<Range> currentRange = m_currentBlockSelection ? m_currentBlockSelection.get() : frame.selection().selection().toNormalizedRange();
+
+ if (!currentRange)
+ return;
+
+ Ref<Range> expandedRange = expandedRangeFromHandle(*currentRange, handlePosition);
+ SelectionFlags flags;
+ RefPtr<Range> contractedRange = contractedRangeFromHandle(*currentRange, handlePosition, flags);
+
+ IntRect currentBounds = selectionBoxForRange(currentRange.get());
+ IntRect expandedBounds = selectionBoxForRange(expandedRange.ptr());
+ IntRect contractedBounds = selectionBoxForRange(contractedRange.get());
+
+ float current;
+ float expanded;
+ float contracted;
+ float maxThreshold;
+ float minThreshold;
+
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top: {
+ current = currentBounds.y();
+ expanded = expandedBounds.y();
+ contracted = contractedBounds.y();
+ maxThreshold = FLT_MIN;
+ minThreshold = FLT_MAX;
+ break;
+ }
+ case SelectionHandlePosition::Right: {
+ current = currentBounds.maxX();
+ expanded = expandedBounds.maxX();
+ contracted = contractedBounds.maxX();
+ maxThreshold = FLT_MAX;
+ minThreshold = FLT_MIN;
+ break;
+ }
+ case SelectionHandlePosition::Bottom: {
+ current = currentBounds.maxY();
+ expanded = expandedBounds.maxY();
+ contracted = contractedBounds.maxY();
+ maxThreshold = FLT_MAX;
+ minThreshold = FLT_MIN;
+ break;
+ }
+ case SelectionHandlePosition::Left: {
+ current = currentBounds.x();
+ expanded = expandedBounds.x();
+ contracted = contractedBounds.x();
+ maxThreshold = FLT_MIN;
+ minThreshold = FLT_MAX;
+ break;
+ }
+ }
+
+ static const float fractionToGrow = 0.3;
+
+ growThreshold = current + (expanded - current) * fractionToGrow;
+ shrinkThreshold = current + (contracted - current) * (1 - fractionToGrow);
+ if (areRangesEqual(expandedRange.ptr(), currentRange.get()))
+ growThreshold = maxThreshold;
+
+}
+#endif
+
void WebPage::selectWithGesture(const IntPoint& point, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, CallbackID callbackID)
{
auto& frame = m_page->focusController().focusedOrMainFrame();
@@ -1289,7 +1647,90 @@
return (base < extent) ? Range::create(*frame->document(), base, extent) : Range::create(*frame->document(), extent, base);
}
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
+RefPtr<Range> WebPage::rangeForBlockAtPoint(const IntPoint& point)
+{
+ HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint((point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::IgnoreClipping);
+
+ Node* currentNode = result.innerNode();
+ RefPtr<Range> range;
+
+ if (currentNode->isTextNode()) {
+ range = enclosingTextUnitOfGranularity(m_page->focusController().focusedOrMainFrame().visiblePositionForPoint(point), ParagraphGranularity, DirectionForward);
+ if (range && !range->collapsed())
+ return range;
+ }
+
+ if (!currentNode->isElementNode())
+ currentNode = currentNode->parentElement();
+
+ if (!currentNode)
+ return nullptr;
+
+ range = Range::create(currentNode->document());
+ range->selectNodeContents(*currentNode);
+ return range;
+}
+
+static inline bool shouldExpand(SelectionHandlePosition handlePosition, const IntRect& rect, const IntPoint& point)
+{
+ switch (handlePosition) {
+ case SelectionHandlePosition::Top:
+ return (point.y() < rect.y());
+ case SelectionHandlePosition::Left:
+ return (point.x() < rect.x());
+ case SelectionHandlePosition::Right:
+ return (point.x() > rect.maxX());
+ case SelectionHandlePosition::Bottom:
+ return (point.y() > rect.maxY());
+ }
+}
+
+RefPtr<WebCore::Range> WebPage::changeBlockSelection(const IntPoint& point, SelectionHandlePosition handlePosition, float& growThreshold, float& shrinkThreshold, SelectionFlags& flags)
+{
+ Frame& frame = m_page->focusController().focusedOrMainFrame();
+ RefPtr<Range> currentRange = m_currentBlockSelection ? m_currentBlockSelection.get() : frame.selection().selection().toNormalizedRange();
+ if (!currentRange)
+ return nullptr;
+ RefPtr<Range> newRange = shouldExpand(handlePosition, selectionBoxForRange(currentRange.get()), point) ? expandedRangeFromHandle(*currentRange, handlePosition) : contractedRangeFromHandle(*currentRange, handlePosition, flags);
+
+ if (newRange) {
+ m_currentBlockSelection = newRange;
+ frame.selection().setSelectedRange(newRange.get(), VP_DEFAULT_AFFINITY, true, UserTriggered);
+ }
+
+ computeExpandAndShrinkThresholdsForHandle(point, handlePosition, growThreshold, shrinkThreshold);
+ return newRange;
+}
+
+void WebPage::updateBlockSelectionWithTouch(const IntPoint& point, uint32_t touch, uint32_t handlePosition)
+{
+ Frame& frame = m_page->focusController().focusedOrMainFrame();
+ IntPoint adjustedPoint = frame.view()->rootViewToContents(point);
+
+ float growThreshold = 0;
+ float shrinkThreshold = 0;
+ SelectionFlags flags = None;
+
+ switch (static_cast<SelectionTouch>(touch)) {
+ case SelectionTouch::Started:
+ computeExpandAndShrinkThresholdsForHandle(adjustedPoint, static_cast<SelectionHandlePosition>(handlePosition), growThreshold, shrinkThreshold);
+ break;
+ case SelectionTouch::Ended:
+ break;
+ case SelectionTouch::Moved:
+ changeBlockSelection(adjustedPoint, static_cast<SelectionHandlePosition>(handlePosition), growThreshold, shrinkThreshold, flags);
+ break;
+ default:
+ return;
+ }
+
+ send(Messages::WebPageProxy::DidUpdateBlockSelectionWithTouch(touch, static_cast<uint32_t>(flags), growThreshold, shrinkThreshold));
+}
+#endif
+
void WebPage::clearSelection(){
m_currentBlockSelection = nullptr;
m_page->focusController().focusedOrMainFrame().selection().clear();