Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / html / HTMLSummaryElement.cpp
index 8bc6aff..13d3cf4 100644 (file)
 #include "config.h"
 #include "HTMLSummaryElement.h"
 
-#if ENABLE(DETAILS)
-
+#if ENABLE(DETAILS_ELEMENT)
 #include "DetailsMarkerControl.h"
 #include "HTMLDetailsElement.h"
-#include "HTMLNames.h"
+#include "HTMLFormControlElement.h"
+#include "HTMLSlotElement.h"
+#include "KeyboardEvent.h"
 #include "MouseEvent.h"
 #include "PlatformMouseEvent.h"
-#include "RenderSummary.h"
-#include "ShadowContentElement.h"
+#include "RenderBlockFlow.h"
+#include "ShadowRoot.h"
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
-class SummaryContentElement : public ShadowContentElement {
-public:
-    static PassRefPtr<SummaryContentElement> create(Document*);
-
-private:
-    SummaryContentElement(Document* document)
-        : ShadowContentElement(document)
-    {
-    }
-
-    virtual bool shouldInclude(Node*) { return true; }
-};
+Ref<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document& document)
+{
+    Ref<HTMLSummaryElement> summary = adoptRef(*new HTMLSummaryElement(tagName, document));
+    summary->addShadowRoot(ShadowRoot::create(document, ShadowRoot::Type::UserAgent));
+    return summary;
+}
 
-PassRefPtr<SummaryContentElement> SummaryContentElement::create(Document* document)
+HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document& document)
+    : HTMLElement(tagName, document)
 {
-    return adoptRef(new SummaryContentElement(document));
+    ASSERT(hasTagName(summaryTag));
 }
 
-PassRefPtr<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document* document)
+RenderPtr<RenderElement> HTMLSummaryElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
 {
-    RefPtr<HTMLSummaryElement> result = adoptRef(new HTMLSummaryElement(tagName, document));
-    result->createShadowSubtree();
-    return result;
+    return createRenderer<RenderBlockFlow>(*this, WTFMove(style));
 }
 
-HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document* document)
-    : HTMLElement(tagName, document)
+void HTMLSummaryElement::didAddUserAgentShadowRoot(ShadowRoot* root)
 {
-    ASSERT(hasTagName(summaryTag));
+    root->appendChild(DetailsMarkerControl::create(document()), ASSERT_NO_EXCEPTION);
+    root->appendChild(HTMLSlotElement::create(slotTag, document()));
 }
 
-RenderObject* HTMLSummaryElement::createRenderer(RenderArena* arena, RenderStyle*)
+HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
 {
-    return new (arena) RenderSummary(this);
+    auto* parent = parentElement();
+    if (parent && is<HTMLDetailsElement>(*parent))
+        return downcast<HTMLDetailsElement>(parent);
+    // Fallback summary element is in the shadow tree.
+    auto* host = shadowHost();
+    if (host && is<HTMLDetailsElement>(*host))
+        return downcast<HTMLDetailsElement>(host);
+    return nullptr;
 }
 
-void HTMLSummaryElement::createShadowSubtree()
+bool HTMLSummaryElement::isActiveSummary() const
 {
-    ExceptionCode ec = 0;
-    ensureShadowRoot()->appendChild(DetailsMarkerControl::create(document()), ec, true);
-    ensureShadowRoot()->appendChild(SummaryContentElement::create(document()), ec, true);
+    HTMLDetailsElement* details = detailsElement();
+    if (!details)
+        return false;
+    return details->isActiveSummary(*this);
 }
 
-HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
+static bool isClickableControl(Node* node)
 {
-    Element* mayDetails = toElement(parentNodeForRenderingAndStyle());
-    if (!mayDetails || !mayDetails->hasTagName(detailsTag))
-        return 0;
-    return static_cast<HTMLDetailsElement*>(mayDetails);
+    ASSERT(node);
+    if (!is<Element>(*node))
+        return false;
+    Element& element = downcast<Element>(*node);
+    if (is<HTMLFormControlElement>(element))
+        return true;
+    Element* host = element.shadowHost();
+    return host && is<HTMLFormControlElement>(host);
 }
 
-bool HTMLSummaryElement::isMainSummary() const
+bool HTMLSummaryElement::supportsFocus() const
 {
-    if (HTMLDetailsElement* details = detailsElement())
-        return details->mainSummary() == this;
-    return 0;
+    return isActiveSummary();
 }
 
 void HTMLSummaryElement::defaultEventHandler(Event* event)
 {
+    if (isActiveSummary() && renderer()) {
+        if (event->type() == eventNames().DOMActivateEvent && !isClickableControl(event->target()->toNode())) {
+            if (HTMLDetailsElement* details = detailsElement())
+                details->toggleOpen();
+            event->setDefaultHandled();
+            return;
+        }
+
+        if (is<KeyboardEvent>(*event)) {
+            KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event);
+            if (keyboardEvent.type() == eventNames().keydownEvent && keyboardEvent.keyIdentifier() == "U+0020") {
+                setActive(true, true);
+                // No setDefaultHandled() - IE dispatches a keypress in this case.
+                return;
+            }
+            if (keyboardEvent.type() == eventNames().keypressEvent) {
+                switch (keyboardEvent.charCode()) {
+                case '\r':
+                    dispatchSimulatedClick(event);
+                    keyboardEvent.setDefaultHandled();
+                    return;
+                case ' ':
+                    // Prevent scrolling down the page.
+                    keyboardEvent.setDefaultHandled();
+                    return;
+                }
+            }
+            if (keyboardEvent.type() == eventNames().keyupEvent && keyboardEvent.keyIdentifier() == "U+0020") {
+                if (active())
+                    dispatchSimulatedClick(event);
+                keyboardEvent.setDefaultHandled();
+                return;
+            }
+        }
+    }
+
     HTMLElement::defaultEventHandler(event);
-    if (!isMainSummary() || !renderer() || !renderer()->isSummary() || !event->isMouseEvent() || event->type() != eventNames().clickEvent || event->defaultHandled())
-        return;
+}
 
-    MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
-    if (mouseEvent->button() != LeftButton)
-        return;
+bool HTMLSummaryElement::willRespondToMouseClickEvents()
+{
+    if (isActiveSummary() && renderer())
+        return true;
 
-    if (HTMLDetailsElement* details = detailsElement())
-        details->toggleOpen();
-    event->setDefaultHandled();
+    return HTMLElement::willRespondToMouseClickEvents();
 }
 
 }