Backed out 3 changesets (bug 739396) for Mulet perma-fail on a CLOSED TREE.
Backed out changeset 299911e6983b (bug 739396) Backed out changeset de11af3e0964 (bug 739396) Backed out changeset e274cb276cc5 (bug 739396)
This commit is contained in:
@@ -3039,95 +3039,3 @@ nsRange::Constructor(const GlobalObject& aGlobal,
|
|||||||
|
|
||||||
return window->GetDoc()->CreateRange(aRv);
|
return window->GetDoc()->CreateRange(aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsRange::ExcludeNonSelectableNodes(nsTArray<nsRefPtr<nsRange>>* aOutRanges)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mIsPositioned);
|
|
||||||
MOZ_ASSERT(mEndParent);
|
|
||||||
MOZ_ASSERT(mStartParent);
|
|
||||||
|
|
||||||
nsRange* range = this;
|
|
||||||
nsRefPtr<nsRange> newRange;
|
|
||||||
while (range) {
|
|
||||||
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
|
|
||||||
nsresult rv = iter->Init(range);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool added = false;
|
|
||||||
bool seenSelectable = false;
|
|
||||||
nsIContent* firstNonSelectableContent = nullptr;
|
|
||||||
while (true) {
|
|
||||||
ErrorResult err;
|
|
||||||
nsINode* node = iter->GetCurrentNode();
|
|
||||||
iter->Next();
|
|
||||||
bool selectable = true;
|
|
||||||
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 (frame) {
|
|
||||||
frame->IsSelectable(&selectable, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!selectable) {
|
|
||||||
if (!firstNonSelectableContent) {
|
|
||||||
firstNonSelectableContent = content;
|
|
||||||
}
|
|
||||||
if (iter->IsDone() && seenSelectable) {
|
|
||||||
// The tail end of the initial range is non-selectable - truncate the
|
|
||||||
// current range before the first non-selectable node.
|
|
||||||
range->SetEndBefore(*firstNonSelectableContent, err);
|
|
||||||
}
|
|
||||||
} else if (firstNonSelectableContent) {
|
|
||||||
if (range == this && !seenSelectable) {
|
|
||||||
// This is the initial range and all its nodes until now are
|
|
||||||
// non-selectable so just trim them from the start.
|
|
||||||
range->SetStartBefore(*node, err);
|
|
||||||
if (err.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break; // restart the same range with a new iterator
|
|
||||||
} else {
|
|
||||||
// Save the end point before truncating the range.
|
|
||||||
nsINode* endParent = range->mEndParent;
|
|
||||||
int32_t endOffset = range->mEndOffset;
|
|
||||||
|
|
||||||
// Truncate the current range before the first non-selectable node.
|
|
||||||
range->SetEndBefore(*firstNonSelectableContent, err);
|
|
||||||
|
|
||||||
// Store it in the result (strong ref) - do this before creating
|
|
||||||
// a new range in |newRange| below so we don't drop the last ref
|
|
||||||
// to the range created in the previous iteration.
|
|
||||||
if (!added && !err.Failed()) {
|
|
||||||
aOutRanges->AppendElement(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new range for the remainder.
|
|
||||||
rv = CreateRange(node, 0, endParent, endOffset,
|
|
||||||
getter_AddRefs(newRange));
|
|
||||||
if (NS_FAILED(rv) || newRange->Collapsed()) {
|
|
||||||
newRange = nullptr;
|
|
||||||
}
|
|
||||||
range = newRange;
|
|
||||||
break; // create a new iterator for the new range, if any
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
seenSelectable = true;
|
|
||||||
if (!added) {
|
|
||||||
added = true;
|
|
||||||
aOutRanges->AppendElement(range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (iter->IsDone()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -264,19 +264,6 @@ public:
|
|||||||
nsINode* aEndParent, int32_t aEndOffset,
|
nsINode* aEndParent, int32_t aEndOffset,
|
||||||
bool aClampToEdge, bool aFlushLayout);
|
bool aClampToEdge, bool aFlushLayout);
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan this range for -moz-user-select:none nodes and split it up into
|
|
||||||
* multiple ranges to exclude those nodes. The resulting ranges are put
|
|
||||||
* in aOutRanges. If no -moz-user-select:none node is found in the range
|
|
||||||
* then |this| is unmodified and is the only range in aOutRanges.
|
|
||||||
* Otherwise, |this| will be modified so that it ends before the first
|
|
||||||
* -moz-user-select:none node and additional ranges may also be created.
|
|
||||||
* If all nodes in the range are -moz-user-select:none then aOutRanges
|
|
||||||
* will be empty.
|
|
||||||
* @param aOutRanges the resulting set of ranges
|
|
||||||
*/
|
|
||||||
void ExcludeNonSelectableNodes(nsTArray<nsRefPtr<nsRange>>* aOutRanges);
|
|
||||||
|
|
||||||
typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
|
typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
|
||||||
protected:
|
protected:
|
||||||
void RegisterCommonAncestor(nsINode* aNode);
|
void RegisterCommonAncestor(nsINode* aNode);
|
||||||
|
|||||||
@@ -656,5 +656,3 @@ skip-if = buildapp == 'b2g' || e10s
|
|||||||
support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs
|
support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs
|
||||||
[test_bug1025933.html]
|
[test_bug1025933.html]
|
||||||
[test_element.matches.html]
|
[test_element.matches.html]
|
||||||
[test_user_select.html]
|
|
||||||
skip-if = buildapp == 'b2g'
|
|
||||||
|
|||||||
@@ -1,259 +0,0 @@
|
|||||||
<!DOCTYPE>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>-moz-user-select selection tests</title>
|
|
||||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
@font-face {
|
|
||||||
font-family: Ahem;
|
|
||||||
src: url("Ahem.ttf");
|
|
||||||
}
|
|
||||||
body { font-family: Ahem; font-size: 20px; }
|
|
||||||
s { -moz-user-select: none; }
|
|
||||||
n { display: none; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="test1">aaaaaaa<s>bbbbbbbb</s>ccccccc</div>
|
|
||||||
<div id="test2"><s>aaaaaaa</s>bbbbbbbbccccccc</div>
|
|
||||||
<div id="test3">aaaaaaabbbbbbbb<s>ccccccc</s></div>
|
|
||||||
<div id="test4">aaaaaaa<x><s>bbbbbbbb</s></x>ccccccc</div>
|
|
||||||
<div id="test5"><x><s>aaaaaaa</s></x>bbbbbbbbccccccc</div>
|
|
||||||
<div id="test6">aaaaaaabbbbbbbb<x><s>ccccccc</s></x></div>
|
|
||||||
<div id="test7">aaaaaaa<x><s><n>bbbb</n>bbbb</s></x>ccccccc</div>
|
|
||||||
<div id="test8"><x><s>aa<n>aaa</n>aa</s></x>bbbbbbbbccccccc</div>
|
|
||||||
<div id="test9">aaaaaaabbbbbbbb<x><s>cc<n>ccccc</n></s></x></div>
|
|
||||||
<div id="testA">aaaaaaa<n>bbb<s>bbbbb</s></n>ccccccc</div>
|
|
||||||
<div id="testB"><n><s>aaaa</s>aaa</n>bbbbbbbbccccccc</div>
|
|
||||||
<div id="testC">aaaaaaabbbbbbbb<n>cc<s>c</s>cccc</n></div>
|
|
||||||
|
|
||||||
<iframe id="testD" src="data:text/html,<body>aaaa<span style='-moz-user-select:none'>bbbb</span>cccc"></iframe>
|
|
||||||
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
function test()
|
|
||||||
{
|
|
||||||
function clear(w)
|
|
||||||
{
|
|
||||||
var sel = (w ? w : window).getSelection();
|
|
||||||
sel.removeAllRanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragSelect(e, x1, x2, x3)
|
|
||||||
{
|
|
||||||
dir = x2 > x1 ? 1 : -1;
|
|
||||||
synthesizeMouse(e, x1, 5, { type: "mousedown" });
|
|
||||||
synthesizeMouse(e, x1 + dir, 5, { type: "mousemove" });
|
|
||||||
if (x3)
|
|
||||||
synthesizeMouse(e, x3, 5, { type: "mousemove" });
|
|
||||||
synthesizeMouse(e, x2 - dir, 5, { type: "mousemove" });
|
|
||||||
synthesizeMouse(e, x2, 5, { type: "mouseup" });
|
|
||||||
}
|
|
||||||
|
|
||||||
function shiftClick(e, x)
|
|
||||||
{
|
|
||||||
synthesizeMouse(e, x, 5, { type: "mousedown", shiftKey: true });
|
|
||||||
synthesizeMouse(e, x, 5, { type: "mouseup", shiftKey: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(arr, e)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
var sel = window.getSelection();
|
|
||||||
for (i = 0; i < arr.length; ++i) {
|
|
||||||
var data = arr[i];
|
|
||||||
var r = new Range()
|
|
||||||
r.setStart(node(e, data[0]), data[1]);
|
|
||||||
r.setEnd(node(e, data[2]), data[3]);
|
|
||||||
sel.addRange(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkText(text, e)
|
|
||||||
{
|
|
||||||
var sel = window.getSelection();
|
|
||||||
is(sel.toString(), text, e.id + ": selected text")
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkRangeText(text, index)
|
|
||||||
{
|
|
||||||
var r = window.getSelection().getRangeAt(index);
|
|
||||||
is(r.toString(), text, e.id + ": range["+index+"].toString()")
|
|
||||||
}
|
|
||||||
|
|
||||||
function node(e, index)
|
|
||||||
{
|
|
||||||
return index == -1 ? e : e.childNodes[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkRanges(arr, e)
|
|
||||||
{
|
|
||||||
var sel = window.getSelection();
|
|
||||||
is(sel.rangeCount, arr.length, e.id + ": Selection range count");
|
|
||||||
for (i = 0; i < arr.length; ++i) {
|
|
||||||
var expected = arr[i];
|
|
||||||
var r = sel.getRangeAt(i);
|
|
||||||
is(r.startContainer, node(e, expected[0]), e.id + ": range["+i+"].startContainer");
|
|
||||||
is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset");
|
|
||||||
is(r.endContainer, node(e, expected[2]), e.id + ": range["+i+"].endContainer");
|
|
||||||
is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======================================================
|
|
||||||
// ================== dragSelect tests ==================
|
|
||||||
// ======================================================
|
|
||||||
|
|
||||||
var e = document.getElementById('test1');
|
|
||||||
dragSelect(e, 20, 340);
|
|
||||||
checkText('aaaaaacc', e);
|
|
||||||
checkRanges([[0,1,-1,1], [2,0,2,2]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
dragSelect(e, 20, 260, 120);
|
|
||||||
checkText('aaaaa', e);
|
|
||||||
checkRanges([[0,1,0,6]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test2');
|
|
||||||
dragSelect(e, 20, 340);
|
|
||||||
checkText('', e);
|
|
||||||
checkRanges([], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
dragSelect(e, 340, 20, 140);
|
|
||||||
checkText('bbbbbbbbcc', e);
|
|
||||||
checkRanges([[1,0,1,10]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test3');
|
|
||||||
dragSelect(e, 20, 340, 295);
|
|
||||||
checkText('aaaaaabbbbbbbb', e);
|
|
||||||
checkRanges([[0,1,0,15]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test4');
|
|
||||||
dragSelect(e, 20, 340);
|
|
||||||
checkText('aaaaaacc', e);
|
|
||||||
checkRanges([[0,1,1,0], [2,0,2,2]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test5');
|
|
||||||
dragSelect(e, 340, 20, 140);
|
|
||||||
checkText('bbbbbbbbcc', e);
|
|
||||||
checkRanges([[1,0,1,10]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test6');
|
|
||||||
dragSelect(e, 20, 340, 295);
|
|
||||||
checkText('aaaaaabbbbbbbb', e);
|
|
||||||
checkRanges([[0,1,0,15]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test7');
|
|
||||||
dragSelect(e, 20, 340);
|
|
||||||
checkText('aaaaaacccccc', e);
|
|
||||||
checkRanges([[0,1,1,0], [2,0,2,6]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test8');
|
|
||||||
dragSelect(e, 340, 20, 140);
|
|
||||||
checkText('bbbbbccccc', e);
|
|
||||||
checkRanges([[1,3,1,13]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test9');
|
|
||||||
dragSelect(e, 20, 340, 295);
|
|
||||||
checkText('aaaaaabbbbbbbb', e);
|
|
||||||
checkRanges([[0,1,0,15]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('testA');
|
|
||||||
dragSelect(e, 20, 340);
|
|
||||||
checkText('aaaaaaccccccc', e);
|
|
||||||
checkRanges([[0,1,2,7]], e);
|
|
||||||
checkRangeText('aaaaaabbbbbbbbccccccc', 0);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('testB');
|
|
||||||
dragSelect(e, 340, 20, 140);
|
|
||||||
checkText('bbbbbbbccccccc', e);
|
|
||||||
checkRanges([[1,1,1,15]], e);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test9');
|
|
||||||
dragSelect(e, 20, 340, 295);
|
|
||||||
checkText('aaaaaabbbbbbbb', e);
|
|
||||||
checkRanges([[0,1,0,15]], e);
|
|
||||||
|
|
||||||
// ======================================================
|
|
||||||
// ================== shift+click tests =================
|
|
||||||
// ======================================================
|
|
||||||
|
|
||||||
// test extending a selection that starts in a -moz-user-select:none node
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test2');
|
|
||||||
init([[0,0,0,1]], e);
|
|
||||||
checkRangeText('aaaaaaa', 0);
|
|
||||||
checkText('', e);
|
|
||||||
shiftClick(e, 340);
|
|
||||||
checkRangeText('bbbbbbbbcc', 0);
|
|
||||||
checkText('bbbbbbbbcc', e);
|
|
||||||
checkRanges([[-1,1,1,10]], e);
|
|
||||||
|
|
||||||
// test extending a selection that end in a -moz-user-select:none node
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('test3');
|
|
||||||
init([[1,0,1,1]], e);
|
|
||||||
checkRangeText('ccccccc', 0);
|
|
||||||
checkText('', e);
|
|
||||||
shiftClick(e, 20);
|
|
||||||
checkRangeText('aaaaaabbbbbbbb', 0);
|
|
||||||
checkText('aaaaaabbbbbbbb', e);
|
|
||||||
checkRanges([[0,1,-1,1]], e);
|
|
||||||
|
|
||||||
// ======================================================
|
|
||||||
// ==================== Script tests ====================
|
|
||||||
// ======================================================
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('testD');
|
|
||||||
clear(e.contentWindow);
|
|
||||||
sel = e.contentWindow.getSelection();
|
|
||||||
sel.selectAllChildren(e.contentDocument.body);
|
|
||||||
is(window.getSelection().rangeCount, 0, "testD: no selection in outer window");
|
|
||||||
is(sel.toString(), 'aaaacccc', "testD: scripted selection");
|
|
||||||
is(sel.rangeCount, 1, "testD: scripted selection isn't filtered");
|
|
||||||
is(sel.getRangeAt(0).toString(), 'aaaabbbbcccc', "testD: scripted selection isn't filtered");
|
|
||||||
|
|
||||||
// ======================================================
|
|
||||||
// ================== Kbd command tests =================
|
|
||||||
// ======================================================
|
|
||||||
|
|
||||||
clear();
|
|
||||||
e = document.getElementById('testD');
|
|
||||||
clear(e.contentWindow);
|
|
||||||
e.contentWindow.focus();
|
|
||||||
synthesizeKey("a", { accelKey:true }, e.contentWindow);
|
|
||||||
sel = e.contentWindow.getSelection();
|
|
||||||
is(window.getSelection().rangeCount, 0, "testD: no selection in outer window");
|
|
||||||
is(sel.toString(), 'aaaacccc', "testD: kbd selection");
|
|
||||||
is(sel.rangeCount, 2, "testD: kbd selection is filtered");
|
|
||||||
is(sel.getRangeAt(0).toString(), 'aaaa', "testD: kbd selection is filtered");
|
|
||||||
is(sel.getRangeAt(1).toString(), 'cccc', "testD: kbd selection is filtered");
|
|
||||||
|
|
||||||
clear();
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
window.onload = function() { setTimeout(test, 0); };
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "nsILinkHandler.h"
|
#include "nsILinkHandler.h"
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsISelectionListener.h"
|
#include "nsISelectionListener.h"
|
||||||
#include "mozilla/dom/Selection.h"
|
#include "nsISelectionPrivate.h"
|
||||||
#include "nsIDOMHTMLDocument.h"
|
#include "nsIDOMHTMLDocument.h"
|
||||||
#include "nsIDOMHTMLElement.h"
|
#include "nsIDOMHTMLElement.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
@@ -316,7 +316,7 @@ private:
|
|||||||
|
|
||||||
nsresult SyncParentSubDocMap();
|
nsresult SyncParentSubDocMap();
|
||||||
|
|
||||||
mozilla::dom::Selection* GetDocumentSelection();
|
nsresult GetDocumentSelection(nsISelection **aSelection);
|
||||||
|
|
||||||
void DestroyPresShell();
|
void DestroyPresShell();
|
||||||
void DestroyPresContext();
|
void DestroyPresContext();
|
||||||
@@ -704,12 +704,12 @@ nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow)
|
|||||||
mSelectionListener = selectionListener;
|
mSelectionListener = selectionListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
|
nsCOMPtr<nsISelection> selection;
|
||||||
if (!selection) {
|
rv = GetDocumentSelection(getter_AddRefs(selection));
|
||||||
return NS_ERROR_FAILURE;
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
|
|
||||||
rv = selection->AddSelectionListener(mSelectionListener);
|
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
|
||||||
|
rv = selPrivate->AddSelectionListener(mSelectionListener);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
@@ -2562,14 +2562,19 @@ nsDocumentViewer::CreateDeviceContext(nsView* aContainerView)
|
|||||||
|
|
||||||
// Return the selection for the document. Note that text fields have their
|
// Return the selection for the document. Note that text fields have their
|
||||||
// own selection, which cannot be accessed with this method.
|
// own selection, which cannot be accessed with this method.
|
||||||
mozilla::dom::Selection*
|
nsresult nsDocumentViewer::GetDocumentSelection(nsISelection **aSelection)
|
||||||
nsDocumentViewer::GetDocumentSelection()
|
|
||||||
{
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aSelection);
|
||||||
if (!mPresShell) {
|
if (!mPresShell) {
|
||||||
return nullptr;
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
|
nsCOMPtr<nsISelectionController> selcon;
|
||||||
|
selcon = do_QueryInterface(mPresShell);
|
||||||
|
if (selcon)
|
||||||
|
return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||||
|
aSelection);
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================================================================
|
/* ========================================================================================
|
||||||
@@ -2578,11 +2583,12 @@ nsDocumentViewer::GetDocumentSelection()
|
|||||||
|
|
||||||
NS_IMETHODIMP nsDocumentViewer::ClearSelection()
|
NS_IMETHODIMP nsDocumentViewer::ClearSelection()
|
||||||
{
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsISelection> selection;
|
||||||
|
|
||||||
// use nsCopySupport::GetSelectionForCopy() ?
|
// use nsCopySupport::GetSelectionForCopy() ?
|
||||||
nsRefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
|
rv = GetDocumentSelection(getter_AddRefs(selection));
|
||||||
if (!selection) {
|
if (NS_FAILED(rv)) return rv;
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return selection->CollapseToStart();
|
return selection->CollapseToStart();
|
||||||
}
|
}
|
||||||
@@ -2592,17 +2598,16 @@ NS_IMETHODIMP nsDocumentViewer::SelectAll()
|
|||||||
// XXX this is a temporary implementation copied from nsWebShell
|
// XXX this is a temporary implementation copied from nsWebShell
|
||||||
// for now. I think nsDocument and friends should have some helper
|
// for now. I think nsDocument and friends should have some helper
|
||||||
// functions to make this easier.
|
// functions to make this easier.
|
||||||
|
nsCOMPtr<nsISelection> selection;
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
// use nsCopySupport::GetSelectionForCopy() ?
|
// use nsCopySupport::GetSelectionForCopy() ?
|
||||||
nsRefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
|
rv = GetDocumentSelection(getter_AddRefs(selection));
|
||||||
if (!selection) {
|
if (NS_FAILED(rv)) return rv;
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMHTMLDocument> htmldoc = do_QueryInterface(mDocument);
|
nsCOMPtr<nsIDOMHTMLDocument> htmldoc = do_QueryInterface(mDocument);
|
||||||
nsCOMPtr<nsIDOMNode> bodyNode;
|
nsCOMPtr<nsIDOMNode> bodyNode;
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
if (htmldoc)
|
if (htmldoc)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMHTMLElement>bodyElement;
|
nsCOMPtr<nsIDOMHTMLElement>bodyElement;
|
||||||
@@ -2620,7 +2625,6 @@ NS_IMETHODIMP nsDocumentViewer::SelectAll()
|
|||||||
rv = selection->RemoveAllRanges();
|
rv = selection->RemoveAllRanges();
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
mozilla::dom::Selection::AutoApplyUserSelectStyle userSelection(selection);
|
|
||||||
rv = selection->SelectAllChildren(bodyNode);
|
rv = selection->SelectAllChildren(bodyNode);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -3544,10 +3548,9 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocumen
|
|||||||
NS_ASSERTION(mDocViewer, "Should have doc viewer!");
|
NS_ASSERTION(mDocViewer, "Should have doc viewer!");
|
||||||
|
|
||||||
// get the selection state
|
// get the selection state
|
||||||
nsRefPtr<mozilla::dom::Selection> selection = mDocViewer->GetDocumentSelection();
|
nsCOMPtr<nsISelection> selection;
|
||||||
if (!selection) {
|
nsresult rv = mDocViewer->GetDocumentSelection(getter_AddRefs(selection));
|
||||||
return NS_ERROR_FAILURE;
|
if (NS_FAILED(rv)) return rv;
|
||||||
}
|
|
||||||
|
|
||||||
nsIDocument* theDoc = mDocViewer->GetDocument();
|
nsIDocument* theDoc = mDocViewer->GetDocument();
|
||||||
if (!theDoc) return NS_ERROR_FAILURE;
|
if (!theDoc) return NS_ERROR_FAILURE;
|
||||||
@@ -4429,9 +4432,11 @@ nsDocumentViewer::DestroyPresShell()
|
|||||||
// Break circular reference (or something)
|
// Break circular reference (or something)
|
||||||
mPresShell->EndObservingDocument();
|
mPresShell->EndObservingDocument();
|
||||||
|
|
||||||
nsRefPtr<mozilla::dom::Selection> selection = GetDocumentSelection();
|
nsCOMPtr<nsISelection> selection;
|
||||||
if (selection && mSelectionListener)
|
GetDocumentSelection(getter_AddRefs(selection));
|
||||||
selection->RemoveSelectionListener(mSelectionListener);
|
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(selection);
|
||||||
|
if (selPrivate && mSelectionListener)
|
||||||
|
selPrivate->RemoveSelectionListener(mSelectionListener);
|
||||||
|
|
||||||
nsRefPtr<SelectionCarets> selectionCaret = mPresShell->GetSelectionCarets();
|
nsRefPtr<SelectionCarets> selectionCaret = mPresShell->GetSelectionCarets();
|
||||||
if (selectionCaret) {
|
if (selectionCaret) {
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
|
|
||||||
#include "nsIWeakReference.h"
|
#include "nsIWeakReference.h"
|
||||||
|
|
||||||
#include "mozilla/AutoRestore.h"
|
|
||||||
#include "mozilla/TextRange.h"
|
|
||||||
#include "nsISelection.h"
|
#include "nsISelection.h"
|
||||||
#include "nsISelectionController.h"
|
#include "nsISelectionController.h"
|
||||||
#include "nsISelectionPrivate.h"
|
#include "nsISelectionPrivate.h"
|
||||||
#include "nsRange.h"
|
#include "nsRange.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "mozilla/TextRange.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
struct CachedOffsetForFrame;
|
struct CachedOffsetForFrame;
|
||||||
@@ -101,14 +100,8 @@ public:
|
|||||||
int32_t aFlags = 0);
|
int32_t aFlags = 0);
|
||||||
nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract,
|
nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract,
|
||||||
nsTArray<RangeData>* aOutput);
|
nsTArray<RangeData>* aOutput);
|
||||||
/**
|
nsresult AddItem(nsRange *aRange, int32_t* aOutIndex);
|
||||||
* AddItem adds aRange to this Selection. If mApplyUserSelectStyle is true,
|
nsresult RemoveItem(nsRange *aRange);
|
||||||
* then aRange is first scanned for -moz-user-select:none nodes and split up
|
|
||||||
* into multiple ranges to exclude those before adding the resulting ranges
|
|
||||||
* to this Selection.
|
|
||||||
*/
|
|
||||||
nsresult AddItem(nsRange* aRange, int32_t* aOutIndex);
|
|
||||||
nsresult RemoveItem(nsRange* aRange);
|
|
||||||
nsresult RemoveCollapsedRanges();
|
nsresult RemoveCollapsedRanges();
|
||||||
nsresult Clear(nsPresContext* aPresContext);
|
nsresult Clear(nsPresContext* aPresContext);
|
||||||
nsresult Collapse(nsINode* aParentNode, int32_t aOffset);
|
nsresult Collapse(nsINode* aParentNode, int32_t aOffset);
|
||||||
@@ -212,19 +205,6 @@ public:
|
|||||||
|
|
||||||
nsresult NotifySelectionListeners();
|
nsresult NotifySelectionListeners();
|
||||||
|
|
||||||
friend struct AutoApplyUserSelectStyle;
|
|
||||||
struct MOZ_STACK_CLASS AutoApplyUserSelectStyle
|
|
||||||
{
|
|
||||||
AutoApplyUserSelectStyle(Selection* aSelection
|
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
||||||
: mSavedValue(aSelection->mApplyUserSelectStyle)
|
|
||||||
{
|
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
|
||||||
aSelection->mApplyUserSelectStyle = true;
|
|
||||||
}
|
|
||||||
AutoRestore<bool> mSavedValue;
|
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class ScrollSelectionIntoViewEvent;
|
class ScrollSelectionIntoViewEvent;
|
||||||
@@ -278,11 +258,6 @@ private:
|
|||||||
int32_t* aStartIndex, int32_t* aEndIndex);
|
int32_t* aStartIndex, int32_t* aEndIndex);
|
||||||
RangeData* FindRangeData(nsIDOMRange* aRange);
|
RangeData* FindRangeData(nsIDOMRange* aRange);
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for AddItem.
|
|
||||||
*/
|
|
||||||
nsresult AddItemInternal(nsRange* aRange, int32_t* aOutIndex);
|
|
||||||
|
|
||||||
// These are the ranges inside this selection. They are kept sorted in order
|
// These are the ranges inside this selection. They are kept sorted in order
|
||||||
// of DOM start position.
|
// of DOM start position.
|
||||||
//
|
//
|
||||||
@@ -306,11 +281,6 @@ private:
|
|||||||
CachedOffsetForFrame *mCachedOffsetForFrame;
|
CachedOffsetForFrame *mCachedOffsetForFrame;
|
||||||
nsDirection mDirection;
|
nsDirection mDirection;
|
||||||
SelectionType mType;
|
SelectionType mType;
|
||||||
/**
|
|
||||||
* True if the current selection operation was initiated by user action.
|
|
||||||
* It determines whether we exclude -moz-user-select:none nodes or not.
|
|
||||||
*/
|
|
||||||
bool mApplyUserSelectStyle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsISelectionController.h"
|
#include "nsISelectionController.h"
|
||||||
#include "nsISelectionListener.h"
|
|
||||||
#include "nsITableCellLayout.h"
|
#include "nsITableCellLayout.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "WordMovementType.h"
|
#include "WordMovementType.h"
|
||||||
@@ -614,18 +613,9 @@ private:
|
|||||||
int16_t PopReason()
|
int16_t PopReason()
|
||||||
{
|
{
|
||||||
int16_t retval = mSelectionChangeReason;
|
int16_t retval = mSelectionChangeReason;
|
||||||
mSelectionChangeReason = nsISelectionListener::NO_REASON;
|
mSelectionChangeReason = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
bool IsUserSelectionReason() const
|
|
||||||
{
|
|
||||||
return (mSelectionChangeReason &
|
|
||||||
(nsISelectionListener::DRAG_REASON |
|
|
||||||
nsISelectionListener::MOUSEDOWN_REASON |
|
|
||||||
nsISelectionListener::MOUSEUP_REASON |
|
|
||||||
nsISelectionListener::KEYPRESS_REASON)) !=
|
|
||||||
nsISelectionListener::NO_REASON;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class mozilla::dom::Selection;
|
friend class mozilla::dom::Selection;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|||||||
@@ -1548,11 +1548,6 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus,
|
|||||||
if (!mDomSelections[index])
|
if (!mDomSelections[index])
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
Maybe<Selection::AutoApplyUserSelectStyle> userSelect;
|
|
||||||
if (IsUserSelectionReason()) {
|
|
||||||
userSelect.emplace(mDomSelections[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//traverse through document and unselect crap here
|
//traverse through document and unselect crap here
|
||||||
if (!aContinueSelection) {//single click? setting cursor down
|
if (!aContinueSelection) {//single click? setting cursor down
|
||||||
uint32_t batching = mBatching;//hack to use the collapse code.
|
uint32_t batching = mBatching;//hack to use the collapse code.
|
||||||
@@ -3108,7 +3103,6 @@ Selection::Selection()
|
|||||||
: mCachedOffsetForFrame(nullptr)
|
: mCachedOffsetForFrame(nullptr)
|
||||||
, mDirection(eDirNext)
|
, mDirection(eDirNext)
|
||||||
, mType(nsISelectionController::SELECTION_NORMAL)
|
, mType(nsISelectionController::SELECTION_NORMAL)
|
||||||
, mApplyUserSelectStyle(false)
|
|
||||||
{
|
{
|
||||||
SetIsDOMBinding();
|
SetIsDOMBinding();
|
||||||
}
|
}
|
||||||
@@ -3118,7 +3112,6 @@ Selection::Selection(nsFrameSelection* aList)
|
|||||||
, mCachedOffsetForFrame(nullptr)
|
, mCachedOffsetForFrame(nullptr)
|
||||||
, mDirection(eDirNext)
|
, mDirection(eDirNext)
|
||||||
, mType(nsISelectionController::SELECTION_NORMAL)
|
, mType(nsISelectionController::SELECTION_NORMAL)
|
||||||
, mApplyUserSelectStyle(false)
|
|
||||||
{
|
{
|
||||||
SetIsDOMBinding();
|
SetIsDOMBinding();
|
||||||
}
|
}
|
||||||
@@ -3461,25 +3454,6 @@ Selection::AddItem(nsRange* aItem, int32_t* aOutIndex)
|
|||||||
|
|
||||||
NS_ASSERTION(aOutIndex, "aOutIndex can't be null");
|
NS_ASSERTION(aOutIndex, "aOutIndex can't be null");
|
||||||
|
|
||||||
if (mApplyUserSelectStyle) {
|
|
||||||
nsAutoTArray<nsRefPtr<nsRange>, 4> rangesToAdd;
|
|
||||||
aItem->ExcludeNonSelectableNodes(&rangesToAdd);
|
|
||||||
for (size_t i = 0; i < rangesToAdd.Length(); ++i) {
|
|
||||||
nsresult rv = AddItemInternal(rangesToAdd[i], aOutIndex);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
return AddItemInternal(aItem, aOutIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
Selection::AddItemInternal(nsRange* aItem, int32_t* aOutIndex)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aItem);
|
|
||||||
MOZ_ASSERT(aItem->IsPositioned());
|
|
||||||
MOZ_ASSERT(aOutIndex);
|
|
||||||
|
|
||||||
*aOutIndex = -1;
|
*aOutIndex = -1;
|
||||||
|
|
||||||
// a common case is that we have no ranges yet
|
// a common case is that we have no ranges yet
|
||||||
@@ -4469,7 +4443,8 @@ Selection::AddRange(nsRange& aRange, ErrorResult& aRv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!didAddRange) {
|
if (!didAddRange)
|
||||||
|
{
|
||||||
result = AddItem(&aRange, &rangeIndex);
|
result = AddItem(&aRange, &rangeIndex);
|
||||||
if (NS_FAILED(result)) {
|
if (NS_FAILED(result)) {
|
||||||
aRv.Throw(result);
|
aRv.Throw(result);
|
||||||
@@ -4477,10 +4452,7 @@ Selection::AddRange(nsRange& aRange, ErrorResult& aRv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rangeIndex < 0) {
|
NS_ASSERTION(rangeIndex >= 0, "Range index not returned");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAnchorFocusRange(rangeIndex);
|
setAnchorFocusRange(rangeIndex);
|
||||||
|
|
||||||
// Make sure the caret appears on the next line, if at a newline
|
// Make sure the caret appears on the next line, if at a newline
|
||||||
@@ -4949,48 +4921,7 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDirection dir = GetDirection();
|
//mFrameSelection->InvalidateDesiredX();
|
||||||
|
|
||||||
// If aParentNode is inside a range in a multi-range selection we need
|
|
||||||
// to remove the ranges that follows in the selection direction and
|
|
||||||
// make that range the mAnchorFocusRange.
|
|
||||||
if (mRanges.Length() > 1) {
|
|
||||||
for (size_t i = 0; i < mRanges.Length(); ++i) {
|
|
||||||
nsRange* range = mRanges[i].mRange;
|
|
||||||
bool disconnected1 = false;
|
|
||||||
bool disconnected2 = false;
|
|
||||||
const bool isBeforeStart =
|
|
||||||
nsContentUtils::ComparePoints(range->GetStartParent(),
|
|
||||||
range->StartOffset(),
|
|
||||||
&aParentNode, aOffset,
|
|
||||||
&disconnected1) > 0;
|
|
||||||
const bool isAfterEnd =
|
|
||||||
nsContentUtils::ComparePoints(range->GetEndParent(),
|
|
||||||
range->EndOffset(),
|
|
||||||
&aParentNode, aOffset,
|
|
||||||
&disconnected2) < 0;
|
|
||||||
if (!isBeforeStart && !isAfterEnd && !disconnected1 && !disconnected2) {
|
|
||||||
// aParentNode/aOffset is inside 'range'.
|
|
||||||
mAnchorFocusRange = range;
|
|
||||||
if (dir == eDirNext) {
|
|
||||||
for (size_t j = i + 1; j < mRanges.Length(); ++j) {
|
|
||||||
nsRange* r = mRanges[j].mRange;
|
|
||||||
r->SetInSelection(false);
|
|
||||||
selectFrames(presContext, r, false);
|
|
||||||
}
|
|
||||||
mRanges.TruncateLength(i + 1);
|
|
||||||
} else {
|
|
||||||
for (size_t j = 0; j < i; ++j) {
|
|
||||||
nsRange* r = mRanges[j].mRange;
|
|
||||||
r->SetInSelection(false);
|
|
||||||
selectFrames(presContext, r, false);
|
|
||||||
}
|
|
||||||
mRanges.RemoveElementsAt(0, i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsINode* anchorNode = GetAnchorNode();
|
nsINode* anchorNode = GetAnchorNode();
|
||||||
nsINode* focusNode = GetFocusNode();
|
nsINode* focusNode = GetFocusNode();
|
||||||
@@ -5004,6 +4935,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv)
|
|||||||
int32_t startOffset = range->StartOffset();
|
int32_t startOffset = range->StartOffset();
|
||||||
int32_t endOffset = range->EndOffset();
|
int32_t endOffset = range->EndOffset();
|
||||||
|
|
||||||
|
nsDirection dir = GetDirection();
|
||||||
|
|
||||||
//compare anchor to old cursor.
|
//compare anchor to old cursor.
|
||||||
|
|
||||||
// We pass |disconnected| to the following ComparePoints calls in order
|
// We pass |disconnected| to the following ComparePoints calls in order
|
||||||
@@ -5229,14 +5162,6 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRanges.Length() > 1) {
|
|
||||||
for (size_t i = 0; i < mRanges.Length(); ++i) {
|
|
||||||
nsRange* range = mRanges[i].mRange;
|
|
||||||
MOZ_ASSERT(range->IsInSelection());
|
|
||||||
selectFrames(presContext, range, range->IsInSelection());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_OUT_RANGE(range);
|
DEBUG_OUT_RANGE(range);
|
||||||
#ifdef DEBUG_SELECTION
|
#ifdef DEBUG_SELECTION
|
||||||
if (eDirNext == mDirection)
|
if (eDirNext == mDirection)
|
||||||
|
|||||||
Reference in New Issue
Block a user