Changeset 238188 in webkit
- Timestamp:
- Nov 14, 2018 11:27:29 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r238186 r238188 1 2018-11-14 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] A few drag and drop tests are crashing after r238146 4 https://bugs.webkit.org/show_bug.cgi?id=191617 5 6 Reviewed by Dean Jackson. 7 8 The notion of temporarily suppressing the selection assistant was introduced during iOS drag and drop 9 development as a way of allowing both the selection view and dropped content snapshot to fade in simultaneously 10 during a drop in an editable element. r238146 piggy-backs on this mechanism by changing selection suppression 11 state when an element is focused, when the selection changes, and when an element is blurred, depending on 12 whether the currently focused element is transparent. 13 14 However, in the case where the selection assistant is suppressed due to a running drop animation, if focus moves 15 to an element that is not fully transparent, we end up prematurely unsuppressing the text selection assistant. 16 This subsequently causes selection UI to immediately show up after a drop instead of animating in alongside a 17 snapshot of the inserted document fragment, if the drop moved focus to an editable element. 18 19 A number of drag and drop tests on iOS exercised this codepath by dragging content into editable fields and/or 20 moving content between editable elements in a web view. These tests began to crash due to selection views and 21 the accompanying callout bar appearing earlier than usual, which triggers an unrelated UIKit assertion in 22 <https://webkit.org/b/190401>. 23 24 This patch fixes the failing tests by refactoring our selection assistant suppression code. Instead of 25 maintaining a single `BOOL` flag indicating whether the selection is suppressed, we use an `OptionSet` of 26 `SuppressSelectionAssistantReason`s, which (at the moment) only include (1) a running drop animation, and (2) 27 focusing a transparent element. The text selection assistant is considered suppressed when either of the reasons 28 apply. This allows us to correctly handle a drop animation that occurs simultaneously as an element is focused 29 without unsuppressing the selection assistant early, and also allows us to handle selection assistant 30 suppression in more nuanced ways, depending on the suppression reason. 31 32 * UIProcess/ios/WKContentViewInteraction.h: 33 * UIProcess/ios/WKContentViewInteraction.mm: 34 (-[WKContentView cleanupInteraction]): 35 (-[WKContentView _displayFormNodeInputView]): 36 37 Only prevent zooming to the focused element during drop if we're suppressing the selection assistant due to 38 focusing a transparent element. In the case of a drop, we still want to allow scrolling and zooming. 39 40 (-[WKContentView canShowNonEmptySelectionView]): 41 (-[WKContentView hasSelectablePositionAtPoint:]): 42 (-[WKContentView pointIsNearMarkedText:]): 43 (-[WKContentView textInteractionGesture:shouldBeginAtPoint:]): 44 (-[WKContentView _startAssistingKeyboard]): 45 (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]): 46 (-[WKContentView _stopAssistingNode]): 47 (-[WKContentView _updateChangedSelection:]): 48 (-[WKContentView _shouldSuppressSelectionCommands]): 49 (-[WKContentView _beginSuppressingSelectionAssistantForReason:]): 50 (-[WKContentView _stopSuppressingSelectionAssistantForReason:]): 51 52 Add helper methods for adding or removing selection assistant suppression reasons. When the last selection 53 assistant suppression reason is removed, we activate the selection assistant, and conversely, when the first 54 suppression reason is added, we deactivate the selection assistant. 55 56 (-[WKContentView _didConcludeEditDataInteraction:]): 57 (-[WKContentView _didPerformDragOperation:]): 58 (-[WKContentView dropInteraction:performDrop:]): 59 (-[WKContentView suppressAssistantSelectionView]): Deleted. 60 (-[WKContentView setSuppressAssistantSelectionView:]): Deleted. 61 1 62 2018-11-14 Wenson Hsieh <wenson_hsieh@apple.com> 2 63 -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
r238186 r238188 51 51 #import <wtf/BlockPtr.h> 52 52 #import <wtf/Forward.h> 53 #import <wtf/OptionSet.h> 53 54 #import <wtf/Vector.h> 54 55 #import <wtf/WeakObjCPtr.h> … … 157 158 namespace WebKit { 158 159 160 enum SuppressSelectionAssistantReason : uint8_t { 161 FocusedElementIsTransparent = 1 << 0, 162 DropAnimationIsRunning = 1 << 1 163 }; 164 159 165 struct WKSelectionDrawingInfo { 160 166 enum class SelectionType { None, Plugin, Range }; … … 210 216 211 217 RetainPtr<UIWKTextInteractionAssistant> _textSelectionAssistant; 212 BOOL _suppressAssistantSelectionView;218 OptionSet<WebKit::SuppressSelectionAssistantReason> _suppressSelectionAssistantReasons; 213 219 214 220 RetainPtr<UITextInputTraits> _traits; … … 338 344 @property (nonatomic, readonly) const WebKit::AssistedNodeInformation& assistedNodeInformation; 339 345 @property (nonatomic, readonly) UIWebFormAccessory *formAccessoryView; 340 @property (nonatomic) BOOL suppressAssistantSelectionView;341 346 @property (nonatomic, readonly) UITextInputAssistantItem *inputAssistantItemForWebView; 342 347 -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r238186 r238188 823 823 824 824 _hasSetUpInteractions = NO; 825 _suppressSelectionAssistantReasons = { }; 825 826 } 826 827 … … 1343 1344 - (void)_displayFormNodeInputView 1344 1345 { 1345 if (! self.suppressAssistantSelectionView) {1346 if (!_suppressSelectionAssistantReasons.contains(FocusedElementIsTransparent)) { 1346 1347 // In case user scaling is force enabled, do not use that scaling when zooming in with an input field. 1347 1348 // Zooming above the page's default scale factor should only happen when the user performs it. … … 1737 1738 - (BOOL)canShowNonEmptySelectionView 1738 1739 { 1739 if ( self.suppressAssistantSelectionView)1740 if (_suppressSelectionAssistantReasons) 1740 1741 return NO; 1741 1742 … … 1749 1750 return NO; 1750 1751 1751 if ( self.suppressAssistantSelectionView)1752 if (_suppressSelectionAssistantReasons) 1752 1753 return NO; 1753 1754 … … 1775 1776 return NO; 1776 1777 1777 if ( self.suppressAssistantSelectionView)1778 if (_suppressSelectionAssistantReasons) 1778 1779 return NO; 1779 1780 … … 1789 1790 return NO; 1790 1791 1791 if ( self.suppressAssistantSelectionView)1792 if (_suppressSelectionAssistantReasons) 1792 1793 return NO; 1793 1794 … … 4200 4201 [self setUpTextSelectionAssistant]; 4201 4202 4202 if (self.isFirstResponder && ! self.suppressAssistantSelectionView)4203 if (self.isFirstResponder && !_suppressSelectionAssistantReasons) 4203 4204 [_textSelectionAssistant activateSelection]; 4204 4205 … … 4286 4287 startInputSessionPolicy = [inputDelegate _webView:_webView decidePolicyForFocusedElement:focusedElementInfo.get()]; 4287 4288 4288 self.suppressAssistantSelectionView = information.elementIsTransparent; 4289 if (information.elementIsTransparent) 4290 [self _beginSuppressingSelectionAssistantForReason:FocusedElementIsTransparent]; 4291 else 4292 [self _stopSuppressingSelectionAssistantForReason:FocusedElementIsTransparent]; 4289 4293 4290 4294 switch (startInputSessionPolicy) { … … 4431 4435 [_webView didEndFormControlInteraction]; 4432 4436 4433 self.suppressAssistantSelectionView = NO;4437 [self _stopSuppressingSelectionAssistantForReason:FocusedElementIsTransparent]; 4434 4438 } 4435 4439 … … 4769 4773 4770 4774 auto& postLayoutData = state.postLayoutData(); 4771 if (hasAssistedNode(_assistedNodeInformation)) 4772 self.suppressAssistantSelectionView = postLayoutData.elementIsTransparent; 4775 if (hasAssistedNode(_assistedNodeInformation)) { 4776 if (postLayoutData.elementIsTransparent) 4777 [self _beginSuppressingSelectionAssistantForReason:FocusedElementIsTransparent]; 4778 else 4779 [self _stopSuppressingSelectionAssistantForReason:FocusedElementIsTransparent]; 4780 } 4773 4781 4774 4782 WKSelectionDrawingInfo selectionDrawingInfo(_page->editorState()); … … 4795 4803 [[self selectionInteractionAssistant] showSelectionCommands]; 4796 4804 4797 if (! self.suppressAssistantSelectionView)4805 if (!_suppressSelectionAssistantReasons) 4798 4806 [_textSelectionAssistant activateSelection]; 4799 4807 … … 4806 4814 - (BOOL)_shouldSuppressSelectionCommands 4807 4815 { 4808 return _suppressAssistantSelectionView; 4809 } 4810 4811 - (BOOL)suppressAssistantSelectionView 4812 { 4813 return _suppressAssistantSelectionView; 4814 } 4815 4816 - (void)setSuppressAssistantSelectionView:(BOOL)suppressAssistantSelectionView 4817 { 4818 if (_suppressAssistantSelectionView == suppressAssistantSelectionView) 4819 return; 4820 4821 _suppressAssistantSelectionView = suppressAssistantSelectionView; 4822 if (!_textSelectionAssistant) 4823 return; 4824 4825 if (suppressAssistantSelectionView) 4816 return !!_suppressSelectionAssistantReasons; 4817 } 4818 4819 - (void)_beginSuppressingSelectionAssistantForReason:(SuppressSelectionAssistantReason)reason 4820 { 4821 bool wasSuppressingSelectionAssistant = !!_suppressSelectionAssistantReasons; 4822 _suppressSelectionAssistantReasons.add(reason); 4823 4824 if (!wasSuppressingSelectionAssistant) 4826 4825 [_textSelectionAssistant deactivateSelection]; 4827 else 4826 } 4827 4828 - (void)_stopSuppressingSelectionAssistantForReason:(SuppressSelectionAssistantReason)reason 4829 { 4830 bool wasSuppressingSelectionAssistant = !!_suppressSelectionAssistantReasons; 4831 _suppressSelectionAssistantReasons.remove(reason); 4832 4833 if (wasSuppressingSelectionAssistant && !_suppressSelectionAssistantReasons) 4828 4834 [_textSelectionAssistant activateSelection]; 4829 4835 } … … 5337 5343 [visibleContentViewSnapshot removeFromSuperview]; 5338 5344 [UIView animateWithDuration:0.25 animations:^() { 5339 [protectedSelf setSuppressAssistantSelectionView:NO];5345 [protectedSelf _stopSuppressingSelectionAssistantForReason:DropAnimationIsRunning]; 5340 5346 [unselectedContentSnapshot setAlpha:0]; 5341 5347 } completion:^(BOOL completed) { … … 5354 5360 5355 5361 if (!_isAnimatingConcludeEditDrag) 5356 self.suppressAssistantSelectionView = NO;5362 [self _stopSuppressingSelectionAssistantForReason:DropAnimationIsRunning]; 5357 5363 5358 5364 CGPoint global; … … 5803 5809 5804 5810 retainedSelf->_visibleContentViewSnapshot = [retainedSelf snapshotViewAfterScreenUpdates:NO]; 5805 [retainedSelf setSuppressAssistantSelectionView:YES];5811 [retainedSelf _beginSuppressingSelectionAssistantForReason:DropAnimationIsRunning]; 5806 5812 [UIView performWithoutAnimation:[retainedSelf] { 5807 5813 [retainedSelf->_visibleContentViewSnapshot setFrame:[retainedSelf bounds]]; -
trunk/Tools/ChangeLog
r238186 r238188 1 2018-11-14 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] A few drag and drop tests are crashing after r238146 4 https://bugs.webkit.org/show_bug.cgi?id=191617 5 6 Reviewed by Dean Jackson. 7 8 Augment these crashing tests to verify that selection commands are suppressed during drop over editable elements 9 via more robust means. These tests currently hit an assertion when revealing the callout bar too early, because 10 TestWebKitAPI is not a UI application (see <https://webkit.org/b/190401>). 11 12 Instead of relying on this other bug, directly ask the text input whether it is suppressing selection commands 13 during a drop, and remember the answer via DragAndDropSimulator. 14 15 * TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm: 16 (TestWebKitAPI::TEST): 17 18 Add to the existing tests that started failing after r238146. 19 20 * TestWebKitAPI/cocoa/DragAndDropSimulator.h: 21 * TestWebKitAPI/cocoa/TestWKWebView.h: 22 * TestWebKitAPI/cocoa/TestWKWebView.mm: 23 (-[TestWKWebView textInputContentView]): 24 * TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm: 25 (-[DragAndDropSimulator _resetSimulatedState]): 26 (-[DragAndDropSimulator _webView:dataInteractionOperationWasHandled:forSession:itemProviders:]): 27 * TestWebKitAPI/ios/UIKitSPI.h: 28 1 29 2018-11-14 Wenson Hsieh <wenson_hsieh@apple.com> 2 30 -
trunk/Tools/TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm
r237607 r238188 347 347 [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)]; 348 348 349 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 349 350 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"source.textContent"].length, 0UL); 350 351 EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"editor.textContent"].UTF8String); … … 367 368 [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)]; 368 369 370 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 369 371 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"source.textContent"].length, 0UL); 370 372 EXPECT_WK_STREQ("Hello world", [webView editorValue].UTF8String); … … 402 404 NSUInteger secondParagraphOffset = [finalTextContent rangeOfString:@"This is the second paragraph"].location; 403 405 406 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 404 407 EXPECT_FALSE(firstParagraphOffset == NSNotFound); 405 408 EXPECT_FALSE(secondParagraphOffset == NSNotFound); … … 428 431 [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)]; 429 432 433 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 430 434 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"source.value"].length, 0UL); 431 435 EXPECT_WK_STREQ("Hello world", [webView editorValue].UTF8String); … … 444 448 [webView stringByEvaluatingJavaScript:@"source.selectionEnd = source.value.length"]; 445 449 [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)]; 450 451 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 446 452 447 453 NSItemProvider *itemProvider = [simulator sourceItemProviders].firstObject; … … 465 471 [webView stringByEvaluatingJavaScript:@"source.selectionEnd = source.value.length"]; 466 472 [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)]; 473 474 EXPECT_TRUE([simulator suppressedSelectionCommandsDuringDrop]); 467 475 468 476 NSItemProvider *itemProvider = [simulator sourceItemProviders].firstObject; -
trunk/Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h
r237266 r238188 108 108 @property (nonatomic, readonly) CGRect lastKnownDragCaretRect; 109 109 @property (nonatomic, readonly) NSArray<UITargetedDragPreview *> *liftPreviews; 110 @property (nonatomic, readonly) BOOL suppressedSelectionCommandsDuringDrop; 110 111 111 112 #endif // PLATFORM(IOS_FAMILY) -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h
r238186 r238188 34 34 @class _WKActivatedElementInfo; 35 35 @protocol UITextInputMultiDocument; 36 @protocol UITextInputPrivate; 36 37 #endif 37 38 … … 77 78 #if PLATFORM(IOS_FAMILY) 78 79 @interface TestWKWebView (IOSOnly) 79 @property (nonatomic, readonly) UIView <UITextInput , UITextInputMultiDocument> *textInputContentView;80 @property (nonatomic, readonly) UIView <UITextInputPrivate, UITextInputMultiDocument> *textInputContentView; 80 81 @property (nonatomic, readonly) RetainPtr<NSArray> selectionRectsAfterPresentationUpdate; 81 82 @property (nonatomic, readonly) CGRect caretViewRectInContentCoordinates; -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r238186 r238188 352 352 @implementation TestWKWebView (IOSOnly) 353 353 354 - (UIView <UITextInput , UITextInputMultiDocument> *)textInputContentView355 { 356 return (UIView <UITextInput , UITextInputMultiDocument> *)[self valueForKey:@"_currentContentView"];354 - (UIView <UITextInputPrivate, UITextInputMultiDocument> *)textInputContentView 355 { 356 return (UIView <UITextInputPrivate, UITextInputMultiDocument> *)[self valueForKey:@"_currentContentView"]; 357 357 } 358 358 -
trunk/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm
r237266 r238188 316 316 DragAndDropPhase _phase; 317 317 318 BOOL _suppressedSelectionCommandsDuringDrop; 318 319 RetainPtr<UIDropProposal> _currentDropProposal; 319 320 } … … 358 359 - (void)_resetSimulatedState 359 360 { 361 _suppressedSelectionCommandsDuringDrop = NO; 360 362 _phase = DragAndDropPhaseBeginning; 361 363 _currentProgress = 0; … … 651 653 - (void)_webView:(WKWebView *)webView dataInteractionOperationWasHandled:(BOOL)handled forSession:(id)session itemProviders:(NSArray<UIItemProvider *> *)itemProviders 652 654 { 655 _suppressedSelectionCommandsDuringDrop = [_webView textInputContentView]._shouldSuppressSelectionCommands; 653 656 _isDoneWithCurrentRun = true; 654 657 -
trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h
r238186 r238188 80 80 - (void)insertTextSuggestion:(UITextSuggestion *)textSuggestion; 81 81 - (void)handleKeyWebEvent:(WebEvent *)theEvent withCompletionHandler:(void (^)(WebEvent *, BOOL))completionHandler; 82 - (BOOL)_shouldSuppressSelectionCommands; 82 83 @end 83 84
Note: See TracChangeset
for help on using the changeset viewer.