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"; 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 // Send mouse events to the top-level window
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
if (aIsStartHandle) { // If we're moving the start handle, we need to re-position the carat
// If we're moving the start handle, we need to re-position the caret using a fake mouse click if (aIsStartHandle)
this._sendStartMouseEvents(cwu);
// 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(); 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("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); cwu.sendMouseEventToWindow("mouseup", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
} },
// Send a shift+click to select text between the carat at the start and an end point // 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(); 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("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); 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 // aX/aY are in top-level window browser coordinates
@ -1554,14 +1577,27 @@ var SelectionHandler = {
this.cache = null; 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); let range = this._view.getSelection().getRangeAt(0);
this.cache.rect = range.getBoundingClientRect();
let rects = range.getClientRects(); let rects = range.getClientRects();
this.cache.start = { x: rects[0].left, y: rects[0].bottom }; let 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 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() { updateCacheOffset: function sh_updateCacheOffset() {