Changeset 262051 in webkit


Ignore:
Timestamp:
May 22, 2020 4:15:00 AM (4 years ago)
Author:
timothy_horton@apple.com
Message:

iOS: Pressing tab in the Mail subject field moves focus to the body, but pressing shift tab doesn't move it back
https://bugs.webkit.org/show_bug.cgi?id=212243
<rdar://problem/59127764>

Reviewed by Wenson Hsieh.

Source/WebCore:

New API Tests: WebKit.ShiftTabTakesFocusFromEditableWebView and WebKit.TabDoesNotTakeFocusFromEditableWebView

  • page/FocusController.cpp:

(WebCore::FocusController::relinquishFocusToChrome):
(WebCore::FocusController::advanceFocusInDocumentOrder):

  • page/FocusController.h:

Factor out the code that decides whether the Chrome might accept focus,
and transfers focus out to the Chrome, for use in EventHandler.

  • page/EventHandler.cpp:

(WebCore::EventHandler::defaultTabEventHandler):
In the case where we are shift-tabbing out of an editable web view,
allow focus to pass to the Chrome. Previously, we would not allow this,
because tabKeyCyclesThroughElements is false in editable web views.
However, focus exiting the web view entirely needn't be covered by
"cycles through elements" behavior.
We can't do this for plain "tab", because that needs to be allowed to
insert a tab character instead.

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/UIDelegate.mm:

