Changeset 76147 in webkit


Ignore:
Timestamp:
Jan 19, 2011 12:17:17 PM (13 years ago)
Author:
Dimitri Glazkov
Message:

2011-01-14 Dimitri Glazkov <Dimitri Glazkov>

Reviewed by Darin Adler.

Remove event forwarding logic from input[type=range], simplify event flow and thumb positioning logic.
https://bugs.webkit.org/show_bug.cgi?id=52464

This change has two parts:

1) Utilize shadow DOM event retargeting to get rid of forwarding events

via render tree;

2) Move thumb positioning logic from RenderSlider to SliderThumbElement.

These two are highly co-dependent. It looked ugly when I tried to
separate them.

No change in behavior, covered by existing tests.

  • html/HTMLInputElement.cpp: (WebCore::HTMLInputElement::defaultEventHandler): Added invocation of

InputType::handleMouseDownEvent.

  • html/InputType.cpp: (WebCore::InputType::handleMouseDownEvent): Added empty decl.
  • html/InputType.h: Added def.
  • html/RangeInputType.cpp: (WebCore::RangeInputType::handleMouseDownEvent): Added to handle the case

when the user clicks on the track of the slider. Also removed the
forwardEvent method.

  • html/RangeInputType.h: Added/removed defs.
  • html/shadow/SliderThumbElement.cpp: (WebCore::SliderThumbElement::dragFrom): Added a helper method to start

dragging from any position.

(WebCore::SliderThumbElement::dragTo): Added a helper method to drag to

specified position.

(WebCore::SliderThumbElement::setPosition): Collapsed most of the positioning

logic in RenderSlider into this method, which is now a simple calculation
and adjusting of thumb position based on supplied coordinates.

(WebCore::SliderThumbElement::startDragging): Added.
(WebCore::SliderThumbElement::stopDragging): Added.
(WebCore::SliderThumbElement::defaultEventHandler): Removed most of the

old position-sniffing logic and replaced with simple calls to start,
stop, and drag the thumb.

  • html/shadow/SliderThumbElement.h: Added defs.
  • rendering/RenderSlider.cpp: Removed a bunch of code that is no longer

necessary.

  • rendering/RenderSlider.h: Removed defs, removed now-unnecessary friendliness.
