⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 275054 in webkit


Ignore:
Timestamp:
Mar 25, 2021, 1:22:10 PM (5 years ago)
Author:
Aditya Keerthi
Message:

[iOS] Date picker view jumps to center when switching between MobileSafari and another app
https://bugs.webkit.org/show_bug.cgi?id=223662
<rdar://problem/74748727>

Reviewed by Tim Horton.

Tapping on a date input presents a UIDatePicker inside of a
UIContextMenuInteraction. The presentation of context menus is
dependent on the _positionInformation in WKContentViewInteraction being
up-to-date.

To ensure the value is up-to-date, a position information request is
made prior to presenting the date picker. However, the location used
for the request is the current FocusedElementInformation's
lastInteractionLocation. This is fine in most cases, since the date
picker is usually present immediately after tapping on the date input.
However, the date picker can be closed and presented again when
switching between MobileSafari and another app, as the input is focused
again when MobileSafari is reopened. If the switch is performed using a
gesture, the last interaction location is modified. Consequently, the
last interaction location does not always correspond to the position
of the date input, and the position information request gives us
incorrect information, leading to incorrect presentation of the picker.

To fix, add a new way of presenting context menus that is not dependent
on position information. Instead, form controls can use the information
they already have in FocusedElementInformation to present their
peripherals.

No new tests, since this bug only reproduces when swiping to switch apps.
Other touches in the web view immediately dismiss the date picker, making
the bug difficult to reproduce in a test.

  • Shared/FocusedElementInformation.cpp:

(WebKit::FocusedElementInformation::encode const):
(WebKit::FocusedElementInformation::decode):

  • Shared/FocusedElementInformation.h:

Added a member to inform FocusedElementInformation whether the focused
element is in a subscrollable region.

See r248447 for more details on why this information is needed when
creating a UITargetedPreview.

  • UIProcess/ios/WKContentViewInteraction.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView overridePositionTrackingViewForTargetedPreviewIfNecessary:containerScrollingNodeID:]):

Factored out the logic that overrides the targeted preview's position
tracking view when the element is in a subscrollable region.

(-[WKContentView _createTargetedContextMenuHintPreviewForFocusedElement]):

Create a targeted preview using the current FocusedElementInformation.

(-[WKContentView _createTargetedContextMenuHintPreviewIfPossible]):

  • UIProcess/ios/forms/WKDateTimeInputControl.mm:

(-[WKDateTimePicker controlBeginEditing]):

Displaying the context menu no longer needs to be done asynchronously
since the FocusedElementInformation is already available during
controlBeginEditing.

  • UIProcess/ios/forms/WKFormSelectPicker.mm:

Adopt the new logic for <select> elements, since the presented context
menu is an input peripheral, and can run into the same issues as the
date picker.

(-[WKSelectPicker controlBeginEditing]):
(-[WKSelectPicker contextMenuInteraction:previewForHighlightingMenuWithConfiguration:]):

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::completeSyntheticClick):

Remove a redundant call to elementDidRefocus following r258333. The
FocusController already calls elementDidRefocus before this point, when
the mousepress event is dispatched.

The redundant call was uncovered when making the context menu
presentation synchronous, and causes problems with the presentation.
Specifically, the first call to elementDidRefocus causes the context
menu to be presented. The second call then results in an attempt
to scroll the web view, since the context menu can obscure the
assisted node. The additional scrolling is unwanted behavior, since it
does not occur when focusing the node for the first time.

This issue was previously unobserved, since the asynchronous presentation
of the context menu (after obtaining new position information) resulted
in both calls to elementDidRefocus occuring before presentation.

(WebKit::WebPage::getFocusedElementInformation):

Forward the scrolling node information to the UIProcess, so that the
position tracking view of the UITargetedPreview can be overridden
if necessary.

