diff options
Diffstat (limited to 'Source/WebCore/html/shadow')
33 files changed, 1983 insertions, 2602 deletions
diff --git a/Source/WebCore/html/shadow/AutoFillButtonElement.cpp b/Source/WebCore/html/shadow/AutoFillButtonElement.cpp new file mode 100644 index 000000000..c021daab7 --- /dev/null +++ b/Source/WebCore/html/shadow/AutoFillButtonElement.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AutoFillButtonElement.h" + +#include "Event.h" +#include "EventNames.h" +#include "HTMLNames.h" +#include "MouseEvent.h" +#include "TextFieldInputType.h" + +namespace WebCore { + +using namespace HTMLNames; + +Ref<AutoFillButtonElement> AutoFillButtonElement::create(Document& document, AutoFillButtonOwner& owner) +{ + return adoptRef(*new AutoFillButtonElement(document, owner)); +} + +AutoFillButtonElement::AutoFillButtonElement(Document& document, AutoFillButtonOwner& owner) + : HTMLDivElement(divTag, document) + , m_owner(owner) +{ +} + +void AutoFillButtonElement::defaultEventHandler(Event& event) +{ + if (!is<MouseEvent>(event)) { + if (!event.defaultHandled()) + HTMLDivElement::defaultEventHandler(event); + return; + } + + MouseEvent& mouseEvent = downcast<MouseEvent>(event); + + if (mouseEvent.type() == eventNames().clickEvent) { + m_owner.autoFillButtonElementWasClicked(); + event.setDefaultHandled(); + } + + if (!event.defaultHandled()) + HTMLDivElement::defaultEventHandler(event); +} + +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/AutoFillButtonElement.h b/Source/WebCore/html/shadow/AutoFillButtonElement.h new file mode 100644 index 000000000..58c474eab --- /dev/null +++ b/Source/WebCore/html/shadow/AutoFillButtonElement.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "HTMLDivElement.h" + +namespace WebCore { + +class TextFieldInputType; + +class AutoFillButtonElement final : public HTMLDivElement { +public: + class AutoFillButtonOwner { + public: + virtual ~AutoFillButtonOwner() { } + virtual void autoFillButtonElementWasClicked() = 0; + }; + + static Ref<AutoFillButtonElement> create(Document&, AutoFillButtonOwner&); + +private: + explicit AutoFillButtonElement(Document&, AutoFillButtonOwner&); + + void defaultEventHandler(Event&) override; + + AutoFillButtonOwner& m_owner; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/ContentDistributor.cpp b/Source/WebCore/html/shadow/ContentDistributor.cpp deleted file mode 100644 index c4c77a747..000000000 --- a/Source/WebCore/html/shadow/ContentDistributor.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ContentDistributor.h" - -#include "ElementIterator.h" -#include "InsertionPoint.h" - -namespace WebCore { - -ContentDistributor::ContentDistributor() - : m_insertionPointListIsValid(true) - , m_validity(Undetermined) -{ -} - -ContentDistributor::~ContentDistributor() -{ -} - -void ContentDistributor::invalidateInsertionPointList() -{ - m_insertionPointListIsValid = false; - m_insertionPointList.clear(); -} - -const Vector<RefPtr<InsertionPoint>>& ContentDistributor::ensureInsertionPointList(ShadowRoot* shadowRoot) -{ - if (m_insertionPointListIsValid) - return m_insertionPointList; - - m_insertionPointListIsValid = true; - ASSERT(m_insertionPointList.isEmpty()); - - for (auto& element : descendantsOfType<Element>(*shadowRoot)) { - if (element.isInsertionPoint()) - m_insertionPointList.append(toInsertionPoint(&element)); - } - - return m_insertionPointList; -} - -InsertionPoint* ContentDistributor::findInsertionPointFor(const Node* key) const -{ - return m_nodeToInsertionPoint.get(key); -} - -void ContentDistributor::distribute(Element* host) -{ - ASSERT(needsDistribution()); - ASSERT(m_nodeToInsertionPoint.isEmpty()); - ASSERT(!host->containingShadowRoot() || host->containingShadowRoot()->distributor().isValid()); - - m_validity = Valid; - - if (ShadowRoot* root = host->shadowRoot()) { - const Vector<RefPtr<InsertionPoint>>& insertionPoints = ensureInsertionPointList(root); - for (size_t i = 0; i < insertionPoints.size(); ++i) { - InsertionPoint* point = insertionPoints[i].get(); - if (!point->isActive()) - continue; - - distributeSelectionsTo(point, host); - } - } -} - -bool ContentDistributor::invalidate(Element* host) -{ - ASSERT(needsInvalidation()); - bool needsReattach = (m_validity == Undetermined) || !m_nodeToInsertionPoint.isEmpty(); - - if (ShadowRoot* root = host->shadowRoot()) { - const Vector<RefPtr<InsertionPoint>>& insertionPoints = ensureInsertionPointList(root); - for (size_t i = 0; i < insertionPoints.size(); ++i) { - needsReattach = true; - insertionPoints[i]->clearDistribution(); - } - } - - m_validity = Invalidating; - m_nodeToInsertionPoint.clear(); - return needsReattach; -} - -void ContentDistributor::distributeSelectionsTo(InsertionPoint* insertionPoint, Element* host) -{ - for (Node* child = host->firstChild(); child; child = child->nextSibling()) { - ASSERT(!child->isInsertionPoint()); - - if (insertionPoint->matchTypeFor(child) != InsertionPoint::AlwaysMatches) - continue; - - m_nodeToInsertionPoint.add(child, insertionPoint); - } - - if (m_nodeToInsertionPoint.isEmpty()) - return; - insertionPoint->setHasDistribution(); -} - -void ContentDistributor::ensureDistribution(ShadowRoot* shadowRoot) -{ - ASSERT(shadowRoot); - - Vector<ShadowRoot*, 8> shadowRoots; - for (Element* current = shadowRoot->hostElement(); current; current = current->shadowHost()) { - ShadowRoot* currentRoot = current->shadowRoot(); - if (!currentRoot->distributor().needsDistribution()) - break; - shadowRoots.append(currentRoot); - } - - for (size_t i = shadowRoots.size(); i > 0; --i) - shadowRoots[i - 1]->distributor().distribute(shadowRoots[i - 1]->hostElement()); -} - -void ContentDistributor::invalidateDistribution(Element* host) -{ - bool didNeedInvalidation = needsInvalidation(); - bool needsReattach = didNeedInvalidation ? invalidate(host) : false; - - if (needsReattach) - host->setNeedsStyleRecalc(ReconstructRenderTree); - - if (didNeedInvalidation) { - ASSERT(m_validity == Invalidating); - m_validity = Invalidated; - } -} - -void ContentDistributor::didShadowBoundaryChange(Element* host) -{ - setValidity(Undetermined); - invalidateDistribution(host); -} - -} diff --git a/Source/WebCore/html/shadow/ContentDistributor.h b/Source/WebCore/html/shadow/ContentDistributor.h deleted file mode 100644 index f0ed8af0d..000000000 --- a/Source/WebCore/html/shadow/ContentDistributor.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ContentDistributor_h -#define ContentDistributor_h - -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class ContainerNode; -class Element; -class InsertionPoint; -class Node; -class ShadowRoot; - -class ContentDistributor { - WTF_MAKE_NONCOPYABLE(ContentDistributor); -public: - enum Validity { - Valid = 0, - Invalidated = 1, - Invalidating = 2, - Undetermined = 3 - }; - - ContentDistributor(); - ~ContentDistributor(); - - void invalidateInsertionPointList(); - - InsertionPoint* findInsertionPointFor(const Node* key) const; - - void distributeSelectionsTo(InsertionPoint*, Element* host); - - void invalidateDistribution(Element* host); - void didShadowBoundaryChange(Element* host); - - static void ensureDistribution(ShadowRoot*); - void distribute(Element* host); - bool needsDistribution() const; - -private: - const Vector<RefPtr<InsertionPoint>>& ensureInsertionPointList(ShadowRoot*); - - bool invalidate(Element* host); - - void setValidity(Validity validity) { m_validity = validity; } - bool isValid() const { return m_validity == Valid; } - bool needsInvalidation() const { return m_validity != Invalidated; } - - Vector<RefPtr<InsertionPoint>> m_insertionPointList; - HashMap<const Node*, RefPtr<InsertionPoint>> m_nodeToInsertionPoint; - bool m_insertionPointListIsValid; - unsigned m_validity : 2; -}; - -inline bool ContentDistributor::needsDistribution() const -{ - // During the invalidation, re-distribution should be supressed. - return m_validity != Valid && m_validity != Invalidating; -} - -} - -#endif diff --git a/Source/WebCore/html/shadow/DetailsMarkerControl.cpp b/Source/WebCore/html/shadow/DetailsMarkerControl.cpp index a48e29f49..6cdf65f1b 100644 --- a/Source/WebCore/html/shadow/DetailsMarkerControl.cpp +++ b/Source/WebCore/html/shadow/DetailsMarkerControl.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,7 +30,6 @@ */ #include "config.h" -#if ENABLE(DETAILS_ELEMENT) #include "DetailsMarkerControl.h" #include "HTMLNames.h" @@ -38,34 +38,25 @@ namespace WebCore { -using namespace HTMLNames; - -DetailsMarkerControl::DetailsMarkerControl(Document& document) - : HTMLDivElement(divTag, document) -{ -} - -RenderPtr<RenderElement> DetailsMarkerControl::createElementRenderer(PassRef<RenderStyle> style) +Ref<DetailsMarkerControl> DetailsMarkerControl::create(Document& document) { - return createRenderer<RenderDetailsMarker>(*this, std::move(style)); + return adoptRef(*new DetailsMarkerControl(document)); } -bool DetailsMarkerControl::rendererIsNeeded(const RenderStyle& style) +DetailsMarkerControl::DetailsMarkerControl(Document& document) + : HTMLDivElement(HTMLNames::divTag, document) { - return summaryElement()->isMainSummary() && HTMLDivElement::rendererIsNeeded(style); + setPseudo(AtomicString("-webkit-details-marker", AtomicString::ConstructFromLiteral)); } -const AtomicString& DetailsMarkerControl::shadowPseudoId() const +RenderPtr<RenderElement> DetailsMarkerControl::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-details-marker", AtomicString::ConstructFromLiteral)); - return pseudId; + return createRenderer<RenderDetailsMarker>(*this, WTFMove(style)); } -HTMLSummaryElement* DetailsMarkerControl::summaryElement() +bool DetailsMarkerControl::rendererIsNeeded(const RenderStyle& style) { - return toHTMLSummaryElement(shadowHost()); + return downcast<HTMLSummaryElement>(shadowHost())->isActiveSummary() && HTMLDivElement::rendererIsNeeded(style); } } - -#endif diff --git a/Source/WebCore/html/shadow/DetailsMarkerControl.h b/Source/WebCore/html/shadow/DetailsMarkerControl.h index 004dd10e3..fb16c736a 100644 --- a/Source/WebCore/html/shadow/DetailsMarkerControl.h +++ b/Source/WebCore/html/shadow/DetailsMarkerControl.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,35 +29,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DetailsMarkerControl_h -#define DetailsMarkerControl_h +#pragma once #include "HTMLDivElement.h" -#include <wtf/Forward.h> namespace WebCore { -class HTMLSummaryElement; - class DetailsMarkerControl final : public HTMLDivElement { public: - static PassRefPtr<DetailsMarkerControl> create(Document&); + static Ref<DetailsMarkerControl> create(Document&); private: DetailsMarkerControl(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; - virtual bool rendererIsNeeded(const RenderStyle&) override; - virtual const AtomicString& shadowPseudoId() const override; - - HTMLSummaryElement* summaryElement(); + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; + bool rendererIsNeeded(const RenderStyle&) override; }; -inline PassRefPtr<DetailsMarkerControl> DetailsMarkerControl::create(Document& document) -{ - return adoptRef(new DetailsMarkerControl(document)); -} - -} - -#endif +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/ImageControlsRootElement.cpp b/Source/WebCore/html/shadow/ImageControlsRootElement.cpp new file mode 100644 index 000000000..f178dfad8 --- /dev/null +++ b/Source/WebCore/html/shadow/ImageControlsRootElement.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ImageControlsRootElement.h" + +#if ENABLE(SERVICE_CONTROLS) + +namespace WebCore { + +#if !PLATFORM(MAC) +Ref<ImageControlsRootElement> ImageControlsRootElement::maybeCreate(Document& document) +{ + return adoptRef(*new ImageControlsRootElement(document)); +} +#endif + +ImageControlsRootElement::ImageControlsRootElement(Document& document) + : HTMLDivElement(HTMLNames::divTag, document) +{ +} + +ImageControlsRootElement::~ImageControlsRootElement() +{ +} + +} // namespace WebCore + +#endif // ENABLE(SERVICE_CONTROLS) diff --git a/Source/WebCore/html/shadow/ImageControlsRootElement.h b/Source/WebCore/html/shadow/ImageControlsRootElement.h new file mode 100644 index 000000000..19986dfe2 --- /dev/null +++ b/Source/WebCore/html/shadow/ImageControlsRootElement.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(SERVICE_CONTROLS) + +#include "HTMLDivElement.h" + +namespace WebCore { + +class Document; + +class ImageControlsRootElement : public HTMLDivElement { +public: + virtual ~ImageControlsRootElement(); + + static RefPtr<ImageControlsRootElement> tryCreate(Document&); + +protected: + explicit ImageControlsRootElement(Document&); + +private: + bool isImageControlsRootElement() const final { return true; } +}; + +} // namespace WebCore + +#endif // ENABLE(SERVICE_CONTROLS) diff --git a/Source/WebCore/html/shadow/InsertionPoint.cpp b/Source/WebCore/html/shadow/InsertionPoint.cpp deleted file mode 100644 index 102c8f218..000000000 --- a/Source/WebCore/html/shadow/InsertionPoint.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "InsertionPoint.h" - -#include "QualifiedName.h" -#include "StaticNodeList.h" -#include "Text.h" - -namespace WebCore { - -using namespace HTMLNames; - -InsertionPoint::InsertionPoint(const QualifiedName& tagName, Document& document) - : HTMLElement(tagName, document, CreateInsertionPoint) - , m_hasDistribution(false) -{ -} - -InsertionPoint::~InsertionPoint() -{ -} - -bool InsertionPoint::shouldUseFallbackElements() const -{ - return isActive() && !hasDistribution(); -} - -bool InsertionPoint::isActive() const -{ - if (!containingShadowRoot()) - return false; - const Node* node = parentNode(); - while (node) { - if (node->isInsertionPoint()) - return false; - - node = node->parentNode(); - } - return true; -} - -bool InsertionPoint::rendererIsNeeded(const RenderStyle& style) -{ - return !isActive() && HTMLElement::rendererIsNeeded(style); -} - -void InsertionPoint::childrenChanged(const ChildChange& change) -{ - HTMLElement::childrenChanged(change); - if (ShadowRoot* root = containingShadowRoot()) - root->invalidateDistribution(); -} - -Node::InsertionNotificationRequest InsertionPoint::insertedInto(ContainerNode& insertionPoint) -{ - HTMLElement::insertedInto(insertionPoint); - - if (ShadowRoot* root = containingShadowRoot()) { - root->distributor().didShadowBoundaryChange(root->hostElement()); - root->distributor().invalidateInsertionPointList(); - } - - return InsertionDone; -} - -void InsertionPoint::removedFrom(ContainerNode& insertionPoint) -{ - ShadowRoot* root = containingShadowRoot(); - if (!root) - root = insertionPoint.containingShadowRoot(); - - if (root && root->hostElement()) { - root->invalidateDistribution(); - root->distributor().invalidateInsertionPointList(); - } - - // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up. - clearDistribution(); - - HTMLElement::removedFrom(insertionPoint); -} - -Node* InsertionPoint::firstDistributed() const -{ - if (!m_hasDistribution) - return 0; - for (Node* current = shadowHost()->firstChild(); current; current = current->nextSibling()) { - if (matchTypeFor(current) == InsertionPoint::AlwaysMatches) - return current; - } - return 0; -} - -Node* InsertionPoint::lastDistributed() const -{ - if (!m_hasDistribution) - return 0; - for (Node* current = shadowHost()->lastChild(); current; current = current->previousSibling()) { - if (matchTypeFor(current) == InsertionPoint::AlwaysMatches) - return current; - } - return 0; -} - -Node* InsertionPoint::nextDistributedTo(const Node* node) const -{ - for (Node* current = node->nextSibling(); current; current = current->nextSibling()) { - if (matchTypeFor(current) == InsertionPoint::AlwaysMatches) - return current; - } - return 0; -} - -Node* InsertionPoint::previousDistributedTo(const Node* node) const -{ - for (Node* current = node->previousSibling(); current; current = current->previousSibling()) { - if (matchTypeFor(current) == InsertionPoint::AlwaysMatches) - return current; - } - return 0; -} - -InsertionPoint* findInsertionPointOf(const Node* projectedNode) -{ - if (ShadowRoot* shadowRoot = shadowRootOfParentForDistribution(projectedNode)) { - if (ShadowRoot* root = projectedNode->containingShadowRoot()) - ContentDistributor::ensureDistribution(root); - return shadowRoot->distributor().findInsertionPointFor(projectedNode); - } - return 0; -} - -} // namespace WebCore diff --git a/Source/WebCore/html/shadow/InsertionPoint.h b/Source/WebCore/html/shadow/InsertionPoint.h deleted file mode 100644 index c7927d273..000000000 --- a/Source/WebCore/html/shadow/InsertionPoint.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef InsertionPoint_h -#define InsertionPoint_h - -#include "ContentDistributor.h" -#include "HTMLElement.h" -#include "HTMLNames.h" -#include "ShadowRoot.h" -#include <wtf/Forward.h> - -namespace WebCore { - -class InsertionPoint : public HTMLElement { -public: - enum MatchType { - AlwaysMatches, - NeverMatches, - }; - - virtual ~InsertionPoint(); - - bool hasDistribution() const { return m_hasDistribution; } - void setHasDistribution() { m_hasDistribution = true; } - void clearDistribution() { m_hasDistribution = false; } - bool isActive() const; - - virtual MatchType matchTypeFor(Node*) const { return AlwaysMatches; } - - bool shouldUseFallbackElements() const; - - Node* firstDistributed() const; - Node* lastDistributed() const; - Node* nextDistributedTo(const Node*) const; - Node* previousDistributedTo(const Node*) const; - -protected: - InsertionPoint(const QualifiedName&, Document&); - virtual bool rendererIsNeeded(const RenderStyle&) override; - virtual void childrenChanged(const ChildChange&) override; - virtual InsertionNotificationRequest insertedInto(ContainerNode&) override; - virtual void removedFrom(ContainerNode&) override; - virtual bool isInsertionPointNode() const override { return true; } - -private: - - bool m_hasDistribution; -}; - -inline bool isInsertionPoint(const Node& node) { return node.isInsertionPoint(); } - -NODE_TYPE_CASTS(InsertionPoint); - -inline bool isActiveInsertionPoint(const Node* node) -{ - return node && node->isInsertionPoint() && toInsertionPoint(node)->isActive(); -} - -inline Node* parentNodeForDistribution(const Node* node) -{ - ASSERT(node); - - if (Node* parent = node->parentNode()) { - if (parent->isInsertionPoint() && toInsertionPoint(parent)->shouldUseFallbackElements()) - return parent->parentNode(); - return parent; - } - - return 0; -} - -inline Element* parentElementForDistribution(const Node* node) -{ - if (Node* parent = parentNodeForDistribution(node)) { - if (parent->isElementNode()) - return toElement(parent); - } - - return 0; -} - -inline ShadowRoot* shadowRootOfParentForDistribution(const Node* node) -{ - ASSERT(node); - if (Element* parent = parentElementForDistribution(node)) - return parent->shadowRoot(); - - return 0; -} - -InsertionPoint* findInsertionPointOf(const Node*); - -inline bool hasShadowRootOrActiveInsertionPointParent(const Node& node) -{ - return hasShadowRootParent(node) - || isActiveInsertionPoint(findInsertionPointOf(&node)) - || isActiveInsertionPoint(node.parentNode()); -} - -} // namespace WebCore - -#endif // InsertionPoint_h diff --git a/Source/WebCore/html/shadow/MediaControlElementTypes.cpp b/Source/WebCore/html/shadow/MediaControlElementTypes.cpp index d6049a508..a2a62a890 100644 --- a/Source/WebCore/html/shadow/MediaControlElementTypes.cpp +++ b/Source/WebCore/html/shadow/MediaControlElementTypes.cpp @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -33,7 +33,7 @@ #include "MediaControlElementTypes.h" #include "CSSValueKeywords.h" -#include "ExceptionCodePlaceholder.h" +#include "EventNames.h" #include "HTMLNames.h" #include "MouseEvent.h" #include "RenderMedia.h" @@ -46,12 +46,6 @@ using namespace HTMLNames; class Event; -// FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in. -static const double cSkipRepeatDelay = 0.1; -static const double cSkipTime = 0.2; -static const double cScanRepeatDelay = 1.5; -static const double cScanMaximumRate = 8; - HTMLMediaElement* parentMediaElement(Node* node) { if (!node) @@ -59,18 +53,17 @@ HTMLMediaElement* parentMediaElement(Node* node) Node* mediaNode = node->shadowHost(); if (!mediaNode) mediaNode = node; - if (!mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement()) + if (!is<HTMLMediaElement>(*mediaNode)) return nullptr; - return toHTMLMediaElement(mediaNode); + return downcast<HTMLMediaElement>(mediaNode); } MediaControlElementType mediaControlElementType(Node* node) { ASSERT_WITH_SECURITY_IMPLICATION(node->isMediaControlElement()); - HTMLElement* element = toHTMLElement(node); - if (isHTMLInputElement(element)) - return static_cast<MediaControlInputElement*>(element)->displayType(); - return static_cast<MediaControlDivElement*>(element)->displayType(); + if (is<HTMLInputElement>(*node)) + return static_cast<MediaControlInputElement*>(node)->displayType(); + return static_cast<MediaControlDivElement*>(node)->displayType(); } MediaControlElement::MediaControlElement(MediaControlElementType displayType, HTMLElement* element) @@ -144,11 +137,11 @@ MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document& document, { } -void MediaControlMuteButtonElement::defaultEventHandler(Event* event) +void MediaControlMuteButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { mediaController()->setMuted(!mediaController()->muted()); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); @@ -168,18 +161,15 @@ void MediaControlMuteButtonElement::updateDisplayType() MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document& document, MediaControlElementType displayType) : MediaControlInputElement(document, displayType) - , m_actionOnStop(Nothing) - , m_seekType(Skip) - , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired) { } -void MediaControlSeekButtonElement::defaultEventHandler(Event* event) +void MediaControlSeekButtonElement::defaultEventHandler(Event& event) { // Set the mousedown and mouseup events as defaultHandled so they // do not trigger drag start or end actions in MediaControlPanelElement. - if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent) - event->setDefaultHandled(); + if (event.type() == eventNames().mousedownEvent || event.type() == eventNames().mouseupEvent) + event.setDefaultHandled(); } void MediaControlSeekButtonElement::setActive(bool flag, bool pause) @@ -188,62 +178,13 @@ void MediaControlSeekButtonElement::setActive(bool flag, bool pause) return; if (flag) - startTimer(); + mediaController()->beginScanning(isForwardButton() ? MediaControllerInterface::Forward : MediaControllerInterface::Backward); else - stopTimer(); + mediaController()->endScanning(); MediaControlInputElement::setActive(flag, pause); } -void MediaControlSeekButtonElement::startTimer() -{ - m_seekType = mediaController()->supportsScanning() ? Scan : Skip; - - if (m_seekType == Skip) { - // Seeking by skipping requires the video to be paused during seeking. - m_actionOnStop = mediaController()->paused() ? Nothing : Play; - mediaController()->pause(); - } else { - // Seeking by scanning requires the video to be playing during seeking. - m_actionOnStop = mediaController()->paused() ? Pause : Nothing; - mediaController()->play(); - mediaController()->setPlaybackRate(nextRate()); - } - - m_seekTimer.start(0, m_seekType == Skip ? cSkipRepeatDelay : cScanRepeatDelay); -} - -void MediaControlSeekButtonElement::stopTimer() -{ - if (m_seekType == Scan) - mediaController()->setPlaybackRate(mediaController()->defaultPlaybackRate()); - - if (m_actionOnStop == Play) - mediaController()->play(); - else if (m_actionOnStop == Pause) - mediaController()->pause(); - - if (m_seekTimer.isActive()) - m_seekTimer.stop(); -} - -double MediaControlSeekButtonElement::nextRate() const -{ - double rate = std::min(cScanMaximumRate, fabs(mediaController()->playbackRate() * 2)); - if (!isForwardButton()) - rate *= -1; - return rate; -} - -void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>&) -{ - if (m_seekType == Skip) { - double skipTime = isForwardButton() ? cSkipTime : -cSkipTime; - mediaController()->setCurrentTime(mediaController()->currentTime() + skipTime); - } else - mediaController()->setPlaybackRate(nextRate()); -} - // ---------------------------- MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& document) @@ -252,10 +193,10 @@ MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& docum { } -void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) +void MediaControlVolumeSliderElement::defaultEventHandler(Event& event) { // Left button is 0. Rejects mouse events not from left button. - if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) + if (is<MouseEvent>(event) && downcast<MouseEvent>(event).button()) return; if (!renderer()) @@ -263,15 +204,15 @@ void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) MediaControlInputElement::defaultEventHandler(event); - if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) + if (event.type() == eventNames().mouseoverEvent || event.type() == eventNames().mouseoutEvent || event.type() == eventNames().mousemoveEvent) return; double volume = value().toDouble(); if (volume != mediaController()->volume()) - mediaController()->setVolume(volume, ASSERT_NO_EXCEPTION); + mediaController()->setVolume(volume); if (m_clearMutedOnUserInteraction) mediaController()->setMuted(false); - event->setDefaultHandled(); + event.setDefaultHandled(); } bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents() diff --git a/Source/WebCore/html/shadow/MediaControlElementTypes.h b/Source/WebCore/html/shadow/MediaControlElementTypes.h index d4e4c07aa..ea05eb721 100644 --- a/Source/WebCore/html/shadow/MediaControlElementTypes.h +++ b/Source/WebCore/html/shadow/MediaControlElementTypes.h @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MediaControlElementTypes_h -#define MediaControlElementTypes_h +#pragma once #if ENABLE(VIDEO) @@ -36,7 +35,7 @@ #include "HTMLInputElement.h" #include "HTMLMediaElement.h" #include "MediaControllerInterface.h" -#include "RenderBlock.h" +#include "RenderObject.h" namespace WebCore { @@ -75,7 +74,7 @@ enum MediaControlElementType { }; HTMLMediaElement* parentMediaElement(Node*); -inline HTMLMediaElement* parentMediaElement(RenderObject& renderer) { return parentMediaElement(renderer.node()); } +inline HTMLMediaElement* parentMediaElement(const RenderObject& renderer) { return parentMediaElement(renderer.node()); } MediaControlElementType mediaControlElementType(Node*); @@ -88,7 +87,6 @@ public: virtual bool isShowing() const; virtual MediaControlElementType displayType() { return m_displayType; } - virtual const AtomicString& shadowPseudoId() const = 0; virtual void setMediaController(MediaControllerInterface* controller) { m_mediaController = controller; } virtual MediaControllerInterface* mediaController() const { return m_mediaController; } @@ -110,18 +108,20 @@ private: class MediaControlDivElement : public HTMLDivElement, public MediaControlElement { protected: - virtual bool isMediaControlElement() const override { return MediaControlElement::isMediaControlElement(); } explicit MediaControlDivElement(Document&, MediaControlElementType); + +private: + bool isMediaControlElement() const final { return MediaControlElement::isMediaControlElement(); } }; // ---------------------------- class MediaControlInputElement : public HTMLInputElement, public MediaControlElement { protected: - virtual bool isMediaControlElement() const override { return MediaControlElement::isMediaControlElement(); } explicit MediaControlInputElement(Document&, MediaControlElementType); private: + bool isMediaControlElement() const final { return MediaControlElement::isMediaControlElement(); } virtual void updateDisplayType() { } }; @@ -145,57 +145,46 @@ class MediaControlMuteButtonElement : public MediaControlInputElement { public: void changedMute(); - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } protected: explicit MediaControlMuteButtonElement(Document&, MediaControlElementType); - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; private: - virtual void updateDisplayType() override; + void updateDisplayType() override; }; // ---------------------------- class MediaControlSeekButtonElement : public MediaControlInputElement { public: - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } protected: explicit MediaControlSeekButtonElement(Document&, MediaControlElementType); - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; virtual bool isForwardButton() const = 0; private: - virtual void setActive(bool /*flag*/ = true, bool /*pause*/ = false) override final; - - void startTimer(); - void stopTimer(); - double nextRate() const; - void seekTimerFired(Timer<MediaControlSeekButtonElement>&); - - enum ActionType { Nothing, Play, Pause }; - ActionType m_actionOnStop; - enum SeekType { Skip, Scan }; - SeekType m_seekType; - Timer<MediaControlSeekButtonElement> m_seekTimer; + void setActive(bool /*flag*/ = true, bool /*pause*/ = false) final; }; // ---------------------------- class MediaControlVolumeSliderElement : public MediaControlInputElement { public: - virtual bool willRespondToMouseMoveEvents() override; - virtual bool willRespondToMouseClickEvents() override; + bool willRespondToMouseMoveEvents() override; + bool willRespondToMouseClickEvents() override; void setVolume(double); void setClearMutedOnUserInteraction(bool); protected: explicit MediaControlVolumeSliderElement(Document&); - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; private: bool m_clearMutedOnUserInteraction; @@ -204,5 +193,3 @@ private: } // namespace WebCore #endif // ENABLE(VIDEO) - -#endif // MediaControlElementTypes_h diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp index 91df2d97b..87da17e58 100644 --- a/Source/WebCore/html/shadow/MediaControlElements.cpp +++ b/Source/WebCore/html/shadow/MediaControlElements.cpp @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -28,21 +28,26 @@ */ #include "config.h" +#include "MediaControlElements.h" #if ENABLE(VIDEO) -#include "MediaControlElements.h" #include "DOMTokenList.h" +#include "ElementChildIterator.h" #include "EventHandler.h" #include "EventNames.h" -#include "ExceptionCodePlaceholder.h" #include "Frame.h" #include "GraphicsContext.h" +#include "HTMLHeadingElement.h" +#include "HTMLLIElement.h" +#include "HTMLUListElement.h" #include "HTMLVideoElement.h" #include "ImageBuffer.h" #include "Language.h" #include "LocalizedStrings.h" +#include "Logging.h" #include "MediaControls.h" +#include "Page.h" #include "PageGroup.h" #include "RenderLayer.h" #include "RenderMediaControlElements.h" @@ -51,13 +56,8 @@ #include "RenderView.h" #include "Settings.h" #include "ShadowRoot.h" -#if ENABLE(VIDEO_TRACK) #include "TextTrackList.h" -#endif - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "RenderWidget.h" -#endif +#include "VTTRegionList.h" namespace WebCore { @@ -72,19 +72,14 @@ MediaControlPanelElement::MediaControlPanelElement(Document& document) , m_isBeingDragged(false) , m_isDisplayed(false) , m_opaque(true) - , m_transitionTimer(this, &MediaControlPanelElement::transitionTimerFired) + , m_transitionTimer(*this, &MediaControlPanelElement::transitionTimerFired) { + setPseudo(AtomicString("-webkit-media-controls-panel", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlPanelElement> MediaControlPanelElement::create(Document& document) +Ref<MediaControlPanelElement> MediaControlPanelElement::create(Document& document) { - return adoptRef(new MediaControlPanelElement(document)); -} - -const AtomicString& MediaControlPanelElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-panel", AtomicString::ConstructFromLiteral)); - return id; + return adoptRef(*new MediaControlPanelElement(document)); } void MediaControlPanelElement::startDrag(const LayoutPoint& eventLocation) @@ -152,7 +147,7 @@ void MediaControlPanelElement::stopTimer() m_transitionTimer.stop(); } -void MediaControlPanelElement::transitionTimerFired(Timer<MediaControlPanelElement>&) +void MediaControlPanelElement::transitionTimerFired() { if (!m_opaque) hide(); @@ -172,7 +167,7 @@ void MediaControlPanelElement::setPosition(const LayoutPoint& position) setInlineStyleProperty(CSSPropertyMarginLeft, 0.0, CSSPrimitiveValue::CSS_PX); setInlineStyleProperty(CSSPropertyMarginTop, 0.0, CSSPrimitiveValue::CSS_PX); - classList()->add("dragged", IGNORE_EXCEPTION); + classList().add("dragged"); } void MediaControlPanelElement::resetPosition() @@ -182,7 +177,7 @@ void MediaControlPanelElement::resetPosition() removeInlineStyleProperty(CSSPropertyMarginLeft); removeInlineStyleProperty(CSSPropertyMarginTop); - classList()->remove("dragged", IGNORE_EXCEPTION); + classList().remove("dragged"); m_cumulativeDragOffset.setX(0); m_cumulativeDragOffset.setY(0); @@ -195,8 +190,8 @@ void MediaControlPanelElement::makeOpaque() double duration = document().page() ? document().page()->theme().mediaControlsFadeInDuration() : 0; - setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); - setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S); + setInlineStyleProperty(CSSPropertyTransitionProperty, CSSPropertyOpacity); + setInlineStyleProperty(CSSPropertyTransitionDuration, duration, CSSPrimitiveValue::CSS_S); setInlineStyleProperty(CSSPropertyOpacity, 1.0, CSSPrimitiveValue::CSS_NUMBER); m_opaque = true; @@ -212,29 +207,29 @@ void MediaControlPanelElement::makeTransparent() double duration = document().page() ? document().page()->theme().mediaControlsFadeOutDuration() : 0; - setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); - setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S); + setInlineStyleProperty(CSSPropertyTransitionProperty, CSSPropertyOpacity); + setInlineStyleProperty(CSSPropertyTransitionDuration, duration, CSSPrimitiveValue::CSS_S); setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER); m_opaque = false; startTimer(); } -void MediaControlPanelElement::defaultEventHandler(Event* event) +void MediaControlPanelElement::defaultEventHandler(Event& event) { MediaControlDivElement::defaultEventHandler(event); - if (event->isMouseEvent()) { - LayoutPoint location = static_cast<MouseEvent*>(event)->absoluteLocation(); - if (event->type() == eventNames().mousedownEvent && event->target() == this) { + if (is<MouseEvent>(event)) { + LayoutPoint location = downcast<MouseEvent>(event).absoluteLocation(); + if (event.type() == eventNames().mousedownEvent && event.target() == this) { startDrag(location); - event->setDefaultHandled(); - } else if (event->type() == eventNames().mousemoveEvent && m_isBeingDragged) + event.setDefaultHandled(); + } else if (event.type() == eventNames().mousemoveEvent && m_isBeingDragged) continueDrag(location); - else if (event->type() == eventNames().mouseupEvent && m_isBeingDragged) { + else if (event.type() == eventNames().mouseupEvent && m_isBeingDragged) { continueDrag(location); endDrag(); - event->setDefaultHandled(); + event.setDefaultHandled(); } } } @@ -261,17 +256,12 @@ MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(Document& d // Mapping onto same MediaControlElementType as panel element, since it has similar properties. : MediaControlDivElement(document, MediaControlsPanel) { + setPseudo(AtomicString("-webkit-media-controls-enclosure", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlPanelEnclosureElement> MediaControlPanelEnclosureElement::create(Document& document) -{ - return adoptRef(new MediaControlPanelEnclosureElement(document)); -} - -const AtomicString& MediaControlPanelEnclosureElement::shadowPseudoId() const +Ref<MediaControlPanelEnclosureElement> MediaControlPanelEnclosureElement::create(Document& document) { - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-enclosure", AtomicString::ConstructFromLiteral)); - return id; + return adoptRef(*new MediaControlPanelEnclosureElement(document)); } // ---------------------------- @@ -280,17 +270,12 @@ MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(Documen // Mapping onto same MediaControlElementType as panel element, since it has similar properties. : MediaControlDivElement(document, MediaControlsPanel) { + setPseudo(AtomicString("-webkit-media-controls-overlay-enclosure", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlOverlayEnclosureElement> MediaControlOverlayEnclosureElement::create(Document& document) +Ref<MediaControlOverlayEnclosureElement> MediaControlOverlayEnclosureElement::create(Document& document) { - return adoptRef(new MediaControlOverlayEnclosureElement(document)); -} - -const AtomicString& MediaControlOverlayEnclosureElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-enclosure", AtomicString::ConstructFromLiteral)); - return id; + return adoptRef(*new MediaControlOverlayEnclosureElement(document)); } // ---------------------------- @@ -298,43 +283,34 @@ const AtomicString& MediaControlOverlayEnclosureElement::shadowPseudoId() const MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document& document) : MediaControlDivElement(document, MediaTimelineContainer) { + setPseudo(AtomicString("-webkit-media-controls-timeline-container", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlTimelineContainerElement> MediaControlTimelineContainerElement::create(Document& document) +Ref<MediaControlTimelineContainerElement> MediaControlTimelineContainerElement::create(Document& document) { - RefPtr<MediaControlTimelineContainerElement> element = adoptRef(new MediaControlTimelineContainerElement(document)); + Ref<MediaControlTimelineContainerElement> element = adoptRef(*new MediaControlTimelineContainerElement(document)); element->hide(); - return element.release(); -} - -const AtomicString& MediaControlTimelineContainerElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline-container", AtomicString::ConstructFromLiteral)); - return id; + return element; } void MediaControlTimelineContainerElement::setTimeDisplaysHidden(bool hidden) { - for (unsigned i = 0; i < childNodeCount(); ++i) { - Node* child = childNode(i); - if (!child || !child->isElementNode()) - continue; - Element* element = toElement(child); - if (element->shadowPseudoId() != getMediaControlTimeRemainingDisplayElementShadowPseudoId() - && element->shadowPseudoId() != getMediaControlCurrentTimeDisplayElementShadowPseudoId()) + for (auto& element : childrenOfType<Element>(*this)) { + if (element.shadowPseudoId() != getMediaControlTimeRemainingDisplayElementShadowPseudoId() + && element.shadowPseudoId() != getMediaControlCurrentTimeDisplayElementShadowPseudoId()) continue; - MediaControlTimeDisplayElement* timeDisplay = static_cast<MediaControlTimeDisplayElement*>(element); + MediaControlTimeDisplayElement& timeDisplay = static_cast<MediaControlTimeDisplayElement&>(element); if (hidden) - timeDisplay->hide(); + timeDisplay.hide(); else - timeDisplay->show(); + timeDisplay.show(); } } -RenderPtr<RenderElement> MediaControlTimelineContainerElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> MediaControlTimelineContainerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderMediaControlTimelineContainer>(*this, std::move(style)); + return createRenderer<RenderMediaControlTimelineContainer>(*this, WTFMove(style)); } // ---------------------------- @@ -342,28 +318,29 @@ RenderPtr<RenderElement> MediaControlTimelineContainerElement::createElementRend MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(Document& document) : MediaControlDivElement(document, MediaVolumeSliderContainer) { + setPseudo(AtomicString("-webkit-media-controls-volume-slider-container", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlVolumeSliderContainerElement> MediaControlVolumeSliderContainerElement::create(Document& document) +Ref<MediaControlVolumeSliderContainerElement> MediaControlVolumeSliderContainerElement::create(Document& document) { - RefPtr<MediaControlVolumeSliderContainerElement> element = adoptRef(new MediaControlVolumeSliderContainerElement(document)); + Ref<MediaControlVolumeSliderContainerElement> element = adoptRef(*new MediaControlVolumeSliderContainerElement(document)); element->hide(); - return element.release(); + return element; } -RenderPtr<RenderElement> MediaControlVolumeSliderContainerElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> MediaControlVolumeSliderContainerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderMediaVolumeSliderContainer>(*this, std::move(style)); + return createRenderer<RenderMediaVolumeSliderContainer>(*this, WTFMove(style)); } -void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event* event) +void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event& event) { - if (!event->isMouseEvent() || event->type() != eventNames().mouseoutEvent) + if (!is<MouseEvent>(event) || event.type() != eventNames().mouseoutEvent) return; // Poor man's mouseleave event detection. - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - EventTarget* relatedTarget = mouseEvent->relatedTarget(); + MouseEvent& mouseEvent = downcast<MouseEvent>(event); + EventTarget* relatedTarget = mouseEvent.relatedTarget(); if (!relatedTarget || !relatedTarget->toNode()) return; @@ -373,25 +350,20 @@ void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event* event) hide(); } -const AtomicString& MediaControlVolumeSliderContainerElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-container", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document& document) : MediaControlDivElement(document, MediaStatusDisplay) , m_stateBeingDisplayed(Nothing) { + setPseudo(AtomicString("-webkit-media-controls-status-display", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlStatusDisplayElement> MediaControlStatusDisplayElement::create(Document& document) +Ref<MediaControlStatusDisplayElement> MediaControlStatusDisplayElement::create(Document& document) { - RefPtr<MediaControlStatusDisplayElement> element = adoptRef(new MediaControlStatusDisplayElement(document)); + Ref<MediaControlStatusDisplayElement> element = adoptRef(*new MediaControlStatusDisplayElement(document)); element->hide(); - return element.release(); + return element; } void MediaControlStatusDisplayElement::update() @@ -416,75 +388,58 @@ void MediaControlStatusDisplayElement::update() switch (m_stateBeingDisplayed) { case Nothing: - setInnerText("", IGNORE_EXCEPTION); + setInnerText(emptyString()); break; case Loading: - setInnerText(mediaElementLoadingStateText(), IGNORE_EXCEPTION); + setInnerText(mediaElementLoadingStateText()); break; case LiveBroadcast: - setInnerText(mediaElementLiveBroadcastStateText(), IGNORE_EXCEPTION); + setInnerText(mediaElementLiveBroadcastStateText()); break; } } -const AtomicString& MediaControlStatusDisplayElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-status-display", AtomicString::ConstructFromLiteral)); - return id; -} - - // ---------------------------- MediaControlPanelMuteButtonElement::MediaControlPanelMuteButtonElement(Document& document, MediaControls* controls) : MediaControlMuteButtonElement(document, MediaMuteButton) , m_controls(controls) { + setPseudo(AtomicString("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElement::create(Document& document, MediaControls* controls) +Ref<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElement::create(Document& document, MediaControls* controls) { ASSERT(controls); - RefPtr<MediaControlPanelMuteButtonElement> button = adoptRef(new MediaControlPanelMuteButtonElement(document, controls)); + Ref<MediaControlPanelMuteButtonElement> button = adoptRef(*new MediaControlPanelMuteButtonElement(document, controls)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlPanelMuteButtonElement::defaultEventHandler(Event* event) +void MediaControlPanelMuteButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().mouseoverEvent) + if (event.type() == eventNames().mouseoverEvent) m_controls->showVolumeSlider(); MediaControlMuteButtonElement::defaultEventHandler(event); } -const AtomicString& MediaControlPanelMuteButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlVolumeSliderMuteButtonElement::MediaControlVolumeSliderMuteButtonElement(Document& document) : MediaControlMuteButtonElement(document, MediaMuteButton) { + setPseudo(AtomicString("-webkit-media-controls-volume-slider-mute-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(Document& document) +Ref<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(Document& document) { - RefPtr<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(new MediaControlVolumeSliderMuteButtonElement(document)); + Ref<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(*new MediaControlVolumeSliderMuteButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); -} - -const AtomicString& MediaControlVolumeSliderMuteButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-mute-button", AtomicString::ConstructFromLiteral)); - return id; + return button; } // ---------------------------- @@ -492,25 +447,26 @@ const AtomicString& MediaControlVolumeSliderMuteButtonElement::shadowPseudoId() MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document& document) : MediaControlInputElement(document, MediaPlayButton) { + setPseudo(AtomicString("-webkit-media-controls-play-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(Document& document) +Ref<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(Document& document) { - RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(document)); + Ref<MediaControlPlayButtonElement> button = adoptRef(*new MediaControlPlayButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlPlayButtonElement::defaultEventHandler(Event* event) +void MediaControlPlayButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { if (mediaController()->canPlay()) mediaController()->play(); else mediaController()->pause(); updateDisplayType(); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } @@ -520,33 +476,28 @@ void MediaControlPlayButtonElement::updateDisplayType() setDisplayType(mediaController()->canPlay() ? MediaPlayButton : MediaPauseButton); } -const AtomicString& MediaControlPlayButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(Document& document) : MediaControlInputElement(document, MediaOverlayPlayButton) { + setPseudo(AtomicString("-webkit-media-controls-overlay-play-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonElement::create(Document& document) +Ref<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonElement::create(Document& document) { - RefPtr<MediaControlOverlayPlayButtonElement> button = adoptRef(new MediaControlOverlayPlayButtonElement(document)); + Ref<MediaControlOverlayPlayButtonElement> button = adoptRef(*new MediaControlOverlayPlayButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event* event) +void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent && mediaController()->canPlay()) { + if (event.type() == eventNames().clickEvent && mediaController()->canPlay()) { mediaController()->play(); updateDisplayType(); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } @@ -559,32 +510,20 @@ void MediaControlOverlayPlayButtonElement::updateDisplayType() hide(); } -const AtomicString& MediaControlOverlayPlayButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-play-button", AtomicString::ConstructFromLiteral)); - return id; -} - - // ---------------------------- MediaControlSeekForwardButtonElement::MediaControlSeekForwardButtonElement(Document& document) : MediaControlSeekButtonElement(document, MediaSeekForwardButton) { + setPseudo(AtomicString("-webkit-media-controls-seek-forward-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlSeekForwardButtonElement> MediaControlSeekForwardButtonElement::create(Document& document) +Ref<MediaControlSeekForwardButtonElement> MediaControlSeekForwardButtonElement::create(Document& document) { - RefPtr<MediaControlSeekForwardButtonElement> button = adoptRef(new MediaControlSeekForwardButtonElement(document)); + Ref<MediaControlSeekForwardButtonElement> button = adoptRef(*new MediaControlSeekForwardButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); -} - -const AtomicString& MediaControlSeekForwardButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-forward-button", AtomicString::ConstructFromLiteral)); - return id; + return button; } // ---------------------------- @@ -592,20 +531,15 @@ const AtomicString& MediaControlSeekForwardButtonElement::shadowPseudoId() const MediaControlSeekBackButtonElement::MediaControlSeekBackButtonElement(Document& document) : MediaControlSeekButtonElement(document, MediaSeekBackButton) { + setPseudo(AtomicString("-webkit-media-controls-seek-back-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlSeekBackButtonElement> MediaControlSeekBackButtonElement::create(Document& document) +Ref<MediaControlSeekBackButtonElement> MediaControlSeekBackButtonElement::create(Document& document) { - RefPtr<MediaControlSeekBackButtonElement> button = adoptRef(new MediaControlSeekBackButtonElement(document)); + Ref<MediaControlSeekBackButtonElement> button = adoptRef(*new MediaControlSeekBackButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); -} - -const AtomicString& MediaControlSeekBackButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-back-button", AtomicString::ConstructFromLiteral)); - return id; + return button; } // ---------------------------- @@ -613,84 +547,75 @@ const AtomicString& MediaControlSeekBackButtonElement::shadowPseudoId() const MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document& document) : MediaControlInputElement(document, MediaRewindButton) { + setPseudo(AtomicString("-webkit-media-controls-rewind-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlRewindButtonElement> MediaControlRewindButtonElement::create(Document& document) +Ref<MediaControlRewindButtonElement> MediaControlRewindButtonElement::create(Document& document) { - RefPtr<MediaControlRewindButtonElement> button = adoptRef(new MediaControlRewindButtonElement(document)); + Ref<MediaControlRewindButtonElement> button = adoptRef(*new MediaControlRewindButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlRewindButtonElement::defaultEventHandler(Event* event) +void MediaControlRewindButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { mediaController()->setCurrentTime(std::max<double>(0, mediaController()->currentTime() - 30)); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlRewindButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-rewind-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document& document) : MediaControlInputElement(document, MediaReturnToRealtimeButton) { + setPseudo(AtomicString("-webkit-media-controls-return-to-realtime-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlReturnToRealtimeButtonElement> MediaControlReturnToRealtimeButtonElement::create(Document& document) +Ref<MediaControlReturnToRealtimeButtonElement> MediaControlReturnToRealtimeButtonElement::create(Document& document) { - RefPtr<MediaControlReturnToRealtimeButtonElement> button = adoptRef(new MediaControlReturnToRealtimeButtonElement(document)); + Ref<MediaControlReturnToRealtimeButtonElement> button = adoptRef(*new MediaControlReturnToRealtimeButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); button->hide(); - return button.release(); + return button; } -void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event) +void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { mediaController()->returnToRealtime(); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlReturnToRealtimeButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-return-to-realtime-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document& document, MediaControls* controls) : MediaControlInputElement(document, MediaShowClosedCaptionsButton) -#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) +#if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK) , m_controls(controls) #endif { -#if !PLATFORM(MAC) && !PLATFORM(WIN) || !PLATFORM(GTK) +#if !PLATFORM(COCOA) && !PLATFORM(WIN) || !PLATFORM(GTK) UNUSED_PARAM(controls); #endif + setPseudo(AtomicString("-webkit-media-controls-toggle-closed-captions-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(Document& document, MediaControls* controls) +Ref<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(Document& document, MediaControls* controls) { ASSERT(controls); - RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(document, controls)); + Ref<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(*new MediaControlToggleClosedCaptionsButtonElement(document, controls)); button->ensureUserAgentShadowRoot(); button->setType("button"); button->hide(); - return button.release(); + return button; } void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() @@ -700,51 +625,40 @@ void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() setChecked(captionsVisible); } -void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event) +void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { // FIXME: It's not great that the shared code is dictating behavior of platform-specific // UI. Not all ports may want the closed captions button to toggle a list of tracks, so // we have to use #if. // https://bugs.webkit.org/show_bug.cgi?id=101877 -#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(GTK) +#if !PLATFORM(COCOA) && !PLATFORM(WIN) && !PLATFORM(GTK) mediaController()->setClosedCaptionsVisible(!mediaController()->closedCaptionsVisible()); setChecked(mediaController()->closedCaptionsVisible()); updateDisplayType(); #else m_controls->toggleClosedCaptionTrackList(); #endif - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-toggle-closed-captions-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlClosedCaptionsContainerElement::MediaControlClosedCaptionsContainerElement(Document& document) : MediaControlDivElement(document, MediaClosedCaptionsContainer) { + setPseudo(AtomicString("-webkit-media-controls-closed-captions-container", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlClosedCaptionsContainerElement> MediaControlClosedCaptionsContainerElement::create(Document& document) +Ref<MediaControlClosedCaptionsContainerElement> MediaControlClosedCaptionsContainerElement::create(Document& document) { - RefPtr<MediaControlClosedCaptionsContainerElement> element = adoptRef(new MediaControlClosedCaptionsContainerElement(document)); - element->setAttribute(dirAttr, "auto"); + Ref<MediaControlClosedCaptionsContainerElement> element = adoptRef(*new MediaControlClosedCaptionsContainerElement(document)); + element->setAttributeWithoutSynchronization(dirAttr, AtomicString("auto", AtomicString::ConstructFromLiteral)); element->hide(); - return element.release(); -} - -const AtomicString& MediaControlClosedCaptionsContainerElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-closed-captions-container", AtomicString::ConstructFromLiteral)); - return id; + return element; } // ---------------------------- @@ -758,21 +672,22 @@ MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListE #if !ENABLE(VIDEO_TRACK) UNUSED_PARAM(controls); #endif + setPseudo(AtomicString("-webkit-media-controls-closed-captions-track-list", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(Document& document, MediaControls* controls) +Ref<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(Document& document, MediaControls* controls) { ASSERT(controls); - RefPtr<MediaControlClosedCaptionsTrackListElement> element = adoptRef(new MediaControlClosedCaptionsTrackListElement(document, controls)); - return element.release(); + Ref<MediaControlClosedCaptionsTrackListElement> element = adoptRef(*new MediaControlClosedCaptionsTrackListElement(document, controls)); + return element; } -void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event* event) +void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event& event) { #if ENABLE(VIDEO_TRACK) - if (event->type() == eventNames().clickEvent) { - Node* target = event->target()->toNode(); - if (!target || !target->isElementNode()) + if (event.type() == eventNames().clickEvent) { + Node* target = event.target()->toNode(); + if (!is<Element>(target)) return; // When we created the elements in the track list, we gave them a custom @@ -781,7 +696,7 @@ void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event* even // tell the HTMLMediaElement to enable that track. RefPtr<TextTrack> textTrack; - MenuItemToTrackMap::iterator iter = m_menuToTrackMap.find(toElement(target)); + MenuItemToTrackMap::iterator iter = m_menuToTrackMap.find(downcast<Element>(target)); if (iter != m_menuToTrackMap.end()) textTrack = iter->value; m_menuToTrackMap.clear(); @@ -804,30 +719,23 @@ void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event* even #endif } -const AtomicString& MediaControlClosedCaptionsTrackListElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-closed-captions-track-list", AtomicString::ConstructFromLiteral)); - return id; -} - void MediaControlClosedCaptionsTrackListElement::updateDisplay() { #if ENABLE(VIDEO_TRACK) - DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<AtomicString> selectedClassValue("selected", AtomicString::ConstructFromLiteral); if (!mediaController()->hasClosedCaptions()) return; if (!document().page()) return; - CaptionUserPreferences::CaptionDisplayMode displayMode = document().page()->group().captionPreferences()->captionDisplayMode(); + CaptionUserPreferences::CaptionDisplayMode displayMode = document().page()->group().captionPreferences().captionDisplayMode(); HTMLMediaElement* mediaElement = parentMediaElement(this); if (!mediaElement) return; - TextTrackList* trackList = mediaElement->textTracks(); - if (!trackList || !trackList->length()) + if (!mediaElement->textTracks().length()) return; rebuildTrackListMenu(); @@ -835,9 +743,7 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay() RefPtr<Element> offMenuItem; bool trackMenuItemSelected = false; - for (unsigned i = 0, length = m_menuItems.size(); i < length; ++i) { - RefPtr<Element> trackItem = m_menuItems[i]; - + for (auto& trackItem : m_menuItems) { RefPtr<TextTrack> textTrack; MenuItemToTrackMap::iterator iter = m_menuToTrackMap.find(trackItem.get()); if (iter == m_menuToTrackMap.end()) @@ -853,24 +759,24 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay() if (textTrack == TextTrack::captionMenuAutomaticItem()) { if (displayMode == CaptionUserPreferences::Automatic) - trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); + trackItem->classList().add(selectedClassValue); else - trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); + trackItem->classList().remove(selectedClassValue); continue; } - if (displayMode != CaptionUserPreferences::Automatic && textTrack->mode() == TextTrack::showingKeyword()) { + if (displayMode != CaptionUserPreferences::Automatic && textTrack->mode() == TextTrack::Mode::Showing) { trackMenuItemSelected = true; - trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); + trackItem->classList().add(selectedClassValue); } else - trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); + trackItem->classList().remove(selectedClassValue); } if (offMenuItem) { if (displayMode == CaptionUserPreferences::ForcedOnly && !trackMenuItemSelected) - offMenuItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION); + offMenuItem->classList().add(selectedClassValue); else - offMenuItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION); + offMenuItem->classList().remove(selectedClassValue); } #endif } @@ -890,27 +796,26 @@ void MediaControlClosedCaptionsTrackListElement::rebuildTrackListMenu() if (!mediaElement) return; - TextTrackList* trackList = mediaElement->textTracks(); - if (!trackList || !trackList->length()) + TextTrackList& trackList = mediaElement->textTracks(); + if (!trackList.length()) return; if (!document().page()) return; - CaptionUserPreferences* captionPreferences = document().page()->group().captionPreferences(); - Vector<RefPtr<TextTrack>> tracksForMenu = captionPreferences->sortedTrackListForMenu(trackList); + auto& captionPreferences = document().page()->group().captionPreferences(); + Vector<RefPtr<TextTrack>> tracksForMenu = captionPreferences.sortedTrackListForMenu(&trackList); - RefPtr<Element> captionsHeader = document().createElement(h3Tag, ASSERT_NO_EXCEPTION); + auto captionsHeader = HTMLHeadingElement::create(h3Tag, document()); captionsHeader->appendChild(document().createTextNode(textTrackSubtitlesText())); appendChild(captionsHeader); - RefPtr<Element> captionsMenuList = document().createElement(ulTag, ASSERT_NO_EXCEPTION); + auto captionsMenuList = HTMLUListElement::create(document()); - for (unsigned i = 0, length = tracksForMenu.size(); i < length; ++i) { - RefPtr<TextTrack> textTrack = tracksForMenu[i]; - RefPtr<Element> menuItem = document().createElement(liTag, ASSERT_NO_EXCEPTION); - menuItem->appendChild(document().createTextNode(captionPreferences->displayNameForTrack(textTrack.get()))); + for (auto& textTrack : tracksForMenu) { + auto menuItem = HTMLLIElement::create(document()); + menuItem->appendChild(document().createTextNode(captionPreferences.displayNameForTrack(textTrack.get()))); captionsMenuList->appendChild(menuItem); - m_menuItems.append(menuItem); - m_menuToTrackMap.add(menuItem, textTrack); + m_menuItems.append(menuItem.ptr()); + m_menuToTrackMap.add(menuItem.ptr(), textTrack); } appendChild(captionsMenuList); @@ -923,45 +828,46 @@ MediaControlTimelineElement::MediaControlTimelineElement(Document& document, Med : MediaControlInputElement(document, MediaSlider) , m_controls(controls) { + setPseudo(AtomicString("-webkit-media-controls-timeline", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(Document& document, MediaControls* controls) +Ref<MediaControlTimelineElement> MediaControlTimelineElement::create(Document& document, MediaControls* controls) { ASSERT(controls); - RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(document, controls)); + Ref<MediaControlTimelineElement> timeline = adoptRef(*new MediaControlTimelineElement(document, controls)); timeline->ensureUserAgentShadowRoot(); timeline->setType("range"); - timeline->setAttribute(precisionAttr, "float"); - return timeline.release(); + timeline->setAttributeWithoutSynchronization(precisionAttr, AtomicString("float", AtomicString::ConstructFromLiteral)); + return timeline; } -void MediaControlTimelineElement::defaultEventHandler(Event* event) +void MediaControlTimelineElement::defaultEventHandler(Event& event) { // Left button is 0. Rejects mouse events not from left button. - if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) + if (is<MouseEvent>(event) && downcast<MouseEvent>(event).button()) return; if (!renderer()) return; - if (event->type() == eventNames().mousedownEvent) + if (event.type() == eventNames().mousedownEvent) mediaController()->beginScrubbing(); - if (event->type() == eventNames().mouseupEvent) + if (event.type() == eventNames().mouseupEvent) mediaController()->endScrubbing(); MediaControlInputElement::defaultEventHandler(event); - if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) + if (event.type() == eventNames().mouseoverEvent || event.type() == eventNames().mouseoutEvent || event.type() == eventNames().mousemoveEvent) return; double time = value().toDouble(); - if (event->type() == eventNames().inputEvent && time != mediaController()->currentTime()) + if ((event.isInputEvent() || event.type() == eventNames().inputEvent) && time != mediaController()->currentTime()) mediaController()->setCurrentTime(time); - RenderSlider* slider = toRenderSlider(renderer()); - if (slider && slider->inDragMode()) + RenderSlider& slider = downcast<RenderSlider>(*renderer()); + if (slider.inDragMode()) m_controls->updateCurrentTimeDisplay(); } @@ -985,34 +891,22 @@ void MediaControlTimelineElement::setDuration(double duration) setAttribute(maxAttr, AtomicString::number(std::isfinite(duration) ? duration : 0)); } - -const AtomicString& MediaControlTimelineElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlPanelVolumeSliderElement::MediaControlPanelVolumeSliderElement(Document& document) : MediaControlVolumeSliderElement(document) { + setPseudo(AtomicString("-webkit-media-controls-volume-slider", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlPanelVolumeSliderElement> MediaControlPanelVolumeSliderElement::create(Document& document) +Ref<MediaControlPanelVolumeSliderElement> MediaControlPanelVolumeSliderElement::create(Document& document) { - RefPtr<MediaControlPanelVolumeSliderElement> slider = adoptRef(new MediaControlPanelVolumeSliderElement(document)); + Ref<MediaControlPanelVolumeSliderElement> slider = adoptRef(*new MediaControlPanelVolumeSliderElement(document)); slider->ensureUserAgentShadowRoot(); slider->setType("range"); - slider->setAttribute(precisionAttr, "float"); - slider->setAttribute(maxAttr, "1"); - return slider.release(); -} - -const AtomicString& MediaControlPanelVolumeSliderElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider", AtomicString::ConstructFromLiteral)); - return id; + slider->setAttributeWithoutSynchronization(precisionAttr, AtomicString("float", AtomicString::ConstructFromLiteral)); + slider->setAttributeWithoutSynchronization(maxAttr, AtomicString("1", AtomicString::ConstructFromLiteral)); + return slider; } // ---------------------------- @@ -1020,22 +914,17 @@ const AtomicString& MediaControlPanelVolumeSliderElement::shadowPseudoId() const MediaControlFullscreenVolumeSliderElement::MediaControlFullscreenVolumeSliderElement(Document& document) : MediaControlVolumeSliderElement(document) { + setPseudo(AtomicString("-webkit-media-controls-fullscreen-volume-slider", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlFullscreenVolumeSliderElement> MediaControlFullscreenVolumeSliderElement::create(Document& document) +Ref<MediaControlFullscreenVolumeSliderElement> MediaControlFullscreenVolumeSliderElement::create(Document& document) { - RefPtr<MediaControlFullscreenVolumeSliderElement> slider = adoptRef(new MediaControlFullscreenVolumeSliderElement(document)); + Ref<MediaControlFullscreenVolumeSliderElement> slider = adoptRef(*new MediaControlFullscreenVolumeSliderElement(document)); slider->ensureUserAgentShadowRoot(); slider->setType("range"); - slider->setAttribute(precisionAttr, "float"); - slider->setAttribute(maxAttr, "1"); - return slider.release(); -} - -const AtomicString& MediaControlFullscreenVolumeSliderElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-slider", AtomicString::ConstructFromLiteral)); - return id; + slider->setAttributeWithoutSynchronization(precisionAttr, AtomicString("float", AtomicString::ConstructFromLiteral)); + slider->setAttributeWithoutSynchronization(maxAttr, AtomicString("1", AtomicString::ConstructFromLiteral)); + return slider; } // ---------------------------- @@ -1043,45 +932,40 @@ const AtomicString& MediaControlFullscreenVolumeSliderElement::shadowPseudoId() MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document& document) : MediaControlInputElement(document, MediaEnterFullscreenButton) { + setPseudo(AtomicString("-webkit-media-controls-fullscreen-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(Document& document) +Ref<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(Document& document) { - RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(document)); + Ref<MediaControlFullscreenButtonElement> button = adoptRef(*new MediaControlFullscreenButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); button->hide(); - return button.release(); + return button; } -void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) +void MediaControlFullscreenButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { + if (event.type() == eventNames().clickEvent) { #if ENABLE(FULLSCREEN_API) // Only use the new full screen API if the fullScreenEnabled setting has // been explicitly enabled. Otherwise, use the old fullscreen API. This // allows apps which embed a WebView to retain the existing full screen // video implementation without requiring them to implement their own full // screen behavior. - if (document().settings() && document().settings()->fullScreenEnabled()) { + if (document().settings().fullScreenEnabled()) { if (document().webkitIsFullScreen() && document().webkitCurrentFullScreenElement() == parentMediaElement(this)) document().webkitCancelFullScreen(); else - document().requestFullScreenForElement(parentMediaElement(this), 0, Document::ExemptIFrameAllowFullScreenRequirement); + document().requestFullScreenForElement(parentMediaElement(this), Document::ExemptIFrameAllowFullScreenRequirement); } else #endif mediaController()->enterFullscreen(); - event->setDefaultHandled(); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button", AtomicString::ConstructFromLiteral)); - return id; -} - void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen) { setDisplayType(isFullscreen ? MediaExitFullscreenButton : MediaEnterFullscreenButton); @@ -1092,143 +976,119 @@ void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen) MediaControlFullscreenVolumeMinButtonElement::MediaControlFullscreenVolumeMinButtonElement(Document& document) : MediaControlInputElement(document, MediaUnMuteButton) { + setPseudo(AtomicString("-webkit-media-controls-fullscreen-volume-min-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> MediaControlFullscreenVolumeMinButtonElement::create(Document& document) +Ref<MediaControlFullscreenVolumeMinButtonElement> MediaControlFullscreenVolumeMinButtonElement::create(Document& document) { - RefPtr<MediaControlFullscreenVolumeMinButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMinButtonElement(document)); + Ref<MediaControlFullscreenVolumeMinButtonElement> button = adoptRef(*new MediaControlFullscreenVolumeMinButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlFullscreenVolumeMinButtonElement::defaultEventHandler(Event* event) +void MediaControlFullscreenVolumeMinButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { - ExceptionCode code = 0; - mediaController()->setVolume(0, code); - event->setDefaultHandled(); + if (event.type() == eventNames().clickEvent) { + mediaController()->setVolume(0); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlFullscreenVolumeMinButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-min-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlFullscreenVolumeMaxButtonElement::MediaControlFullscreenVolumeMaxButtonElement(Document& document) : MediaControlInputElement(document, MediaMuteButton) { + setPseudo(AtomicString("-webkit-media-controls-fullscreen-volume-max-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> MediaControlFullscreenVolumeMaxButtonElement::create(Document& document) +Ref<MediaControlFullscreenVolumeMaxButtonElement> MediaControlFullscreenVolumeMaxButtonElement::create(Document& document) { - RefPtr<MediaControlFullscreenVolumeMaxButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMaxButtonElement(document)); + Ref<MediaControlFullscreenVolumeMaxButtonElement> button = adoptRef(*new MediaControlFullscreenVolumeMaxButtonElement(document)); button->ensureUserAgentShadowRoot(); button->setType("button"); - return button.release(); + return button; } -void MediaControlFullscreenVolumeMaxButtonElement::defaultEventHandler(Event* event) +void MediaControlFullscreenVolumeMaxButtonElement::defaultEventHandler(Event& event) { - if (event->type() == eventNames().clickEvent) { - ExceptionCode code = 0; - mediaController()->setVolume(1, code); - event->setDefaultHandled(); + if (event.type() == eventNames().clickEvent) { + mediaController()->setVolume(1); + event.setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlFullscreenVolumeMaxButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-max-button", AtomicString::ConstructFromLiteral)); - return id; -} - // ---------------------------- MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(Document& document) : MediaControlTimeDisplayElement(document, MediaTimeRemainingDisplay) { + setPseudo(getMediaControlTimeRemainingDisplayElementShadowPseudoId()); } -PassRefPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(Document& document) +Ref<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(Document& document) { - return adoptRef(new MediaControlTimeRemainingDisplayElement(document)); + return adoptRef(*new MediaControlTimeRemainingDisplayElement(document)); } static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseudoId() { - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-time-remaining-display", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<AtomicString> id("-webkit-media-controls-time-remaining-display", AtomicString::ConstructFromLiteral); return id; } -const AtomicString& MediaControlTimeRemainingDisplayElement::shadowPseudoId() const -{ - return getMediaControlTimeRemainingDisplayElementShadowPseudoId(); -} - // ---------------------------- MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(Document& document) : MediaControlTimeDisplayElement(document, MediaCurrentTimeDisplay) { + setPseudo(getMediaControlCurrentTimeDisplayElementShadowPseudoId()); } -PassRefPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(Document& document) +Ref<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(Document& document) { - return adoptRef(new MediaControlCurrentTimeDisplayElement(document)); + return adoptRef(*new MediaControlCurrentTimeDisplayElement(document)); } static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoId() { - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-current-time-display", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<AtomicString> id("-webkit-media-controls-current-time-display", AtomicString::ConstructFromLiteral); return id; } -const AtomicString& MediaControlCurrentTimeDisplayElement::shadowPseudoId() const -{ - return getMediaControlCurrentTimeDisplayElementShadowPseudoId(); -} - // ---------------------------- #if ENABLE(VIDEO_TRACK) MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement(Document& document) : MediaControlDivElement(document, MediaTextTrackDisplayContainer) - , m_updateTimer(this, &MediaControlTextTrackContainerElement::updateTimerFired) + , m_updateTimer(*this, &MediaControlTextTrackContainerElement::updateTimerFired) , m_fontSize(0) , m_fontSizeIsImportant(false) + , m_updateTextTrackRepresentationStyle(false) { + setPseudo(AtomicString("-webkit-media-text-track-container", AtomicString::ConstructFromLiteral)); } -PassRefPtr<MediaControlTextTrackContainerElement> MediaControlTextTrackContainerElement::create(Document& document) +Ref<MediaControlTextTrackContainerElement> MediaControlTextTrackContainerElement::create(Document& document) { - RefPtr<MediaControlTextTrackContainerElement> element = adoptRef(new MediaControlTextTrackContainerElement(document)); + auto element = adoptRef(*new MediaControlTextTrackContainerElement(document)); element->hide(); - return element.release(); + return element; } -RenderPtr<RenderElement> MediaControlTextTrackContainerElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> MediaControlTextTrackContainerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderTextTrackContainerElement>(*this, std::move(style)); + return createRenderer<RenderTextTrackContainerElement>(*this, WTFMove(style)); } -const AtomicString& MediaControlTextTrackContainerElement::textTrackContainerElementShadowPseudoId() -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-text-track-container", AtomicString::ConstructFromLiteral)); - return id; -} - -const AtomicString& MediaControlTextTrackContainerElement::shadowPseudoId() const +static bool compareCueIntervalForDisplay(const CueInterval& one, const CueInterval& two) { - return textTrackContainerElementShadowPseudoId(); -} + return one.data()->isPositionedAbove(two.data()); +}; void MediaControlTextTrackContainerElement::updateDisplay() { @@ -1243,7 +1103,7 @@ void MediaControlTextTrackContainerElement::updateDisplay() return; // 2. Let video be the media element or other playback mechanism. - HTMLVideoElement* video = toHTMLVideoElement(mediaElement); + HTMLVideoElement& video = downcast<HTMLVideoElement>(*mediaElement); // 3. Let output be an empty list of absolutely positioned CSS block boxes. Vector<RefPtr<HTMLDivElement>> output; @@ -1267,7 +1127,7 @@ void MediaControlTextTrackContainerElement::updateDisplay() // 7. Let cues be an empty list of text track cues. // 8. For each track track in tracks, append to cues all the cues from // track's list of cues that have their text track cue active flag set. - CueList activeCues = video->currentlyActiveCues(); + CueList activeCues = video.currentlyActiveCues(); // 9. If reset is false, then, for each text track cue cue in cues: if cue's // text track cue display state has a set of CSS boxes, then add those boxes @@ -1277,76 +1137,158 @@ void MediaControlTextTrackContainerElement::updateDisplay() // within the TextTrackCue instance itself. If parameters of the cue change, // the display tree is cleared. + // If the number of CSS boxes in the output is less than the number of cues + // we wish to render (e.g., we are adding another cue in a set of roll-up + // cues), remove all the existing CSS boxes representing the cues and re-add + // them so that the new cue is at the bottom. + // FIXME: Calling countChildNodes() here is inefficient. We don't need to + // traverse all children just to check if there are less children than cues. + if (countChildNodes() < activeCues.size()) + removeChildren(); + + // Sort the active cues for the appropriate display order. For example, for roll-up + // or paint-on captions, we need to add the cues in reverse chronological order, + // so that the newest captions appear at the bottom. + std::sort(activeCues.begin(), activeCues.end(), &compareCueIntervalForDisplay); + // 10. For each text track cue cue in cues that has not yet had // corresponding CSS boxes added to output, in text track cue order, run the // following substeps: for (size_t i = 0; i < activeCues.size(); ++i) { - TextTrackCue* cue = activeCues[i].data(); + if (!mediaController()->closedCaptionsVisible()) + continue; + + TextTrackCue* textTrackCue = activeCues[i].data(); + if (!textTrackCue->isRenderable()) + continue; + + VTTCue* cue = toVTTCue(textTrackCue); ASSERT(cue->isActive()); if (!cue->track() || !cue->track()->isRendered() || !cue->isActive() || cue->text().isEmpty()) continue; - RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree(m_videoDisplaySize.size()); - if (displayBox->hasChildNodes() && !contains(displayBox.get())) { - // Note: the display tree of a cue is removed when the active flag of the cue is unset. - appendChild(displayBox, ASSERT_NO_EXCEPTION); - cue->setFontSize(m_fontSize, m_videoDisplaySize.size(), m_fontSizeIsImportant); + LOG(Media, "MediaControlTextTrackContainerElement::updateDisplay(%p) - adding and positioning cue #%zu: \"%s\", start=%.2f, end=%.2f, line=%.2f", this, i, cue->text().utf8().data(), cue->startTime(), cue->endTime(), cue->line()); + + Ref<VTTCueBox> displayBox = cue->getDisplayTree(m_videoDisplaySize.size(), m_fontSize); + if (cue->track()->mode() == TextTrack::Mode::Disabled) + continue; + + VTTRegion* region = cue->track()->regions()->getRegionById(cue->regionId()); + if (!region) { + // If cue has an empty text track cue region identifier or there is no + // WebVTT region whose region identifier is identical to cue's text + // track cue region identifier, run the following substeps: + if (displayBox->hasChildNodes() && !contains(displayBox.ptr())) { + // Note: the display tree of a cue is removed when the active flag of the cue is unset. + appendChild(displayBox); + cue->setFontSize(m_fontSize, m_videoDisplaySize.size(), m_fontSizeIsImportant); + } + } else { + // Let region be the WebVTT region whose region identifier + // matches the text track cue region identifier of cue. + Ref<HTMLDivElement> regionNode = region->getDisplayTree(); + + // Append the region to the viewport, if it was not already. + if (!contains(regionNode.ptr())) + appendChild(region->getDisplayTree()); + + region->appendTextTrackCueBox(WTFMove(displayBox)); } } // 11. Return output. if (hasChildNodes()) { show(); - if (mediaElement->requiresTextTrackRepresentation()) { - if (!m_textTrackRepresentation) - m_textTrackRepresentation = TextTrackRepresentation::create(this); - mediaElement->setTextTrackRepresentation(m_textTrackRepresentation.get()); - - if (Page* page = document().page()) - m_textTrackRepresentation->setContentScale(page->deviceScaleFactor()); - - m_textTrackRepresentation->update(); - setInlineStyleProperty(CSSPropertyWidth, m_videoDisplaySize.size().width(), CSSPrimitiveValue::CSS_PX); - setInlineStyleProperty(CSSPropertyHeight, m_videoDisplaySize.size().height(), CSSPrimitiveValue::CSS_PX); - } + updateTextTrackRepresentation(); } else { hide(); clearTextTrackRepresentation(); } } -void MediaControlTextTrackContainerElement::updateTimerFired(Timer<MediaControlTextTrackContainerElement>&) +void MediaControlTextTrackContainerElement::updateActiveCuesFontSize() { if (!document().page()) return; - if (m_textTrackRepresentation) { - setInlineStyleProperty(CSSPropertyWidth, m_videoDisplaySize.size().width(), CSSPrimitiveValue::CSS_PX); - setInlineStyleProperty(CSSPropertyHeight, m_videoDisplaySize.size().height(), CSSPrimitiveValue::CSS_PX); - } - HTMLMediaElement* mediaElement = parentMediaElement(this); if (!mediaElement) return; float smallestDimension = std::min(m_videoDisplaySize.size().height(), m_videoDisplaySize.size().width()); - float fontScale = document().page()->group().captionPreferences()->captionFontSizeScaleAndImportance(m_fontSizeIsImportant); + float fontScale = document().page()->group().captionPreferences().captionFontSizeScaleAndImportance(m_fontSizeIsImportant); m_fontSize = lroundf(smallestDimension * fontScale); - - CueList activeCues = mediaElement->currentlyActiveCues(); - for (size_t i = 0; i < activeCues.size(); ++i) { - TextTrackCue* cue = activeCues[i].data(); - cue->setFontSize(m_fontSize, m_videoDisplaySize.size(), m_fontSizeIsImportant); + + for (auto& activeCue : mediaElement->currentlyActiveCues()) { + TextTrackCue* cue = activeCue.data(); + if (!cue->isRenderable()) + continue; + + toVTTCue(cue)->setFontSize(m_fontSize, m_videoDisplaySize.size(), m_fontSizeIsImportant); } + +} + +void MediaControlTextTrackContainerElement::updateTimerFired() +{ + if (!document().page()) + return; + + if (m_textTrackRepresentation) + updateStyleForTextTrackRepresentation(); + + updateActiveCuesFontSize(); updateDisplay(); } +void MediaControlTextTrackContainerElement::updateTextTrackRepresentation() +{ + HTMLMediaElement* mediaElement = parentMediaElement(this); + if (!mediaElement) + return; + + if (!mediaElement->requiresTextTrackRepresentation()) + return; + + if (!m_textTrackRepresentation) { + m_textTrackRepresentation = TextTrackRepresentation::create(*this); + m_updateTextTrackRepresentationStyle = true; + mediaElement->setTextTrackRepresentation(m_textTrackRepresentation.get()); + } + + m_textTrackRepresentation->update(); + updateStyleForTextTrackRepresentation(); +} + void MediaControlTextTrackContainerElement::clearTextTrackRepresentation() { + if (!m_textTrackRepresentation) + return; + + m_textTrackRepresentation = nullptr; + m_updateTextTrackRepresentationStyle = true; if (HTMLMediaElement* mediaElement = parentMediaElement(this)) mediaElement->setTextTrackRepresentation(nullptr); - m_textTrackRepresentation = nullptr; + updateStyleForTextTrackRepresentation(); + updateActiveCuesFontSize(); +} + +void MediaControlTextTrackContainerElement::updateStyleForTextTrackRepresentation() +{ + if (!m_updateTextTrackRepresentationStyle) + return; + m_updateTextTrackRepresentationStyle = false; + + if (m_textTrackRepresentation) { + setInlineStyleProperty(CSSPropertyWidth, m_videoDisplaySize.size().width(), CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyHeight, m_videoDisplaySize.size().height(), CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); + setInlineStyleProperty(CSSPropertyLeft, 0, CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyTop, 0, CSSPrimitiveValue::CSS_PX); + return; + } + removeInlineStyleProperty(CSSPropertyPosition); removeInlineStyleProperty(CSSPropertyWidth); removeInlineStyleProperty(CSSPropertyHeight); @@ -1356,6 +1298,8 @@ void MediaControlTextTrackContainerElement::clearTextTrackRepresentation() void MediaControlTextTrackContainerElement::enteredFullscreen() { + if (hasChildNodes()) + updateTextTrackRepresentation(); updateSizes(true); } @@ -1374,31 +1318,28 @@ void MediaControlTextTrackContainerElement::updateSizes(bool forceUpdate) if (!document().page()) return; - IntRect videoBox; + mediaElement->syncTextTrackBounds(); + IntRect videoBox; if (m_textTrackRepresentation) videoBox = m_textTrackRepresentation->bounds(); else { -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - if (!mediaElement->renderer() || !mediaElement->renderer()->isWidget()) + if (!is<RenderVideo>(mediaElement->renderer())) return; - videoBox = pixelSnappedIntRect(toRenderWidget(mediaElement->renderer())->contentBoxRect()); -#else - if (!mediaElement->renderer() || !mediaElement->renderer()->isVideo()) - return; - videoBox = toRenderVideo(*mediaElement->renderer()).videoBox(); -#endif + videoBox = downcast<RenderVideo>(*mediaElement->renderer()).videoBox(); } if (!forceUpdate && m_videoDisplaySize == videoBox) return; + m_videoDisplaySize = videoBox; + m_updateTextTrackRepresentationStyle = true; // FIXME (121170): This function is called during layout, and should lay out the text tracks immediately. m_updateTimer.startOneShot(0); } -PassRefPtr<Image> MediaControlTextTrackContainerElement::createTextTrackRepresentationImage() +RefPtr<Image> MediaControlTextTrackContainerElement::createTextTrackRepresentationImage() { if (!hasChildNodes()) return nullptr; @@ -1409,14 +1350,14 @@ PassRefPtr<Image> MediaControlTextTrackContainerElement::createTextTrackRepresen document().updateLayout(); - auto renderer = this->renderer(); + auto* renderer = this->renderer(); if (!renderer) return nullptr; if (!renderer->hasLayer()) return nullptr; - RenderLayer* layer = toRenderLayerModelObject(renderer)->layer(); + RenderLayer* layer = downcast<RenderLayerModelObject>(*renderer).layer(); float deviceScaleFactor = 1; if (Page* page = document().page()) @@ -1424,17 +1365,20 @@ PassRefPtr<Image> MediaControlTextTrackContainerElement::createTextTrackRepresen IntRect paintingRect = IntRect(IntPoint(), layer->size()); - std::unique_ptr<ImageBuffer> buffer(ImageBuffer::create(paintingRect.size(), deviceScaleFactor, ColorSpaceDeviceRGB)); + // FIXME (149422): This buffer should not be unconditionally unaccelerated. + std::unique_ptr<ImageBuffer> buffer(ImageBuffer::create(paintingRect.size(), Unaccelerated, deviceScaleFactor)); if (!buffer) return nullptr; - layer->paint(buffer->context(), paintingRect, PaintBehaviorFlattenCompositingLayers, nullptr, nullptr, RenderLayer::PaintLayerPaintingCompositingAllPhases); + layer->paint(buffer->context(), paintingRect, LayoutSize(), PaintBehaviorFlattenCompositingLayers, nullptr, RenderLayer::PaintLayerPaintingCompositingAllPhases); - return buffer->copyImage(); + return ImageBuffer::sinkIntoImage(WTFMove(buffer)); } void MediaControlTextTrackContainerElement::textTrackRepresentationBoundsChanged(const IntRect&) { + if (hasChildNodes()) + updateTextTrackRepresentation(); updateSizes(); } diff --git a/Source/WebCore/html/shadow/MediaControlElements.h b/Source/WebCore/html/shadow/MediaControlElements.h index 6f5205d4b..29642f0ae 100644 --- a/Source/WebCore/html/shadow/MediaControlElements.h +++ b/Source/WebCore/html/shadow/MediaControlElements.h @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -27,10 +27,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MediaControlElements_h -#define MediaControlElements_h +#pragma once #if ENABLE(VIDEO) + #include "MediaControlElementTypes.h" #include "TextTrackRepresentation.h" @@ -40,7 +40,7 @@ namespace WebCore { class MediaControlPanelElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlPanelElement> create(Document&); + static Ref<MediaControlPanelElement> create(Document&); void setCanBeDragged(bool); void setIsDisplayed(bool); @@ -50,15 +50,14 @@ public: void makeTransparent(); #if !PLATFORM(IOS) - virtual bool willRespondToMouseMoveEvents() override { return true; } - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseMoveEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: explicit MediaControlPanelElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; void startDrag(const LayoutPoint& eventLocation); void continueDrag(const LayoutPoint& eventLocation); @@ -66,7 +65,7 @@ private: void startTimer(); void stopTimer(); - void transitionTimerFired(Timer<MediaControlPanelElement>&); + void transitionTimerFired(); void setPosition(const LayoutPoint&); @@ -77,76 +76,71 @@ private: LayoutPoint m_lastDragEventLocation; LayoutPoint m_cumulativeDragOffset; - Timer<MediaControlPanelElement> m_transitionTimer; + Timer m_transitionTimer; }; // ---------------------------- class MediaControlPanelEnclosureElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlPanelEnclosureElement> create(Document&); + static Ref<MediaControlPanelEnclosureElement> create(Document&); private: explicit MediaControlPanelEnclosureElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- class MediaControlOverlayEnclosureElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlOverlayEnclosureElement> create(Document&); + static Ref<MediaControlOverlayEnclosureElement> create(Document&); private: explicit MediaControlOverlayEnclosureElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- -class MediaControlTimelineContainerElement : public MediaControlDivElement { +class MediaControlTimelineContainerElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlTimelineContainerElement> create(Document&); + static Ref<MediaControlTimelineContainerElement> create(Document&); void setTimeDisplaysHidden(bool); private: explicit MediaControlTimelineContainerElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; }; // ---------------------------- -class MediaControlVolumeSliderContainerElement : public MediaControlDivElement { +class MediaControlVolumeSliderContainerElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlVolumeSliderContainerElement> create(Document&); + static Ref<MediaControlVolumeSliderContainerElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseMoveEvents() override { return true; } + bool willRespondToMouseMoveEvents() override { return true; } #endif private: explicit MediaControlVolumeSliderContainerElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; }; // ---------------------------- -class MediaControlStatusDisplayElement : public MediaControlDivElement { +class MediaControlStatusDisplayElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlStatusDisplayElement> create(Document&); + static Ref<MediaControlStatusDisplayElement> create(Document&); void update(); private: explicit MediaControlStatusDisplayElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; enum StateBeingDisplayed { Nothing, Loading, LiveBroadcast }; StateBeingDisplayed m_stateBeingDisplayed; @@ -156,17 +150,16 @@ private: class MediaControlPanelMuteButtonElement final : public MediaControlMuteButtonElement { public: - static PassRefPtr<MediaControlPanelMuteButtonElement> create(Document&, MediaControls*); + static Ref<MediaControlPanelMuteButtonElement> create(Document&, MediaControls*); #if !PLATFORM(IOS) - virtual bool willRespondToMouseMoveEvents() override { return true; } + bool willRespondToMouseMoveEvents() override { return true; } #endif private: explicit MediaControlPanelMuteButtonElement(Document&, MediaControls*); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; MediaControls* m_controls; }; @@ -175,11 +168,10 @@ private: class MediaControlVolumeSliderMuteButtonElement final : public MediaControlMuteButtonElement { public: - static PassRefPtr<MediaControlVolumeSliderMuteButtonElement> create(Document&); + static Ref<MediaControlVolumeSliderMuteButtonElement> create(Document&); private: explicit MediaControlVolumeSliderMuteButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; @@ -187,115 +179,108 @@ private: class MediaControlPlayButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlPlayButtonElement> create(Document&); + static Ref<MediaControlPlayButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif - virtual void updateDisplayType() override; + void updateDisplayType() override; private: explicit MediaControlPlayButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- class MediaControlOverlayPlayButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlOverlayPlayButtonElement> create(Document&); + static Ref<MediaControlOverlayPlayButtonElement> create(Document&); - virtual void updateDisplayType() override; + void updateDisplayType() override; private: explicit MediaControlOverlayPlayButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- -class MediaControlSeekForwardButtonElement : public MediaControlSeekButtonElement { +class MediaControlSeekForwardButtonElement final : public MediaControlSeekButtonElement { public: - static PassRefPtr<MediaControlSeekForwardButtonElement> create(Document&); + static Ref<MediaControlSeekForwardButtonElement> create(Document&); private: explicit MediaControlSeekForwardButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual bool isForwardButton() const override { return true; } + bool isForwardButton() const override { return true; } }; // ---------------------------- -class MediaControlSeekBackButtonElement : public MediaControlSeekButtonElement { +class MediaControlSeekBackButtonElement final : public MediaControlSeekButtonElement { public: - static PassRefPtr<MediaControlSeekBackButtonElement> create(Document&); + static Ref<MediaControlSeekBackButtonElement> create(Document&); private: explicit MediaControlSeekBackButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual bool isForwardButton() const override { return false; } + bool isForwardButton() const override { return false; } }; // ---------------------------- -class MediaControlRewindButtonElement : public MediaControlInputElement { +class MediaControlRewindButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlRewindButtonElement> create(Document&); + static Ref<MediaControlRewindButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: explicit MediaControlRewindButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- -class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElement { +class MediaControlReturnToRealtimeButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(Document&); + static Ref<MediaControlReturnToRealtimeButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: explicit MediaControlReturnToRealtimeButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- class MediaControlToggleClosedCaptionsButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(Document&, MediaControls*); + static Ref<MediaControlToggleClosedCaptionsButtonElement> create(Document&, MediaControls*); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif - virtual void updateDisplayType() override; + void updateDisplayType() override; private: explicit MediaControlToggleClosedCaptionsButtonElement(Document&, MediaControls*); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; -#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) +#if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK) MediaControls* m_controls; #endif }; @@ -304,25 +289,24 @@ private: class MediaControlClosedCaptionsContainerElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlClosedCaptionsContainerElement> create(Document&); + static Ref<MediaControlClosedCaptionsContainerElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: MediaControlClosedCaptionsContainerElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- class MediaControlClosedCaptionsTrackListElement final : public MediaControlDivElement { public: - static PassRefPtr<MediaControlClosedCaptionsTrackListElement> create(Document&, MediaControls*); + static Ref<MediaControlClosedCaptionsTrackListElement> create(Document&, MediaControls*); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif void updateDisplay(); @@ -332,8 +316,7 @@ private: void rebuildTrackListMenu(); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; typedef Vector<RefPtr<Element>> TrackMenuItems; TrackMenuItems m_menuItems; @@ -348,10 +331,10 @@ private: class MediaControlTimelineElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlTimelineElement> create(Document&, MediaControls*); + static Ref<MediaControlTimelineElement> create(Document&, MediaControls*); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override; + bool willRespondToMouseClickEvents() override; #endif void setPosition(double); @@ -360,8 +343,7 @@ public: private: explicit MediaControlTimelineElement(Document&, MediaControls*); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; MediaControls* m_controls; }; @@ -370,73 +352,68 @@ private: class MediaControlFullscreenButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlFullscreenButtonElement> create(Document&); + static Ref<MediaControlFullscreenButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif - virtual void setIsFullscreen(bool); + void setIsFullscreen(bool); private: explicit MediaControlFullscreenButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- class MediaControlPanelVolumeSliderElement final : public MediaControlVolumeSliderElement { public: - static PassRefPtr<MediaControlPanelVolumeSliderElement> create(Document&); + static Ref<MediaControlPanelVolumeSliderElement> create(Document&); private: explicit MediaControlPanelVolumeSliderElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- -class MediaControlFullscreenVolumeSliderElement : public MediaControlVolumeSliderElement { +class MediaControlFullscreenVolumeSliderElement final : public MediaControlVolumeSliderElement { public: - static PassRefPtr<MediaControlFullscreenVolumeSliderElement> create(Document&); + static Ref<MediaControlFullscreenVolumeSliderElement> create(Document&); private: explicit MediaControlFullscreenVolumeSliderElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- -class MediaControlFullscreenVolumeMinButtonElement : public MediaControlInputElement { +class MediaControlFullscreenVolumeMinButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(Document&); + static Ref<MediaControlFullscreenVolumeMinButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: explicit MediaControlFullscreenVolumeMinButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; // ---------------------------- -class MediaControlFullscreenVolumeMaxButtonElement : public MediaControlInputElement { +class MediaControlFullscreenVolumeMaxButtonElement final : public MediaControlInputElement { public: - static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(Document&); + static Ref<MediaControlFullscreenVolumeMaxButtonElement> create(Document&); #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override { return true; } + bool willRespondToMouseClickEvents() override { return true; } #endif private: explicit MediaControlFullscreenVolumeMaxButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; }; @@ -444,22 +421,20 @@ private: class MediaControlTimeRemainingDisplayElement final : public MediaControlTimeDisplayElement { public: - static PassRefPtr<MediaControlTimeRemainingDisplayElement> create(Document&); + static Ref<MediaControlTimeRemainingDisplayElement> create(Document&); private: explicit MediaControlTimeRemainingDisplayElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- class MediaControlCurrentTimeDisplayElement final : public MediaControlTimeDisplayElement { public: - static PassRefPtr<MediaControlCurrentTimeDisplayElement> create(Document&); + static Ref<MediaControlCurrentTimeDisplayElement> create(Document&); private: explicit MediaControlCurrentTimeDisplayElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; }; // ---------------------------- @@ -468,31 +443,33 @@ private: class MediaControlTextTrackContainerElement final : public MediaControlDivElement, public TextTrackRepresentationClient { public: - static PassRefPtr<MediaControlTextTrackContainerElement> create(Document&); + static Ref<MediaControlTextTrackContainerElement> create(Document&); void updateDisplay(); void updateSizes(bool forceUpdate = false); void enteredFullscreen(); void exitedFullscreen(); - static const AtomicString& textTrackContainerElementShadowPseudoId(); private: - void updateTimerFired(Timer<MediaControlTextTrackContainerElement>&); + void updateTimerFired(); + void updateActiveCuesFontSize(); explicit MediaControlTextTrackContainerElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; - virtual PassRefPtr<Image> createTextTrackRepresentationImage() override; - virtual void textTrackRepresentationBoundsChanged(const IntRect&) override; + RefPtr<Image> createTextTrackRepresentationImage() override; + void textTrackRepresentationBoundsChanged(const IntRect&) override; + void updateTextTrackRepresentation(); void clearTextTrackRepresentation(); - OwnPtr<TextTrackRepresentation> m_textTrackRepresentation; + void updateStyleForTextTrackRepresentation(); + std::unique_ptr<TextTrackRepresentation> m_textTrackRepresentation; - Timer<MediaControlTextTrackContainerElement> m_updateTimer; + Timer m_updateTimer; IntRect m_videoDisplaySize; int m_fontSize; bool m_fontSizeIsImportant; + bool m_updateTextTrackRepresentationStyle; }; #endif @@ -500,5 +477,3 @@ private: } // namespace WebCore #endif // ENABLE(VIDEO) - -#endif // MediaControlElements_h diff --git a/Source/WebCore/html/shadow/MediaControls.cpp b/Source/WebCore/html/shadow/MediaControls.cpp index 7bfaf436c..2228f49b5 100644 --- a/Source/WebCore/html/shadow/MediaControls.cpp +++ b/Source/WebCore/html/shadow/MediaControls.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -29,7 +29,9 @@ #if ENABLE(VIDEO) #include "MediaControls.h" -#include "ExceptionCodePlaceholder.h" +#include "EventNames.h" +#include "Page.h" +#include "RenderElement.h" #include "Settings.h" namespace WebCore { @@ -48,10 +50,11 @@ MediaControls::MediaControls(Document& document) , m_volumeSlider(0) , m_toggleClosedCaptionsButton(0) , m_fullScreenButton(0) - , m_hideFullscreenControlsTimer(this, &MediaControls::hideFullscreenControlsTimerFired) + , m_hideFullscreenControlsTimer(*this, &MediaControls::hideFullscreenControlsTimerFired) , m_isFullscreen(false) , m_isMouseOverControls(false) { + setPseudo(AtomicString("-webkit-media-controls", AtomicString::ConstructFromLiteral)); } void MediaControls::setMediaController(MediaControllerInterface* controller) @@ -115,7 +118,7 @@ void MediaControls::reset() refreshClosedCaptionsButtonVisibility(); if (m_fullScreenButton) { - if (m_mediaController->supportsFullscreen() && m_mediaController->hasVideo()) + if (m_mediaController->supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenModeStandard) && m_mediaController->hasVideo()) m_fullScreenButton->show(); else m_fullScreenButton->hide(); @@ -220,7 +223,7 @@ void MediaControls::updateCurrentTimeDisplay() if (!page) return; - m_currentTimeDisplay->setInnerText(page->theme().formatMediaControlsTime(now), IGNORE_EXCEPTION); + m_currentTimeDisplay->setInnerText(page->theme().formatMediaControlsTime(now)); m_currentTimeDisplay->setCurrentValue(now); } @@ -293,11 +296,11 @@ void MediaControls::exitedFullscreen() #endif } -void MediaControls::defaultEventHandler(Event* event) +void MediaControls::defaultEventHandler(Event& event) { HTMLDivElement::defaultEventHandler(event); - if (event->type() == eventNames().mouseoverEvent) { + if (event.type() == eventNames().mouseoverEvent) { if (!containsRelatedTarget(event)) { m_isMouseOverControls = true; if (!m_mediaController->canPlay()) { @@ -309,7 +312,7 @@ void MediaControls::defaultEventHandler(Event* event) return; } - if (event->type() == eventNames().mouseoutEvent) { + if (event.type() == eventNames().mouseoutEvent) { if (!containsRelatedTarget(event)) { m_isMouseOverControls = false; stopHideFullscreenControlsTimer(); @@ -317,7 +320,7 @@ void MediaControls::defaultEventHandler(Event* event) return; } - if (event->type() == eventNames().mousemoveEvent) { + if (event.type() == eventNames().mousemoveEvent) { if (m_isFullscreen) { // When we get a mouse move in fullscreen mode, show the media controls, and start a timer // that will hide the media controls after a 3 seconds without a mouse move. @@ -329,7 +332,7 @@ void MediaControls::defaultEventHandler(Event* event) } } -void MediaControls::hideFullscreenControlsTimerFired(Timer<MediaControls>&) +void MediaControls::hideFullscreenControlsTimerFired() { if (m_mediaController->paused()) return; @@ -363,36 +366,31 @@ void MediaControls::stopHideFullscreenControlsTimer() m_hideFullscreenControlsTimer.stop(); } -const AtomicString& MediaControls::shadowPseudoId() const +bool MediaControls::containsRelatedTarget(Event& event) { - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls")); - return id; -} - -bool MediaControls::containsRelatedTarget(Event* event) -{ - if (!event->isMouseEvent()) + if (!is<MouseEvent>(event)) return false; - EventTarget* relatedTarget = static_cast<MouseEvent*>(event)->relatedTarget(); + EventTarget* relatedTarget = downcast<MouseEvent>(event).relatedTarget(); if (!relatedTarget) return false; return contains(relatedTarget->toNode()); } #if ENABLE(VIDEO_TRACK) + void MediaControls::createTextTrackDisplay() { if (m_textDisplayContainer) return; - RefPtr<MediaControlTextTrackContainerElement> textDisplayContainer = MediaControlTextTrackContainerElement::create(document()); - m_textDisplayContainer = textDisplayContainer.get(); + auto textDisplayContainer = MediaControlTextTrackContainerElement::create(document()); + m_textDisplayContainer = textDisplayContainer.ptr(); if (m_mediaController) m_textDisplayContainer->setMediaController(m_mediaController); // Insert it before the first controller element so it always displays behind the controls. - insertBefore(textDisplayContainer.release(), m_panel, IGNORE_EXCEPTION); + insertBefore(textDisplayContainer, m_panel); } void MediaControls::showTextTrackDisplay() @@ -423,6 +421,7 @@ void MediaControls::textTrackPreferencesChanged() if (m_textDisplayContainer) m_textDisplayContainer->updateSizes(true); } + #endif void MediaControls::setSliderVolume() diff --git a/Source/WebCore/html/shadow/MediaControls.h b/Source/WebCore/html/shadow/MediaControls.h index 47124cfef..72c1ec61d 100644 --- a/Source/WebCore/html/shadow/MediaControls.h +++ b/Source/WebCore/html/shadow/MediaControls.h @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MediaControls_h -#define MediaControls_h +#pragma once #if ENABLE(VIDEO) @@ -33,7 +32,6 @@ #include "HTMLDivElement.h" #include "MediaControlElements.h" #include "MouseEvent.h" -#include "Page.h" #include "RenderTheme.h" #include "Text.h" #include <wtf/RefPtr.h> @@ -46,7 +44,6 @@ namespace WebCore { class Document; class Event; -class Page; class MediaPlayer; class RenderBox; @@ -59,7 +56,7 @@ class MediaControls : public HTMLDivElement { // This function is to be implemented in your port-specific media // controls implementation since it will return a child instance. - static PassRefPtr<MediaControls> create(Document&); + static RefPtr<MediaControls> tryCreate(Document&); virtual void setMediaController(MediaControllerInterface*); @@ -94,10 +91,10 @@ class MediaControls : public HTMLDivElement { virtual void exitedFullscreen(); #if !PLATFORM(IOS) - virtual bool willRespondToMouseMoveEvents() override { return true; } + bool willRespondToMouseMoveEvents() override { return true; } #endif - virtual void hideFullscreenControlsTimerFired(Timer<MediaControls>&); + virtual void hideFullscreenControlsTimerFired(); virtual void startHideFullscreenControlsTimer(); virtual void stopHideFullscreenControlsTimer(); @@ -112,9 +109,9 @@ class MediaControls : public HTMLDivElement { protected: explicit MediaControls(Document&); - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; - virtual bool containsRelatedTarget(Event*); + virtual bool containsRelatedTarget(Event&); void setSliderVolume(); @@ -137,14 +134,12 @@ protected: MediaControlToggleClosedCaptionsButtonElement* m_toggleClosedCaptionsButton; MediaControlFullscreenButtonElement* m_fullScreenButton; - Timer<MediaControls> m_hideFullscreenControlsTimer; + Timer m_hideFullscreenControlsTimer; bool m_isFullscreen; bool m_isMouseOverControls; private: - virtual bool isMediaControls() const override { return true; } - - virtual const AtomicString& shadowPseudoId() const override; + bool isMediaControls() const final { return true; } }; inline MediaControls* toMediaControls(Node* node) @@ -156,8 +151,6 @@ inline MediaControls* toMediaControls(Node* node) // This will catch anyone doing an unneccessary cast. void toMediaControls(const MediaControls*); -} +} // namespace WebCore -#endif - -#endif +#endif // ENABLE(VIDEO) diff --git a/Source/WebCore/html/shadow/MediaControlsApple.cpp b/Source/WebCore/html/shadow/MediaControlsApple.cpp new file mode 100644 index 000000000..61092524c --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlsApple.cpp @@ -0,0 +1,568 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(VIDEO) +#include "MediaControlsApple.h" + +#include "CSSValueKeywords.h" +#include "EventNames.h" +#include "Page.h" +#include "WheelEvent.h" + +namespace WebCore { + +MediaControlsApple::MediaControlsApple(Document& document) + : MediaControls(document) +{ +} + +RefPtr<MediaControls> MediaControls::tryCreate(Document& document) +{ + return MediaControlsApple::tryCreateControls(document); +} + +RefPtr<MediaControlsApple> MediaControlsApple::tryCreateControls(Document& document) +{ + if (!document.page()) + return nullptr; + + auto controls = adoptRef(*new MediaControlsApple(document)); + + auto panel = MediaControlPanelElement::create(document); + + auto rewindButton = MediaControlRewindButtonElement::create(document); + controls->m_rewindButton = rewindButton.ptr(); + if (panel->appendChild(rewindButton).hasException()) + return nullptr; + + auto playButton = MediaControlPlayButtonElement::create(document); + controls->m_playButton = playButton.ptr(); + if (panel->appendChild(playButton).hasException()) + return nullptr; + + auto returnToRealtimeButton = MediaControlReturnToRealtimeButtonElement::create(document); + controls->m_returnToRealTimeButton = returnToRealtimeButton.ptr(); + if (panel->appendChild(returnToRealtimeButton).hasException()) + return nullptr; + + if (document.page()->theme().usesMediaControlStatusDisplay()) { + auto statusDisplay = MediaControlStatusDisplayElement::create(document); + controls->m_statusDisplay = statusDisplay.ptr(); + if (panel->appendChild(statusDisplay).hasException()) + return nullptr; + } + + auto timelineContainer = MediaControlTimelineContainerElement::create(document); + + auto currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(document); + controls->m_currentTimeDisplay = currentTimeDisplay.ptr(); + if (timelineContainer->appendChild(currentTimeDisplay).hasException()) + return nullptr; + + auto timeline = MediaControlTimelineElement::create(document, controls.ptr()); + controls->m_timeline = timeline.ptr(); + if (timelineContainer->appendChild(timeline).hasException()) + return nullptr; + + auto timeRemainingDisplay = MediaControlTimeRemainingDisplayElement::create(document); + controls->m_timeRemainingDisplay = timeRemainingDisplay.ptr(); + if (timelineContainer->appendChild(timeRemainingDisplay).hasException()) + return nullptr; + + controls->m_timelineContainer = timelineContainer.ptr(); + if (panel->appendChild(timelineContainer).hasException()) + return nullptr; + + // FIXME: Only create when needed <http://webkit.org/b/57163> + auto seekBackButton = MediaControlSeekBackButtonElement::create(document); + controls->m_seekBackButton = seekBackButton.ptr(); + if (panel->appendChild(seekBackButton).hasException()) + return nullptr; + + // FIXME: Only create when needed <http://webkit.org/b/57163> + auto seekForwardButton = MediaControlSeekForwardButtonElement::create(document); + controls->m_seekForwardButton = seekForwardButton.ptr(); + if (panel->appendChild(seekForwardButton).hasException()) + return nullptr; + + if (document.page()->theme().supportsClosedCaptioning()) { + auto closedCaptionsContainer = MediaControlClosedCaptionsContainerElement::create(document); + + auto closedCaptionsTrackList = MediaControlClosedCaptionsTrackListElement::create(document, controls.ptr()); + controls->m_closedCaptionsTrackList = closedCaptionsTrackList.ptr(); + if (closedCaptionsContainer->appendChild(closedCaptionsTrackList).hasException()) + return nullptr; + + auto toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document, controls.ptr()); + controls->m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.ptr(); + if (panel->appendChild(toggleClosedCaptionsButton).hasException()) + return nullptr; + + controls->m_closedCaptionsContainer = closedCaptionsContainer.ptr(); + if (controls->appendChild(closedCaptionsContainer).hasException()) + return nullptr; + } + + // FIXME: Only create when needed <http://webkit.org/b/57163> + auto fullScreenButton = MediaControlFullscreenButtonElement::create(document); + controls->m_fullScreenButton = fullScreenButton.ptr(); + panel->appendChild(fullScreenButton); + + // The mute button and the slider element should be in the same div. + auto panelVolumeControlContainer = HTMLDivElement::create(document); + + if (document.page()->theme().usesMediaControlVolumeSlider()) { + auto volumeSliderContainer = MediaControlVolumeSliderContainerElement::create(document); + + auto slider = MediaControlPanelVolumeSliderElement::create(document); + controls->m_volumeSlider = slider.ptr(); + if (volumeSliderContainer->appendChild(slider).hasException()) + return nullptr; + + // This is a duplicate mute button, which is visible in some ports at the bottom of the volume bar. + // It's important only when the volume bar is displayed below the controls. + auto volumeSliderMuteButton = MediaControlVolumeSliderMuteButtonElement::create(document); + controls->m_volumeSliderMuteButton = volumeSliderMuteButton.ptr(); + if (volumeSliderContainer->appendChild(volumeSliderMuteButton).hasException()) + return nullptr; + + controls->m_volumeSliderContainer = volumeSliderContainer.ptr(); + if (panelVolumeControlContainer->appendChild(volumeSliderContainer).hasException()) + return nullptr; + } + + auto panelMuteButton = MediaControlPanelMuteButtonElement::create(document, controls.ptr()); + controls->m_panelMuteButton = panelMuteButton.ptr(); + if (panelVolumeControlContainer->appendChild(panelMuteButton).hasException()) + return nullptr; + + if (panel->appendChild(panelVolumeControlContainer).hasException()) + return nullptr; + + // FIXME: Only create when needed <http://webkit.org/b/57163> + auto fullScreenMinVolumeButton = MediaControlFullscreenVolumeMinButtonElement::create(document); + controls->m_fullScreenMinVolumeButton = fullScreenMinVolumeButton.ptr(); + if (panel->appendChild(fullScreenMinVolumeButton).hasException()) + return nullptr; + + auto fullScreenVolumeSlider = MediaControlFullscreenVolumeSliderElement::create(document); + controls->m_fullScreenVolumeSlider = fullScreenVolumeSlider.ptr(); + if (panel->appendChild(fullScreenVolumeSlider).hasException()) + return nullptr; + + auto fullScreenMaxVolumeButton = MediaControlFullscreenVolumeMaxButtonElement::create(document); + controls->m_fullScreenMaxVolumeButton = fullScreenMaxVolumeButton.ptr(); + if (panel->appendChild(fullScreenMaxVolumeButton).hasException()) + return nullptr; + + controls->m_panel = panel.ptr(); + if (controls->appendChild(panel).hasException()) + return nullptr; + + return WTFMove(controls); +} + +void MediaControlsApple::setMediaController(MediaControllerInterface* controller) +{ + if (m_mediaController == controller) + return; + + MediaControls::setMediaController(controller); + + if (m_rewindButton) + m_rewindButton->setMediaController(controller); + if (m_returnToRealTimeButton) + m_returnToRealTimeButton->setMediaController(controller); + if (m_statusDisplay) + m_statusDisplay->setMediaController(controller); + if (m_timeRemainingDisplay) + m_timeRemainingDisplay->setMediaController(controller); + if (m_timelineContainer) + m_timelineContainer->setMediaController(controller); + if (m_seekBackButton) + m_seekBackButton->setMediaController(controller); + if (m_seekForwardButton) + m_seekForwardButton->setMediaController(controller); + if (m_volumeSliderMuteButton) + m_volumeSliderMuteButton->setMediaController(controller); + if (m_volumeSliderContainer) + m_volumeSliderContainer->setMediaController(controller); + if (m_fullScreenMinVolumeButton) + m_fullScreenMinVolumeButton->setMediaController(controller); + if (m_fullScreenVolumeSlider) + m_fullScreenVolumeSlider->setMediaController(controller); + if (m_fullScreenMaxVolumeButton) + m_fullScreenMaxVolumeButton->setMediaController(controller); + if (m_closedCaptionsTrackList) + m_closedCaptionsTrackList->setMediaController(controller); + if (m_closedCaptionsContainer) + m_closedCaptionsContainer->setMediaController(controller); +} + +void MediaControlsApple::defaultEventHandler(Event& event) +{ + if (event.type() == eventNames().clickEvent) { + if (m_closedCaptionsContainer && m_closedCaptionsContainer->isShowing()) { + hideClosedCaptionTrackList(); + event.setDefaultHandled(); + } + } + + MediaControls::defaultEventHandler(event); +} + +void MediaControlsApple::hide() +{ + MediaControls::hide(); + m_volumeSliderContainer->hide(); + if (m_closedCaptionsContainer) + hideClosedCaptionTrackList(); +} + +void MediaControlsApple::makeTransparent() +{ + MediaControls::makeTransparent(); + m_volumeSliderContainer->hide(); + if (m_closedCaptionsContainer) + hideClosedCaptionTrackList(); +} + +void MediaControlsApple::changedClosedCaptionsVisibility() +{ + MediaControls::changedClosedCaptionsVisibility(); + if (m_closedCaptionsContainer && m_closedCaptionsContainer->isShowing()) + hideClosedCaptionTrackList(); + +} + +void MediaControlsApple::reset() +{ + Page* page = document().page(); + if (!page) + return; + + updateStatusDisplay(); + + if (m_mediaController->supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenModeStandard)) + m_fullScreenButton->show(); + else + m_fullScreenButton->hide(); + + double duration = m_mediaController->duration(); + if (std::isfinite(duration) || page->theme().hasOwnDisabledStateHandlingFor(MediaSliderPart)) { + m_timeline->setDuration(duration); + m_timelineContainer->show(); + m_timeline->setPosition(m_mediaController->currentTime()); + updateCurrentTimeDisplay(); + } else + m_timelineContainer->hide(); + + if (m_mediaController->hasAudio() || page->theme().hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) + m_panelMuteButton->show(); + else + m_panelMuteButton->hide(); + + if (m_volumeSlider) + setSliderVolume(); + + if (m_toggleClosedCaptionsButton) { + if (m_mediaController->hasClosedCaptions()) + m_toggleClosedCaptionsButton->show(); + else + m_toggleClosedCaptionsButton->hide(); + } + + if (m_playButton) + m_playButton->updateDisplayType(); + +#if ENABLE(FULLSCREEN_API) + if (m_fullScreenVolumeSlider) + setFullscreenSliderVolume(); + + if (m_isFullscreen) { + if (m_mediaController->isLiveStream()) { + m_seekBackButton->hide(); + m_seekForwardButton->hide(); + m_rewindButton->show(); + m_returnToRealTimeButton->show(); + } else { + m_seekBackButton->show(); + m_seekForwardButton->show(); + m_rewindButton->hide(); + m_returnToRealTimeButton->hide(); + } + } else +#endif + if (!m_mediaController->isLiveStream()) { + m_returnToRealTimeButton->hide(); + m_rewindButton->show(); + } else { + m_returnToRealTimeButton->show(); + m_rewindButton->hide(); + } + + makeOpaque(); +} + +void MediaControlsApple::updateCurrentTimeDisplay() +{ + double now = m_mediaController->currentTime(); + double duration = m_mediaController->duration(); + + Page* page = document().page(); + if (!page) + return; + + // Allow the theme to format the time. + m_currentTimeDisplay->setInnerText(page->theme().formatMediaControlsCurrentTime(now, duration)); + m_currentTimeDisplay->setCurrentValue(now); + m_timeRemainingDisplay->setInnerText(page->theme().formatMediaControlsRemainingTime(now, duration)); + m_timeRemainingDisplay->setCurrentValue(now - duration); +} + +void MediaControlsApple::reportedError() +{ + Page* page = document().page(); + if (!page) + return; + + if (!page->theme().hasOwnDisabledStateHandlingFor(MediaSliderPart)) + m_timelineContainer->hide(); + + if (!page->theme().hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) + m_panelMuteButton->hide(); + + m_fullScreenButton->hide(); + + if (m_volumeSliderContainer) + m_volumeSliderContainer->hide(); + if (m_toggleClosedCaptionsButton && !page->theme().hasOwnDisabledStateHandlingFor(MediaToggleClosedCaptionsButtonPart)) + m_toggleClosedCaptionsButton->hide(); + if (m_closedCaptionsContainer) + hideClosedCaptionTrackList(); +} + +void MediaControlsApple::updateStatusDisplay() +{ + if (m_statusDisplay) + m_statusDisplay->update(); +} + +void MediaControlsApple::loadedMetadata() +{ + if (m_statusDisplay && !m_mediaController->isLiveStream()) + m_statusDisplay->hide(); + + MediaControls::loadedMetadata(); +} + +void MediaControlsApple::changedMute() +{ + MediaControls::changedMute(); + + if (m_volumeSliderMuteButton) + m_volumeSliderMuteButton->changedMute(); +} + +void MediaControlsApple::changedVolume() +{ + MediaControls::changedVolume(); + + if (m_fullScreenVolumeSlider) + setFullscreenSliderVolume(); +} + +void MediaControlsApple::enteredFullscreen() +{ + MediaControls::enteredFullscreen(); + m_panel->setCanBeDragged(true); + + if (m_mediaController->isLiveStream()) { + m_seekBackButton->hide(); + m_seekForwardButton->hide(); + m_rewindButton->show(); + m_returnToRealTimeButton->show(); + } else { + m_seekBackButton->show(); + m_seekForwardButton->show(); + m_rewindButton->hide(); + m_returnToRealTimeButton->hide(); + } +} + +void MediaControlsApple::exitedFullscreen() +{ + m_rewindButton->show(); + m_seekBackButton->show(); + m_seekForwardButton->show(); + m_returnToRealTimeButton->show(); + + m_panel->setCanBeDragged(false); + + // We will keep using the panel, but we want it to go back to the standard position. + // This will matter right away because we use the panel even when not fullscreen. + // And if we reenter fullscreen we also want the panel in the standard position. + m_panel->resetPosition(); + + MediaControls::exitedFullscreen(); +} + +void MediaControlsApple::showVolumeSlider() +{ + if (!m_mediaController->hasAudio()) + return; + + if (m_volumeSliderContainer) + m_volumeSliderContainer->show(); +} + +void MediaControlsApple::toggleClosedCaptionTrackList() +{ + if (!m_mediaController->hasClosedCaptions()) + return; + + if (m_closedCaptionsContainer) { + if (m_closedCaptionsContainer->isShowing()) + hideClosedCaptionTrackList(); + else { + if (m_closedCaptionsTrackList) + m_closedCaptionsTrackList->updateDisplay(); + showClosedCaptionTrackList(); + } + } +} + +void MediaControlsApple::showClosedCaptionTrackList() +{ + if (!m_closedCaptionsContainer || m_closedCaptionsContainer->isShowing()) + return; + + m_closedCaptionsContainer->show(); + + // Ensure the controls panel does not receive any events while the captions + // track list is visible as all events now need to be captured by the + // track list. + m_panel->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone); + + EventListener& listener = eventListener(); + m_closedCaptionsContainer->addEventListener(eventNames().wheelEvent, listener, true); + + // Track click events in the capture phase at two levels, first at the document level + // such that a click outside of the <video> may dismiss the track list, second at the + // media controls level such that a click anywhere outside of the track list hides the + // track list. These two levels are necessary since it would not be possible to get a + // reference to the track list when handling the event outside of the shadow tree. + document().addEventListener(eventNames().clickEvent, listener, true); + addEventListener(eventNames().clickEvent, listener, true); +} + +void MediaControlsApple::hideClosedCaptionTrackList() +{ + if (!m_closedCaptionsContainer || !m_closedCaptionsContainer->isShowing()) + return; + + m_closedCaptionsContainer->hide(); + + // Buttons in the controls panel may now be interactive. + m_panel->removeInlineStyleProperty(CSSPropertyPointerEvents); + + EventListener& listener = eventListener(); + m_closedCaptionsContainer->removeEventListener(eventNames().wheelEvent, listener, true); + document().removeEventListener(eventNames().clickEvent, listener, true); + removeEventListener(eventNames().clickEvent, listener, true); +} + +void MediaControlsApple::setFullscreenSliderVolume() +{ + m_fullScreenVolumeSlider->setVolume(m_mediaController->muted() ? 0.0 : m_mediaController->volume()); +} + +bool MediaControlsApple::shouldClosedCaptionsContainerPreventPageScrolling(int wheelDeltaY) +{ + int scrollTop = m_closedCaptionsContainer->scrollTop(); + // Scrolling down. + if (wheelDeltaY < 0 && (scrollTop + m_closedCaptionsContainer->offsetHeight()) >= m_closedCaptionsContainer->scrollHeight()) + return true; + // Scrolling up. + if (wheelDeltaY > 0 && scrollTop <= 0) + return true; + return false; +} + +void MediaControlsApple::handleClickEvent(Event& event) +{ + Node* currentTarget = event.currentTarget()->toNode(); + Node* target = event.target()->toNode(); + + if ((currentTarget == &document() && !shadowHost()->contains(target)) || (currentTarget == this && !m_closedCaptionsContainer->contains(target))) { + hideClosedCaptionTrackList(); + event.stopImmediatePropagation(); + event.setDefaultHandled(); + } +} + +void MediaControlsApple::closedCaptionTracksChanged() +{ + if (m_toggleClosedCaptionsButton) { + if (m_mediaController->hasClosedCaptions()) + m_toggleClosedCaptionsButton->show(); + else + m_toggleClosedCaptionsButton->hide(); + } +} + +MediaControlsAppleEventListener& MediaControlsApple::eventListener() +{ + if (!m_eventListener) + m_eventListener = MediaControlsAppleEventListener::create(this); + return *m_eventListener; +} + +// -------- + +void MediaControlsAppleEventListener::handleEvent(ScriptExecutionContext*, Event* event) +{ + if (event->type() == eventNames().clickEvent) + m_mediaControls->handleClickEvent(*event); + else if (eventNames().isWheelEventType(event->type()) && is<WheelEvent>(*event)) { + WheelEvent& wheelEvent = downcast<WheelEvent>(*event); + if (m_mediaControls->shouldClosedCaptionsContainerPreventPageScrolling(wheelEvent.wheelDeltaY())) + wheelEvent.preventDefault(); + } +} + +bool MediaControlsAppleEventListener::operator==(const EventListener& listener) const +{ + if (const MediaControlsAppleEventListener* mediaControlsAppleEventListener = MediaControlsAppleEventListener::cast(&listener)) + return m_mediaControls == mediaControlsAppleEventListener->m_mediaControls; + return false; +} + +} + +#endif diff --git a/Source/WebCore/html/shadow/MediaControlsApple.h b/Source/WebCore/html/shadow/MediaControlsApple.h new file mode 100644 index 000000000..31b2bc9a5 --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlsApple.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(VIDEO) + +#include "MediaControls.h" + +namespace WebCore { + +class MediaControlsApple; + +class MediaControlsAppleEventListener : public EventListener { +public: + static Ref<MediaControlsAppleEventListener> create(MediaControlsApple* mediaControls) { return adoptRef(*new MediaControlsAppleEventListener(mediaControls)); } + static const MediaControlsAppleEventListener* cast(const EventListener* listener) + { + return listener->type() == MediaControlsAppleEventListenerType + ? static_cast<const MediaControlsAppleEventListener*>(listener) + : 0; + } + + bool operator==(const EventListener& other) const override; + +private: + MediaControlsAppleEventListener(MediaControlsApple* mediaControls) + : EventListener(MediaControlsAppleEventListenerType) + , m_mediaControls(mediaControls) + { + } + + void handleEvent(ScriptExecutionContext*, Event*) override; + + MediaControlsApple* m_mediaControls; +}; + +class MediaControlsApple final : public MediaControls { +public: + static RefPtr<MediaControlsApple> tryCreateControls(Document&); + + // MediaControls implementation. + void setMediaController(MediaControllerInterface*) override; + + void hide() override; + void makeTransparent() override; + + void reset() override; + + void changedMute() override; + void changedVolume() override; + + void enteredFullscreen() override; + void exitedFullscreen() override; + + void reportedError() override; + void loadedMetadata() override; + + void showVolumeSlider() override; + void updateCurrentTimeDisplay() override; + void updateStatusDisplay() override; + + void changedClosedCaptionsVisibility() override; + void toggleClosedCaptionTrackList() override; + void closedCaptionTracksChanged() override; + + bool shouldClosedCaptionsContainerPreventPageScrolling(int wheelDeltaY); + void handleClickEvent(Event&); + +private: + MediaControlsApple(Document&); + + void defaultEventHandler(Event&) override; + MediaControlsAppleEventListener& eventListener(); + + void showClosedCaptionTrackList(); + void hideClosedCaptionTrackList(); + void setFullscreenSliderVolume(); + + MediaControlRewindButtonElement* m_rewindButton { nullptr }; + MediaControlReturnToRealtimeButtonElement* m_returnToRealTimeButton { nullptr }; + MediaControlStatusDisplayElement* m_statusDisplay { nullptr }; + MediaControlTimeRemainingDisplayElement* m_timeRemainingDisplay { nullptr }; + MediaControlTimelineContainerElement* m_timelineContainer { nullptr }; + MediaControlSeekBackButtonElement* m_seekBackButton { nullptr }; + MediaControlSeekForwardButtonElement* m_seekForwardButton { nullptr }; + MediaControlClosedCaptionsTrackListElement* m_closedCaptionsTrackList { nullptr }; + MediaControlClosedCaptionsContainerElement* m_closedCaptionsContainer { nullptr }; + MediaControlVolumeSliderMuteButtonElement* m_volumeSliderMuteButton { nullptr }; + MediaControlVolumeSliderContainerElement* m_volumeSliderContainer { nullptr }; + MediaControlFullscreenVolumeMinButtonElement* m_fullScreenMinVolumeButton { nullptr }; + MediaControlFullscreenVolumeSliderElement* m_fullScreenVolumeSlider { nullptr }; + MediaControlFullscreenVolumeMaxButtonElement* m_fullScreenMaxVolumeButton { nullptr }; + RefPtr<MediaControlsAppleEventListener> m_eventListener; +}; + +} // namespace WebCore + +#endif // ENABLE(VIDEO) diff --git a/Source/WebCore/html/shadow/MediaControlsGtk.cpp b/Source/WebCore/html/shadow/MediaControlsGtk.cpp deleted file mode 100644 index 7382d434e..000000000 --- a/Source/WebCore/html/shadow/MediaControlsGtk.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2011, 2012 Google Inc. All rights reserved. - * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> - * Copyright (C) 2012 Igalia S.L. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(VIDEO) -#include "MediaControlsGtk.h" - -namespace WebCore { - -class MediaControlsGtkEventListener : public EventListener { -public: - static PassRefPtr<MediaControlsGtkEventListener> create(MediaControlsGtk* mediaControls) { return adoptRef(new MediaControlsGtkEventListener(mediaControls)); } - static const MediaControlsGtkEventListener* cast(const EventListener* listener) - { - return listener->type() == GObjectEventListenerType - ? static_cast<const MediaControlsGtkEventListener*>(listener) - : 0; - } - - virtual bool operator==(const EventListener& other); - -private: - MediaControlsGtkEventListener(MediaControlsGtk* mediaControls) - : EventListener(GObjectEventListenerType) - , m_mediaControls(mediaControls) - { - } - - virtual void handleEvent(ScriptExecutionContext*, Event*); - - MediaControlsGtk* m_mediaControls; -}; - -MediaControlsGtk::MediaControlsGtk(Document& document) - : MediaControls(document) - , m_durationDisplay(0) - , m_enclosure(0) - , m_closedCaptionsTrackList(0) - , m_closedCaptionsContainer(0) - , m_eventListener(0) -{ -} - -PassRefPtr<MediaControls> MediaControls::create(Document& document) -{ - return MediaControlsGtk::createControls(document); -} - -PassRefPtr<MediaControlsGtk> MediaControlsGtk::createControls(Document& document) -{ - if (!document.page()) - return 0; - - RefPtr<MediaControlsGtk> controls = adoptRef(new MediaControlsGtk(document)); - - if (controls->initializeControls(document)) - return controls.release(); - - return 0; -} - -bool MediaControlsGtk::initializeControls(Document& document) -{ - // Create an enclosing element for the panel so we can visually offset the controls correctly. - RefPtr<MediaControlPanelEnclosureElement> enclosure = MediaControlPanelEnclosureElement::create(document); - RefPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(document); - ExceptionCode exceptionCode; - - RefPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(document); - m_playButton = playButton.get(); - panel->appendChild(playButton.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(document, this); - m_timeline = timeline.get(); - panel->appendChild(timeline.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(document); - m_currentTimeDisplay = currentTimeDisplay.get(); - m_currentTimeDisplay->hide(); - panel->appendChild(currentTimeDisplay.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(document); - m_durationDisplay = durationDisplay.get(); - panel->appendChild(durationDisplay.release(), exceptionCode); - if (exceptionCode) - return false; - - if (document.page()->theme().supportsClosedCaptioning()) { - RefPtr<MediaControlClosedCaptionsContainerElement> closedCaptionsContainer = MediaControlClosedCaptionsContainerElement::create(document); - - RefPtr<MediaControlClosedCaptionsTrackListElement> closedCaptionsTrackList = MediaControlClosedCaptionsTrackListElement::create(document, this); - m_closedCaptionsTrackList = closedCaptionsTrackList.get(); - closedCaptionsContainer->appendChild(closedCaptionsTrackList.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document, this); - m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); - panel->appendChild(toggleClosedCaptionsButton.release(), exceptionCode); - if (exceptionCode) - return false; - - m_closedCaptionsContainer = closedCaptionsContainer.get(); - appendChild(closedCaptionsContainer.release(), exceptionCode); - if (exceptionCode) - return false; - } - - RefPtr<MediaControlFullscreenButtonElement> fullscreenButton = MediaControlFullscreenButtonElement::create(document); - m_fullScreenButton = fullscreenButton.get(); - panel->appendChild(fullscreenButton.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlPanelMuteButtonElement> panelMuteButton = MediaControlPanelMuteButtonElement::create(document, this); - m_panelMuteButton = panelMuteButton.get(); - panel->appendChild(panelMuteButton.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlVolumeSliderContainerElement> sliderContainer = MediaControlVolumeSliderContainerElement::create(document); - m_volumeSliderContainer = sliderContainer.get(); - panel->appendChild(sliderContainer.release(), exceptionCode); - if (exceptionCode) - return false; - - RefPtr<MediaControlPanelVolumeSliderElement> slider = MediaControlPanelVolumeSliderElement::create(document); - m_volumeSlider = slider.get(); - m_volumeSlider->setClearMutedOnUserInteraction(true); - m_volumeSliderContainer->appendChild(slider.release(), exceptionCode); - if (exceptionCode) - return false; - - m_panel = panel.get(); - enclosure->appendChild(panel.release(), exceptionCode); - if (exceptionCode) - return false; - - m_enclosure = enclosure.get(); - appendChild(enclosure.release(), exceptionCode); - if (exceptionCode) - return false; - - return true; -} - -void MediaControlsGtk::setMediaController(MediaControllerInterface* controller) -{ - if (m_mediaController == controller) - return; - - MediaControls::setMediaController(controller); - - if (m_durationDisplay) - m_durationDisplay->setMediaController(controller); - if (m_enclosure) - m_enclosure->setMediaController(controller); - if (m_closedCaptionsContainer) - m_closedCaptionsContainer->setMediaController(controller); - if (m_closedCaptionsTrackList) - m_closedCaptionsTrackList->setMediaController(controller); -} - -void MediaControlsGtk::reset() -{ - Page* page = document().page(); - if (!page) - return; - - double duration = m_mediaController->duration(); - m_durationDisplay->setInnerText(page->theme().formatMediaControlsTime(duration), ASSERT_NO_EXCEPTION); - m_durationDisplay->setCurrentValue(duration); - - if (m_toggleClosedCaptionsButton) { - if (m_mediaController->hasClosedCaptions()) - m_toggleClosedCaptionsButton->show(); - else - m_toggleClosedCaptionsButton->hide(); - } - - MediaControls::reset(); -} - -void MediaControlsGtk::playbackStarted() -{ - m_currentTimeDisplay->show(); - m_durationDisplay->hide(); - - MediaControls::playbackStarted(); -} - -void MediaControlsGtk::updateCurrentTimeDisplay() -{ - double now = m_mediaController->currentTime(); - double duration = m_mediaController->duration(); - - Page* page = document().page(); - if (!page) - return; - - // After seek, hide duration display and show current time. - if (now > 0) { - m_currentTimeDisplay->show(); - m_durationDisplay->hide(); - } - - // Allow the theme to format the time. - ExceptionCode exceptionCode; - m_currentTimeDisplay->setInnerText(page->theme().formatMediaControlsCurrentTime(now, duration), exceptionCode); - m_currentTimeDisplay->setCurrentValue(now); -} - -void MediaControlsGtk::changedMute() -{ - MediaControls::changedMute(); - - if (m_mediaController->muted()) - m_volumeSlider->setVolume(0); - else - m_volumeSlider->setVolume(m_mediaController->volume()); -} - - -void MediaControlsGtk::makeTransparent() -{ - MediaControls::makeTransparent(); - - if (m_volumeSliderContainer) - m_volumeSliderContainer->hide(); - - hideClosedCaptionTrackList(); -} - -void MediaControlsGtk::showVolumeSlider() -{ - if (!m_mediaController->hasAudio()) - return; - - if (m_volumeSliderContainer) - m_volumeSliderContainer->show(); -} - -#if ENABLE(VIDEO_TRACK) -void MediaControlsGtk::createTextTrackDisplay() -{ - if (m_textDisplayContainer) - return; - - RefPtr<MediaControlTextTrackContainerElement> textDisplayContainer = MediaControlTextTrackContainerElement::create(document()); - m_textDisplayContainer = textDisplayContainer.get(); - - if (m_mediaController) - m_textDisplayContainer->setMediaController(m_mediaController); - - // Insert it before the first controller element so it always displays behind the controls. - insertBefore(textDisplayContainer.release(), m_enclosure, ASSERT_NO_EXCEPTION); -} -#endif - -void MediaControlsGtk::toggleClosedCaptionTrackList() -{ - if (!m_mediaController->hasClosedCaptions()) - return; - - if (!m_closedCaptionsContainer || !m_closedCaptionsTrackList) - return; - - if (m_closedCaptionsContainer->isShowing()) { - hideClosedCaptionTrackList(); - return; - } - - m_closedCaptionsTrackList->updateDisplay(); - showClosedCaptionTrackList(); -} - -void MediaControlsGtk::showClosedCaptionTrackList() -{ - m_volumeSliderContainer->hide(); - - if (!m_closedCaptionsContainer || m_closedCaptionsContainer->isShowing()) - return; - - m_closedCaptionsContainer->show(); - m_panel->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone); - - RefPtr<EventListener> listener = eventListener(); - - // Check for clicks outside the media-control - document().addEventListener(eventNames().clickEvent, listener, true); - // Check for clicks inside the media-control box - addEventListener(eventNames().clickEvent, listener, true); -} - -void MediaControlsGtk::hideClosedCaptionTrackList() -{ - if (!m_closedCaptionsContainer || !m_closedCaptionsContainer->isShowing()) - return; - - m_closedCaptionsContainer->hide(); - m_panel->removeInlineStyleProperty(CSSPropertyPointerEvents); - - EventListener* listener = eventListener().get(); - - document().removeEventListener(eventNames().clickEvent, listener, true); - removeEventListener(eventNames().clickEvent, listener, true); -} - -void MediaControlsGtk::handleClickEvent(Event *event) -{ - Node* currentTarget = event->currentTarget()->toNode(); - Node* target = event->target()->toNode(); - - if ((currentTarget == &document() && !shadowHost()->contains(target)) - || (currentTarget == this && !m_closedCaptionsContainer->contains(target))) { - hideClosedCaptionTrackList(); - event->stopImmediatePropagation(); - event->setDefaultHandled(); - } -} - -PassRefPtr<MediaControlsGtkEventListener> MediaControlsGtk::eventListener() -{ - if (!m_eventListener) - m_eventListener = MediaControlsGtkEventListener::create(this); - - return m_eventListener; -} - -void MediaControlsGtkEventListener::handleEvent(ScriptExecutionContext*, Event* event) -{ - if (event->type() == eventNames().clickEvent) - m_mediaControls->handleClickEvent(event); - - return; -} - -bool MediaControlsGtkEventListener::operator==(const EventListener& listener) -{ - if (const MediaControlsGtkEventListener* mediaControlsGtkEventListener = MediaControlsGtkEventListener::cast(&listener)) - return m_mediaControls == mediaControlsGtkEventListener->m_mediaControls; - return false; -} - -} -#endif diff --git a/Source/WebCore/html/shadow/MediaControlsGtk.h b/Source/WebCore/html/shadow/MediaControlsGtk.h deleted file mode 100644 index b444ca33e..000000000 --- a/Source/WebCore/html/shadow/MediaControlsGtk.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2011, 2012 Google Inc. All rights reserved. - * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> - * Copyright (C) 2012 Igalia S.L. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaControlsGtk_h -#define MediaControlsGtk_h - -#if ENABLE(VIDEO) - -#include "MediaControls.h" - -namespace WebCore { - -class MediaControlsGtkEventListener; - -class MediaControlsGtk : public MediaControls { -public: - // Called from port-specific parent create function to create custom controls. - static PassRefPtr<MediaControlsGtk> createControls(Document&); - - virtual void setMediaController(MediaControllerInterface*) override; - virtual void reset() override; - virtual void playbackStarted() override; - void changedMute() override; - virtual void updateCurrentTimeDisplay() override; - virtual void showVolumeSlider() override; - virtual void makeTransparent() override; - virtual void toggleClosedCaptionTrackList() override; - - void handleClickEvent(Event*); - -#if ENABLE(VIDEO_TRACK) - void createTextTrackDisplay() override; -#endif - -protected: - explicit MediaControlsGtk(Document&); - bool initializeControls(Document&); - -private: - void showClosedCaptionTrackList(); - void hideClosedCaptionTrackList(); - - PassRefPtr<MediaControlsGtkEventListener> eventListener(); - - MediaControlTimeRemainingDisplayElement* m_durationDisplay; - MediaControlPanelEnclosureElement* m_enclosure; - MediaControlVolumeSliderContainerElement* m_volumeSliderContainer; - MediaControlClosedCaptionsTrackListElement* m_closedCaptionsTrackList; - MediaControlClosedCaptionsContainerElement* m_closedCaptionsContainer; - - RefPtr<MediaControlsGtkEventListener> m_eventListener; -}; - -} - -#endif - -#endif diff --git a/Source/WebCore/html/shadow/MeterShadowElement.cpp b/Source/WebCore/html/shadow/MeterShadowElement.cpp deleted file mode 100644 index f34a9c496..000000000 --- a/Source/WebCore/html/shadow/MeterShadowElement.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if ENABLE(METER_ELEMENT) -#include "MeterShadowElement.h" - -#include "CSSPropertyNames.h" -#include "HTMLMeterElement.h" -#include "HTMLNames.h" -#include "RenderMeter.h" -#include "RenderTheme.h" -#include "ShadowRoot.h" -#include "StyleProperties.h" - -namespace WebCore { - -using namespace HTMLNames; - -MeterShadowElement::MeterShadowElement(Document& document) - : HTMLDivElement(HTMLNames::divTag, document) -{ -} - -HTMLMeterElement* MeterShadowElement::meterElement() const -{ - return toHTMLMeterElement(shadowHost()); -} - -bool MeterShadowElement::rendererIsNeeded(const RenderStyle& style) -{ - auto render = meterElement()->renderer(); - return render && !render->theme().supportsMeter(render->style().appearance()) && HTMLDivElement::rendererIsNeeded(style); -} - -MeterInnerElement::MeterInnerElement(Document& document) - : MeterShadowElement(document) -{ - DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-meter-inner-element", AtomicString::ConstructFromLiteral)); - setPseudo(pseudoId); -} - -bool MeterInnerElement::rendererIsNeeded(const RenderStyle& style) -{ - if (meterElement()->hasAuthorShadowRoot()) - return HTMLDivElement::rendererIsNeeded(style); - - auto render = meterElement()->renderer(); - return render && !render->theme().supportsMeter(render->style().appearance()) && HTMLDivElement::rendererIsNeeded(style); -} - -RenderPtr<RenderElement> MeterInnerElement::createElementRenderer(PassRef<RenderStyle> style) -{ - return createRenderer<RenderMeter>(*this, std::move(style)); -} - -const AtomicString& MeterValueElement::valuePseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, optimumPseudoId, ("-webkit-meter-optimum-value", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, suboptimumPseudoId, ("-webkit-meter-suboptimum-value", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, evenLessGoodPseudoId, ("-webkit-meter-even-less-good-value", AtomicString::ConstructFromLiteral)); - - HTMLMeterElement* meter = meterElement(); - if (!meter) - return optimumPseudoId; - - switch (meter->gaugeRegion()) { - case HTMLMeterElement::GaugeRegionOptimum: - return optimumPseudoId; - case HTMLMeterElement::GaugeRegionSuboptimal: - return suboptimumPseudoId; - case HTMLMeterElement::GaugeRegionEvenLessGood: - return evenLessGoodPseudoId; - default: - ASSERT_NOT_REACHED(); - return optimumPseudoId; - } -} - -void MeterValueElement::setWidthPercentage(double width) -{ - setInlineStyleProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); -} - -} - -#endif - diff --git a/Source/WebCore/html/shadow/MeterShadowElement.h b/Source/WebCore/html/shadow/MeterShadowElement.h deleted file mode 100644 index a3cf162d9..000000000 --- a/Source/WebCore/html/shadow/MeterShadowElement.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MeterShadowElement_h -#define MeterShadowElement_h - -#if ENABLE(METER_ELEMENT) -#include "HTMLDivElement.h" -#include <wtf/Forward.h> - -namespace WebCore { - -class HTMLMeterElement; -class RenderMeter; - -class MeterShadowElement : public HTMLDivElement { -public: - HTMLMeterElement* meterElement() const; - -protected: - MeterShadowElement(Document&); - -private: - virtual bool rendererIsNeeded(const RenderStyle&) override; -}; - -class MeterInnerElement final : public MeterShadowElement { -public: - static PassRefPtr<MeterInnerElement> create(Document&); - -private: - MeterInnerElement(Document&); - - virtual bool rendererIsNeeded(const RenderStyle&) override; - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; -}; - -inline PassRefPtr<MeterInnerElement> MeterInnerElement::create(Document& document) -{ - return adoptRef(new MeterInnerElement(document)); -} - -class MeterBarElement final : public MeterShadowElement { -public: - static PassRefPtr<MeterBarElement> create(Document&); - -private: - MeterBarElement(Document& document) - : MeterShadowElement(document) - { - DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-meter-bar", AtomicString::ConstructFromLiteral)); - setPseudo(pseudoId); - } -}; - -inline PassRefPtr<MeterBarElement> MeterBarElement::create(Document& document) -{ - return adoptRef(new MeterBarElement(document)); -} - -class MeterValueElement final : public MeterShadowElement { -public: - static PassRefPtr<MeterValueElement> create(Document&); - void setWidthPercentage(double); - void updatePseudo() { setPseudo(valuePseudoId()); } - -private: - MeterValueElement(Document& document) - : MeterShadowElement(document) - { - updatePseudo(); - } - - const AtomicString& valuePseudoId() const; -}; - -inline PassRefPtr<MeterValueElement> MeterValueElement::create(Document& document) -{ - return adoptRef(new MeterValueElement(document)); -} - -} -#endif // ENABLE(METER_ELEMENT) -#endif // MeterShadowElement_h diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.cpp b/Source/WebCore/html/shadow/ProgressShadowElement.cpp index 112e77814..e23ac216b 100644 --- a/Source/WebCore/html/shadow/ProgressShadowElement.cpp +++ b/Source/WebCore/html/shadow/ProgressShadowElement.cpp @@ -29,7 +29,6 @@ */ #include "config.h" -#if ENABLE(PROGRESS_ELEMENT) #include "ProgressShadowElement.h" #include "HTMLNames.h" @@ -47,7 +46,7 @@ ProgressShadowElement::ProgressShadowElement(Document& document) HTMLProgressElement* ProgressShadowElement::progressElement() const { - return toHTMLProgressElement(shadowHost()); + return downcast<HTMLProgressElement>(shadowHost()); } bool ProgressShadowElement::rendererIsNeeded(const RenderStyle& style) @@ -61,16 +60,13 @@ ProgressInnerElement::ProgressInnerElement(Document& document) { } -RenderPtr<RenderElement> ProgressInnerElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> ProgressInnerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderProgress>(*this, std::move(style)); + return createRenderer<RenderProgress>(*this, WTFMove(style)); } bool ProgressInnerElement::rendererIsNeeded(const RenderStyle& style) { - if (progressElement()->hasAuthorShadowRoot()) - return HTMLDivElement::rendererIsNeeded(style); - RenderObject* progressRenderer = progressElement()->renderer(); return progressRenderer && !progressRenderer->style().hasAppearance() && HTMLDivElement::rendererIsNeeded(style); } @@ -91,4 +87,3 @@ void ProgressValueElement::setWidthPercentage(double width) } } -#endif diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.h b/Source/WebCore/html/shadow/ProgressShadowElement.h index 78bc49ec4..f7ccb500a 100644 --- a/Source/WebCore/html/shadow/ProgressShadowElement.h +++ b/Source/WebCore/html/shadow/ProgressShadowElement.h @@ -29,10 +29,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ProgressShadowElement_h -#define ProgressShadowElement_h +#pragma once -#if ENABLE(PROGRESS_ELEMENT) #include "HTMLDivElement.h" #include <wtf/Forward.h> @@ -48,58 +46,56 @@ protected: ProgressShadowElement(Document&); private: - virtual bool rendererIsNeeded(const RenderStyle&) override; + bool rendererIsNeeded(const RenderStyle&) override; }; class ProgressInnerElement final : public ProgressShadowElement { public: - static PassRefPtr<ProgressInnerElement> create(Document&); + static Ref<ProgressInnerElement> create(Document&); private: ProgressInnerElement(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; - virtual bool rendererIsNeeded(const RenderStyle&) override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; + bool rendererIsNeeded(const RenderStyle&) override; }; -inline PassRefPtr<ProgressInnerElement> ProgressInnerElement::create(Document& document) +inline Ref<ProgressInnerElement> ProgressInnerElement::create(Document& document) { - RefPtr<ProgressInnerElement> result = adoptRef(new ProgressInnerElement(document)); + Ref<ProgressInnerElement> result = adoptRef(*new ProgressInnerElement(document)); result->setPseudo(AtomicString("-webkit-progress-inner-element", AtomicString::ConstructFromLiteral)); return result; } class ProgressBarElement final : public ProgressShadowElement { public: - static PassRefPtr<ProgressBarElement> create(Document&); + static Ref<ProgressBarElement> create(Document&); private: ProgressBarElement(Document&); }; -inline PassRefPtr<ProgressBarElement> ProgressBarElement::create(Document& document) +inline Ref<ProgressBarElement> ProgressBarElement::create(Document& document) { - RefPtr<ProgressBarElement> result = adoptRef(new ProgressBarElement(document)); + Ref<ProgressBarElement> result = adoptRef(*new ProgressBarElement(document)); result->setPseudo(AtomicString("-webkit-progress-bar", AtomicString::ConstructFromLiteral)); return result; } class ProgressValueElement final : public ProgressShadowElement { public: - static PassRefPtr<ProgressValueElement> create(Document&); + static Ref<ProgressValueElement> create(Document&); void setWidthPercentage(double); private: ProgressValueElement(Document&); }; -inline PassRefPtr<ProgressValueElement> ProgressValueElement::create(Document& document) +inline Ref<ProgressValueElement> ProgressValueElement::create(Document& document) { - RefPtr<ProgressValueElement> result = adoptRef(new ProgressValueElement(document)); + Ref<ProgressValueElement> result = adoptRef(*new ProgressValueElement(document)); result->setPseudo(AtomicString("-webkit-progress-value", AtomicString::ConstructFromLiteral)); return result; } -} -#endif // ENABLE(PROGRESS_ELEMENT) -#endif // ProgressShadowElement_h +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp index 33dbf2e52..87a2e4d37 100644 --- a/Source/WebCore/html/shadow/SliderThumbElement.cpp +++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp @@ -36,6 +36,7 @@ #include "CSSValueKeywords.h" #include "Event.h" #include "EventHandler.h" +#include "EventNames.h" #include "Frame.h" #include "HTMLInputElement.h" #include "HTMLParserIdioms.h" @@ -44,8 +45,9 @@ #include "RenderSlider.h" #include "RenderTheme.h" #include "ShadowRoot.h" +#include "StyleResolver.h" -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) #include "Document.h" #include "Page.h" #include "TouchEvent.h" @@ -55,20 +57,20 @@ namespace WebCore { using namespace HTMLNames; -inline static Decimal sliderPosition(HTMLInputElement* element) +inline static Decimal sliderPosition(HTMLInputElement& element) { - const StepRange stepRange(element->createStepRange(RejectAny)); - const Decimal oldValue = parseToDecimalForNumberType(element->value(), stepRange.defaultValue()); + const StepRange stepRange(element.createStepRange(RejectAny)); + const Decimal oldValue = parseToDecimalForNumberType(element.value(), stepRange.defaultValue()); return stepRange.proportionFromValue(stepRange.clampValue(oldValue)); } -inline static bool hasVerticalAppearance(HTMLInputElement* input) +inline static bool hasVerticalAppearance(HTMLInputElement& input) { - ASSERT(input->renderer()); - const RenderStyle& sliderStyle = input->renderer()->style(); + ASSERT(input.renderer()); + const RenderStyle& sliderStyle = input.renderer()->style(); #if ENABLE(VIDEO) - if (sliderStyle.appearance() == MediaVolumeSliderPart && input->renderer()->theme().usesVerticalVolumeSlider()) + if (sliderStyle.appearance() == MediaVolumeSliderPart && input.renderer()->theme().usesVerticalVolumeSlider()) return true; #endif @@ -77,25 +79,27 @@ inline static bool hasVerticalAppearance(HTMLInputElement* input) // -------------------------------- -RenderSliderThumb::RenderSliderThumb(SliderThumbElement& element, PassRef<RenderStyle> style) - : RenderBlockFlow(element, std::move(style)) +RenderSliderThumb::RenderSliderThumb(SliderThumbElement& element, RenderStyle&& style) + : RenderBlockFlow(element, WTFMove(style)) { } -void RenderSliderThumb::updateAppearance(RenderStyle* parentStyle) +void RenderSliderThumb::updateAppearance(const RenderStyle* parentStyle) { if (parentStyle->appearance() == SliderVerticalPart) - style().setAppearance(SliderThumbVerticalPart); + mutableStyle().setAppearance(SliderThumbVerticalPart); else if (parentStyle->appearance() == SliderHorizontalPart) - style().setAppearance(SliderThumbHorizontalPart); + mutableStyle().setAppearance(SliderThumbHorizontalPart); else if (parentStyle->appearance() == MediaSliderPart) - style().setAppearance(MediaSliderThumbPart); + mutableStyle().setAppearance(MediaSliderThumbPart); else if (parentStyle->appearance() == MediaVolumeSliderPart) - style().setAppearance(MediaVolumeSliderThumbPart); + mutableStyle().setAppearance(MediaVolumeSliderThumbPart); else if (parentStyle->appearance() == MediaFullScreenVolumeSliderPart) - style().setAppearance(MediaFullScreenVolumeSliderThumbPart); - if (style().hasAppearance()) - theme().adjustSliderThumbSize(&style(), element()); + mutableStyle().setAppearance(MediaFullScreenVolumeSliderThumbPart); + if (style().hasAppearance()) { + ASSERT(element()); + theme().adjustSliderThumbSize(mutableStyle(), element()); + } } bool RenderSliderThumb::isSliderThumb() const @@ -107,27 +111,29 @@ bool RenderSliderThumb::isSliderThumb() const // FIXME: Find a way to cascade appearance and adjust heights, and get rid of this class. // http://webkit.org/b/62535 -class RenderSliderContainer : public RenderFlexibleBox { +class RenderSliderContainer final : public RenderFlexibleBox { public: - RenderSliderContainer(SliderContainerElement& element, PassRef<RenderStyle> style) - : RenderFlexibleBox(element, std::move(style)) + RenderSliderContainer(SliderContainerElement& element, RenderStyle&& style) + : RenderFlexibleBox(element, WTFMove(style)) { } public: - virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override; + RenderBox::LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override; private: - virtual void layout() override; + void layout() override; + bool isFlexibleBoxImpl() const override { return true; } }; -void RenderSliderContainer::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const +RenderBox::LogicalExtentComputedValues RenderSliderContainer::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const { - HTMLInputElement* input = element()->shadowHost()->toInputElement(); + ASSERT(element()->shadowHost()); + auto& input = downcast<HTMLInputElement>(*element()->shadowHost()); bool isVertical = hasVerticalAppearance(input); #if ENABLE(DATALIST_ELEMENT) - if (input->renderer()->isSlider() && !isVertical && input->list()) { + if (input.renderer()->isSlider() && !isVertical && input.list()) { int offsetFromCenter = theme().sliderTickOffsetFromTrackCenter(); LayoutUnit trackHeight = 0; if (offsetFromCenter < 0) @@ -140,30 +146,30 @@ void RenderSliderContainer::computeLogicalHeight(LayoutUnit logicalHeight, Layou if (zoomFactor != 1.0) trackHeight *= zoomFactor; - RenderBox::computeLogicalHeight(trackHeight, logicalTop, computedValues); - return; + return RenderBox::computeLogicalHeight(trackHeight, logicalTop); } #endif if (isVertical) logicalHeight = RenderSlider::defaultTrackLength; - RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); + return RenderBox::computeLogicalHeight(logicalHeight, logicalTop); } void RenderSliderContainer::layout() { - HTMLInputElement* input = element()->shadowHost()->toInputElement(); + ASSERT(element()->shadowHost()); + auto& input = downcast<HTMLInputElement>(*element()->shadowHost()); bool isVertical = hasVerticalAppearance(input); - style().setFlexDirection(isVertical ? FlowColumn : FlowRow); + mutableStyle().setFlexDirection(isVertical ? FlowColumn : FlowRow); TextDirection oldTextDirection = style().direction(); if (isVertical) { // FIXME: Work around rounding issues in RTL vertical sliders. We want them to // render identically to LTR vertical sliders. We can remove this work around when // subpixel rendering is enabled on all ports. - style().setDirection(LTR); + mutableStyle().setDirection(LTR); } - RenderBox* thumb = input->sliderThumbElement() ? input->sliderThumbElement()->renderBox() : 0; - RenderBox* track = input->sliderTrackElement() ? input->sliderTrackElement()->renderBox() : 0; + RenderBox* thumb = input.sliderThumbElement() ? input.sliderThumbElement()->renderBox() : nullptr; + RenderBox* track = input.sliderTrackElement() ? input.sliderTrackElement()->renderBox() : nullptr; // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place. // FIXME: Make a custom Render class for the track and move the thumb positioning code there. if (track) @@ -171,7 +177,7 @@ void RenderSliderContainer::layout() RenderFlexibleBox::layout(); - style().setDirection(oldTextDirection); + mutableStyle().setDirection(oldTextDirection); // These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector). if (!thumb || !track) return; @@ -188,6 +194,7 @@ void RenderSliderContainer::layout() else thumbLocation.setX(thumbLocation.x() - offset); thumb->setLocation(thumbLocation); + thumb->repaint(); } // -------------------------------- @@ -195,7 +202,7 @@ void RenderSliderContainer::layout() SliderThumbElement::SliderThumbElement(Document& document) : HTMLDivElement(HTMLNames::divTag, document) , m_inDragMode(false) -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) , m_exclusiveTouchIdentifier(NoIdentifier) , m_isRegisteredAsTouchEventListener(false) #endif @@ -212,9 +219,9 @@ void SliderThumbElement::setPositionFromValue() renderer()->setNeedsLayout(); } -RenderPtr<RenderElement> SliderThumbElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> SliderThumbElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderSliderThumb>(*this, std::move(style)); + return createRenderer<RenderSliderThumb>(*this, WTFMove(style)); } bool SliderThumbElement::isDisabledFormControl() const @@ -223,12 +230,6 @@ bool SliderThumbElement::isDisabledFormControl() const return !input || input->isDisabledFormControl(); } -bool SliderThumbElement::matchesReadOnlyPseudoClass() const -{ - HTMLInputElement* input = hostInput(); - return input && input->matchesReadOnlyPseudoClass(); -} - bool SliderThumbElement::matchesReadWritePseudoClass() const { HTMLInputElement* input = hostInput(); @@ -242,7 +243,7 @@ Element* SliderThumbElement::focusDelegate() void SliderThumbElement::dragFrom(const LayoutPoint& point) { - Ref<SliderThumbElement> protect(*this); + Ref<SliderThumbElement> protectedThis(*this); setPositionFromPoint(point); #if !PLATFORM(IOS) startDragging(); @@ -252,52 +253,56 @@ void SliderThumbElement::dragFrom(const LayoutPoint& point) void SliderThumbElement::setPositionFromPoint(const LayoutPoint& absolutePoint) { RefPtr<HTMLInputElement> input = hostInput(); - if (!input || !input->renderer() || !renderBox()) + if (!input) return; - HTMLElement* trackElement = input->sliderTrackElement(); - if (!trackElement->renderBox()) + auto* inputRenderer = input->renderBox(); + if (!inputRenderer) return; - input->setTextAsOfLastFormControlChangeEvent(input->value()); + auto* thumbRenderer = renderBox(); + if (!thumbRenderer) + return; + + ASSERT(input->sliderTrackElement()); + auto* trackRenderer = input->sliderTrackElement()->renderBox(); + if (!trackRenderer) + return; // Do all the tracking math relative to the input's renderer's box. - RenderBox& inputRenderer = *toRenderBox(input->renderer()); - RenderBox& trackRenderer = *trackElement->renderBox(); - bool isVertical = hasVerticalAppearance(input.get()); - bool isLeftToRightDirection = renderBox()->style().isLeftToRightDirection(); + bool isVertical = hasVerticalAppearance(*input); + bool isLeftToRightDirection = thumbRenderer->style().isLeftToRightDirection(); - LayoutPoint offset = roundedLayoutPoint(inputRenderer.absoluteToLocal(absolutePoint, UseTransforms)); - FloatRect trackBoundingBox = trackRenderer.localToContainerQuad(FloatRect(0, 0, trackRenderer.width(), trackRenderer.height()), &inputRenderer).enclosingBoundingBox(); + auto offset = inputRenderer->absoluteToLocal(absolutePoint, UseTransforms); + auto trackBoundingBox = trackRenderer->localToContainerQuad(FloatRect { { }, trackRenderer->size() }, inputRenderer).enclosingBoundingBox(); LayoutUnit trackLength; LayoutUnit position; if (isVertical) { - trackLength = trackRenderer.contentHeight() - renderBox()->height(); - position = offset.y() - renderBox()->height() / 2 - trackBoundingBox.y() - renderBox()->marginBottom(); + trackLength = trackRenderer->contentHeight() - thumbRenderer->height(); + position = offset.y() - thumbRenderer->height() / 2 - trackBoundingBox.y() - thumbRenderer->marginBottom(); } else { - trackLength = trackRenderer.contentWidth() - renderBox()->width(); - position = offset.x() - renderBox()->width() / 2 - trackBoundingBox.x(); - position -= isLeftToRightDirection ? renderBox()->marginLeft() : renderBox()->marginRight(); + trackLength = trackRenderer->contentWidth() - thumbRenderer->width(); + position = offset.x() - thumbRenderer->width() / 2 - trackBoundingBox.x(); + position -= isLeftToRightDirection ? thumbRenderer->marginLeft() : thumbRenderer->marginRight(); } position = std::max<LayoutUnit>(0, std::min(position, trackLength)); - const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackLength); - const Decimal fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio; - StepRange stepRange(input->createStepRange(RejectAny)); - Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction)); + auto ratio = Decimal::fromDouble(static_cast<double>(position) / trackLength); + auto fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio; + auto stepRange = input->createStepRange(RejectAny); + auto value = stepRange.clampValue(stepRange.valueFromProportion(fraction)); #if ENABLE(DATALIST_ELEMENT) const LayoutUnit snappingThreshold = renderer()->theme().sliderTickSnappingThreshold(); if (snappingThreshold > 0) { - Decimal closest = input->findClosestTickMarkValue(value); - if (closest.isFinite()) { - double closestFraction = stepRange.proportionFromValue(closest).toDouble(); + if (std::optional<Decimal> closest = input->findClosestTickMarkValue(value)) { + double closestFraction = stepRange.proportionFromValue(*closest).toDouble(); double closestRatio = isVertical || !isLeftToRightDirection ? 1.0 - closestFraction : closestFraction; LayoutUnit closestPosition = trackLength * closestRatio; if ((closestPosition - position).abs() <= snappingThreshold) - value = closest; + value = *closest; } } #endif @@ -310,7 +315,6 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& absolutePoint) input->setValueFromRenderer(valueString); if (renderer()) renderer()->setNeedsLayout(); - input->dispatchFormControlChangeEvent(); } void SliderThumbElement::startDragging() @@ -334,9 +338,9 @@ void SliderThumbElement::stopDragging() } #if !PLATFORM(IOS) -void SliderThumbElement::defaultEventHandler(Event* event) +void SliderThumbElement::defaultEventHandler(Event& event) { - if (!event->isMouseEvent()) { + if (!is<MouseEvent>(event)) { HTMLDivElement::defaultEventHandler(event); return; } @@ -344,15 +348,15 @@ void SliderThumbElement::defaultEventHandler(Event* event) // FIXME: Should handle this readonly/disabled check in more general way. // Missing this kind of check is likely to occur elsewhere if adding it in each shadow element. HTMLInputElement* input = hostInput(); - if (!input || input->isDisabledOrReadOnly()) { + if (!input || input->isDisabledFormControl()) { stopDragging(); HTMLDivElement::defaultEventHandler(event); return; } - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - bool isLeftButton = mouseEvent->button() == LeftButton; - const AtomicString& eventType = event->type(); + MouseEvent& mouseEvent = downcast<MouseEvent>(event); + bool isLeftButton = mouseEvent.button() == LeftButton; + const AtomicString& eventType = mouseEvent.type(); // We intentionally do not call event->setDefaultHandled() here because // MediaControlTimelineElement::defaultEventHandler() wants to handle these @@ -361,15 +365,16 @@ void SliderThumbElement::defaultEventHandler(Event* event) startDragging(); return; } else if (eventType == eventNames().mouseupEvent && isLeftButton) { + input->dispatchFormControlChangeEvent(); stopDragging(); return; } else if (eventType == eventNames().mousemoveEvent) { if (m_inDragMode) - setPositionFromPoint(mouseEvent->absoluteLocation()); + setPositionFromPoint(mouseEvent.absoluteLocation()); return; } - HTMLDivElement::defaultEventHandler(event); + HTMLDivElement::defaultEventHandler(mouseEvent); } #endif @@ -377,7 +382,7 @@ void SliderThumbElement::defaultEventHandler(Event* event) bool SliderThumbElement::willRespondToMouseMoveEvents() { const HTMLInputElement* input = hostInput(); - if (input && !input->isDisabledOrReadOnly() && m_inDragMode) + if (input && !input->isDisabledFormControl() && m_inDragMode) return true; return HTMLDivElement::willRespondToMouseMoveEvents(); @@ -386,7 +391,7 @@ bool SliderThumbElement::willRespondToMouseMoveEvents() bool SliderThumbElement::willRespondToMouseClickEvents() { const HTMLInputElement* input = hostInput(); - if (input && !input->isDisabledOrReadOnly()) + if (input && !input->isDisabledFormControl()) return true; return HTMLDivElement::willRespondToMouseClickEvents(); @@ -399,12 +404,12 @@ void SliderThumbElement::willDetachRenderers() if (Frame* frame = document().frame()) frame->eventHandler().setCapturingMouseEventsElement(nullptr); } -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) unregisterForTouchEvents(); #endif } -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) unsigned SliderThumbElement::exclusiveTouchIdentifier() const { return m_exclusiveTouchIdentifier; @@ -421,64 +426,79 @@ void SliderThumbElement::clearExclusiveTouchIdentifier() m_exclusiveTouchIdentifier = NoIdentifier; } -static Touch* findTouchWithIdentifier(TouchList* list, unsigned identifier) +static Touch* findTouchWithIdentifier(TouchList& list, unsigned identifier) { - unsigned length = list->length(); + unsigned length = list.length(); for (unsigned i = 0; i < length; ++i) { - Touch* touch = list->item(i); + Touch* touch = list.item(i); if (touch->identifier() == identifier) return touch; } return nullptr; } -void SliderThumbElement::handleTouchStart(TouchEvent* touchEvent) +void SliderThumbElement::handleTouchStart(TouchEvent& touchEvent) { - TouchList* targetTouches = touchEvent->targetTouches(); + TouchList* targetTouches = touchEvent.targetTouches(); + if (!targetTouches) + return; + if (targetTouches->length() != 1) return; - // Ignore the touch if it is not really inside the thumb. Touch* touch = targetTouches->item(0); + if (!renderer()) + return; IntRect boundingBox = renderer()->absoluteBoundingBoxRect(); + // Ignore the touch if it is not really inside the thumb. if (!boundingBox.contains(touch->pageX(), touch->pageY())) return; setExclusiveTouchIdentifier(touch->identifier()); startDragging(); - touchEvent->setDefaultHandled(); + touchEvent.setDefaultHandled(); } -void SliderThumbElement::handleTouchMove(TouchEvent* touchEvent) +void SliderThumbElement::handleTouchMove(TouchEvent& touchEvent) { unsigned identifier = exclusiveTouchIdentifier(); if (identifier == NoIdentifier) return; - Touch* touch = findTouchWithIdentifier(touchEvent->targetTouches(), identifier); + TouchList* targetTouches = touchEvent.targetTouches(); + if (!targetTouches) + return; + + Touch* touch = findTouchWithIdentifier(*targetTouches, identifier); if (!touch) return; if (m_inDragMode) setPositionFromPoint(IntPoint(touch->pageX(), touch->pageY())); - touchEvent->setDefaultHandled(); + touchEvent.setDefaultHandled(); } -void SliderThumbElement::handleTouchEndAndCancel(TouchEvent* touchEvent) +void SliderThumbElement::handleTouchEndAndCancel(TouchEvent& touchEvent) { unsigned identifier = exclusiveTouchIdentifier(); if (identifier == NoIdentifier) return; + TouchList* targetTouches = touchEvent.targetTouches(); + if (!targetTouches) + return; // If our exclusive touch still exists, it was not the touch // that ended, so we should not stop dragging. - Touch* exclusiveTouch = findTouchWithIdentifier(touchEvent->targetTouches(), identifier); + Touch* exclusiveTouch = findTouchWithIdentifier(*targetTouches, identifier); if (exclusiveTouch) return; clearExclusiveTouchIdentifier(); + RefPtr<HTMLInputElement> input = hostInput(); + if (input) + input->dispatchFormControlChangeEvent(); stopDragging(); } @@ -488,19 +508,19 @@ void SliderThumbElement::didAttachRenderers() registerForTouchEvents(); } -void SliderThumbElement::handleTouchEvent(TouchEvent* touchEvent) +void SliderThumbElement::handleTouchEvent(TouchEvent& touchEvent) { HTMLInputElement* input = hostInput(); ASSERT(input); if (input->isReadOnly() || input->isDisabledFormControl()) { clearExclusiveTouchIdentifier(); stopDragging(); - touchEvent->setDefaultHandled(); + touchEvent.setDefaultHandled(); HTMLDivElement::defaultEventHandler(touchEvent); return; } - const AtomicString& eventType = touchEvent->type(); + const AtomicString& eventType = touchEvent.type(); if (eventType == eventNames().touchstartEvent) { handleTouchStart(touchEvent); return; @@ -529,7 +549,7 @@ void SliderThumbElement::registerForTouchEvents() ASSERT(shouldAcceptTouchEvents()); - document().addTouchEventListener(this); + document().addTouchEventHandler(this); m_isRegisteredAsTouchEventListener = true; } @@ -541,7 +561,7 @@ void SliderThumbElement::unregisterForTouchEvents() clearExclusiveTouchIdentifier(); stopDragging(); - document().removeTouchEventListener(this); + document().removeTouchEventHandler(this); m_isRegisteredAsTouchEventListener = false; } @@ -552,53 +572,49 @@ void SliderThumbElement::disabledAttributeChanged() else unregisterForTouchEvents(); } -#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#endif // ENABLE(IOS_TOUCH_EVENTS) HTMLInputElement* SliderThumbElement::hostInput() const { // Only HTMLInputElement creates SliderThumbElement instances as its shadow nodes. // So, shadowHost() must be an HTMLInputElement. - Element* host = shadowHost(); - return host ? host->toInputElement() : 0; + return downcast<HTMLInputElement>(shadowHost()); } -static const AtomicString& sliderThumbShadowPseudoId() +std::optional<ElementStyle> SliderThumbElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* hostStyle) { - DEFINE_STATIC_LOCAL(const AtomicString, sliderThumb, ("-webkit-slider-thumb", AtomicString::ConstructFromLiteral)); - return sliderThumb; -} + // This doesn't actually compute style. This is just a hack to pick shadow pseudo id when host style is known. -static const AtomicString& mediaSliderThumbShadowPseudoId() -{ - DEFINE_STATIC_LOCAL(const AtomicString, mediaSliderThumb, ("-webkit-media-slider-thumb", AtomicString::ConstructFromLiteral)); - return mediaSliderThumb; -} + static NeverDestroyed<const AtomicString> sliderThumbShadowPseudoId("-webkit-slider-thumb", AtomicString::ConstructFromLiteral); + static NeverDestroyed<const AtomicString> mediaSliderThumbShadowPseudoId("-webkit-media-slider-thumb", AtomicString::ConstructFromLiteral); -const AtomicString& SliderThumbElement::shadowPseudoId() const -{ - HTMLInputElement* input = hostInput(); - if (!input) - return sliderThumbShadowPseudoId(); - if (!input->renderer()) - return emptyAtom; + if (!hostStyle) + return std::nullopt; - const RenderStyle& sliderStyle = input->renderer()->style(); - switch (sliderStyle.appearance()) { + switch (hostStyle->appearance()) { case MediaSliderPart: case MediaSliderThumbPart: case MediaVolumeSliderPart: case MediaVolumeSliderThumbPart: case MediaFullScreenVolumeSliderPart: case MediaFullScreenVolumeSliderThumbPart: - return mediaSliderThumbShadowPseudoId(); + m_shadowPseudoId = mediaSliderThumbShadowPseudoId; + break; default: - return sliderThumbShadowPseudoId(); + m_shadowPseudoId = sliderThumbShadowPseudoId; } + + return std::nullopt; +} + +const AtomicString& SliderThumbElement::shadowPseudoId() const +{ + return m_shadowPseudoId; } -PassRefPtr<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren() +Ref<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren(Document& targetDocument) { - return create(document()); + return create(targetDocument); } // -------------------------------- @@ -606,41 +622,48 @@ PassRefPtr<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren inline SliderContainerElement::SliderContainerElement(Document& document) : HTMLDivElement(HTMLNames::divTag, document) { + setHasCustomStyleResolveCallbacks(); } -PassRefPtr<SliderContainerElement> SliderContainerElement::create(Document& document) +Ref<SliderContainerElement> SliderContainerElement::create(Document& document) { - return adoptRef(new SliderContainerElement(document)); + return adoptRef(*new SliderContainerElement(document)); } -RenderPtr<RenderElement> SliderContainerElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> SliderContainerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderSliderContainer>(*this, std::move(style)); + return createRenderer<RenderSliderContainer>(*this, WTFMove(style)); } -const AtomicString& SliderContainerElement::shadowPseudoId() const +std::optional<ElementStyle> SliderContainerElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* hostStyle) { - DEFINE_STATIC_LOCAL(const AtomicString, mediaSliderContainer, ("-webkit-media-slider-container", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, sliderContainer, ("-webkit-slider-container", AtomicString::ConstructFromLiteral)); + // This doesn't actually compute style. This is just a hack to pick shadow pseudo id when host style is known. - HTMLInputElement* input = shadowHost()->toInputElement(); - if (!input) - return sliderContainer; - if (!input->renderer()) - return emptyAtom; + static NeverDestroyed<const AtomicString> mediaSliderContainer("-webkit-media-slider-container", AtomicString::ConstructFromLiteral); + static NeverDestroyed<const AtomicString> sliderContainer("-webkit-slider-container", AtomicString::ConstructFromLiteral); + + if (!hostStyle) + return std::nullopt; - const RenderStyle& sliderStyle = input->renderer()->style(); - switch (sliderStyle.appearance()) { + switch (hostStyle->appearance()) { case MediaSliderPart: case MediaSliderThumbPart: case MediaVolumeSliderPart: case MediaVolumeSliderThumbPart: case MediaFullScreenVolumeSliderPart: case MediaFullScreenVolumeSliderThumbPart: - return mediaSliderContainer; + m_shadowPseudoId = mediaSliderContainer; + break; default: - return sliderContainer; + m_shadowPseudoId = sliderContainer; } + + return std::nullopt; +} + +const AtomicString& SliderContainerElement::shadowPseudoId() const +{ + return m_shadowPseudoId; } } diff --git a/Source/WebCore/html/shadow/SliderThumbElement.h b/Source/WebCore/html/shadow/SliderThumbElement.h index a061d63b8..f8a99b375 100644 --- a/Source/WebCore/html/shadow/SliderThumbElement.h +++ b/Source/WebCore/html/shadow/SliderThumbElement.h @@ -29,11 +29,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SliderThumbElement_h -#define SliderThumbElement_h +#pragma once #include "HTMLDivElement.h" -#include "HTMLNames.h" #include "RenderBlockFlow.h" #include <wtf/Forward.h> @@ -45,15 +43,15 @@ class TouchEvent; class SliderThumbElement final : public HTMLDivElement { public: - static PassRefPtr<SliderThumbElement> create(Document&); + static Ref<SliderThumbElement> create(Document&); void setPositionFromValue(); void dragFrom(const LayoutPoint&); HTMLInputElement* hostInput() const; void setPositionFromPoint(const LayoutPoint&); -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) - void handleTouchEvent(TouchEvent*); +#if ENABLE(IOS_TOUCH_EVENTS) + void handleTouchEvent(TouchEvent&); void disabledAttributeChanged(); #endif @@ -61,81 +59,90 @@ public: private: SliderThumbElement(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; - virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() override; - virtual bool isDisabledFormControl() const override; - virtual bool matchesReadOnlyPseudoClass() const override; - virtual bool matchesReadWritePseudoClass() const override; - virtual Element* focusDelegate() override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; + + Ref<Element> cloneElementWithoutAttributesAndChildren(Document&) override; + bool isDisabledFormControl() const override; + bool matchesReadWritePseudoClass() const override; + Element* focusDelegate() override; #if !PLATFORM(IOS) - virtual void defaultEventHandler(Event*) override; - virtual bool willRespondToMouseMoveEvents() override; - virtual bool willRespondToMouseClickEvents() override; + void defaultEventHandler(Event&) override; + bool willRespondToMouseMoveEvents() override; + bool willRespondToMouseClickEvents() override; #endif -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) - virtual void didAttachRenderers() override; +#if ENABLE(IOS_TOUCH_EVENTS) + void didAttachRenderers() override; #endif - virtual void willDetachRenderers() override; + void willDetachRenderers() override; - virtual const AtomicString& shadowPseudoId() const override; + std::optional<ElementStyle> resolveCustomStyle(const RenderStyle&, const RenderStyle*) override; + const AtomicString& shadowPseudoId() const override; void startDragging(); void stopDragging(); -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) unsigned exclusiveTouchIdentifier() const; void setExclusiveTouchIdentifier(unsigned); void clearExclusiveTouchIdentifier(); - void handleTouchStart(TouchEvent*); - void handleTouchMove(TouchEvent*); - void handleTouchEndAndCancel(TouchEvent*); + void handleTouchStart(TouchEvent&); + void handleTouchMove(TouchEvent&); + void handleTouchEndAndCancel(TouchEvent&); bool shouldAcceptTouchEvents(); void registerForTouchEvents(); void unregisterForTouchEvents(); #endif + AtomicString m_shadowPseudoId; bool m_inDragMode; -#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) +#if ENABLE(IOS_TOUCH_EVENTS) // FIXME: Currently it is safe to use 0, but this may need to change - // if touch identifers change in the future and can be 0. + // if touch identifiers change in the future and can be 0. static const unsigned NoIdentifier = 0; unsigned m_exclusiveTouchIdentifier; bool m_isRegisteredAsTouchEventListener; #endif }; -inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(Document& document) +inline Ref<SliderThumbElement> SliderThumbElement::create(Document& document) { - return adoptRef(new SliderThumbElement(document)); + return adoptRef(*new SliderThumbElement(document)); } // -------------------------------- class RenderSliderThumb final : public RenderBlockFlow { public: - RenderSliderThumb(SliderThumbElement&, PassRef<RenderStyle>); - void updateAppearance(RenderStyle* parentStyle); + RenderSliderThumb(SliderThumbElement&, RenderStyle&&); + void updateAppearance(const RenderStyle* parentStyle); private: - virtual bool isSliderThumb() const override; + bool isSliderThumb() const override; }; // -------------------------------- class SliderContainerElement final : public HTMLDivElement { public: - static PassRefPtr<SliderContainerElement> create(Document&); + static Ref<SliderContainerElement> create(Document&); private: SliderContainerElement(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; - virtual const AtomicString& shadowPseudoId() const override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; + std::optional<ElementStyle> resolveCustomStyle(const RenderStyle&, const RenderStyle*) override; + const AtomicString& shadowPseudoId() const override; + bool isSliderContainerElement() const override { return true; } + + AtomicString m_shadowPseudoId; }; -} +} // namespace WebCore -#endif +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::SliderContainerElement) + static bool isType(const WebCore::Element& element) { return element.isSliderContainerElement(); } + static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/html/shadow/SpinButtonElement.cpp b/Source/WebCore/html/shadow/SpinButtonElement.cpp index 5e4711a68..98bd72bff 100644 --- a/Source/WebCore/html/shadow/SpinButtonElement.cpp +++ b/Source/WebCore/html/shadow/SpinButtonElement.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -35,6 +35,7 @@ #include "MouseEvent.h" #include "Page.h" #include "RenderBox.h" +#include "RenderTheme.h" #include "ScrollbarTheme.h" #include "WheelEvent.h" #include <wtf/Ref.h> @@ -49,20 +50,15 @@ inline SpinButtonElement::SpinButtonElement(Document& document, SpinButtonOwner& , m_capturing(false) , m_upDownState(Indeterminate) , m_pressStartingState(Indeterminate) - , m_repeatingTimer(this, &SpinButtonElement::repeatingTimerFired) + , m_repeatingTimer(*this, &SpinButtonElement::repeatingTimerFired) { setHasCustomStyleResolveCallbacks(); + setPseudo(AtomicString("-webkit-inner-spin-button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<SpinButtonElement> SpinButtonElement::create(Document& document, SpinButtonOwner& spinButtonOwner) +Ref<SpinButtonElement> SpinButtonElement::create(Document& document, SpinButtonOwner& spinButtonOwner) { - return adoptRef(new SpinButtonElement(document, spinButtonOwner)); -} - -const AtomicString& SpinButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, innerPseudoId, ("-webkit-inner-spin-button", AtomicString::ConstructFromLiteral)); - return innerPseudoId; + return adoptRef(*new SpinButtonElement(document, spinButtonOwner)); } void SpinButtonElement::willDetachRenderers() @@ -70,35 +66,35 @@ void SpinButtonElement::willDetachRenderers() releaseCapture(); } -void SpinButtonElement::defaultEventHandler(Event* event) +void SpinButtonElement::defaultEventHandler(Event& event) { - if (!event->isMouseEvent()) { - if (!event->defaultHandled()) + if (!is<MouseEvent>(event)) { + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RenderBox* box = renderBox(); if (!box) { - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } if (!shouldRespondToMouseEvents()) { - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), UseTransforms)); - if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { - if (box->pixelSnappedBorderBoxRect().contains(local)) { + MouseEvent& mouseEvent = downcast<MouseEvent>(event); + IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent.absoluteLocation(), UseTransforms)); + if (mouseEvent.type() == eventNames().mousedownEvent && mouseEvent.button() == LeftButton) { + if (box->borderBoxRect().contains(local)) { // The following functions of HTMLInputElement may run JavaScript // code which detaches this shadow node. We need to take a reference // and check renderer() after such function calls. - Ref<SpinButtonElement> protect(*this); + Ref<SpinButtonElement> protectedThis(*this); if (m_spinButtonOwner) m_spinButtonOwner->focusAndSelectSpinButtonOwner(); if (renderer()) { @@ -112,22 +108,32 @@ void SpinButtonElement::defaultEventHandler(Event* event) doStepAction(m_upDownState == Up ? 1 : -1); } } - event->setDefaultHandled(); + mouseEvent.setDefaultHandled(); } - } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) + } else if (mouseEvent.type() == eventNames().mouseupEvent && mouseEvent.button() == LeftButton) stopRepeatingTimer(); - else if (event->type() == eventNames().mousemoveEvent) { - if (box->pixelSnappedBorderBoxRect().contains(local)) { + else if (mouseEvent.type() == eventNames().mousemoveEvent) { + if (box->borderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document().frame()) { frame->eventHandler().setCapturingMouseEventsElement(this); m_capturing = true; if (Page* page = document().page()) - page->chrome().registerPopupOpeningObserver(this); + page->chrome().registerPopupOpeningObserver(*this); } } UpDownState oldUpDownState = m_upDownState; - m_upDownState = local.y() < box->height() / 2 ? Up : Down; + switch (renderer()->theme().innerSpinButtonLayout(*renderer())) { + case RenderTheme::InnerSpinButtonLayout::Vertical: + m_upDownState = local.y() < box->height() / 2 ? Up : Down; + break; + case RenderTheme::InnerSpinButtonLayout::HorizontalUpLeft: + m_upDownState = local.x() < box->width() / 2 ? Up : Down; + break; + case RenderTheme::InnerSpinButtonLayout::HorizontalUpRight: + m_upDownState = local.x() > box->width() / 2 ? Up : Down; + break; + } if (m_upDownState != oldUpDownState) renderer()->repaint(); } else { @@ -136,8 +142,8 @@ void SpinButtonElement::defaultEventHandler(Event* event) } } - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); + if (!mouseEvent.defaultHandled()) + HTMLDivElement::defaultEventHandler(mouseEvent); } void SpinButtonElement::willOpenPopup() @@ -146,12 +152,12 @@ void SpinButtonElement::willOpenPopup() m_upDownState = Indeterminate; } -void SpinButtonElement::forwardEvent(Event* event) +void SpinButtonElement::forwardEvent(Event& event) { if (!renderBox()) return; - if (event->eventInterface() != WheelEventInterfaceType) + if (!is<WheelEvent>(event)) return; if (!m_spinButtonOwner) @@ -160,8 +166,8 @@ void SpinButtonElement::forwardEvent(Event* event) if (!m_spinButtonOwner->shouldSpinButtonRespondToWheelEvents()) return; - doStepAction(static_cast<WheelEvent*>(event)->wheelDeltaY()); - event->setDefaultHandled(); + doStepAction(downcast<WheelEvent>(event).wheelDeltaY()); + event.setDefaultHandled(); } bool SpinButtonElement::willRespondToMouseMoveEvents() @@ -199,16 +205,11 @@ void SpinButtonElement::releaseCapture() frame->eventHandler().setCapturingMouseEventsElement(nullptr); m_capturing = false; if (Page* page = document().page()) - page->chrome().unregisterPopupOpeningObserver(this); + page->chrome().unregisterPopupOpeningObserver(*this); } } } -bool SpinButtonElement::matchesReadOnlyPseudoClass() const -{ - return shadowHost()->matchesReadOnlyPseudoClass(); -} - bool SpinButtonElement::matchesReadWritePseudoClass() const { return shadowHost()->matchesReadWritePseudoClass(); @@ -217,8 +218,8 @@ bool SpinButtonElement::matchesReadWritePseudoClass() const void SpinButtonElement::startRepeatingTimer() { m_pressStartingState = m_upDownState; - ScrollbarTheme* theme = ScrollbarTheme::theme(); - m_repeatingTimer.start(theme->initialAutoscrollTimerDelay(), theme->autoscrollTimerDelay()); + ScrollbarTheme& theme = ScrollbarTheme::theme(); + m_repeatingTimer.start(theme.initialAutoscrollTimerDelay(), theme.autoscrollTimerDelay()); } void SpinButtonElement::stopRepeatingTimer() @@ -240,7 +241,7 @@ void SpinButtonElement::step(int amount) doStepAction(amount); } -void SpinButtonElement::repeatingTimerFired(Timer<SpinButtonElement>*) +void SpinButtonElement::repeatingTimerFired() { if (m_upDownState != Indeterminate) step(m_upDownState == Up ? 1 : -1); diff --git a/Source/WebCore/html/shadow/SpinButtonElement.h b/Source/WebCore/html/shadow/SpinButtonElement.h index eb8bb3d8e..ced532e56 100644 --- a/Source/WebCore/html/shadow/SpinButtonElement.h +++ b/Source/WebCore/html/shadow/SpinButtonElement.h @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SpinButtonElement_h -#define SpinButtonElement_h +#pragma once #include "HTMLDivElement.h" #include "PopupOpeningObserver.h" @@ -54,44 +53,45 @@ public: // The owner of SpinButtonElement must call removeSpinButtonOwner // because SpinButtonElement can be outlive SpinButtonOwner // implementation, e.g. during event handling. - static PassRefPtr<SpinButtonElement> create(Document&, SpinButtonOwner&); + static Ref<SpinButtonElement> create(Document&, SpinButtonOwner&); UpDownState upDownState() const { return m_upDownState; } - virtual void releaseCapture(); + void releaseCapture(); void removeSpinButtonOwner() { m_spinButtonOwner = 0; } void step(int amount); - virtual bool willRespondToMouseMoveEvents() override; - virtual bool willRespondToMouseClickEvents() override; + bool willRespondToMouseMoveEvents() override; + bool willRespondToMouseClickEvents() override; - void forwardEvent(Event*); + void forwardEvent(Event&); private: SpinButtonElement(Document&, SpinButtonOwner&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void willDetachRenderers() override; - virtual bool isSpinButtonElement() const override { return true; } - virtual bool isDisabledFormControl() const override { return shadowHost() && shadowHost()->isDisabledFormControl(); } - virtual bool matchesReadOnlyPseudoClass() const override; - virtual bool matchesReadWritePseudoClass() const override; - virtual void defaultEventHandler(Event*) override; - virtual void willOpenPopup() override; + void willDetachRenderers() override; + bool isSpinButtonElement() const override { return true; } + bool isDisabledFormControl() const override { return shadowHost() && shadowHost()->isDisabledFormControl(); } + bool matchesReadWritePseudoClass() const override; + void defaultEventHandler(Event&) override; + void willOpenPopup() override; void doStepAction(int); void startRepeatingTimer(); void stopRepeatingTimer(); - void repeatingTimerFired(Timer<SpinButtonElement>*); - virtual void setHovered(bool = true) override; + void repeatingTimerFired(); + void setHovered(bool = true) override; bool shouldRespondToMouseEvents(); - virtual bool isMouseFocusable() const override { return false; } + bool isMouseFocusable() const override { return false; } SpinButtonOwner* m_spinButtonOwner; bool m_capturing; UpDownState m_upDownState; UpDownState m_pressStartingState; - Timer<SpinButtonElement> m_repeatingTimer; + Timer m_repeatingTimer; }; -} // namespace +} // namespace WebCore -#endif +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::SpinButtonElement) + static bool isType(const WebCore::Element& element) { return element.isSpinButtonElement(); } + static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.cpp b/Source/WebCore/html/shadow/TextControlInnerElements.cpp index ac35831f3..584da68c7 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.cpp +++ b/Source/WebCore/html/shadow/TextControlInnerElements.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2010, 2014 Apple Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -28,18 +28,19 @@ #include "TextControlInnerElements.h" #include "Document.h" -#include "EventHandler.h" #include "EventNames.h" #include "Frame.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "LocalizedStrings.h" #include "MouseEvent.h" +#include "PlatformMouseEvent.h" #include "RenderSearchField.h" #include "RenderTextControl.h" #include "RenderView.h" #include "ScriptController.h" -#include "SpeechInput.h" -#include "SpeechInputEvent.h" +#include "ShadowRoot.h" +#include "StyleResolver.h" #include "TextEvent.h" #include "TextEventInputType.h" #include <wtf/Ref.h> @@ -53,14 +54,14 @@ TextControlInnerContainer::TextControlInnerContainer(Document& document) { } -PassRefPtr<TextControlInnerContainer> TextControlInnerContainer::create(Document& document) +Ref<TextControlInnerContainer> TextControlInnerContainer::create(Document& document) { - return adoptRef(new TextControlInnerContainer(document)); + return adoptRef(*new TextControlInnerContainer(document)); } -RenderPtr<RenderElement> TextControlInnerContainer::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> TextControlInnerContainer::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderTextControlInnerContainer>(*this, std::move(style)); + return createRenderer<RenderTextControlInnerContainer>(*this, WTFMove(style)); } TextControlInnerElement::TextControlInnerElement(Document& document) @@ -69,15 +70,26 @@ TextControlInnerElement::TextControlInnerElement(Document& document) setHasCustomStyleResolveCallbacks(); } -PassRefPtr<TextControlInnerElement> TextControlInnerElement::create(Document& document) +Ref<TextControlInnerElement> TextControlInnerElement::create(Document& document) { - return adoptRef(new TextControlInnerElement(document)); + return adoptRef(*new TextControlInnerElement(document)); } -PassRefPtr<RenderStyle> TextControlInnerElement::customStyleForRenderer() +std::optional<ElementStyle> TextControlInnerElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* shadowHostStyle) { - RenderTextControlSingleLine* parentRenderer = toRenderTextControlSingleLine(shadowHost()->renderer()); - return parentRenderer->createInnerBlockStyle(&parentRenderer->style()); + auto innerContainerStyle = RenderStyle::createPtr(); + innerContainerStyle->inheritFrom(*shadowHostStyle); + + innerContainerStyle->setFlexGrow(1); + // min-width: 0; is needed for correct shrinking. + innerContainerStyle->setMinWidth(Length(0, Fixed)); + innerContainerStyle->setDisplay(BLOCK); + innerContainerStyle->setDirection(LTR); + + // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable. + innerContainerStyle->setUserModify(READ_ONLY); + + return ElementStyle(WTFMove(innerContainerStyle)); } // --------------------------- @@ -88,17 +100,17 @@ inline TextControlInnerTextElement::TextControlInnerTextElement(Document& docume setHasCustomStyleResolveCallbacks(); } -PassRefPtr<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document) +Ref<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document) { - return adoptRef(new TextControlInnerTextElement(document)); + return adoptRef(*new TextControlInnerTextElement(document)); } -void TextControlInnerTextElement::defaultEventHandler(Event* event) +void TextControlInnerTextElement::defaultEventHandler(Event& event) { // FIXME: In the future, we should add a way to have default event listeners. // Then we would add one to the text field's inner div, and we wouldn't need this subclass. // Or possibly we could just use a normal event listener. - if (event->isBeforeTextInsertedEvent() || event->type() == eventNames().webkitEditableContentChangedEvent) { + if (event.isBeforeTextInsertedEvent() || event.type() == eventNames().webkitEditableContentChangedEvent) { Element* shadowAncestor = shadowHost(); // A TextControlInnerTextElement can have no host if its been detached, // but kept alive by an EditCommand. In this case, an undo/redo can @@ -108,256 +120,137 @@ void TextControlInnerTextElement::defaultEventHandler(Event* event) if (shadowAncestor) shadowAncestor->defaultEventHandler(event); } - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); } -RenderPtr<RenderElement> TextControlInnerTextElement::createElementRenderer(PassRef<RenderStyle> style) +RenderPtr<RenderElement> TextControlInnerTextElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) { - return createRenderer<RenderTextControlInnerBlock>(*this, std::move(style)); + return createRenderer<RenderTextControlInnerBlock>(*this, WTFMove(style)); } RenderTextControlInnerBlock* TextControlInnerTextElement::renderer() const { - return toRenderTextControlInnerBlock(HTMLDivElement::renderer()); + return downcast<RenderTextControlInnerBlock>(HTMLDivElement::renderer()); } -PassRefPtr<RenderStyle> TextControlInnerTextElement::customStyleForRenderer() +std::optional<ElementStyle> TextControlInnerTextElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* shadowHostStyle) { - RenderTextControl* parentRenderer = toRenderTextControl(shadowHost()->renderer()); - return parentRenderer->createInnerTextStyle(&parentRenderer->style()); + auto style = downcast<HTMLTextFormControlElement>(*shadowHost()).createInnerTextStyle(*shadowHostStyle); + return ElementStyle(std::make_unique<RenderStyle>(WTFMove(style))); } // ---------------------------- -inline SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document& document) +TextControlPlaceholderElement::TextControlPlaceholderElement(Document& document) : HTMLDivElement(divTag, document) { + setPseudo(AtomicString("placeholder", AtomicString::ConstructFromLiteral)); + setHasCustomStyleResolveCallbacks(); } -PassRefPtr<SearchFieldResultsButtonElement> SearchFieldResultsButtonElement::create(Document& document) +std::optional<ElementStyle> TextControlPlaceholderElement::resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle) { - return adoptRef(new SearchFieldResultsButtonElement(document)); -} + auto style = resolveStyle(&parentStyle); -const AtomicString& SearchFieldResultsButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, resultsId, ("-webkit-search-results-button", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, resultsDecorationId, ("-webkit-search-results-decoration", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, decorationId, ("-webkit-search-decoration", AtomicString::ConstructFromLiteral)); - Element* host = shadowHost(); - if (!host) - return resultsId; - if (HTMLInputElement* input = host->toInputElement()) { - if (input->maxResults() < 0) - return decorationId; - if (input->maxResults() > 0) - return resultsId; - return resultsDecorationId; - } - return resultsId; -} + auto& controlElement = downcast<HTMLTextFormControlElement>(*containingShadowRoot()->host()); + style.renderStyle->setDisplay(controlElement.isPlaceholderVisible() ? BLOCK : NONE); -void SearchFieldResultsButtonElement::defaultEventHandler(Event* event) -{ - // On mousedown, bring up a menu, if needed - HTMLInputElement* input = toHTMLInputElement(shadowHost()); - if (input && event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { - input->focus(); - input->select(); -#if !PLATFORM(IOS) - RenderSearchField* renderer = toRenderSearchField(input->renderer()); - if (renderer->popupIsVisible()) - renderer->hidePopup(); - else if (input->maxResults() > 0) - renderer->showPopup(); -#endif - event->setDefaultHandled(); + if (is<HTMLInputElement>(controlElement)) { + auto& inputElement = downcast<HTMLInputElement>(controlElement); + style.renderStyle->setTextOverflow(inputElement.shouldTruncateText(*shadowHostStyle) ? TextOverflowEllipsis : TextOverflowClip); } - - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); -} - -#if !PLATFORM(IOS) -bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents() -{ - return true; + return WTFMove(style); } -#endif // ---------------------------- -inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document) +inline SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document& document) : HTMLDivElement(divTag, document) - , m_capturing(false) { - setHasCustomStyleResolveCallbacks(); } -PassRefPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document) +Ref<SearchFieldResultsButtonElement> SearchFieldResultsButtonElement::create(Document& document) { - return adoptRef(new SearchFieldCancelButtonElement(document)); + return adoptRef(*new SearchFieldResultsButtonElement(document)); } -const AtomicString& SearchFieldCancelButtonElement::shadowPseudoId() const +void SearchFieldResultsButtonElement::defaultEventHandler(Event& event) { - DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral)); - return pseudoId; -} - -void SearchFieldCancelButtonElement::willDetachRenderers() -{ - if (m_capturing) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsElement(nullptr); - } -} - -void SearchFieldCancelButtonElement::defaultEventHandler(Event* event) -{ - // If the element is visible, on mouseup, clear the value, and set selection - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); - if (!input || input->isDisabledOrReadOnly()) { - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); - return; - } - - if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { - if (renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsElement(this); - m_capturing = true; - } - } + // On mousedown, bring up a menu, if needed + auto* input = downcast<HTMLInputElement>(shadowHost()); + if (input && event.type() == eventNames().mousedownEvent && is<MouseEvent>(event) && downcast<MouseEvent>(event).button() == LeftButton) { input->focus(); input->select(); - event->setDefaultHandled(); - } - if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { - if (m_capturing) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsElement(nullptr); - m_capturing = false; - } - if (hovered()) { - String oldValue = input->value(); - input->setValueForUser(""); - input->onSearch(); - event->setDefaultHandled(); - } +#if !PLATFORM(IOS) + if (auto* renderer = input->renderer()) { + auto& searchFieldRenderer = downcast<RenderSearchField>(*renderer); + if (searchFieldRenderer.popupIsVisible()) + searchFieldRenderer.hidePopup(); + else if (input->maxResults() > 0) + searchFieldRenderer.showPopup(); } +#endif + event.setDefaultHandled(); } - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); } #if !PLATFORM(IOS) -bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents() +bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents() { - const HTMLInputElement* input = toHTMLInputElement(shadowHost()); - if (input && !input->isDisabledOrReadOnly()) - return true; - - return HTMLDivElement::willRespondToMouseClickEvents(); + return true; } #endif // ---------------------------- -#if ENABLE(INPUT_SPEECH) - -inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Document& document) +inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document) : HTMLDivElement(divTag, document) - , m_capturing(false) - , m_state(Idle) - , m_listenerId(0) -{ - setHasCustomStyleResolveCallbacks(); -} - -InputFieldSpeechButtonElement::~InputFieldSpeechButtonElement() { - SpeechInput* speech = speechInput(); - if (speech && m_listenerId) { // Could be null when page is unloading. - if (m_state != Idle) - speech->cancelRecognition(m_listenerId); - speech->unregisterListener(m_listenerId); - } + setPseudo(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral)); +#if !PLATFORM(IOS) + setAttributeWithoutSynchronization(aria_labelAttr, AXSearchFieldCancelButtonText()); +#endif + setAttributeWithoutSynchronization(roleAttr, AtomicString("button", AtomicString::ConstructFromLiteral)); } -PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(Document& document) +Ref<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document) { - return adoptRef(new InputFieldSpeechButtonElement(document)); + return adoptRef(*new SearchFieldCancelButtonElement(document)); } -void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) +void SearchFieldCancelButtonElement::defaultEventHandler(Event& event) { - // For privacy reasons, only allow clicks directly coming from the user. - if (!ScriptController::processingUserGesture()) { - HTMLDivElement::defaultEventHandler(event); - return; - } - - // The call to focus() below dispatches a focus event, and an event handler in the page might - // remove the input element from DOM. To make sure it remains valid until we finish our work - // here, we take a temporary reference. - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); - + RefPtr<HTMLInputElement> input(downcast<HTMLInputElement>(shadowHost())); if (!input || input->isDisabledOrReadOnly()) { - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } - // On mouse down, select the text and set focus. - if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { - if (renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsElement(this); - m_capturing = true; - } - } - Ref<InputFieldSpeechButtonElement> protect(*this); + if (event.type() == eventNames().mousedownEvent && is<MouseEvent>(event) && downcast<MouseEvent>(event).button() == LeftButton) { input->focus(); input->select(); - event->setDefaultHandled(); - } - // On mouse up, release capture cleanly. - if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { - if (m_capturing && renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsElement(nullptr); - m_capturing = false; - } - } + event.setDefaultHandled(); } - if (event->type() == eventNames().clickEvent && m_listenerId) { - switch (m_state) { - case Idle: - startSpeechInput(); - break; - case Recording: - stopSpeechInput(); - break; - case Recognizing: - // Nothing to do here, we will continue to wait for results. - break; - } - event->setDefaultHandled(); + if (event.type() == eventNames().clickEvent) { + input->setValueForUser(emptyString()); + input->onSearch(); + event.setDefaultHandled(); } - if (!event->defaultHandled()) + if (!event.defaultHandled()) HTMLDivElement::defaultEventHandler(event); } #if !PLATFORM(IOS) -bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents() +bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents() { - const HTMLInputElement* input = toHTMLInputElement(shadowHost()); + const HTMLInputElement* input = downcast<HTMLInputElement>(shadowHost()); if (input && !input->isDisabledOrReadOnly()) return true; @@ -365,106 +258,4 @@ bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents() } #endif -void InputFieldSpeechButtonElement::setState(SpeechInputState state) -{ - if (m_state != state) { - m_state = state; - shadowHost()->renderer()->repaint(); - } -} - -SpeechInput* InputFieldSpeechButtonElement::speechInput() -{ - return SpeechInput::from(document().page()); -} - -void InputFieldSpeechButtonElement::didCompleteRecording(int) -{ - setState(Recognizing); -} - -void InputFieldSpeechButtonElement::didCompleteRecognition(int) -{ - setState(Idle); -} - -void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputResultArray& results) -{ - m_results = results; - - // The call to setValue() below dispatches an event, and an event handler in the page might - // remove the input element from DOM. To make sure it remains valid until we finish our work - // here, we take a temporary reference. - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); - if (!input || input->isDisabledOrReadOnly()) - return; - - Ref<InputFieldSpeechButtonElement> protect(*this); - if (document().domWindow()) { - // Call selectionChanged, causing the element to cache the selection, - // so that the text event inserts the text in this element even if - // focus has moved away from it. - input->selectionChanged(false); - input->dispatchEvent(TextEvent::create(document().domWindow(), results.isEmpty() ? "" : results[0]->utterance(), TextEventInputOther)); - } - - // This event is sent after the text event so the website can perform actions using the input field content immediately. - // It provides alternative recognition hypotheses and notifies that the results come from speech input. - input->dispatchEvent(SpeechInputEvent::create(eventNames().webkitspeechchangeEvent, results)); - - // Check before accessing the renderer as the above event could have potentially turned off - // speech in the input element, hence removing this button and renderer from the hierarchy. - if (renderer()) - renderer()->repaint(); -} - -void InputFieldSpeechButtonElement::willAttachRenderers() -{ - ASSERT(!m_listenerId); - if (SpeechInput* input = SpeechInput::from(document().page())) - m_listenerId = input->registerListener(this); -} - -void InputFieldSpeechButtonElement::willDetachRenderers() -{ - if (m_capturing) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsElement(nullptr); - } - - if (m_listenerId) { - if (m_state != Idle) - speechInput()->cancelRecognition(m_listenerId); - speechInput()->unregisterListener(m_listenerId); - m_listenerId = 0; - } -} - -void InputFieldSpeechButtonElement::startSpeechInput() -{ - if (m_state != Idle) - return; - - RefPtr<HTMLInputElement> input = toHTMLInputElement(shadowHost()); - AtomicString language = input->computeInheritedLanguage(); - String grammar = input->getAttribute(webkitgrammarAttr); - IntRect rect = document().view()->contentsToRootView(pixelSnappedBoundingBox()); - if (speechInput()->startRecognition(m_listenerId, rect, language, grammar, document().securityOrigin())) - setState(Recording); -} - -void InputFieldSpeechButtonElement::stopSpeechInput() -{ - if (m_state == Recording) - speechInput()->stopRecording(m_listenerId); -} - -const AtomicString& InputFieldSpeechButtonElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-input-speech-button", AtomicString::ConstructFromLiteral)); - return pseudoId; -} - -#endif // ENABLE(INPUT_SPEECH) - } diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.h b/Source/WebCore/html/shadow/TextControlInnerElements.h index 73e79c230..b16e1e736 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.h +++ b/Source/WebCore/html/shadow/TextControlInnerElements.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2010, 2014 Apple Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,145 +24,92 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TextControlInnerElements_h -#define TextControlInnerElements_h +#pragma once #include "HTMLDivElement.h" -#include "SpeechInputListener.h" #include <wtf/Forward.h> namespace WebCore { class RenderTextControlInnerBlock; -class SpeechInput; class TextControlInnerContainer final : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerContainer> create(Document&); + static Ref<TextControlInnerContainer> create(Document&); protected: TextControlInnerContainer(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; }; class TextControlInnerElement final : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerElement> create(Document&); + static Ref<TextControlInnerElement> create(Document&); protected: TextControlInnerElement(Document&); - virtual PassRefPtr<RenderStyle> customStyleForRenderer() override; + std::optional<ElementStyle> resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle) override; private: - virtual bool isMouseFocusable() const override { return false; } + bool isMouseFocusable() const override { return false; } }; class TextControlInnerTextElement final : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerTextElement> create(Document&); + static Ref<TextControlInnerTextElement> create(Document&); - virtual void defaultEventHandler(Event*) override; + void defaultEventHandler(Event&) override; RenderTextControlInnerBlock* renderer() const; private: TextControlInnerTextElement(Document&); - virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override; - virtual PassRefPtr<RenderStyle> customStyleForRenderer() override; - virtual bool isMouseFocusable() const override { return false; } - virtual bool isTextControlInnerTextElement() const override { return true; } + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; + std::optional<ElementStyle> resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle) override; + bool isMouseFocusable() const override { return false; } + bool isTextControlInnerTextElement() const override { return true; } }; -inline bool isTextControlInnerTextElement(const HTMLElement& element) { return element.isTextControlInnerTextElement(); } -inline bool isTextControlInnerTextElement(const Node& node) { return node.isHTMLElement() && isTextControlInnerTextElement(toHTMLElement(node)); } -NODE_TYPE_CASTS(TextControlInnerTextElement) - -class SearchFieldResultsButtonElement final : public HTMLDivElement { +class TextControlPlaceholderElement final : public HTMLDivElement { public: - static PassRefPtr<SearchFieldResultsButtonElement> create(Document&); - - virtual void defaultEventHandler(Event*) override; -#if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override; -#endif + static Ref<TextControlPlaceholderElement> create(Document& document) { return adoptRef(*new TextControlPlaceholderElement(document)); } private: - SearchFieldResultsButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual bool isMouseFocusable() const override { return false; } + TextControlPlaceholderElement(Document&); + + std::optional<ElementStyle> resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle) override; }; -class SearchFieldCancelButtonElement final : public HTMLDivElement { +class SearchFieldResultsButtonElement final : public HTMLDivElement { public: - static PassRefPtr<SearchFieldCancelButtonElement> create(Document&); + static Ref<SearchFieldResultsButtonElement> create(Document&); - virtual void defaultEventHandler(Event*) override; - virtual bool isSearchFieldCancelButtonElement() const override { return true; } + void defaultEventHandler(Event&) override; #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents() override; + bool willRespondToMouseClickEvents() override; #endif private: - SearchFieldCancelButtonElement(Document&); - virtual const AtomicString& shadowPseudoId() const override; - virtual void willDetachRenderers() override; - virtual bool isMouseFocusable() const override { return false; } - - bool m_capturing; + SearchFieldResultsButtonElement(Document&); + bool isMouseFocusable() const override { return false; } }; -#if ENABLE(INPUT_SPEECH) - -class InputFieldSpeechButtonElement final - : public HTMLDivElement, - public SpeechInputListener { +class SearchFieldCancelButtonElement final : public HTMLDivElement { public: - enum SpeechInputState { - Idle, - Recording, - Recognizing, - }; + static Ref<SearchFieldCancelButtonElement> create(Document&); - static PassRefPtr<InputFieldSpeechButtonElement> create(Document&); - virtual ~InputFieldSpeechButtonElement(); - - virtual void defaultEventHandler(Event*); + void defaultEventHandler(Event&) override; #if !PLATFORM(IOS) - virtual bool willRespondToMouseClickEvents(); + bool willRespondToMouseClickEvents() override; #endif - virtual bool isInputFieldSpeechButtonElement() const { return true; } - SpeechInputState state() const { return m_state; } - void startSpeechInput(); - void stopSpeechInput(); - - // SpeechInputListener methods. - void didCompleteRecording(int); - void didCompleteRecognition(int); - void setRecognitionResult(int, const SpeechInputResultArray&); private: - InputFieldSpeechButtonElement(Document&); - SpeechInput* speechInput(); - void setState(SpeechInputState state); - virtual const AtomicString& shadowPseudoId() const; - virtual bool isMouseFocusable() const override { return false; } - virtual void willAttachRenderers() override; - virtual void willDetachRenderers() override; - - - bool m_capturing; - SpeechInputState m_state; - int m_listenerId; - SpeechInputResultArray m_results; + SearchFieldCancelButtonElement(Document&); + bool isMouseFocusable() const override { return false; } }; -inline InputFieldSpeechButtonElement* toInputFieldSpeechButtonElement(Element* element) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!element || element->isInputFieldSpeechButtonElement()); - return static_cast<InputFieldSpeechButtonElement*>(element); -} - -#endif // ENABLE(INPUT_SPEECH) +} // namespace WebCore -} // namespace - -#endif +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::TextControlInnerTextElement) + static bool isType(const WebCore::HTMLElement& element) { return element.isTextControlInnerTextElement(); } + static bool isType(const WebCore::Node& node) { return is<WebCore::HTMLElement>(node) && isType(downcast<WebCore::HTMLElement>(node)); } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp b/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp new file mode 100644 index 000000000..671000675 --- /dev/null +++ b/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "YouTubeEmbedShadowElement.h" + +#include "RenderBlockFlow.h" + +namespace WebCore { + +Ref<YouTubeEmbedShadowElement> YouTubeEmbedShadowElement::create(Document& doc) +{ + return adoptRef(*new YouTubeEmbedShadowElement(doc)); +} + +YouTubeEmbedShadowElement::YouTubeEmbedShadowElement(Document& document) + : HTMLDivElement(HTMLNames::divTag, document) +{ + setPseudo(AtomicString("-webkit-plugin-replacement", AtomicString::ConstructFromLiteral)); +} + +RenderPtr<RenderElement> YouTubeEmbedShadowElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&) +{ + return createRenderer<RenderBlockFlow>(*this, WTFMove(style)); +} + +} diff --git a/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h b/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h new file mode 100644 index 000000000..b7cde4d25 --- /dev/null +++ b/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "HTMLDivElement.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class YouTubeEmbedShadowElement final : public HTMLDivElement { +public: + static Ref<YouTubeEmbedShadowElement> create(Document&); + + RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final; + +private: + YouTubeEmbedShadowElement(Document&); +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/meterElementShadow.css b/Source/WebCore/html/shadow/meterElementShadow.css new file mode 100644 index 000000000..8b42aa477 --- /dev/null +++ b/Source/WebCore/html/shadow/meterElementShadow.css @@ -0,0 +1,36 @@ +/* use div# because the preprocessor doen't like # start */ + +div#inner { + -webkit-appearance: inherit; + box-sizing: inherit; + height: 100%; + width: 100%; +} + +div#bar { + background: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#ddd), color-stop(0.20, #eee), color-stop(0.45, #ccc), color-stop(0.55, #ccc)); + height: 100%; + width: 100%; + box-sizing: border-box; +} + +div#value { + height: 100%; + box-sizing: border-box; +} + +div#value.optimum { + background: -webkit-gradient(linear, left top, left bottom, from(#ad7), to(#ad7), color-stop(0.20, #cea), color-stop(0.45, #7a3), color-stop(0.55, #7a3)); +} + +div#value.suboptimum { + background: -webkit-gradient(linear, left top, left bottom, from(#fe7), to(#fe7), color-stop(0.20, #ffc), color-stop(0.45, #db3), color-stop(0.55, #db3)); + height: 100%; + box-sizing: border-box; +} + +div#value.even-less-good { + background: -webkit-gradient(linear, left top, left bottom, from(#f77), to(#f77), color-stop(0.20, #fcc), color-stop(0.45, #d44), color-stop(0.55, #d44)); + height: 100%; + box-sizing: border-box; +} |