Bug 916481 - Make Finder.jsm send back the selection rect of the find result [r=evilpie,emtwo]

This commit is contained in:
Matt Brubeck 2014-01-09 07:58:26 -08:00
parent 6ab25a7c7b
commit 9ec3d0aeae
5 changed files with 104 additions and 9 deletions

View File

@ -171,8 +171,11 @@ var FindHelperUI = {
this.searchAgain(this._searchString, false);
},
onFindResult: function(aResult, aFindBackwards, aLinkURL) {
onFindResult: function(aResult, aFindBackwards, aLinkURL, aRect) {
this._status = aResult;
if (aRect) {
this._zoom(aRect, Browser.selectedBrowser.contentDocumentHeight);
}
this.updateCommands();
},

View File

@ -5,6 +5,7 @@
<title>Find bar tests</title>
</head>
<body>
<p>Find bar tests</title>
<p>Find bar tests</p>
<p style="position: absolute; bottom: 0;">bottom</p>
</body>
</html>

View File

@ -88,3 +88,45 @@ gTests.push({
Browser.closeTab(tab);
}
});
gTests.push({
desc: "Text at bottom of screen is not obscured by findbar",
run: function() {
let textbox = document.getElementById("findbar-textbox");
let tab = yield addTab(chromeRoot + "browser_findbar.html");
yield waitForCondition(() => BrowserUI.ready);
is(Elements.findbar.isShowing, false, "Find bar is hidden by default");
FindHelperUI.show();
yield waitForCondition(() => FindHelperUI.isActive);
EventUtils.sendString("bottom");
let event = yield waitForEvent(window, "MozDeckOffsetChanged");
ok(!(event instanceof Error), "MozDeckOffsetChanged received (1)");
ok(event.detail > 0, "Browser deck shifted upward");
textbox.select();
EventUtils.sendString("bar");
event = yield waitForEvent(window, "MozDeckOffsetChanged");
ok(!(event instanceof Error), "MozDeckOffsetChanged received (2)");
is(event.detail, 0, "Browser deck shifted back to normal");
textbox.select();
EventUtils.sendString("bottom");
event = yield waitForEvent(window, "MozDeckOffsetChanged");
ok(!(event instanceof Error), "MozDeckOffsetChanged received (3)");
ok(event.detail > 0, "Browser deck shifted upward again");
let waitForDeckOffset = waitForEvent(window, "MozDeckOffsetChanged");
let waitForTransitionEnd = waitForEvent(Elements.findbar, "transitionend");
FindHelperUI.hide();
event = yield waitForDeckOffset;
ok(!(event instanceof Error), "MozDeckOffsetChanged received (4)");
is(event.detail, 0, "Browser deck shifted back to normal when findbar hides");
// Cleanup.
yield waitForTransitionEnd;
Browser.closeTab(tab);
}
});

View File

@ -9,7 +9,8 @@ const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const Services = Cu.import("resource://gre/modules/Services.jsm").Services;
Cu.import("resource://gre/modules/Geometry.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function Finder(docShell) {
this._fastFind = Cc["@mozilla.org/typeaheadfind;1"].createInstance(Ci.nsITypeAheadFind);
@ -55,8 +56,10 @@ Finder.prototype = {
linkURL = this._textToSubURIService.unEscapeURIForUI(docCharset, foundLink.href);
}
let rect = this._getResultRect();
for (let l of this._listeners) {
l.onFindResult(aResult, aFindBackwards, linkURL);
l.onFindResult(aResult, aFindBackwards, linkURL, rect);
}
},
@ -186,6 +189,48 @@ Finder.prototype = {
return this._docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
},
/**
* Get the bounding selection rect in CSS px relative to the origin of the
* top-level content document.
*/
_getResultRect: function () {
let topWin = this._getWindow();
let win = this._fastFind.currentWindow;
if (!win)
return null;
let selection = win.getSelection();
if (!selection.rangeCount || selection.isCollapsed) {
// The selection can be into an input or a textarea element.
let nodes = win.document.querySelectorAll("input, textarea");
for (let node of nodes) {
if (node instanceof Ci.nsIDOMNSEditableElement && node.editor) {
let sc = node.editor.selectionController;
selection = sc.getSelection(Ci.nsISelectionController.SELECTION_NORMAL);
if (selection.rangeCount && !selection.isCollapsed) {
break;
}
}
}
}
let utils = topWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let scrollX = {}, scrollY = {};
utils.getScrollXY(false, scrollX, scrollY);
for (let frame = win; frame != topWin; frame = frame.parent) {
let rect = frame.frameElement.getBoundingClientRect();
let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
scrollX.value += rect.left + parseInt(left, 10);
scrollY.value += rect.top + parseInt(top, 10);
}
let rect = Rect.fromRect(selection.getRangeAt(0).getBoundingClientRect());
return rect.translate(scrollX.value, scrollY.value);
},
_outlineLink: function (aDrawOutline) {
let foundLink = this._fastFind.foundLink;

View File

@ -35,7 +35,7 @@ RemoteFinder.prototype = {
for (let l of this._listeners) {
l.onFindResult(aMessage.data.result, aMessage.data.findBackwards,
aMessage.data.linkURL);
aMessage.data.linkURL, aMessage.data.rect);
}
},
@ -108,10 +108,14 @@ RemoteFinderListener.prototype = {
"Finder:KeyPress"
],
onFindResult: function (aResult, aFindBackwards, aLinkURL) {
let data = { result: aResult, findBackwards: aFindBackwards,
linkURL: aLinkURL, searchString: this._finder.searchString };
this._global.sendAsyncMessage("Finder:Result", data);
onFindResult: function (aResult, aFindBackwards, aLinkURL, aRect) {
this._global.sendAsyncMessage("Finder:Result", {
result: aResult,
findBackwards: aFindBackwards,
linkURL: aLinkURL,
rect: aRect,
searchString: this._finder.searchString,
});
},
//XXXmikedeboer-20131016: implement |shouldFocusContent| here to mitigate