Changeset 90004 in webkit


Ignore:
Timestamp:
Jun 29, 2011 2:39:58 AM (13 years ago)
Author:
hayato@chromium.org
Message:

2011-06-29 Hayato Ito <hayato@chromium.org>

Reviewed by Hajime Morita.

Make a shadow host transfer a focus to the first focusable element in the shadow root when its focus() is called.
https://bugs.webkit.org/show_bug.cgi?id=62358.

This patch doesn't take an effect on the following elements to keep a compatibility.

  • <input>, <textarea>, <video> and <audio> elements We'll address these elements separately after re-targeting focus events (bug 61421) is implemented.

A shadow root's <content> is not considered in this patch.
That should be addressed in another patch. See bug 63522.

  • fast/dom/shadow/shadow-host-transfer-focus-expected.txt: Added.
  • fast/dom/shadow/shadow-host-transfer-focus.html: Added.

2011-06-29 Hayato Ito <hayato@chromium.org>

Reviewed by Hajime Morita.

Make a shadow host transfer a focus to the first focusable element in the shadow root when its focus() is called.
https://bugs.webkit.org/show_bug.cgi?id=62358.

This patch doesn't take an effect on the following elements to keep a compatibility.

  • <input>, <textarea>, <video> and <audio> elements We'll address these elements separately after re-targeting focus events (bug 61421) is implemented.

A shadow root's <content> is not considered in this patch.
That should be addressed in another patch. See bug 63522.

