Changeset 93276 in webkit


Ignore:
Timestamp:
Aug 17, 2011 7:41:10 PM (13 years ago)
Author:
hayato@chromium.org
Message:

Implement proper handling of focus/blur events in regard to shadow DOM boundaries.
https://bugs.webkit.org/show_bug.cgi?id=61421

Reviewed by Dimitri Glazkov.

Introduces FocusEventDispatchMediator/BlurEventDispatchMediator so
that focus/blue events are stopped at the lowest common shadow boundary.

Source/WebCore:

  • dom/Document.cpp:

(WebCore::Document::setFocusedNode):

  • dom/Event.cpp:

(WebCore::FocusEventDispatchMediator::create):
(WebCore::FocusEventDispatchMediator::FocusEventDispatchMediator):
(WebCore::FocusEventDispatchMediator::dispatchEvent):
(WebCore::BlurEventDispatchMediator::create):
(WebCore::BlurEventDispatchMediator::BlurEventDispatchMediator):
(WebCore::BlurEventDispatchMediator::dispatchEvent):

  • dom/Event.h:
  • dom/Node.cpp:

(WebCore::Node::dispatchFocusEvent):
(WebCore::Node::dispatchBlurEvent):

  • dom/Node.h:
  • html/HTMLFormControlElement.cpp:

(WebCore::HTMLFormControlElement::dispatchBlurEvent):

  • html/HTMLFormControlElement.h:
  • html/HTMLSelectElement.cpp:

(WebCore::HTMLSelectElement::dispatchFocusEvent):
(WebCore::HTMLSelectElement::dispatchBlurEvent):

  • html/HTMLSelectElement.h:
  • html/HTMLTextFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
(WebCore::HTMLTextFormControlElement::dispatchBlurEvent):

  • html/HTMLTextFormControlElement.h:
  • page/FocusController.cpp:

(WebCore::dispatchEventsOnWindowAndFocusedNode):

LayoutTests:

  • fast/dom/shadow/shadow-boundary-events.html:
