зеркало из https://github.com/mozilla/gecko-dev.git
Use GetExtremeCaretPosition() for all editable nodes, not just the doc root. b=512295 r=roc
This commit is contained in:
Родитель
250e32b726
Коммит
55b5f2a328
|
@ -25,7 +25,7 @@
|
|||
* Håkan Waara <hwaara@chello.se>
|
||||
* Dan Rosen <dr@netscape.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
* Mats Palmgren <matspal@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -3023,52 +3023,19 @@ PresShell::CompleteMove(PRBool aForward, PRBool aExtend)
|
|||
{
|
||||
// Beware! This may flush notifications via synchronous
|
||||
// ScrollSelectionIntoView.
|
||||
|
||||
nsIContent* root = mSelection->GetAncestorLimiter();
|
||||
nsIDocument* doc;
|
||||
if (root && (doc = root->GetOwnerDoc()) && doc->GetRootContent() != root) {
|
||||
// Make the caret be either at the very beginning (0) or the very end of
|
||||
// root. Only do this when not moving to the beginning or end of the
|
||||
// document (root is null or root is the documentElement), that's handled
|
||||
// below by moving to beginning or end of the scrollable view.
|
||||
nsIContent* node = root;
|
||||
PRInt32 offset = 0;
|
||||
nsFrameSelection::HINT hint = nsFrameSelection::HINTLEFT;
|
||||
if (aForward) {
|
||||
nsIContent* next = node;
|
||||
PRUint32 count;
|
||||
while ((count = next->GetChildCount()) > 0) {
|
||||
node = next;
|
||||
offset = count;
|
||||
next = next->GetChildAt(count - 1);
|
||||
}
|
||||
|
||||
if (offset > 0 && node->GetChildAt(offset - 1)->Tag() == nsGkAtoms::br) {
|
||||
--offset;
|
||||
hint = nsFrameSelection::HINTRIGHT; // for bug 106855
|
||||
}
|
||||
}
|
||||
|
||||
mSelection->HandleClick(node, offset, offset, aExtend, PR_FALSE, hint);
|
||||
|
||||
// HandleClick resets ancestorLimiter, so set it again.
|
||||
mSelection->SetAncestorLimiter(root);
|
||||
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be
|
||||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return
|
||||
ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
nsISelectionController::SELECTION_FOCUS_REGION,
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
nsIFrame *frame = FrameConstructor()->GetRootElementFrame();
|
||||
nsIContent* limiter = mSelection->GetAncestorLimiter();
|
||||
nsIFrame* frame = limiter ? limiter->GetPrimaryFrame()
|
||||
: FrameConstructor()->GetRootElementFrame();
|
||||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsPeekOffsetStruct pos = frame->GetExtremeCaretPosition(!aForward);
|
||||
|
||||
mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffset/*End*/ ,aExtend, PR_FALSE, aForward);
|
||||
|
||||
mSelection->HandleClick(pos.mResultContent, pos.mContentOffset,
|
||||
pos.mContentOffset, aExtend, PR_FALSE, aForward);
|
||||
if (limiter) {
|
||||
// HandleClick resets ancestorLimiter, so set it again.
|
||||
mSelection->SetAncestorLimiter(limiter);
|
||||
}
|
||||
|
||||
// After ScrollSelectionIntoView(), the pending notifications might be
|
||||
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
|
||||
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
|
||||
|
|
|
@ -91,6 +91,16 @@ _TEST_FILES = \
|
|||
test_bug435293-interaction.html \
|
||||
test_bug435293-skew.html \
|
||||
test_bug495648.xul \
|
||||
test_reftests_with_caret.html \
|
||||
bug106855-1.html \
|
||||
bug106855-2.html \
|
||||
bug106855-1-ref.html \
|
||||
bug482484.html \
|
||||
bug482484-ref.html \
|
||||
bug512295-1.html \
|
||||
bug512295-1-ref.html \
|
||||
bug512295-2.html \
|
||||
bug512295-2-ref.html \
|
||||
test_bug514127.html \
|
||||
test_bug518777.html \
|
||||
test_flush_on_paint.html \
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x<br>
|
||||
<textarea id="t" rows="4">
|
||||
A
|
||||
|
||||
|
||||
</textarea><br>
|
||||
y
|
||||
<script>
|
||||
// Position the caret at the last line
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
||||
var area = document.getElementById('t');
|
||||
area.focus();
|
||||
|
||||
sendKey('RIGHT', window); // now after "A"
|
||||
sendKey('RIGHT', window); //
|
||||
sendKey('RIGHT', window); //
|
||||
sendKey('RIGHT', window); // now at the last line
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x<br>
|
||||
<textarea id="t" rows="4">
|
||||
A
|
||||
|
||||
|
||||
</textarea><br>
|
||||
y
|
||||
<script>
|
||||
// Position the caret at the last line
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
||||
var area = document.getElementById('t');
|
||||
area.focus();
|
||||
|
||||
sendKey('DOWN', window); // now after "A"
|
||||
sendKey('DOWN', window); //
|
||||
sendKey('DOWN', window); // now at the last line
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x<br>
|
||||
<textarea id="t" rows="4">
|
||||
A
|
||||
|
||||
|
||||
</textarea><br>
|
||||
y
|
||||
<script>
|
||||
// Position the caret at the last line
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
||||
var area = document.getElementById('t');
|
||||
area.focus();
|
||||
|
||||
sendKey('DOWN', window); // now after "A"
|
||||
sendKey('DOWN', window); //
|
||||
sendKey('DOWN', window); //
|
||||
sendKey('DOWN', window); // now at the last line
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML><html><head></head>
|
||||
<body>
|
||||
<div contentEditable="true" id="div"><p id="p">ABC</p></div>
|
||||
<script>
|
||||
// Position the caret after the "A"
|
||||
var div = document.getElementById('div');
|
||||
var p = document.getElementById('p');
|
||||
div.focus();
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(p.firstChild, 1)
|
||||
range.setEnd(p.firstChild, 1);
|
||||
sel.addRange(range);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div contentEditable="true" id="div"><p id="p">BC</p></div>
|
||||
<script>
|
||||
// Position the caret before the "B"
|
||||
var div = document.getElementById('div');
|
||||
div.focus();
|
||||
var p = document.getElementById('p');
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(p.firstChild, 0)
|
||||
range.setEnd(p.firstChild, 0);
|
||||
sel.addRange(range);
|
||||
|
||||
sendKey('UP', div); // move UP
|
||||
sendChar('A', div); // insert "A"
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div contenteditable="true">
|
||||
<p id="p">A B CD EFG<br>
|
||||
1234567890</p>
|
||||
</div>
|
||||
x
|
||||
<script>
|
||||
// Position the caret at the end of the P element
|
||||
var p = document.getElementById('p');
|
||||
var div = p.parentNode;
|
||||
div.focus();
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(p, p.childNodes.length);
|
||||
range.setEnd(p, p.childNodes.length);
|
||||
sel.addRange(range);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div contenteditable="true">
|
||||
<p id="p">A B CD EFG<br>
|
||||
1234567890</p>
|
||||
</div>
|
||||
x
|
||||
<script>
|
||||
// Position the caret after "A"
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
var p = document.getElementById('p');
|
||||
var t = p.firstChild;
|
||||
range.setStart(t, 1);
|
||||
range.setEnd(t, 1);
|
||||
sel.addRange(range);
|
||||
p.parentNode.focus();
|
||||
|
||||
sendKey('DOWN', window); // now after "1"
|
||||
sendKey('DOWN', window); // now make sure we get to the end
|
||||
sendKey('DOWN', window); // now make sure we get to the end
|
||||
sendKey('DOWN', window); // now make sure we get to the end
|
||||
sendKey('DOWN', window); // now make sure we get to the end
|
||||
sendKey('DOWN', window); // now make sure we get to the end
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x
|
||||
<div contenteditable="true">
|
||||
<p id="p">A B CD EFG<br>
|
||||
1234567890</p>
|
||||
</div>
|
||||
<script>
|
||||
// Position the caret before the "A"
|
||||
var p = document.getElementById('p');
|
||||
var div = p.parentNode;
|
||||
div.focus();
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(p.firstChild, 0);
|
||||
range.setEnd(p.firstChild, 0);
|
||||
sel.addRange(range);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML><html><head>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
x
|
||||
<div contenteditable="true">
|
||||
<p id="p">A B CD EFG<br>
|
||||
1234567890</p>
|
||||
</div>
|
||||
<script>
|
||||
// Position the caret after "A"
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
var p = document.getElementById('p');
|
||||
var t = p.firstChild;
|
||||
range.setStart(t, 1);
|
||||
range.setEnd(t, 1);
|
||||
sel.addRange(range);
|
||||
p.parentNode.focus();
|
||||
|
||||
sendKey('DOWN', window); // now after "1"
|
||||
sendKey('DOWN', window); // now below the P element
|
||||
sendKey('UP', window); // now before the "1"
|
||||
sendKey('UP', window); // now before the "A"
|
||||
sendKey('UP', window); // now before the "A"
|
||||
sendKey('UP', window); // now before the "A"
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,112 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Reftests with caret drawing</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript">
|
||||
|
||||
var canvases = [];
|
||||
function callbackTestCanvas(canvas)
|
||||
{
|
||||
canvases.push(canvas);
|
||||
|
||||
if (canvases.length != 2)
|
||||
return;
|
||||
|
||||
var result = canvases[0];
|
||||
var reference = canvases[1];
|
||||
|
||||
var ret = compareSnapshots(result.snapshot, reference.snapshot, true);
|
||||
ok(ret[0], "Reftest " + result.src +
|
||||
(ret[0] ? "" : (" FAILED\n" +
|
||||
"RESULT=" + ret[1] + "\n" +
|
||||
"REFERENCE=" + ret[2] + "\n")));
|
||||
|
||||
// Remove the iframes if the test was successful
|
||||
if (ret[0]) {
|
||||
result.parentNode.removeChild(result);
|
||||
reference.parentNode.removeChild(reference);
|
||||
}
|
||||
canvases = [];
|
||||
nextTest();
|
||||
}
|
||||
|
||||
function doSnapShot(iframe) {
|
||||
iframe.snapshot = snapshotWindow(iframe.contentWindow, true);
|
||||
callbackTestCanvas(iframe);
|
||||
};
|
||||
|
||||
function remotePageLoaded() {
|
||||
var iframe = this;
|
||||
setTimeout(function(){doSnapShot(iframe);}, 0)
|
||||
};
|
||||
|
||||
function createIframe(url,next) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = url;
|
||||
iframe.remotePageLoaded = remotePageLoaded;
|
||||
var me = this;
|
||||
iframe.addEventListener("load", function() {
|
||||
iframe.remotePageLoaded();
|
||||
if (next) setTimeout(function(){createIframe(next,null);}, 0)
|
||||
}, false);
|
||||
window.document.body.appendChild(iframe);
|
||||
};
|
||||
|
||||
function refTest(test,ref) {
|
||||
createIframe(test,ref);
|
||||
};
|
||||
|
||||
var caretBlinkTime;
|
||||
function endTest() {
|
||||
SimpleTest.finish();
|
||||
netscape.security.PrivilegeManager.enablePrivilege(
|
||||
'UniversalPreferencesRead UniversalPreferencesWrite UniversalXPConnect');
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.setIntPref("ui.caretBlinkTime", caretBlinkTime);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
[ 'bug106855-1.html' , 'bug106855-1-ref.html' ] ,
|
||||
[ 'bug106855-2.html' , 'bug106855-1-ref.html' ] ,
|
||||
[ 'bug482484.html' , 'bug482484-ref.html' ] ,
|
||||
[ 'bug512295-1.html' , 'bug512295-1-ref.html' ] ,
|
||||
[ 'bug512295-2.html' , 'bug512295-2-ref.html' ]
|
||||
];
|
||||
var testIndex = 0;
|
||||
|
||||
function nextTest() {
|
||||
if (testIndex < tests.length) {
|
||||
refTest(tests[testIndex][0],tests[testIndex][1]);
|
||||
++testIndex;
|
||||
} else {
|
||||
endTest();
|
||||
}
|
||||
}
|
||||
function runTests() {
|
||||
try {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege(
|
||||
'UniversalPreferencesRead UniversalPreferencesWrite UniversalXPConnect');
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
caretBlinkTime = prefs.getIntPref("ui.caretBlinkTime");
|
||||
prefs.setIntPref("ui.caretBlinkTime", -1);
|
||||
|
||||
nextTest();
|
||||
} catch(e) {
|
||||
endTest();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
</body>
|
||||
</html>
|
|
@ -10,7 +10,7 @@ try {
|
|||
gWindowUtils = null;
|
||||
}
|
||||
|
||||
function snapshotWindow(win) {
|
||||
function snapshotWindow(win, withCaret) {
|
||||
var el = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
el.width = win.innerWidth;
|
||||
el.height = win.innerHeight;
|
||||
|
@ -18,9 +18,11 @@ function snapshotWindow(win) {
|
|||
// drawWindow requires privileges
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
el.getContext("2d").drawWindow(win, win.scrollX, win.scrollY,
|
||||
win.innerWidth, win.innerHeight,
|
||||
"rgb(255,255,255)");
|
||||
var ctx = el.getContext("2d");
|
||||
ctx.drawWindow(win, win.scrollX, win.scrollY,
|
||||
win.innerWidth, win.innerHeight,
|
||||
"rgb(255,255,255)",
|
||||
withCaret ? ctx.DRAWWINDOW_DRAW_CARET : 0);
|
||||
return el;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче