Composer bugs: Drag and drop problems (47399, r=anthonyd), workaround for bad dragNdrop event (50703, r=nisheeth)
git-svn-id: svn://10.0.0.236/trunk@78187 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
1465df6c2d
commit
06f0642f0b
@ -474,9 +474,12 @@ nsRemoveListCommand::IsCommandEnabled(const PRUnichar *aCommand, nsISupports * r
|
||||
PRUnichar *tagStr;
|
||||
nsresult rv = editorShell->GetListState(&bMixed, &tagStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*outCmdEnabled = (tagStr && *tagStr != nsnull);
|
||||
|
||||
if (bMixed)
|
||||
*outCmdEnabled = PR_TRUE;
|
||||
else
|
||||
*outCmdEnabled = (tagStr && *tagStr);
|
||||
|
||||
if (tagStr) nsCRT::free(tagStr);
|
||||
}
|
||||
|
||||
|
||||
@ -682,11 +682,11 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIDragService, dragService, "component://netscape/widget/dragservice", &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
|
||||
if (dragSession)
|
||||
{
|
||||
{
|
||||
PRBool flavorSupported = PR_FALSE;
|
||||
dragSession->IsDataFlavorSupported(kUnicodeMime, &flavorSupported);
|
||||
if ( !flavorSupported )
|
||||
@ -696,54 +696,73 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent)
|
||||
if ( !flavorSupported )
|
||||
dragSession->IsDataFlavorSupported(kJPEGImageMime, &flavorSupported);
|
||||
if (! flavorSupported )
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aMouseEvent));
|
||||
if (!nsuiEvent) return NS_OK;
|
||||
|
||||
//some day we want to use another way to stop this from bubbling.
|
||||
aMouseEvent->PreventBubble();
|
||||
aMouseEvent->PreventDefault();
|
||||
|
||||
/* for bug 47399, when dropping a drag session, if you are over your original
|
||||
selection, nothing should happen. */
|
||||
nsCOMPtr<nsIDOMSelection> tempSelection;
|
||||
rv = mEditor->GetSelection(getter_AddRefs(tempSelection));
|
||||
if (NS_FAILED(rv) || !tempSelection)
|
||||
selection, nothing should happen.
|
||||
cmanske: But do this only if drag source is not the same as target (current) document!
|
||||
*/
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
rv = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv) || !selection)
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 rangeCount;
|
||||
rv = tempSelection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv))
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor);
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
rv = editor->GetDocument(getter_AddRefs(domdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for(int i = 0; i < rangeCount; i++)
|
||||
nsCOMPtr<nsIDOMDocument> sourceDoc;
|
||||
rv = dragSession->GetSourceDocument(getter_AddRefs(sourceDoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (domdoc == sourceDoc)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Don't bother if collapsed - can always drop
|
||||
if (!isCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
rv = nsuiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = tempSelection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
PRInt32 offset = 0;
|
||||
rv = nsuiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
PRInt32 rangeCount;
|
||||
rv = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aMouseEvent));
|
||||
if (!nsuiEvent)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent))))
|
||||
continue;//dont bail yet, iterate through them all
|
||||
rv = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
PRInt32 offset = 0;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset)))
|
||||
continue;//dont bail yet, iterate through them all
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
PRBool inrange;
|
||||
rv = nsrange->IsPointInRange(parent, offset, &inrange);
|
||||
if(inrange)
|
||||
return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection
|
||||
PRBool inrange;
|
||||
rv = nsrange->IsPointInRange(parent, offset, &inrange);
|
||||
if(inrange)
|
||||
return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we are not over orginal selection, drop that baby!
|
||||
return htmlEditor->InsertFromDrop(aMouseEvent);
|
||||
|
||||
@ -31,10 +31,16 @@
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNSRange.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsIDOMHTMLTableElement.h"
|
||||
#include "nsIDOMHTMLTableCellElement.h"
|
||||
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
|
||||
/*
|
||||
* nsEditorShellMouseListener implementation
|
||||
*/
|
||||
@ -160,104 +166,144 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint16 buttonNumber;
|
||||
nsresult res = mouseEvent->GetButton(&buttonNumber);
|
||||
// Don't do anything special if not an HTML editor
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
nsresult res = mEditorShell->GetEditor(getter_AddRefs(editor));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool isContextClick;
|
||||
// Test if special 'table selection' key is pressed when double-clicking
|
||||
// so we look for an enclosing cell or table
|
||||
PRBool tableMode = PR_FALSE;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// Cmd is Mac table-select key
|
||||
res = mouseEvent->GetMetaKey(&tableMode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
#else
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 3;
|
||||
res = mouseEvent->GetCtrlKey(&tableMode);
|
||||
#endif
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool NodeIsInSelection = PR_FALSE;
|
||||
|
||||
if (isContextClick || (buttonNumber == 1 && clickCount == 2))
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
// Context menu or double click
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node)
|
||||
PRUint16 buttonNumber;
|
||||
res = mouseEvent->GetButton(&buttonNumber);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool isContextClick;
|
||||
// Test if special 'table selection' key is pressed when double-clicking
|
||||
// so we look for an enclosing cell or table
|
||||
PRBool tableMode = PR_FALSE;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// Cmd is Mac table-select key
|
||||
res = mouseEvent->GetMetaKey(&tableMode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
#else
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 3;
|
||||
res = mouseEvent->GetCtrlKey(&tableMode);
|
||||
#endif
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
mEditorShell->GetEditorSelection(getter_AddRefs(selection));
|
||||
if (!selection) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset = 0;
|
||||
|
||||
// Get location of mouse within target node
|
||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aMouseEvent);
|
||||
if (!uiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Detect if mouse point is withing current selection
|
||||
PRBool NodeIsInSelection = PR_FALSE;
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
|
||||
if (!isCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
mEditorShell->GetEditorSelection(getter_AddRefs(selection));
|
||||
if (selection)
|
||||
PRInt32 rangeCount;
|
||||
res = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
res = selection->ContainsNode(node, PR_TRUE, &NodeIsInSelection);
|
||||
// Kludge: We really want to reposition the caret exactly as done for
|
||||
// left mouse button, but we never reach the frame's HandlePress method.
|
||||
// Thus for text nodes, the best we can do is reposition to the start of the node,
|
||||
// but only if not already selected, of course
|
||||
if (!NodeIsInSelection)
|
||||
selection->Collapse(node, 0);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
res = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(res) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(res) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
res = nsrange->IsPointInRange(parent, offset, &NodeIsInSelection);
|
||||
}
|
||||
|
||||
// Get enclosing link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (isContextClick)
|
||||
{
|
||||
// Set selection to node clicked on if NOT within an existing selection
|
||||
if (element && !NodeIsInSelection)
|
||||
mEditorShell->SelectElement(element);
|
||||
// Always fall through to do other actions, such as context menu
|
||||
}
|
||||
else if (buttonNumber == 1)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
// printf("nsEditorShellMouseListener::MouseDown: clickCount=%d\n",clickCount);
|
||||
#endif
|
||||
|
||||
if (tableMode && clickCount == 2)
|
||||
if (isContextClick || (buttonNumber == 1 && clickCount == 2))
|
||||
{
|
||||
if (!GetParentCell(aMouseEvent, getter_AddRefs(element)))
|
||||
GetParentTable(aMouseEvent, getter_AddRefs(element));
|
||||
// Context menu or double click
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node && !NodeIsInSelection)
|
||||
{
|
||||
selection->Collapse(parent, offset);
|
||||
|
||||
// Get enclosing link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
}
|
||||
}
|
||||
// No table or cell -- look for other element (ignore text nodes)
|
||||
if (element)
|
||||
|
||||
if (isContextClick)
|
||||
{
|
||||
PRInt32 x,y;
|
||||
res = mouseEvent->GetClientX(&x);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// Set selection to node clicked on if NOT within an existing selection
|
||||
if (element && !NodeIsInSelection)
|
||||
mEditorShell->SelectElement(element);
|
||||
// Always fall through to do other actions, such as context menu
|
||||
}
|
||||
else if (buttonNumber == 1)
|
||||
{
|
||||
if (tableMode && clickCount == 2)
|
||||
{
|
||||
if (!GetParentCell(aMouseEvent, getter_AddRefs(element)))
|
||||
GetParentTable(aMouseEvent, getter_AddRefs(element));
|
||||
}
|
||||
// No table or cell -- look for other element (ignore text nodes)
|
||||
if (element)
|
||||
{
|
||||
PRInt32 x,y;
|
||||
res = mouseEvent->GetClientX(&x);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = mouseEvent->GetClientY(&y);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mouseEvent->GetClientY(&y);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Let editor decide what to do with this
|
||||
PRBool handled = PR_FALSE;
|
||||
mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled);
|
||||
// KLUDGE to work around bug 50703: Prevent drag/drop events until we are done
|
||||
if (clickCount == 2)
|
||||
htmlEditor->IgnoreSpuriousDragEvent(PR_TRUE);
|
||||
|
||||
if (handled)
|
||||
mouseEvent->PreventDefault();
|
||||
// Let editor decide what to do with this
|
||||
PRBool handled = PR_FALSE;
|
||||
mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled);
|
||||
|
||||
if (handled)
|
||||
mouseEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,10 +313,7 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
nsresult
|
||||
nsEditorShellMouseListener::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
printf("* nsEditorShellMouseListener::MouseUp message\n");
|
||||
#endif
|
||||
return NS_OK; // didn't handle event
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
@ -239,6 +239,7 @@ nsHTMLEditor::nsHTMLEditor()
|
||||
, mIsComposing(PR_FALSE)
|
||||
, mMaxTextLength(-1)
|
||||
, mSelectedCellIndex(0)
|
||||
, mIgnoreSpuriousDragEvent(PR_FALSE)
|
||||
{
|
||||
// Done in nsEditor
|
||||
// NS_INIT_REFCNT();
|
||||
@ -2620,7 +2621,7 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsString &aSourceToInsert)
|
||||
res = nsrange->CreateContextualFragment(inputString,
|
||||
getter_AddRefs(docfrag));
|
||||
|
||||
//XXXX BUG: This is not returning the text between <title> ... </title>
|
||||
//XXXX BUG 50965: This is not returning the text between <title> ... </title>
|
||||
// Special code is needed in JS to handle title anyway, so it really doesn't matter!
|
||||
|
||||
if (NS_FAILED(res))
|
||||
@ -5000,7 +5001,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
@ -5011,74 +5011,150 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
|
||||
|
||||
if (dragSession)
|
||||
if (!dragSession) return NS_OK;
|
||||
|
||||
// Get the nsITransferable interface for getting the data from the drop
|
||||
nsCOMPtr<nsITransferable> trans;
|
||||
rv = PrepareTransferable(getter_AddRefs(trans));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!trans) return NS_OK; // NS_ERROR_FAILURE; SHOULD WE FAIL?
|
||||
|
||||
PRUint32 numItems = 0;
|
||||
rv = dragSession->GetNumDropItems(&numItems);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Combine any deletion and drop insertion into one transaction
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
|
||||
PRUint32 i;
|
||||
PRBool doPlaceCaret = PR_TRUE;
|
||||
for (i = 0; i < numItems; ++i)
|
||||
{
|
||||
// Get the nsITransferable interface for getting the data from the drop
|
||||
nsCOMPtr<nsITransferable> trans;
|
||||
rv = PrepareTransferable(getter_AddRefs(trans));
|
||||
if (NS_SUCCEEDED(rv) && trans)
|
||||
rv = dragSession->GetData(trans, i);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!trans) return NS_OK; // NS_ERROR_FAILURE; Should we fail?
|
||||
|
||||
if ( doPlaceCaret )
|
||||
{
|
||||
PRUint32 numItems = 0;
|
||||
if (NS_SUCCEEDED(dragSession->GetNumDropItems(&numItems)))
|
||||
{
|
||||
PRUint32 i;
|
||||
PRBool doPlaceCaret = PR_TRUE;
|
||||
for (i = 0; i < numItems; ++i)
|
||||
{
|
||||
if (NS_SUCCEEDED(dragSession->GetData(trans, i)))
|
||||
{
|
||||
if ( doPlaceCaret )
|
||||
{
|
||||
// check if the user pressed the key to force a copy rather than a move
|
||||
// if we run into problems here, we'll just assume the user doesn't want a copy
|
||||
PRBool userWantsCopy = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDropEvent) );
|
||||
if (mouseEvent)
|
||||
// check if the user pressed the key to force a copy rather than a move
|
||||
// if we run into problems here, we'll just assume the user doesn't want a copy
|
||||
PRBool userWantsCopy = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aDropEvent));
|
||||
if (!nsuiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDropEvent) );
|
||||
if (mouseEvent)
|
||||
|
||||
#ifdef XP_MAC
|
||||
mouseEvent->GetAltKey(&userWantsCopy); // check modifiers here
|
||||
mouseEvent->GetAltKey(&userWantsCopy);
|
||||
#else
|
||||
mouseEvent->GetCtrlKey(&userWantsCopy); // check modifiers here
|
||||
mouseEvent->GetCtrlKey(&userWantsCopy);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> srcdomdoc;
|
||||
dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
|
||||
if (srcdomdoc)
|
||||
{
|
||||
// do deletion of selection if sourcedocument is current document && appropriate modifier isn't pressed
|
||||
nsCOMPtr<nsIDOMDocument>destdomdoc;
|
||||
rv = GetDocument(getter_AddRefs(destdomdoc));
|
||||
if ( NS_SUCCEEDED(rv) && !userWantsCopy && (srcdomdoc == destdomdoc) )
|
||||
{
|
||||
rv = DeleteSelection(eNone);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// Source doc is null if source is *not* the current editor document
|
||||
nsCOMPtr<nsIDOMDocument> srcdomdoc;
|
||||
rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Set the selection to the point under the mouse cursor:
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aDropEvent));
|
||||
// Current doc is destination
|
||||
nsCOMPtr<nsIDOMDocument>destdomdoc;
|
||||
rv = GetDocument(getter_AddRefs(destdomdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!nsuiEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent))))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 offset = 0;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset)))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
rv = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!selection) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
if (NS_SUCCEEDED(GetSelection(getter_AddRefs(selection))))
|
||||
(void)selection->Collapse(parent, offset);
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Parent and offset under the mouse cursor
|
||||
nsCOMPtr<nsIDOMNode> newSelectionParent;
|
||||
PRInt32 newSelectionOffset = 0;
|
||||
rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!newSelectionParent) return NS_ERROR_FAILURE;
|
||||
|
||||
doPlaceCaret = PR_FALSE;
|
||||
}
|
||||
|
||||
rv = InsertFromTransferable(trans);
|
||||
rv = nsuiEvent->GetRangeOffset(&newSelectionOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// We never have to delete if selection is already collapsed
|
||||
PRBool deleteSelection = PR_FALSE;
|
||||
PRBool cursorIsInSelection = PR_FALSE;
|
||||
|
||||
// Check if mouse is in the selection
|
||||
if (!isCollapsed)
|
||||
{
|
||||
PRInt32 rangeCount;
|
||||
rv = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv))
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
|
||||
for (PRInt32 j = 0; j < rangeCount; j++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
rv = selection->GetRangeAt(j, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
rv = nsrange->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
|
||||
if(cursorIsInSelection)
|
||||
break;
|
||||
}
|
||||
if (cursorIsInSelection)
|
||||
{
|
||||
// Dragging within same doc can't drop on itself -- leave!
|
||||
// (We shouldn't get here - drag event shouldn't have started if over selection)
|
||||
if (srcdomdoc == destdomdoc)
|
||||
return NS_OK;
|
||||
|
||||
// Dragging from another window onto a selection
|
||||
// XXX Decision made to NOT do this,
|
||||
// note that 4.x does replace if dropped on
|
||||
//deleteSelection = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are NOT over the selection
|
||||
if (srcdomdoc == destdomdoc)
|
||||
{
|
||||
// Within the same doc: delete if user doesn't want to copy
|
||||
deleteSelection = !userWantsCopy;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Different source doc: Don't delete
|
||||
deleteSelection = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteSelection)
|
||||
{
|
||||
rv = DeleteSelection(eNone);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// If we deleted the selection because we dropped from another doc,
|
||||
// then we don't have to relocate the caret (insert at the deletion point)
|
||||
if (!(deleteSelection && srcdomdoc != destdomdoc))
|
||||
{
|
||||
// Move the selection to the point under the mouse cursor
|
||||
selection->Collapse(newSelectionParent, newSelectionOffset);
|
||||
}
|
||||
|
||||
// We have to figure out whether to delete and relocate caret only once
|
||||
doPlaceCaret = PR_FALSE;
|
||||
}
|
||||
|
||||
rv = InsertFromTransferable(trans);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -5090,7 +5166,19 @@ NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool &aCanDrag)
|
||||
* that particular point is actually within the selection (not just that there is a selection)
|
||||
*/
|
||||
aCanDrag = PR_FALSE;
|
||||
|
||||
|
||||
// KLUDGE to work around bug 50703
|
||||
// After double click and object property editing,
|
||||
// we get a spurious drag event
|
||||
if (mIgnoreSpuriousDragEvent)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
printf(" *** IGNORING SPURIOUS DRAG EVENT!\n");
|
||||
#endif
|
||||
mIgnoreSpuriousDragEvent = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
@ -577,6 +577,10 @@ protected:
|
||||
|
||||
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);
|
||||
|
||||
//XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
|
||||
PRBool mIgnoreSpuriousDragEvent;
|
||||
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
||||
@ -474,9 +474,12 @@ nsRemoveListCommand::IsCommandEnabled(const PRUnichar *aCommand, nsISupports * r
|
||||
PRUnichar *tagStr;
|
||||
nsresult rv = editorShell->GetListState(&bMixed, &tagStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*outCmdEnabled = (tagStr && *tagStr != nsnull);
|
||||
|
||||
if (bMixed)
|
||||
*outCmdEnabled = PR_TRUE;
|
||||
else
|
||||
*outCmdEnabled = (tagStr && *tagStr);
|
||||
|
||||
if (tagStr) nsCRT::free(tagStr);
|
||||
}
|
||||
|
||||
|
||||
@ -31,10 +31,16 @@
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNSRange.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsIDOMHTMLTableElement.h"
|
||||
#include "nsIDOMHTMLTableCellElement.h"
|
||||
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
|
||||
/*
|
||||
* nsEditorShellMouseListener implementation
|
||||
*/
|
||||
@ -160,104 +166,144 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint16 buttonNumber;
|
||||
nsresult res = mouseEvent->GetButton(&buttonNumber);
|
||||
// Don't do anything special if not an HTML editor
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
nsresult res = mEditorShell->GetEditor(getter_AddRefs(editor));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool isContextClick;
|
||||
// Test if special 'table selection' key is pressed when double-clicking
|
||||
// so we look for an enclosing cell or table
|
||||
PRBool tableMode = PR_FALSE;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// Cmd is Mac table-select key
|
||||
res = mouseEvent->GetMetaKey(&tableMode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
#else
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 3;
|
||||
res = mouseEvent->GetCtrlKey(&tableMode);
|
||||
#endif
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool NodeIsInSelection = PR_FALSE;
|
||||
|
||||
if (isContextClick || (buttonNumber == 1 && clickCount == 2))
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
// Context menu or double click
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node)
|
||||
PRUint16 buttonNumber;
|
||||
res = mouseEvent->GetButton(&buttonNumber);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool isContextClick;
|
||||
// Test if special 'table selection' key is pressed when double-clicking
|
||||
// so we look for an enclosing cell or table
|
||||
PRBool tableMode = PR_FALSE;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// Cmd is Mac table-select key
|
||||
res = mouseEvent->GetMetaKey(&tableMode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
#else
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 3;
|
||||
res = mouseEvent->GetCtrlKey(&tableMode);
|
||||
#endif
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
mEditorShell->GetEditorSelection(getter_AddRefs(selection));
|
||||
if (!selection) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset = 0;
|
||||
|
||||
// Get location of mouse within target node
|
||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aMouseEvent);
|
||||
if (!uiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Detect if mouse point is withing current selection
|
||||
PRBool NodeIsInSelection = PR_FALSE;
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
|
||||
if (!isCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
mEditorShell->GetEditorSelection(getter_AddRefs(selection));
|
||||
if (selection)
|
||||
PRInt32 rangeCount;
|
||||
res = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
res = selection->ContainsNode(node, PR_TRUE, &NodeIsInSelection);
|
||||
// Kludge: We really want to reposition the caret exactly as done for
|
||||
// left mouse button, but we never reach the frame's HandlePress method.
|
||||
// Thus for text nodes, the best we can do is reposition to the start of the node,
|
||||
// but only if not already selected, of course
|
||||
if (!NodeIsInSelection)
|
||||
selection->Collapse(node, 0);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
res = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(res) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(res) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
res = nsrange->IsPointInRange(parent, offset, &NodeIsInSelection);
|
||||
}
|
||||
|
||||
// Get enclosing link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (isContextClick)
|
||||
{
|
||||
// Set selection to node clicked on if NOT within an existing selection
|
||||
if (element && !NodeIsInSelection)
|
||||
mEditorShell->SelectElement(element);
|
||||
// Always fall through to do other actions, such as context menu
|
||||
}
|
||||
else if (buttonNumber == 1)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
// printf("nsEditorShellMouseListener::MouseDown: clickCount=%d\n",clickCount);
|
||||
#endif
|
||||
|
||||
if (tableMode && clickCount == 2)
|
||||
if (isContextClick || (buttonNumber == 1 && clickCount == 2))
|
||||
{
|
||||
if (!GetParentCell(aMouseEvent, getter_AddRefs(element)))
|
||||
GetParentTable(aMouseEvent, getter_AddRefs(element));
|
||||
// Context menu or double click
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node && !NodeIsInSelection)
|
||||
{
|
||||
selection->Collapse(parent, offset);
|
||||
|
||||
// Get enclosing link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
}
|
||||
}
|
||||
// No table or cell -- look for other element (ignore text nodes)
|
||||
if (element)
|
||||
|
||||
if (isContextClick)
|
||||
{
|
||||
PRInt32 x,y;
|
||||
res = mouseEvent->GetClientX(&x);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// Set selection to node clicked on if NOT within an existing selection
|
||||
if (element && !NodeIsInSelection)
|
||||
mEditorShell->SelectElement(element);
|
||||
// Always fall through to do other actions, such as context menu
|
||||
}
|
||||
else if (buttonNumber == 1)
|
||||
{
|
||||
if (tableMode && clickCount == 2)
|
||||
{
|
||||
if (!GetParentCell(aMouseEvent, getter_AddRefs(element)))
|
||||
GetParentTable(aMouseEvent, getter_AddRefs(element));
|
||||
}
|
||||
// No table or cell -- look for other element (ignore text nodes)
|
||||
if (element)
|
||||
{
|
||||
PRInt32 x,y;
|
||||
res = mouseEvent->GetClientX(&x);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = mouseEvent->GetClientY(&y);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mouseEvent->GetClientY(&y);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Let editor decide what to do with this
|
||||
PRBool handled = PR_FALSE;
|
||||
mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled);
|
||||
// KLUDGE to work around bug 50703: Prevent drag/drop events until we are done
|
||||
if (clickCount == 2)
|
||||
htmlEditor->IgnoreSpuriousDragEvent(PR_TRUE);
|
||||
|
||||
if (handled)
|
||||
mouseEvent->PreventDefault();
|
||||
// Let editor decide what to do with this
|
||||
PRBool handled = PR_FALSE;
|
||||
mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled);
|
||||
|
||||
if (handled)
|
||||
mouseEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,10 +313,7 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
nsresult
|
||||
nsEditorShellMouseListener::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
printf("* nsEditorShellMouseListener::MouseUp message\n");
|
||||
#endif
|
||||
return NS_OK; // didn't handle event
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
@ -239,6 +239,7 @@ nsHTMLEditor::nsHTMLEditor()
|
||||
, mIsComposing(PR_FALSE)
|
||||
, mMaxTextLength(-1)
|
||||
, mSelectedCellIndex(0)
|
||||
, mIgnoreSpuriousDragEvent(PR_FALSE)
|
||||
{
|
||||
// Done in nsEditor
|
||||
// NS_INIT_REFCNT();
|
||||
@ -2620,7 +2621,7 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsString &aSourceToInsert)
|
||||
res = nsrange->CreateContextualFragment(inputString,
|
||||
getter_AddRefs(docfrag));
|
||||
|
||||
//XXXX BUG: This is not returning the text between <title> ... </title>
|
||||
//XXXX BUG 50965: This is not returning the text between <title> ... </title>
|
||||
// Special code is needed in JS to handle title anyway, so it really doesn't matter!
|
||||
|
||||
if (NS_FAILED(res))
|
||||
@ -5000,7 +5001,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
@ -5011,74 +5011,150 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
|
||||
|
||||
if (dragSession)
|
||||
if (!dragSession) return NS_OK;
|
||||
|
||||
// Get the nsITransferable interface for getting the data from the drop
|
||||
nsCOMPtr<nsITransferable> trans;
|
||||
rv = PrepareTransferable(getter_AddRefs(trans));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!trans) return NS_OK; // NS_ERROR_FAILURE; SHOULD WE FAIL?
|
||||
|
||||
PRUint32 numItems = 0;
|
||||
rv = dragSession->GetNumDropItems(&numItems);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Combine any deletion and drop insertion into one transaction
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
|
||||
PRUint32 i;
|
||||
PRBool doPlaceCaret = PR_TRUE;
|
||||
for (i = 0; i < numItems; ++i)
|
||||
{
|
||||
// Get the nsITransferable interface for getting the data from the drop
|
||||
nsCOMPtr<nsITransferable> trans;
|
||||
rv = PrepareTransferable(getter_AddRefs(trans));
|
||||
if (NS_SUCCEEDED(rv) && trans)
|
||||
rv = dragSession->GetData(trans, i);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!trans) return NS_OK; // NS_ERROR_FAILURE; Should we fail?
|
||||
|
||||
if ( doPlaceCaret )
|
||||
{
|
||||
PRUint32 numItems = 0;
|
||||
if (NS_SUCCEEDED(dragSession->GetNumDropItems(&numItems)))
|
||||
{
|
||||
PRUint32 i;
|
||||
PRBool doPlaceCaret = PR_TRUE;
|
||||
for (i = 0; i < numItems; ++i)
|
||||
{
|
||||
if (NS_SUCCEEDED(dragSession->GetData(trans, i)))
|
||||
{
|
||||
if ( doPlaceCaret )
|
||||
{
|
||||
// check if the user pressed the key to force a copy rather than a move
|
||||
// if we run into problems here, we'll just assume the user doesn't want a copy
|
||||
PRBool userWantsCopy = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDropEvent) );
|
||||
if (mouseEvent)
|
||||
// check if the user pressed the key to force a copy rather than a move
|
||||
// if we run into problems here, we'll just assume the user doesn't want a copy
|
||||
PRBool userWantsCopy = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aDropEvent));
|
||||
if (!nsuiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDropEvent) );
|
||||
if (mouseEvent)
|
||||
|
||||
#ifdef XP_MAC
|
||||
mouseEvent->GetAltKey(&userWantsCopy); // check modifiers here
|
||||
mouseEvent->GetAltKey(&userWantsCopy);
|
||||
#else
|
||||
mouseEvent->GetCtrlKey(&userWantsCopy); // check modifiers here
|
||||
mouseEvent->GetCtrlKey(&userWantsCopy);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> srcdomdoc;
|
||||
dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
|
||||
if (srcdomdoc)
|
||||
{
|
||||
// do deletion of selection if sourcedocument is current document && appropriate modifier isn't pressed
|
||||
nsCOMPtr<nsIDOMDocument>destdomdoc;
|
||||
rv = GetDocument(getter_AddRefs(destdomdoc));
|
||||
if ( NS_SUCCEEDED(rv) && !userWantsCopy && (srcdomdoc == destdomdoc) )
|
||||
{
|
||||
rv = DeleteSelection(eNone);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// Source doc is null if source is *not* the current editor document
|
||||
nsCOMPtr<nsIDOMDocument> srcdomdoc;
|
||||
rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Set the selection to the point under the mouse cursor:
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aDropEvent));
|
||||
// Current doc is destination
|
||||
nsCOMPtr<nsIDOMDocument>destdomdoc;
|
||||
rv = GetDocument(getter_AddRefs(destdomdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!nsuiEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent))))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 offset = 0;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset)))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
rv = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!selection) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
if (NS_SUCCEEDED(GetSelection(getter_AddRefs(selection))))
|
||||
(void)selection->Collapse(parent, offset);
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Parent and offset under the mouse cursor
|
||||
nsCOMPtr<nsIDOMNode> newSelectionParent;
|
||||
PRInt32 newSelectionOffset = 0;
|
||||
rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!newSelectionParent) return NS_ERROR_FAILURE;
|
||||
|
||||
doPlaceCaret = PR_FALSE;
|
||||
}
|
||||
|
||||
rv = InsertFromTransferable(trans);
|
||||
rv = nsuiEvent->GetRangeOffset(&newSelectionOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// We never have to delete if selection is already collapsed
|
||||
PRBool deleteSelection = PR_FALSE;
|
||||
PRBool cursorIsInSelection = PR_FALSE;
|
||||
|
||||
// Check if mouse is in the selection
|
||||
if (!isCollapsed)
|
||||
{
|
||||
PRInt32 rangeCount;
|
||||
rv = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv))
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
|
||||
for (PRInt32 j = 0; j < rangeCount; j++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
rv = selection->GetRangeAt(j, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
rv = nsrange->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
|
||||
if(cursorIsInSelection)
|
||||
break;
|
||||
}
|
||||
if (cursorIsInSelection)
|
||||
{
|
||||
// Dragging within same doc can't drop on itself -- leave!
|
||||
// (We shouldn't get here - drag event shouldn't have started if over selection)
|
||||
if (srcdomdoc == destdomdoc)
|
||||
return NS_OK;
|
||||
|
||||
// Dragging from another window onto a selection
|
||||
// XXX Decision made to NOT do this,
|
||||
// note that 4.x does replace if dropped on
|
||||
//deleteSelection = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are NOT over the selection
|
||||
if (srcdomdoc == destdomdoc)
|
||||
{
|
||||
// Within the same doc: delete if user doesn't want to copy
|
||||
deleteSelection = !userWantsCopy;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Different source doc: Don't delete
|
||||
deleteSelection = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteSelection)
|
||||
{
|
||||
rv = DeleteSelection(eNone);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// If we deleted the selection because we dropped from another doc,
|
||||
// then we don't have to relocate the caret (insert at the deletion point)
|
||||
if (!(deleteSelection && srcdomdoc != destdomdoc))
|
||||
{
|
||||
// Move the selection to the point under the mouse cursor
|
||||
selection->Collapse(newSelectionParent, newSelectionOffset);
|
||||
}
|
||||
|
||||
// We have to figure out whether to delete and relocate caret only once
|
||||
doPlaceCaret = PR_FALSE;
|
||||
}
|
||||
|
||||
rv = InsertFromTransferable(trans);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -5090,7 +5166,19 @@ NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool &aCanDrag)
|
||||
* that particular point is actually within the selection (not just that there is a selection)
|
||||
*/
|
||||
aCanDrag = PR_FALSE;
|
||||
|
||||
|
||||
// KLUDGE to work around bug 50703
|
||||
// After double click and object property editing,
|
||||
// we get a spurious drag event
|
||||
if (mIgnoreSpuriousDragEvent)
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
printf(" *** IGNORING SPURIOUS DRAG EVENT!\n");
|
||||
#endif
|
||||
mIgnoreSpuriousDragEvent = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
@ -577,6 +577,10 @@ protected:
|
||||
|
||||
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);
|
||||
|
||||
//XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
|
||||
PRBool mIgnoreSpuriousDragEvent;
|
||||
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
||||
@ -682,11 +682,11 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIDragService, dragService, "component://netscape/widget/dragservice", &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
|
||||
if (dragSession)
|
||||
{
|
||||
{
|
||||
PRBool flavorSupported = PR_FALSE;
|
||||
dragSession->IsDataFlavorSupported(kUnicodeMime, &flavorSupported);
|
||||
if ( !flavorSupported )
|
||||
@ -696,54 +696,73 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent)
|
||||
if ( !flavorSupported )
|
||||
dragSession->IsDataFlavorSupported(kJPEGImageMime, &flavorSupported);
|
||||
if (! flavorSupported )
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aMouseEvent));
|
||||
if (!nsuiEvent) return NS_OK;
|
||||
|
||||
//some day we want to use another way to stop this from bubbling.
|
||||
aMouseEvent->PreventBubble();
|
||||
aMouseEvent->PreventDefault();
|
||||
|
||||
/* for bug 47399, when dropping a drag session, if you are over your original
|
||||
selection, nothing should happen. */
|
||||
nsCOMPtr<nsIDOMSelection> tempSelection;
|
||||
rv = mEditor->GetSelection(getter_AddRefs(tempSelection));
|
||||
if (NS_FAILED(rv) || !tempSelection)
|
||||
selection, nothing should happen.
|
||||
cmanske: But do this only if drag source is not the same as target (current) document!
|
||||
*/
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
rv = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv) || !selection)
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 rangeCount;
|
||||
rv = tempSelection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv))
|
||||
return rv?rv:NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor);
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
rv = editor->GetDocument(getter_AddRefs(domdoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for(int i = 0; i < rangeCount; i++)
|
||||
nsCOMPtr<nsIDOMDocument> sourceDoc;
|
||||
rv = dragSession->GetSourceDocument(getter_AddRefs(sourceDoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (domdoc == sourceDoc)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Don't bother if collapsed - can always drop
|
||||
if (!isCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
rv = nsuiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = tempSelection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
PRInt32 offset = 0;
|
||||
rv = nsuiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
PRInt32 rangeCount;
|
||||
rv = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aMouseEvent));
|
||||
if (!nsuiEvent)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent))))
|
||||
continue;//dont bail yet, iterate through them all
|
||||
rv = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv) || !range)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
PRInt32 offset = 0;
|
||||
if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset)))
|
||||
continue;//dont bail yet, iterate through them all
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(rv) || !nsrange)
|
||||
continue;//dont bail yet, iterate through them all
|
||||
|
||||
PRBool inrange;
|
||||
rv = nsrange->IsPointInRange(parent, offset, &inrange);
|
||||
if(inrange)
|
||||
return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection
|
||||
PRBool inrange;
|
||||
rv = nsrange->IsPointInRange(parent, offset, &inrange);
|
||||
if(inrange)
|
||||
return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we are not over orginal selection, drop that baby!
|
||||
return htmlEditor->InsertFromDrop(aMouseEvent);
|
||||
|
||||
@ -466,19 +466,26 @@ public:
|
||||
*/
|
||||
NS_IMETHOD InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)=0;
|
||||
|
||||
/**
|
||||
* Document me!
|
||||
*
|
||||
*/
|
||||
/** Set the value of the "bgcolor" attribute on the document's <body> element
|
||||
*
|
||||
* @param aColor The HTML color string, such as "#ffccff" or "yellow"
|
||||
*/
|
||||
NS_IMETHOD SetBackgroundColor(const nsString& aColor)=0;
|
||||
|
||||
|
||||
/**
|
||||
* Document me!
|
||||
*
|
||||
*/
|
||||
/** Set an attribute on the document's <body> element
|
||||
* such as text, link, background colors
|
||||
*
|
||||
* 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT?
|
||||
*
|
||||
* @param aAttr The attribute to be set
|
||||
* @param aValue The value of the attribute
|
||||
*/
|
||||
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue)=0;
|
||||
|
||||
//XXX Used to suppress spurious drag/drop events to workaround bug 50703
|
||||
// Don't use this method! It will go away after first release!
|
||||
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent)=0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -362,8 +362,6 @@ function ValidateAndPreviewImage(ShowErrorMessage)
|
||||
}
|
||||
else backgroundImage = null;
|
||||
|
||||
dump("ValidateAndPreviewImage: styleValue ="+styleValue+"\n");
|
||||
|
||||
// Set style on preview (removes image if not valid)
|
||||
dialog.ColorPreview.setAttribute(styleStr, styleValue);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user