+2011-05-28 Jer Noble <jer.noble@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Mouse clicks propagate outside full-screen media controls.
+ https://bugs.webkit.org/show_bug.cgi?id=61689
+
+ Mouse click events are propagating out of the media controls, so mouse click
+ listeners registered on the video element are getting fired when the user
+ clicks on media controller buttons. By default, block propagation of click
+ events from MediaControlElements by overriding preDispatchEventHandler, and
+ convert all instances of defaultEventHandler -> preDispatchEventHandler. Change
+ all calls of event->setDefaultHandled() to event->stopPropagation().
+
+ * html/shadow/MediaControlElements.cpp:
+ (WebCore::MediaControlElement::preDispatchEventHandler): Added. Block
+ propagation of all mouse click events.
+ (WebCore::MediaControlVolumeSliderContainerElement::preDispatchEventHandler):
+ Renamed from setDefaultHandled.
+ (WebCore::MediaControlMuteButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlPanelMuteButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlPlayButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlSeekButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlRewindButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlReturnToRealtimeButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlToggleClosedCaptionsButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlTimelineElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlVolumeSliderElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlFullscreenButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlFullscreenVolumeMinButtonElement::preDispatchEventHandler): Ditto.
+ (WebCore::MediaControlFullscreenVolumeMaxButtonElement::preDispatchEventHandler): Ditto.
+ * html/shadow/MediaControlElements.h:
+
2011-05-28 Gavin Peters <gavinp@chromium.org>
Reviewed by Adam Barth.
{
}
+void* MediaControlElement::preDispatchEventHandler(Event* event)
+{
+ if (event->type() == eventNames().clickEvent)
+ event->stopPropagation();
+
+ return 0;
+}
+
static const String& displayString()
{
DEFINE_STATIC_LOCAL(String, s, ("display"));
return new (arena) RenderMediaVolumeSliderContainer(this);
}
-void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event* event)
+void* MediaControlVolumeSliderContainerElement::preDispatchEventHandler(Event* event)
{
if (!event->isMouseEvent() || event->type() != eventNames().mouseoutEvent)
- return;
+ return 0;
// Poor man's mouseleave event detection.
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
if (!mouseEvent->relatedTarget() || !mouseEvent->relatedTarget()->toNode())
- return;
+ return 0;
if (this->containsIncludingShadowDOM(mouseEvent->relatedTarget()->toNode()))
- return;
+ return 0;
hide();
+ return 0;
}
{
}
-void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
+void* MediaControlMuteButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
mediaElement()->setMuted(!mediaElement()->muted());
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
void MediaControlMuteButtonElement::changedMute()
return button.release();
}
-void MediaControlPanelMuteButtonElement::defaultEventHandler(Event* event)
+void* MediaControlPanelMuteButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().mouseoverEvent)
m_controls->showVolumeSlider();
- MediaControlMuteButtonElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlPanelMuteButtonElement::shadowPseudoId() const
return button.release();
}
-void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
+void* MediaControlPlayButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
mediaElement()->togglePlayState();
updateDisplayType();
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
void MediaControlPlayButtonElement::updateDisplayType()
{
}
-void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
+void* MediaControlSeekButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().mousedownEvent) {
if (Frame* frame = document()->frame()) {
}
mediaElement()->pause(event->fromUserGesture());
m_seekTimer.startRepeating(cSeekRepeatDelay);
- event->setDefaultHandled();
+ event->stopPropagation();
} else if (event->type() == eventNames().mouseupEvent) {
if (m_capturing)
if (Frame* frame = document()->frame()) {
}
m_seekTimer.stop();
m_seeking = false;
- event->setDefaultHandled();
+ event->stopPropagation();
}
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
return button.release();
}
-void MediaControlRewindButtonElement::defaultEventHandler(Event* event)
+void* MediaControlRewindButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
mediaElement()->rewind(30);
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlRewindButtonElement::shadowPseudoId() const
return button.release();
}
-void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event)
+void* MediaControlReturnToRealtimeButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
mediaElement()->returnToRealtime();
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlReturnToRealtimeButtonElement::shadowPseudoId() const
return button.release();
}
-void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
+void* MediaControlToggleClosedCaptionsButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
mediaElement()->setClosedCaptionsVisible(!mediaElement()->closedCaptionsVisible());
setChecked(mediaElement()->closedCaptionsVisible());
updateDisplayType();
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
return timeline.release();
}
-void MediaControlTimelineElement::defaultEventHandler(Event* event)
+void* MediaControlTimelineElement::preDispatchEventHandler(Event* event)
{
// Left button is 0. Rejects mouse events not from left button.
if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
- return;
+ return 0;
if (!attached())
- return;
+ return 0;
if (event->type() == eventNames().mousedownEvent)
mediaElement()->beginScrubbing();
MediaControlInputElement::defaultEventHandler(event);
if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
- return;
+ return 0;
float time = narrowPrecisionToFloat(value().toDouble());
if (time != mediaElement()->currentTime()) {
if (event->type() == eventNames().mouseupEvent)
mediaElement()->endScrubbing();
+ return 0;
}
void MediaControlTimelineElement::setPosition(float currentTime)
return slider.release();
}
-void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
+void* MediaControlVolumeSliderElement::preDispatchEventHandler(Event* event)
{
// Left button is 0. Rejects mouse events not from left button.
if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
- return;
+ return 0;
if (!attached())
- return;
+ return 0;
MediaControlInputElement::defaultEventHandler(event);
if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
- return;
+ return 0;
float volume = narrowPrecisionToFloat(value().toDouble());
if (volume != mediaElement()->volume()) {
mediaElement()->setVolume(volume, ec);
ASSERT(!ec);
}
+ return 0;
}
void MediaControlVolumeSliderElement::setVolume(float volume)
return button.release();
}
-void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
+void* MediaControlFullscreenButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
#if ENABLE(FULLSCREEN_API)
} else
#endif
mediaElement()->enterFullscreen();
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const
return button.release();
}
-void MediaControlFullscreenVolumeMinButtonElement::defaultEventHandler(Event* event)
+void* MediaControlFullscreenVolumeMinButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
ExceptionCode code = 0;
mediaElement()->setVolume(0, code);
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlFullscreenVolumeMinButtonElement::shadowPseudoId() const
return button.release();
}
-void MediaControlFullscreenVolumeMaxButtonElement::defaultEventHandler(Event* event)
+void* MediaControlFullscreenVolumeMaxButtonElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
ExceptionCode code = 0;
mediaElement()->setVolume(1, code);
- event->setDefaultHandled();
+ event->stopPropagation();
}
- HTMLInputElement::defaultEventHandler(event);
+ return 0;
}
const AtomicString& MediaControlFullscreenVolumeMaxButtonElement::shadowPseudoId() const
MediaControlElement(HTMLMediaElement*);
private:
+ virtual void *preDispatchEventHandler(Event*);
virtual bool isMediaControlElement() const { return true; }
HTMLMediaElement* m_mediaElement;
private:
MediaControlVolumeSliderContainerElement(HTMLMediaElement*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
virtual MediaControlElementType displayType() const;
virtual const AtomicString& shadowPseudoId() const;
};
protected:
MediaControlMuteButtonElement(HTMLMediaElement*, MediaControlElementType);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
private:
MediaControlPanelMuteButtonElement(HTMLMediaElement*, MediaControls*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
virtual const AtomicString& shadowPseudoId() const;
MediaControls* m_controls;
public:
static PassRefPtr<MediaControlPlayButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
virtual void updateDisplayType();
private:
class MediaControlSeekButtonElement : public MediaControlInputElement {
public:
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
protected:
MediaControlSeekButtonElement(HTMLMediaElement*, MediaControlElementType);
public:
static PassRefPtr<MediaControlRewindButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
MediaControlRewindButtonElement(HTMLMediaElement*);
public:
static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
MediaControlReturnToRealtimeButtonElement(HTMLMediaElement*);
public:
static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
virtual void updateDisplayType();
private:
public:
static PassRefPtr<MediaControlTimelineElement> create(HTMLMediaElement*, MediaControls*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
void setPosition(float);
void setDuration(float);
public:
static PassRefPtr<MediaControlVolumeSliderElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
void setVolume(float);
protected:
public:
static PassRefPtr<MediaControlFullscreenButtonElement> create(HTMLMediaElement*, MediaControls*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
MediaControlFullscreenButtonElement(HTMLMediaElement*, MediaControls*);
public:
static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
MediaControlFullscreenVolumeMinButtonElement(HTMLMediaElement*);
public:
static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(HTMLMediaElement*);
- virtual void defaultEventHandler(Event*);
+ virtual void *preDispatchEventHandler(Event*);
private:
MediaControlFullscreenVolumeMaxButtonElement(HTMLMediaElement*);