Changeset 242833 in webkit
- Timestamp:
- Mar 12, 2019, 4:51:57 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/forms/ios/keyboard-stability-when-refocusing-element-expected.txt (added)
-
LayoutTests/fast/forms/ios/keyboard-stability-when-refocusing-element.html (added)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.h (modified) (1 diff)
-
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (modified) (3 diffs)
-
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (modified) (1 diff)
-
Source/WebKit/WebProcess/WebPage/WebPage.cpp (modified) (6 diffs)
-
Source/WebKit/WebProcess/WebPage/WebPage.h (modified) (5 diffs)
-
Source/WebKit/WebProcess/WebPage/WebPage.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r242826 r242833 1 2019-03-12 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Input view sometimes flickers when blurring and refocusing an element 4 https://bugs.webkit.org/show_bug.cgi?id=195639 5 <rdar://problem/48735337> 6 7 Reviewed by Tim Horton. 8 9 Add a test to ensure that the form control interaction doesn't stop and start again when blurring and focusing 10 an editable element. 11 12 * fast/forms/ios/keyboard-stability-when-refocusing-element-expected.txt: Added. 13 * fast/forms/ios/keyboard-stability-when-refocusing-element.html: Added. 14 1 15 2019-03-12 Dean Jackson <dino@apple.com> 2 16 -
trunk/Source/WebKit/ChangeLog
r242824 r242833 1 2019-03-12 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Input view sometimes flickers when blurring and refocusing an element 4 https://bugs.webkit.org/show_bug.cgi?id=195639 5 <rdar://problem/48735337> 6 7 Reviewed by Tim Horton. 8 9 On iOS, if a focused element is blurred and immediately refocused in the scope of user interaction, we will end 10 up reloading interaction state (input views, autocorrection contexts, etc.) in the UI process. On certain well- 11 trafficked websites, this results in the input view and input accessory view flickering (or more egregiously, 12 scrolling to re-reveal the focused element) when changing selection. 13 14 To fix the issue, this patch refactors some focus management logic to suppress sending focused element updates 15 to the UI process in the case where the same element is being blurred and immediately refocused. To do this, we 16 track the most recently blurred element and bail when the recently blurred element is identical to the newly 17 focused element. See below for more detail. 18 19 Test: fast/forms/ios/keyboard-stability-when-refocusing-element.html 20 21 * UIProcess/WebPageProxy.h: 22 * UIProcess/ios/WKContentViewInteraction.mm: 23 (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]): 24 (-[WKContentView _elementDidBlur]): 25 26 Update the web process' notion of whether an input view is showing. Importantly, this accounts for decisions 27 made by _WKUIDelegate. See below for more details. 28 29 (isAssistableInputType): Deleted. 30 31 Removed this helper function; this was only used in one place as a sanity check that the focused element's type 32 is not none, right before attempting to show an input view. Instead, we can just check the focused element's 33 type directly against InputType::None in the if statement of the early return. 34 35 * UIProcess/ios/WebPageProxyIOS.mm: 36 (WebKit::WebPageProxy::setIsShowingInputViewForFocusedElement): 37 38 Add a hook to notify the web process when an input view is showing or not (see below for more detail). 39 40 * WebProcess/WebPage/WebPage.cpp: 41 (WebKit::WebPage::didStartPageTransition): 42 (WebKit::WebPage::elementDidRefocus): 43 (WebKit::WebPage::shouldDispatchUpdateAfterFocusingElement const): 44 45 Add a helper to determine whether we notify the UI process about a newly focused element. On macOS, this is true 46 only when the new focused element is neither the currently focused element, nor the focused element that was 47 just blurred. On iOS, we have an additional constraint that when the input view is not showing, we still need to 48 notify the UI process, since the UI process might want to begin showing the keyboard for an element that has 49 only been programmatically focused, for which we aren't currently showing the input view. 50 51 (WebKit::WebPage::elementDidFocus): 52 (WebKit::WebPage::elementDidBlur): 53 54 Replace a couple of existing member variables in WebPage used for focus management: 55 - Replace m_hasPendingBlurNotification with m_recentlyBlurredElement, a RefPtr to the Element that is being 56 blurred. Behavior here is the same as before (i.e. having a pending blur notification is equivalent to 57 having recently blurred a focused element). However, this allows us to check newly focused elements against 58 the recently blurred element in WebPage::elementDidFocus(). 59 - Replace m_isFocusingElementDueToUserInteraction with m_isShowingInputViewForFocusedElement. The flag 60 m_isFocusingElementDueToUserInteraction was originally added to fix <webkit.org/b/146735>, by ensuring that 61 we don't send redundant ElementDidFocus (formerly, StartAssistingNode) messages to the UI process even when 62 the keyboard is already up. In these simpler times, user interaction when focusing an element was equivalent 63 to showing an input view for the focused element. However, in today's world, there are a variety of reasons 64 why we might or might not show an input view for a given element (including, but not limited to activity 65 state changes and decisions made by _WKInputDelegate). As such, it doesn't make sense to continue relying on 66 m_isFocusingElementDueToUserInteraction in this early return. Instead, have the UI process propagate a 67 message back to the web process, to let it know whether there is a keyboard showing, and use this flag 68 instead. 69 70 * WebProcess/WebPage/WebPage.h: 71 * WebProcess/WebPage/WebPage.messages.in: 72 * WebProcess/WebPage/ios/WebPageIOS.mm: 73 (WebKit::WebPage::setIsShowingInputViewForFocusedElement): 74 1 75 2019-03-12 Tim Horton <timothy_horton@apple.com> 2 76 -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r242796 r242833 1195 1195 1196 1196 void blurFocusedElement(); 1197 void setIsShowingInputViewForFocusedElement(bool); 1197 1198 #endif 1198 1199 -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r242801 r242833 4818 4818 } 4819 4819 4820 static bool isAssistableInputType(WebKit::InputType type)4821 {4822 switch (type) {4823 case WebKit::InputType::ContentEditable:4824 case WebKit::InputType::Text:4825 case WebKit::InputType::Password:4826 case WebKit::InputType::TextArea:4827 case WebKit::InputType::Search:4828 case WebKit::InputType::Email:4829 case WebKit::InputType::URL:4830 case WebKit::InputType::Phone:4831 case WebKit::InputType::Number:4832 case WebKit::InputType::NumberPad:4833 case WebKit::InputType::Date:4834 case WebKit::InputType::DateTime:4835 case WebKit::InputType::DateTimeLocal:4836 case WebKit::InputType::Month:4837 case WebKit::InputType::Week:4838 case WebKit::InputType::Time:4839 case WebKit::InputType::Select:4840 case WebKit::InputType::Drawing:4841 #if ENABLE(INPUT_TYPE_COLOR)4842 case WebKit::InputType::Color:4843 #endif4844 return true;4845 4846 case WebKit::InputType::None:4847 return false;4848 }4849 4850 ASSERT_NOT_REACHED();4851 return false;4852 }4853 4854 4820 static const double minimumFocusedElementAreaForSuppressingSelectionAssistant = 4; 4855 4821 … … 4934 4900 #endif 4935 4901 4936 if (!shouldShowInputView) 4937 return; 4938 4939 if (!isAssistableInputType(information.elementType)) 4940 return; 4902 if (!shouldShowInputView || information.elementType == WebKit::InputType::None) { 4903 _page->setIsShowingInputViewForFocusedElement(false); 4904 return; 4905 } 4906 4907 _page->setIsShowingInputViewForFocusedElement(true); 4941 4908 4942 4909 // FIXME: We should remove this check when we manage to send ElementDidFocus from the WebProcess … … 5057 5024 5058 5025 [_webView didEndFormControlInteraction]; 5026 _page->setIsShowingInputViewForFocusedElement(false); 5059 5027 5060 5028 if (!_isChangingFocus) { -
trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
r242796 r242833 899 899 } 900 900 901 void WebPageProxy::setIsShowingInputViewForFocusedElement(bool showingInputView) 902 { 903 process().send(Messages::WebPage::SetIsShowingInputViewForFocusedElement(showingInputView), m_pageID); 904 } 905 901 906 void WebPageProxy::elementDidFocus(const FocusedElementInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData) 902 907 { -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r242762 r242833 3125 3125 #endif 3126 3126 m_hasEverFocusedElementDueToUserInteractionSincePageTransition = false; 3127 m_isFocusingElementDueToUserInteraction = false;3128 3127 m_lastEditorStateWasContentEditable = EditorStateIsContentEditable::Unset; 3129 3128 #if PLATFORM(MAC) … … 3138 3137 send(Messages::WebPageProxy::SetNeedsPlainTextQuirk(m_needsPlainTextQuirk)); 3139 3138 } 3139 #endif 3140 #if PLATFORM(IOS_FAMILY) 3141 m_isShowingInputViewForFocusedElement = false; 3140 3142 #endif 3141 3143 } … … 5304 5306 elementDidFocus(element); 5305 5307 5306 if (m_ isFocusingElementDueToUserInteraction)5308 if (m_userIsInteracting) 5307 5309 scheduleFullEditorStateUpdate(); 5308 5310 } 5309 5311 5312 bool WebPage::shouldDispatchUpdateAfterFocusingElement(const Element& element) const 5313 { 5314 if (m_focusedElement == &element || m_recentlyBlurredElement == &element) { 5315 #if PLATFORM(IOS_FAMILY) 5316 return !m_isShowingInputViewForFocusedElement; 5317 #else 5318 return false; 5319 #endif 5320 } 5321 return true; 5322 } 5323 5310 5324 void WebPage::elementDidFocus(WebCore::Element& element) 5311 5325 { 5312 if (m_focusedElement == &element && m_isFocusingElementDueToUserInteraction) 5313 return; 5326 if (!shouldDispatchUpdateAfterFocusingElement(element)) { 5327 m_focusedElement = &element; 5328 m_recentlyBlurredElement = nullptr; 5329 return; 5330 } 5314 5331 5315 5332 if (element.hasTagName(WebCore::HTMLNames::selectTag) || element.hasTagName(WebCore::HTMLNames::inputTag) || element.hasTagName(WebCore::HTMLNames::textareaTag) || element.hasEditableStyle()) { 5316 5333 m_focusedElement = &element; 5317 m_isFocusingElementDueToUserInteraction |= m_userIsInteracting;5318 5334 5319 5335 #if PLATFORM(IOS_FAMILY) … … 5331 5347 m_formClient->willBeginInputSession(this, &element, WebFrame::fromCoreFrame(*element.document().frame()), m_userIsInteracting, userData); 5332 5348 5333 send(Messages::WebPageProxy::ElementDidFocus(information, m_userIsInteracting, m_ hasPendingBlurNotification, m_changingActivityState, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));5349 send(Messages::WebPageProxy::ElementDidFocus(information, m_userIsInteracting, m_recentlyBlurredElement, m_changingActivityState, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); 5334 5350 #elif PLATFORM(MAC) 5335 if (element.hasTagName(WebCore::HTMLNames::selectTag)) 5336 send(Messages::WebPageProxy::SetEditableElementIsFocused(false)); 5337 else 5338 send(Messages::WebPageProxy::SetEditableElementIsFocused(true)); 5339 #endif 5340 m_hasPendingBlurNotification = false; 5351 // FIXME: This can be unified with the iOS code above by bringing ElementDidFocus to macOS. 5352 // This also doesn't take other noneditable controls into account, such as input type color. 5353 send(Messages::WebPageProxy::SetEditableElementIsFocused(!element.hasTagName(WebCore::HTMLNames::selectTag))); 5354 #endif 5355 m_recentlyBlurredElement = nullptr; 5341 5356 } 5342 5357 } … … 5345 5360 { 5346 5361 if (m_focusedElement == &element) { 5347 m_hasPendingBlurNotification = true; 5348 RefPtr<WebPage> protectedThis(this); 5349 callOnMainThread([protectedThis] { 5350 if (protectedThis->m_hasPendingBlurNotification) { 5362 m_recentlyBlurredElement = WTFMove(m_focusedElement); 5363 callOnMainThread([protectedThis = makeRefPtr(this)] { 5364 if (protectedThis->m_recentlyBlurredElement) { 5351 5365 #if PLATFORM(IOS_FAMILY) 5352 5366 protectedThis->send(Messages::WebPageProxy::ElementDidBlur()); … … 5355 5369 #endif 5356 5370 } 5357 protectedThis->m_ hasPendingBlurNotification = false;5371 protectedThis->m_recentlyBlurredElement = nullptr; 5358 5372 }); 5359 5360 m_isFocusingElementDueToUserInteraction = false;5361 m_focusedElement = nullptr;5362 5373 } 5363 5374 } -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.h
r242796 r242833 659 659 void setFocusedElementValueAsNumber(double); 660 660 void setFocusedElementSelectedIndex(uint32_t index, bool allowMultipleSelection); 661 void setIsShowingInputViewForFocusedElement(bool); 661 662 void updateSelectionAppearance(); 662 663 void getSelectionContext(CallbackID); … … 1528 1529 void cancelGesturesBlockedOnSynchronousReplies(); 1529 1530 1531 bool shouldDispatchUpdateAfterFocusingElement(const WebCore::Element&) const; 1532 1530 1533 uint64_t m_pageID; 1531 1534 … … 1725 1728 1726 1729 bool m_userIsInteracting { false }; 1727 bool m_isFocusingElementDueToUserInteraction { false };1728 1730 bool m_hasEverFocusedElementDueToUserInteractionSincePageTransition { false }; 1729 1731 bool m_needsHiddenContentEditableQuirk { false }; … … 1736 1738 1737 1739 RefPtr<WebCore::Element> m_focusedElement; 1738 bool m_hasPendingBlurNotification { false };1740 RefPtr<WebCore::Element> m_recentlyBlurredElement; 1739 1741 bool m_hasPendingEditorStateUpdate { false }; 1740 1742 … … 1747 1749 RefPtr<WebCore::Node> m_interactionNode; 1748 1750 WebCore::IntPoint m_lastInteractionLocation; 1751 1752 bool m_isShowingInputViewForFocusedElement { false }; 1749 1753 1750 1754 enum SelectionAnchor { Start, End }; -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
r242796 r242833 110 110 RequestFocusedElementInformation(WebKit::CallbackID callbackID) 111 111 HardwareKeyboardAvailabilityChanged(bool keyboardIsAttached) 112 SetIsShowingInputViewForFocusedElement(bool showingInputView) 112 113 #endif 113 114 -
trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r242798 r242833 931 931 } 932 932 933 void WebPage::setIsShowingInputViewForFocusedElement(bool showingInputView) 934 { 935 m_isShowingInputViewForFocusedElement = showingInputView; 936 } 937 933 938 void WebPage::setFocusedElementValue(const String& value) 934 939 {
Note:
See TracChangeset
for help on using the changeset viewer.