Bug 559993. Scroll the whole selection into view, not just the focus point when finding on a page. r=roc a=blocking-final+
authorTimothy Nikkel <tnikkel@gmail.com>
Wed, 24 Nov 2010 19:35:02 -0600
changeset 58206 015f5aa6ede2db5e8c376255c8686617f1668aaa
parent 58205 c6a2526886f959b6923e93aa5578945140dca1f9
child 58207 0a29ac059eb580261f1b9401161a4c095d0c1bec
push id17201
push usertnikkel@gmail.com
push dateThu, 25 Nov 2010 01:35:45 +0000
treeherdermozilla-central@0a29ac059eb5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, blocking-final
bugs559993
milestone2.0b8pre
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
Bug 559993. Scroll the whole selection into view, not just the focus point when finding on a page. r=roc a=blocking-final+
browser/base/content/test/Makefile.in
browser/base/content/test/browser_visibleFindSelection.js
content/base/public/nsISelectionController.idl
embedding/components/find/src/nsWebBrowserFind.cpp
layout/generic/nsSelection.cpp
toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -194,16 +194,17 @@ endif
                  browser_sanitize-timespans.js \
                  browser_sanitizeDialog.js \
                  browser_scope.js \
                  browser_selectTabAtIndex.js \
                  browser_tab_dragdrop2.js \
                  browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_owner.js \
+                 browser_visibleFindSelection.js \
                  browser_visibleTabs.js \
                  browser_visibleTabs_contextMenu.js \
                  browser_visibleTabs_bookmarkAllPages.js \
                  browser_visibleTabs_bookmarkAllTabs.js \
                  browser_visibleTabs_tabPreview.js \
                  bug592338.html \
                  discovery.html \
                  domplate_test.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_visibleFindSelection.js