Location:
trunk/Source/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r76146 r76147  
     12011-01-14  Dimitri Glazkov  <dglazkov@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        Remove event forwarding logic from input[type=range], simplify event flow and thumb positioning logic.
     6        https://bugs.webkit.org/show_bug.cgi?id=52464
     7
     8        This change has two parts:
     9
     10        1) Utilize shadow DOM event retargeting to get rid of forwarding events
     11           via render tree;
     12        2) Move thumb positioning logic from RenderSlider to SliderThumbElement.
     13
     14        These two are highly co-dependent. It looked ugly when I tried to
     15        separate them.
     16
     17        No change in behavior, covered by existing tests.
     18
     19        * html/HTMLInputElement.cpp:
     20        (WebCore::HTMLInputElement::defaultEventHandler): Added invocation of
     21            InputType::handleMouseDownEvent.
     22        * html/InputType.cpp:
     23        (WebCore::InputType::handleMouseDownEvent): Added empty decl.
     24        * html/InputType.h: Added def.
     25        * html/RangeInputType.cpp:
     26        (WebCore::RangeInputType::handleMouseDownEvent): Added to handle the case
     27            when the user clicks on the track of the slider. Also removed the
     28            forwardEvent method.
     29        * html/RangeInputType.h: Added/removed defs.
     30        * html/shadow/SliderThumbElement.cpp:
     31        (WebCore::SliderThumbElement::dragFrom): Added a helper method to start
     32            dragging from any position.
     33        (WebCore::SliderThumbElement::dragTo): Added a helper method to drag to
     34            specified position.
     35        (WebCore::SliderThumbElement::setPosition): Collapsed most of the positioning
     36            logic in RenderSlider into this method, which is now a simple calculation
     37            and adjusting of thumb position based on supplied coordinates.
     38        (WebCore::SliderThumbElement::startDragging): Added.
     39        (WebCore::SliderThumbElement::stopDragging): Added.
     40        (WebCore::SliderThumbElement::defaultEventHandler): Removed most of the
     41            old position-sniffing logic and replaced with simple calls to start,
     42            stop, and drag the thumb.
     43        * html/shadow/SliderThumbElement.h: Added defs.
     44        * rendering/RenderSlider.cpp: Removed a bunch of code that is no longer
     45            necessary.
     46        * rendering/RenderSlider.h: Removed defs, removed now-unnecessary friendliness.
     47
    1482011-01-19  Shane Stephens  <shanestephens@google.com>
    249
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r76115 r76147  
    10371037    }
    10381038
     1039    if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
     1040        m_inputType->handleMouseDownEvent(static_cast<MouseEvent*>(evt));
     1041        if (evt->defaultHandled())
     1042            return;
     1043    }
     1044
    10391045    m_inputType->forwardEvent(evt);
    10401046
  • trunk/Source/WebCore/html/InputType.cpp

    r75749 r76147  
    306306}
    307307
     308void InputType::handleMouseDownEvent(MouseEvent*)
     309{
     310}
     311
    308312void InputType::handleDOMActivateEvent(Event*)
    309313{
  • trunk/Source/WebCore/html/InputType.h

    r75749 r76147  
    154154
    155155    virtual void handleClickEvent(MouseEvent*);
     156    virtual void handleMouseDownEvent(MouseEvent*);
    156157    virtual PassOwnPtr<ClickHandlingState> willDispatchClick();
    157158    virtual void didDispatchClick(Event*, const ClickHandlingState&);
  • trunk/Source/WebCore/html/RangeInputType.cpp

    r75749 r76147  
    3737#include "HTMLParserIdioms.h"
    3838#include "KeyboardEvent.h"
     39#include "MouseEvent.h"
     40#include "PlatformMouseEvent.h"
    3941#include "RenderSlider.h"
    4042#include "SliderThumbElement.h"
     
    140142{
    141143    return rangeStepScaleFactor;
     144}
     145
     146void RangeInputType::handleMouseDownEvent(MouseEvent* event)
     147{
     148    if (event->button() != LeftButton || event->target() != element())
     149        return;
     150
     151    if (SliderThumbElement* thumb = toSliderThumbElement(element()->shadowRoot()))
     152        thumb->dragFrom(event->absoluteLocation());
    142153}
    143154
     
    182193}
    183194
    184 void RangeInputType::forwardEvent(Event* event)
    185 {
    186     if (element()->renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent()))
    187         toRenderSlider(element()->renderer())->forwardEvent(event);
    188 }
    189 
    190195void RangeInputType::createShadowSubtree()
    191196{
  • trunk/Source/WebCore/html/RangeInputType.h

    r75749 r76147  
    5656    virtual double defaultStep() const;
    5757    virtual double stepScaleFactor() const;
     58    virtual void handleMouseDownEvent(MouseEvent*);
    5859    virtual void handleKeydownEvent(KeyboardEvent*);
    59     virtual void forwardEvent(Event*);
    6060    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const;
    6161    virtual void createShadowSubtree();
  • trunk/Source/WebCore/html/shadow/SliderThumbElement.cpp

    r75749 r76147  
    3636#include "Event.h"
    3737#include "Frame.h"
     38#include "HTMLInputElement.h"
     39#include "HTMLParserIdioms.h"
    3840#include "MouseEvent.h"
    3941#include "RenderSlider.h"
    4042#include "RenderTheme.h"
     43#include "StepRange.h"
     44#include <wtf/MathExtras.h>
     45
     46using namespace std;
    4147
    4248namespace WebCore {
     
    4854    virtual void layout();
    4955};
    50 
    5156
    5257RenderSliderThumb::RenderSliderThumb(Node* node)
     
    8186}
    8287
     88void SliderThumbElement::dragFrom(const IntPoint& point)
     89{
     90    setPosition(point);
     91    startDragging();
     92}
     93
     94void SliderThumbElement::setPosition(const IntPoint& point)
     95{
     96    HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
     97    ASSERT(input);
     98
     99    if (!input->renderer() || !renderer())
     100        return;
     101
     102    IntPoint offset = roundedIntPoint(input->renderer()->absoluteToLocal(point, false, true));
     103    RenderStyle* sliderStyle = input->renderer()->style();
     104    bool isVertical = sliderStyle->appearance() == SliderVerticalPart || sliderStyle->appearance() == MediaVolumeSliderPart;
     105
     106    int trackSize;
     107    int position;
     108    int currentPosition;
     109    if (isVertical) {
     110        trackSize = input->renderBox()->contentHeight() - renderBox()->height();
     111        position = offset.y() - renderBox()->height() / 2;
     112        currentPosition = renderBox()->y() - input->renderBox()->contentBoxRect().y();
     113    } else {
     114        trackSize = input->renderBox()->contentWidth() - renderBox()->width();
     115        position = offset.x() - renderBox()->width() / 2;
     116        currentPosition = renderBox()->x() - input->renderBox()->contentBoxRect().x();
     117    }
     118    position = max(0, min(position, trackSize));
     119    if (position == currentPosition)
     120        return;
     121
     122    StepRange range(input);
     123    double fraction = static_cast<double>(position) / trackSize;
     124    if (isVertical)
     125        fraction = 1 - fraction;
     126    double value = range.clampValue(range.valueFromProportion(fraction));
     127
     128    // FIXME: This is no longer being set from renderer. Consider updating the method name.
     129    input->setValueFromRenderer(serializeForNumberType(value));
     130    renderer()->setNeedsLayout(true);
     131    input->dispatchFormControlChangeEvent();
     132}
     133
     134void SliderThumbElement::startDragging()
     135{
     136    if (Frame* frame = document()->frame()) {
     137        frame->eventHandler()->setCapturingMouseEventsNode(this);
     138        m_inDragMode = true;
     139    }
     140}
     141
     142void SliderThumbElement::stopDragging()
     143{
     144    if (!m_inDragMode)
     145        return;
     146
     147    if (Frame* frame = document()->frame())
     148        frame->eventHandler()->setCapturingMouseEventsNode(0);
     149    m_inDragMode = false;
     150}
     151
    83152void SliderThumbElement::defaultEventHandler(Event* event)
    84153{
     
    93162
    94163    if (eventType == eventNames().mousedownEvent && isLeftButton) {
    95         if (document()->frame() && renderer()) {
    96             RenderSlider* slider = toRenderSlider(renderer()->parent());
    97             if (slider) {
    98                 if (slider->mouseEventIsInThumb(mouseEvent)) {
    99                     // We selected the thumb, we want the cursor to always stay at
    100                     // the same position relative to the thumb.
    101                     m_offsetToThumb = slider->mouseEventOffsetToThumb(mouseEvent);
    102                 } else {
    103                     // We are outside the thumb, move the thumb to the point were
    104                     // we clicked. We'll be exactly at the center of the thumb.
    105                     m_offsetToThumb.setX(0);
    106                     m_offsetToThumb.setY(0);
    107                 }
    108 
    109                 m_inDragMode = true;
    110                 document()->frame()->eventHandler()->setCapturingMouseEventsNode(shadowHost());
    111                 event->setDefaultHandled();
    112                 return;
    113             }
    114         }
     164        startDragging();
     165        return;
    115166    } else if (eventType == eventNames().mouseupEvent && isLeftButton) {
    116         if (m_inDragMode) {
    117             if (Frame* frame = document()->frame())
    118                 frame->eventHandler()->setCapturingMouseEventsNode(0);     
    119             m_inDragMode = false;
    120             event->setDefaultHandled();
    121             return;
    122         }
     167        stopDragging();
     168        return;
    123169    } else if (eventType == eventNames().mousemoveEvent) {
    124         if (m_inDragMode && renderer() && renderer()->parent()) {
    125             RenderSlider* slider = toRenderSlider(renderer()->parent());
    126             if (slider) {
    127                 FloatPoint curPoint = slider->absoluteToLocal(mouseEvent->absoluteLocation(), false, true);
    128                 IntPoint eventOffset(curPoint.x() + m_offsetToThumb.x(), curPoint.y() + m_offsetToThumb.y());
    129                 slider->setValueForPosition(slider->positionForOffset(eventOffset));
    130                 event->setDefaultHandled();
    131                 return;
    132             }
    133         }
     170        if (m_inDragMode)
     171            setPosition(mouseEvent->absoluteLocation());
     172        return;
    134173    }
    135174
  • trunk/Source/WebCore/html/shadow/SliderThumbElement.h

    r75749 r76147  
    5151    bool inDragMode() const { return m_inDragMode; }
    5252
     53    void dragFrom(const IntPoint&);
    5354    virtual void defaultEventHandler(Event*);
    5455    virtual void detach();
     
    5859    SliderThumbElement(Document*);
    5960    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     61    void startDragging();
     62    void stopDragging();
     63    void setPosition(const IntPoint&);
    6064
    6165    FloatPoint m_offsetToThumb;
  • trunk/Source/WebCore/rendering/RenderSlider.cpp

    r75749 r76147  
    182182}
    183183
    184 bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
    185 {
    186     SliderThumbElement* thumbElement = sliderThumbElement();
    187     if (!thumbElement || !thumbElement->renderer())
    188         return false;
    189 
    190 #if ENABLE(VIDEO)
    191     if (style()->appearance() == MediaSliderPart || style()->appearance() == MediaVolumeSliderPart) {
    192         MediaControlInputElement* sliderThumb = static_cast<MediaControlInputElement*>(thumbElement->renderer()->node());
    193         return sliderThumb->hitTest(evt->absoluteLocation());
    194     }
    195 #endif
    196 
    197     FloatPoint localPoint = thumbElement->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
    198     IntRect thumbBounds = thumbElement->renderBox()->borderBoxRect();
    199     return thumbBounds.contains(roundedIntPoint(localPoint));
    200 }
    201 
    202 FloatPoint RenderSlider::mouseEventOffsetToThumb(MouseEvent* evt)
    203 {
    204     SliderThumbElement* thumbElement = sliderThumbElement();
    205     ASSERT(thumbElement && thumbElement->renderer());
    206     FloatPoint localPoint = thumbElement->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
    207     IntRect thumbBounds = thumbElement->renderBox()->borderBoxRect();
    208     FloatPoint offset;
    209     offset.setX(thumbBounds.x() + thumbBounds.width() / 2 - localPoint.x());
    210     offset.setY(thumbBounds.y() + thumbBounds.height() / 2 - localPoint.y());
    211     return offset;
    212 }
    213 
    214 void RenderSlider::setValueForPosition(int position)
    215 {
    216     SliderThumbElement* thumbElement = sliderThumbElement();
    217     if (!thumbElement || !thumbElement->renderer())
    218         return;
    219 
    220     HTMLInputElement* element = static_cast<HTMLInputElement*>(node());
    221 
    222     // Calculate the new value based on the position, and send it to the element.
    223     StepRange range(element);
    224     double fraction = static_cast<double>(position) / trackSize();
    225     if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
    226         fraction = 1 - fraction;
    227     double value = range.clampValue(range.valueFromProportion(fraction));
    228     element->setValueFromRenderer(serializeForNumberType(value));
    229 
    230     // Also update the position if appropriate.
    231     if (position != currentPosition()) {
    232         setNeedsLayout(true);
    233 
    234         // FIXME: It seems like this could send extra change events if the same value is set
    235         // multiple times with no layout in between.
    236         element->dispatchFormControlChangeEvent();
    237     }
    238 }
    239 
    240 int RenderSlider::positionForOffset(const IntPoint& p)
    241 {
    242     SliderThumbElement* thumbElement = sliderThumbElement();
    243     if (!thumbElement || !thumbElement->renderer())
    244         return 0;
    245 
    246     int position;
    247     if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
    248         position = p.y() - thumbElement->renderBox()->height() / 2;
    249     else
    250         position = p.x() - thumbElement->renderBox()->width() / 2;
    251    
    252     return max(0, min(position, trackSize()));
    253 }
    254 
    255 int RenderSlider::currentPosition()
    256 {
    257     SliderThumbElement* thumbElement = sliderThumbElement();
    258     ASSERT(thumbElement && thumbElement->renderer());
    259 
    260     if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
    261         return toRenderBox(thumbElement->renderer())->y() - contentBoxRect().y();
    262     return toRenderBox(thumbElement->renderer())->x() - contentBoxRect().x();
    263 }
    264 
    265 int RenderSlider::trackSize()
    266 {
    267     SliderThumbElement* thumbElement = sliderThumbElement();
    268     ASSERT(thumbElement && thumbElement->renderer());
    269 
    270     if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
    271         return contentHeight() - thumbElement->renderBox()->height();
    272     return contentWidth() - thumbElement->renderBox()->width();
    273 }
    274 
    275 void RenderSlider::forwardEvent(Event* event)
    276 {
    277     SliderThumbElement* thumbElement = sliderThumbElement();
    278     if (!thumbElement)
    279         return;
    280 
    281     if (event->isMouseEvent()) {
    282         MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
    283         if (event->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
    284             if (!mouseEventIsInThumb(mouseEvent)) {
    285                 IntPoint eventOffset = roundedIntPoint(absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
    286                 setValueForPosition(positionForOffset(eventOffset));
    287             }
    288         }
    289     }
    290 
    291     thumbElement->defaultEventHandler(event);
    292 }
    293 
    294184bool RenderSlider::inDragMode() const
    295185{
  • trunk/Source/WebCore/rendering/RenderSlider.h

    r75749 r76147  
    3535        virtual ~RenderSlider();
    3636
    37         void forwardEvent(Event*);
    3837        bool inDragMode() const;
    3938        IntRect thumbRect();
     
    5049        // SliderThumbElement and accessing sliderThumbElement should not be necessary in this class.
    5150        SliderThumbElement* sliderThumbElement() const;
    52         bool mouseEventIsInThumb(MouseEvent*);
    53         FloatPoint mouseEventOffsetToThumb(MouseEvent*);
    54 
    55         void setValueForPosition(int position);
    56         void setPositionFromValue();
    57         int positionForOffset(const IntPoint&);
    58 
    59         int currentPosition();
    6051
    6152        virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
    62 
    63         int trackSize();
    64 
    65         friend class SliderThumbElement;
    6653    };
    6754
Note: See TracChangeset for help on using the changeset viewer.