зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1216001 part 2 - Optimize nsRange::ExcludeNonSelectableNodes by counting ignorable whitespace text nodes next to an unselectable node as unselectable too. r=bz
This commit is contained in:
Родитель
a3c53b91a3
Коммит
41740a7ab3
|
@ -3154,6 +3154,12 @@ nsRange::Constructor(const GlobalObject& aGlobal,
|
|||
return window->GetDoc()->CreateRange(aRv);
|
||||
}
|
||||
|
||||
static bool ExcludeIfNextToNonSelectable(nsIContent* aContent)
|
||||
{
|
||||
return aContent->IsNodeOfType(nsINode::eTEXT) &&
|
||||
aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE);
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
|
||||
{
|
||||
|
@ -3172,6 +3178,10 @@ nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
|
|||
|
||||
bool added = false;
|
||||
bool seenSelectable = false;
|
||||
// |firstNonSelectableContent| is the first node in a consecutive sequence
|
||||
// of non-IsSelectable nodes. When we find a selectable node after such
|
||||
// a sequence we'll end the last nsRange, create a new one and restart
|
||||
// the outer loop.
|
||||
nsIContent* firstNonSelectableContent = nullptr;
|
||||
while (true) {
|
||||
ErrorResult err;
|
||||
|
@ -3181,12 +3191,19 @@ nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
|
|||
nsIContent* content =
|
||||
node && node->IsContent() ? node->AsContent() : nullptr;
|
||||
if (content) {
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
|
||||
frame = p->GetPrimaryFrame();
|
||||
if (firstNonSelectableContent && ExcludeIfNextToNonSelectable(content)) {
|
||||
// Ignorable whitespace next to a sequence of non-selectable nodes
|
||||
// counts as non-selectable (bug 1216001).
|
||||
selectable = false;
|
||||
}
|
||||
if (frame) {
|
||||
frame->IsSelectable(&selectable, nullptr);
|
||||
if (selectable) {
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
|
||||
frame = p->GetPrimaryFrame();
|
||||
}
|
||||
if (frame) {
|
||||
frame->IsSelectable(&selectable, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
src: url("Ahem.ttf");
|
||||
}
|
||||
body { font-family: Ahem; font-size: 20px; }
|
||||
s { -moz-user-select: none; }
|
||||
s, .non-selectable { -moz-user-select: none; }
|
||||
n { display: none; }
|
||||
a { position:absolute; bottom: 0; right:0; }
|
||||
.text { -moz-user-select: text; }
|
||||
|
@ -34,6 +34,16 @@ a { position:absolute; bottom: 0; right:0; }
|
|||
<div id="testB"><n><s>aaaa</s>aaa</n>bbbbbbbbccccccc</div>
|
||||
<div id="testC">aaaaaaabbbbbbbb<n>cc<s>c</s>cccc</n></div>
|
||||
<div id="testE">aaa<s id="testEc1">aaaa<a class="text">bbbb</a>dd<a>cccc</a>ddddddd</s>eeee</div>
|
||||
<div id="testF">aaaa
|
||||
<div class="non-selectable">x</div>
|
||||
<div class="non-selectable">x</div>
|
||||
<div class="non-selectable">x</div>
|
||||
bbbb</div>
|
||||
<div id="testG" style="white-space:pre">aaaa
|
||||
<div class="non-selectable">x</div>
|
||||
<div class="non-selectable">x</div>
|
||||
<div class="non-selectable">x</div>
|
||||
bbbb</div>
|
||||
|
||||
<iframe id="testD" src="data:text/html,<body>aaaa<span style='-moz-user-select:none'>bbbb</span>cccc"></iframe>
|
||||
|
||||
|
@ -100,9 +110,11 @@ function test()
|
|||
is(NL(r.toString()), text, e.id + ": range["+index+"].toString()")
|
||||
}
|
||||
|
||||
function node(e, index)
|
||||
function node(e, arg)
|
||||
{
|
||||
return index == -1 ? e : e.childNodes[index];
|
||||
if (typeof arg == "number")
|
||||
return arg == -1 ? e : e.childNodes[arg];
|
||||
return arg;
|
||||
}
|
||||
|
||||
function checkRangeCount(n, e)
|
||||
|
@ -258,6 +270,22 @@ function test()
|
|||
checkRanges([[0,1,-1,1]], e);
|
||||
doneTest(e);
|
||||
|
||||
clear();
|
||||
e = document.getElementById('testF');
|
||||
synthesizeMouse(e, 1, 1, {});
|
||||
synthesizeMouse(e, 400, 100, { shiftKey: true });
|
||||
checkText("aaaa bbbb", e);
|
||||
checkRanges([[0,0,-1,1],[6,0,6,5]], e);
|
||||
doneTest(e);
|
||||
|
||||
clear();
|
||||
e = document.getElementById('testG');
|
||||
synthesizeMouse(e, 1, 1, {});
|
||||
synthesizeMouse(e, 400, 180, { shiftKey: true });
|
||||
checkText("aaaa bbbb", e); // XXX this doesn't seem right - bug 1247799
|
||||
checkRanges([[0,0,-1,1],[2,0,-1,3],[4,0,-1,5],[6,0,6,5]], e);
|
||||
doneTest(e);
|
||||
|
||||
// ======================================================
|
||||
// ==================== Script tests ====================
|
||||
// ======================================================
|
||||
|
|
Загрузка…
Ссылка в новой задаче