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

Changeset 242661 in webkit


Ignore:
Timestamp:
Mar 8, 2019, 3:51:05 PM (7 years ago)
Author:
Alan Bujtas
Message:

[ContentChangeObserver] Expand "isConsideredClickable" to descendants
https://bugs.webkit.org/show_bug.cgi?id=195478
<rdar://problem/48724935>

Reviewed by Simon Fraser.

Source/WebCore:

In StyleChangeScope we try to figure out whether newly visible content should stick (menu panes etc) by checking if it is clickable.
This works fine as long as all the visible elements are gaining new renderers through this style update processs.
However when an element becomes visible by a change other than display: (not)none, it's not sufficient to just check the element itself,
since it might not respond to click at all, while its descendants do.
A concrete example is a max-height value change on usps.com, where the max-height is on a container (menu pane).
This container itself is not clickable while most of its children are (menu items).

Test: fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container.html

  • page/ios/ContentChangeObserver.cpp:

(WebCore::ContentChangeObserver::StyleChangeScope::StyleChangeScope):
(WebCore::ContentChangeObserver::StyleChangeScope::~StyleChangeScope):
(WebCore::ContentChangeObserver::StyleChangeScope::isConsideredHidden const):
(WebCore::ContentChangeObserver::StyleChangeScope::isConsideredClickable const):
(WebCore::isConsideredHidden): Deleted.

  • page/ios/ContentChangeObserver.h:

LayoutTests:

  • fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container-expected.txt: Added.
  • fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container.html: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r242644 r242661  
     12019-03-08  Zalan Bujtas  <zalan@apple.com>
     2
     3        [ContentChangeObserver] Expand "isConsideredClickable" to descendants
     4        https://bugs.webkit.org/show_bug.cgi?id=195478
     5        <rdar://problem/48724935>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container-expected.txt: Added.
     10        * fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container.html: Added.
     11
    1122019-03-08  Truitt Savell  <tsavell@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r242656 r242661  
     12019-03-08  Zalan Bujtas  <zalan@apple.com>
     2
     3        [ContentChangeObserver] Expand "isConsideredClickable" to descendants
     4        https://bugs.webkit.org/show_bug.cgi?id=195478
     5        <rdar://problem/48724935>
     6
     7        Reviewed by Simon Fraser.
     8
     9        In StyleChangeScope we try to figure out whether newly visible content should stick (menu panes etc) by checking if it is clickable.
     10        This works fine as long as all the visible elements are gaining new renderers through this style update processs.
     11        However when an element becomes visible by a change other than display: (not)none, it's not sufficient to just check the element itself,
     12        since it might not respond to click at all, while its descendants do.
     13        A concrete example is a max-height value change on usps.com, where the max-height is on a container (menu pane).
     14        This container itself is not clickable while most of its children are (menu items).   
     15
     16        Test: fast/events/touch/ios/content-observation/clickable-content-is-inside-a-container.html
     17
     18        * page/ios/ContentChangeObserver.cpp:
     19        (WebCore::ContentChangeObserver::StyleChangeScope::StyleChangeScope):
     20        (WebCore::ContentChangeObserver::StyleChangeScope::~StyleChangeScope):
     21        (WebCore::ContentChangeObserver::StyleChangeScope::isConsideredHidden const):
     22        (WebCore::ContentChangeObserver::StyleChangeScope::isConsideredClickable const):
     23        (WebCore::isConsideredHidden): Deleted.
     24        * page/ios/ContentChangeObserver.h:
     25
    1262019-03-08  Zalan Bujtas  <zalan@apple.com>
    227
  • trunk/Source/WebCore/page/ios/ContentChangeObserver.cpp

    r242656 r242661  
    3434#include "NodeRenderStyle.h"
    3535#include "Page.h"
     36#include "RenderDescendantIterator.h"
    3637#include "Settings.h"
    3738
     
    296297}
    297298
    298 static bool isConsideredHidden(const Element& element)
    299 {
    300     if (!element.renderStyle())
    301         return true;
    302 
    303     auto& style = *element.renderStyle();
     299ContentChangeObserver::StyleChangeScope::StyleChangeScope(Document& document, const Element& element)
     300    : m_contentChangeObserver(document.contentChangeObserver())
     301    , m_element(element)
     302    , m_hadRenderer(element.renderer())
     303{
     304    if (m_contentChangeObserver.isObservingContentChanges() && !m_contentChangeObserver.hasVisibleChangeState())
     305        m_wasHidden = isConsideredHidden();
     306}
     307
     308ContentChangeObserver::StyleChangeScope::~StyleChangeScope()
     309{
     310    auto changedFromHiddenToVisible = [&] {
     311        return m_wasHidden && !isConsideredHidden();
     312    };
     313   
     314    if (changedFromHiddenToVisible() && isConsideredClickable())
     315        m_contentChangeObserver.contentVisibilityDidChange();
     316}
     317
     318bool ContentChangeObserver::StyleChangeScope::isConsideredHidden() const
     319{
     320    if (!m_element.renderStyle())
     321        return true;
     322
     323    auto& style = *m_element.renderStyle();
    304324    if (style.display() == DisplayType::None)
    305325        return true;
     
    330350}
    331351
    332 ContentChangeObserver::StyleChangeScope::StyleChangeScope(Document& document, const Element& element)
    333     : m_contentChangeObserver(document.contentChangeObserver())
    334     , m_element(element)
    335 {
    336     auto qualifiesForVisibilityCheck = [&] {
    337         if (m_element.isInUserAgentShadowTree())
    338             return false;
    339         if (!const_cast<Element&>(m_element).willRespondToMouseClickEvents())
    340             return false;
    341         return true;
    342     };
    343 
    344     auto needsObserving = m_contentChangeObserver.isObservingContentChanges() && !m_contentChangeObserver.hasVisibleChangeState() && qualifiesForVisibilityCheck();
    345     if (needsObserving)
    346         m_wasHidden = isConsideredHidden(m_element);
    347 }
    348 
    349 ContentChangeObserver::StyleChangeScope::~StyleChangeScope()
    350 {
    351     if (!m_wasHidden || isConsideredHidden(m_element))
    352         return;
    353 
    354     m_contentChangeObserver.contentVisibilityDidChange();
     352bool ContentChangeObserver::StyleChangeScope::isConsideredClickable() const
     353{
     354    if (m_element.isInUserAgentShadowTree())
     355        return false;
     356    if (!m_hadRenderer)
     357        return const_cast<Element&>(m_element).willRespondToMouseClickEvents();
     358    ASSERT(m_element.renderer());
     359    if (const_cast<Element&>(m_element).willRespondToMouseClickEvents())
     360        return true;
     361    // In case when the visible content already had renderers it's not sufficient to check the "newly visible" element only since it might just be the container for the clickable content. 
     362    for (auto& descendant : descendantsOfType<RenderElement>(*m_element.renderer())) {
     363        if (descendant.element()->willRespondToMouseClickEvents())
     364            return true;
     365    }
     366    return false;
    355367}
    356368
  • trunk/Source/WebCore/page/ios/ContentChangeObserver.h

    r242656 r242661  
    5959
    6060    private:
     61        bool isConsideredHidden() const;
     62        bool isConsideredClickable() const;
     63
    6164        ContentChangeObserver& m_contentChangeObserver;
    6265        const Element& m_element;
    6366        bool m_wasHidden { false };
     67        bool m_hadRenderer { false };
    6468    };
    6569
Note: See TracChangeset for help on using the changeset viewer.