Location:
trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r93275 r93276  
     12011-08-17  Hayato Ito  <hayato@chromium.org>
     2
     3        Implement proper handling of focus/blur events in regard to shadow DOM boundaries.
     4        https://bugs.webkit.org/show_bug.cgi?id=61421
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        Introduces FocusEventDispatchMediator/BlurEventDispatchMediator so
     9        that focus/blue events are stopped at the lowest common shadow boundary.
     10
     11        * fast/dom/shadow/shadow-boundary-events.html:
     12
    1132011-08-17  Ben Wells  <benwells@chromium.org>
    214
  • trunk/LayoutTests/fast/dom/shadow/shadow-boundary-events-expected.txt

    r93038 r93276  
    6969PASS dispatchedEvent("focusin") is ["divL(@divL)", "shadowK(@shadowK)", "shadowK(@divJ)"]
    7070PASS dispatchedEvent("focusout") is ["divH(@divH)", "shadowG(@shadowG)", "shadowF(@shadowF)", "shadowF(@divE)"]
     71
     72Move focus from a node to its sibling node. All nodes are outside of shadow boundary.
     73Moving focus from divB to divC
     74PASS dispatchedEvent("focus") is ["divC(@divA)(capturing phase)", "divC(@divC)"]
     75PASS dispatchedEvent("blur") is ["divB(@divA)(capturing phase)", "divB(@divB)"]
     76
     77Old focused node and new focused node exist in separated subtrees, crossing shadow boundaries. Making sure that an event is not dispatched beyond the lowest common boundary.
     78Moving focus from shadowD/shadowF/shadowG/divH to shadowD/shadowK/divL
     79PASS dispatchedEvent("focus") is ["shadowK(@divJ)(capturing phase)", "shadowK(@shadowK)(capturing phase)", "divL(@divL)"]
     80PASS dispatchedEvent("blur") is ["shadowF(@divE)(capturing phase)", "shadowF(@shadowF)(capturing phase)", "shadowG(@shadowG)(capturing phase)", "divH(@divH)"]
    7181PASS successfullyParsed is true
    7282
  • trunk/LayoutTests/fast/dom/shadow/shadow-boundary-events.html

    r93038 r93276  
    5858    if (event.currentTarget)
    5959        eventString += '(@' + event.currentTarget.id + ')';
     60    if (event.eventPhase == 1)
     61        eventString += '(capturing phase)';
    6062    eventRecords[eventType].push(eventString);
    6163}
     
    98100        element.addEventListener('focusin', recordEvent, false);
    99101        element.addEventListener('focusout', recordEvent, false);
     102        element.addEventListener('focus', recordEvent, true);  // capturing phase
     103        element.addEventListener('blur', recordEvent, true);  // capturing phase
    100104    }
    101105}
     
    192196    // Omitted test cases where either a oldFocusedNode or newFocusedNode is an ancestor of the other.
    193197    // Due to a focus transfer mechanism on shadow hosts, a focused node should be a leaf node in general.
     198
     199    // Test for focus/blur events. Event listners should be registerd on captureing phase.
     200    moveFocus('divB', 'divC',
     201              'Move focus from a node to its sibling node. All nodes are outside of shadow boundary.');
     202    shouldBe('dispatchedEvent("focus")', '["divC(@divA)(capturing phase)", "divC(@divC)"]');
     203    shouldBe('dispatchedEvent("blur")', '["divB(@divA)(capturing phase)", "divB(@divB)"]');
     204
     205    moveFocus('shadowD/shadowF/shadowG/divH', 'shadowD/shadowK/divL',
     206              'Old focused node and new focused node exist in separated subtrees, crossing shadow boundaries. Making sure that an event is not dispatched beyond the lowest common boundary.');
     207    shouldBe('dispatchedEvent("focus")', '["shadowK(@divJ)(capturing phase)", "shadowK(@shadowK)(capturing phase)", "divL(@divL)"]');
     208    shouldBe('dispatchedEvent("blur")', '["shadowF(@divE)(capturing phase)", "shadowF(@shadowF)(capturing phase)", "shadowG(@shadowG)(capturing phase)", "divH(@divH)"]');
    194209}
    195210
  • trunk/Source/WebCore/ChangeLog

    r93275 r93276  
     12011-08-17  Hayato Ito  <hayato@chromium.org>
     2
     3        Implement proper handling of focus/blur events in regard to shadow DOM boundaries.
     4        https://bugs.webkit.org/show_bug.cgi?id=61421
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        Introduces FocusEventDispatchMediator/BlurEventDispatchMediator so
     9        that focus/blue events are stopped at the lowest common shadow boundary.
     10
     11        * dom/Document.cpp:
     12        (WebCore::Document::setFocusedNode):
     13        * dom/Event.cpp:
     14        (WebCore::FocusEventDispatchMediator::create):
     15        (WebCore::FocusEventDispatchMediator::FocusEventDispatchMediator):
     16        (WebCore::FocusEventDispatchMediator::dispatchEvent):
     17        (WebCore::BlurEventDispatchMediator::create):
     18        (WebCore::BlurEventDispatchMediator::BlurEventDispatchMediator):
     19        (WebCore::BlurEventDispatchMediator::dispatchEvent):
     20        * dom/Event.h:
     21        * dom/Node.cpp:
     22        (WebCore::Node::dispatchFocusEvent):
     23        (WebCore::Node::dispatchBlurEvent):
     24        * dom/Node.h:
     25        * html/HTMLFormControlElement.cpp:
     26        (WebCore::HTMLFormControlElement::dispatchBlurEvent):
     27        * html/HTMLFormControlElement.h:
     28        * html/HTMLSelectElement.cpp:
     29        (WebCore::HTMLSelectElement::dispatchFocusEvent):
     30        (WebCore::HTMLSelectElement::dispatchBlurEvent):
     31        * html/HTMLSelectElement.h:
     32        * html/HTMLTextFormControlElement.cpp:
     33        (WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
     34        (WebCore::HTMLTextFormControlElement::dispatchBlurEvent):
     35        * html/HTMLTextFormControlElement.h:
     36        * page/FocusController.cpp:
     37        (WebCore::dispatchEventsOnWindowAndFocusedNode):
     38
    1392011-08-17  Ben Wells  <benwells@chromium.org>
    240
  • trunk/Source/WebCore/dom/Document.cpp

    r93269 r93276  
    31263126
    31273127        // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
    3128         oldFocusedNode->dispatchBlurEvent();
     3128        oldFocusedNode->dispatchBlurEvent(newFocusedNode);
    31293129
    31303130        if (m_focusedNode) {
     
    31703170
    31713171        // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
    3172         m_focusedNode->dispatchFocusEvent();
     3172        m_focusedNode->dispatchFocusEvent(oldFocusedNode);
    31733173
    31743174        if (m_focusedNode != newFocusedNode) {
  • trunk/Source/WebCore/dom/Event.cpp

    r92365 r93276  
    309309}
    310310
     311PassRefPtr<FocusEventDispatchMediator> FocusEventDispatchMediator::create(PassRefPtr<Node> oldFocusedNode)
     312{
     313    return adoptRef(new FocusEventDispatchMediator(oldFocusedNode));
     314}
     315
     316FocusEventDispatchMediator::FocusEventDispatchMediator(PassRefPtr<Node> oldFocusedNode)
     317    : EventDispatchMediator(Event::create(eventNames().focusEvent, false, false))
     318    , m_oldFocusedNode(oldFocusedNode)
     319{
     320}
     321
     322bool FocusEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
     323{
     324    dispatcher->adjustRelatedTarget(event(), m_oldFocusedNode);
     325    return EventDispatchMediator::dispatchEvent(dispatcher);
     326}
     327
     328PassRefPtr<BlurEventDispatchMediator> BlurEventDispatchMediator::create(PassRefPtr<Node> newFocusedNode)
     329{
     330    return adoptRef(new BlurEventDispatchMediator(newFocusedNode));
     331}
     332
     333BlurEventDispatchMediator::BlurEventDispatchMediator(PassRefPtr<Node> newFocusedNode)
     334    : EventDispatchMediator(Event::create(eventNames().blurEvent, false, false))
     335    , m_newFocusedNode(newFocusedNode)
     336{
     337}
     338
     339bool BlurEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
     340{
     341    dispatcher->adjustRelatedTarget(event(), m_newFocusedNode);
     342    return EventDispatchMediator::dispatchEvent(dispatcher);
     343}
     344
     345
    311346} // namespace WebCore
  • trunk/Source/WebCore/dom/Event.h

    r92450 r93276  
    231231}
    232232
     233class FocusEventDispatchMediator : public EventDispatchMediator {
     234public:
     235    static PassRefPtr<FocusEventDispatchMediator> create(PassRefPtr<Node> oldFocusedNode);
     236private:
     237    explicit FocusEventDispatchMediator(PassRefPtr<Node> oldFocusedNode);
     238    virtual bool dispatchEvent(EventDispatcher*) const;
     239    RefPtr<Node> m_oldFocusedNode;
     240};
     241
     242class BlurEventDispatchMediator : public EventDispatchMediator {
     243public:
     244    static PassRefPtr<BlurEventDispatchMediator> create(PassRefPtr<Node> newFocusedNode);
     245private:
     246    explicit BlurEventDispatchMediator(PassRefPtr<Node> newFocusedNode);
     247    virtual bool dispatchEvent(EventDispatcher*) const;
     248    RefPtr<Node> m_newFocusedNode;
     249};
     250
    233251} // namespace WebCore
    234252
  • trunk/Source/WebCore/dom/Node.cpp

    r93071 r93276  
    27782778}
    27792779
    2780 void Node::dispatchFocusEvent()
     2780void Node::dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode)
    27812781{
    27822782    if (document()->page())
    27832783        document()->page()->chrome()->client()->elementDidFocus(this);
    27842784   
    2785     dispatchEvent(Event::create(eventNames().focusEvent, false, false));
     2785    EventDispatcher::dispatchEvent(this, FocusEventDispatchMediator::create(oldFocusedNode));
    27862786}
    27872787
     
    27902790}
    27912791
    2792 void Node::dispatchBlurEvent()
     2792void Node::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
    27932793{
    27942794    if (document()->page())
    27952795        document()->page()->chrome()->client()->elementDidBlur(this);
    2796    
    2797     dispatchEvent(Event::create(eventNames().blurEvent, false, false));
     2796
     2797    EventDispatcher::dispatchEvent(this, BlurEventDispatchMediator::create(newFocusedNode));
    27982798}
    27992799
  • trunk/Source/WebCore/dom/Node.h

    r93071 r93276  
    563563    void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true);
    564564
    565     virtual void dispatchFocusEvent();
     565    virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode);
    566566    virtual void willBlur();
    567     virtual void dispatchBlurEvent();
     567    virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
    568568    virtual void dispatchChangeEvent();
    569569    virtual void dispatchInputEvent();
  • trunk/Source/WebCore/html/HTMLFormControlElement.cpp

    r90849 r93276  
    431431}
    432432
    433 void HTMLFormControlElement::dispatchBlurEvent()
    434 {
    435     HTMLElement::dispatchBlurEvent();
     433void HTMLFormControlElement::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
     434{
     435    HTMLElement::dispatchBlurEvent(newFocusedNode);
    436436    hideVisibleValidationMessage();
    437437}
  • trunk/Source/WebCore/html/HTMLFormControlElement.h

    r90849 r93276  
    122122    virtual void recalcStyle(StyleChange);
    123123
    124     virtual void dispatchBlurEvent();
     124    virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
    125125    virtual void detach();
    126126
  • trunk/Source/WebCore/html/HTMLSelectElement.cpp

    r89332 r93276  
    368368}
    369369
    370 void HTMLSelectElement::dispatchFocusEvent()
     370void HTMLSelectElement::dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode)
    371371{
    372372    SelectElement::dispatchFocusEvent(m_data, this);
    373     HTMLFormControlElementWithState::dispatchFocusEvent();
    374 }
    375 
    376 void HTMLSelectElement::dispatchBlurEvent()
     373    HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedNode);
     374}
     375
     376void HTMLSelectElement::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
    377377{
    378378    SelectElement::dispatchBlurEvent(m_data, this);
    379     HTMLFormControlElementWithState::dispatchBlurEvent();
     379    HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedNode);
    380380}
    381381
  • trunk/Source/WebCore/html/HTMLSelectElement.h

    r86135 r93276  
    104104    virtual void recalcStyle(StyleChange);
    105105
    106     virtual void dispatchFocusEvent();
    107     virtual void dispatchBlurEvent();
     106    virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode);
     107    virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
    108108   
    109109    virtual bool canStartSelection() const { return false; }
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r92088 r93276  
    6565}
    6666
    67 void HTMLTextFormControlElement::dispatchFocusEvent()
     67void HTMLTextFormControlElement::dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode)
    6868{
    6969    if (supportsPlaceholder())
    7070        updatePlaceholderVisibility(false);
    7171    handleFocusEvent();
    72     HTMLFormControlElementWithState::dispatchFocusEvent();
    73 }
    74 
    75 void HTMLTextFormControlElement::dispatchBlurEvent()
     72    HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedNode);
     73}
     74
     75void HTMLTextFormControlElement::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
    7676{
    7777    if (supportsPlaceholder())
    7878        updatePlaceholderVisibility(false);
    7979    handleBlurEvent();
    80     HTMLFormControlElementWithState::dispatchBlurEvent();
     80    HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedNode);
    8181}
    8282
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.h

    r92088 r93276  
    102102    TextFieldSelectionDirection computeSelectionDirection() const;
    103103
    104     virtual void dispatchFocusEvent();
    105     virtual void dispatchBlurEvent();
     104    virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode);
     105    virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
    106106
    107107    bool isPlaceholderEmpty() const;
  • trunk/Source/WebCore/page/FocusController.cpp

    r93270 r93276  
    7878
    7979    if (!focused && document->focusedNode())
    80         document->focusedNode()->dispatchBlurEvent();
     80        document->focusedNode()->dispatchBlurEvent(0);
    8181    document->dispatchWindowEvent(Event::create(focused ? eventNames().focusEvent : eventNames().blurEvent, false, false));
    8282    if (focused && document->focusedNode())
    83         document->focusedNode()->dispatchFocusEvent();
     83        document->focusedNode()->dispatchFocusEvent(0);
    8484}
    8585
Note: See TracChangeset for help on using the changeset viewer.