@@ -0,0 +1,39 @@
+
+function test() {
+  waitForExplicitFinish();
+
+  let tab = gBrowser.addTab();
+  gBrowser.selectedTab = tab;
+  tab.linkedBrowser.addEventListener("load", function(aEvent) {
+    tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
+
+    ok(true, "Load listener called");
+    waitForFocus(onFocus, content);
+  }, true);
+
+  content.location = "data:text/html,<div style='position: absolute; left: 2200px; background: green; width: 200px; height: 200px;'>div</div><div style='position: absolute; left: 0px; background: red; width: 200px; height: 200px;'><span id='s'>div</span></div>";
+}
+
+function onFocus() {
+  EventUtils.synthesizeKey("f", { accelKey: true });
+  ok(gFindBarInitialized, "find bar is now initialized");
+
+  EventUtils.synthesizeKey("d", {});
+  EventUtils.synthesizeKey("i", {});
+  EventUtils.synthesizeKey("v", {});
+  // finds the div in the green box
+
+  EventUtils.synthesizeKey("g", { accelKey: true });
+  // finds the div in the red box
+
+  var rect = content.document.getElementById("s").getBoundingClientRect();
+  ok(rect.left >= 0, "scroll should include find result");
+
+  // clear the find bar
+  EventUtils.synthesizeKey("a", { accelKey: true });
+  EventUtils.synthesizeKey("VK_DELETE", { });
+
+  gFindBar.close();
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/content/base/public/nsISelectionController.idl
+++ b/content/base/public/nsISelectionController.idl
@@ -62,17 +62,18 @@ interface nsISelectionController : nsISe
    const short SELECTION_IME_CONVERTEDTEXT=16;
    const short SELECTION_IME_SELECTEDCONVERTEDTEXT=32;
    const short SELECTION_ACCESSIBILITY=64; // For accessibility API usage
    const short SELECTION_FIND=128;
    const short NUM_SELECTIONTYPES=9;
 
    const short SELECTION_ANCHOR_REGION = 0;
    const short SELECTION_FOCUS_REGION = 1;
-   const short NUM_SELECTION_REGIONS = 2;
+   const short SELECTION_WHOLE_SELECTION = 2;
+   const short NUM_SELECTION_REGIONS = 3;
 
    const short SELECTION_OFF = 0;
    const short SELECTION_HIDDEN =1;//>HIDDEN displays selection
    const short SELECTION_ON = 2;
    const short SELECTION_DISABLED = 3;
    const short SELECTION_ATTENTION = 4;
 
    /**
--- a/embedding/components/find/src/nsWebBrowserFind.cpp
+++ b/embedding/components/find/src/nsWebBrowserFind.cpp
@@ -446,17 +446,17 @@ void nsWebBrowserFind::SetSelectionAndSc
 
     // Scroll if necessary to make the selection visible:
     // Must be the last thing to do - bug 242056
 
     // After ScrollSelectionIntoView(), the pending notifications might be
     // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
     selCon->ScrollSelectionIntoView
       (nsISelectionController::SELECTION_NORMAL,
-       nsISelectionController::SELECTION_FOCUS_REGION,
+       nsISelectionController::SELECTION_WHOLE_SELECTION,
        nsISelectionController::SCROLL_SYNCHRONOUS);
   }
 }
 
 // Adapted from nsTextServicesDocument::GetDocumentContentRootNode
 nsresult nsWebBrowserFind::GetRootNode(nsIDOMDocument* aDomDoc,
                                        nsIDOMNode **aNode)
 {
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -193,19 +193,26 @@ public:
   NS_DECL_NSISELECTION
   NS_DECL_NSISELECTION2
   NS_DECL_NSISELECTION3
   NS_DECL_NSISELECTIONPRIVATE
 
   // utility methods for scrolling the selection into view
   nsresult      GetPresContext(nsPresContext **aPresContext);
   nsresult      GetPresShell(nsIPresShell **aPresShell);
-  // Returns the position of the region, and frame that that position is relative
-  // to. The 'position' is a zero-width rectangle.
+  // Returns a rect containing the selection region, and frame that that
+  // position is relative to. For SELECTION_ANCHOR_REGION or
+  // SELECTION_FOCUS_REGION the rect is a zero-width rectangle. For
+  // SELECTION_WHOLE_SELECTION the rect contains both the anchor and focus
+  // region rects.
   nsIFrame*     GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect *aRect);
+  // Returns the position of the region (SELECTION_ANCHOR_REGION or
+  // SELECTION_FOCUS_REGION only), and frame that that position is relative to.
+  // The 'position' is a zero-width rectangle.
+  nsIFrame*     GetSelectionEndPointGeometry(SelectionRegion aRegion, nsRect *aRect);
 
   nsresult      PostScrollSelectionIntoViewEvent(SelectionRegion aRegion, PRBool aFirstAncestorOnly);
   enum {
     SCROLL_SYNCHRONOUS = 1<<1,
     SCROLL_FIRST_ANCESTOR_ONLY = 1<<2,
     SCROLL_DO_FLUSH = 1<<3
   };
   // aDoFlush only matters if aIsSynchronous is true.  If not, we'll just flush
@@ -5504,16 +5511,62 @@ nsTypedSelection::GetSelectionAnchorGeom
 {
   if (!mFrameSelection)
     return nsnull;  // nothing to do
 
   NS_ENSURE_TRUE(aRect, nsnull);
 
   aRect->SetRect(0, 0, 0, 0);
 
+  switch (aRegion) {
+    case nsISelectionController::SELECTION_ANCHOR_REGION:
+    case nsISelectionController::SELECTION_FOCUS_REGION:
+      return GetSelectionEndPointGeometry(aRegion, aRect);
+      break;
+    case nsISelectionController::SELECTION_WHOLE_SELECTION:
+      break;
+    default:
+      return nsnull;
+  }
+
+  NS_ASSERTION(aRegion == nsISelectionController::SELECTION_WHOLE_SELECTION,
+    "should only be SELECTION_WHOLE_SELECTION here");
+
+  nsRect anchorRect;
+  nsIFrame* anchorFrame = GetSelectionEndPointGeometry(
+    nsISelectionController::SELECTION_ANCHOR_REGION, &anchorRect);
+  if (!anchorFrame)
+    return nsnull;
+
+  nsRect focusRect;
+  nsIFrame* focusFrame = GetSelectionEndPointGeometry(
+    nsISelectionController::SELECTION_FOCUS_REGION, &focusRect);
+  if (!focusFrame)
+    return nsnull;
+
+  NS_ASSERTION(anchorFrame->PresContext() == focusFrame->PresContext(),
+    "points of selection in different documents?");
+  // make focusRect relative to anchorFrame
+  focusRect += focusFrame->GetOffsetTo(anchorFrame);
+
+  aRect->UnionRectIncludeEmpty(anchorRect, focusRect);
+  return anchorFrame;
+}
+
+nsIFrame *
+nsTypedSelection::GetSelectionEndPointGeometry(SelectionRegion aRegion,
+                                               nsRect *aRect)
+{
+  if (!mFrameSelection)
+    return nsnull;  // nothing to do
+
+  NS_ENSURE_TRUE(aRect, nsnull);
+
+  aRect->SetRect(0, 0, 0, 0);
+
   nsINode    *node       = nsnull;
   PRInt32     nodeOffset = 0;
   nsIFrame   *frame      = nsnull;
 
   switch (aRegion) {
     case nsISelectionController::SELECTION_ANCHOR_REGION:
       node       = GetAnchorNode();
       nodeOffset = GetAnchorOffset();
--- a/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/src/nsTypeAheadFind.cpp
@@ -557,17 +557,17 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
       // ATTENTION, or when we MoveFocus() and the selection is not on a
       // link, we'll blur, which will lose the ATTENTION.
       if (selectionController) {
         // Beware! This may flush notifications via synchronous
         // ScrollSelectionIntoView.
         SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ATTENTION);
         selectionController->ScrollSelectionIntoView(
           nsISelectionController::SELECTION_NORMAL, 
-          nsISelectionController::SELECTION_FOCUS_REGION,
+          nsISelectionController::SELECTION_WHOLE_SELECTION,
           nsISelectionController::SCROLL_SYNCHRONOUS);
       }
 
       mCurrentWindow = window;
       *aResult = hasWrapped ? FIND_WRAPPED : FIND_FOUND;
       return NS_OK;
     }