(-[FocusDelegate _webView:takeFocus:]):
(-[FocusDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(TEST):

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r262049 r262051  
     12020-05-22  Tim Horton  <timothy_horton@apple.com>
     2
     3        iOS: Pressing tab in the Mail subject field moves focus to the body, but pressing shift tab doesn't move it back
     4        https://bugs.webkit.org/show_bug.cgi?id=212243
     5        <rdar://problem/59127764>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        New API Tests: WebKit.ShiftTabTakesFocusFromEditableWebView and WebKit.TabDoesNotTakeFocusFromEditableWebView
     10
     11        * page/FocusController.cpp:
     12        (WebCore::FocusController::relinquishFocusToChrome):
     13        (WebCore::FocusController::advanceFocusInDocumentOrder):
     14        * page/FocusController.h:
     15        Factor out the code that decides whether the Chrome might accept focus,
     16        and transfers focus out to the Chrome, for use in EventHandler.
     17
     18        * page/EventHandler.cpp:
     19        (WebCore::EventHandler::defaultTabEventHandler):
     20        In the case where we are shift-tabbing out of an editable web view,
     21        allow focus to pass to the Chrome. Previously, we would not allow this,
     22        because tabKeyCyclesThroughElements is false in editable web views.
     23        However, focus exiting the web view entirely needn't be covered by
     24        "cycles through elements" behavior.
     25        We can't do this for plain "tab", because that needs to be allowed to
     26        insert a tab character instead.
     27
    1282020-05-22  Tyler Wilcock  <twilco.o@protonmail.com>
    229
  • trunk/Source/WebCore/page/EventHandler.cpp

    r261776 r262051  
    40954095    if (!page)
    40964096        return;
    4097     if (!page->tabKeyCyclesThroughElements())
    4098         return;
    40994097
    41004098    FocusDirection focusDirection = event.shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
     
    41034101    if (m_frame.document()->inDesignMode())
    41044102        return;
     4103
     4104    // Allow shift-tab to relinquish focus even if we don't allow tab to cycle between elements inside the view.
     4105    // We can only do this for shift-tab, not tab itself because tabKeyCyclesThroughElements is used to make
     4106    // tab character insertion work in editable web views.
     4107    if (!page->tabKeyCyclesThroughElements()) {
     4108        if (focusDirection == FocusDirectionBackward) {
     4109            if (page->focusController().relinquishFocusToChrome(focusDirection))
     4110                event.setDefaultHandled();
     4111        }
     4112        return;
     4113    }
    41054114
    41064115    if (page->focusController().advanceFocus(focusDirection, &event))
  • trunk/Source/WebCore/page/FocusController.cpp

    r259241 r262051  
    449449}
    450450
     451bool FocusController::relinquishFocusToChrome(FocusDirection direction)
     452{
     453    RefPtr<Document> document = focusedOrMainFrame().document();
     454    if (!document)
     455        return false;
     456
     457    if (!m_page.chrome().canTakeFocus(direction) || m_page.isControlledByAutomation())
     458        return false;
     459
     460    document->setFocusedElement(nullptr);
     461    setFocusedFrame(nullptr);
     462    m_page.chrome().takeFocus(direction);
     463    return true;
     464}
     465
    451466bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, KeyboardEvent* event, bool initialFocus)
    452467{
     
    467482    if (!element) {
    468483        // We didn't find a node to focus, so we should try to pass focus to Chrome.
    469         if (!initialFocus && m_page.chrome().canTakeFocus(direction) && !m_page.isControlledByAutomation()) {
    470             document->setFocusedElement(nullptr);
    471             setFocusedFrame(nullptr);
    472             m_page.chrome().takeFocus(direction);
    473             return true;
     484        if (!initialFocus) {
     485            if (relinquishFocusToChrome(direction))
     486                return true;
    474487        }
    475488
  • trunk/Source/WebCore/page/FocusController.h

    r247529 r262051  
    7979    Seconds timeSinceFocusWasSet() const;
    8080
     81    bool relinquishFocusToChrome(FocusDirection);
     82
    8183private:
    8284    void setActiveInternal(bool);
  • trunk/Tools/ChangeLog

    r262047 r262051  
     12020-05-22  Tim Horton  <timothy_horton@apple.com>
     2
     3        iOS: Pressing tab in the Mail subject field moves focus to the body, but pressing shift tab doesn't move it back
     4        https://bugs.webkit.org/show_bug.cgi?id=212243
     5        <rdar://problem/59127764>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/UIDelegate.mm:
     10        (-[FocusDelegate _webView:takeFocus:]):
     11        (-[FocusDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
     12        (TEST):
     13
    1142020-05-21  Wenson Hsieh  <wenson_hsieh@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UIDelegate.mm

    r258574 r262051  
    810810}
    811811
    812 static _WKFocusDirection takenDirection;
    813 
    814812@interface FocusDelegate : NSObject <WKUIDelegatePrivate>
    815 @end
    816 
    817 @implementation FocusDelegate
     813@property (nonatomic) _WKFocusDirection takenDirection;
     814@property (nonatomic) BOOL useShiftTab;
     815@end
     816
     817@implementation FocusDelegate {
     818@package
     819    bool _done;
     820    bool _didSendKeyEvent;
     821}
    818822
    819823- (void)_webView:(WKWebView *)webView takeFocus:(_WKFocusDirection)direction
    820824{
    821     takenDirection = direction;
    822     done = true;
     825    _takenDirection = direction;
     826    _done = true;
    823827}
    824828
     
    826830{
    827831    completionHandler();
    828     synthesizeTab([webView window], webView, true);
     832    _didSendKeyEvent = true;
     833    synthesizeTab([webView window], webView, _useShiftTab);
    829834}
    830835
     
    835840    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
    836841    auto delegate = adoptNS([[FocusDelegate alloc] init]);
     842    [delegate setUseShiftTab:YES];
    837843    [webView setUIDelegate:delegate.get()];
    838844    NSString *html = @"<script>function loaded() { document.getElementById('in').focus(); alert('ready'); }</script>"
    839845    "<body onload='loaded()'><input type='text' id='in'></body>";
    840846    [webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://example.com/"]];
    841     TestWebKitAPI::Util::run(&done);
    842     ASSERT_EQ(takenDirection, _WKFocusDirectionBackward);
     847    TestWebKitAPI::Util::run(&delegate->_done);
     848    ASSERT_EQ([delegate takenDirection], _WKFocusDirectionBackward);
     849}
     850
     851TEST(WebKit, ShiftTabTakesFocusFromEditableWebView)
     852{
     853    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
     854    [webView _setEditable:YES];
     855
     856    auto delegate = adoptNS([[FocusDelegate alloc] init]);
     857    [delegate setUseShiftTab:YES];
     858    [webView setUIDelegate:delegate.get()];
     859    NSString *html = @"<script>function loaded() { document.body.focus(); alert('ready'); }</script>"
     860    "<body onload='loaded()'></body>";
     861    [webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://example.com/"]];
     862    TestWebKitAPI::Util::run(&delegate->_done);
     863    ASSERT_EQ([delegate takenDirection], _WKFocusDirectionBackward);
     864}
     865
     866TEST(WebKit, TabDoesNotTakeFocusFromEditableWebView)
     867{
     868    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
     869    [webView _setEditable:YES];
     870
     871    auto delegate = adoptNS([[FocusDelegate alloc] init]);
     872    [webView setUIDelegate:delegate.get()];
     873    NSString *html = @"<script>function loaded() { document.body.focus(); alert('ready'); }</script>"
     874    "<body onload='loaded()'></body>";
     875    [webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://example.com/"]];
     876    TestWebKitAPI::Util::run(&delegate->_didSendKeyEvent);
     877    EXPECT_WK_STREQ("\t", [webView stringByEvaluatingJavaScript:@"document.body.textContent"]);
     878    ASSERT_FALSE(delegate->_done);
    843879}
    844880
Note: See TracChangeset for help on using the changeset viewer.