Test: fast/dom/shadow/shadow-host-transfer-focus.html

  • dom/Element.cpp: (WebCore::Element::focus):
  • page/FocusController.cpp: (WebCore::shadowRoot): (WebCore::isTreeScopeOwner): (WebCore::FocusController::transferFocusToElementInShadowRoot): (WebCore::hasCustomFocusLogic): (WebCore::FocusController::findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot): (WebCore::FocusController::advanceFocusInDocumentOrder): (WebCore::ownerOfTreeScope): (WebCore::FocusController::findFocusableNodeAcrossTreeScope):
  • page/FocusController.h:
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r90002 r90004  
     12011-06-29  Hayato Ito  <hayato@chromium.org>
     2
     3        Reviewed by Hajime Morita.
     4
     5        Make a shadow host transfer a focus to the first focusable element in the shadow root when its focus() is called.
     6        https://bugs.webkit.org/show_bug.cgi?id=62358.
     7
     8        This patch doesn't take an effect on the following elements to keep a compatibility.
     9        - <input>, <textarea>, <video> and <audio> elements
     10        We'll address these elements separately after re-targeting focus events
     11        (bug 61421) is implemented.
     12
     13        A shadow root's <content> is not considered in this patch.
     14        That should be addressed in another patch. See bug 63522.
     15
     16        * fast/dom/shadow/shadow-host-transfer-focus-expected.txt: Added.
     17        * fast/dom/shadow/shadow-host-transfer-focus.html: Added.
     18
    1192011-06-29  Roland Steiner  <rolandsteiner@chromium.org>
    220
  • trunk/Source/WebCore/ChangeLog

    r90003 r90004  
     12011-06-29  Hayato Ito  <hayato@chromium.org>
     2
     3        Reviewed by Hajime Morita.
     4
     5        Make a shadow host transfer a focus to the first focusable element in the shadow root when its focus() is called.
     6        https://bugs.webkit.org/show_bug.cgi?id=62358.
     7
     8        This patch doesn't take an effect on the following elements to keep a compatibility.
     9        - <input>, <textarea>, <video> and <audio> elements
     10        We'll address these elements separately after re-targeting focus events
     11        (bug 61421) is implemented.
     12
     13        A shadow root's <content> is not considered in this patch.
     14        That should be addressed in another patch. See bug 63522.
     15
     16        Test: fast/dom/shadow/shadow-host-transfer-focus.html
     17
     18        * dom/Element.cpp:
     19        (WebCore::Element::focus):
     20        * page/FocusController.cpp:
     21        (WebCore::shadowRoot):
     22        (WebCore::isTreeScopeOwner):
     23        (WebCore::FocusController::transferFocusToElementInShadowRoot):
     24        (WebCore::hasCustomFocusLogic):
     25        (WebCore::FocusController::findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot):
     26        (WebCore::FocusController::advanceFocusInDocumentOrder):
     27        (WebCore::ownerOfTreeScope):
     28        (WebCore::FocusController::findFocusableNodeAcrossTreeScope):
     29        * page/FocusController.h:
     30
    1312011-06-29  Ryan Sleevi  <rsleevi@chromium.org>
    232
  • trunk/Source/WebCore/dom/Element.cpp

    r89989 r90004  
    16111611        // does not make sense to continue and update appearence.
    16121612        protect = this;
     1613        if (shadowRoot() && page->focusController()->transferFocusToElementInShadowRoot(this, restorePreviousSelection))
     1614            return;
    16131615        if (!page->focusController()->setFocusedNode(this, doc->frame()))
    16141616            return;
  • trunk/Source/WebCore/page/FocusController.cpp

    r88421 r90004  
    147147}
    148148
    149 inline static ShadowRoot* shadowRoot(Node* node)
     149static inline ShadowRoot* shadowRoot(Node* node)
    150150{
    151151    return node->isElementNode() ? toElement(node)->shadowRoot() : 0;
    152152}
    153153
    154 inline static bool isTreeScopeOwner(Node* node)
     154static inline bool isTreeScopeOwner(Node* node)
    155155{
    156156    return node && (node->isFrameOwnerElement() || shadowRoot(node));
    157157}
    158158
    159 Node* FocusController::deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event)
     159bool FocusController::transferFocusToElementInShadowRoot(Element* shadowHost, bool restorePreviousSelection)
     160{
     161    ASSERT(shadowRoot(shadowHost));
     162    Node* node = findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot(FocusDirectionForward, shadowHost, 0);
     163    if (shadowHost == node)
     164        return false;
     165    toElement(node)->focus(restorePreviousSelection);
     166    return true;
     167}
     168
     169static inline bool hasCustomFocusLogic(Node* node)
     170{
     171    return node->hasTagName(inputTag) || node->hasTagName(textareaTag) || node->hasTagName(videoTag) || node->hasTagName(audioTag);
     172}
     173
     174Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot(FocusDirection direction, Node* node, KeyboardEvent* event)
    160175{
    161176    // The node we found might be a HTMLFrameOwnerElement or a shadow host, so descend down the tree until we find either:
     
    171186            foundNode = findFocusableNode(direction, document, 0, event);
    172187        } else {
     188            // FIXME: Until a focus re-targeting (bug 61421) is implemented,
     189            // skipping these elements is the safest way to keep a compatibility.
     190            if (hasCustomFocusLogic(node))
     191                break;
    173192            ASSERT(shadowRoot(node));
    174             // FIXME: Some elements (e.g. HTMLInputElement and HTMLTextAreaElement) do extra work in their focus() methods.
    175             // Skipping these elements is the safest fix until we find a better way.
    176             if (node->hasTagName(inputTag) || node->hasTagName(textareaTag))
    177                 break;
    178193            foundNode = findFocusableNode(direction, shadowRoot(node), 0, event);
    179194        }
     
    245260        // Chrome doesn't want focus, so we should wrap focus.
    246261        node = findFocusableNode(direction, m_page->mainFrame()->document(), 0, event);
    247         node = deepFocusableNode(direction, node, event);
     262        node = findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot(direction, node, event);
    248263
    249264        if (!node)
     
    295310    static_cast<Element*>(node)->focus(false);
    296311    return true;
     312}
     313
     314static inline Node* ownerOfTreeScope(TreeScope* scope)
     315{
     316    ASSERT(scope);
     317    if (scope->isShadowRoot())
     318        return scope->shadowHost();
     319    if (scope->document()->frame())
     320        return scope->document()->frame()->ownerElement();
     321    return 0;
    297322}
    298323
     
    308333        scope = owner->treeScope();
    309334    }
    310     node = deepFocusableNode(direction, node, event);
     335    node = findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot(direction, node, event);
    311336    return node;
    312337}
     
    430455    startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : std::numeric_limits<short>::max();
    431456    return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
    432 }
    433 
    434 Node* FocusController::ownerOfTreeScope(TreeScope* scope)
    435 {
    436     ASSERT(scope);
    437     if (scope->isShadowRoot())
    438         return scope->shadowHost();
    439     if (scope->document()->frame())
    440         return scope->document()->frame()->ownerElement();
    441     return 0;
    442457}
    443458
  • trunk/Source/WebCore/page/FocusController.h

    r88421 r90004  
    3535
    3636struct FocusCandidate;
     37class Element;
    3738class Frame;
    3839class IntRect;
     
    6263    bool isFocused() const { return m_isFocused; }
    6364
     65    bool transferFocusToElementInShadowRoot(Element* shadowHost, bool restorePreviousSelection);
     66
    6467private:
    6568    bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*);
     
    6770
    6871    Node* findFocusableNodeAcrossTreeScope(FocusDirection, TreeScope* startScope, Node* start, KeyboardEvent*);
    69     Node* deepFocusableNode(FocusDirection, Node*, KeyboardEvent*);
    70     Node* ownerOfTreeScope(TreeScope*);
     72    Node* findFocusableNodeDecendingDownIntoFrameDocumentOrShadowRoot(FocusDirection, Node*, KeyboardEvent*);
    7173
    7274    // Searches through the given tree scope, starting from start node, for the next/previous selectable element that comes after/before start node.
Note: See TracChangeset for help on using the changeset viewer.