зеркало из https://github.com/mozilla/pjs.git
r=bryner, sr=bzbarsky Patch from Rich Walsh - fix misidentification of anchor containing text blocks as anchors during drag/drop
This commit is contained in:
Родитель
c284457122
Коммит
2bc46bee24
|
@ -142,7 +142,7 @@ private:
|
||||||
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage** outImage);
|
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage** outImage);
|
||||||
static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
|
static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
|
||||||
nsAString& outLinkText);
|
nsAString& outLinkText);
|
||||||
static void FindFirstAnchor(nsIDOMNode* inNode, nsIDOMNode** outAnchor);
|
static void GetSelectedLink(nsISelection* inSelection, nsIDOMNode **outLinkNode);
|
||||||
|
|
||||||
enum serializationMode {serializeAsText, serializeAsHTML};
|
enum serializationMode {serializeAsText, serializeAsHTML};
|
||||||
// if inNode is null, use the selection from the window
|
// if inNode is null, use the selection from the window
|
||||||
|
@ -852,70 +852,6 @@ mFlavorDataProvider(inFlavorDataProvider)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// FindFirstAnchor
|
|
||||||
//
|
|
||||||
// A recursive routine that finds the first child link initiating anchor
|
|
||||||
//
|
|
||||||
void
|
|
||||||
nsTransferableFactory::FindFirstAnchor(nsIDOMNode* inNode, nsIDOMNode** outAnchor)
|
|
||||||
{
|
|
||||||
if ( !inNode && !outAnchor )
|
|
||||||
return;
|
|
||||||
*outAnchor = nsnull;
|
|
||||||
|
|
||||||
static NS_NAMED_LITERAL_STRING(simple, "simple");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> curr = inNode;
|
|
||||||
while ( curr ) {
|
|
||||||
// check me (base case of recursion)
|
|
||||||
PRUint16 nodeType = 0;
|
|
||||||
curr->GetNodeType(&nodeType);
|
|
||||||
if ( nodeType == nsIDOMNode::ELEMENT_NODE ) {
|
|
||||||
// a?
|
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> a(do_QueryInterface(curr));
|
|
||||||
if (a) {
|
|
||||||
*outAnchor = curr;
|
|
||||||
NS_ADDREF(*outAnchor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// area?
|
|
||||||
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(curr));
|
|
||||||
if (area) {
|
|
||||||
*outAnchor = curr;
|
|
||||||
NS_ADDREF(*outAnchor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple XLink?
|
|
||||||
nsCOMPtr<nsIContent> content(do_QueryInterface(curr));
|
|
||||||
NS_WARN_IF_FALSE(content, "DOM node is not content?");
|
|
||||||
if (!content)
|
|
||||||
return;
|
|
||||||
nsAutoString value;
|
|
||||||
content->GetAttr(kNameSpaceID_XLink, nsHTMLAtoms::type, value);
|
|
||||||
if (value.Equals(simple)) {
|
|
||||||
*outAnchor = curr;
|
|
||||||
NS_ADDREF(*outAnchor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// recursively check my children
|
|
||||||
nsCOMPtr<nsIDOMNode> firstChild;
|
|
||||||
curr->GetFirstChild(getter_AddRefs(firstChild));
|
|
||||||
FindFirstAnchor(firstChild, outAnchor);
|
|
||||||
if ( *outAnchor )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// check my siblings
|
|
||||||
nsIDOMNode* temp = nsnull;
|
|
||||||
curr->GetNextSibling(&temp);
|
|
||||||
curr = dont_AddRef(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FindParentLinkNode
|
// FindParentLinkNode
|
||||||
|
@ -1183,16 +1119,21 @@ nsTransferableFactory::Produce(nsITransferable** outTrans)
|
||||||
nsCOMPtr<nsIDOMNode> selectedImageOrLinkNode;
|
nsCOMPtr<nsIDOMNode> selectedImageOrLinkNode;
|
||||||
GetDraggableSelectionData(selection, realTargetNode, getter_AddRefs(selectedImageOrLinkNode), &haveSelectedContent);
|
GetDraggableSelectionData(selection, realTargetNode, getter_AddRefs(selectedImageOrLinkNode), &haveSelectedContent);
|
||||||
|
|
||||||
if (selectedImageOrLinkNode)
|
// either plain text or anchor text is selected
|
||||||
|
if (haveSelectedContent)
|
||||||
{
|
{
|
||||||
image = do_QueryInterface(selectedImageOrLinkNode);
|
|
||||||
link = do_QueryInterface(selectedImageOrLinkNode);
|
link = do_QueryInterface(selectedImageOrLinkNode);
|
||||||
useSelectedText = !image && link;
|
if (link && isAltKeyDown)
|
||||||
|
return NS_OK;
|
||||||
|
useSelectedText = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
// an image is selected
|
||||||
|
else if (selectedImageOrLinkNode)
|
||||||
|
image = do_QueryInterface(selectedImageOrLinkNode);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we're not using a selected element. Look for draggable elements
|
// nothing is selected -
|
||||||
// under the mouse
|
// look for draggable elements under the mouse
|
||||||
|
|
||||||
// if the alt key is down, don't start a drag if we're in an anchor because
|
// if the alt key is down, don't start a drag if we're in an anchor because
|
||||||
// we want to do selection.
|
// we want to do selection.
|
||||||
|
@ -1203,9 +1144,6 @@ nsTransferableFactory::Produce(nsITransferable** outTrans)
|
||||||
area = do_QueryInterface(draggedNode);
|
area = do_QueryInterface(draggedNode);
|
||||||
image = do_QueryInterface(draggedNode);
|
image = do_QueryInterface(draggedNode);
|
||||||
link = do_QueryInterface(draggedNode);
|
link = do_QueryInterface(draggedNode);
|
||||||
|
|
||||||
if (haveSelectedContent)
|
|
||||||
useSelectedText = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,10 +1202,9 @@ nsTransferableFactory::Produce(nsITransferable** outTrans)
|
||||||
}
|
}
|
||||||
else if (parentLink)
|
else if (parentLink)
|
||||||
{
|
{
|
||||||
|
// parentLink will always be null if there's selected content
|
||||||
linkNode = parentLink;
|
linkNode = parentLink;
|
||||||
nodeToSerialize = linkNode;
|
nodeToSerialize = linkNode;
|
||||||
if (haveSelectedContent)
|
|
||||||
useSelectedText = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
else if (!haveSelectedContent)
|
else if (!haveSelectedContent)
|
||||||
{
|
{
|
||||||
|
@ -1486,17 +1423,10 @@ nsresult nsTransferableFactory::GetDraggableSelectionData(nsISelection* inSelect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we didn't find an image, look for an anchor
|
// see if the selection is a link; if so, its node will be returned
|
||||||
nsCOMPtr<nsIDOMNode> firstAnchor;
|
GetSelectedLink(inSelection, outImageOrLinkNode);
|
||||||
FindFirstAnchor(selectionStart, getter_AddRefs(firstAnchor));
|
|
||||||
if (firstAnchor)
|
// indicate that a link or text is selected
|
||||||
{
|
|
||||||
PRBool anchorInSelection = PR_FALSE;
|
|
||||||
inSelection->ContainsNode(firstAnchor, PR_FALSE, &anchorInSelection);
|
|
||||||
if (anchorInSelection)
|
|
||||||
CallQueryInterface(firstAnchor, outImageOrLinkNode); // addrefs
|
|
||||||
}
|
|
||||||
|
|
||||||
*outDragSelectedText = PR_TRUE;
|
*outDragSelectedText = PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1504,6 +1434,118 @@ nsresult nsTransferableFactory::GetDraggableSelectionData(nsISelection* inSelect
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void nsTransferableFactory::GetSelectedLink(nsISelection* inSelection,
|
||||||
|
nsIDOMNode **outLinkNode)
|
||||||
|
{
|
||||||
|
*outLinkNode = nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> selectionStart;
|
||||||
|
inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
|
||||||
|
nsCOMPtr<nsIDOMNode> selectionEnd;
|
||||||
|
inSelection->GetFocusNode(getter_AddRefs(selectionEnd));
|
||||||
|
|
||||||
|
// simple case: only one node is selected
|
||||||
|
// see if it or its parent is an anchor, then exit
|
||||||
|
|
||||||
|
if (selectionStart == selectionEnd)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> link;
|
||||||
|
FindParentLinkNode(selectionStart, getter_AddRefs(link));
|
||||||
|
if (link)
|
||||||
|
NS_IF_ADDREF(*outLinkNode = link);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// more complicated case: multiple nodes are selected
|
||||||
|
|
||||||
|
// Unless you use the Alt key while selecting anchor text, it is
|
||||||
|
// nearly impossible to avoid overlapping into adjacent nodes.
|
||||||
|
// Deal with this by trimming off the leading and/or trailing
|
||||||
|
// nodes of the selection if the strings they produce are empty.
|
||||||
|
|
||||||
|
// first, use a range determine if the selection was marked LTR or RTL;
|
||||||
|
// if the latter, swap endpoints so we trim in the right direction
|
||||||
|
|
||||||
|
PRInt32 startOffset, endOffset;
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMRange> range;
|
||||||
|
inSelection->GetRangeAt(0, getter_AddRefs(range));
|
||||||
|
if (!range)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> tempNode;
|
||||||
|
range->GetStartContainer( getter_AddRefs(tempNode));
|
||||||
|
if (tempNode != selectionStart)
|
||||||
|
{
|
||||||
|
selectionEnd = selectionStart;
|
||||||
|
selectionStart = tempNode;
|
||||||
|
inSelection->GetAnchorOffset(&endOffset);
|
||||||
|
inSelection->GetFocusOffset(&startOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inSelection->GetAnchorOffset(&startOffset);
|
||||||
|
inSelection->GetFocusOffset(&endOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim leading node if the string is empty or
|
||||||
|
// the selection starts at the end of the text
|
||||||
|
|
||||||
|
nsAutoString nodeStr;
|
||||||
|
selectionStart->GetNodeValue(nodeStr);
|
||||||
|
if (nodeStr.IsEmpty() || startOffset+1 >= NS_STATIC_CAST(PRInt32, nodeStr.Length()))
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> curr = selectionStart;
|
||||||
|
nsIDOMNode* next;
|
||||||
|
while (curr)
|
||||||
|
{
|
||||||
|
curr->GetNextSibling(&next);
|
||||||
|
if (next)
|
||||||
|
{
|
||||||
|
selectionStart = dont_AddRef(next);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curr->GetParentNode(&next);
|
||||||
|
curr = dont_AddRef(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim trailing node if the selection ends before its text begins
|
||||||
|
|
||||||
|
if (endOffset == 0)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> curr = selectionEnd;
|
||||||
|
nsIDOMNode* next;
|
||||||
|
while (curr)
|
||||||
|
{
|
||||||
|
curr->GetPreviousSibling(&next);
|
||||||
|
if (next)
|
||||||
|
{
|
||||||
|
selectionEnd = dont_AddRef(next);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curr->GetParentNode(&next);
|
||||||
|
curr = dont_AddRef(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if the leading & trailing nodes are part of the
|
||||||
|
// same anchor - if so, return the anchor node
|
||||||
|
nsCOMPtr<nsIDOMNode> link;
|
||||||
|
FindParentLinkNode(selectionStart, getter_AddRefs(link));
|
||||||
|
if (link)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> link2;
|
||||||
|
FindParentLinkNode(selectionEnd, getter_AddRefs(link2));
|
||||||
|
if (link == link2)
|
||||||
|
NS_IF_ADDREF(*outLinkNode = link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
|
|
Загрузка…
Ссылка в новой задаче