Skip to content

Commit

Permalink
Cherry-pick 69d07a6. rdar://problem/111793617
Browse files Browse the repository at this point in the history
    When selecting Live Text in Safari on iOS, the selection handles move away from the selection when zooming
    https://bugs.webkit.org/show_bug.cgi?id=259964
    rdar://111793617

    Reviewed by Wenson Hsieh.

    UIKit now scales the selection handles when zooming and updates their position accordingly.
    Since WebKit is also scaling them ourselves, this results in a position that's offset from the
    selection proportional to the zoom amount.

    Fix by no longer scaling the selection handles in WebKit.

    * LayoutTests/resources/ui-helper.js:
    (window.UIHelper.getSelectionEndGrabberViewShapePathDescription.return.new.Promise.):
    (window.UIHelper.getSelectionEndGrabberViewShapePathDescription.return.new.Promise):
    (window.UIHelper.getSelectionEndGrabberViewShapePathDescription):
    * Source/WebKit/UIProcess/ios/WKTextSelectionRect.mm:
    (-[WKTextSelectionRect _customHandleInfo]):
    * Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
    * Tools/TestRunnerShared/UIScriptContext/UIScriptController.h:
    (WTR::UIScriptController::selectionEndGrabberViewShapePathDescription const):
    * Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h:
    * Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm:
    (WTR::UIScriptControllerIOS::selectionEndGrabberViewShapePathDescription const):

    Canonical link: https://commits.webkit.org/266753@main

Canonical link: https://commits.webkit.org/265870.322@safari-7616.1.27.10-branch
  • Loading branch information
rr-codes authored and Dan Robson committed Aug 10, 2023
1 parent 28e6324 commit fe9fffd
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 0 deletions.
16 changes: 16 additions & 0 deletions LayoutTests/resources/ui-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,22 @@ window.UIHelper = class UIHelper {
});
}

static getSelectionEndGrabberViewShapePathDescription()
{
if (!this.isWebKit2() || !this.isIOSFamily())
return Promise.resolve();

return new Promise(resolve => {
testRunner.runUIScript(`(function() {
uiController.doAfterNextStablePresentationUpdate(function() {
uiController.uiScriptComplete(JSON.stringify(uiController.selectionEndGrabberViewShapePathDescription));
});
})()`, jsonString => {
resolve(JSON.parse(jsonString));
});
});
}

static midPointOfRect(rect) {
return { x: rect.left + (rect.width / 2), y: rect.top + (rect.height / 2) };
}
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/ios/WKTextSelectionRect.mm
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ - (WKTextSelectionRectCustomHandleInfo *)_customHandleInfo
return nil;

auto scaledQuad = _selectionGeometry.quad();
#if !HAVE(REDESIGNED_TEXT_CURSOR)
scaledQuad.scale(_scaleFactor);
#endif
return adoptNS([[WKTextSelectionRectCustomHandleInfo alloc] initWithFloatQuad:scaledQuad isHorizontal:_selectionGeometry.isHorizontal()]).autorelease();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ interface UIScriptController {
readonly attribute object contentVisibleRect;
readonly attribute object selectionStartGrabberViewRect;
readonly attribute object selectionEndGrabberViewRect;
readonly attribute object selectionEndGrabberViewShapePathDescription;
readonly attribute object selectionCaretViewRect;
readonly attribute object selectionCaretViewRectInGlobalCoordinates;
readonly attribute object selectionRangeViewRects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ class UIScriptController : public JSWrappable {
virtual JSObjectRef textSelectionCaretRect() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionStartGrabberViewRect() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionEndGrabberViewRect() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionEndGrabberViewShapePathDescription() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionCaretViewRect() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionCaretViewRectInGlobalCoordinates() const { notImplemented(); return nullptr; }
virtual JSObjectRef selectionRangeViewRects() const { notImplemented(); return nullptr; }
Expand Down
1 change: 1 addition & 0 deletions Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class UIScriptControllerIOS final : public UIScriptControllerCocoa {
JSObjectRef contentVisibleRect() const override;
JSObjectRef selectionStartGrabberViewRect() const override;
JSObjectRef selectionEndGrabberViewRect() const override;
JSObjectRef selectionEndGrabberViewShapePathDescription() const override;
JSObjectRef selectionCaretViewRect() const override;
JSObjectRef selectionCaretViewRectInGlobalCoordinates() const override;
JSObjectRef selectionCaretViewRect(id<UICoordinateSpace>) const;
Expand Down
55 changes: 55 additions & 0 deletions Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,46 @@ static BOOL returnNo()
};
}

static RetainPtr<NSDictionary> toNSDictionary(CGPathRef path)
{
auto pathElementTypeToString = [](CGPathElementType type) {
switch (type) {
case kCGPathElementMoveToPoint:
return @"MoveToPoint";

case kCGPathElementAddLineToPoint:
return @"AddLineToPoint";

case kCGPathElementAddQuadCurveToPoint:
return @"AddQuadCurveToPoint";

case kCGPathElementAddCurveToPoint:
return @"AddCurveToPoint";

case kCGPathElementCloseSubpath:
return @"CloseSubpath";

default:
return @"Unknown";
}
};

auto attributes = adoptNS([[NSMutableDictionary alloc] init]);

CGPathApplyWithBlock(path, ^(const CGPathElement *element) {
if (!element)
return;

NSString *typeString = pathElementTypeToString(element->type);
[attributes setObject:@{
@"x": @(element->points->x),
@"y": @(element->points->y),
} forKey:typeString];
});

return attributes;
}

static Vector<String> parseModifierArray(JSContextRef context, JSValueRef arrayValue)
{
if (!arrayValue)
Expand Down Expand Up @@ -882,6 +922,21 @@ static void clipSelectionViewRectToContentView(CGRect& rect, UIView *contentView
return JSValueToObject(jsContext, [JSValue valueWithObject:toNSDictionary(frameInContentViewCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::selectionEndGrabberViewShapePathDescription() const
{
UIView *handleView = nil;

#if HAVE(UI_TEXT_SELECTION_DISPLAY_INTERACTION)
if (auto view = textSelectionDisplayInteraction().handleViews.lastObject; !isHiddenOrHasHiddenAncestor(view))
handleView = view;
#else
UIView *contentView = platformContentView();
handleView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView.endGrabber"];
#endif

return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary((CGPathRef)[handleView valueForKeyPath:@"stemView.shapeLayer.path"]).get() inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
}

JSObjectRef UIScriptControllerIOS::selectionCaretViewRect(id<UICoordinateSpace> coordinateSpace) const
{
UIView *contentView = platformContentView();
Expand Down

0 comments on commit fe9fffd

Please sign in to comment.