Bug 765057 - (Part 2) Reverse handles if the start handle goes past the end of the selection and vice versa. r=mbrubeck

This commit is contained in:
Margaret Leibovic 2012-06-20 17:56:08 -07:00
parent 383581c1f7
commit 1ebac830be

View File

@ -1500,25 +1500,48 @@ var SelectionHandler = {
this._end.style.top = aY + this.cache.offset.y + "px";
}
//XXX bug 765057: Reverse text selection handles if necessary
// Send mouse events to the top-level window
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
if (aIsStartHandle) {
// If we're moving the start handle, we need to re-position the caret using a fake mouse click
let start = this._start.getBoundingClientRect();
cwu.sendMouseEventToWindow("mousedown", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
cwu.sendMouseEventToWindow("mouseup", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
}
// If we're moving the start handle, we need to re-position the carat
if (aIsStartHandle)
this._sendStartMouseEvents(cwu);
// Send a shift+click to select text between the carat at the start and an end point
// We always need to fire events for the end to move the selection
this._sendEndMouseEvents(cwu);
// Update the cached selection area after firing the mouse events
let selectionReversed = this.updateCacheForSelection(aIsStartHandle);
// Reverse the handles if necessary
if (selectionReversed) {
let oldStart = this._start;
let oldEnd = this._end;
oldStart.setAttribute("anonid", "selection-handle-end");
oldEnd.setAttribute("anonid", "selection-handle-start");
this._start = oldEnd;
this._end = oldStart;
// Re-send mouse events to update the selection corresponding to the new handles
this._sendStartMouseEvents(cwu);
this._sendEndMouseEvents(cwu);
}
},
// Positions the caret using a fake mouse click
_sendStartMouseEvents: function sh_sendStartMouseEvents(cwu) {
let start = this._start.getBoundingClientRect();
cwu.sendMouseEventToWindow("mousedown", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
cwu.sendMouseEventToWindow("mouseup", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
},
// Selects text between the carat at the start and an end point using a fake shift+click
_sendEndMouseEvents: function sh_sendEndMouseEvents(cwu) {
let end = this._end.getBoundingClientRect();
cwu.sendMouseEventToWindow("mousedown", end.left + this.HANDLE_PADDING, end.top - this.HANDLE_VERTICAL_MARGIN, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
cwu.sendMouseEventToWindow("mouseup", end.left + this.HANDLE_PADDING, end.top - this.HANDLE_VERTICAL_MARGIN, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
// Update the cached selection area
this.updateCacheForSelection();
},
// aX/aY are in top-level window browser coordinates
@ -1554,14 +1577,27 @@ var SelectionHandler = {
this.cache = null;
},
updateCacheForSelection: function sh_updateCacheForSelection() {
// Returns true if the selection has been reversed. Takes optional aIsStartHandle
// param to decide whether the selection has been reversed.
updateCacheForSelection: function sh_updateCacheForSelection(aIsStartHandle) {
let range = this._view.getSelection().getRangeAt(0);
this.cache.rect = range.getBoundingClientRect();
let rects = range.getClientRects();
this.cache.start = { x: rects[0].left, y: rects[0].bottom };
this.cache.end = { x: rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
let start = { x: rects[0].left, y: rects[0].bottom };
let end = { x: rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
this.cache.rect = range.getBoundingClientRect();
let selectionReversed = false;
if (this.cache.start) {
// If the end moved past the old end, but we're dragging the start handle, then that handle should become the end handle (and vice versa)
selectionReversed = (aIsStartHandle && (end.y > this.cache.end.y || (end.y == this.cache.end.y && end.x > this.cache.end.x))) ||
(!aIsStartHandle && (start.y < this.cache.start.y || (start.y == this.cache.start.y && start.x < this.cache.start.x)));
}
this.cache.start = start;
this.cache.end = end;
return selectionReversed;
},
updateCacheOffset: function sh_updateCacheOffset() {