WebKit Bugzilla
Attachment 346569 Details for
Bug 188322
: [iOS] Caret disappears after resigning and becoming first responder if active focus state is retained
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Fix macOS builds
bug-188322-20180803175328.patch (text/plain), 27.10 KB, created by
Wenson Hsieh
on 2018-08-03 17:53:29 PDT
(
hide
)
Description:
Fix macOS builds
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2018-08-03 17:53:29 PDT
Size:
27.10 KB
patch
obsolete
>Subversion Revision: 234566 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 1c549d38186b03b469f851c541121707f26c973b..f113b9c58d7901f44c803b73067945c14348a0a5 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,46 @@ >+2018-08-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Caret disappears after resigning and becoming first responder if active focus state is retained >+ https://bugs.webkit.org/show_bug.cgi?id=188322 >+ <rdar://problem/42455270> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Prior to r230745, when a user selects a word in non-editable web content without a prior selection, we would >+ always try to activate the text interaction assistant, creating a selection view (a UITextSelectionView). After >+ the long press is recognized, this text selection view is configured for "highlight mode", which is a special >+ mode for presenting selection UI where the grabber handles at the start and end of the selection are suppressed. >+ UIKit then prepares to show the selection by asking WKContentView for the number of selection rects; if this >+ number is zero, the UITextSelectionView is removed from the superview, and state that keeps track of whether the >+ selection view is in "highlight mode" is reset. >+ >+ In the case where there's no prior selection, our cached EditorState in the UI process will not be up to date >+ yet when the gesture is recognized. This means that when UIKit asks us for the number of selection rects, we'll >+ return 0, which causes any state tracking "highlight mode" for the selection to be reset, subsequently resulting >+ in selection handles showing up before the user has ended the initial loupe gesture. >+ >+ r230745 addressed this bug by removing logic to activate the text selection when becoming first responder, >+ instead deferring until the next -_selectionChanged call with post-layout editor state data to activate the >+ selection. While this does ensure that selection handles don't erroneously appear, it also means that clients >+ that call -becomeFirstResponder to show selection UI and the keyboard in a web view while an element is already >+ focused will not have an active selection assistant (i.e. the selection view will still be hidden). One way this >+ happens is when Safari uses `-_retainActiveFocusedState` in combination with `-resignFirstResponder` and >+ `-becomeFirstResponder` to temporarily switch focus away from the web view when the URL bar is tapped. >+ >+ To fix both the inactive selection after `-becomeFirstResponder` as well as the selection handles showing up >+ when performing a loupe gesture, we simply make the check in `-becomeFirstResponderForWebView` more nuanced. >+ Instead of always activating the selection or never activating the selection, only activate the selection if the >+ current editor state has information about a selection to avoid causing the selection view to be immediately >+ removed and "highlight mode" to be reset when selecting a word via loupe gesture for the first time. >+ >+ Tests: KeyboardInputTests.CaretSelectionRectAfterRestoringFirstResponder >+ KeyboardInputTests.RangedSelectionRectAfterRestoringFirstResponder >+ editing/selection/ios/selection-handles-after-touch-end.html >+ >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView becomeFirstResponderForWebView]): >+ (-[WKContentView canShowNonEmptySelectionView]): >+ > 2018-08-03 Alex Christensen <achristensen@webkit.org> > > Fix spelling of "overridden" >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >index 09e53ef759e44d6ca9329df85e6ff615bc6a58fe..8cee7b7f699c0f45f47a27064d9569e20f3cc2ad 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -974,6 +974,9 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI > didBecomeFirstResponder = [super becomeFirstResponder]; > } > >+ if (didBecomeFirstResponder && [self canShowNonEmptySelectionView]) >+ [_textSelectionAssistant activateSelection]; >+ > return didBecomeFirstResponder; > } > >@@ -1676,6 +1679,15 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI > }]; > } > >+- (BOOL)canShowNonEmptySelectionView >+{ >+ if (self.suppressAssistantSelectionView) >+ return NO; >+ >+ auto& state = _page->editorState(); >+ return !state.isMissingPostLayoutData && !state.selectionIsNone; >+} >+ > - (BOOL)hasSelectablePositionAtPoint:(CGPoint)point > { > if (!_webView.configuration._textInteractionGesturesEnabled) >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 3e03d597471165c5f762faa30fa6ee0ba93fee90..a69fc4d4f2767b6dba0afdd865415844ddb5fcb4 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,41 @@ >+2018-08-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Caret disappears after resigning and becoming first responder if active focus state is retained >+ https://bugs.webkit.org/show_bug.cgi?id=188322 >+ <rdar://problem/42455270> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adds plumbing in UIScriptController to grab the start and end selection handle rects for use in the new layout >+ test. Also adds new API tests to verify that when a web view resigns first responder, both caret and range >+ selection views are hidden, and when first responder status is restored, both caret and range selection views >+ are made visible again. >+ >+ * DumpRenderTree/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptController::selectionStartGrabberViewRect const): >+ (WTR::UIScriptController::selectionEndGrabberViewRect const): >+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: >+ * TestRunnerShared/UIScriptContext/UIScriptController.cpp: >+ (WTR::UIScriptController::selectionStartGrabberViewRect const): >+ (WTR::UIScriptController::selectionEndGrabberViewRect const): >+ * TestRunnerShared/UIScriptContext/UIScriptController.h: >+ * TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm: >+ (-[TestWKWebView waitForCaretViewFrameToBecome:]): >+ (-[TestWKWebView waitForSelectionViewRectsToBecome:]): >+ (webViewWithAutofocusedInput): >+ >+ Pull out some common logic for creating a web view that allows programmatic focus to present the keyboard, and >+ immediately loading a web page with an autofocusing text field. >+ >+ (TestWebKitAPI::TEST): >+ * TestWebKitAPI/cocoa/TestWKWebView.h: >+ * TestWebKitAPI/cocoa/TestWKWebView.mm: >+ (-[TestWKWebView caretViewRectInContentCoordinates]): >+ (-[TestWKWebView selectionViewRectsInContentCoordinates]): >+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptController::selectionStartGrabberViewRect const): >+ (WTR::UIScriptController::selectionEndGrabberViewRect const): >+ > 2018-08-03 David Fenton <david_fenton@apple.com> > > Unreviewed, rolling out r234517. >diff --git a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >index b94ca8d831e540ebd4ba441569c74097c15b1de5..a446ff5552a0387783c031747cee04ed8ca03a1a 100644 >--- a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >+++ b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >@@ -366,6 +366,16 @@ void UIScriptController::completeBackSwipe(JSValueRef callback) > { > } > >+JSObjectRef UIScriptController::selectionStartGrabberViewRect() const >+{ >+ return nullptr; >+} >+ >+JSObjectRef UIScriptController::selectionEndGrabberViewRect() const >+{ >+ return nullptr; >+} >+ > } > > #endif // PLATFORM(IOS) >diff --git a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >index 809e475bc45f89f4af4b21cf02b097710a527663..8deb4eb10b2262c05a64c3d3a8c96aa6244c09fa 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >+++ b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >@@ -234,6 +234,9 @@ interface UIScriptController { > > readonly attribute object selectionRangeViewRects; // An array of objects with 'left', 'top', 'width', and 'height' properties. > readonly attribute object textSelectionCaretRect; // An object with 'left', 'top', 'width', 'height' properties. >+ readonly attribute object selectionStartGrabberViewRect; >+ readonly attribute object selectionEndGrabberViewRect; >+ > readonly attribute object inputViewBounds; > > void replaceTextAtRange(DOMString text, long location, long length); >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >index 42c12cef1b7bbe24cf72605d30727b7d70cfef9c..e94f0af72bbb345af6693357f30811b7f897a282 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >@@ -384,6 +384,16 @@ JSObjectRef UIScriptController::textSelectionCaretRect() const > return nullptr; > } > >+JSObjectRef UIScriptController::selectionStartGrabberViewRect() const >+{ >+ return nullptr; >+} >+ >+JSObjectRef UIScriptController::selectionEndGrabberViewRect() const >+{ >+ return nullptr; >+} >+ > JSObjectRef UIScriptController::inputViewBounds() const > { > return nullptr; >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >index b2e1adeb839ffd3b2662a083728aa23f1012064c..95d7d54985645ab7b3632ee809b2c0f64bb26b06 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >@@ -156,6 +156,8 @@ public: > > JSObjectRef selectionRangeViewRects() const; > JSObjectRef textSelectionCaretRect() const; >+ JSObjectRef selectionStartGrabberViewRect() const; >+ JSObjectRef selectionEndGrabberViewRect() const; > JSObjectRef inputViewBounds() const; > > void replaceTextAtRange(JSStringRef, int location, int length); >diff --git a/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm b/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm >index 209db0881aee62a38e76cf4abd3f8d2108d49db5..39bdba4c96d52e20fa7add3d57353257617494fc 100644 >--- a/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm >+++ b/Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm >@@ -34,9 +34,54 @@ > #import <WebKit/WKWebViewPrivate.h> > #import <WebKitLegacy/WebEvent.h> > >-namespace TestWebKitAPI { >+@implementation TestWKWebView (KeyboardInputTests) > >-TEST(KeyboardInputTests, CanHandleKeyEventInCompletionHandler) >+- (void)waitForCaretViewFrameToBecome:(CGRect)frame >+{ >+ BOOL hasEmittedWarning = NO; >+ NSTimeInterval secondsToWaitUntilWarning = 2; >+ NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]; >+ while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) { >+ CGRect currentFrame = self.caretViewRectInContentCoordinates; >+ if (CGRectEqualToRect(currentFrame, frame)) >+ break; >+ >+ if (hasEmittedWarning || startTime + secondsToWaitUntilWarning >= [NSDate timeIntervalSinceReferenceDate]) >+ continue; >+ >+ NSLog(@"Expected a caret rect of %@, but still observed %@", NSStringFromCGRect(frame), NSStringFromCGRect(currentFrame)); >+ hasEmittedWarning = YES; >+ } >+} >+ >+- (void)waitForSelectionViewRectsToBecome:(NSArray<NSValue *> *)selectionRects >+{ >+ BOOL hasEmittedWarning = NO; >+ NSTimeInterval secondsToWaitUntilWarning = 2; >+ NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]; >+ while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) { >+ NSArray<NSValue *> *currentRects = self.selectionViewRectsInContentCoordinates; >+ BOOL selectionRectsMatch = YES; >+ if (currentRects.count == selectionRects.count) { >+ for (NSUInteger index = 0; index < selectionRects.count; ++index) >+ selectionRectsMatch |= [selectionRects[index] isEqualToValue:currentRects[index]]; >+ } else >+ selectionRectsMatch = NO; >+ >+ if (selectionRectsMatch) >+ break; >+ >+ if (hasEmittedWarning || startTime + secondsToWaitUntilWarning >= [NSDate timeIntervalSinceReferenceDate]) >+ continue; >+ >+ NSLog(@"Expected a selection rects of %@, but still observed %@", selectionRects, currentRects); >+ hasEmittedWarning = YES; >+ } >+} >+ >+@end >+ >+static RetainPtr<TestWKWebView> webViewWithAutofocusedInput() > { > auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); > auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); >@@ -47,10 +92,19 @@ TEST(KeyboardInputTests, CanHandleKeyEventInCompletionHandler) > return _WKFocusStartsInputSessionPolicyAllow; > }]; > [webView _setInputDelegate:inputDelegate.get()]; >- [webView synchronouslyLoadHTMLString:@"<input autofocus>"]; >+ [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><input autofocus>"]; > > TestWebKitAPI::Util::run(&doneWaiting); > doneWaiting = false; >+ return webView; >+} >+ >+namespace TestWebKitAPI { >+ >+TEST(KeyboardInputTests, CanHandleKeyEventInCompletionHandler) >+{ >+ auto webView = webViewWithAutofocusedInput(); >+ bool doneWaiting = false; > > id <UITextInputPrivate> contentView = (id <UITextInputPrivate>)[webView firstResponder]; > auto firstWebEvent = adoptNS([[WebEvent alloc] initWithKeyEventType:WebEventKeyDown timeStamp:CFAbsoluteTimeGetCurrent() characters:@"a" charactersIgnoringModifiers:@"a" modifiers:0 isRepeating:NO withFlags:0 withInputManagerHint:nil keyCode:0 isTabKey:NO]); >@@ -68,6 +122,41 @@ TEST(KeyboardInputTests, CanHandleKeyEventInCompletionHandler) > EXPECT_WK_STREQ("a", [webView stringByEvaluatingJavaScript:@"document.querySelector('input').value"]); > } > >+TEST(KeyboardInputTests, CaretSelectionRectAfterRestoringFirstResponder) >+{ >+ auto expectedCaretRect = CGRectMake(16, 13, 3, 15); >+ auto webView = webViewWithAutofocusedInput(); >+ EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]); >+ [webView waitForCaretViewFrameToBecome:expectedCaretRect]; >+ >+ dispatch_block_t restoreActiveFocusState = [webView _retainActiveFocusedState]; >+ [webView resignFirstResponder]; >+ restoreActiveFocusState(); >+ [webView waitForCaretViewFrameToBecome:CGRectZero]; >+ >+ [webView becomeFirstResponder]; >+ [webView waitForCaretViewFrameToBecome:expectedCaretRect]; >+} >+ >+TEST(KeyboardInputTests, RangedSelectionRectAfterRestoringFirstResponder) >+{ >+ NSArray *expectedSelectionRects = @[ [NSValue valueWithCGRect:CGRectMake(16, 13, 24, 15)] ]; >+ >+ auto webView = webViewWithAutofocusedInput(); >+ [[webView textInputContentView] insertText:@"hello"]; >+ [webView selectAll:nil]; >+ EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]); >+ [webView waitForSelectionViewRectsToBecome:expectedSelectionRects]; >+ >+ dispatch_block_t restoreActiveFocusState = [webView _retainActiveFocusedState]; >+ [webView resignFirstResponder]; >+ restoreActiveFocusState(); >+ [webView waitForSelectionViewRectsToBecome:@[ ]]; >+ >+ [webView becomeFirstResponder]; >+ [webView waitForSelectionViewRectsToBecome:expectedSelectionRects]; >+} >+ > } // namespace TestWebKitAPI > > #endif // WK_API_ENABLED && PLATFORM(IOS) >diff --git a/Tools/TestWebKitAPI/cocoa/TestWKWebView.h b/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >index a5d651a7df67722a691dba07c393eaa2acc14463..cf98daa234c09857a65e56a2b28e2ee090a7e947 100644 >--- a/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >+++ b/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >@@ -63,6 +63,8 @@ > @interface TestWKWebView (IOSOnly) > @property (nonatomic, readonly) UIView <UITextInput> *textInputContentView; > @property (nonatomic, readonly) RetainPtr<NSArray> selectionRectsAfterPresentationUpdate; >+@property (nonatomic, readonly) CGRect caretViewRectInContentCoordinates; >+@property (nonatomic, readonly) NSArray<NSValue *> *selectionViewRectsInContentCoordinates; > - (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position; > @end > #endif >diff --git a/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm b/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >index c545a44c3771bc9434e41f31913266b9cae140e3..3740d582f3f51eb7dd70164bdeb3e711be57f805 100644 >--- a/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >+++ b/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >@@ -337,6 +337,22 @@ NSEventMask __simulated_forceClickAssociatedEventsMask(id self, SEL _cmd) > return selectionRects; > } > >+- (CGRect)caretViewRectInContentCoordinates >+{ >+ UIView *selectionView = [self.textInputContentView valueForKeyPath:@"interactionAssistant.selectionView"]; >+ CGRect caretFrame = [[selectionView valueForKeyPath:@"caretView.frame"] CGRectValue]; >+ return [selectionView convertRect:caretFrame toView:self.textInputContentView]; >+} >+ >+- (NSArray<NSValue *> *)selectionViewRectsInContentCoordinates >+{ >+ NSMutableArray *selectionRects = [NSMutableArray array]; >+ NSArray<UITextSelectionRect *> *rects = [self.textInputContentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView.rects"]; >+ for (UITextSelectionRect *rect in rects) >+ [selectionRects addObject:[NSValue valueWithCGRect:rect.rect]]; >+ return selectionRects; >+} >+ > - (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position > { > __block RetainPtr<_WKActivatedElementInfo> info; >diff --git a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >index bd42d3aed4ed5a00ebd99d637342004126eed97c..c6ebfca52151906f6420dc760d051a80fea735af 100644 >--- a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >+++ b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >@@ -579,6 +579,26 @@ JSObjectRef UIScriptController::textSelectionCaretRect() const > return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(TestController::singleton().mainWebView()->platformView()._uiTextCaretRect) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr); > } > >+JSObjectRef UIScriptController::selectionStartGrabberViewRect() const >+{ >+ WKWebView *webView = TestController::singleton().mainWebView()->platformView(); >+ UIView *contentView = [webView valueForKeyPath:@"_currentContentView"]; >+ UIView *selectionRangeView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView"]; >+ auto frameInContentCoordinates = [selectionRangeView convertRect:[[selectionRangeView valueForKeyPath:@"startGrabber"] frame] toView:contentView]; >+ auto jsContext = m_context->jsContext(); >+ return JSValueToObject(jsContext, [JSValue valueWithObject:toNSDictionary(frameInContentCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr); >+} >+ >+JSObjectRef UIScriptController::selectionEndGrabberViewRect() const >+{ >+ WKWebView *webView = TestController::singleton().mainWebView()->platformView(); >+ UIView *contentView = [webView valueForKeyPath:@"_currentContentView"]; >+ UIView *selectionRangeView = [contentView valueForKeyPath:@"interactionAssistant.selectionView.rangeView"]; >+ auto frameInContentCoordinates = [selectionRangeView convertRect:[[selectionRangeView valueForKeyPath:@"endGrabber"] frame] toView:contentView]; >+ auto jsContext = m_context->jsContext(); >+ return JSValueToObject(jsContext, [JSValue valueWithObject:toNSDictionary(frameInContentCoordinates) inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr); >+} >+ > JSObjectRef UIScriptController::inputViewBounds() const > { > return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(TestController::singleton().mainWebView()->platformView()._inputViewBounds) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 23404cef68bd856ac0d28794d0392fbf0ad98166..fbdd6661baee539aa957cfb99c9e8076c497d4c3 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,27 @@ >+2018-08-03 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Caret disappears after resigning and becoming first responder if active focus state is retained >+ https://bugs.webkit.org/show_bug.cgi?id=188322 >+ <rdar://problem/42455270> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adds a new layout test to verify that (1) selection handles are not shown when selecting a word by long >+ pressing prior to ending the touch, and (2) selection handles are shown after ending the touch. >+ >+ * editing/selection/ios/selection-handles-after-touch-end-expected.txt: Added. >+ * editing/selection/ios/selection-handles-after-touch-end.html: Added. >+ * resources/ui-helper.js: >+ >+ Introduces new hooks in UIHelper to grab the frames of the start and end selection handle views. >+ >+ (window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise.): >+ (window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise): >+ (window.UIHelper.getSelectionStartGrabberViewRect): >+ (window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise.): >+ (window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise): >+ (window.UIHelper.getSelectionEndGrabberViewRect): >+ > 2018-08-03 Justin Fan <justin_fan@apple.com> > > WebGL 2 conformance: vertex_arrays/vertex_array_object.html >diff --git a/LayoutTests/editing/selection/ios/selection-handles-after-touch-end-expected.txt b/LayoutTests/editing/selection/ios/selection-handles-after-touch-end-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..78620a5c154383adc339f2f3a82c77e05b6b170b >--- /dev/null >+++ b/LayoutTests/editing/selection/ios/selection-handles-after-touch-end-expected.txt >@@ -0,0 +1,11 @@ >+WK >+ >+Selection rects before touchend: >+{ left = 0, top = 0, width = 250, height = 170 } >+Selection start handle before touchend: { left = 0, top = 0, width = 0, height = 0 } >+Selection end handle before touchend: { left = 0, top = 0, width = 0, height = 0 } >+ >+Selection rects after touchend: >+{ left = 0, top = 0, width = 250, height = 170 } >+Selection start handle after touchend: { left = 0, top = 0, width = 2, height = 170 } >+Selection end handle after touchend: { left = 249, top = 0, width = 2, height = 170 } >diff --git a/LayoutTests/editing/selection/ios/selection-handles-after-touch-end.html b/LayoutTests/editing/selection/ios/selection-handles-after-touch-end.html >new file mode 100644 >index 0000000000000000000000000000000000000000..59b0dbb8c9c16426ca6303826d0aeefe5cca483f >--- /dev/null >+++ b/LayoutTests/editing/selection/ios/selection-handles-after-touch-end.html >@@ -0,0 +1,75 @@ >+<html> >+<head> >+<script src="../../../resources/ui-helper.js"></script> >+<meta name=viewport content="width=device-width"> >+<style> >+ body, html { >+ width: 100%; >+ height: 100%; >+ margin: 0; >+ } >+ >+ #target { >+ font-size: 150px; >+ } >+</style> >+</head> >+ >+<body> >+<p id="target">WK</p> >+<pre id="output"></pre> >+<script> >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+} >+ >+function appendOutput(s) >+{ >+ const paragraph = document.createElement("div"); >+ paragraph.textContent = s; >+ output.appendChild(paragraph); >+} >+ >+function toString(rect) >+{ >+ return `{ left = ${Math.round(rect.left)}, top = ${Math.round(rect.top)}, width = ${Math.round(rect.width)}, height = ${Math.round(rect.height)} }`; >+} >+ >+function checkDone() { >+ if (!window.doneCount) >+ doneCount = 0; >+ if (++doneCount == 3) >+ testRunner.notifyDone(); >+} >+ >+document.addEventListener("selectionchange", async () => { >+ if (!getSelection().rangeCount || getSelection().getRangeAt(0).collapsed) >+ return; >+ >+ appendOutput("Selection rects before touchend:"); >+ (await UIHelper.getUISelectionRects()).map(toString).map(appendOutput); >+ appendOutput(`Selection start handle before touchend: ${toString(await UIHelper.getSelectionStartGrabberViewRect())}`); >+ appendOutput(`Selection end handle before touchend: ${toString(await UIHelper.getSelectionEndGrabberViewRect())}`); >+ appendOutput("\n"); >+ testRunner.runUIScript("uiController.liftUpAtPoint(100, 75, 1, () => uiController.uiScriptComplete(''));", checkDone); >+}); >+ >+document.addEventListener("touchend", async () => { >+ appendOutput("Selection rects after touchend:"); >+ (await UIHelper.getUISelectionRects()).map(toString).map(appendOutput); >+ appendOutput(`Selection start handle after touchend: ${toString(await UIHelper.getSelectionStartGrabberViewRect())}`); >+ appendOutput(`Selection end handle after touchend: ${toString(await UIHelper.getSelectionEndGrabberViewRect())}`); >+ checkDone(); >+}); >+ >+if (window.testRunner && testRunner.runUIScript) >+ testRunner.runUIScript("uiController.touchDownAtPoint(100, 75, 1, () => uiController.uiScriptComplete(''));", checkDone); >+else { >+ appendOutput(`This test verifies that selection handles are not present when selecting a word via long press, >+ before ending the long press. To manually test, long press the word "WK" until a selection highlight is shown, >+ and verify that there are no selection handles. Upon release, selection handles should appear.`); >+} >+</script> >+</body> >+</html> >\ No newline at end of file >diff --git a/LayoutTests/resources/ui-helper.js b/LayoutTests/resources/ui-helper.js >index 40ad82d63defdd65b3bd734e65408281986c6db4..9d0c6146ab447d212a89338ae70f665ab57d83b7 100644 >--- a/LayoutTests/resources/ui-helper.js >+++ b/LayoutTests/resources/ui-helper.js >@@ -153,6 +153,38 @@ window.UIHelper = class UIHelper { > }); > } > >+ static getSelectionStartGrabberViewRect() >+ { >+ if (!this.isWebKit2() || !this.isIOS()) >+ return Promise.resolve(); >+ >+ return new Promise(resolve => { >+ testRunner.runUIScript(`(function() { >+ uiController.doAfterNextStablePresentationUpdate(function() { >+ uiController.uiScriptComplete(JSON.stringify(uiController.selectionStartGrabberViewRect)); >+ }); >+ })()`, jsonString => { >+ resolve(JSON.parse(jsonString)); >+ }); >+ }); >+ } >+ >+ static getSelectionEndGrabberViewRect() >+ { >+ if (!this.isWebKit2() || !this.isIOS()) >+ return Promise.resolve(); >+ >+ return new Promise(resolve => { >+ testRunner.runUIScript(`(function() { >+ uiController.doAfterNextStablePresentationUpdate(function() { >+ uiController.uiScriptComplete(JSON.stringify(uiController.selectionEndGrabberViewRect)); >+ }); >+ })()`, jsonString => { >+ resolve(JSON.parse(jsonString)); >+ }); >+ }); >+ } >+ > static replaceTextAtRange(text, location, length) { > return new Promise(resolve => { > testRunner.runUIScript(`(() => {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188322
:
346566
|
346569
|
346595
|
346596
|
346597
|
346635
|
346682