dragndrop: Allow drag'n'drop to start from elements inside a shadow root (Bug 1521471) r=emilio
authorArtur Signell <artur@vaadin.com>
Wed, 08 May 2019 18:30:45 +0000
changeset 531921 23e432bdaf62c88b10c45a4953a8ea6206f5c9bf
parent 531920 e8dbcc5c516f05fe34f90efaf6fd199118979012
child 531922 57598d1d033f5086f6f53def5960761757fa28fe
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1521471
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
dragndrop: Allow drag'n'drop to start from elements inside a shadow root (Bug 1521471) r=emilio Before this change, only elements inside the shadow root tree were scanned for the draggable=true attribute. We now check the flattened tree instead so an element inside a shadow root can start a drag for an element containing the shadow root. Differential Revision: https://phabricator.services.mozilla.com/D30365
dom/events/test/test_dragstart.html
layout/generic/nsFrame.cpp
--- a/dom/events/test/test_dragstart.html
+++ b/dom/events/test/test_dragstart.html
@@ -63,38 +63,48 @@ function afterDragTests()
 
 //  disable testing input dragging for now, as it doesn't seem to be testable 
 //  draggable = $("input");
 //  draggable.setSelectionRange(0, 4);
 //  synthesizeMouse(draggable, 8, 8, { type: "mousedown" });
 //  synthesizeMouse(draggable, 15, 15, { type: "mousemove" });
 //  sendMouseEventsForDrag("input");
 
+  // draggable element inside a shadow root
+  sendMouseEventsForShadowRootDrag();
+
   // next, check if the draggable attribute can be used to adjust the drag target
   gDragInfo = { target: $("dragtrue"), testid: "draggable true node" };
   sendMouseEventsForDrag("dragtrue");
   gDragInfo = { target: $("dragtrue"), testid: "draggable true child" };
   sendMouseEventsForDrag("spantrue");
   gDragInfo = { target: $("dragfalse").firstChild, testid: "draggable false node" };
   sendMouseEventsForDrag("dragfalse");
   gDragInfo = { target: $("spanfalse").firstChild, testid: "draggable false child" };
   sendMouseEventsForDrag("spanfalse");
 
   synthesizeMouse(draggable, 12, 12, { type: "mouseup" });
-  if (gExtraDragTests == 4)
+  if (gExtraDragTests == 5)
     SimpleTest.finish();
 }
 
 function sendMouseEventsForDrag(nodeid)
 {
   var draggable = $(nodeid);
   synthesizeMouse(draggable, 3, 3, { type: "mousedown" });
   synthesizeMouse(draggable, 10, 10, { type: "mousemove" });
   synthesizeMouse(draggable, 12, 12, { type: "mousemove" });
 }
+function sendMouseEventsForShadowRootDrag()
+{
+  var draggable = $("shadow_host_containing_draggable").shadowRoot.firstElementChild;
+  synthesizeMouse(draggable, 3, 3, { type: "mousedown" });
+  synthesizeMouse(draggable, 10, 10, { type: "mousemove" });
+  synthesizeMouse(draggable, 12, 12, { type: "mousemove" });
+}
 
 function doDragStartSelection(event)
 {
   is(event.type, "dragstart", "dragstart event type");
   is(event.target, $("draggable").firstChild, "dragstart event target");
   is(event.bubbles, true, "dragstart event bubbles");
   is(event.cancelable, true, "dragstart event cancelable");
 
@@ -449,16 +459,28 @@ function doDragStartInput(event)
   checkTypes(dt, ["text/plain"], 0, "initial input");
 
   is(SpecialPowers.wrap(dt).mozItemCount, 1, "initial input item count");
 //  is(dt.getData("text/plain"), "Text", "input text/plain");
 
 //  event.preventDefault();
 }
 
+
+function doDragStartInShadowRoot(event)
+{
+  is(event.type, "dragstart", "shadow root dragstart event type");
+  is(event.target, $("shadow_host_containing_draggable"), "shadow root dragstart event target");
+  is(event.bubbles, true, "shadow root dragstart event bubbles");
+  is(event.cancelable, true, "shadow root dragstart event cancelable");
+
+  event.preventDefault();
+
+  gExtraDragTests++;
+}
 function doDragStartSynthetic(event)
 {
   is(event.type, "dragstart", "synthetic dragstart event type");
 
   var dt = event.dataTransfer;
   todo(dt instanceof DataTransfer, "synthetic dragstart dataTransfer is DataTransfer");
 //  Uncomment next line once the todo instanceof above is fixed.
 //  checkTypes(dt, [], 0, "synthetic dragstart");
@@ -591,10 +613,18 @@ function expectError(fn, eid, testid)
   </div>
 </div>
 
 <!--iframe src="http://www.mozilla.org" width="400" height="400"></iframe-->
 
 <div id="synthetic" ondragstart="doDragStartSynthetic(event)">Synthetic Event Dispatch</div>
 <div id="synthetic2" ondragover="doDragOverSynthetic(event)">Synthetic Event Dispatch</div>
 
+<div draggable="true" id="shadow_host_containing_draggable"></div>
+
+<script>
+shadow_host_containing_draggable.attachShadow({ mode: 'open' }).innerHTML = 
+`<span>Inside shadow root</span>`;
+shadow_host_containing_draggable.addEventListener("dragstart", doDragStartInShadowRoot);
+
+</script>
 </body>
 </html>
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4244,17 +4244,17 @@ nsFrame::HandlePress(nsPresContext* aPre
   // weaaak. only the editor can display frame selection not just text and
   // images
   isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
 
   WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
 
   if (!mouseEvent->IsAlt()) {
     for (nsIContent* content = mContent; content;
-         content = content->GetParent()) {
+         content = content->GetFlattenedTreeParent()) {
       if (nsContentUtils::ContentIsDraggable(content) &&
           !content->IsEditable()) {
         // coordinate stuff is the fix for bug #55921
         if ((mRect - GetPosition())
                 .Contains(nsLayoutUtils::GetEventCoordinatesRelativeTo(
                     mouseEvent, this))) {
           return NS_OK;
         }