Reviewed by Darin Adler.
Flip input[type=range] to use the new shadow DOM model.
https://bugs.webkit.org/show_bug.cgi?id=52317
This is a straight-up flip, minimal change to the logic, which will be
refactored in a follow-up patch.
Covered by existing tests.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::initForStyleResolve): Changed to use either
host or parent node to find parent.
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::updateType): Added logic for destroying/creating
shadow DOM subtree.
* html/InputType.cpp:
(WebCore::InputType::createShadowSubtree): Added empty decl.
(WebCore::InputType::destroyShadowSubtree): Added a method to destroy
shadow subtree.
* html/InputType.h: Added defs.
* html/RangeInputType.cpp:
(WebCore::RangeInputType::createShadowSubtree): Added a virtual method to create
slider thumb.
* html/RangeInputType.h: Adde def.
* html/shadow/SliderThumbElement.cpp: Added temporary RenderSliderThumb class
to handle cascading appearance.
(WebCore::RenderSliderThumb::RenderSliderThumb): Added.
(WebCore::RenderSliderThumb::layout): Moved here the logic from
RenderSlider::createThumbStyle.
(WebCore::SliderThumbElement::createRenderer): Added virtual method to
create RenderSliderThumb instance.
(WebCore::SliderThumbElement::defaultEventHandler): Changed to use HTMLDivElement
as base class.
(WebCore::SliderThumbElement::detach): Ditto.
* html/shadow/SliderThumbElement.h:
(WebCore::SliderThumbElement::SliderThumbElement): Ditto.
(WebCore::SliderThumbElement::create): Ditto.
(WebCore::toSliderThumbElement): Added a casting helper.
* rendering/MediaControlElements.cpp:
(WebCore::MediaControlInputElement::attach): Added handling of shadow DOM,
since the whole method is hand-rolled.
(WebCore::MediaControlInputElement::updateStyle): Ditto.
* rendering/RenderSlider.cpp:
(WebCore::RenderSlider::~RenderSlider): Removed unneeded code.
(WebCore::RenderSlider::thumbRect): Changed to use sliderThumbElement helper.
(WebCore::RenderSlider::layout): Ditto.
(WebCore::RenderSlider::sliderThumbElement): Added a temporary helper to access
SliderThumbElement.
(WebCore::RenderSlider::mouseEventIsInThumb): Changed to use sliderThumbElement helper.
(WebCore::RenderSlider::mouseEventOffsetToThumb): Ditto.
(WebCore::RenderSlider::setValueForPosition): Ditto.
(WebCore::RenderSlider::positionForOffset): Ditto.
(WebCore::RenderSlider::currentPosition): Ditto.
(WebCore::RenderSlider::trackSize): Ditto.
(WebCore::RenderSlider::forwardEvent): Ditto.
(WebCore::RenderSlider::inDragMode): Ditto.
* rendering/RenderSlider.h: Added def.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75725
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-01-12 Dimitri Glazkov <dglazkov@chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Flip input[type=range] to use the new shadow DOM model.
+ https://bugs.webkit.org/show_bug.cgi?id=52317
+
+ This is a straight-up flip, minimal change to the logic, which will be
+ refactored in a follow-up patch.
+
+ Covered by existing tests.
+
+ * css/CSSStyleSelector.cpp:
+ (WebCore::CSSStyleSelector::initForStyleResolve): Changed to use either
+ host or parent node to find parent.
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::updateType): Added logic for destroying/creating
+ shadow DOM subtree.
+ * html/InputType.cpp:
+ (WebCore::InputType::createShadowSubtree): Added empty decl.
+ (WebCore::InputType::destroyShadowSubtree): Added a method to destroy
+ shadow subtree.
+ * html/InputType.h: Added defs.
+ * html/RangeInputType.cpp:
+ (WebCore::RangeInputType::createShadowSubtree): Added a virtual method to create
+ slider thumb.
+ * html/RangeInputType.h: Adde def.
+ * html/shadow/SliderThumbElement.cpp: Added temporary RenderSliderThumb class
+ to handle cascading appearance.
+ (WebCore::RenderSliderThumb::RenderSliderThumb): Added.
+ (WebCore::RenderSliderThumb::layout): Moved here the logic from
+ RenderSlider::createThumbStyle.
+ (WebCore::SliderThumbElement::createRenderer): Added virtual method to
+ create RenderSliderThumb instance.
+ (WebCore::SliderThumbElement::defaultEventHandler): Changed to use HTMLDivElement
+ as base class.
+ (WebCore::SliderThumbElement::detach): Ditto.
+ * html/shadow/SliderThumbElement.h:
+ (WebCore::SliderThumbElement::SliderThumbElement): Ditto.
+ (WebCore::SliderThumbElement::create): Ditto.
+ (WebCore::toSliderThumbElement): Added a casting helper.
+ * rendering/MediaControlElements.cpp:
+ (WebCore::MediaControlInputElement::attach): Added handling of shadow DOM,
+ since the whole method is hand-rolled.
+ (WebCore::MediaControlInputElement::updateStyle): Ditto.
+ * rendering/RenderSlider.cpp:
+ (WebCore::RenderSlider::~RenderSlider): Removed unneeded code.
+ (WebCore::RenderSlider::thumbRect): Changed to use sliderThumbElement helper.
+ (WebCore::RenderSlider::layout): Ditto.
+ (WebCore::RenderSlider::sliderThumbElement): Added a temporary helper to access
+ SliderThumbElement.
+ (WebCore::RenderSlider::mouseEventIsInThumb): Changed to use sliderThumbElement helper.
+ (WebCore::RenderSlider::mouseEventOffsetToThumb): Ditto.
+ (WebCore::RenderSlider::setValueForPosition): Ditto.
+ (WebCore::RenderSlider::positionForOffset): Ditto.
+ (WebCore::RenderSlider::currentPosition): Ditto.
+ (WebCore::RenderSlider::trackSize): Ditto.
+ (WebCore::RenderSlider::forwardEvent): Ditto.
+ (WebCore::RenderSlider::inDragMode): Ditto.
+ * rendering/RenderSlider.h: Added def.
+
2011-01-13 Dan Bernstein <mitz@apple.com>
Reviewed by Simon Fraser.
{
m_checker.m_pseudoStyle = pseudoID;
- m_parentNode = e ? e->parentNode() : 0;
-
-#if ENABLE(SVG)
- if (!m_parentNode && e && e->isSVGElement() && e->isShadowRoot())
- m_parentNode = e->shadowHost();
-#endif
+ m_parentNode = e ? e->parentOrHostNode() : 0;
if (parentStyle)
m_parentStyle = parentStyle;
bool neededActivationCallback = needsActivationCallback();
bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
+ m_inputType->destroyShadowSubtree();
m_inputType = newType.release();
+ m_inputType->createShadowSubtree();
setNeedsWillValidateCheck();
return RenderObject::createObject(element(), style);
}
+void InputType::createShadowSubtree()
+{
+}
+
+void InputType::destroyShadowSubtree()
+{
+ element()->setShadowRoot(0);
+}
+
double InputType::parseToDouble(const String&, double defaultValue) const
{
return defaultValue;
virtual void accessKeyAction(bool sendToAnyElement);
virtual bool canBeSuccessfulSubmitButton();
+
+ // Shadow tree handling
+
+ virtual void createShadowSubtree();
+ void destroyShadowSubtree();
+
// Miscellaneous functions
virtual bool rendererIsNeeded();
#include "HTMLParserIdioms.h"
#include "KeyboardEvent.h"
#include "RenderSlider.h"
+#include "SliderThumbElement.h"
#include "StepRange.h"
#include <limits>
#include <wtf/MathExtras.h>
toRenderSlider(element()->renderer())->forwardEvent(event);
}
+void RangeInputType::createShadowSubtree()
+{
+ element()->setShadowRoot(SliderThumbElement::create(element()->document()));
+}
+
RenderObject* RangeInputType::createRenderer(RenderArena* arena, RenderStyle*) const
{
return new (arena) RenderSlider(element());
virtual void handleKeydownEvent(KeyboardEvent*);
virtual void forwardEvent(Event*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const;
+ virtual void createShadowSubtree();
virtual double parseToDouble(const String&, double) const;
virtual String serialize(double) const;
virtual void accessKeyAction(bool sendToAnyElement);
#include "Frame.h"
#include "MouseEvent.h"
#include "RenderSlider.h"
+#include "RenderTheme.h"
namespace WebCore {
+// FIXME: Find a way to cascade appearance (see the layout method) and get rid of this class.
+class RenderSliderThumb : public RenderBlock {
+public:
+ RenderSliderThumb(Node*);
+ virtual void layout();
+};
+
+
+RenderSliderThumb::RenderSliderThumb(Node* node)
+ : RenderBlock(node)
+{
+}
+
+void RenderSliderThumb::layout()
+{
+ // FIXME: Hard-coding this cascade of appearance is bad, because it's something
+ // that CSS usually does. We need to find a way to express this in CSS.
+ RenderStyle* parentStyle = parent()->style();
+ if (parentStyle->appearance() == SliderVerticalPart)
+ style()->setAppearance(SliderThumbVerticalPart);
+ else if (parentStyle->appearance() == SliderHorizontalPart)
+ style()->setAppearance(SliderThumbHorizontalPart);
+ else if (parentStyle->appearance() == MediaSliderPart)
+ style()->setAppearance(MediaSliderThumbPart);
+ else if (parentStyle->appearance() == MediaVolumeSliderPart)
+ style()->setAppearance(MediaVolumeSliderThumbPart);
+
+ if (style()->hasAppearance()) {
+ // FIXME: This should pass the style, not the renderer, to the theme.
+ theme()->adjustSliderThumbSize(this);
+ }
+ RenderBlock::layout();
+}
+
+RenderObject* SliderThumbElement::createRenderer(RenderArena* arena, RenderStyle*)
+{
+ return new (arena) RenderSliderThumb(this);
+}
+
void SliderThumbElement::defaultEventHandler(Event* event)
{
if (!event->isMouseEvent()) {
- ShadowBlockElement::defaultEventHandler(event);
+ HTMLDivElement::defaultEventHandler(event);
return;
}
}
}
- ShadowBlockElement::defaultEventHandler(event);
+ HTMLDivElement::defaultEventHandler(event);
}
void SliderThumbElement::detach()
if (Frame* frame = document()->frame())
frame->eventHandler()->setCapturingMouseEventsNode(0);
}
- ShadowBlockElement::detach();
+ HTMLDivElement::detach();
}
}
#define SliderThumbElement_h
#include "FloatPoint.h"
+#include "HTMLDivElement.h"
+#include "HTMLNames.h"
#include "RenderStyleConstants.h"
-#include "ShadowElement.h"
#include <wtf/Forward.h>
namespace WebCore {
class Event;
class FloatPoint;
-class SliderThumbElement : public ShadowBlockElement {
+class SliderThumbElement : public HTMLDivElement {
public:
- static PassRefPtr<SliderThumbElement> create(HTMLElement* shadowParent);
+ static PassRefPtr<SliderThumbElement> create(Document*);
bool inDragMode() const { return m_inDragMode; }
virtual void detach();
virtual AtomicString shadowPseudoId() const;
-private:
- SliderThumbElement(HTMLElement* shadowParent);
+private:
+ SliderThumbElement(Document*);
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
FloatPoint m_offsetToThumb;
bool m_inDragMode;
};
-inline SliderThumbElement::SliderThumbElement(HTMLElement* shadowParent)
- : ShadowBlockElement(shadowParent)
+inline SliderThumbElement::SliderThumbElement(Document* document)
+ : HTMLDivElement(HTMLNames::divTag, document)
, m_inDragMode(false)
{
}
-inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(HTMLElement* shadowParent)
+inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(Document* document)
{
- return adoptRef(new SliderThumbElement(shadowParent));
+ return adoptRef(new SliderThumbElement(document));
}
inline AtomicString SliderThumbElement::shadowPseudoId() const
return sliderThumb;
}
+inline SliderThumbElement* toSliderThumbElement(Node* node)
+{
+ ASSERT(!node || node->isHTMLElement());
+ return static_cast<SliderThumbElement*>(node);
}
+}
#endif
parentNode()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
}
ContainerNode::attach();
+ // FIXME: Currently, MeidaControlInput circumvents the normal attachment
+ // and style recalc cycle and thus we need to add extra logic to be aware of
+ // the shadow DOM. Remove this once all media controls are transitioned to use the regular
+ // style calculation.
+ if (Node* shadowNode = shadowRoot())
+ shadowNode->attach();
}
void MediaControlInputElement::updateStyle()
attach();
else if (renderer())
renderer()->setStyle(style.get());
+
+ // FIXME: Currently, MeidaControlInput circumvents the normal attachment
+ // and style recalc cycle and thus we need to add extra logic to be aware of
+ // the shadow DOM. Remove this once all media controls are transitioned to use
+ // the new shadow DOM.
+ if (Node* shadowNode = shadowRoot())
+ shadowNode->recalcStyle(Node::Force);
}
bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
RenderSlider::~RenderSlider()
{
- if (m_thumb)
- m_thumb->detach();
}
int RenderSlider::baselinePosition(FontBaseline, bool /*firstLine*/, LineDirectionMode, LinePositionMode) const
setPreferredLogicalWidthsDirty(false);
}
-void RenderSlider::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderBlock::styleDidChange(diff, oldStyle);
-
- if (m_thumb)
- m_thumb->renderer()->setStyle(createThumbStyle(style()));
-}
-
-PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle)
-{
- RefPtr<RenderStyle> thumbStyle = document()->styleSelector()->styleForElement(m_thumb.get(), style(), false);
-
- if (parentStyle->appearance() == SliderVerticalPart)
- thumbStyle->setAppearance(SliderThumbVerticalPart);
- else if (parentStyle->appearance() == SliderHorizontalPart)
- thumbStyle->setAppearance(SliderThumbHorizontalPart);
- else if (parentStyle->appearance() == MediaSliderPart)
- thumbStyle->setAppearance(MediaSliderThumbPart);
- else if (parentStyle->appearance() == MediaVolumeSliderPart)
- thumbStyle->setAppearance(MediaVolumeSliderThumbPart);
-
- return thumbStyle.release();
-}
-
IntRect RenderSlider::thumbRect()
{
- if (!m_thumb)
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ if (!thumbElement)
return IntRect();
IntRect thumbRect;
- RenderBox* thumb = toRenderBox(m_thumb->renderer());
+ RenderBox* thumb = toRenderBox(thumbElement->renderer());
thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));
{
ASSERT(needsLayout());
- RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0;
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ RenderBox* thumb = thumbElement ? toRenderBox(thumbElement->renderer()) : 0;
IntSize baseSize(borderAndPaddingWidth(), borderAndPaddingHeight());
setNeedsLayout(false);
}
-void RenderSlider::updateFromElement()
+SliderThumbElement* RenderSlider::sliderThumbElement() const
{
- // Layout will take care of the thumb's size and position.
- if (!m_thumb) {
- m_thumb = SliderThumbElement::create(static_cast<HTMLElement*>(node()));
- RefPtr<RenderStyle> thumbStyle = createThumbStyle(style());
- m_thumb->setRenderer(m_thumb->createRenderer(renderArena(), thumbStyle.get()));
- m_thumb->renderer()->setStyle(thumbStyle.release());
- m_thumb->setAttached();
- m_thumb->setInDocument();
- addChild(m_thumb->renderer());
- }
- setNeedsLayout(true);
+ return toSliderThumbElement(static_cast<Element*>(node())->shadowRoot());
}
bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
{
- if (!m_thumb || !m_thumb->renderer())
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ if (!thumbElement || !thumbElement->renderer())
return false;
#if ENABLE(VIDEO)
if (style()->appearance() == MediaSliderPart || style()->appearance() == MediaVolumeSliderPart) {
- MediaControlInputElement *sliderThumb = static_cast<MediaControlInputElement*>(m_thumb->renderer()->node());
+ MediaControlInputElement* sliderThumb = static_cast<MediaControlInputElement*>(thumbElement->renderer()->node());
return sliderThumb->hitTest(evt->absoluteLocation());
}
#endif
- FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
- IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect();
+ FloatPoint localPoint = thumbElement->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
+ IntRect thumbBounds = thumbElement->renderBox()->borderBoxRect();
return thumbBounds.contains(roundedIntPoint(localPoint));
}
FloatPoint RenderSlider::mouseEventOffsetToThumb(MouseEvent* evt)
{
- ASSERT(m_thumb && m_thumb->renderer());
- FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
- IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect();
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ ASSERT(thumbElement && thumbElement->renderer());
+ FloatPoint localPoint = thumbElement->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
+ IntRect thumbBounds = thumbElement->renderBox()->borderBoxRect();
FloatPoint offset;
offset.setX(thumbBounds.x() + thumbBounds.width() / 2 - localPoint.x());
offset.setY(thumbBounds.y() + thumbBounds.height() / 2 - localPoint.y());
void RenderSlider::setValueForPosition(int position)
{
- if (!m_thumb || !m_thumb->renderer())
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ if (!thumbElement || !thumbElement->renderer())
return;
HTMLInputElement* element = static_cast<HTMLInputElement*>(node());
int RenderSlider::positionForOffset(const IntPoint& p)
{
- if (!m_thumb || !m_thumb->renderer())
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ if (!thumbElement || !thumbElement->renderer())
return 0;
int position;
if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
- position = p.y() - m_thumb->renderBox()->height() / 2;
+ position = p.y() - thumbElement->renderBox()->height() / 2;
else
- position = p.x() - m_thumb->renderBox()->width() / 2;
+ position = p.x() - thumbElement->renderBox()->width() / 2;
return max(0, min(position, trackSize()));
}
int RenderSlider::currentPosition()
{
- ASSERT(m_thumb);
- ASSERT(m_thumb->renderer());
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ ASSERT(thumbElement && thumbElement->renderer());
if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
- return toRenderBox(m_thumb->renderer())->y() - contentBoxRect().y();
- return toRenderBox(m_thumb->renderer())->x() - contentBoxRect().x();
+ return toRenderBox(thumbElement->renderer())->y() - contentBoxRect().y();
+ return toRenderBox(thumbElement->renderer())->x() - contentBoxRect().x();
}
int RenderSlider::trackSize()
{
- ASSERT(m_thumb);
- ASSERT(m_thumb->renderer());
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ ASSERT(thumbElement && thumbElement->renderer());
if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
- return contentHeight() - m_thumb->renderBox()->height();
- return contentWidth() - m_thumb->renderBox()->width();
+ return contentHeight() - thumbElement->renderBox()->height();
+ return contentWidth() - thumbElement->renderBox()->width();
}
void RenderSlider::forwardEvent(Event* event)
{
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ if (!thumbElement)
+ return;
+
if (event->isMouseEvent()) {
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
if (event->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
}
}
- m_thumb->defaultEventHandler(event);
+ thumbElement->defaultEventHandler(event);
}
bool RenderSlider::inDragMode() const
{
- return m_thumb && m_thumb->inDragMode();
+ SliderThumbElement* thumbElement = sliderThumbElement();
+ return thumbElement && thumbElement->inDragMode();
}
} // namespace WebCore
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
virtual void computePreferredLogicalWidths();
virtual void layout();
- virtual void updateFromElement();
+ // FIXME: Eventually, the logic of manipulating slider thumb should move to
+ // SliderThumbElement and accessing sliderThumbElement should not be necessary in this class.
+ SliderThumbElement* sliderThumbElement() const;
bool mouseEventIsInThumb(MouseEvent*);
FloatPoint mouseEventOffsetToThumb(MouseEvent*);
int currentPosition();
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- PassRefPtr<RenderStyle> createThumbStyle(const RenderStyle* parentStyle);
-
int trackSize();
- RefPtr<SliderThumbElement> m_thumb;
-
friend class SliderThumbElement;
};