diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/html | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/html')
75 files changed, 3452 insertions, 496 deletions
diff --git a/Source/WebCore/html/FormAssociatedElement.h b/Source/WebCore/html/FormAssociatedElement.h index aa5abd9..7f3e9ac 100644 --- a/Source/WebCore/html/FormAssociatedElement.h +++ b/Source/WebCore/html/FormAssociatedElement.h @@ -46,7 +46,6 @@ public: virtual bool isFormControlElement() const = 0; virtual bool isEnumeratable() const = 0; - virtual bool isResettable() const = 0; const AtomicString& name() const { return formControlName(); } diff --git a/Source/WebCore/html/HTMLAttributeNames.in b/Source/WebCore/html/HTMLAttributeNames.in index 3a6fea4..5e0fe7b 100644 --- a/Source/WebCore/html/HTMLAttributeNames.in +++ b/Source/WebCore/html/HTMLAttributeNames.in @@ -85,6 +85,7 @@ coords data datetime declare +default defer dir direction @@ -118,6 +119,7 @@ incremental indeterminate ismap keytype +kind label lang language @@ -178,8 +180,6 @@ onerror onfocus onfocusin onfocusout -onformchange -onforminput onhashchange oninput oninvalid @@ -276,6 +276,7 @@ x-webkit-speech x-webkit-grammar spellcheck src +srclang standby start step diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp index 67d1caa..1747273 100644 --- a/Source/WebCore/html/HTMLCanvasElement.cpp +++ b/Source/WebCore/html/HTMLCanvasElement.cpp @@ -175,7 +175,7 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas #if ENABLE(WEBGL) Settings* settings = document()->settings(); if (settings && settings->webGLEnabled() -#if !PLATFORM(CHROMIUM) +#if !PLATFORM(CHROMIUM) && !PLATFORM(GTK) && settings->acceleratedCompositingEnabled() #endif ) { @@ -318,27 +318,6 @@ void HTMLCanvasElement::clearPresentationCopy() m_presentedImage.clear(); } -void HTMLCanvasElement::attach() -{ - HTMLElement::attach(); - - if (m_context && m_context->is2d()) { - CanvasRenderingContext2D* ctx = static_cast<CanvasRenderingContext2D*>(m_context.get()); - ctx->updateFont(); - } -} - -void HTMLCanvasElement::recalcStyle(StyleChange change) -{ - HTMLElement::recalcStyle(change); - - // Update font if needed. - if (change == Force && m_context && m_context->is2d()) { - CanvasRenderingContext2D* ctx = static_cast<CanvasRenderingContext2D*>(m_context.get()); - ctx->updateFont(); - } -} - void HTMLCanvasElement::setSurfaceSize(const IntSize& size) { m_size = size; @@ -363,8 +342,12 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType)) lowercaseMimeType = "image/png"; +<<<<<<< HEAD #if PLATFORM(CG) || (USE(SKIA) && !PLATFORM(ANDROID)) // FIXME: Consider using this code path on Android. http://b/4572024 +======= +#if USE(CG) || USE(SKIA) +>>>>>>> WebKit.org at r84325 // Try to get ImageData first, as that may avoid lossy conversions. RefPtr<ImageData> imageData = getImageData(); @@ -460,10 +443,8 @@ void HTMLCanvasElement::createImageBuffer() const m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality); #if USE(JSC) - if (hasCachedDOMNodeWrapperUnchecked(document(), const_cast<HTMLCanvasElement*>(this))) { - JSC::JSLock lock(JSC::SilenceAssertionsOnly); - scriptExecutionContext()->globalData()->heap.reportExtraMemoryCost(m_imageBuffer->dataSize()); - } + JSC::JSLock lock(JSC::SilenceAssertionsOnly); + scriptExecutionContext()->globalData()->heap.reportExtraMemoryCost(m_imageBuffer->dataSize()); #endif } diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h index 6fdd222..9eab209 100644 --- a/Source/WebCore/html/HTMLCanvasElement.h +++ b/Source/WebCore/html/HTMLCanvasElement.h @@ -34,7 +34,7 @@ #if PLATFORM(CHROMIUM) || PLATFORM(QT) #define DefaultInterpolationQuality InterpolationMedium -#elif PLATFORM(CG) +#elif USE(CG) #define DefaultInterpolationQuality InterpolationLow #else #define DefaultInterpolationQuality InterpolationDefault @@ -150,10 +150,6 @@ private: virtual void parseMappedAttribute(Attribute*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - virtual void attach(); - - virtual void recalcStyle(StyleChange); - void reset(); void createImageBuffer() const; diff --git a/Source/WebCore/html/HTMLDetailsElement.cpp b/Source/WebCore/html/HTMLDetailsElement.cpp index f9c2f6c..b41f5dd 100644 --- a/Source/WebCore/html/HTMLDetailsElement.cpp +++ b/Source/WebCore/html/HTMLDetailsElement.cpp @@ -21,11 +21,12 @@ #include "config.h" #include "HTMLDetailsElement.h" -#include "Frame.h" #include "HTMLNames.h" +#include "HTMLSummaryElement.h" +#include "LocalizedStrings.h" #include "MouseEvent.h" -#include "PlatformMouseEvent.h" #include "RenderDetails.h" +#include "Text.h" namespace WebCore { @@ -49,48 +50,76 @@ RenderObject* HTMLDetailsElement::createRenderer(RenderArena* arena, RenderStyle return new (arena) RenderDetails(this); } -void HTMLDetailsElement::findMainSummary() +Node* HTMLDetailsElement::findSummaryFor(ContainerNode* container) { - m_mainSummary = 0; + for (Node* child = container->firstChild(); child; child = child->nextSibling()) { + if (child->hasTagName(summaryTag)) + return child; + } - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (child->hasTagName(summaryTag)) { - m_mainSummary = child; - break; - } + return 0; +} + +Node* HTMLDetailsElement::findMainSummary() +{ + Node* found = findSummaryFor(this); + if (found) { + removeShadowRoot(); + return found; } + + createShadowSubtree(); + found = findSummaryFor(shadowRoot()); + ASSERT(found); + return found; +} + +void HTMLDetailsElement::refreshMainSummary(RefreshRenderer refreshRenderer) +{ + RefPtr<Node> oldSummary = m_mainSummary; + m_mainSummary = findMainSummary(); + + if (oldSummary == m_mainSummary || !attached()) + return; + + if (oldSummary && oldSummary->parentNodeForRenderingAndStyle()) { + oldSummary->detach(); + oldSummary->attach(); + } + + if (refreshRenderer == RefreshRendererAllowed) { + m_mainSummary->detach(); + m_mainSummary->attach(); + } +} + +void HTMLDetailsElement::createShadowSubtree() +{ + if (shadowRoot()) + return; + + RefPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(summaryTag, document()); + ExceptionCode ec = 0; + defaultSummary->appendChild(Text::create(document(), defaultDetailsSummaryText()), ec); + ensureShadowRoot()->appendChild(defaultSummary, ec, true); } + void HTMLDetailsElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) { - Node* oldSummary = m_mainSummary; - findMainSummary(); - - if (oldSummary != m_mainSummary && !m_isOpen && attached()) { - if (oldSummary && oldSummary->attached()) - oldSummary->detach(); - if (m_mainSummary && childCountDelta < 0 && !m_mainSummary->renderer()) { - // If childCountDelta is less then zero and the main summary has changed it must be because previous main - // summary was removed. The new main summary was then inside the unrevealed content and needs to be - // reattached to create its renderer. If childCountDelta is not less then zero then a new <summary> element - // has been added and it will be attached without our help. - m_mainSummary->detach(); - m_mainSummary->attach(); - } - } - } + // If childCountDelta is less then zero and the main summary has changed it must be because previous main + // summary was removed. The new main summary was then inside the unrevealed content and needs to be + // reattached to create its renderer. If childCountDelta is not less then zero then a new <summary> element + // has been added and it will be attached without our help. + if (!changedByParser) + refreshMainSummary(childCountDelta < 0 ? RefreshRendererAllowed : RefreshRendererSupressed); } void HTMLDetailsElement::finishParsingChildren() { HTMLElement::finishParsingChildren(); - findMainSummary(); - if (attached() && m_mainSummary && !m_mainSummary->renderer()) { - m_mainSummary->detach(); - m_mainSummary->attach(); - } + refreshMainSummary(RefreshRendererAllowed); } void HTMLDetailsElement::parseMappedAttribute(Attribute* attr) @@ -111,26 +140,9 @@ bool HTMLDetailsElement::childShouldCreateRenderer(Node* child) const return m_isOpen || child == m_mainSummary; } -void HTMLDetailsElement::defaultEventHandler(Event* event) +void HTMLDetailsElement::toggleOpen() { - HTMLElement::defaultEventHandler(event); - - if (!renderer() || !renderer()->isDetails() || !event->isMouseEvent() || event->type() != eventNames().clickEvent || event->defaultHandled()) - return; - - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - if (mouseEvent->button() != LeftButton) - return; - - RenderDetails* renderDetails = static_cast<RenderDetails*>(renderer()); - - float factor = document() && document()->frame() ? document()->frame()->pageZoomFactor() : 1.0f; - FloatPoint pos = renderDetails->absoluteToLocal(FloatPoint(mouseEvent->pageX() * factor, mouseEvent->pageY() * factor)); - - if (renderDetails->interactiveArea().contains(pos.x(), pos.y())) { - setAttribute(openAttr, m_isOpen ? String() : String("")); - event->setDefaultHandled(); - } + setAttribute(openAttr, m_isOpen ? nullAtom : emptyAtom); } } diff --git a/Source/WebCore/html/HTMLDetailsElement.h b/Source/WebCore/html/HTMLDetailsElement.h index 45a9035..70ae9c6 100644 --- a/Source/WebCore/html/HTMLDetailsElement.h +++ b/Source/WebCore/html/HTMLDetailsElement.h @@ -29,19 +29,29 @@ class HTMLDetailsElement : public HTMLElement { public: static PassRefPtr<HTMLDetailsElement> create(const QualifiedName& tagName, Document* document); Node* mainSummary() const { return m_mainSummary; } + void toggleOpen(); private: + enum RefreshRenderer { + RefreshRendererAllowed, + RefreshRendererSupressed, + }; + HTMLDetailsElement(const QualifiedName&, Document*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta); virtual void finishParsingChildren(); + virtual bool canHaveLightChildRendererWithShadow() const { return true; } void parseMappedAttribute(Attribute*); bool childShouldCreateRenderer(Node*) const; - void defaultEventHandler(Event*); - void findMainSummary(); + Node* findSummaryFor(ContainerNode*); + Node* findMainSummary(); + void refreshMainSummary(RefreshRenderer); + + void createShadowSubtree(); Node* m_mainSummary; bool m_isOpen; diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp index e3b5043..b2b57a2 100644 --- a/Source/WebCore/html/HTMLElement.cpp +++ b/Source/WebCore/html/HTMLElement.cpp @@ -194,10 +194,6 @@ void HTMLElement::parseMappedAttribute(Attribute* attr) setAttributeEventListener(eventNames().focusinEvent, createAttributeEventListener(this, attr)); } else if (attr->name() == onfocusoutAttr) { setAttributeEventListener(eventNames().focusoutEvent, createAttributeEventListener(this, attr)); - } else if (attr->name() == onformchangeAttr) { - setAttributeEventListener(eventNames().formchangeEvent, createAttributeEventListener(this, attr)); - } else if (attr->name() == onforminputAttr) { - setAttributeEventListener(eventNames().forminputEvent, createAttributeEventListener(this, attr)); } else if (attr->name() == onblurAttr) { setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr)); } else if (attr->name() == onkeydownAttr) { @@ -657,11 +653,6 @@ bool HTMLElement::supportsFocus() const return Element::supportsFocus() || (rendererIsEditable() && parentNode() && !parentNode()->rendererIsEditable()); } -bool HTMLElement::isContentEditable() const -{ - return rendererIsEditable(); -} - String HTMLElement::contentEditable() const { const AtomicString& value = fastGetAttribute(contenteditableAttr); @@ -819,40 +810,6 @@ HTMLFormElement* HTMLElement::virtualForm() const return findFormAncestor(); } -HTMLFormElement* HTMLElement::shadowAncestorOwnerForm() -{ - Node* ancestorNode = shadowAncestorNode(); - if (!ancestorNode) - return form(); - - if (!ancestorNode->isHTMLElement()) - return 0; - HTMLElement* ancestorHTML = toHTMLElement(ancestorNode); - if (!ancestorHTML) - return 0; - return ancestorHTML->form(); -} - -void HTMLElement::dispatchChangeEvents() -{ - RefPtr<HTMLElement> protector(this); - RefPtr<HTMLFormElement> ownerForm(shadowAncestorOwnerForm()); - - Node::dispatchChangeEvents(); - if (ownerForm) - ownerForm->dispatchFormChange(); -} - -void HTMLElement::dispatchInputEvents() -{ - RefPtr<HTMLElement> protector(this); - RefPtr<HTMLFormElement> ownerForm(shadowAncestorOwnerForm()); - - Node::dispatchInputEvents(); - if (ownerForm) - ownerForm->dispatchFormInput(); -} - static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastNode = 0) { firstNode->setSelfOrAncestorHasDirAutoAttribute(flag); diff --git a/Source/WebCore/html/HTMLElement.h b/Source/WebCore/html/HTMLElement.h index 077b1c3..5a5fdfb 100644 --- a/Source/WebCore/html/HTMLElement.h +++ b/Source/WebCore/html/HTMLElement.h @@ -57,8 +57,6 @@ public: virtual bool supportsFocus() const; - bool isContentEditable() const; - String contentEditable() const; void setContentEditable(const String&, ExceptionCode&); @@ -83,9 +81,6 @@ public: HTMLFormElement* findFormAncestor() const; - virtual void dispatchChangeEvents(); - virtual void dispatchInputEvents(); - TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const; protected: @@ -108,8 +103,6 @@ private: Node* insertAdjacent(const String& where, Node* newChild, ExceptionCode&); PassRefPtr<DocumentFragment> textToFragment(const String&, ExceptionCode&); - HTMLFormElement* shadowAncestorOwnerForm(); - void dirAttributeChanged(Attribute*); void adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child); void calculateAndAdjustDirectionality(); diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp index af061fe..87f4e4d 100644 --- a/Source/WebCore/html/HTMLFormControlElement.cpp +++ b/Source/WebCore/html/HTMLFormControlElement.cpp @@ -201,14 +201,14 @@ void HTMLFormControlElement::setChangedSinceLastFormControlChangeEvent(bool chan void HTMLFormControlElement::dispatchFormControlChangeEvent() { - HTMLElement::dispatchChangeEvents(); + HTMLElement::dispatchChangeEvent(); setChangedSinceLastFormControlChangeEvent(false); } void HTMLFormControlElement::dispatchFormControlInputEvent() { setChangedSinceLastFormControlChangeEvent(true); - HTMLElement::dispatchInputEvents(); + HTMLElement::dispatchInputEvent(); } void HTMLFormControlElement::setDisabled(bool b) @@ -638,7 +638,7 @@ void HTMLTextFormControlElement::select() void HTMLTextFormControlElement::dispatchFormControlChangeEvent() { if (m_textAsOfLastFormControlChangeEvent != value()) { - HTMLElement::dispatchChangeEvents(); + HTMLElement::dispatchChangeEvent(); setTextAsOfLastFormControlChangeEvent(value()); } setChangedSinceLastFormControlChangeEvent(false); diff --git a/Source/WebCore/html/HTMLFormControlElement.h b/Source/WebCore/html/HTMLFormControlElement.h index ede3299..884ace0 100644 --- a/Source/WebCore/html/HTMLFormControlElement.h +++ b/Source/WebCore/html/HTMLFormControlElement.h @@ -63,7 +63,6 @@ public: virtual bool isFocusable() const; virtual bool isEnumeratable() const { return false; } - virtual bool isResettable() const { return false; } // Determines whether or not a control will be automatically focused. virtual bool autofocus() const; diff --git a/Source/WebCore/html/HTMLFormElement.cpp b/Source/WebCore/html/HTMLFormElement.cpp index f051ea1..cfea3d8 100644 --- a/Source/WebCore/html/HTMLFormElement.cpp +++ b/Source/WebCore/html/HTMLFormElement.cpp @@ -236,17 +236,11 @@ bool HTMLFormElement::validateInteractively(Event* event) FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get(); HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); if (unhandled->isFocusable() && unhandled->inDocument()) { - RefPtr<Document> originalDocument(unhandled->document()); unhandled->scrollIntoViewIfNeeded(false); - // scrollIntoViewIfNeeded() dispatches events, so the state - // of 'unhandled' might be changed so it's no longer focusable or - // moved to another document. - if (unhandled->isFocusable() && unhandled->inDocument() && originalDocument == unhandled->document()) { - unhandled->focus(); - if (unhandled->isFormControlElement()) - static_cast<HTMLFormControlElement*>(unhandled)->updateVisibleValidationMessage(); - break; - } + unhandled->focus(); + if (unhandled->isFormControlElement()) + static_cast<HTMLFormControlElement*>(unhandled)->updateVisibleValidationMessage(); + break; } } // Warn about all of unfocusable controls. @@ -417,7 +411,7 @@ unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element) // Compares the position of the form element and the inserted element. // Updates the indeces in order to the relation of the position: unsigned short position = compareDocumentPosition(element); - if (position & DOCUMENT_POSITION_CONTAINS) + if (position & (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_CONTAINED_BY)) ++m_associatedElementsAfterIndex; else if (position & DOCUMENT_POSITION_PRECEDING) { ++m_associatedElementsBeforeIndex; @@ -488,18 +482,15 @@ void HTMLFormElement::removeFormElement(FormAssociatedElement* e) { if (e->isFormControlElement()) m_checkedRadioButtons.removeButton(static_cast<HTMLFormControlElement*>(e)); - HTMLElement* element = toHTMLElement(e); - if (element->fastHasAttribute(formAttr)) { - unsigned index; - for (index = 0; index < m_associatedElements.size(); ++index) - if (m_associatedElements[index] == e) - break; - ASSERT(index < m_associatedElements.size()); - if (index < m_associatedElementsBeforeIndex) - --m_associatedElementsBeforeIndex; - if (index < m_associatedElementsAfterIndex) - --m_associatedElementsAfterIndex; - } else + unsigned index; + for (index = 0; index < m_associatedElements.size(); ++index) { + if (m_associatedElements[index] == e) + break; + } + ASSERT(index < m_associatedElements.size()); + if (index < m_associatedElementsBeforeIndex) + --m_associatedElementsBeforeIndex; + if (index < m_associatedElementsAfterIndex) --m_associatedElementsAfterIndex; removeFromVector(m_associatedElements, e); } @@ -593,39 +584,6 @@ bool HTMLFormElement::checkValidity() return !checkInvalidControlsAndCollectUnhandled(controls); } -void HTMLFormElement::broadcastFormEvent(const AtomicString& eventName) -{ - RefPtr<HTMLFormElement> protector(this); - // Copy m_associatedElements because event handlers called from - // formElement->dispatchEvent() might change m_associatedElements. - Vector<RefPtr<FormAssociatedElement> > elements; - elements.reserveCapacity(m_associatedElements.size()); - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - if (!m_associatedElements[i]->isResettable()) - continue; - elements.append(m_associatedElements[i]); - } - - for (unsigned i = 0; i < elements.size(); ++i) { - // We can assume a resettable control is always a HTMLFormControlElement. - // FIXME: We should handle resettable non-HTMLFormControlElements maybe in the future. - ASSERT(elements[i]->isFormControlElement()); - HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(elements[i].get()); - if (!formElement->dispatchEvent(Event::create(eventName, false, false))) - continue; - } -} - -void HTMLFormElement::dispatchFormInput() -{ - broadcastFormEvent(eventNames().forminputEvent); -} - -void HTMLFormElement::dispatchFormChange() -{ - broadcastFormEvent(eventNames().formchangeEvent); -} - bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(Vector<RefPtr<FormAssociatedElement> >& unhandledInvalidControls) { RefPtr<HTMLFormElement> protector(this); diff --git a/Source/WebCore/html/HTMLFormElement.h b/Source/WebCore/html/HTMLFormElement.h index f723533..3100f67 100644 --- a/Source/WebCore/html/HTMLFormElement.h +++ b/Source/WebCore/html/HTMLFormElement.h @@ -114,9 +114,6 @@ public: const Vector<FormAssociatedElement*>& associatedElements() const { return m_associatedElements; } - void dispatchFormInput(); - void dispatchFormChange(); - private: HTMLFormElement(const QualifiedName&, Document*); @@ -148,8 +145,6 @@ private: // are any invalid controls in this form. bool checkInvalidControlsAndCollectUnhandled(Vector<RefPtr<FormAssociatedElement> >&); - void broadcastFormEvent(const AtomicString&); - friend class HTMLFormCollection; typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<HTMLFormControlElement> > AliasMap; diff --git a/Source/WebCore/html/HTMLFormElement.idl b/Source/WebCore/html/HTMLFormElement.idl index 3e9e46d..e9759e2 100644 --- a/Source/WebCore/html/HTMLFormElement.idl +++ b/Source/WebCore/html/HTMLFormElement.idl @@ -43,9 +43,6 @@ module html { #endif void reset(); boolean checkValidity(); - - void dispatchFormInput(); - void dispatchFormChange(); }; } diff --git a/Source/WebCore/html/HTMLFrameOwnerElement.cpp b/Source/WebCore/html/HTMLFrameOwnerElement.cpp index 2a7b610..a217881 100644 --- a/Source/WebCore/html/HTMLFrameOwnerElement.cpp +++ b/Source/WebCore/html/HTMLFrameOwnerElement.cpp @@ -89,6 +89,11 @@ void HTMLFrameOwnerElement::setSandboxFlags(SandboxFlags flags) frame->loader()->ownerElementSandboxFlagsChanged(); } +bool HTMLFrameOwnerElement::isKeyboardFocusable(KeyboardEvent* event) const +{ + return m_contentFrame && HTMLElement::isKeyboardFocusable(event); +} + #if ENABLE(SVG) SVGDocument* HTMLFrameOwnerElement::getSVGDocument(ExceptionCode& ec) const { diff --git a/Source/WebCore/html/HTMLFrameOwnerElement.h b/Source/WebCore/html/HTMLFrameOwnerElement.h index f784f4f..de9d153 100644 --- a/Source/WebCore/html/HTMLFrameOwnerElement.h +++ b/Source/WebCore/html/HTMLFrameOwnerElement.h @@ -66,7 +66,7 @@ private: friend class Frame; virtual bool isFrameOwnerElement() const { return true; } - virtual bool isKeyboardFocusable(KeyboardEvent*) const { return m_contentFrame; } + virtual bool isKeyboardFocusable(KeyboardEvent*) const; Frame* m_contentFrame; SandboxFlags m_sandboxFlags; diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp index 7ae6ad9..83e8c7d 100644 --- a/Source/WebCore/html/HTMLInputElement.cpp +++ b/Source/WebCore/html/HTMLInputElement.cpp @@ -443,6 +443,7 @@ void HTMLInputElement::setType(const String& type) void HTMLInputElement::updateType() { +<<<<<<< HEAD const AtomicString& typeString = fastGetAttribute(typeAttr); OwnPtr<InputType> newType = InputType::create(this, typeString); @@ -450,19 +451,21 @@ void HTMLInputElement::updateType() if (newType->isPasswordField() && document()->focusedNode() == this) PlatformBridge::updateTextfield(document()->view(), this, true, String()); #endif +======= + OwnPtr<InputType> newType = InputType::create(this, fastGetAttribute(typeAttr)); + bool hadType = m_hasType; + m_hasType = true; + if (m_inputType->formControlType() == newType->formControlType()) + return; +>>>>>>> WebKit.org at r84325 - if (m_hasType && !newType->canChangeFromAnotherType()) { + if (hadType && !newType->canChangeFromAnotherType()) { // Set the attribute back to the old value. // Useful in case we were called from inside parseMappedAttribute. setAttribute(typeAttr, type()); return; } - m_hasType = true; - - if (m_inputType->formControlType() == newType->formControlType()) - return; - checkedRadioButtons().removeButton(this); bool wasAttached = attached(); diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h index f2c2625..2a98b13 100644 --- a/Source/WebCore/html/HTMLInputElement.h +++ b/Source/WebCore/html/HTMLInputElement.h @@ -215,7 +215,6 @@ private: virtual bool isKeyboardFocusable(KeyboardEvent*) const; virtual bool isMouseFocusable() const; virtual bool isEnumeratable() const; - virtual bool isResettable() const { return true; } virtual void updateFocusAppearance(bool restorePreviousSelection); virtual void aboutToUnload(); virtual bool shouldUseInputMethod() const; diff --git a/Source/WebCore/html/HTMLKeygenElement.cpp b/Source/WebCore/html/HTMLKeygenElement.cpp index b90335e..29c9deb 100644 --- a/Source/WebCore/html/HTMLKeygenElement.cpp +++ b/Source/WebCore/html/HTMLKeygenElement.cpp @@ -32,6 +32,7 @@ #include "HTMLSelectElement.h" #include "HTMLOptionElement.h" #include "SSLKeyGenerator.h" +#include "ShadowRoot.h" #include "Text.h" #include <wtf/StdLibExtras.h> @@ -67,15 +68,18 @@ inline HTMLKeygenElement::HTMLKeygenElement(const QualifiedName& tagName, Docume ASSERT(hasTagName(keygenTag)); // Create a select element with one option element for each key size. - RefPtr<HTMLSelectElement> select = KeygenSelectElement::create(document); Vector<String> keys; getSupportedKeySizes(keys); + + RefPtr<HTMLSelectElement> select = KeygenSelectElement::create(document); + ExceptionCode ec = 0; for (size_t i = 0; i < keys.size(); ++i) { RefPtr<HTMLOptionElement> option = HTMLOptionElement::create(document, this->form()); - select->parserAddChild(option); - option->parserAddChild(Text::create(document, keys[i])); + select->appendChild(option, ec); + option->appendChild(Text::create(document, keys[i]), ec); } - setShadowRoot(select); + + ensureShadowRoot()->appendChild(select, ec); } PassRefPtr<HTMLKeygenElement> HTMLKeygenElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form) @@ -87,7 +91,7 @@ void HTMLKeygenElement::parseMappedAttribute(Attribute* attr) { // Reflect disabled attribute on the shadow select element if (attr->name() == disabledAttr) - selectShadow()->setAttribute(attr->name(), attr->value()); + shadowSelect()->setAttribute(attr->name(), attr->value()); if (attr->name() == challengeAttr) m_challenge = attr->value(); @@ -102,7 +106,7 @@ bool HTMLKeygenElement::appendFormData(FormDataList& encoded_values, bool) // Only RSA is supported at this time. if (!m_keyType.isNull() && !equalIgnoringCase(m_keyType, "rsa")) return false; - String value = signedPublicKeyAndChallengeString(selectShadow()->selectedIndex(), m_challenge, document()->baseURL()); + String value = signedPublicKeyAndChallengeString(shadowSelect()->selectedIndex(), m_challenge, document()->baseURL()); if (value.isNull()) return false; encoded_values.appendData(name(), value.utf8()); @@ -117,12 +121,14 @@ const AtomicString& HTMLKeygenElement::formControlType() const void HTMLKeygenElement::reset() { - static_cast<HTMLFormControlElement*>(selectShadow())->reset(); + static_cast<HTMLFormControlElement*>(shadowSelect())->reset(); } -HTMLSelectElement* HTMLKeygenElement::selectShadow() +HTMLSelectElement* HTMLKeygenElement::shadowSelect() const { - return static_cast<HTMLSelectElement*>(shadowRoot()); + Node* shadow = shadowRoot(); + ASSERT(shadow); + return shadow ? static_cast<HTMLSelectElement*>(shadow->firstChild()) : 0; } } // namespace diff --git a/Source/WebCore/html/HTMLKeygenElement.h b/Source/WebCore/html/HTMLKeygenElement.h index a7a8a64..88782c8 100644 --- a/Source/WebCore/html/HTMLKeygenElement.h +++ b/Source/WebCore/html/HTMLKeygenElement.h @@ -49,10 +49,9 @@ private: virtual bool isEnumeratable() const { return true; } - virtual bool isResettable() const { return true; } virtual void reset(); - HTMLSelectElement* selectShadow(); + HTMLSelectElement* shadowSelect() const; AtomicString m_challenge; AtomicString m_keyType; diff --git a/Source/WebCore/html/HTMLLinkElement.cpp b/Source/WebCore/html/HTMLLinkElement.cpp index 67262d9..7cbf38b 100644 --- a/Source/WebCore/html/HTMLLinkElement.cpp +++ b/Source/WebCore/html/HTMLLinkElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "CachedCSSStyleSheet.h" +#include "CachedResource.h" #include "CachedResourceLoader.h" #include "CSSStyleSelector.h" #include "Document.h" @@ -78,8 +79,8 @@ HTMLLinkElement::~HTMLLinkElement() } #if ENABLE(LINK_PREFETCH) - if (m_cachedLinkPrefetch) - m_cachedLinkPrefetch->removeClient(this); + if (m_cachedLinkResource) + m_cachedLinkResource->removeClient(this); #endif } @@ -163,6 +164,7 @@ void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& rel, RelAttribute relAttribute.m_isDNSPrefetch = false; #if ENABLE(LINK_PREFETCH) relAttribute.m_isLinkPrefetch = false; + relAttribute.m_isLinkSubresource = false; #endif #ifdef ANDROID_APPLE_TOUCH_ICON relAttribute.m_isTouchIcon = false; @@ -180,10 +182,6 @@ void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& rel, RelAttribute #endif else if (equalIgnoringCase(rel, "dns-prefetch")) relAttribute.m_isDNSPrefetch = true; -#if ENABLE(LINK_PREFETCH) - else if (equalIgnoringCase(rel, "prefetch")) - relAttribute.m_isLinkPrefetch = true; -#endif else if (equalIgnoringCase(rel, "alternate stylesheet") || equalIgnoringCase(rel, "stylesheet alternate")) { relAttribute.m_isStyleSheet = true; relAttribute.m_isAlternate = true; @@ -201,6 +199,12 @@ void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& rel, RelAttribute relAttribute.m_isAlternate = true; else if (equalIgnoringCase(*it, "icon")) relAttribute.m_isIcon = true; +#if ENABLE(LINK_PREFETCH) + else if (equalIgnoringCase(*it, "prefetch")) + relAttribute.m_isLinkPrefetch = true; + else if (equalIgnoringCase(*it, "subresource")) + relAttribute.m_isLinkSubresource = true; +#endif } } } @@ -250,12 +254,16 @@ void HTMLLinkElement::process() } #if ENABLE(LINK_PREFETCH) - if (m_relAttribute.m_isLinkPrefetch && m_url.isValid() && document()->frame()) { + if ((m_relAttribute.m_isLinkPrefetch || m_relAttribute.m_isLinkSubresource) && m_url.isValid() && document()->frame()) { if (!checkBeforeLoadEvent()) return; - m_cachedLinkPrefetch = document()->cachedResourceLoader()->requestLinkPrefetch(m_url); - if (m_cachedLinkPrefetch) - m_cachedLinkPrefetch->addClient(this); + ResourceLoadPriority priority = ResourceLoadPriorityUnresolved; + if (m_relAttribute.m_isLinkSubresource) + priority = ResourceLoadPriorityLow; + + m_cachedLinkResource = document()->cachedResourceLoader()->requestLinkResource(m_url, priority); + if (m_cachedLinkResource) + m_cachedLinkResource->addClient(this); } #endif @@ -427,19 +435,19 @@ bool HTMLLinkElement::isLoading() const void HTMLLinkElement::onloadTimerFired(Timer<HTMLLinkElement>* timer) { ASSERT_UNUSED(timer, timer == &m_onloadTimer); - if (m_cachedLinkPrefetch->errorOccurred()) + if (m_cachedLinkResource->errorOccurred()) dispatchEvent(Event::create(eventNames().errorEvent, false, false)); else dispatchEvent(Event::create(eventNames().loadEvent, false, false)); - m_cachedLinkPrefetch->removeClient(this); - m_cachedLinkPrefetch = 0; + m_cachedLinkResource->removeClient(this); + m_cachedLinkResource = 0; } void HTMLLinkElement::notifyFinished(CachedResource* resource) { m_onloadTimer.startOneShot(0); - ASSERT(m_cachedLinkPrefetch.get() == resource); + ASSERT(m_cachedLinkResource.get() == resource); } #endif diff --git a/Source/WebCore/html/HTMLLinkElement.h b/Source/WebCore/html/HTMLLinkElement.h index d31feeb..f602d38 100644 --- a/Source/WebCore/html/HTMLLinkElement.h +++ b/Source/WebCore/html/HTMLLinkElement.h @@ -48,6 +48,7 @@ public: #endif #if ENABLE(LINK_PREFETCH) bool m_isLinkPrefetch; + bool m_isLinkSubresource; #endif RelAttribute() @@ -57,6 +58,7 @@ public: , m_isDNSPrefetch(false) #if ENABLE(LINK_PREFETCH) , m_isLinkPrefetch(false) + , m_isLinkSubresource(false) #endif { } @@ -138,7 +140,7 @@ private: CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet; RefPtr<CSSStyleSheet> m_sheet; #if ENABLE(LINK_PREFETCH) - CachedResourceHandle<CachedResource> m_cachedLinkPrefetch; + CachedResourceHandle<CachedResource> m_cachedLinkResource; Timer<HTMLLinkElement> m_onloadTimer; #endif KURL m_url; diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index 29c0cb8..5505343 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -33,6 +33,7 @@ #include "ChromeClient.h" #include "ClientRect.h" #include "ClientRectList.h" +#include "ContentSecurityPolicy.h" #include "ContentType.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" @@ -54,12 +55,14 @@ #include "MediaList.h" #include "MediaPlayer.h" #include "MediaQueryEvaluator.h" +#include "MouseEvent.h" #include "MIMETypeRegistry.h" #include "Page.h" #include "RenderVideo.h" #include "RenderView.h" #include "ScriptEventListener.h" #include "Settings.h" +#include "ShadowRoot.h" #include "TimeRanges.h" #include <limits> #include <wtf/CurrentTime.h> @@ -161,6 +164,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum , m_sendProgressEvents(true) , m_isFullscreen(false) , m_closedCaptionsVisible(false) + , m_mouseOver(false) #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) , m_needWidgetUpdate(false) #endif @@ -223,12 +227,14 @@ void HTMLMediaElement::attributeChanged(Attribute* attr, bool preserveDecls) } else if (attrName == controlsAttr) { #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO) - if (!isVideo() && attached() && (controls() != (renderer() != 0))) { - detach(); - attach(); - } - if (hasMediaControls()) - mediaControls()->reset(); + if (controls()) { + if (!hasMediaControls()) { + ensureMediaControls(); + mediaControls()->reset(); + } + mediaControls()->show(); + } else if (hasMediaControls()) + mediaControls()->hide(); #else if (m_player) m_player->setControls(controls()); @@ -743,6 +749,9 @@ bool HTMLMediaElement::isSafeToLoadURL(const KURL& url, InvalidSourceAction acti return false; } + if (!document()->contentSecurityPolicy()->allowMediaFromSource(url)) + return false; + return true; } @@ -900,6 +909,8 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state) noneSupported(); updateDisplayState(); + if (hasMediaControls()) + mediaControls()->reportedError(); return; } @@ -929,6 +940,9 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state) m_networkState = NETWORK_IDLE; m_completelyLoaded = true; } + + if (hasMediaControls()) + mediaControls()->changedNetworkState(); } void HTMLMediaElement::mediaPlayerReadyStateChanged(MediaPlayer*) @@ -978,6 +992,8 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { scheduleEvent(eventNames().durationchangeEvent); scheduleEvent(eventNames().loadedmetadataEvent); + if (hasMediaControls()) + mediaControls()->loadedMetadata(); if (renderer()) renderer()->updateFromElement(); m_player->seek(0); @@ -1491,6 +1507,10 @@ bool HTMLMediaElement::controls() const if (isVideo() && document()->page() && document()->page()->chrome()->requiresFullscreenForVideoPlayback()) return true; + // Always show controls when in full screen mode. + if (isFullscreen()) + return true; + return hasAttribute(controlsAttr); } @@ -1605,9 +1625,11 @@ void HTMLMediaElement::playbackProgressTimerFired(Timer<HTMLMediaElement>*) return; scheduleTimeupdateEvent(true); - if (hasMediaControls()) + if (hasMediaControls()) { + if (!m_mouseOver && controls()) + mediaControls()->makeTransparent(); mediaControls()->playbackProgressed(); - + } // FIXME: deal with cue ranges here } @@ -1997,13 +2019,26 @@ void HTMLMediaElement::mediaPlayerRenderingModeChanged(MediaPlayer*) void HTMLMediaElement::mediaPlayerEngineUpdated(MediaPlayer*) { - beginProcessingMediaPlayerCallback(); LOG(Media, "HTMLMediaElement::mediaPlayerEngineUpdated"); + beginProcessingMediaPlayerCallback(); if (renderer()) renderer()->updateFromElement(); endProcessingMediaPlayerCallback(); } +void HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable(MediaPlayer*) +{ + LOG(Media, "HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable"); + beginProcessingMediaPlayerCallback(); + if (displayMode() == PosterWaitingForVideo) { + setDisplayMode(Video); +#if USE(ACCELERATED_COMPOSITING) + mediaPlayerRenderingModeChanged(m_player.get()); +#endif + } + endProcessingMediaPlayerCallback(); +} + PassRefPtr<TimeRanges> HTMLMediaElement::buffered() const { if (!m_player) @@ -2148,9 +2183,11 @@ void HTMLMediaElement::updatePlayState() if (!m_isFullscreen && isVideo() && document() && document()->page() && document()->page()->chrome()->requiresFullscreenForVideoPlayback()) enterFullscreen(); - // Set rate before calling play in case the rate was set before the media engine was setup. - // The media engine should just stash the rate since it isn't already playing. + // Set rate, muted before calling play in case they were set before the media engine was setup. + // The media engine should just stash the rate and muted values since it isn't already playing. m_player->setRate(m_playbackRate); + m_player->setMuted(m_muted); + m_player->play(); } @@ -2323,10 +2360,18 @@ void HTMLMediaElement::defaultEventHandler(Event* event) if (widget) widget->handleEvent(event); #else - if (hasMediaControls()) - mediaControls()->forwardEvent(event); - if (event->defaultHandled()) - return; + if (event->isMouseEvent()) { + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); + if (mouseEvent->relatedTarget() != this) { + if (event->type() == eventNames().mouseoverEvent) { + m_mouseOver = true; + if (hasMediaControls() && controls() && !canPlay()) + mediaControls()->makeOpaque(); + } else if (event->type() == eventNames().mouseoutEvent) + m_mouseOver = false; + } + } + HTMLElement::defaultEventHandler(event); #endif } @@ -2459,9 +2504,16 @@ bool HTMLMediaElement::isFullscreen() const void HTMLMediaElement::enterFullscreen() { LOG(Media, "HTMLMediaElement::enterFullscreen"); - +#if ENABLE(FULLSCREEN_API) + if (document() && document()->settings() && document()->settings()->fullScreenEnabled()) { + webkitRequestFullScreen(0); + return; + } +#endif ASSERT(!m_isFullscreen); m_isFullscreen = true; + if (hasMediaControls()) + mediaControls()->enteredFullscreen(); if (document() && document()->page()) { document()->page()->chrome()->client()->enterFullscreenForNode(this); scheduleEvent(eventNames().webkitbeginfullscreenEvent); @@ -2471,9 +2523,17 @@ void HTMLMediaElement::enterFullscreen() void HTMLMediaElement::exitFullscreen() { LOG(Media, "HTMLMediaElement::exitFullscreen"); - +#if ENABLE(FULLSCREEN_API) + if (document() && document()->settings() && document()->settings()->fullScreenEnabled()) { + if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == this) + document()->webkitCancelFullScreen(); + return; + } +#endif ASSERT(m_isFullscreen); m_isFullscreen = false; + if (hasMediaControls()) + mediaControls()->exitedFullscreen(); if (document() && document()->page()) { if (document()->page()->chrome()->requiresFullscreenForVideoPlayback()) pauseInternal(); @@ -2606,15 +2666,44 @@ void HTMLMediaElement::privateBrowsingStateDidChange() MediaControls* HTMLMediaElement::mediaControls() { - ASSERT(renderer()); - return toRenderMedia(renderer())->controls(); + if (!shadowRoot()) + return 0; + + Node* node = shadowRoot()->firstChild(); + ASSERT(node->isHTMLElement()); + return static_cast<MediaControls*>(node); +} + +bool HTMLMediaElement::hasMediaControls() +{ + return shadowRoot(); +} + +void HTMLMediaElement::ensureMediaControls() +{ + if (hasMediaControls()) + return; + + ExceptionCode ec; + ensureShadowRoot()->appendChild(MediaControls::create(this), ec); } -bool HTMLMediaElement::hasMediaControls() const +void* HTMLMediaElement::preDispatchEventHandler(Event* event) { - return renderer() && renderer()->isMedia(); + if (event && event->type() == eventNames().webkitfullscreenchangeEvent) { + if (controls()) { + if (!hasMediaControls()) { + ensureMediaControls(); + mediaControls()->reset(); + } + mediaControls()->show(); + } else if (hasMediaControls()) + mediaControls()->hide(); + } + return 0; } + } #endif diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h index ea958fa..604cdf8 100644 --- a/Source/WebCore/html/HTMLMediaElement.h +++ b/Source/WebCore/html/HTMLMediaElement.h @@ -212,7 +212,7 @@ protected: virtual void willMoveToNewOwnerDocument(); virtual void didMoveToNewOwnerDocument(); - enum DisplayMode { Unknown, None, Poster, Video }; + enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video }; DisplayMode displayMode() const { return m_displayMode; } virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; } @@ -257,6 +257,7 @@ private: virtual void mediaPlayerRenderingModeChanged(MediaPlayer*); #endif virtual void mediaPlayerEngineUpdated(MediaPlayer*); + virtual void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*); void loadTimerFired(Timer<HTMLMediaElement>*); void asyncEventTimerFired(Timer<HTMLMediaElement>*); @@ -323,7 +324,10 @@ private: void invalidateCachedTime(); void refreshCachedTime() const; - bool hasMediaControls() const; + bool hasMediaControls(); + void ensureMediaControls(); + + virtual void* preDispatchEventHandler(Event*); Timer<HTMLMediaElement> m_loadTimer; Timer<HTMLMediaElement> m_asyncEventTimer; @@ -331,7 +335,7 @@ private: Timer<HTMLMediaElement> m_playbackProgressTimer; Vector<RefPtr<Event> > m_pendingEvents; RefPtr<TimeRanges> m_playedTimeRanges; - + float m_playbackRate; float m_defaultPlaybackRate; bool m_webkitPreservesPitch; @@ -404,6 +408,7 @@ private: bool m_isFullscreen : 1; bool m_closedCaptionsVisible : 1; + bool m_mouseOver : 1; #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) bool m_needWidgetUpdate : 1; diff --git a/Source/WebCore/html/HTMLMeterElement.cpp b/Source/WebCore/html/HTMLMeterElement.cpp index 2ebf57e..88b1622 100644 --- a/Source/WebCore/html/HTMLMeterElement.cpp +++ b/Source/WebCore/html/HTMLMeterElement.cpp @@ -29,7 +29,9 @@ #include "HTMLFormElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" +#include "MeterShadowElement.h" #include "RenderMeter.h" +#include "ShadowRoot.h" #include <wtf/StdLibExtras.h> namespace WebCore { @@ -42,9 +44,15 @@ HTMLMeterElement::HTMLMeterElement(const QualifiedName& tagName, Document* docum ASSERT(hasTagName(meterTag)); } +HTMLMeterElement::~HTMLMeterElement() +{ +} + PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form) { - return adoptRef(new HTMLMeterElement(tagName, document, form)); + RefPtr<HTMLMeterElement> meter = adoptRef(new HTMLMeterElement(tagName, document, form)); + meter->createShadowSubtree(); + return meter; } RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*) @@ -60,18 +68,16 @@ const AtomicString& HTMLMeterElement::formControlType() const void HTMLMeterElement::parseMappedAttribute(Attribute* attribute) { - if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr) { - if (renderer()) - renderer()->updateFromElement(); - } else + if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr) + didElementStateChange(); + else HTMLFormControlElement::parseMappedAttribute(attribute); } void HTMLMeterElement::attach() { HTMLFormControlElement::attach(); - if (renderer()) - renderer()->updateFromElement(); + didElementStateChange(); } double HTMLMeterElement::min() const @@ -203,5 +209,30 @@ HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const return GaugeRegionSuboptimal; } +double HTMLMeterElement::valueRatio() const +{ + double min = this->min(); + double max = this->max(); + double value = this->value(); + + if (max <= min) + return 0; + return (value - min) / (max - min); +} + +void HTMLMeterElement::didElementStateChange() +{ + m_value->setWidthPercentage(valueRatio()*100); +} + +void HTMLMeterElement::createShadowSubtree() +{ + RefPtr<MeterBarElement> bar = MeterBarElement::create(document()); + m_value = MeterValueElement::create(document()); + ExceptionCode ec = 0; + bar->appendChild(m_value, ec); + ensureShadowRoot()->appendChild(bar, ec); +} + } // namespace #endif diff --git a/Source/WebCore/html/HTMLMeterElement.h b/Source/WebCore/html/HTMLMeterElement.h index d5038e0..5ce1193 100644 --- a/Source/WebCore/html/HTMLMeterElement.h +++ b/Source/WebCore/html/HTMLMeterElement.h @@ -26,6 +26,8 @@ namespace WebCore { +class MeterValueElement; + class HTMLMeterElement : public HTMLFormControlElement { public: static PassRefPtr<HTMLMeterElement> create(const QualifiedName&, Document*, HTMLFormElement*); @@ -54,19 +56,23 @@ public: double optimum() const; void setOptimum(double, ExceptionCode&); + double valueRatio() const; GaugeRegion gaugeRegion() const; + private: HTMLMeterElement(const QualifiedName&, Document*, HTMLFormElement*); + virtual ~HTMLMeterElement(); virtual bool recalcWillValidate() const { return false; } - virtual const AtomicString& formControlType() const; - virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - virtual void parseMappedAttribute(Attribute*); - virtual void attach(); + + void didElementStateChange(); + void createShadowSubtree(); + + RefPtr<MeterValueElement> m_value; }; } // namespace diff --git a/Source/WebCore/html/HTMLObjectElement.cpp b/Source/WebCore/html/HTMLObjectElement.cpp index 4f4d0a1..f5f0083 100644 --- a/Source/WebCore/html/HTMLObjectElement.cpp +++ b/Source/WebCore/html/HTMLObjectElement.cpp @@ -236,17 +236,19 @@ bool HTMLObjectElement::hasFallbackContent() const return false; } -inline bool HTMLObjectElement::hasValidClassId() +bool HTMLObjectElement::hasValidClassId() { +#if PLATFORM(QT) + if (equalIgnoringCase(serviceType(), "application/x-qt-plugin") || equalIgnoringCase(serviceType(), "application/x-qt-styled-widget")) + return true; +#endif + + if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType()) && classId().startsWith("java:", false)) + return true; + // HTML5 says that fallback content should be rendered if a non-empty // classid is specified for which the UA can't find a suitable plug-in. - // WebKit supports no classids, with the exception of Qt plug-ins, which use - // classid to specify which QObject to load. -#if PLATFORM(QT) - return classId().isEmpty() || equalIgnoringCase(serviceType(), "application/x-qt-plugin") || equalIgnoringCase(serviceType(), "application/x-qt-styled-widget"); -#else return classId().isEmpty(); -#endif } // FIXME: This should be unified with HTMLEmbedElement::updateWidget and diff --git a/Source/WebCore/html/HTMLObjectElement.h b/Source/WebCore/html/HTMLObjectElement.h index 82d63f7..b929ad5 100644 --- a/Source/WebCore/html/HTMLObjectElement.h +++ b/Source/WebCore/html/HTMLObjectElement.h @@ -50,7 +50,6 @@ public: virtual bool isFormControlElement() const { return false; } virtual bool isEnumeratable() const { return true; } - virtual bool isResettable() const { return false; } virtual bool appendFormData(FormDataList&, bool); // Implementations of constraint validation API. diff --git a/Source/WebCore/html/HTMLOutputElement.h b/Source/WebCore/html/HTMLOutputElement.h index 4c5c684..83ecee2 100644 --- a/Source/WebCore/html/HTMLOutputElement.h +++ b/Source/WebCore/html/HTMLOutputElement.h @@ -56,7 +56,6 @@ private: virtual void parseMappedAttribute(Attribute*); virtual const AtomicString& formControlType() const; virtual bool isEnumeratable() const { return true; } - virtual bool isResettable() const { return true; } virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual void reset(); diff --git a/Source/WebCore/html/HTMLProgressElement.cpp b/Source/WebCore/html/HTMLProgressElement.cpp index cab0429..710f7e4 100644 --- a/Source/WebCore/html/HTMLProgressElement.cpp +++ b/Source/WebCore/html/HTMLProgressElement.cpp @@ -30,23 +30,33 @@ #include "HTMLFormElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" -#include "ProgressBarValueElement.h" +#include "ProgressShadowElement.h" #include "RenderProgress.h" +#include "ShadowRoot.h" #include <wtf/StdLibExtras.h> namespace WebCore { using namespace HTMLNames; +const double HTMLProgressElement::IndeterminatePosition = -1; +const double HTMLProgressElement::InvalidPosition = -2; + HTMLProgressElement::HTMLProgressElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form) : HTMLFormControlElement(tagName, document, form) { ASSERT(hasTagName(progressTag)); } +HTMLProgressElement::~HTMLProgressElement() +{ +} + PassRefPtr<HTMLProgressElement> HTMLProgressElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form) { - return adoptRef(new HTMLProgressElement(tagName, document, form)); + RefPtr<HTMLProgressElement> progress = adoptRef(new HTMLProgressElement(tagName, document, form)); + progress->createShadowSubtree(); + return progress; } RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle*) @@ -72,7 +82,6 @@ void HTMLProgressElement::parseMappedAttribute(Attribute* attribute) void HTMLProgressElement::attach() { - createShadowSubtreeIfNeeded(); HTMLFormControlElement::attach(); didElementStateChange(); } @@ -117,21 +126,24 @@ void HTMLProgressElement::setMax(double max, ExceptionCode& ec) double HTMLProgressElement::position() const { if (!hasAttribute(valueAttr)) - return -1; + return HTMLProgressElement::IndeterminatePosition; return value() / max(); } void HTMLProgressElement::didElementStateChange() { + m_value->setWidthPercentage(position()*100); if (renderer()) renderer()->updateFromElement(); } -void HTMLProgressElement::createShadowSubtreeIfNeeded() +void HTMLProgressElement::createShadowSubtree() { - if (shadowRoot()) - return; - setShadowRoot(ProgressBarValueElement::create(document()).get()); + RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document()); + m_value = ProgressValueElement::create(document()); + ExceptionCode ec = 0; + bar->appendChild(m_value, ec); + ensureShadowRoot()->appendChild(bar, ec); } } // namespace diff --git a/Source/WebCore/html/HTMLProgressElement.h b/Source/WebCore/html/HTMLProgressElement.h index a0db966..42109f7 100644 --- a/Source/WebCore/html/HTMLProgressElement.h +++ b/Source/WebCore/html/HTMLProgressElement.h @@ -26,8 +26,13 @@ namespace WebCore { +class ProgressValueElement; + class HTMLProgressElement : public HTMLFormControlElement { public: + static const double IndeterminatePosition; + static const double InvalidPosition; + static PassRefPtr<HTMLProgressElement> create(const QualifiedName&, Document*, HTMLFormElement*); double value() const; @@ -40,6 +45,7 @@ public: private: HTMLProgressElement(const QualifiedName&, Document*, HTMLFormElement*); + virtual ~HTMLProgressElement(); virtual bool recalcWillValidate() const { return false; } @@ -52,7 +58,9 @@ private: virtual void attach(); void didElementStateChange(); - void createShadowSubtreeIfNeeded(); + void createShadowSubtree(); + + RefPtr<ProgressValueElement> m_value; }; } // namespace diff --git a/Source/WebCore/html/HTMLSelectElement.h b/Source/WebCore/html/HTMLSelectElement.h index 837675c..e6e1bec 100644 --- a/Source/WebCore/html/HTMLSelectElement.h +++ b/Source/WebCore/html/HTMLSelectElement.h @@ -107,7 +107,6 @@ private: virtual bool canStartSelection() const { return false; } virtual bool isEnumeratable() const { return true; } - virtual bool isResettable() const { return true; } virtual bool saveFormControlState(String& value) const; virtual void restoreFormControlState(const String&); diff --git a/Source/WebCore/html/HTMLSummaryElement.cpp b/Source/WebCore/html/HTMLSummaryElement.cpp index 9c2222a..1a1fefc 100644 --- a/Source/WebCore/html/HTMLSummaryElement.cpp +++ b/Source/WebCore/html/HTMLSummaryElement.cpp @@ -21,8 +21,11 @@ #include "config.h" #include "HTMLSummaryElement.h" +#include "DetailsMarkerControl.h" #include "HTMLDetailsElement.h" #include "HTMLNames.h" +#include "MouseEvent.h" +#include "PlatformMouseEvent.h" #include "RenderSummary.h" namespace WebCore { @@ -31,7 +34,9 @@ using namespace HTMLNames; PassRefPtr<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document* document) { - return adoptRef(new HTMLSummaryElement(tagName, document)); + RefPtr<HTMLSummaryElement> result = adoptRef(new HTMLSummaryElement(tagName, document)); + result->createShadowSubtree(); + return result; } HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document* document) @@ -45,4 +50,40 @@ RenderObject* HTMLSummaryElement::createRenderer(RenderArena* arena, RenderStyle return new (arena) RenderSummary(this); } +void HTMLSummaryElement::createShadowSubtree() +{ + ExceptionCode ec = 0; + ensureShadowRoot()->appendChild(DetailsMarkerControl::create(document()), ec, true); +} + +HTMLDetailsElement* HTMLSummaryElement::detailsElement() const +{ + Element* mayDetails = toElement(parentNodeForRenderingAndStyle()); + if (!mayDetails || !mayDetails->hasTagName(detailsTag)) + return 0; + return static_cast<HTMLDetailsElement*>(mayDetails); +} + +bool HTMLSummaryElement::isMainSummary() const +{ + if (HTMLDetailsElement* details = detailsElement()) + return details->mainSummary() == this; + return 0; +} + +void HTMLSummaryElement::defaultEventHandler(Event* event) +{ + HTMLElement::defaultEventHandler(event); + if (!isMainSummary() || !renderer() || !renderer()->isSummary() || !event->isMouseEvent() || event->type() != eventNames().clickEvent || event->defaultHandled()) + return; + + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); + if (mouseEvent->button() != LeftButton) + return; + + if (HTMLDetailsElement* details = detailsElement()) + details->toggleOpen(); + event->setDefaultHandled(); +} + } diff --git a/Source/WebCore/html/HTMLSummaryElement.h b/Source/WebCore/html/HTMLSummaryElement.h index 1a93ee9..7e3766a 100644 --- a/Source/WebCore/html/HTMLSummaryElement.h +++ b/Source/WebCore/html/HTMLSummaryElement.h @@ -25,14 +25,22 @@ namespace WebCore { +class HTMLDetailsElement; + class HTMLSummaryElement : public HTMLElement { public: static PassRefPtr<HTMLSummaryElement> create(const QualifiedName&, Document*); + bool isMainSummary() const; private: HTMLSummaryElement(const QualifiedName&, Document*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual void defaultEventHandler(Event*); + virtual void createShadowSubtree(); + virtual bool canHaveLightChildRendererWithShadow() const { return true; } + + HTMLDetailsElement* detailsElement() const; }; } diff --git a/Source/WebCore/html/HTMLTagNames.in b/Source/WebCore/html/HTMLTagNames.in index bea63e4..0bf4ff9 100644 --- a/Source/WebCore/html/HTMLTagNames.in +++ b/Source/WebCore/html/HTMLTagNames.in @@ -126,7 +126,7 @@ th interfaceName=HTMLTableCellElement thead interfaceName=HTMLTableSectionElement title tr interfaceName=HTMLTableRowElement -track interfaceName=HTMLElement +track wrapperOnlyIfMediaIsAvailable, conditional=VIDEO_TRACK tt interfaceName=HTMLElement u interfaceName=HTMLElement ul interfaceName=HTMLUListElement diff --git a/Source/WebCore/html/HTMLTextAreaElement.cpp b/Source/WebCore/html/HTMLTextAreaElement.cpp index c8ec9ab..5b12a14 100644 --- a/Source/WebCore/html/HTMLTextAreaElement.cpp +++ b/Source/WebCore/html/HTMLTextAreaElement.cpp @@ -108,7 +108,8 @@ void HTMLTextAreaElement::restoreFormControlState(const String& state) void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { - setNonDirtyValue(defaultValue()); + if (!m_isDirty) + setNonDirtyValue(defaultValue()); HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } @@ -347,12 +348,6 @@ String HTMLTextAreaElement::defaultValue() const value += static_cast<Text*>(n)->data(); } - UChar firstCharacter = value[0]; - if (firstCharacter == '\r' && value[1] == '\n') - value.remove(0, 2); - else if (firstCharacter == '\r' || firstCharacter == '\n') - value.remove(0, 1); - return value; } @@ -371,17 +366,14 @@ void HTMLTextAreaElement::setDefaultValue(const String& defaultValue) removeChild(textNodes[i].get(), ec); // Normalize line endings. - // Add an extra line break if the string starts with one, since - // the code to read default values from the DOM strips the leading one. String value = defaultValue; value.replace("\r\n", "\n"); value.replace('\r', '\n'); - if (value[0] == '\n') - value = "\n" + value; insertBefore(document()->createTextNode(value), firstChild(), ec); - setNonDirtyValue(value); + if (!m_isDirty) + setNonDirtyValue(value); } int HTMLTextAreaElement::maxLength() const diff --git a/Source/WebCore/html/HTMLTextAreaElement.h b/Source/WebCore/html/HTMLTextAreaElement.h index 40193a0..1ab8ba7 100644 --- a/Source/WebCore/html/HTMLTextAreaElement.h +++ b/Source/WebCore/html/HTMLTextAreaElement.h @@ -82,7 +82,6 @@ private: virtual void defaultEventHandler(Event*); virtual bool isEnumeratable() const { return true; } - virtual bool isResettable() const { return true; } virtual const AtomicString& formControlType() const; diff --git a/Source/WebCore/html/HTMLTitleElement.cpp b/Source/WebCore/html/HTMLTitleElement.cpp index 78c8b6a..b046c7b 100644 --- a/Source/WebCore/html/HTMLTitleElement.cpp +++ b/Source/WebCore/html/HTMLTitleElement.cpp @@ -25,6 +25,7 @@ #include "Document.h" #include "HTMLNames.h" +#include "RenderStyle.h" #include "Text.h" namespace WebCore { @@ -33,7 +34,6 @@ using namespace HTMLNames; inline HTMLTitleElement::HTMLTitleElement(const QualifiedName& tagName, Document* document) : HTMLElement(tagName, document) - , m_title("") { ASSERT(hasTagName(titleTag)); } @@ -57,7 +57,7 @@ void HTMLTitleElement::removedFromDocument() void HTMLTitleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { - m_title = text(); + m_title = textWithDirection(); if (inDocument()) document()->setTitleElement(m_title, this); HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); @@ -71,10 +71,20 @@ String HTMLTitleElement::text() const if (n->isTextNode()) val += static_cast<Text*>(n)->data(); } - + return val; } +StringWithDirection HTMLTitleElement::textWithDirection() +{ + TextDirection direction = LTR; + if (RenderStyle* style = computedStyle()) + direction = style->direction(); + else if (RefPtr<RenderStyle> style = styleForRenderer()) + direction = style->direction(); + return StringWithDirection(text(), direction); +} + void HTMLTitleElement::setText(const String &value) { ExceptionCode ec = 0; diff --git a/Source/WebCore/html/HTMLTitleElement.h b/Source/WebCore/html/HTMLTitleElement.h index 8b90f56..6920997 100644 --- a/Source/WebCore/html/HTMLTitleElement.h +++ b/Source/WebCore/html/HTMLTitleElement.h @@ -23,6 +23,7 @@ #define HTMLTitleElement_h #include "HTMLElement.h" +#include "StringWithDirection.h" namespace WebCore { @@ -33,6 +34,8 @@ public: String text() const; void setText(const String&); + StringWithDirection textWithDirection(); + private: HTMLTitleElement(const QualifiedName&, Document*); @@ -40,7 +43,7 @@ private: virtual void removedFromDocument(); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - String m_title; + StringWithDirection m_title; }; } //namespace diff --git a/Source/WebCore/html/HTMLTrackElement.cpp b/Source/WebCore/html/HTMLTrackElement.cpp new file mode 100644 index 0000000..63f2788 --- /dev/null +++ b/Source/WebCore/html/HTMLTrackElement.cpp @@ -0,0 +1,128 @@ +/* + * 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: + * 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_TRACK) +#include "HTMLTrackElement.h" + +#include "HTMLMediaElement.h" +#include "HTMLNames.h" +#include "Logging.h" + +using namespace std; + +namespace WebCore { + +using namespace HTMLNames; + +inline HTMLTrackElement::HTMLTrackElement(const QualifiedName& tagName, Document* document) + : HTMLElement(tagName, document) +{ + LOG(Media, "HTMLTrackElement::HTMLTrackElement - %p", this); + ASSERT(hasTagName(trackTag)); +} + +PassRefPtr<HTMLTrackElement> HTMLTrackElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new HTMLTrackElement(tagName, document)); +} + +void HTMLTrackElement::insertedIntoTree(bool deep) +{ + HTMLElement::insertedIntoTree(deep); + if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag))) { + // TODO(annacc): + // static_cast<HTMLMediaElement*>(parentNode())->trackWasAdded(this); + } +} + +void HTMLTrackElement::willRemove() +{ + if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag))) { + // TODO(annacc): + // static_cast<HTMLMediaElement*>(parentNode())->trackWillBeRemoved(this); + } + HTMLElement::willRemove(); +} + +KURL HTMLTrackElement::src() const +{ + return document()->completeURL(getAttribute(srcAttr)); +} + +void HTMLTrackElement::setSrc(const String& url) +{ + setAttribute(srcAttr, url); +} + +String HTMLTrackElement::kind() const +{ + return getAttribute(kindAttr); +} + +void HTMLTrackElement::setKind(const String& kind) +{ + setAttribute(kindAttr, kind); +} + +String HTMLTrackElement::srclang() const +{ + return getAttribute(srclangAttr); +} + +void HTMLTrackElement::setSrclang(const String& srclang) +{ + setAttribute(srclangAttr, srclang); +} + +String HTMLTrackElement::label() const +{ + return getAttribute(labelAttr); +} + +void HTMLTrackElement::setLabel(const String& label) +{ + setAttribute(labelAttr, label); +} + +bool HTMLTrackElement::isDefault() const +{ + return hasAttribute(defaultAttr); +} + +void HTMLTrackElement::setIsDefault(bool isDefault) +{ + setBooleanAttribute(defaultAttr, isDefault); +} + +bool HTMLTrackElement::isURLAttribute(Attribute* attribute) const +{ + return attribute->name() == srcAttr; +} + +} + +#endif diff --git a/Source/WebCore/html/HTMLTrackElement.h b/Source/WebCore/html/HTMLTrackElement.h new file mode 100644 index 0000000..4697e02 --- /dev/null +++ b/Source/WebCore/html/HTMLTrackElement.h @@ -0,0 +1,62 @@ +/* + * 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: + * 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 HTMLTrackElement_h +#define HTMLTrackElement_h + +#if ENABLE(VIDEO_TRACK) + +#include "HTMLElement.h" + +namespace WebCore { + +class HTMLTrackElement : public HTMLElement { +public: + static PassRefPtr<HTMLTrackElement> create(const QualifiedName&, Document*); + + KURL src() const; + String kind() const; + String srclang() const; + String label() const; + + bool isDefault() const; + void setKind(const String&); + void setSrc(const String&); + void setSrclang(const String&); + void setLabel(const String&); + void setIsDefault(bool); + +private: + HTMLTrackElement(const QualifiedName&, Document*); + + virtual void insertedIntoTree(bool); + virtual void willRemove(); + virtual bool isURLAttribute(Attribute*) const; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/html/HTMLTrackElement.idl b/Source/WebCore/html/HTMLTrackElement.idl new file mode 100644 index 0000000..309f0f0 --- /dev/null +++ b/Source/WebCore/html/HTMLTrackElement.idl @@ -0,0 +1,36 @@ +/* + * 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: + * 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. + */ + +module html { +interface [Conditional=VIDEO_TRACK] HTMLTrackElement : HTMLElement { + attribute [Reflect, URL] DOMString src; + attribute DOMString kind; + attribute DOMString srclang; + attribute DOMString label; + attribute [Reflect=default] boolean isDefault; + + // readonly attribute TextTrack track; +}; +} diff --git a/Source/WebCore/html/HTMLVideoElement.cpp b/Source/WebCore/html/HTMLVideoElement.cpp index 4ddcdfe..5b7f42d 100644 --- a/Source/WebCore/html/HTMLVideoElement.cpp +++ b/Source/WebCore/html/HTMLVideoElement.cpp @@ -129,6 +129,11 @@ bool HTMLVideoElement::supportsFullscreen() const return false; // Check with the platform client. +#if ENABLE(FULLSCREEN_API) + if (page->chrome()->client()->supportsFullScreenForElement(this, false)) + return true; +#endif + return page->chrome()->client()->supportsFullscreenForNode(this); } @@ -183,7 +188,7 @@ void HTMLVideoElement::setDisplayMode(DisplayMode mode) if (oldMode != Video && player()) player()->prepareForRendering(); if (!hasAvailableVideoFrame()) - mode = Poster; + mode = PosterWaitingForVideo; } } else if (oldMode != Video && player()) player()->prepareForRendering(); diff --git a/Source/WebCore/html/HTMLVideoElement.h b/Source/WebCore/html/HTMLVideoElement.h index 714fcaa..57b70ea 100644 --- a/Source/WebCore/html/HTMLVideoElement.h +++ b/Source/WebCore/html/HTMLVideoElement.h @@ -64,7 +64,7 @@ public: // Used by canvas to gain raw pixel access void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); - bool shouldDisplayPosterImage() const { return displayMode() == Poster; } + bool shouldDisplayPosterImage() const { return displayMode() == Poster || displayMode() == PosterWaitingForVideo; } private: HTMLVideoElement(const QualifiedName&, Document*); diff --git a/Source/WebCore/html/InputType.cpp b/Source/WebCore/html/InputType.cpp index d944909..9756313 100644 --- a/Source/WebCore/html/InputType.cpp +++ b/Source/WebCore/html/InputType.cpp @@ -55,6 +55,7 @@ #include "RenderObject.h" #include "ResetInputType.h" #include "SearchInputType.h" +#include "ShadowRoot.h" #include "SubmitInputType.h" #include "TelephoneInputType.h" #include "TextInputType.h" @@ -365,7 +366,7 @@ void InputType::createShadowSubtree() void InputType::destroyShadowSubtree() { - element()->setShadowRoot(0); + element()->removeShadowRoot(); } double InputType::parseToDouble(const String&, double defaultValue) const diff --git a/Source/WebCore/html/RangeInputType.cpp b/Source/WebCore/html/RangeInputType.cpp index cbec740..22e7f8e 100644 --- a/Source/WebCore/html/RangeInputType.cpp +++ b/Source/WebCore/html/RangeInputType.cpp @@ -39,6 +39,7 @@ #include "MouseEvent.h" #include "PlatformMouseEvent.h" #include "RenderSlider.h" +#include "ShadowRoot.h" #include "SliderThumbElement.h" #include "StepRange.h" #include <limits> @@ -152,7 +153,7 @@ void RangeInputType::handleMouseDownEvent(MouseEvent* event) if (event->button() != LeftButton || event->target() != element()) return; - if (SliderThumbElement* thumb = toSliderThumbElement(element()->shadowRoot())) + if (SliderThumbElement* thumb = shadowSliderThumb()) thumb->dragFrom(event->absoluteLocation()); } @@ -216,7 +217,8 @@ void RangeInputType::handleTouchStartEvent(TouchEvent* touchEvent) void RangeInputType::createShadowSubtree() { - element()->setShadowRoot(SliderThumbElement::create(element()->document())); + ExceptionCode ec = 0; + element()->ensureShadowRoot()->appendChild(SliderThumbElement::create(element()->document()), ec); } RenderObject* RangeInputType::createRenderer(RenderArena* arena, RenderStyle*) const @@ -261,7 +263,7 @@ void RangeInputType::minOrMaxAttributeChanged() void RangeInputType::valueChanged() { - toSliderThumbElement(element()->shadowRoot())->setPositionFromValue(); + shadowSliderThumb()->setPositionFromValue(); } String RangeInputType::fallbackValue() @@ -285,4 +287,10 @@ bool RangeInputType::shouldRespectListAttribute() return true; } +SliderThumbElement* RangeInputType::shadowSliderThumb() const +{ + Node* shadow = element()->shadowRoot(); + return shadow ? toSliderThumbElement(shadow->firstChild()) : 0; +} + } // namespace WebCore diff --git a/Source/WebCore/html/RangeInputType.h b/Source/WebCore/html/RangeInputType.h index ac89d02..b7af291 100644 --- a/Source/WebCore/html/RangeInputType.h +++ b/Source/WebCore/html/RangeInputType.h @@ -35,6 +35,8 @@ namespace WebCore { +class SliderThumbElement; + class RangeInputType : public InputType { public: static PassOwnPtr<InputType> create(HTMLInputElement*); @@ -67,9 +69,14 @@ private: virtual String fallbackValue(); virtual String sanitizeValue(const String& proposedValue); virtual bool shouldRespectListAttribute(); +<<<<<<< HEAD #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS) virtual void handleTouchStartEvent(TouchEvent*); #endif +======= + + SliderThumbElement* shadowSliderThumb() const; +>>>>>>> WebKit.org at r84325 }; } // namespace WebCore diff --git a/Source/WebCore/html/ValidationMessage.cpp b/Source/WebCore/html/ValidationMessage.cpp index 59a1467..48912d7 100644 --- a/Source/WebCore/html/ValidationMessage.cpp +++ b/Source/WebCore/html/ValidationMessage.cpp @@ -40,6 +40,7 @@ #include "Page.h" #include "RenderObject.h" #include "Settings.h" +#include "ShadowRoot.h" #include "Text.h" #include <wtf/PassOwnPtr.h> @@ -129,12 +130,7 @@ void ValidationMessage::buildBubbleTree(Timer<ValidationMessage>*) // contains non-absolute or non-fixed renderers as children. m_bubble->getInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueAbsolute); ExceptionCode ec = 0; - // FIXME: We need a way to host multiple shadow roots in a single node, or - // to inherit an existing shadow tree. - if (host->shadowRoot()) - host->shadowRoot()->appendChild(m_bubble.get(), ec); - else - host->setShadowRoot(m_bubble); + host->ensureShadowRoot()->appendChild(m_bubble.get(), ec); RefPtr<HTMLElement> clipper = ElementWithPseudoId::create(doc, "-webkit-validation-bubble-arrow-clipper"); clipper->appendChild(ElementWithPseudoId::create(doc, "-webkit-validation-bubble-arrow"), ec); @@ -161,12 +157,8 @@ void ValidationMessage::deleteBubbleTree(Timer<ValidationMessage>*) if (m_bubble) { m_bubbleMessage = 0; HTMLElement* host = toHTMLElement(m_element); - if (m_bubble->isShadowRoot()) - host->setShadowRoot(0); - else { - ExceptionCode ec; - host->shadowRoot()->removeChild(m_bubble.get(), ec); - } + ExceptionCode ec; + host->shadowRoot()->removeChild(m_bubble.get(), ec); m_bubble = 0; } m_message = String(); diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp index f5ff078..ab6427e 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -133,7 +133,11 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bo m_context3D = p->sharedGraphicsContext3D(); if (m_context3D) { m_drawingBuffer = m_context3D->graphicsContext3D()->createDrawingBuffer(IntSize(canvas->width(), canvas->height())); - c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas->width(), canvas->height())); + if (!m_drawingBuffer) { + c->setSharedGraphicsContext3D(0, 0, IntSize()); + m_context3D.clear(); + } else + c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas->width(), canvas->height())); } } #endif @@ -146,7 +150,8 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() bool CanvasRenderingContext2D::isAccelerated() const { #if USE(IOSURFACE_CANVAS_BACKING_STORE) - return canvas()->document()->page()->settings()->canvasUsesAcceleratedDrawing(); + ImageBuffer* buffer = canvas()->buffer(); + return buffer ? buffer->isAccelerated() : false; #elif ENABLE(ACCELERATED_2D_CANVAS) return m_context3D; #else @@ -172,13 +177,18 @@ void CanvasRenderingContext2D::reset() #if ENABLE(ACCELERATED_2D_CANVAS) if (GraphicsContext* c = drawingContext()) { if (m_context3D && m_drawingBuffer) { - m_drawingBuffer->reset(IntSize(canvas()->width(), canvas()->height())); - c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas()->width(), canvas()->height())); + if (m_drawingBuffer->reset(IntSize(canvas()->width(), canvas()->height()))) { + c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas()->width(), canvas()->height())); #if USE(ACCELERATED_COMPOSITING) - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) - renderBox->layer()->contentChanged(RenderLayer::CanvasChanged); + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) + renderBox->layer()->contentChanged(RenderLayer::CanvasChanged); #endif + } else { + c->setSharedGraphicsContext3D(0, 0, IntSize()); + m_drawingBuffer.clear(); + m_context3D.clear(); + } } } #endif @@ -203,6 +213,83 @@ CanvasRenderingContext2D::State::State() { } +CanvasRenderingContext2D::State::State(const State& other) + : FontSelectorClient() +{ + m_unparsedStrokeColor = other.m_unparsedStrokeColor; + m_unparsedFillColor = other.m_unparsedFillColor; + m_strokeStyle = other.m_strokeStyle; + m_fillStyle = other.m_fillStyle; + m_lineWidth = other.m_lineWidth; + m_lineCap = other.m_lineCap; + m_lineJoin = other.m_lineJoin; + m_miterLimit = other.m_miterLimit; + m_shadowOffset = other.m_shadowOffset; + m_shadowBlur = other.m_shadowBlur; + m_shadowColor = other.m_shadowColor; + m_globalAlpha = other.m_globalAlpha; + m_globalComposite = other.m_globalComposite; + m_transform = other.m_transform; + m_invertibleCTM = other.m_invertibleCTM; + m_textAlign = other.m_textAlign; + m_textBaseline = other.m_textBaseline; + m_unparsedFont = other.m_unparsedFont; + m_font = other.m_font; + m_realizedFont = other.m_realizedFont; + + if (m_realizedFont) + m_font.fontSelector()->registerForInvalidationCallbacks(this); +} + +CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(const State& other) +{ + if (this == &other) + return *this; + + if (m_realizedFont) + m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + + m_unparsedStrokeColor = other.m_unparsedStrokeColor; + m_unparsedFillColor = other.m_unparsedFillColor; + m_strokeStyle = other.m_strokeStyle; + m_fillStyle = other.m_fillStyle; + m_lineWidth = other.m_lineWidth; + m_lineCap = other.m_lineCap; + m_lineJoin = other.m_lineJoin; + m_miterLimit = other.m_miterLimit; + m_shadowOffset = other.m_shadowOffset; + m_shadowBlur = other.m_shadowBlur; + m_shadowColor = other.m_shadowColor; + m_globalAlpha = other.m_globalAlpha; + m_globalComposite = other.m_globalComposite; + m_transform = other.m_transform; + m_invertibleCTM = other.m_invertibleCTM; + m_textAlign = other.m_textAlign; + m_textBaseline = other.m_textBaseline; + m_unparsedFont = other.m_unparsedFont; + m_font = other.m_font; + m_realizedFont = other.m_realizedFont; + + if (m_realizedFont) + m_font.fontSelector()->registerForInvalidationCallbacks(this); + + return *this; +} + +CanvasRenderingContext2D::State::~State() +{ + if (m_realizedFont) + m_font.fontSelector()->unregisterForInvalidationCallbacks(this); +} + +void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector) +{ + ASSERT_ARG(fontSelector, fontSelector == m_font.fontSelector()); + ASSERT(m_realizedFont); + + m_font.update(fontSelector); +} + void CanvasRenderingContext2D::save() { ASSERT(m_stateStack.size() >= 1); @@ -959,7 +1046,7 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h didDraw(boundingRect); } -#if PLATFORM(CG) +#if USE(CG) static inline CGSize adjustedShadowSize(CGFloat width, CGFloat height) { // Work around <rdar://problem/5539388> by ensuring that shadow offsets will get truncated @@ -1063,7 +1150,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, GraphicsContext* dc = drawingContext(); if (!dc) return; -#if PLATFORM(CG) +#if USE(CG) const CGFloat components[5] = { c, m, y, k, a }; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceCMYK(); CGColorRef shadowColor = CGColorCreate(colorSpace, components); @@ -1150,8 +1237,12 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, - ExceptionCode& ec) +void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) +{ + drawImage(image, srcRect, dstRect, state().m_globalComposite, ec); +} + +void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, ExceptionCode& ec) { if (!image) { ec = TYPE_MISMATCH_ERR; @@ -1193,7 +1284,7 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec FloatRect sourceRect = c->roundToDevicePixels(normalizedSrcRect); FloatRect destRect = c->roundToDevicePixels(normalizedDstRect); - c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, destRect, sourceRect, state().m_globalComposite); + c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, destRect, sourceRect, op); didDraw(destRect); } @@ -1352,34 +1443,17 @@ void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec } #endif -// FIXME: Why isn't this just another overload of drawImage? Why have a different name? void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, const String& compositeOperation) { - if (!image) - return; - - CachedImage* cachedImage = image->cachedImage(); - if (!cachedImage) - return; - - checkOrigin(image); - - GraphicsContext* c = drawingContext(); - if (!c) - return; - if (!state().m_invertibleCTM) - return; - CompositeOperator op; if (!parseCompositeOperator(compositeOperation, op)) op = CompositeSourceOver; - FloatRect destRect = FloatRect(dx, dy, dw, dh); - c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, destRect, FloatRect(sx, sy, sw, sh), op); - didDraw(destRect); + ExceptionCode ec; + drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, ec); } void CanvasRenderingContext2D::setAlpha(float alpha) @@ -1680,15 +1754,7 @@ void CanvasRenderingContext2D::setFont(const String& newFont) state().m_font = newStyle->font(); state().m_font.update(styleSelector->fontSelector()); state().m_realizedFont = true; -} - -void CanvasRenderingContext2D::updateFont() -{ - if (!state().m_realizedFont) - return; - - const Font& font = state().m_font; - font.update(font.fontSelector()); + styleSelector->fontSelector()->registerForInvalidationCallbacks(&state()); } String CanvasRenderingContext2D::textAlign() const @@ -1825,7 +1891,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo if (!fill) textRect.inflate(c->strokeThickness() / 2); -#if PLATFORM(CG) +#if USE(CG) CanvasStyle* drawStyle = fill ? state().m_fillStyle.get() : state().m_strokeStyle.get(); if (drawStyle->canvasGradient() || drawStyle->canvasPattern()) { // FIXME: The rect is not big enough for miters on stroked text. diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h index 206744e..fbaec9e 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h @@ -37,7 +37,7 @@ #include <wtf/Vector.h> -#if PLATFORM(CG) +#if USE(CG) #include <ApplicationServices/ApplicationServices.h> #endif @@ -175,6 +175,7 @@ public: void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&); void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); + void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, ExceptionCode&); #if ENABLE(VIDEO) void drawImage(HTMLVideoElement*, float x, float y, ExceptionCode&); void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionCode&); @@ -204,7 +205,6 @@ public: String font() const; void setFont(const String&); - void updateFont(); String textAlign() const; void setTextAlign(const String&); @@ -228,8 +228,14 @@ public: #endif private: - struct State { + struct State : FontSelectorClient { State(); + virtual ~State(); + + State(const State&); + State& operator=(const State&); + + virtual void fontsNeedUpdate(FontSelector*); String m_unparsedStrokeColor; String m_unparsedFillColor; diff --git a/Source/WebCore/html/canvas/CanvasStyle.cpp b/Source/WebCore/html/canvas/CanvasStyle.cpp index ee8567c..3aee6e8 100644 --- a/Source/WebCore/html/canvas/CanvasStyle.cpp +++ b/Source/WebCore/html/canvas/CanvasStyle.cpp @@ -38,7 +38,7 @@ #include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> -#if PLATFORM(CG) +#if USE(CG) #include <CoreGraphics/CGContext.h> #endif @@ -238,7 +238,7 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context) case CMYKA: { // FIXME: Do this through platform-independent GraphicsContext API. // We'll need a fancier Color abstraction to support CMYKA correctly -#if PLATFORM(CG) +#if USE(CG) CGContextSetCMYKStrokeColor(context->platformContext(), m_cmyka.c, m_cmyka.m, m_cmyka.y, m_cmyka.k, m_cmyka.a); #elif PLATFORM(QT) QPen currentPen = context->platformContext()->pen(); @@ -275,7 +275,7 @@ void CanvasStyle::applyFillColor(GraphicsContext* context) case CMYKA: { // FIXME: Do this through platform-independent GraphicsContext API. // We'll need a fancier Color abstraction to support CMYKA correctly -#if PLATFORM(CG) +#if USE(CG) CGContextSetCMYKFillColor(context->platformContext(), m_cmyka.c, m_cmyka.m, m_cmyka.y, m_cmyka.k, m_cmyka.a); #elif PLATFORM(QT) QBrush currentBrush = context->platformContext()->brush(); diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp index aa40a64..933d37f 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -458,14 +458,14 @@ void WebGLRenderingContext::setupFlags() ASSERT(m_context); m_isGLES2Compliant = m_context->isGLES2Compliant(); - m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->supports("GL_CHROMIUM_strict_attribs"); - m_isResourceSafe = m_context->getExtensions()->supports("GL_CHROMIUM_resource_safe"); + m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs"); + m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe"); if (m_isGLES2Compliant) { - m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_OES_texture_npot"); - m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_OES_packed_depth_stencil"); + m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot"); + m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil"); } else { - m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_ARB_texture_non_power_of_two"); - m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_EXT_packed_depth_stencil"); + m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two"); + m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil"); } } @@ -502,12 +502,12 @@ bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask) if (isContextLost()) return false; - RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); - if (!m_context->layerComposited() || m_layerCleared || m_attributes.preserveDrawingBuffer || m_framebufferBinding) return false; + RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); + // Determine if it's possible to combine the clear the user asked for and this clear. bool combinedClear = mask && !m_scissorEnabled; @@ -3140,10 +3140,8 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum ec = 0; if (isContextLost()) return; - if (!image || !image->cachedImage()) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + if (!validateHTMLImageElement(image)) return; - } checkOrigin(image); texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec); @@ -3334,10 +3332,8 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din ec = 0; if (isContextLost()) return; - if (!image || !image->cachedImage()) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + if (!validateHTMLImageElement(image)) return; - } checkOrigin(image); texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec); @@ -4613,6 +4609,20 @@ WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(GC3Denum target return 0; } +bool WebGLRenderingContext::validateHTMLImageElement(HTMLImageElement* image) +{ + if (!image || !image->cachedImage()) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return false; + } + const KURL& url = image->cachedImage()->response().url(); + if (url.isNull() || url.isEmpty() || !url.isValid()) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return false; + } + return true; +} + void WebGLRenderingContext::vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) { if (isContextLost()) diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h index f716efb..23c147d 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.h +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h @@ -590,6 +590,9 @@ public: // Return the current bound buffer to target, or 0 if parameters are invalid. WebGLBuffer* validateBufferDataParameters(GC3Denum target, GC3Denum usage); + // Helper function for tex{Sub}Image2D to make sure image is ready. + bool validateHTMLImageElement(HTMLImageElement*); + // Helper functions for vertexAttribNf{v}. void vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat); void vertexAttribfvImpl(GC3Duint index, Float32Array*, GC3Dsizei expectedSize); diff --git a/Source/WebCore/html/parser/CSSPreloadScanner.cpp b/Source/WebCore/html/parser/CSSPreloadScanner.cpp index 23364f9..3c23b9f 100644 --- a/Source/WebCore/html/parser/CSSPreloadScanner.cpp +++ b/Source/WebCore/html/parser/CSSPreloadScanner.cpp @@ -54,7 +54,7 @@ void CSSPreloadScanner::scan(const HTMLToken& token, bool scanningBody) m_scanningBody = scanningBody; const HTMLToken::DataVector& characters = token.characters(); - for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end(); ++iter) + for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end() && m_state != DoneParsingImportRules; ++iter) tokenize(*iter); } @@ -64,10 +64,14 @@ inline void CSSPreloadScanner::tokenize(UChar c) // Searching for other types of resources is probably low payoff. switch (m_state) { case Initial: + if (isHTMLSpace(c)) + break; if (c == '@') m_state = RuleStart; else if (c == '/') m_state = MaybeComment; + else + m_state = DoneParsingImportRules; break; case MaybeComment: if (c == '*') @@ -80,10 +84,10 @@ inline void CSSPreloadScanner::tokenize(UChar c) m_state = MaybeCommentEnd; break; case MaybeCommentEnd: + if (c == '*') + break; if (c == '/') m_state = Initial; - else if (c == '*') - ; else m_state = Comment; break; @@ -106,9 +110,11 @@ inline void CSSPreloadScanner::tokenize(UChar c) break; case AfterRule: if (isHTMLSpace(c)) - ; - else if (c == ';') + break; + if (c == ';') m_state = Initial; + else if (c == '{') + m_state = DoneParsingImportRules; else { m_state = RuleValue; m_ruleValue.append(c); @@ -117,23 +123,26 @@ inline void CSSPreloadScanner::tokenize(UChar c) case RuleValue: if (isHTMLSpace(c)) m_state = AfterRuleValue; - else if (c == ';') { + else if (c == ';') emitRule(); - m_state = Initial; - } else + else m_ruleValue.append(c); break; case AfterRuleValue: if (isHTMLSpace(c)) - ; - else if (c == ';') { + break; + if (c == ';') emitRule(); - m_state = Initial; - } else { + else if (c == '{') + m_state = DoneParsingImportRules; + else { // FIXME: media rules m_state = Initial; } break; + case DoneParsingImportRules: + ASSERT_NOT_REACHED(); + break; } } @@ -187,7 +196,11 @@ void CSSPreloadScanner::emitRule() String value = parseCSSStringOrURL(m_ruleValue.data(), m_ruleValue.size()); if (!value.isEmpty()) m_document->cachedResourceLoader()->preload(CachedResource::CSSStyleSheet, value, String(), m_scanningBody); - } + m_state = Initial; + } else if (equalIgnoringCase("charset", m_rule.data(), m_rule.size())) + m_state = Initial; + else + m_state = DoneParsingImportRules; m_rule.clear(); m_ruleValue.clear(); } diff --git a/Source/WebCore/html/parser/CSSPreloadScanner.h b/Source/WebCore/html/parser/CSSPreloadScanner.h index fae95a1..e45fa2d 100644 --- a/Source/WebCore/html/parser/CSSPreloadScanner.h +++ b/Source/WebCore/html/parser/CSSPreloadScanner.h @@ -53,7 +53,8 @@ private: Rule, AfterRule, RuleValue, - AfterRuleValue + AfterRuleValue, + DoneParsingImportRules, }; inline void tokenize(UChar c); diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp index 88db3c2..7519699 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp +++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp @@ -40,7 +40,6 @@ #include "InspectorInstrumentation.h" #include "NestingLevelIncrementer.h" #include "Settings.h" -#include <wtf/CurrentTime.h> #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" @@ -331,6 +330,14 @@ void HTMLDocumentParser::insert(const SegmentedString& source) excludedLineNumberSource.setExcludeLineNumbers(); m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); pumpTokenizerIfPossible(ForceSynchronous); + + if (isWaitingForScripts()) { + // Check the document.write() output with a separate preload scanner as + // the main scanner can't deal with insertions. + HTMLPreloadScanner preloadScanner(document()); + preloadScanner.appendToEnd(source); + preloadScanner.scan(); + } endIfDelayed(); } @@ -344,9 +351,19 @@ void HTMLDocumentParser::append(const SegmentedString& source) // but we need to ensure it isn't deleted yet. RefPtr<HTMLDocumentParser> protect(this); + if (m_preloadScanner) { + if (m_input.current().isEmpty() && !isWaitingForScripts()) { + // We have parsed until the end of the current input and so are now moving ahead of the preload scanner. + // Clear the scanner so we know to scan starting from the current input point if we block again. + m_preloadScanner.clear(); + } else { + m_preloadScanner->appendToEnd(source); + if (isWaitingForScripts()) + m_preloadScanner->scan(); + } + } + m_input.appendToEnd(source); - if (m_preloadScanner) - m_preloadScanner->appendToEnd(source); if (inPumpSession()) { // We've gotten data off the network in a nested write. @@ -473,7 +490,6 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution() ASSERT(!inScriptExecution()); ASSERT(!m_treeBuilder->isPaused()); - m_preloadScanner.clear(); pumpTokenizerIfPossible(AllowYield); endIfDelayed(); } @@ -491,6 +507,13 @@ void HTMLDocumentParser::stopWatchingForLoad(CachedResource* cachedScript) { cachedScript->removeClient(this); } + +void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() +{ + ASSERT(m_preloadScanner); + m_preloadScanner->appendToEnd(m_input.current()); + m_preloadScanner->scan(); +} void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource) { diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.h b/Source/WebCore/html/parser/HTMLDocumentParser.h index a016cf3..d482a3d 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.h +++ b/Source/WebCore/html/parser/HTMLDocumentParser.h @@ -109,6 +109,8 @@ private: virtual void watchForLoad(CachedResource*); virtual void stopWatchingForLoad(CachedResource*); virtual HTMLInputStream& inputStream() { return m_input; } + virtual bool hasPreloadScanner() const { return m_preloadScanner.get(); } + virtual void appendCurrentInputStreamToPreloadScannerAndScan(); // CachedResourceClient virtual void notifyFinished(CachedResource*); diff --git a/Source/WebCore/html/parser/HTMLParserScheduler.h b/Source/WebCore/html/parser/HTMLParserScheduler.h index 730b52b..b0e2e85 100644 --- a/Source/WebCore/html/parser/HTMLParserScheduler.h +++ b/Source/WebCore/html/parser/HTMLParserScheduler.h @@ -26,6 +26,8 @@ #ifndef HTMLParserScheduler_h #define HTMLParserScheduler_h +#include <limits.h> + #include "NestingLevelIncrementer.h" #include "Timer.h" #include <wtf/CurrentTime.h> @@ -39,8 +41,11 @@ class PumpSession : public NestingLevelIncrementer { public: PumpSession(unsigned& nestingLevel) : NestingLevelIncrementer(nestingLevel) - , processedTokens(0) - , startTime(currentTime()) + // Setting processedTokens to INT_MAX causes us to check for yields + // after any token during any parse where yielding is allowed. + // At that time we'll initialize startTime. + , processedTokens(INT_MAX) + , startTime(0) , needsYield(false) { } @@ -63,6 +68,11 @@ public: void checkForYieldBeforeToken(PumpSession& session) { if (session.processedTokens > m_parserChunkSize) { + // currentTime() can be expensive. By delaying, we avoided calling + // currentTime() when constructing non-yielding PumpSessions. + if (!session.startTime) + session.startTime = currentTime(); + session.processedTokens = 0; double elapsedTime = currentTime() - session.startTime; if (elapsedTime > m_parserTimeLimit) diff --git a/Source/WebCore/html/parser/HTMLScriptRunner.cpp b/Source/WebCore/html/parser/HTMLScriptRunner.cpp index 99fff5e..7312334 100644 --- a/Source/WebCore/html/parser/HTMLScriptRunner.cpp +++ b/Source/WebCore/html/parser/HTMLScriptRunner.cpp @@ -169,12 +169,17 @@ bool HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosi ASSERT(scriptElement); // FIXME: If scripting is disabled, always just return true; + bool hadPreloadScanner = m_host->hasPreloadScanner(); + // Try to execute the script given to us. runScript(scriptElement.get(), scriptStartPosition); if (haveParsingBlockingScript()) { if (m_scriptNestingLevel) return false; // Block the parser. Unwind to the outermost HTMLScriptRunner::execute before continuing parsing. + // If preload scanner got created, it is missing the source after the current insertion point. Append it and scan. + if (!hadPreloadScanner && m_host->hasPreloadScanner()) + m_host->appendCurrentInputStreamToPreloadScannerAndScan(); if (!executeParsingBlockingScripts()) return false; // We still have a parsing blocking script, block the parser. } diff --git a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h index 454bc6f..1f22896 100644 --- a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h +++ b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h @@ -45,6 +45,10 @@ public: virtual void stopWatchingForLoad(CachedResource*) = 0; virtual HTMLInputStream& inputStream() = 0; + + virtual bool hasPreloadScanner() const = 0; + virtual void appendCurrentInputStreamToPreloadScannerAndScan() = 0; + }; } diff --git a/Source/WebCore/html/shadow/DetailsMarkerControl.cpp b/Source/WebCore/html/shadow/DetailsMarkerControl.cpp new file mode 100644 index 0000000..e8c6d6e --- /dev/null +++ b/Source/WebCore/html/shadow/DetailsMarkerControl.cpp @@ -0,0 +1,70 @@ +/* + * 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" +#include "DetailsMarkerControl.h" + +#include "HTMLNames.h" +#include "HTMLSummaryElement.h" +#include "RenderDetailsMarker.h" + +namespace WebCore { + +using namespace HTMLNames; + +DetailsMarkerControl::DetailsMarkerControl(Document* document) + : HTMLDivElement(divTag, document) +{ +} + +RenderObject* DetailsMarkerControl::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderDetailsMarker(this); +} + +bool DetailsMarkerControl::rendererIsNeeded(RenderStyle* style) +{ + return summaryElement()->isMainSummary() && HTMLDivElement::rendererIsNeeded(style); +} + +const AtomicString& DetailsMarkerControl::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-details-marker")); + return pseudId; +} + +HTMLSummaryElement* DetailsMarkerControl::summaryElement() +{ + Node* node = this->shadowAncestorNode(); + ASSERT(!node || toElement(node)->hasTagName(summaryTag)); + return static_cast<HTMLSummaryElement*>(node); +} + +} diff --git a/Source/WebCore/html/shadow/ProgressBarValueElement.h b/Source/WebCore/html/shadow/DetailsMarkerControl.h index 22f4e57..3c5b09d 100644 --- a/Source/WebCore/html/shadow/ProgressBarValueElement.h +++ b/Source/WebCore/html/shadow/DetailsMarkerControl.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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 @@ -29,43 +28,32 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ProgressBarValueElement_h -#define ProgressBarValueElement_h +#ifndef DetailsMarkerControl_h +#define DetailsMarkerControl_h #include "HTMLDivElement.h" -#include "HTMLNames.h" -#include "RenderProgress.h" #include <wtf/Forward.h> namespace WebCore { -class ProgressBarValueElement : public HTMLDivElement { +class HTMLSummaryElement; + +class DetailsMarkerControl : public HTMLDivElement { public: - ProgressBarValueElement(Document* document) - : HTMLDivElement(HTMLNames::divTag, document) - { - } + DetailsMarkerControl(Document*); + static PassRefPtr<DetailsMarkerControl> create(Document*); - virtual const AtomicString& shadowPseudoId() const; +private: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - static PassRefPtr<ProgressBarValueElement> create(Document*); + virtual bool rendererIsNeeded(RenderStyle*); + virtual const AtomicString& shadowPseudoId() const; + HTMLSummaryElement* summaryElement(); }; -inline const AtomicString& ProgressBarValueElement::shadowPseudoId() const -{ - DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-progress-bar-value")); - return pseudId; -} - -inline RenderObject* ProgressBarValueElement::createRenderer(RenderArena* arena, RenderStyle*) -{ - return new (arena) RenderProgressBarValuePart(this); -} - -inline PassRefPtr<ProgressBarValueElement> ProgressBarValueElement::create(Document* document) +inline PassRefPtr<DetailsMarkerControl> DetailsMarkerControl::create(Document* document) { - return adoptRef(new ProgressBarValueElement(document)); + return adoptRef(new DetailsMarkerControl(document)); } } diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp new file mode 100644 index 0000000..68b301e --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlElements.cpp @@ -0,0 +1,980 @@ +/* + * Copyright (C) 2008, 2009, 2010 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. + * 3. Neither the name of Apple Computer, 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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" + +#if ENABLE(VIDEO) + +#include "MediaControlElements.h" + +#include "CSSStyleSelector.h" +#include "EventNames.h" +#include "FloatConversion.h" +#include "Frame.h" +#include "HTMLNames.h" +#include "LocalizedStrings.h" +#include "MediaControls.h" +#include "MouseEvent.h" +#include "Page.h" +#include "RenderFlexibleBox.h" +#include "RenderMedia.h" +#include "RenderSlider.h" +#include "RenderTheme.h" +#include "RenderView.h" +#include "Settings.h" + +namespace WebCore { + +using namespace HTMLNames; + +HTMLMediaElement* toParentMediaElement(RenderObject* o) +{ + Node* node = o->node(); + Node* mediaNode = node ? node->shadowAncestorNode() : 0; + if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag))) + return 0; + + return static_cast<HTMLMediaElement*>(mediaNode); +} + +// FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in. +static const float cSeekRepeatDelay = 0.1f; +static const float cStepTime = 0.07f; +static const float cSeekTime = 0.2f; + +// ---------------------------- + +MediaControlElement::MediaControlElement(HTMLMediaElement* mediaElement) + : HTMLDivElement(divTag, mediaElement->document()) + , m_mediaElement(mediaElement) +{ +} + +static const String& displayString() +{ + DEFINE_STATIC_LOCAL(String, s, ("display")); + return s; +} + +void MediaControlElement::show() +{ + ExceptionCode ec; + // FIXME: Make more efficient <http://webkit.org/b/58157> + style()->removeProperty(displayString(), ec); +} + +void MediaControlElement::hide() +{ + ExceptionCode ec; + // FIXME: Make more efficient <http://webkit.org/b/58157> + DEFINE_STATIC_LOCAL(String, none, ("none")); + style()->setProperty(displayString(), none, ec); +} + +// ---------------------------- + +inline MediaControlPanelElement::MediaControlPanelElement(HTMLMediaElement* mediaElement) + : MediaControlElement(mediaElement) +{ +} + +PassRefPtr<MediaControlPanelElement> MediaControlPanelElement::create(HTMLMediaElement* mediaElement) +{ + return adoptRef(new MediaControlPanelElement(mediaElement)); +} + +MediaControlElementType MediaControlPanelElement::displayType() const +{ + return MediaControlsPanel; +} + +const AtomicString& MediaControlPanelElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-panel")); + return id; +} + +// ---------------------------- + +inline MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(HTMLMediaElement* mediaElement) + : MediaControlElement(mediaElement) +{ +} + +PassRefPtr<MediaControlTimelineContainerElement> MediaControlTimelineContainerElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlTimelineContainerElement> element = adoptRef(new MediaControlTimelineContainerElement(mediaElement)); + element->hide(); + return element.release(); +} + +MediaControlElementType MediaControlTimelineContainerElement::displayType() const +{ + return MediaTimelineContainer; +} + +const AtomicString& MediaControlTimelineContainerElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline-container")); + return id; +} + +// ---------------------------- + +class RenderMediaVolumeSliderContainer : public RenderBlock { +public: + RenderMediaVolumeSliderContainer(Node*); + +private: + virtual void layout(); +}; + +RenderMediaVolumeSliderContainer::RenderMediaVolumeSliderContainer(Node* node) + : RenderBlock(node) +{ +} + +void RenderMediaVolumeSliderContainer::layout() +{ + RenderBlock::layout(); + if (style()->display() == NONE || !previousSibling() || !previousSibling()->isBox()) + return; + + RenderBox* buttonBox = toRenderBox(previousSibling()); + + if (view()) + view()->disableLayoutState(); + + IntPoint offset = theme()->volumeSliderOffsetFromMuteButton(buttonBox, IntSize(width(), height())); + setX(offset.x() + buttonBox->offsetLeft()); + setY(offset.y() + buttonBox->offsetTop()); + + if (view()) + view()->enableLayoutState(); +} + +inline MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(HTMLMediaElement* mediaElement) + : MediaControlElement(mediaElement) +{ +} + +PassRefPtr<MediaControlVolumeSliderContainerElement> MediaControlVolumeSliderContainerElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlVolumeSliderContainerElement> element = adoptRef(new MediaControlVolumeSliderContainerElement(mediaElement)); + element->hide(); + return element.release(); +} + +RenderObject* MediaControlVolumeSliderContainerElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderMediaVolumeSliderContainer(this); +} + +void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event* event) +{ + if (!event->isMouseEvent() || event->type() != eventNames().mouseoutEvent) + return; + + // Poor man's mouseleave event detection. + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); + if (!mouseEvent->relatedTarget() || !mouseEvent->relatedTarget()->toNode()) + return; + + if (this->containsIncludingShadowDOM(mouseEvent->relatedTarget()->toNode())) + return; + + hide(); +} + + +MediaControlElementType MediaControlVolumeSliderContainerElement::displayType() const +{ + return MediaVolumeSliderContainer; +} + +const AtomicString& MediaControlVolumeSliderContainerElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-container")); + return id; +} + +// ---------------------------- + +inline MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(HTMLMediaElement* mediaElement) + : MediaControlElement(mediaElement) + , m_stateBeingDisplayed(Nothing) +{ +} + +PassRefPtr<MediaControlStatusDisplayElement> MediaControlStatusDisplayElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlStatusDisplayElement> element = adoptRef(new MediaControlStatusDisplayElement(mediaElement)); + element->hide(); + return element.release(); +} + +void MediaControlStatusDisplayElement::update() +{ + // Get the new state that we'll have to display. + StateBeingDisplayed newStateToDisplay = Nothing; + + if (mediaElement()->readyState() != HTMLMediaElement::HAVE_ENOUGH_DATA && !mediaElement()->currentSrc().isEmpty()) + newStateToDisplay = Loading; + else if (mediaElement()->movieLoadType() == MediaPlayer::LiveStream) + newStateToDisplay = LiveBroadcast; + + if (newStateToDisplay == m_stateBeingDisplayed) + return; + + ExceptionCode e; + + if (m_stateBeingDisplayed == Nothing) + show(); + else if (newStateToDisplay == Nothing) + hide(); + + m_stateBeingDisplayed = newStateToDisplay; + + switch (m_stateBeingDisplayed) { + case Nothing: + setInnerText("", e); + break; + case Loading: + setInnerText(mediaElementLoadingStateText(), e); + break; + case LiveBroadcast: + setInnerText(mediaElementLiveBroadcastStateText(), e); + break; + } +} + +MediaControlElementType MediaControlStatusDisplayElement::displayType() const +{ + return MediaStatusDisplay; +} + +const AtomicString& MediaControlStatusDisplayElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-status-display")); + return id; +} + +// ---------------------------- + +MediaControlInputElement::MediaControlInputElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType) + : HTMLInputElement(inputTag, mediaElement->document(), 0, false) + , m_mediaElement(mediaElement) + , m_displayType(displayType) +{ +} + +void MediaControlInputElement::show() +{ + ExceptionCode ec; + style()->removeProperty(displayString(), ec); +} + +void MediaControlInputElement::hide() +{ + ExceptionCode ec; + DEFINE_STATIC_LOCAL(String, none, ("none")); + style()->setProperty(displayString(), none, ec); +} + + +void MediaControlInputElement::setDisplayType(MediaControlElementType displayType) +{ + if (displayType == m_displayType) + return; + + m_displayType = displayType; + if (RenderObject* object = renderer()) + object->repaint(); +} + +// ---------------------------- + +inline MediaControlMuteButtonElement::MediaControlMuteButtonElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType) + : MediaControlInputElement(mediaElement, displayType) +{ +} + +void MediaControlMuteButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + mediaElement()->setMuted(!mediaElement()->muted()); + event->setDefaultHandled(); + } + + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlMuteButtonElement::changedMute() +{ + updateDisplayType(); +} + +void MediaControlMuteButtonElement::updateDisplayType() +{ + setDisplayType(mediaElement()->muted() ? MediaUnMuteButton : MediaMuteButton); +} + +// ---------------------------- + +inline MediaControlPanelMuteButtonElement::MediaControlPanelMuteButtonElement(HTMLMediaElement* mediaElement, MediaControls* controls) + : MediaControlMuteButtonElement(mediaElement, MediaMuteButton) + , m_controls(controls) +{ +} + +PassRefPtr<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElement::create(HTMLMediaElement* mediaElement, MediaControls* controls) +{ + ASSERT(controls); + + RefPtr<MediaControlPanelMuteButtonElement> button = adoptRef(new MediaControlPanelMuteButtonElement(mediaElement, controls)); + button->setType("button"); + return button.release(); +} + +void MediaControlPanelMuteButtonElement::defaultEventHandler(Event* event) +{ + 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")); + return id; +} + +// ---------------------------- + +inline MediaControlVolumeSliderMuteButtonElement::MediaControlVolumeSliderMuteButtonElement(HTMLMediaElement* mediaElement) + : MediaControlMuteButtonElement(mediaElement, MediaMuteButton) +{ +} + +PassRefPtr<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(new MediaControlVolumeSliderMuteButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +const AtomicString& MediaControlVolumeSliderMuteButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-mute-button")); + return id; +} + +// ---------------------------- + +inline MediaControlPlayButtonElement::MediaControlPlayButtonElement(HTMLMediaElement* mediaElement) + : MediaControlInputElement(mediaElement, MediaPlayButton) +{ +} + +PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +void MediaControlPlayButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + mediaElement()->togglePlayState(); + updateDisplayType(); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlPlayButtonElement::updateDisplayType() +{ + setDisplayType(mediaElement()->canPlay() ? MediaPlayButton : MediaPauseButton); +} + +const AtomicString& MediaControlPlayButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button")); + return id; +} + +// ---------------------------- + +inline MediaControlSeekButtonElement::MediaControlSeekButtonElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType) + : MediaControlInputElement(mediaElement, displayType) + , m_seeking(false) + , m_capturing(false) + , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired) +{ +} + +void MediaControlSeekButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().mousedownEvent) { + if (Frame* frame = document()->frame()) { + m_capturing = true; + frame->eventHandler()->setCapturingMouseEventsNode(this); + } + mediaElement()->pause(event->fromUserGesture()); + m_seekTimer.startRepeating(cSeekRepeatDelay); + event->setDefaultHandled(); + } else if (event->type() == eventNames().mouseupEvent) { + if (m_capturing) + if (Frame* frame = document()->frame()) { + m_capturing = false; + frame->eventHandler()->setCapturingMouseEventsNode(0); + } + ExceptionCode ec; + if (m_seeking || m_seekTimer.isActive()) { + if (!m_seeking) { + float stepTime = isForwardButton() ? cStepTime : -cStepTime; + mediaElement()->setCurrentTime(mediaElement()->currentTime() + stepTime, ec); + } + m_seekTimer.stop(); + m_seeking = false; + event->setDefaultHandled(); + } + } + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*) +{ + ExceptionCode ec; + m_seeking = true; + float seekTime = isForwardButton() ? cSeekTime : -cSeekTime; + mediaElement()->setCurrentTime(mediaElement()->currentTime() + seekTime, ec); +} + +void MediaControlSeekButtonElement::detach() +{ + if (m_capturing) { + if (Frame* frame = document()->frame()) + frame->eventHandler()->setCapturingMouseEventsNode(0); + } + MediaControlInputElement::detach(); +} + +// ---------------------------- + +inline MediaControlSeekForwardButtonElement::MediaControlSeekForwardButtonElement(HTMLMediaElement* mediaElement) + : MediaControlSeekButtonElement(mediaElement, MediaSeekForwardButton) +{ +} + +PassRefPtr<MediaControlSeekForwardButtonElement> MediaControlSeekForwardButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlSeekForwardButtonElement> button = adoptRef(new MediaControlSeekForwardButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +const AtomicString& MediaControlSeekForwardButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-forward-button")); + return id; +} + +// ---------------------------- + +inline MediaControlSeekBackButtonElement::MediaControlSeekBackButtonElement(HTMLMediaElement* mediaElement) + : MediaControlSeekButtonElement(mediaElement, MediaSeekBackButton) +{ +} + +PassRefPtr<MediaControlSeekBackButtonElement> MediaControlSeekBackButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlSeekBackButtonElement> button = adoptRef(new MediaControlSeekBackButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +const AtomicString& MediaControlSeekBackButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-back-button")); + return id; +} + +// ---------------------------- + +inline MediaControlRewindButtonElement::MediaControlRewindButtonElement(HTMLMediaElement* element) + : MediaControlInputElement(element, MediaRewindButton) +{ +} + +PassRefPtr<MediaControlRewindButtonElement> MediaControlRewindButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlRewindButtonElement> button = adoptRef(new MediaControlRewindButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +void MediaControlRewindButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + mediaElement()->rewind(30); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +const AtomicString& MediaControlRewindButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-rewind-button")); + return id; +} + +// ---------------------------- + +inline MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(HTMLMediaElement* mediaElement) + : MediaControlInputElement(mediaElement, MediaReturnToRealtimeButton) +{ +} + +PassRefPtr<MediaControlReturnToRealtimeButtonElement> MediaControlReturnToRealtimeButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlReturnToRealtimeButtonElement> button = adoptRef(new MediaControlReturnToRealtimeButtonElement(mediaElement)); + button->setType("button"); + button->hide(); + return button.release(); +} + +void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + mediaElement()->returnToRealtime(); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +const AtomicString& MediaControlReturnToRealtimeButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-return-to-realtime-button")); + return id; +} + +// ---------------------------- + +inline MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(HTMLMediaElement* mediaElement) + : MediaControlInputElement(mediaElement, MediaShowClosedCaptionsButton) +{ +} + +PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(mediaElement)); + button->setType("button"); + button->hide(); + return button.release(); +} + +void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + mediaElement()->setClosedCaptionsVisible(!mediaElement()->closedCaptionsVisible()); + setChecked(mediaElement()->closedCaptionsVisible()); + updateDisplayType(); + event->setDefaultHandled(); + } + + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() +{ + setDisplayType(mediaElement()->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton); +} + +const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-toggle-closed-captions-button")); + return id; +} + +// ---------------------------- + +MediaControlTimelineElement::MediaControlTimelineElement(HTMLMediaElement* mediaElement, MediaControls* controls) + : MediaControlInputElement(mediaElement, MediaSlider) + , m_controls(controls) +{ +} + +PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(HTMLMediaElement* mediaElement, MediaControls* controls) +{ + ASSERT(controls); + + RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(mediaElement, controls)); + timeline->setType("range"); + timeline->setAttribute(precisionAttr, "float"); + return timeline.release(); +} + +void MediaControlTimelineElement::defaultEventHandler(Event* event) +{ + // Left button is 0. Rejects mouse events not from left button. + if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) + return; + + if (!attached()) + return; + + if (event->type() == eventNames().mousedownEvent) + mediaElement()->beginScrubbing(); + + MediaControlInputElement::defaultEventHandler(event); + + if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) + return; + + float time = narrowPrecisionToFloat(value().toDouble()); + if (time != mediaElement()->currentTime()) { + // FIXME: This is fired 3 times on every click. We should not be doing that <http:/webkit.org/b/58160>. + ExceptionCode ec; + mediaElement()->setCurrentTime(time, ec); + } + + RenderSlider* slider = toRenderSlider(renderer()); +<<<<<<< HEAD:Source/WebCore/rendering/MediaControlElements.cpp + if (slider && slider->inDragMode()) { + toRenderMedia(mediaElement()->renderer())->controls()->updateTimeDisplay(); +#if PLATFORM(ANDROID) + toRenderMedia(mediaElement()->renderer())->controls()->updateLastTouch(); +#endif + } +======= + if (slider && slider->inDragMode()) + m_controls->updateTimeDisplay(); +>>>>>>> WebKit.org at r84325:Source/WebCore/html/shadow/MediaControlElements.cpp + + if (event->type() == eventNames().mouseupEvent) + mediaElement()->endScrubbing(); +} + +void MediaControlTimelineElement::setPosition(float currentTime) +{ + setValue(String::number(currentTime)); +} + +void MediaControlTimelineElement::setDuration(float duration) +{ + setAttribute(maxAttr, String::number(isfinite(duration) ? duration : 0)); +} + + +const AtomicString& MediaControlTimelineElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline")); + return id; +} + +// ---------------------------- + +inline MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(HTMLMediaElement* mediaElement) + : MediaControlInputElement(mediaElement, MediaVolumeSlider) +{ +} + +PassRefPtr<MediaControlVolumeSliderElement> MediaControlVolumeSliderElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlVolumeSliderElement> slider = adoptRef(new MediaControlVolumeSliderElement(mediaElement)); + slider->setType("range"); + slider->setAttribute(precisionAttr, "float"); + slider->setAttribute(maxAttr, "1"); + slider->setAttribute(valueAttr, String::number(mediaElement->volume())); + return slider.release(); +} + +void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) +{ + // Left button is 0. Rejects mouse events not from left button. + if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) + return; + + if (!attached()) + return; + + MediaControlInputElement::defaultEventHandler(event); + + if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) + return; + + float volume = narrowPrecisionToFloat(value().toDouble()); + if (volume != mediaElement()->volume()) { + ExceptionCode ec = 0; + mediaElement()->setVolume(volume, ec); + ASSERT(!ec); + } +} + +void MediaControlVolumeSliderElement::setVolume(float volume) +{ + if (value().toFloat() != volume) + setValue(String::number(volume)); +} + +const AtomicString& MediaControlVolumeSliderElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider")); + return id; +} + +// ---------------------------- + +inline MediaControlFullscreenVolumeSliderElement::MediaControlFullscreenVolumeSliderElement(HTMLMediaElement* mediaElement) + : MediaControlVolumeSliderElement(mediaElement) +{ +} + +PassRefPtr<MediaControlFullscreenVolumeSliderElement> MediaControlFullscreenVolumeSliderElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlFullscreenVolumeSliderElement> slider = adoptRef(new MediaControlFullscreenVolumeSliderElement(mediaElement)); + slider->setType("range"); + slider->setAttribute(precisionAttr, "float"); + slider->setAttribute(maxAttr, "1"); + slider->setAttribute(valueAttr, String::number(mediaElement->volume())); + return slider.release(); +} + +const AtomicString& MediaControlFullscreenVolumeSliderElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-slider")); + return id; +} + +// ---------------------------- + +inline MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(HTMLMediaElement* mediaElement, MediaControls* controls) + : MediaControlInputElement(mediaElement, MediaFullscreenButton) + , m_controls(controls) +{ +} + +PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(HTMLMediaElement* mediaElement, MediaControls* controls) +{ + ASSERT(controls); + + RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(mediaElement, controls)); + button->setType("button"); + button->hide(); + return button.release(); +} + +void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) +{ + 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()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == mediaElement()) { + document()->webkitCancelFullScreen(); + m_controls->exitedFullscreen(); + } else { + mediaElement()->webkitRequestFullScreen(0); + m_controls->enteredFullscreen(); + } + } else +#endif + mediaElement()->enterFullscreen(); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button")); + return id; +} + +// ---------------------------- + +inline MediaControlFullscreenVolumeMinButtonElement::MediaControlFullscreenVolumeMinButtonElement(HTMLMediaElement* mediaElement) + : MediaControlInputElement(mediaElement, MediaUnMuteButton) +{ +} + +PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> MediaControlFullscreenVolumeMinButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlFullscreenVolumeMinButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMinButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +void MediaControlFullscreenVolumeMinButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + ExceptionCode code = 0; + mediaElement()->setVolume(0, code); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +const AtomicString& MediaControlFullscreenVolumeMinButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-min-button")); + return id; +} + +// ---------------------------- + +inline MediaControlFullscreenVolumeMaxButtonElement::MediaControlFullscreenVolumeMaxButtonElement(HTMLMediaElement* mediaElement) +: MediaControlInputElement(mediaElement, MediaMuteButton) +{ +} + +PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> MediaControlFullscreenVolumeMaxButtonElement::create(HTMLMediaElement* mediaElement) +{ + RefPtr<MediaControlFullscreenVolumeMaxButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMaxButtonElement(mediaElement)); + button->setType("button"); + return button.release(); +} + +void MediaControlFullscreenVolumeMaxButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + ExceptionCode code = 0; + mediaElement()->setVolume(1, code); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +const AtomicString& MediaControlFullscreenVolumeMaxButtonElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-max-button")); + return id; +} + +// ---------------------------- + +class RenderMediaControlTimeDisplay : public RenderFlexibleBox { +public: + RenderMediaControlTimeDisplay(Node*); + +private: + virtual void layout(); +}; + +RenderMediaControlTimeDisplay::RenderMediaControlTimeDisplay(Node* node) + : RenderFlexibleBox(node) +{ +} + +// We want the timeline slider to be at least 100 pixels wide. +// FIXME: Eliminate hard-coded widths altogether. +static const int minWidthToDisplayTimeDisplays = 45 + 100 + 45; + +void RenderMediaControlTimeDisplay::layout() +{ + RenderFlexibleBox::layout(); + RenderBox* timelineContainerBox = parentBox(); + while (timelineContainerBox && timelineContainerBox->isAnonymous()) + timelineContainerBox = timelineContainerBox->parentBox(); + + if (timelineContainerBox && timelineContainerBox->width() < minWidthToDisplayTimeDisplays) + setWidth(0); +} + +inline MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(HTMLMediaElement* mediaElement) + : MediaControlElement(mediaElement) + , m_currentValue(0) +{ +} + +void MediaControlTimeDisplayElement::setCurrentValue(float time) +{ + m_currentValue = time; +} + +RenderObject* MediaControlTimeDisplayElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderMediaControlTimeDisplay(this); +} + +// ---------------------------- + +PassRefPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(HTMLMediaElement* mediaElement) +{ + return adoptRef(new MediaControlTimeRemainingDisplayElement(mediaElement)); +} + +MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(HTMLMediaElement* mediaElement) + : MediaControlTimeDisplayElement(mediaElement) +{ +} + +MediaControlElementType MediaControlTimeRemainingDisplayElement::displayType() const +{ + return MediaTimeRemainingDisplay; +} + +const AtomicString& MediaControlTimeRemainingDisplayElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-time-remaining-display")); + return id; +} + +// ---------------------------- + +PassRefPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(HTMLMediaElement* mediaElement) +{ + return adoptRef(new MediaControlCurrentTimeDisplayElement(mediaElement)); +} + +MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(HTMLMediaElement* mediaElement) + : MediaControlTimeDisplayElement(mediaElement) +{ +} + +MediaControlElementType MediaControlCurrentTimeDisplayElement::displayType() const +{ + return MediaCurrentTimeDisplay; +} + +const AtomicString& MediaControlCurrentTimeDisplayElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-current-time-display")); + return id; +} + +} // namespace WebCore + +#endif // ENABLE(VIDEO) diff --git a/Source/WebCore/html/shadow/MediaControlElements.h b/Source/WebCore/html/shadow/MediaControlElements.h new file mode 100644 index 0000000..db3158b --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlElements.h @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2008, 2009, 2010 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. + * 3. Neither the name of Apple Computer, 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#ifndef MediaControlElements_h +#define MediaControlElements_h + +#if ENABLE(VIDEO) + +#include "HTMLDivElement.h" +#include "HTMLInputElement.h" +#include "HTMLMediaElement.h" +#include "RenderBlock.h" + +// These are the shadow elements used in RenderMedia + +namespace WebCore { + +class Event; +class Frame; +class MediaControls; + +// Must match WebKitSystemInterface.h +enum MediaControlElementType { + MediaFullscreenButton = 0, + MediaMuteButton, + MediaPlayButton, + MediaSeekBackButton, + MediaSeekForwardButton, + MediaSlider, + MediaSliderThumb, + MediaRewindButton, + MediaReturnToRealtimeButton, + MediaShowClosedCaptionsButton, + MediaHideClosedCaptionsButton, + MediaUnMuteButton, + MediaPauseButton, + MediaTimelineContainer, + MediaCurrentTimeDisplay, + MediaTimeRemainingDisplay, + MediaStatusDisplay, + MediaControlsPanel, + MediaVolumeSliderContainer, + MediaVolumeSlider, + MediaVolumeSliderThumb, + MediaVolumeSliderMuteButton, +}; + +HTMLMediaElement* toParentMediaElement(RenderObject*); + +// ---------------------------- + +class MediaControlElement : public HTMLDivElement { +public: + void hide(); + void show(); + + virtual MediaControlElementType displayType() const = 0; + + HTMLMediaElement* mediaElement() const { return m_mediaElement; } + +protected: + MediaControlElement(HTMLMediaElement*); + +private: + virtual bool isMediaControlElement() const { return true; } + + HTMLMediaElement* m_mediaElement; +}; + +// ---------------------------- + +class MediaControlPanelElement : public MediaControlElement { +public: + static PassRefPtr<MediaControlPanelElement> create(HTMLMediaElement*); + +private: + MediaControlPanelElement(HTMLMediaElement*); + virtual MediaControlElementType displayType() const; + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlTimelineContainerElement : public MediaControlElement { +public: + static PassRefPtr<MediaControlTimelineContainerElement> create(HTMLMediaElement*); + +private: + MediaControlTimelineContainerElement(HTMLMediaElement*); + virtual const AtomicString& shadowPseudoId() const; + + virtual MediaControlElementType displayType() const; +}; + +// ---------------------------- + +class MediaControlVolumeSliderContainerElement : public MediaControlElement { +public: + static PassRefPtr<MediaControlVolumeSliderContainerElement> create(HTMLMediaElement*); + +private: + MediaControlVolumeSliderContainerElement(HTMLMediaElement*); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual void defaultEventHandler(Event*); + virtual MediaControlElementType displayType() const; + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlStatusDisplayElement : public MediaControlElement { +public: + static PassRefPtr<MediaControlStatusDisplayElement> create(HTMLMediaElement*); + + void update(); + +private: + MediaControlStatusDisplayElement(HTMLMediaElement*); + + virtual MediaControlElementType displayType() const; + virtual const AtomicString& shadowPseudoId() const; + + enum StateBeingDisplayed { Nothing, Loading, LiveBroadcast }; + StateBeingDisplayed m_stateBeingDisplayed; +}; + +// ---------------------------- + +class MediaControlInputElement : public HTMLInputElement { +public: + void hide(); + void show(); + + MediaControlElementType displayType() const { return m_displayType; } + + HTMLMediaElement* mediaElement() const { return m_mediaElement; } + +protected: + MediaControlInputElement(HTMLMediaElement*, MediaControlElementType); + + void setDisplayType(MediaControlElementType); + +private: + virtual bool isMediaControlElement() const { return true; } + + virtual void updateDisplayType() { } + + HTMLMediaElement* m_mediaElement; + MediaControlElementType m_displayType; +}; + +// ---------------------------- + +class MediaControlMuteButtonElement : public MediaControlInputElement { +public: + void changedMute(); + +protected: + MediaControlMuteButtonElement(HTMLMediaElement*, MediaControlElementType); + virtual void defaultEventHandler(Event*); + + +private: + virtual void updateDisplayType(); +}; + +// ---------------------------- + +class MediaControlPanelMuteButtonElement : public MediaControlMuteButtonElement { +public: + static PassRefPtr<MediaControlPanelMuteButtonElement> create(HTMLMediaElement*, MediaControls*); + +private: + MediaControlPanelMuteButtonElement(HTMLMediaElement*, MediaControls*); + + virtual void defaultEventHandler(Event*); + virtual const AtomicString& shadowPseudoId() const; + + MediaControls* m_controls; +}; + +// ---------------------------- + +class MediaControlVolumeSliderMuteButtonElement : public MediaControlMuteButtonElement { +public: + static PassRefPtr<MediaControlVolumeSliderMuteButtonElement> create(HTMLMediaElement*); + +private: + MediaControlVolumeSliderMuteButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + + +// ---------------------------- + +class MediaControlPlayButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlPlayButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + virtual void updateDisplayType(); + +private: + MediaControlPlayButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlSeekButtonElement : public MediaControlInputElement { +public: + virtual void defaultEventHandler(Event*); + +protected: + MediaControlSeekButtonElement(HTMLMediaElement*, MediaControlElementType); + +private: + virtual bool isForwardButton() const = 0; + + virtual void detach(); + void seekTimerFired(Timer<MediaControlSeekButtonElement>*); + + bool m_seeking; + bool m_capturing; + Timer<MediaControlSeekButtonElement> m_seekTimer; +}; + +// ---------------------------- + +class MediaControlSeekForwardButtonElement : public MediaControlSeekButtonElement { +public: + static PassRefPtr<MediaControlSeekForwardButtonElement> create(HTMLMediaElement*); + +private: + MediaControlSeekForwardButtonElement(HTMLMediaElement*); + + virtual bool isForwardButton() const { return true; } + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlSeekBackButtonElement : public MediaControlSeekButtonElement { +public: + static PassRefPtr<MediaControlSeekBackButtonElement> create(HTMLMediaElement*); + +private: + MediaControlSeekBackButtonElement(HTMLMediaElement*); + + virtual bool isForwardButton() const { return false; } + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlRewindButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlRewindButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + +private: + MediaControlRewindButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + +private: + MediaControlReturnToRealtimeButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlToggleClosedCaptionsButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + virtual void updateDisplayType(); + +private: + MediaControlToggleClosedCaptionsButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlTimelineElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlTimelineElement> create(HTMLMediaElement*, MediaControls*); + + virtual void defaultEventHandler(Event*); + void setPosition(float); + void setDuration(float); + +private: + MediaControlTimelineElement(HTMLMediaElement*, MediaControls*); + + virtual const AtomicString& shadowPseudoId() const; + + MediaControls* m_controls; +}; + +// ---------------------------- + +class MediaControlVolumeSliderElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlVolumeSliderElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + void setVolume(float); + +protected: + MediaControlVolumeSliderElement(HTMLMediaElement*); + +private: + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlFullscreenButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlFullscreenButtonElement> create(HTMLMediaElement*, MediaControls*); + + virtual void defaultEventHandler(Event*); + +private: + MediaControlFullscreenButtonElement(HTMLMediaElement*, MediaControls*); + + virtual const AtomicString& shadowPseudoId() const; + + MediaControls* m_controls; +}; + +// ---------------------------- + +class MediaControlFullscreenVolumeSliderElement : public MediaControlVolumeSliderElement { +public: + static PassRefPtr<MediaControlFullscreenVolumeSliderElement> create(HTMLMediaElement*); + +private: + MediaControlFullscreenVolumeSliderElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlFullscreenVolumeMinButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + +private: + MediaControlFullscreenVolumeMinButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlFullscreenVolumeMaxButtonElement : public MediaControlInputElement { +public: + static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(HTMLMediaElement*); + + virtual void defaultEventHandler(Event*); + +private: + MediaControlFullscreenVolumeMaxButtonElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlTimeDisplayElement : public MediaControlElement { +public: + void setCurrentValue(float); + float currentValue() const { return m_currentValue; } + +protected: + MediaControlTimeDisplayElement(HTMLMediaElement*); + +private: + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + + float m_currentValue; +}; + +// ---------------------------- + +class MediaControlTimeRemainingDisplayElement : public MediaControlTimeDisplayElement { +public: + static PassRefPtr<MediaControlTimeRemainingDisplayElement> create(HTMLMediaElement*); + +private: + MediaControlTimeRemainingDisplayElement(HTMLMediaElement*); + + virtual MediaControlElementType displayType() const; + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +class MediaControlCurrentTimeDisplayElement : public MediaControlTimeDisplayElement { +public: + static PassRefPtr<MediaControlCurrentTimeDisplayElement> create(HTMLMediaElement*); + +private: + MediaControlCurrentTimeDisplayElement(HTMLMediaElement*); + + virtual MediaControlElementType displayType() const; + virtual const AtomicString& shadowPseudoId() const; +}; + +// ---------------------------- + +} // namespace WebCore + +#endif // ENABLE(VIDEO) + +#endif // MediaControlElements_h diff --git a/Source/WebCore/html/shadow/MediaControlRootElement.cpp b/Source/WebCore/html/shadow/MediaControlRootElement.cpp new file mode 100644 index 0000000..23a25f5 --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlRootElement.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * 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: + * 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 "MediaControlRootElement.h" + +#include "MediaControlElements.h" +#include "Page.h" +#include "RenderTheme.h" + +using namespace std; + +namespace WebCore { + +MediaControlRootElement::MediaControlRootElement(HTMLMediaElement* mediaElement) + : MediaControls(mediaElement) + , m_mediaElement(mediaElement) + , m_rewindButton(0) + , m_playButton(0) + , m_returnToRealTimeButton(0) + , m_statusDisplay(0) + , m_currentTimeDisplay(0) + , m_timeline(0) + , m_timeRemainingDisplay(0) + , m_timelineContainer(0) + , m_seekBackButton(0) + , m_seekForwardButton(0) + , m_toggleClosedCaptionsButton(0) + , m_panelMuteButton(0) + , m_volumeSlider(0) + , m_volumeSliderMuteButton(0) + , m_volumeSliderContainer(0) + , m_fullScreenButton(0) + , m_fullScreenMinVolumeButton(0) + , m_fullScreenVolumeSlider(0) + , m_fullScreenMaxVolumeButton(0) + , m_panel(0) + , m_opaque(true) +{ +} + +PassRefPtr<MediaControls> MediaControls::create(HTMLMediaElement* mediaElement) +{ + return MediaControlRootElement::create(mediaElement); +} + +PassRefPtr<MediaControlRootElement> MediaControlRootElement::create(HTMLMediaElement* mediaElement) +{ + if (!mediaElement->document()->page()) + return 0; + + RefPtr<MediaControlRootElement> controls = adoptRef(new MediaControlRootElement(mediaElement)); + + RefPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(mediaElement); + + ExceptionCode ec; + + RefPtr<MediaControlRewindButtonElement> rewindButton = MediaControlRewindButtonElement::create(mediaElement); + controls->m_rewindButton = rewindButton.get(); + panel->appendChild(rewindButton.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(mediaElement); + controls->m_playButton = playButton.get(); + panel->appendChild(playButton.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlReturnToRealtimeButtonElement> returnToRealtimeButton = MediaControlReturnToRealtimeButtonElement::create(mediaElement); + controls->m_returnToRealTimeButton = returnToRealtimeButton.get(); + panel->appendChild(returnToRealtimeButton.release(), ec, true); + if (ec) + return 0; + + if (mediaElement->document()->page()->theme()->usesMediaControlStatusDisplay()) { + RefPtr<MediaControlStatusDisplayElement> statusDisplay = MediaControlStatusDisplayElement::create(mediaElement); + controls->m_statusDisplay = statusDisplay.get(); + panel->appendChild(statusDisplay.release(), ec, true); + if (ec) + return 0; + } + + RefPtr<MediaControlTimelineContainerElement> timelineContainer = MediaControlTimelineContainerElement::create(mediaElement); + + RefPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(mediaElement); + controls->m_currentTimeDisplay = currentTimeDisplay.get(); + timelineContainer->appendChild(currentTimeDisplay.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(mediaElement, controls.get()); + controls->m_timeline = timeline.get(); + timelineContainer->appendChild(timeline.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlTimeRemainingDisplayElement> timeRemainingDisplay = MediaControlTimeRemainingDisplayElement::create(mediaElement); + controls->m_timeRemainingDisplay = timeRemainingDisplay.get(); + timelineContainer->appendChild(timeRemainingDisplay.release(), ec, true); + if (ec) + return 0; + + controls->m_timelineContainer = timelineContainer.get(); + panel->appendChild(timelineContainer.release(), ec, true); + if (ec) + return 0; + + // FIXME: Only create when needed <http://webkit.org/b/57163> + RefPtr<MediaControlSeekBackButtonElement> seekBackButton = MediaControlSeekBackButtonElement::create(mediaElement); + controls->m_seekBackButton = seekBackButton.get(); + panel->appendChild(seekBackButton.release(), ec, true); + if (ec) + return 0; + + // FIXME: Only create when needed <http://webkit.org/b/57163> + RefPtr<MediaControlSeekForwardButtonElement> seekForwardButton = MediaControlSeekForwardButtonElement::create(mediaElement); + controls->m_seekForwardButton = seekForwardButton.get(); + panel->appendChild(seekForwardButton.release(), ec, true); + if (ec) + return 0; + + if (mediaElement->document()->page()->theme()->supportsClosedCaptioning()) { + RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(mediaElement); + controls->m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); + panel->appendChild(toggleClosedCaptionsButton.release(), ec, true); + if (ec) + return 0; + } + + // FIXME: Only create when needed <http://webkit.org/b/57163> + RefPtr<MediaControlFullscreenButtonElement> fullScreenButton = MediaControlFullscreenButtonElement::create(mediaElement, controls.get()); + controls->m_fullScreenButton = fullScreenButton.get(); + panel->appendChild(fullScreenButton.release(), ec, true); + + RefPtr<MediaControlPanelMuteButtonElement> panelMuteButton = MediaControlPanelMuteButtonElement::create(mediaElement, controls.get()); + controls->m_panelMuteButton = panelMuteButton.get(); + panel->appendChild(panelMuteButton.release(), ec, true); + if (ec) + return 0; + + if (mediaElement->document()->page()->theme()->usesMediaControlVolumeSlider()) { + RefPtr<MediaControlVolumeSliderContainerElement> volumeSliderContainer = MediaControlVolumeSliderContainerElement::create(mediaElement); + + RefPtr<MediaControlVolumeSliderElement> slider = MediaControlVolumeSliderElement::create(mediaElement); + controls->m_volumeSlider = slider.get(); + volumeSliderContainer->appendChild(slider.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlVolumeSliderMuteButtonElement> volumeSliderMuteButton = MediaControlVolumeSliderMuteButtonElement::create(mediaElement); + controls->m_volumeSliderMuteButton = volumeSliderMuteButton.get(); + volumeSliderContainer->appendChild(volumeSliderMuteButton.release(), ec, true); + if (ec) + return 0; + + controls->m_volumeSliderContainer = volumeSliderContainer.get(); + panel->appendChild(volumeSliderContainer.release(), ec, true); + if (ec) + return 0; + } + + // FIXME: Only create when needed <http://webkit.org/b/57163> + RefPtr<MediaControlFullscreenVolumeMinButtonElement> fullScreenMinVolumeButton = MediaControlFullscreenVolumeMinButtonElement::create(mediaElement); + controls->m_fullScreenMinVolumeButton = fullScreenMinVolumeButton.get(); + panel->appendChild(fullScreenMinVolumeButton.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlFullscreenVolumeSliderElement> fullScreenVolumeSlider = MediaControlFullscreenVolumeSliderElement::create(mediaElement); + controls->m_fullScreenVolumeSlider = fullScreenVolumeSlider.get(); + panel->appendChild(fullScreenVolumeSlider.release(), ec, true); + if (ec) + return 0; + + RefPtr<MediaControlFullscreenVolumeMaxButtonElement> fullScreenMaxVolumeButton = MediaControlFullscreenVolumeMaxButtonElement::create(mediaElement); + controls->m_fullScreenMaxVolumeButton = fullScreenMaxVolumeButton.get(); + panel->appendChild(fullScreenMaxVolumeButton.release(), ec, true); + if (ec) + return 0; + + controls->m_panel = panel.get(); + controls->appendChild(panel.release(), ec, true); + if (ec) + return 0; + + return controls.release(); +} + +void MediaControlRootElement::show() +{ + m_panel->show(); +} + +void MediaControlRootElement::hide() +{ + m_panel->hide(); +} + +static const String& webkitTransitionString() +{ + DEFINE_STATIC_LOCAL(String, s, ("-webkit-transition")); + return s; +} + +static const String& opacityString() +{ + DEFINE_STATIC_LOCAL(String, s, ("opacity")); + return s; +} + +void MediaControlRootElement::makeOpaque() +{ + if (m_opaque) + return; + + DEFINE_STATIC_LOCAL(String, transitionValue, ()); + if (transitionValue.isNull()) + transitionValue = String::format("opacity %.1gs", document()->page()->theme()->mediaControlsFadeInDuration()); + DEFINE_STATIC_LOCAL(String, opacityValue, ("1")); + + ExceptionCode ec; + // FIXME: Make more efficient <http://webkit.org/b/58157> + m_panel->style()->setProperty(webkitTransitionString(), transitionValue, ec); + m_panel->style()->setProperty(opacityString(), opacityValue, ec); + m_opaque = true; +} + +void MediaControlRootElement::makeTransparent() +{ + if (!m_opaque) + return; + + DEFINE_STATIC_LOCAL(String, transitionValue, ()); + if (transitionValue.isNull()) + transitionValue = String::format("opacity %.1gs", document()->page()->theme()->mediaControlsFadeOutDuration()); + DEFINE_STATIC_LOCAL(String, opacityValue, ("0")); + + ExceptionCode ec; + // FIXME: Make more efficient <http://webkit.org/b/58157> + m_panel->style()->setProperty(webkitTransitionString(), transitionValue, ec); + m_panel->style()->setProperty(opacityString(), opacityValue, ec); + m_opaque = false; +} + +void MediaControlRootElement::reset() +{ + Page* page = document()->page(); + if (!page) + return; + + changedNetworkState(); + + if (m_mediaElement->supportsFullscreen()) + m_fullScreenButton->show(); + else + m_fullScreenButton->hide(); + + float duration = m_mediaElement->duration(); + if (isfinite(duration) || page->theme()->hasOwnDisabledStateHandlingFor(MediaSliderPart)) { + m_timeline->setDuration(duration); + m_timelineContainer->show(); + m_timeline->setPosition(m_mediaElement->currentTime()); + updateTimeDisplay(); + } else + m_timelineContainer->hide(); + + if (m_mediaElement->hasAudio() || page->theme()->hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) + m_panelMuteButton->show(); + else + m_panelMuteButton->hide(); + + if (m_volumeSlider) + m_volumeSlider->setVolume(m_mediaElement->volume()); + + if (m_toggleClosedCaptionsButton) { + if (m_mediaElement->hasClosedCaptions()) + m_toggleClosedCaptionsButton->show(); + else + m_toggleClosedCaptionsButton->hide(); + } + + if (m_mediaElement->movieLoadType() != MediaPlayer::LiveStream) { + m_returnToRealTimeButton->hide(); + m_rewindButton->show(); + } else { + m_returnToRealTimeButton->show(); + m_rewindButton->hide(); + } + + makeOpaque(); +} + +void MediaControlRootElement::playbackStarted() +{ + m_playButton->updateDisplayType(); + m_timeline->setPosition(m_mediaElement->currentTime()); + updateTimeDisplay(); +} + +void MediaControlRootElement::playbackProgressed() +{ + m_timeline->setPosition(m_mediaElement->currentTime()); + updateTimeDisplay(); +} + +void MediaControlRootElement::playbackStopped() +{ + m_playButton->updateDisplayType(); + m_timeline->setPosition(m_mediaElement->currentTime()); + updateTimeDisplay(); + makeOpaque(); +} + +void MediaControlRootElement::updateTimeDisplay() +{ + float now = m_mediaElement->currentTime(); + float duration = m_mediaElement->duration(); + + Page* page = document()->page(); + if (!page) + return; + + // Allow the theme to format the time. + ExceptionCode ec; + m_currentTimeDisplay->setInnerText(page->theme()->formatMediaControlsCurrentTime(now, duration), ec); + m_currentTimeDisplay->setCurrentValue(now); + m_timeRemainingDisplay->setInnerText(page->theme()->formatMediaControlsRemainingTime(now, duration), ec); + m_timeRemainingDisplay->setCurrentValue(now - duration); +} + +void MediaControlRootElement::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(); +} + +void MediaControlRootElement::changedNetworkState() +{ + if (m_statusDisplay) + m_statusDisplay->update(); +} + +void MediaControlRootElement::loadedMetadata() +{ + if (m_statusDisplay) + m_statusDisplay->hide(); + + reset(); +} + +void MediaControlRootElement::changedClosedCaptionsVisibility() +{ + if (m_toggleClosedCaptionsButton) + m_toggleClosedCaptionsButton->updateDisplayType(); +} + +void MediaControlRootElement::changedMute() +{ + m_panelMuteButton->changedMute(); + if (m_volumeSliderMuteButton) + m_volumeSliderMuteButton->changedMute(); +} + +void MediaControlRootElement::changedVolume() +{ + if (m_volumeSlider) + m_volumeSlider->setVolume(m_mediaElement->volume()); +} + +void MediaControlRootElement::enteredFullscreen() +{ + if (m_mediaElement->movieLoadType() == MediaPlayer::LiveStream || m_mediaElement->movieLoadType() == MediaPlayer::StoredStream) { + m_seekBackButton->hide(); + m_seekForwardButton->hide(); + } else + m_rewindButton->hide(); +} + +void MediaControlRootElement::exitedFullscreen() +{ + // "show" actually means removal of display:none style, so we are just clearing styles + // when exiting fullscreen. + // FIXME: Clarify naming of show/hide <http://webkit.org/b/58157> + m_rewindButton->show(); + m_seekBackButton->show(); + m_seekForwardButton->show(); +} + +void MediaControlRootElement::showVolumeSlider() +{ + if (!m_mediaElement->hasAudio()) + return; + + if (m_volumeSliderContainer) + m_volumeSliderContainer->show(); +} + +const AtomicString& MediaControlRootElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls")); + return id; +} + +} + +#endif diff --git a/Source/WebCore/html/shadow/MediaControlRootElement.h b/Source/WebCore/html/shadow/MediaControlRootElement.h new file mode 100644 index 0000000..8c6d3ec --- /dev/null +++ b/Source/WebCore/html/shadow/MediaControlRootElement.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * 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: + * 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 MediaControlRootElement_h +#define MediaControlRootElement_h + +#if ENABLE(VIDEO) + +#include "MediaControls.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class HTMLInputElement; +class HTMLMediaElement; +class Event; +class MediaControlPanelMuteButtonElement; +class MediaControlPlayButtonElement; +class MediaControlSeekButtonElement; +class MediaControlRewindButtonElement; +class MediaControlReturnToRealtimeButtonElement; +class MediaControlToggleClosedCaptionsButtonElement; +class MediaControlCurrentTimeDisplayElement; +class MediaControlTimelineElement; +class MediaControlTimeRemainingDisplayElement; +class MediaControlVolumeSliderElement; +class MediaControlFullscreenButtonElement; +class MediaControlTimeDisplayElement; +class MediaControlStatusDisplayElement; +class MediaControlTimelineContainerElement; +class MediaControlSeekBackButtonElement; +class MediaControlSeekForwardButtonElement; +class MediaControlMuteButtonElement; +class MediaControlVolumeSliderElement; +class MediaControlVolumeSliderMuteButtonElement; +class MediaControlVolumeSliderContainerElement; +class MediaControlFullscreenVolumeMinButtonElement; +class MediaControlFullscreenVolumeSliderElement; +class MediaControlFullscreenVolumeMaxButtonElement; +class MediaControlPanelElement; +class MediaPlayer; + +class RenderBox; +class RenderMedia; + +class MediaControlRootElement : public MediaControls { +public: + static PassRefPtr<MediaControlRootElement> create(HTMLMediaElement*); + + // MediaControls implementation. + void show(); + void hide(); + void makeOpaque(); + void makeTransparent(); + + void reset(); + + void playbackProgressed(); + void playbackStarted(); + void playbackStopped(); + + void changedMute(); + void changedVolume(); + + void enteredFullscreen(); + void exitedFullscreen(); + + void reportedError(); + void changedNetworkState(); + void loadedMetadata(); + void changedClosedCaptionsVisibility(); + + void showVolumeSlider(); + void updateTimeDisplay(); + +private: + MediaControlRootElement(HTMLMediaElement*); + + virtual const AtomicString& shadowPseudoId() const; + + HTMLMediaElement* m_mediaElement; + + MediaControlRewindButtonElement* m_rewindButton; + MediaControlPlayButtonElement* m_playButton; + MediaControlReturnToRealtimeButtonElement* m_returnToRealTimeButton; + MediaControlStatusDisplayElement* m_statusDisplay; + MediaControlCurrentTimeDisplayElement* m_currentTimeDisplay; + MediaControlTimelineElement* m_timeline; + MediaControlTimeRemainingDisplayElement* m_timeRemainingDisplay; + MediaControlTimelineContainerElement* m_timelineContainer; + MediaControlSeekBackButtonElement* m_seekBackButton; + MediaControlSeekForwardButtonElement* m_seekForwardButton; + MediaControlToggleClosedCaptionsButtonElement* m_toggleClosedCaptionsButton; + MediaControlPanelMuteButtonElement* m_panelMuteButton; + MediaControlVolumeSliderElement* m_volumeSlider; + MediaControlVolumeSliderMuteButtonElement* m_volumeSliderMuteButton; + MediaControlVolumeSliderContainerElement* m_volumeSliderContainer; + MediaControlFullscreenButtonElement* m_fullScreenButton; + MediaControlFullscreenVolumeMinButtonElement* m_fullScreenMinVolumeButton; + MediaControlFullscreenVolumeSliderElement* m_fullScreenVolumeSlider; + MediaControlFullscreenVolumeMaxButtonElement* m_fullScreenMaxVolumeButton; + MediaControlPanelElement* m_panel; + + bool m_opaque; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/html/shadow/MediaControls.cpp b/Source/WebCore/html/shadow/MediaControls.cpp index 04bdce4..690d1ce 100644 --- a/Source/WebCore/html/shadow/MediaControls.cpp +++ b/Source/WebCore/html/shadow/MediaControls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Apple Inc. All rights reserved. * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,11 +27,13 @@ #include "config.h" #if ENABLE(VIDEO) + #include "MediaControls.h" -#include "EventNames.h" -#include "FloatConversion.h" +#include "HTMLDivElement.h" +#include "HTMLMediaElement.h" #include "HTMLNames.h" +<<<<<<< HEAD #include "MediaControlElements.h" #include "MouseEvent.h" #include "Page.h" @@ -47,14 +49,13 @@ using namespace std; +======= +>>>>>>> WebKit.org at r84325 namespace WebCore { -using namespace HTMLNames; - -static const double cOpacityAnimationRepeatDelay = 0.05; - MediaControls::MediaControls(HTMLMediaElement* mediaElement) +<<<<<<< HEAD : m_mediaElement(mediaElement) , m_opacityAnimationTimer(this, &MediaControls::opacityAnimationTimerFired) , m_opacityAnimationStartTime(0) @@ -555,6 +556,10 @@ void MediaControls::forwardEvent(Event* event) } } #endif +======= + : HTMLDivElement(HTMLNames::divTag, mediaElement->document()) +{ +>>>>>>> WebKit.org at r84325 } #if PLATFORM(ANDROID) diff --git a/Source/WebCore/html/shadow/MediaControls.h b/Source/WebCore/html/shadow/MediaControls.h index 726573e..a14b359 100644 --- a/Source/WebCore/html/shadow/MediaControls.h +++ b/Source/WebCore/html/shadow/MediaControls.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Apple Inc. All rights reserved. * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,76 +29,59 @@ #if ENABLE(VIDEO) -#include "Timer.h" -#include <wtf/RefPtr.h> +#include "HTMLDivElement.h" namespace WebCore { -class HTMLElement; -class HTMLInputElement; class HTMLMediaElement; -class Event; -class MediaControlMuteButtonElement; -class MediaControlPlayButtonElement; -class MediaControlSeekButtonElement; -class MediaControlShadowRootElement; -class MediaControlRewindButtonElement; -class MediaControlReturnToRealtimeButtonElement; -class MediaControlToggleClosedCaptionsButtonElement; -class MediaControlTimelineElement; -class MediaControlVolumeSliderElement; -class MediaControlFullscreenButtonElement; -class MediaControlTimeDisplayElement; -class MediaControlStatusDisplayElement; -class MediaControlTimelineContainerElement; -class MediaControlVolumeSliderContainerElement; -class MediaControlElement; -class MediaControlFullscreenVolumeMinButtonElement; -class MediaControlFullscreenVolumeSliderElement; -class MediaControlFullscreenVolumeMaxButtonElement; -class MediaPlayer; - -class RenderBox; -class RenderMedia; - -class MediaControls { -public: - MediaControls(HTMLMediaElement*); - void reset(); +class MediaControls : public HTMLDivElement { + public: + virtual ~MediaControls() {} - void playbackProgressed(); - void playbackStarted(); - void playbackStopped(); + // This function is to be implemented in your port-specific media + // controls implementation. + static PassRefPtr<MediaControls> create(HTMLMediaElement*); - void changedMute(); - void changedVolume(); - void changedClosedCaptionsVisibility(); + virtual void show() = 0; + virtual void hide() = 0; + virtual void makeOpaque() = 0; + virtual void makeTransparent() = 0; - void destroy(); - void update(); - void updateStyle(); - void forwardEvent(Event*); - void updateTimeDisplay(); + virtual void reset() = 0; - // FIXME: This is temporary to allow RenderMedia::layout tweak the position of controls. - // Once shadow DOM refactoring is complete, the tweaking will be in MediaControlsShadowRoot and this accessor will no longer be necessary. - RenderBox* renderBox(); + virtual void playbackProgressed() = 0; + virtual void playbackStarted() = 0; + virtual void playbackStopped() = 0; +<<<<<<< HEAD #if PLATFORM(ANDROID) void updateLastTouch(); #endif private: PassRefPtr<MediaControlShadowRootElement> create(HTMLMediaElement*); +======= + virtual void changedMute() = 0; + virtual void changedVolume() = 0; +>>>>>>> WebKit.org at r84325 + + virtual void enteredFullscreen() = 0; + virtual void exitedFullscreen() = 0; + + virtual void reportedError() = 0; + virtual void changedNetworkState() = 0; + virtual void loadedMetadata() = 0; + virtual void changedClosedCaptionsVisibility() = 0; - void updateControlVisibility(); - void changeOpacity(HTMLElement*, float opacity); - void opacityAnimationTimerFired(Timer<MediaControls>*); + virtual void showVolumeSlider() = 0; + virtual void updateTimeDisplay() = 0; - void updateVolumeSliderContainer(bool visible); +protected: + MediaControls(HTMLMediaElement*); private: +<<<<<<< HEAD RefPtr<MediaControlShadowRootElement> m_controlsShadowRoot; RefPtr<MediaControlElement> m_panel; RefPtr<MediaControlMuteButtonElement> m_muteButton; @@ -134,10 +117,13 @@ private: #if PLATFORM(ANDROID) double m_lastTouch; #endif +======= + MediaControls(); +>>>>>>> WebKit.org at r84325 }; - } #endif + #endif diff --git a/Source/WebCore/html/shadow/MeterShadowElement.cpp b/Source/WebCore/html/shadow/MeterShadowElement.cpp new file mode 100644 index 0000000..a5eb70b --- /dev/null +++ b/Source/WebCore/html/shadow/MeterShadowElement.cpp @@ -0,0 +1,103 @@ +/* + * 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_TAG) +#include "MeterShadowElement.h" + +#include "CSSMutableStyleDeclaration.h" +#include "CSSPropertyNames.h" +#include "HTMLMeterElement.h" +#include "HTMLNames.h" +#include "RenderMeter.h" +#include "RenderTheme.h" + +namespace WebCore { + +using namespace HTMLNames; + +MeterShadowElement::MeterShadowElement(Document* document) + : HTMLDivElement(HTMLNames::divTag, document) +{ +} + +HTMLMeterElement* MeterShadowElement::meterElement() const +{ + Node* node = const_cast<MeterShadowElement*>(this)->shadowAncestorNode(); + ASSERT(!node || meterTag == toElement(node)->tagQName()); + return static_cast<HTMLMeterElement*>(node); +} + +bool MeterShadowElement::rendererIsNeeded(RenderStyle* style) +{ + RenderMeter* meterRenderer = toRenderMeter(meterElement()->renderer()); + return meterRenderer && !meterRenderer->theme()->supportsMeter(meterRenderer->style()->appearance()) && HTMLDivElement::rendererIsNeeded(style); +} + +const AtomicString& MeterBarElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-meter-bar")); + return pseudId; +} + + +const AtomicString& MeterValueElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, optimumPseudId, ("-webkit-meter-optimum-value")); + DEFINE_STATIC_LOCAL(AtomicString, suboptimumPseudId, ("-webkit-meter-suboptimum-value")); + DEFINE_STATIC_LOCAL(AtomicString, evenLessGoodPseudId, ("-webkit-meter-even-less-good-value")); + + HTMLMeterElement* meter = meterElement(); + if (!meter) + return optimumPseudId; + + switch (meter->gaugeRegion()) { + case HTMLMeterElement::GaugeRegionOptimum: + return optimumPseudId; + case HTMLMeterElement::GaugeRegionSuboptimal: + return suboptimumPseudId; + case HTMLMeterElement::GaugeRegionEvenLessGood: + return evenLessGoodPseudId; + default: + ASSERT_NOT_REACHED(); + return optimumPseudId; + } +} + +void MeterValueElement::setWidthPercentage(double width) +{ + getInlineStyleDecl()->setProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); +} + + +} + +#endif + diff --git a/Source/WebCore/html/shadow/MeterShadowElement.h b/Source/WebCore/html/shadow/MeterShadowElement.h new file mode 100644 index 0000000..93626df --- /dev/null +++ b/Source/WebCore/html/shadow/MeterShadowElement.h @@ -0,0 +1,86 @@ +/* + * 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 + +#include "HTMLDivElement.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class HTMLMeterElement; + +class MeterShadowElement : public HTMLDivElement { +public: + MeterShadowElement(Document*); + HTMLMeterElement* meterElement() const; + +private: + virtual bool rendererIsNeeded(RenderStyle*); +}; + +class MeterBarElement : public MeterShadowElement { +public: + MeterBarElement(Document* document) + : MeterShadowElement(document) + { + } + + static PassRefPtr<MeterBarElement> create(Document*); + virtual const AtomicString& shadowPseudoId() const; +}; + +inline PassRefPtr<MeterBarElement> MeterBarElement::create(Document* document) +{ + return adoptRef(new MeterBarElement(document)); +} + + +class MeterValueElement : public MeterShadowElement { +public: + MeterValueElement(Document* document) + : MeterShadowElement(document) + { + } + + virtual const AtomicString& shadowPseudoId() const; + static PassRefPtr<MeterValueElement> create(Document*); + void setWidthPercentage(double); +}; + +inline PassRefPtr<MeterValueElement> MeterValueElement::create(Document* document) +{ + return adoptRef(new MeterValueElement(document)); +} + +} + +#endif diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.cpp b/Source/WebCore/html/shadow/ProgressShadowElement.cpp new file mode 100644 index 0000000..1cedd0d --- /dev/null +++ b/Source/WebCore/html/shadow/ProgressShadowElement.cpp @@ -0,0 +1,81 @@ +/* + * 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(PROGRESS_TAG) +#include "ProgressShadowElement.h" + +#include "HTMLNames.h" +#include "HTMLProgressElement.h" +#include "RenderObject.h" + +namespace WebCore { + +using namespace HTMLNames; + +ProgressShadowElement::ProgressShadowElement(Document* document) + : HTMLDivElement(HTMLNames::divTag, document) +{ +} + +HTMLProgressElement* ProgressShadowElement::progressElement() const +{ + Node* node = const_cast<ProgressShadowElement*>(this)->shadowAncestorNode(); + ASSERT(!node || progressTag == toElement(node)->tagQName()); + return static_cast<HTMLProgressElement*>(node); +} + +bool ProgressShadowElement::rendererIsNeeded(RenderStyle* style) +{ + RenderObject* progressRenderer = progressElement()->renderer(); + return progressRenderer && !progressRenderer->style()->hasAppearance() && HTMLDivElement::rendererIsNeeded(style); +} + +const AtomicString& ProgressBarElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-progress-bar")); + return pseudId; +} + + +const AtomicString& ProgressValueElement::shadowPseudoId() const +{ + DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-progress-value")); + return pseudId; +} + +void ProgressValueElement::setWidthPercentage(double width) +{ + getInlineStyleDecl()->setProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); +} + +} +#endif + diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.h b/Source/WebCore/html/shadow/ProgressShadowElement.h new file mode 100644 index 0000000..a106bf8 --- /dev/null +++ b/Source/WebCore/html/shadow/ProgressShadowElement.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 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 ProgressShadowElement_h +#define ProgressShadowElement_h + +#include "HTMLDivElement.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class HTMLProgressElement; + +class ProgressShadowElement : public HTMLDivElement { +public: + ProgressShadowElement(Document*); + HTMLProgressElement* progressElement() const; + +private: + virtual bool rendererIsNeeded(RenderStyle*); +}; + +class ProgressBarElement : public ProgressShadowElement { +public: + ProgressBarElement(Document* document) + : ProgressShadowElement(document) + { + } + + static PassRefPtr<ProgressBarElement> create(Document*); + virtual const AtomicString& shadowPseudoId() const; +}; + +inline PassRefPtr<ProgressBarElement> ProgressBarElement::create(Document* document) +{ + return adoptRef(new ProgressBarElement(document)); +} + + +class ProgressValueElement : public ProgressShadowElement { +public: + ProgressValueElement(Document* document) + : ProgressShadowElement(document) + { + } + + virtual const AtomicString& shadowPseudoId() const; + static PassRefPtr<ProgressValueElement> create(Document*); + void setWidthPercentage(double); +}; + +inline PassRefPtr<ProgressValueElement> ProgressValueElement::create(Document* document) +{ + return adoptRef(new ProgressValueElement(document)); +} + +} + +#endif diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp index 6a6e901..e68ab00 100644 --- a/Source/WebCore/html/shadow/SliderThumbElement.cpp +++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp @@ -110,7 +110,7 @@ void SliderThumbElement::dragFrom(const IntPoint& point) void SliderThumbElement::setPositionFromPoint(const IntPoint& point) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost()); + HTMLInputElement* input = hostInput(); ASSERT(input); if (!input->renderer() || !renderer()) @@ -260,6 +260,12 @@ void SliderThumbElement::detach() HTMLDivElement::detach(); } +HTMLInputElement* SliderThumbElement::hostInput() +{ + ASSERT(parentNode()); + return static_cast<HTMLInputElement*>(parentNode()->shadowHost()); +} + const AtomicString& SliderThumbElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb")); diff --git a/Source/WebCore/html/shadow/SliderThumbElement.h b/Source/WebCore/html/shadow/SliderThumbElement.h index 9414ac4..2fa60cb 100644 --- a/Source/WebCore/html/shadow/SliderThumbElement.h +++ b/Source/WebCore/html/shadow/SliderThumbElement.h @@ -41,6 +41,7 @@ namespace WebCore { class HTMLElement; +class HTMLInputElement; class Event; class FloatPoint; @@ -62,6 +63,7 @@ private: void startDragging(); void stopDragging(); void setPositionFromPoint(const IntPoint&); + HTMLInputElement* hostInput(); FloatPoint m_offsetToThumb; bool m_inDragMode; diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.cpp b/Source/WebCore/html/shadow/TextControlInnerElements.cpp index 968c5e4..00fc667 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.cpp +++ b/Source/WebCore/html/shadow/TextControlInnerElements.cpp @@ -393,6 +393,12 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) // here, we take a temporary reference. RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowAncestorNode())); + if (input->disabled() || input->isReadOnlyFormControl()) { + 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()) { @@ -471,6 +477,9 @@ void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputR // 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(static_cast<HTMLInputElement*>(shadowAncestorNode())); + if (input->disabled() || input->isReadOnlyFormControl()) + return; + RefPtr<InputFieldSpeechButtonElement> holdRefButton(this); input->setValue(results.isEmpty() ? "" : results[0]->utterance()); input->dispatchEvent(SpeechInputEvent::create(eventNames().webkitspeechchangeEvent, results)); diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.h b/Source/WebCore/html/shadow/TextControlInnerElements.h index 4ba7857..2340970 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.h +++ b/Source/WebCore/html/shadow/TextControlInnerElements.h @@ -133,6 +133,7 @@ public: virtual void detach(); virtual void defaultEventHandler(Event*); + virtual bool isInputFieldSpeechButtonElement() const { return true; } SpeechInputState state() const { return m_state; } // SpeechInputListener methods. @@ -151,6 +152,12 @@ private: SpeechInputResultArray m_results; }; +inline InputFieldSpeechButtonElement* toInputFieldSpeechButtonElement(Element* element) +{ + ASSERT(!element || element->isInputFieldSpeechButtonElement()); + return static_cast<InputFieldSpeechButtonElement*>(element); +} + #endif // ENABLE(INPUT_SPEECH) } // namespace |