mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1123606 - Fix RTL Logic error affecting Handle Movement in TextAreas, r=margaret
This commit is contained in:
parent
bfc0a8f26b
commit
26375d3aa0
@ -262,10 +262,12 @@ function testLTR_dragAnchorHandleToSelf() {
|
||||
var initialSelectionText = sh._getSelectedText();
|
||||
|
||||
// Drag anchor handle and note results.
|
||||
// Note, due to edge case with border boundaries, we actually
|
||||
// move inside a pixel, to maintain Selection position.
|
||||
sh.observe(null, "TextSelection:Move",
|
||||
JSON.stringify({ handleType : ANCHOR,
|
||||
x : initialSelection.anchorPt.x,
|
||||
y : initialSelection.anchorPt.y
|
||||
y : initialSelection.anchorPt.y - 1
|
||||
})
|
||||
);
|
||||
sh.observe(null, "TextSelection:Position",
|
||||
@ -287,14 +289,11 @@ function testLTR_dragAnchorHandleToSelf() {
|
||||
selectionExists(initialSelection,
|
||||
"LTR Selection initially existed at points"),
|
||||
|
||||
todo(false, "testLTR_dragAnchorHandleToSelf: " +
|
||||
// is(anchorDragSelectionText, LTR_INPUT_TEXT_VALUE,
|
||||
is(anchorDragSelectionText, LTR_INPUT_TEXT_VALUE,
|
||||
"LTR Selection text after anchor drag should match expected value."),
|
||||
todo(false, "testLTR_dragAnchorHandleToSelf: " +
|
||||
// selectionExists(anchorDraggedSelection,
|
||||
selectionExists(anchorDraggedSelection,
|
||||
"LTR Selection after anchor drag existed at points"),
|
||||
todo(false, "testLTR_dragAnchorHandleToSelf: " +
|
||||
// selectionEquals(anchorDraggedSelection, initialSelection,
|
||||
selectionEquals(anchorDraggedSelection, initialSelection,
|
||||
"LTR Selection points after anchor drag " +
|
||||
"should match initial selection points."),
|
||||
|
||||
@ -348,14 +347,11 @@ function testRTL_dragFocusHandleToSelf() {
|
||||
selectionExists(initialSelection,
|
||||
"RTL Selection initially existed at points"),
|
||||
|
||||
todo(false, "testRTL_dragAnchorHandleToSelf: " +
|
||||
// is(focusDragSelectionText, RTL_INPUT_TEXT_VALUE,
|
||||
is(focusDragSelectionText, RTL_INPUT_TEXT_VALUE,
|
||||
"RTL Selection text after focus drag should match expected value."),
|
||||
todo(false, "testRTL_dragAnchorHandleToSelf: " +
|
||||
// selectionExists(focusDraggedSelection,
|
||||
selectionExists(focusDraggedSelection,
|
||||
"RTL Selection after focus drag existed at points"),
|
||||
todo(false, "testRTL_dragAnchorHandleToSelf: " +
|
||||
// selectionEquals(focusDraggedSelection, initialSelection,
|
||||
selectionEquals(focusDraggedSelection, initialSelection,
|
||||
"RTL Selection points after focus drag " +
|
||||
"should match initial selection points."),
|
||||
|
||||
@ -383,10 +379,12 @@ function testRTL_dragAnchorHandleToSelf() {
|
||||
var initialSelectionText = sh._getSelectedText();
|
||||
|
||||
// Drag anchor handle and note results.
|
||||
// Note, due to edge case with border boundaries, we actually
|
||||
// move inside a pixel, to maintain Selection position.
|
||||
sh.observe(null, "TextSelection:Move",
|
||||
JSON.stringify({ handleType : ANCHOR,
|
||||
x : initialSelection.anchorPt.x,
|
||||
y : initialSelection.anchorPt.y
|
||||
y : initialSelection.anchorPt.y - 1
|
||||
})
|
||||
);
|
||||
sh.observe(null, "TextSelection:Position",
|
||||
@ -493,10 +491,15 @@ function greaterThan(n1, n2, msg) {
|
||||
});
|
||||
}
|
||||
|
||||
// Use fuzzy logic to compare screen coords.
|
||||
function truncPoint(point) {
|
||||
return new Point(Math.trunc(point.x), Math.trunc(point.y));
|
||||
}
|
||||
|
||||
function pointEquals(p1, p2, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testInputSelections",
|
||||
result: p1.equals(p2),
|
||||
result: truncPoint(p1).equals(truncPoint(p2)),
|
||||
msg: msg + " : " + p1.toString() + " == " + p2.toString()
|
||||
});
|
||||
}
|
||||
@ -504,7 +507,7 @@ function pointEquals(p1, p2, msg) {
|
||||
function pointNotEquals(p1, p2, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testInputSelections",
|
||||
result: !p1.equals(p2),
|
||||
result: !truncPoint(p1).equals(truncPoint(p2)),
|
||||
msg: msg + " : " + p1.toString() + " == " + p2.toString()
|
||||
});
|
||||
}
|
||||
@ -512,7 +515,7 @@ function pointNotEquals(p1, p2, msg) {
|
||||
function selectionExists(selection, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testInputSelections",
|
||||
result: !selection.anchorPt.equals(selection.focusPt),
|
||||
result: !truncPoint(selection.anchorPt).equals(truncPoint(selection.focusPt)),
|
||||
msg: msg + " : anchor:" + selection.anchorPt.toString() +
|
||||
" focus:" + selection.focusPt.toString()
|
||||
});
|
||||
@ -521,7 +524,8 @@ function selectionExists(selection, msg) {
|
||||
function selectionEquals(s1, s2, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testInputSelections",
|
||||
result: s1.anchorPt.equals(s2.anchorPt) && s1.focusPt.equals(s2.focusPt),
|
||||
result: truncPoint(s1.anchorPt).equals(truncPoint(s2.anchorPt)) &&
|
||||
truncPoint(s1.focusPt).equals(truncPoint(s2.focusPt)),
|
||||
msg: msg
|
||||
});
|
||||
}
|
||||
|
@ -518,19 +518,16 @@ function testRTL_moveFocusHandleDown() {
|
||||
"RTL Initial selection anchorPt.x should be greater than (right of) focusPt.x"),
|
||||
|
||||
selectionExists(changedSelection, "RTL Changed selection existed at points"),
|
||||
todo(false, "testRTL_moveFocusHandleDown: " +
|
||||
// pointEquals(changedSelection.anchorPt, initialSelection.anchorPt,
|
||||
"RTL Changed selection focus handle moving down " +
|
||||
"should not change anchor handle position."),
|
||||
todo(false, "testRTL_moveFocusHandleDown: " +
|
||||
// greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
pointEquals(changedSelection.anchorPt, initialSelection.anchorPt,
|
||||
"RTL Changed selection focus handle moving down " +
|
||||
"should not change anchor handle position."),
|
||||
greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
|
||||
todo(false, "testRTL_moveFocusHandleDown: " +
|
||||
// greaterThan(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) Initial selection focusPt.y"),
|
||||
greaterThan(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) Initial selection focusPt.y"),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -585,24 +582,20 @@ function testRTL_moveFocusHandleUp() {
|
||||
"RTL Initial selection anchorPt.x should be greater than (right of) focusPt.x"),
|
||||
|
||||
selectionExists(changedSelection, "RTL Changed selection existed at points"),
|
||||
todo(false, "testRTL_moveFocusHandleUp: " +
|
||||
// pointEquals(changedSelection.focusPt, initialSelection.anchorPt,
|
||||
"RTL Reversed Changed selection focus handle moving up " +
|
||||
"becomes new anchor handle, " +
|
||||
"new focus handle is initial anchor handle."),
|
||||
todo(false, "testRTL_moveFocusHandleUp: " +
|
||||
// greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
pointEquals(changedSelection.focusPt, initialSelection.anchorPt,
|
||||
"RTL Reversed Changed selection focus handle moving up " +
|
||||
"becomes new anchor handle, " +
|
||||
"new focus handle is initial anchor handle."),
|
||||
greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
|
||||
todo(false, "testRTL_moveFocusHandleUp: " +
|
||||
// is(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be equal to Initial selection focusPt.y"),
|
||||
todo(false, "testRTL_moveFocusHandleUp: " +
|
||||
// lessThan(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection anchorPt.y " +
|
||||
"should be less than (above) Initial selection anchorPt.y"),
|
||||
is(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be equal to Initial selection focusPt.y"),
|
||||
lessThan(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection anchorPt.y " +
|
||||
"should be less than (above) Initial selection anchorPt.y"),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -657,19 +650,16 @@ function testRTL_moveAnchorHandleUp() {
|
||||
"RTL Initial selection anchorPt.x should be greater than (right of) focusPt.x"),
|
||||
|
||||
selectionExists(changedSelection, "RTL Changed selection existed at points"),
|
||||
todo(false, "testRTL_moveAnchorHandleUp: " +
|
||||
// pointEquals(changedSelection.focusPt, initialSelection.focusPt,
|
||||
"RTL Changed selection anchor handle moving up " +
|
||||
"should not change focus handle position."),
|
||||
todo(false, "testRTL_moveAnchorHandleUp: " +
|
||||
// greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
pointEquals(changedSelection.focusPt, initialSelection.focusPt,
|
||||
"RTL Changed selection anchor handle moving up " +
|
||||
"should not change focus handle position."),
|
||||
greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
|
||||
todo(false, "testRTL_moveAnchorHandleUp: " +
|
||||
// lessThan(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Changed selection anchorPt.y " +
|
||||
"should be less than (above) Initial selection anchorPt.y"),
|
||||
lessThan(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Changed selection anchorPt.y " +
|
||||
"should be less than (above) Initial selection anchorPt.y"),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -724,24 +714,20 @@ function testRTL_moveAnchorHandleDown() {
|
||||
"RTL Initial selection anchorPt.x should be greater than (right of) focusPt.x"),
|
||||
|
||||
selectionExists(changedSelection, "RTL Changed selection existed at points"),
|
||||
todo(false, "testRTL_moveAnchorHandleDown: " +
|
||||
// pointEquals(changedSelection.anchorPt, initialSelection.focusPt,
|
||||
"RTL Reversed Changed selection anchor handle moving down " +
|
||||
"becomes new focus handle, " +
|
||||
"new anchor handle is initial focus handle."),
|
||||
todo(false, "testRTL_moveAnchorHandleDown: " +
|
||||
// greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
pointEquals(changedSelection.anchorPt, initialSelection.focusPt,
|
||||
"RTL Reversed Changed selection anchor handle moving down " +
|
||||
"becomes new focus handle, " +
|
||||
"new anchor handle is initial focus handle."),
|
||||
greaterThan(changedSelection.focusPt.y, changedSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) changed anchorPt.y"),
|
||||
|
||||
todo(false, "testRTL_moveAnchorHandleDown: " +
|
||||
// is(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection anchorPt.y " +
|
||||
"should be equal to Initial selection anchorPt.y"),
|
||||
todo(false, "testRTL_moveAnchorHandleDown: " +
|
||||
// greaterThan(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) Initial selection focusPt.y"),
|
||||
is(changedSelection.anchorPt.y, initialSelection.anchorPt.y,
|
||||
"RTL Reversed Changed selection anchorPt.y " +
|
||||
"should be equal to Initial selection anchorPt.y"),
|
||||
greaterThan(changedSelection.focusPt.y, initialSelection.focusPt.y,
|
||||
"RTL Reversed Changed selection focusPt.y " +
|
||||
"should be greater than (below) Initial selection focusPt.y"),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -810,10 +796,15 @@ function greaterThan(n1, n2, msg) {
|
||||
});
|
||||
}
|
||||
|
||||
// Use fuzzy logic to compare screen coords.
|
||||
function truncPoint(point) {
|
||||
return new Point(Math.trunc(point.x), Math.trunc(point.y));
|
||||
}
|
||||
|
||||
function pointEquals(p1, p2, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testTextareaSelections",
|
||||
result: p1.equals(p2),
|
||||
result: truncPoint(p1).equals(truncPoint(p2)),
|
||||
msg: msg + " : " + p1.toString() + " == " + p2.toString()
|
||||
});
|
||||
}
|
||||
@ -821,7 +812,7 @@ function pointEquals(p1, p2, msg) {
|
||||
function pointNotEquals(p1, p2, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testTextareaSelections",
|
||||
result: !p1.equals(p2),
|
||||
result: !truncPoint(p1).equals(truncPoint(p2)),
|
||||
msg: msg + " : " + p1.toString() + " == " + p2.toString()
|
||||
});
|
||||
}
|
||||
@ -829,7 +820,7 @@ function pointNotEquals(p1, p2, msg) {
|
||||
function selectionExists(selection, msg) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Robocop:testTextareaSelections",
|
||||
result: !selection.anchorPt.equals(selection.focusPt),
|
||||
result: !truncPoint(selection.anchorPt).equals(truncPoint(selection.focusPt)),
|
||||
msg: msg + " : anchor:" + selection.anchorPt.toString() +
|
||||
" focus:" + selection.focusPt.toString()
|
||||
});
|
||||
|
@ -40,7 +40,11 @@ var SelectionHandler = {
|
||||
// stored here are relative to the _contentWindow window.
|
||||
_cache: null,
|
||||
_activeType: 0, // TYPE_NONE
|
||||
|
||||
_draggingHandles: false, // True while user drags text selection handles
|
||||
_dragStartAnchorOffset: null, // Editables need initial pos during HandleMove events
|
||||
_dragStartFocusOffset: null, // Editables need initial pos during HandleMove events
|
||||
|
||||
_ignoreCompositionChanges: false, // Persist caret during IME composition updates
|
||||
_prevHandlePositions: [], // Avoid issuing duplicate "TextSelection:Position" messages
|
||||
_deferCloseTimer: null, // Used to defer _closeSelection() actions during programmatic changes
|
||||
@ -152,11 +156,12 @@ var SelectionHandler = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "TextSelection:Move": {
|
||||
let data = JSON.parse(aData);
|
||||
if (this._activeType == this.TYPE_SELECTION) {
|
||||
this._startDraggingHandles();
|
||||
this._moveSelection(data.handleType == this.HANDLE_TYPE_ANCHOR, data.x, data.y);
|
||||
this._moveSelection(data.handleType, new Point(data.x, data.y));
|
||||
|
||||
} else if (this._activeType == this.TYPE_CURSOR) {
|
||||
this._startDraggingHandles();
|
||||
@ -170,30 +175,16 @@ var SelectionHandler = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "TextSelection:Position": {
|
||||
if (this._activeType == this.TYPE_SELECTION) {
|
||||
this._startDraggingHandles();
|
||||
|
||||
// Check to see if the handles should be reversed.
|
||||
let isStartHandle = JSON.parse(aData).handleType == this.HANDLE_TYPE_ANCHOR;
|
||||
try {
|
||||
let selectionReversed = this._updateCacheForSelection(isStartHandle);
|
||||
if (selectionReversed) {
|
||||
// Reverse the anchor and focus to correspond to the new start and end handles.
|
||||
let selection = this._getSelection();
|
||||
let anchorNode = selection.anchorNode;
|
||||
let anchorOffset = selection.anchorOffset;
|
||||
selection.collapse(selection.focusNode, selection.focusOffset);
|
||||
selection.extend(anchorNode, anchorOffset);
|
||||
}
|
||||
} catch (e) {
|
||||
// User finished handle positioning with one end off the screen
|
||||
this._closeSelection();
|
||||
break;
|
||||
}
|
||||
|
||||
this._ensureSelectionDirection();
|
||||
this._stopDraggingHandles();
|
||||
|
||||
this._updateCacheForSelection();
|
||||
this._positionHandles();
|
||||
|
||||
// Changes to handle position can affect selection context and actionbar display
|
||||
this._updateMenu();
|
||||
|
||||
@ -225,6 +216,9 @@ var SelectionHandler = {
|
||||
_startDraggingHandles: function sh_startDraggingHandles() {
|
||||
if (!this._draggingHandles) {
|
||||
this._draggingHandles = true;
|
||||
let selection = this._getSelection();
|
||||
this._dragStartAnchorOffset = selection.anchorOffset;
|
||||
this._dragStartFocusOffset = selection.focusOffset;
|
||||
Messaging.sendRequest({ type: "TextSelection:DraggingHandle", dragging: true });
|
||||
}
|
||||
},
|
||||
@ -234,6 +228,8 @@ var SelectionHandler = {
|
||||
_stopDraggingHandles: function sh_stopDraggingHandles() {
|
||||
if (this._draggingHandles) {
|
||||
this._draggingHandles = false;
|
||||
this._dragStartAnchorOffset = null;
|
||||
this._dragStartFocusOffset = null;
|
||||
Messaging.sendRequest({ type: "TextSelection:DraggingHandle", dragging: false });
|
||||
}
|
||||
},
|
||||
@ -862,35 +858,21 @@ var SelectionHandler = {
|
||||
},
|
||||
|
||||
/*
|
||||
* Helper function for moving the selection inside an editable element.
|
||||
*
|
||||
* @param aAnchorX the stationary handle's x-coordinate in client coordinates
|
||||
* @param aX the moved handle's x-coordinate in client coordinates
|
||||
* @param aCaretPos the current position of the caret
|
||||
* Moves the selection as the user drags a handle.
|
||||
* @param handleType: Specifies either the anchor or the focus handle.
|
||||
* @param handlePt: selection point in client coordinates.
|
||||
*/
|
||||
_moveSelectionInEditable: function sh_moveSelectionInEditable(aAnchorX, aX, aCaretPos) {
|
||||
let anchorOffset = aX < aAnchorX ? this._targetElement.selectionEnd
|
||||
: this._targetElement.selectionStart;
|
||||
let newOffset = aCaretPos.offset;
|
||||
let [start, end] = anchorOffset <= newOffset ?
|
||||
[anchorOffset, newOffset] :
|
||||
[newOffset, anchorOffset];
|
||||
this._targetElement.setSelectionRange(start, end);
|
||||
},
|
||||
_moveSelection: function sh_moveSelection(handleType, handlePt) {
|
||||
let isAnchorHandle = (handleType == this.HANDLE_TYPE_ANCHOR);
|
||||
|
||||
/*
|
||||
* Moves the selection as the user drags a selection handle.
|
||||
*
|
||||
* @param aIsStartHandle whether the user is moving the start handle (as opposed to the end handle)
|
||||
* @param aX, aY selection point in client coordinates
|
||||
*/
|
||||
_moveSelection: function sh_moveSelection(aIsStartHandle, aX, aY) {
|
||||
// XXX We should be smarter about the coordinates we pass to caretPositionFromPoint, especially
|
||||
// in editable targets. We should factor out the logic that's currently in _moveCaret.
|
||||
// Determine new caret position from handlePt, exit if user
|
||||
// moved it offscreen.
|
||||
let viewOffset = this._getViewOffset();
|
||||
let caretPos = this._contentWindow.document.caretPositionFromPoint(aX - viewOffset.x, aY - viewOffset.y);
|
||||
let ptX = handlePt.x - viewOffset.x;
|
||||
let ptY = handlePt.y - viewOffset.y;
|
||||
let cwd = this._contentWindow.document;
|
||||
let caretPos = cwd.caretPositionFromPoint(ptX, ptY);
|
||||
if (!caretPos) {
|
||||
// User moves handle offscreen while positioning
|
||||
return;
|
||||
}
|
||||
|
||||
@ -900,36 +882,36 @@ var SelectionHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the cache as the handle is dragged (keep the cache in client coordinates).
|
||||
if (aIsStartHandle) {
|
||||
this._cache.anchorPt.x = aX;
|
||||
this._cache.anchorPt.y = aY;
|
||||
} else {
|
||||
this._cache.focusPt.x = aX;
|
||||
this._cache.focusPt.y = aY;
|
||||
// Update the Selection for editable elements. Selection Change
|
||||
// logic is the same, regardless of RTL/LTR. Selection direction is
|
||||
// maintained always forward (startOffset <= endOffset).
|
||||
if (targetIsEditable) {
|
||||
let start = this._dragStartAnchorOffset;
|
||||
let end = this._dragStartFocusOffset;
|
||||
if (isAnchorHandle) {
|
||||
start = caretPos.offset;
|
||||
} else {
|
||||
end = caretPos.offset;
|
||||
}
|
||||
if (start > end) {
|
||||
[start, end] = [end, start];
|
||||
}
|
||||
this._targetElement.setSelectionRange(start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the Selection for non-editable elements. Selection Change
|
||||
// logic is the same, regardless of RTL/LTR. Selection direction internally
|
||||
// can finish reversed by user drag. ie: Forward is (a,o ---> f,o),
|
||||
// and reversed is (a,o <--- f,o).
|
||||
let selection = this._getSelection();
|
||||
|
||||
// The handles work the same on both LTR and RTL pages, but the anchor/focus nodes
|
||||
// are reversed, so we need to reverse the logic to extend the selection.
|
||||
if ((aIsStartHandle && !this._isRTL) || (!aIsStartHandle && this._isRTL)) {
|
||||
if (targetIsEditable) {
|
||||
let anchorX = this._isRTL ? this._cache.anchorPt.x : this._cache.focusPt.x;
|
||||
this._moveSelectionInEditable(anchorX, aX, caretPos);
|
||||
} else {
|
||||
let focusNode = selection.focusNode;
|
||||
let focusOffset = selection.focusOffset;
|
||||
selection.collapse(caretPos.offsetNode, caretPos.offset);
|
||||
selection.extend(focusNode, focusOffset);
|
||||
}
|
||||
if (isAnchorHandle) {
|
||||
let focusNode = selection.focusNode;
|
||||
let focusOffset = selection.focusOffset;
|
||||
selection.collapse(caretPos.offsetNode, caretPos.offset);
|
||||
selection.extend(focusNode, focusOffset);
|
||||
} else {
|
||||
if (targetIsEditable) {
|
||||
let anchorX = this._isRTL ? this._cache.focusPt.x : this._cache.anchorPt.x;
|
||||
this._moveSelectionInEditable(anchorX, aX, caretPos);
|
||||
} else {
|
||||
selection.extend(caretPos.offsetNode, caretPos.offset);
|
||||
}
|
||||
selection.extend(caretPos.offsetNode, caretPos.offset);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1149,29 +1131,56 @@ var SelectionHandler = {
|
||||
return offset;
|
||||
},
|
||||
|
||||
// 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) {
|
||||
/*
|
||||
* The direction of the Selection is ensured for editables while the user drags
|
||||
* the handles (per "TextSelection:Move" event). For non-editables, we just let
|
||||
* the user change direction, but fix it up at the end of handle movement (final
|
||||
* "TextSelection:Position" event).
|
||||
*/
|
||||
_ensureSelectionDirection: function() {
|
||||
// Never needed at this time.
|
||||
if (this._targetElement instanceof Ci.nsIDOMNSEditableElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing needed if not reversed.
|
||||
let qcEventResult = this._domWinUtils.sendQueryContentEvent(
|
||||
this._domWinUtils.QUERY_SELECTED_TEXT, 0, 0, 0, 0);
|
||||
if (!qcEventResult.reversed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reverse the Selection.
|
||||
let selection = this._getSelection();
|
||||
let newFocusNode = selection.anchorNode;
|
||||
let newFocusOffset = selection.anchorOffset;
|
||||
|
||||
selection.collapse(selection.focusNode, selection.focusOffset);
|
||||
selection.extend(newFocusNode, newFocusOffset);
|
||||
},
|
||||
|
||||
/*
|
||||
* Updates the TYPE_SELECTION cache, with the handle anchor/focus point values
|
||||
* of the current selection. Passed to Java for UI positioning only.
|
||||
*/
|
||||
_updateCacheForSelection: function() {
|
||||
let rects = this._getSelection().getRangeAt(0).getClientRects();
|
||||
if (!rects[0]) {
|
||||
if (rects.length == 0) {
|
||||
// nsISelection object exists, but there's nothing actually selected
|
||||
throw "Failed to update cache for invalid selection";
|
||||
}
|
||||
|
||||
let start = { x: this._isRTL ? rects[0].right : rects[0].left, y: rects[0].bottom };
|
||||
let end = { x: this._isRTL ? rects[rects.length - 1].left : rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
|
||||
|
||||
let selectionReversed = false;
|
||||
if (this._cache.anchorPt) {
|
||||
// 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.focusPt.y || (end.y == this._cache.focusPt.y && end.x > this._cache.focusPt.x))) ||
|
||||
(!aIsStartHandle && (start.y < this._cache.anchorPt.y || (start.y == this._cache.anchorPt.y && start.x < this._cache.anchorPt.x)));
|
||||
let anchorIdx = 0;
|
||||
let focusIdx = rects.length - 1;
|
||||
if (this._isRTL) {
|
||||
// Right-to-Left (ie: Hebrew) anchorPt is on right, focusPt is on left.
|
||||
this._cache.anchorPt = new Point(rects[anchorIdx].right, rects[anchorIdx].bottom);
|
||||
this._cache.focusPt = new Point(rects[focusIdx].left, rects[focusIdx].bottom);
|
||||
} else {
|
||||
// Left-to-Right (ie: English) anchorPt is on left, focusPt is on right.
|
||||
this._cache.anchorPt = new Point(rects[anchorIdx].left, rects[anchorIdx].bottom);
|
||||
this._cache.focusPt = new Point(rects[focusIdx].right, rects[focusIdx].bottom);
|
||||
}
|
||||
|
||||
this._cache.anchorPt = start;
|
||||
this._cache.focusPt = end;
|
||||
|
||||
return selectionReversed;
|
||||
},
|
||||
|
||||
_getHandlePositions: function sh_getHandlePositions(scroll) {
|
||||
|
@ -298,8 +298,8 @@ XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() {
|
||||
return ContentAreaUtils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Rect",
|
||||
"resource://gre/modules/Geometry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Rect", "resource://gre/modules/Geometry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Point", "resource://gre/modules/Geometry.jsm");
|
||||
|
||||
function resolveGeckoURI(aURI) {
|
||||
if (!aURI)
|
||||
|
Loading…
Reference in New Issue
Block a user