Bug 673037 - Allow selecting text in frames. r=mfinkle

This commit is contained in:
Wes Johnston 2011-07-28 11:01:03 -07:00
Родитель 5ce917a794
Коммит 9896e0a8cf
1 изменённых файлов: 37 добавлений и 10 удалений

Просмотреть файл

@ -1332,6 +1332,7 @@ TouchEventHandler.init();
var SelectionHandler = {
cache: {},
selectedText: "",
contentWindow: null,
init: function() {
addMessageListener("Browser:SelectionStart", this);
@ -1348,13 +1349,34 @@ var SelectionHandler = {
case "Browser:SelectionStart": {
this.selectedText = "";
// if this is an iframe, dig down to find the document that was clicked
let x = json.x;
let y = json.y;
let offsetX = 0;
let offsetY = 0;
let elem = utils.elementFromPoint(x, y, true, false);
while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
// adjust client coordinates' origin to be top left of iframe viewport
let rect = elem.getBoundingClientRect();
scrollOffset = ContentScroll.getScrollOffset(elem.ownerDocument.defaultView);
offsetX += rect.left;
x -= rect.left;
offsetY += rect.top + scrollOffset.y;
y -= rect.top + scrollOffset.y;
utils = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
elem = utils.elementFromPoint(x, y, true, false);
}
let contentWindow = elem.ownerDocument.defaultView;
let currentDocShell = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
// Position the caret using a fake mouse click
utils.sendMouseEventToWindow("mousedown", json.x - scrollOffset.x, json.y - scrollOffset.y, 0, 1, 0, true);
utils.sendMouseEventToWindow("mouseup", json.x - scrollOffset.x, json.y - scrollOffset.y, 0, 1, 0, true);
utils.sendMouseEventToWindow("mousedown", x - scrollOffset.x, y - scrollOffset.y, 0, 1, 0, true);
utils.sendMouseEventToWindow("mouseup", x - scrollOffset.x, y - scrollOffset.y, 0, 1, 0, true);
// Select the word nearest the caret
try {
let selcon = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).QueryInterface(Ci.nsISelectionController);
let selcon = currentDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).QueryInterface(Ci.nsISelectionController);
selcon.wordMove(false, false);
selcon.wordMove(true, true);
} catch(e) {
@ -1363,7 +1385,7 @@ var SelectionHandler = {
}
// Find the selected text rect and send it back so the handles can position correctly
let selection = content.getSelection();
let selection = contentWindow.getSelection();
if (selection.rangeCount == 0)
return;
@ -1384,13 +1406,14 @@ var SelectionHandler = {
let rects = range.getClientRects();
for (let i=0; i<rects.length; i++) {
if (i == 0) {
this.cache.start.x = rects[i].left + scrollOffset.x;
this.cache.start.y = rects[i].bottom + scrollOffset.y;
this.cache.start.x = rects[i].left + offsetX;
this.cache.start.y = rects[i].bottom + offsetY;
}
this.cache.end.x = rects[i].right + scrollOffset.x;
this.cache.end.y = rects[i].bottom + scrollOffset.y;
this.cache.end.x = rects[i].right + offsetX;
this.cache.end.y = rects[i].bottom + offsetY;
}
this.contentWindow = contentWindow;
sendAsyncMessage("Browser:SelectionRange", this.cache);
break;
}
@ -1398,7 +1421,9 @@ var SelectionHandler = {
case "Browser:SelectionEnd": {
try {
// The selection might already be gone
content.getSelection().collapseToStart();
if (this.contentWindow)
this.contentWindow.getSelection().collapseToStart();
this.contentWindow = null;
} catch(e) {}
if (this.selectedText.length) {
@ -1412,6 +1437,8 @@ var SelectionHandler = {
}
case "Browser:SelectionMove":
if (!this.contentWindow)
return;
// Hack to avoid setting focus in a textbox [Bugs 654352 & 667243]
let elemUnder = elementFromPoint(json.x - scrollOffset.x, json.y - scrollOffset.y);
if (elemUnder && elemUnder instanceof Ci.nsIDOMHTMLInputElement || elemUnder instanceof Ci.nsIDOMHTMLTextAreaElement)
@ -1433,7 +1460,7 @@ var SelectionHandler = {
}
// Cache the selected text since the selection might be gone by the time we get the "end" message
this.selectedText = content.getSelection().toString().trim();
this.selectedText = this.contentWindow.getSelection().toString().trim();
break;
}
}