Changeset 173631 in webkit


Ignore:
Timestamp:
Sep 15, 2014 2:47:18 PM (10 years ago)
Author:
jer.noble@apple.com
Message:

Videos with controls enabled never receive 'dragstart' events.
https://bugs.webkit.org/show_bug.cgi?id=136837

Reviewed by Simon Fraser.

When initiating a drag, the DragController checks whether the hit-tested element at a
drag location is a child of the drag source, and bails if early if that is not the case.
For a <video> element with controls, the hit-tested element is an element within the
<video> element's Shadow DOM. Because the DragController uses a method which does not
take Shadow DOM into account when determining a child-parent relationship, this test fails
and all drag operations fail as well.

For <video> elements only, when testing whether the drag source is an ancestor of the
hit-tested element, use containsIncludingShadowDOM() instead of contains(). To ensure that
the controls are still usable when a drag listener is active on a <video> element, mark
the controls as a draggable element, but simply call preventDefault() in the controls'
'dragstart' handler, ensuring the timeline and volume controls are themselves still draggable.

  • Modules/mediacontrols/mediaControlsApple.css:

(audio::-webkit-media-controls-panel):

  • Modules/mediacontrols/mediaControlsApple.js:

(Controller.prototype.createControls):
(Controller.prototype.handlePanelDragStart):

  • page/DragController.cpp:

(WebCore::DragController::startDrag):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r173630 r173631  
     12014-09-15  Jer Noble  <jer.noble@apple.com>
     2
     3        Videos with controls enabled never receive 'dragstart' events.
     4        https://bugs.webkit.org/show_bug.cgi?id=136837
     5
     6        Reviewed by Simon Fraser.
     7
     8        When initiating a drag, the DragController checks whether the hit-tested element at a
     9        drag location is a child of the drag source, and bails if early if that is not the case.
     10        For a <video> element with controls, the hit-tested element is an element within the
     11        <video> element's Shadow DOM. Because the DragController uses a method which does not
     12        take Shadow DOM into account when determining a child-parent relationship, this test fails
     13        and all drag operations fail as well.
     14
     15        For <video> elements only, when testing whether the drag source is an ancestor of the
     16        hit-tested element, use containsIncludingShadowDOM() instead of contains(). To ensure that
     17        the controls are still usable when a drag listener is active on a <video> element, mark
     18        the controls as a draggable element, but simply call preventDefault() in the controls'
     19        'dragstart' handler, ensuring the timeline and volume controls are themselves still draggable.
     20
     21        * Modules/mediacontrols/mediaControlsApple.css:
     22        (audio::-webkit-media-controls-panel):
     23        * Modules/mediacontrols/mediaControlsApple.js:
     24        (Controller.prototype.createControls):
     25        (Controller.prototype.handlePanelDragStart):
     26        * page/DragController.cpp:
     27        (WebCore::DragController::startDrag):
     28
    1292014-09-15  Roger Fong  <roger_fong@apple.com>
    230
  • trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css

    r171593 r173631  
    8181    line-height: 25px;
    8282    -webkit-user-select: none;
     83    -webkit-user-drag: element;
    8384    background-color: transparent;
    8485    background-image: -webkit-linear-gradient(top,
  • trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js

    r171593 r173631  
    297297        this.listenFor(panel, 'click', this.handlePanelClick);
    298298        this.listenFor(panel, 'dblclick', this.handlePanelClick);
     299        this.listenFor(panel, 'dragstart', this.handlePanelDragStart);
    299300
    300301        var rewindButton = this.controls.rewindButton = document.createElement('button');
     
    698699    },
    699700
     701    handlePanelDragStart: function(event)
     702    {
     703        // Prevent drags in the panel from triggering a drag event on the <video> element.
     704        event.preventDefault();
     705    },
     706
    700707    handleRewindButtonClicked: function(event)
    701708    {
  • trunk/Source/WebCore/page/DragController.cpp

    r172948 r173631  
    722722
    723723    HitTestResult hitTestResult = src.eventHandler().hitTestResultAtPoint(dragOrigin, HitTestRequest::ReadOnly | HitTestRequest::Active);
    724     if (!state.source->contains(hitTestResult.innerNode()))
     724
     725    // FIXME(136836): Investigate whether all elements should use the containsIncludingShadowDOM() path here.
     726    bool includeShadowDOM = state.source->isMediaElement();
     727    bool sourceContainsHitNode;
     728    if (includeShadowDOM)
     729        sourceContainsHitNode = state.source->contains(hitTestResult.innerNode());
     730    else
     731        sourceContainsHitNode = state.source->containsIncludingShadowDOM(hitTestResult.innerNode());
     732
     733    if (!sourceContainsHitNode)
    725734        // The original node being dragged isn't under the drag origin anymore... maybe it was
    726735        // hidden or moved out from under the cursor. Regardless, we don't want to start a drag on
Note: See TracChangeset for help on using the changeset viewer.