Location:
trunk/Source/WebKit
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r275050 r275054  
     12021-03-25  Aditya Keerthi  <akeerthi@apple.com>
     2
     3        [iOS] Date picker view jumps to center when switching between MobileSafari and another app
     4        https://bugs.webkit.org/show_bug.cgi?id=223662
     5        <rdar://problem/74748727>
     6
     7        Reviewed by Tim Horton.
     8
     9        Tapping on a date input presents a UIDatePicker inside of a
     10        UIContextMenuInteraction. The presentation of context menus is
     11        dependent on the _positionInformation in WKContentViewInteraction being
     12        up-to-date.
     13
     14        To ensure the value is up-to-date, a position information request is
     15        made prior to presenting the date picker. However, the location used
     16        for the request is the current FocusedElementInformation's
     17        lastInteractionLocation. This is fine in most cases, since the date
     18        picker is usually present immediately after tapping on the date input.
     19        However, the date picker can be closed and presented again when
     20        switching between MobileSafari and another app, as the input is focused
     21        again when MobileSafari is reopened. If the switch is performed using a
     22        gesture, the last interaction location is modified. Consequently, the
     23        last interaction location does not always correspond to the position
     24        of the date input, and the position information request gives us
     25        incorrect information, leading to incorrect presentation of the picker.
     26
     27        To fix, add a new way of presenting context menus that is not dependent
     28        on position information. Instead, form controls can use the information
     29        they already have in FocusedElementInformation to present their
     30        peripherals.
     31
     32        No new tests, since this bug only reproduces when swiping to switch apps.
     33        Other touches in the web view immediately dismiss the date picker, making
     34        the bug difficult to reproduce in a test.
     35
     36        * Shared/FocusedElementInformation.cpp:
     37        (WebKit::FocusedElementInformation::encode const):
     38        (WebKit::FocusedElementInformation::decode):
     39        * Shared/FocusedElementInformation.h:
     40
     41        Added a member to inform FocusedElementInformation whether the focused
     42        element is in a subscrollable region.
     43
     44        See r248447 for more details on why this information is needed when
     45        creating a UITargetedPreview.
     46
     47        * UIProcess/ios/WKContentViewInteraction.h:
     48        * UIProcess/ios/WKContentViewInteraction.mm:
     49        (-[WKContentView overridePositionTrackingViewForTargetedPreviewIfNecessary:containerScrollingNodeID:]):
     50
     51        Factored out the logic that overrides the targeted preview's position
     52        tracking view when the element is in a subscrollable region.
     53
     54        (-[WKContentView _createTargetedContextMenuHintPreviewForFocusedElement]):
     55
     56        Create a targeted preview using the current FocusedElementInformation.
     57
     58        (-[WKContentView _createTargetedContextMenuHintPreviewIfPossible]):
     59        * UIProcess/ios/forms/WKDateTimeInputControl.mm:
     60        (-[WKDateTimePicker controlBeginEditing]):
     61
     62        Displaying the context menu no longer needs to be done asynchronously
     63        since the FocusedElementInformation is already available during
     64        controlBeginEditing.
     65
     66        * UIProcess/ios/forms/WKFormSelectPicker.mm:
     67
     68        Adopt the new logic for <select> elements, since the presented context
     69        menu is an input peripheral, and can run into the same issues as the
     70        date picker.
     71
     72        (-[WKSelectPicker controlBeginEditing]):
     73        (-[WKSelectPicker contextMenuInteraction:previewForHighlightingMenuWithConfiguration:]):
     74        * WebProcess/WebPage/ios/WebPageIOS.mm:
     75        (WebKit::WebPage::completeSyntheticClick):
     76
     77        Remove a redundant call to elementDidRefocus following r258333. The
     78        FocusController already calls elementDidRefocus before this point, when
     79        the mousepress event is dispatched.
     80
     81        The redundant call was uncovered when making the context menu
     82        presentation synchronous, and causes problems with the presentation.
     83        Specifically, the first call to elementDidRefocus causes the context
     84        menu to be presented. The second call then results in an attempt
     85        to scroll the web view, since the context menu can obscure the
     86        assisted node. The additional scrolling is unwanted behavior, since it
     87        does not occur when focusing the node for the first time.
     88
     89        This issue was previously unobserved, since the asynchronous presentation
     90        of the context menu (after obtaining new position information) resulted
     91        in both calls to elementDidRefocus occuring before presentation.
     92
     93        (WebKit::WebPage::getFocusedElementInformation):
     94
     95        Forward the scrolling node information to the UIProcess, so that the
     96        position tracking view of the UITargetedPreview can be overridden
     97        if necessary.
     98
    1992021-03-25  BJ Burg  <bburg@apple.com>
    2100
  • trunk/Source/WebKit/Shared/FocusedElementInformation.cpp

    r273049 r275054  
    100100    encoder << ariaLabel;
    101101    encoder << focusedElementIdentifier;
     102    encoder << containerScrollingNodeID;
    102103#if ENABLE(DATALIST_ELEMENT)
    103104    encoder << hasSuggestions;
     
    226227        return false;
    227228
     229    if (!decoder.decode(result.containerScrollingNodeID))
     230        return false;
     231
    228232#if ENABLE(DATALIST_ELEMENT)
    229233    if (!decoder.decode(result.hasSuggestions))
  • trunk/Source/WebKit/Shared/FocusedElementInformation.h

    r273453 r275054  
    142142
    143143    FocusedElementIdentifier focusedElementIdentifier { 0 };
     144    WebCore::ScrollingNodeID containerScrollingNodeID { 0 };
    144145
    145146    void encode(IPC::Encoder&) const;
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r274610 r275054  
    673673
    674674#if USE(UICONTEXTMENU)
     675- (UITargetedPreview *)_createTargetedContextMenuHintPreviewForFocusedElement;
    675676- (UITargetedPreview *)_createTargetedContextMenuHintPreviewIfPossible;
    676677- (void)_removeContextMenuViewIfPossible;
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r274653 r275054  
    82398239}
    82408240
     8241- (void)overridePositionTrackingViewForTargetedPreviewIfNecessary:(UITargetedPreview *)targetedPreview containerScrollingNodeID:(WebCore::ScrollingNodeID)scrollingNodeID
     8242{
     8243    if (!scrollingNodeID)
     8244        return;
     8245
     8246    UIScrollView *positionTrackingView = self.webView.scrollView;
     8247    if (auto* scrollingCoordinator = _page->scrollingCoordinatorProxy())
     8248        positionTrackingView = scrollingCoordinator->scrollViewForScrollingNodeID(scrollingNodeID);
     8249
     8250    if ([targetedPreview respondsToSelector:@selector(_setOverridePositionTrackingView:)])
     8251        [targetedPreview _setOverridePositionTrackingView:positionTrackingView];
     8252}
     8253
     8254- (UITargetedPreview *)_createTargetedContextMenuHintPreviewForFocusedElement
     8255{
     8256    RetainPtr<UITargetedPreview> targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _focusedElementInformation.interactionRect);
     8257
     8258    [self overridePositionTrackingViewForTargetedPreviewIfNecessary:targetedPreview.get() containerScrollingNodeID:_focusedElementInformation.containerScrollingNodeID];
     8259
     8260    _contextMenuInteractionTargetedPreview = WTFMove(targetedPreview);
     8261    return _contextMenuInteractionTargetedPreview.get();
     8262}
     8263
    82418264- (UITargetedPreview *)_createTargetedContextMenuHintPreviewIfPossible
    82428265{
     
    82568279        targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _positionInformation.bounds);
    82578280
    8258     if (_positionInformation.containerScrollingNodeID) {
    8259         UIScrollView *positionTrackingView = self.webView.scrollView;
    8260         if (auto* scrollingCoordinator = _page->scrollingCoordinatorProxy())
    8261             positionTrackingView = scrollingCoordinator->scrollViewForScrollingNodeID(_positionInformation.containerScrollingNodeID);
    8262 
    8263         if ([targetedPreview respondsToSelector:@selector(_setOverridePositionTrackingView:)])
    8264             [targetedPreview _setOverridePositionTrackingView:positionTrackingView];
    8265     }
     8281    [self overridePositionTrackingViewForTargetedPreviewIfNecessary:targetedPreview.get() containerScrollingNodeID:_positionInformation.containerScrollingNodeID];
    82668282
    82678283    _contextMenuInteractionTargetedPreview = WTFMove(targetedPreview);
  • trunk/Source/WebKit/UIProcess/ios/forms/WKDateTimeInputControl.mm

    r268537 r275054  
    153153- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
    154154{
    155     return [_view _createTargetedContextMenuHintPreviewIfPossible];
     155    return [_view _createTargetedContextMenuHintPreviewForFocusedElement];
    156156}
    157157
     
    414414    _initialValueAsNumber = _view.focusedElementInformation.valueAsNumber;
    415415    [self setDateTimePickerToInitialValue];
    416    
    417 #if USE(UICONTEXTMENU)
    418     WebKit::InteractionInformationRequest positionInformationRequest { WebCore::IntPoint(_view.focusedElementInformation.lastInteractionLocation) };
    419     [_view doAfterPositionInformationUpdate:^(WebKit::InteractionInformationAtPosition interactionInformation) {
    420         [self showDateTimePicker];
    421     } forRequest:positionInformationRequest];
    422 #endif
    423 
     416
     417#if USE(UICONTEXTMENU)
     418    [self showDateTimePicker];
     419#endif
    424420}
    425421
  • trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectPicker.mm

    r274866 r275054  
    506506#if USE(UICONTEXTMENU)
    507507    _selectMenu = [self createMenu];
    508 
    509     WebKit::InteractionInformationRequest positionInformationRequest { WebCore::IntPoint(_view.focusedElementInformation.lastInteractionLocation) };
    510     [_view doAfterPositionInformationUpdate:^(WebKit::InteractionInformationAtPosition interactionInformation) {
    511         [self showSelectPicker];
    512     } forRequest:positionInformationRequest];
     508    [self showSelectPicker];
    513509#endif
    514510}
     
    632628- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
    633629{
    634     return [_view _createTargetedContextMenuHintPreviewIfPossible];
     630    return [_view _createTargetedContextMenuHintPreviewForFocusedElement];
    635631}
    636632
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r274618 r275054  
    867867    RefPtr<Element> newFocusedElement = newFocusedFrame ? newFocusedFrame->document()->focusedElement() : nullptr;
    868868
    869     // If the focus has not changed, we need to notify the client anyway, since it might be
    870     // necessary to start assisting the node.
    871     // If the node has been focused by JavaScript without user interaction, the
    872     // keyboard is not on screen.
    873     if (newFocusedElement && newFocusedElement == oldFocusedElement)
    874         elementDidRefocus(*newFocusedElement);
    875 
    876869    if (nodeRespondingToClick.document().settings().contentChangeObserverEnabled()) {
    877870        auto& document = nodeRespondingToClick.document();
     
    30843077        information.insideFixedPosition = inFixed;
    30853078        information.isRTL = renderer->style().direction() == TextDirection::RTL;
     3079
     3080#if ENABLE(ASYNC_SCROLLING)
     3081        if (auto* scrollingCoordinator = this->scrollingCoordinator())
     3082            information.containerScrollingNodeID = scrollingCoordinator->scrollableContainerNodeID(*renderer);
     3083#endif
    30863084    } else
    30873085        information.interactionRect = { };
Note: See TracChangeset for help on using the changeset viewer.