Bug 670081 Cannot scroll any scrollable elements by drag if non-scrollable element captures mouse events r=roc
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 12 Jul 2011 10:13:24 +0900
changeset 73055 8b1328c6045264dbf8ff7383d97004d0afb64c4a
parent 73054 ec45982514f4f109f0a4e552e95d700ab0f4d28d
child 73056 c05f6481b84a04568c9a9febdbbbab52a59c4586
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs670081
milestone8.0a1
Bug 670081 Cannot scroll any scrollable elements by drag if non-scrollable element captures mouse events r=roc
layout/generic/nsFrame.cpp
layout/generic/test/window_selection_scrolling.html
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2604,28 +2604,28 @@ nsFrame::ExpandSelectionByMouseMove(nsFr
   if (!capturingContent) {
     return NS_OK;  // The capture was canceled.
   }
   nsIContent* selectionRoot =
     GetSelectionRootContentForCapturingContent(aPresShell, capturingContent);
 
   nsIScrollableFrame* scrollableFrame =
     FindNearestScrollableFrameForSelection(this, selectionRoot);
-  // If a non-scrollable content captures by script, we may not be able to find
-  // any scrollable frame.
+  // If a non-scrollable content captures by script and there is no scrollable
+  // frame between the selection root and this, we don't need to do anymore.
   if (!scrollableFrame) {
     return NS_OK;
   }
 
   const PRUint32 kAutoScrollTimerDelay = 30;
 
   if (!handleTableSelection) {
     nsIScrollableFrame* selectionRootScrollableFrame =
-      FindNearestScrollableFrameForSelection(selectionRoot->GetPrimaryFrame());
-    NS_ENSURE_TRUE(selectionRootScrollableFrame, NS_OK);
+      FindNearestScrollableFrameForSelection(selectionRoot->GetPrimaryFrame(),
+                                             selectionRoot);
     while (scrollableFrame) {
       // We don't need to scroll the selection root frame when the mouse cursor
       // is on its edge because selection root frame will be scrolled when the
       // mouse cursor is outside of the frame.  And user may want slower scroll
       // than the "on edge" scroll speed.
       if (selectionRootScrollableFrame == scrollableFrame) {
         break;
       }
--- a/layout/generic/test/window_selection_scrolling.html
+++ b/layout/generic/test/window_selection_scrolling.html
@@ -89,16 +89,17 @@ 15</textarea>
   <iframe id="iframe2"
     src="data:text/html,<div style='height:400px; width:400px;'></div>"></iframe>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var body = document.body;
 
+var div_container = document.getElementById("container");
 var div_fixed = document.getElementById("fixed");
 var div_subframe1 = document.getElementById("static_overflow");
 var div_subframe2 = document.getElementById("static_overflow_inner");
 var iframe = document.getElementById("iframe");
 var input = document.getElementById("input");
 var textarea = document.getElementById("textarea");
 var iframe2 = document.getElementById("iframe2");
 
@@ -685,16 +686,81 @@ var gTests = [
     },
     resetAllElementsBeforeTest: false,
     testTarget: function () { return div_subframe1; },
     expectedScrollTop: function () { return 0; },
     expectedScrollLeft: function () { return 0; },
     scrollIsExpected: true,
   },
 
+  // Scroll subframe1 on its edge when container (non-scrollable element) is
+  // capturing mouse events
+  //   visible scrollable elements: body, div_subframe1
+  {
+    description: "The scrollable div element (subframe1) should be scrolled by moving mouse from subframe1 to the right edge of the div element (container is capturing mouse events)",
+    prepare: function () {
+      div_subframe1.style.display = "block";
+      div_subframe1.onmousedown = function () { div_container.setCapture(); }
+    },
+    test: function () {
+      synthesizeMouse(div_subframe1, 50, 50, { type: "mousedown" });
+      synthesizeMouse(div_subframe1, div_subframe1.clientWidth - 10, 50,
+                      { type: "mousemove" });
+      return true;
+    },
+    resetAllElementsBeforeTest: true,
+    testTarget: function () { return div_subframe1; },
+    expectedScrollTop: function () { return 0; },
+    expectedScrollLeft: function () { return getScrollRightMost(div_subframe1); },
+    scrollIsExpected: true,
+  },
+
+  {
+    description: "The scrollable div element (subframe1) should be scrolled by moving mouse from subframe1 to the left edge of the div element (container is capturing mouse events)",
+    test: function () {
+      synthesizeMouse(div_subframe1, 50, 50, { type: "mousedown" });
+      synthesizeMouse(div_subframe1, 10, 50, { type: "mousemove" });
+      return true;
+    },
+    resetAllElementsBeforeTest: false,
+    testTarget: function () { return div_subframe1; },
+    expectedScrollTop: function () { return 0; },
+    expectedScrollLeft: function () { return 0; },
+    scrollIsExpected: true,
+  },
+
+  {
+    description: "The scrollable div element (subframe1) should be scrolled by moving mouse from subframe1 to the bottom edge of the div element (container is capturing mouse events)",
+    test: function () {
+      synthesizeMouse(div_subframe1, 50, 50, { type: "mousedown" });
+      synthesizeMouse(div_subframe1, 50, div_subframe1.clientHeight - 10,
+                      { type: "mousemove" });
+      return true;
+    },
+    resetAllElementsBeforeTest: false,
+    testTarget: function () { return div_subframe1; },
+    expectedScrollTop: function () { return getScrollBottomMost(div_subframe1); },
+    expectedScrollLeft: function () { return 0; },
+    scrollIsExpected: true,
+  },
+
+  {
+    description: "The scrollable div element (subframe1) should be scrolled by moving mouse from subframe1 to the top edge of the div element (container is capturing mouse events)",
+    test: function () {
+      synthesizeMouse(div_subframe1, 50, 50, { type: "mousedown" });
+      synthesizeMouse(div_subframe1, 50, 10, { type: "mousemove" });
+      return true;
+    },
+    resetAllElementsBeforeTest: false,
+    testTarget: function () { return div_subframe1; },
+    expectedScrollTop: function () { return 0; },
+    expectedScrollLeft: function () { return 0; },
+    scrollIsExpected: true,
+  },
+
   // Scroll subframe1 even if subframe2 is moved under the cursor
   //   visible scrollable elements: body, div_subframe1, div_subframe2
   {
     description: "The scrollable div element (subframe1) should be scrolled even if another scrollable div element (subframe2) is moved under the cursor #1",
     prepare: function () {
       div_subframe1.style.display = "block";
       div_subframe2.style.display = "block";
     },