Bug 499008, part 2, move editor dragstart handling to ContentAreaDragDrop, r=ehsan

This commit is contained in:
Neil Deakin 2012-02-17 09:16:59 -05:00
Родитель 2996ec9d75
Коммит 11d52d2eeb
12 изменённых файлов: 123 добавлений и 518 удалений

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsCopySupport.h"
#include "nsIDOMUIEvent.h"
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMEvent.h"
@ -70,6 +71,7 @@
#include "nsIDocShell.h"
#include "nsIContent.h"
#include "nsIImageLoadingContent.h"
#include "nsITextControlElement.h"
#include "nsUnicharUtils.h"
#include "nsIURL.h"
#include "nsIDocument.h"
@ -88,33 +90,6 @@
#define kHTMLContext "text/_moz_htmlcontext"
#define kHTMLInfo "text/_moz_htmlinfo"
// if aNode is null, use the selection from the window
static nsresult
GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow,
nsIContent* aNode,
nsITransferable** aTransferable)
{
NS_ENSURE_ARG_POINTER(aWindow);
nsCOMPtr<nsIDOMDocument> domDoc;
aWindow->GetDocument(getter_AddRefs(domDoc));
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
nsresult rv;
if (aNode) {
rv = nsCopySupport::GetTransferableForNode(aNode, doc, aTransferable);
} else {
nsCOMPtr<nsISelection> selection;
aWindow->GetSelection(getter_AddRefs(selection));
rv = nsCopySupport::GetTransferableForSelection(selection, doc,
aTransferable);
}
NS_ENSURE_SUCCESS(rv, rv);
return rv;
}
class NS_STACK_CLASS DragDataProducer
{
public:
@ -124,7 +99,7 @@ public:
bool aIsAltKeyPressed);
nsresult Produce(nsDOMDataTransfer* aDataTransfer,
bool* aCanDrag,
bool* aDragSelection,
nsISelection** aSelection,
nsIContent** aDragNode);
private:
@ -172,7 +147,7 @@ nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
bool aIsAltKeyPressed,
nsDOMDataTransfer* aDataTransfer,
bool* aCanDrag,
bool* aDragSelection,
nsISelection** aSelection,
nsIContent** aDragNode)
{
NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
@ -181,7 +156,7 @@ nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
DragDataProducer
provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
return provider.Produce(aDataTransfer, aCanDrag, aDragSelection, aDragNode);
return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode);
}
@ -412,10 +387,10 @@ DragDataProducer::GetNodeString(nsIContent* inNode,
nsresult
DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
bool* aCanDrag,
bool* aDragSelection,
nsISelection** aSelection,
nsIContent** aDragNode)
{
NS_PRECONDITION(aCanDrag && aDragSelection && aDataTransfer && aDragNode,
NS_PRECONDITION(aCanDrag && aSelection && aDataTransfer && aDragNode,
"null pointer passed to Produce");
NS_ASSERTION(mWindow, "window not set");
NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
@ -424,33 +399,72 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
nsresult rv;
nsIContent* dragNode = nsnull;
*aSelection = nsnull;
// find the selection to see what we could be dragging and if
// what we're dragging is in what is selected.
// Find the selection to see what we could be dragging and if what we're
// dragging is in what is selected. If this is an editable textbox, use
// the textbox's selection, otherwise use the window's selection.
nsCOMPtr<nsISelection> selection;
mWindow->GetSelection(getter_AddRefs(selection));
if (!selection) {
return NS_OK;
}
// check if the node is inside a form control. If so, dragging will be
// handled in editor code (nsPlaintextDataTransfer::DoDrag). Don't set
// aCanDrag to false however, as we still want to allow the drag.
nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
nsIContent* findFormParent = findFormNode->GetParent();
while (findFormParent) {
nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
if (form && !form->AllowDraggableChildren()) {
return NS_OK;
nsIContent* editingElement = mSelectionTargetNode->IsEditable() ?
mSelectionTargetNode->GetEditingHost() : nsnull;
nsCOMPtr<nsITextControlElement> textControl(do_QueryInterface(editingElement));
if (textControl) {
nsISelectionController* selcon = textControl->GetSelectionController();
if (selcon) {
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
if (!selection)
return NS_OK;
}
}
else {
mWindow->GetSelection(getter_AddRefs(selection));
if (!selection)
return NS_OK;
// Check if the node is inside a form control. Don't set aCanDrag to false
//however, as we still want to allow the drag.
nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
nsIContent* findFormParent = findFormNode->GetParent();
while (findFormParent) {
nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
if (form && !form->AllowDraggableChildren()) {
return NS_OK;
}
findFormParent = findFormParent->GetParent();
}
findFormParent = findFormParent->GetParent();
}
// if set, serialize the content under this node
nsCOMPtr<nsIContent> nodeToSerialize;
*aDragSelection = false;
{
bool isChromeShell = false;
nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mWindow);
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(webnav);
if (dsti) {
PRInt32 type = -1;
if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
type == nsIDocShellTreeItem::typeChrome) {
isChromeShell = true;
}
}
// In chrome shells, only allow dragging inside editable areas.
if (isChromeShell && !editingElement)
return NS_OK;
if (isChromeShell && textControl) {
// Only use the selection if it isn't collapsed.
bool isCollapsed = false;
selection->GetIsCollapsed(&isCollapsed);
if (!isCollapsed)
selection.swap(*aSelection);
}
else {
// In content shells, a number of checks are made below to determine
// whether an image or a link is being dragged. If so, add additional
// data to the data transfer. This is also done for chrome shells, but
// only when in a non-textbox editor.
bool haveSelectedContent = false;
// possible parent link node
@ -490,7 +504,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
return NS_OK;
}
*aDragSelection = true;
selection.swap(*aSelection);
} else if (selectedImageOrLinkNode) {
// an image is selected
image = do_QueryInterface(selectedImageOrLinkNode);
@ -660,20 +674,28 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
}
}
if (nodeToSerialize || *aDragSelection) {
// if we have selected text, use it in preference to the node
if (*aDragSelection) {
nodeToSerialize = nsnull;
}
if (nodeToSerialize || *aSelection) {
mHtmlString.Truncate();
mContextString.Truncate();
mInfoString.Truncate();
mTitleString.Truncate();
nsCOMPtr<nsIDOMDocument> domDoc;
mWindow->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
// if we have selected text, use it in preference to the node
nsCOMPtr<nsITransferable> transferable;
rv = ::GetTransferableForNodeOrSelection(mWindow, nodeToSerialize,
getter_AddRefs(transferable));
NS_ENSURE_SUCCESS(rv, rv);
if (*aSelection) {
rv = nsCopySupport::GetTransferableForSelection(*aSelection, doc,
getter_AddRefs(transferable));
}
else {
rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
getter_AddRefs(transferable));
}
nsCOMPtr<nsISupportsString> data;
PRUint32 dataSize;
rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
@ -747,15 +769,17 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
}
// add a special flavor, even if we don't have html context data
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
// add a special flavor for the html context data
if (!mContextString.IsEmpty())
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
// add a special flavor if we have html info data
if (!mInfoString.IsEmpty())
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
// add the full html
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
if (!mHtmlString.IsEmpty())
AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
// add the plain text. we use the url for text/plain data if an anchor is
// being dragged, rather than the title text of the link or the alt text for

Просмотреть файл

@ -78,8 +78,8 @@ public:
* aDataTransfer - the dataTransfer for the drag event.
* aCanDrag - [out] set to true if the drag may proceed, false to stop the
* drag entirely
* aDragSelection - [out] set to true to indicate that a selection is being
* dragged, rather than a specific node
* aSelection - [out] set to the selection being dragged, or null if no
* selection is being dragged.
* aDragNode - [out] the link, image or area being dragged, or null if the
* drag occurred on another element.
*/
@ -89,7 +89,7 @@ public:
bool aIsAltKeyPressed,
nsDOMDataTransfer* aDataTransfer,
bool* aCanDrag,
bool* aDragSelection,
nsISelection** aSelection,
nsIContent** aDragNode);
};

Просмотреть файл

@ -2081,14 +2081,12 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
if (!dataTransfer)
return;
bool isInEditor = false;
bool isSelection = false;
nsCOMPtr<nsISelection> selection;
nsCOMPtr<nsIContent> eventContent, targetContent;
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(eventContent));
if (eventContent)
DetermineDragTarget(aPresContext, eventContent, dataTransfer,
&isSelection, &isInEditor,
getter_AddRefs(targetContent));
getter_AddRefs(selection), getter_AddRefs(targetContent));
// Stop tracking the drag gesture now. This should stop us from
// reentering GenerateDragGesture inside DOM event processing.
@ -2129,9 +2127,8 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
// elements in an editor, only fire the draggesture event so that the
// editor code can handle it but content doesn't see a dragstart.
nsEventStatus status = nsEventStatus_eIgnore;
if (!isInEditor)
nsEventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nsnull,
&status);
nsEventDispatcher::Dispatch(targetContent, aPresContext, &startEvent, nsnull,
&status);
nsDragEvent* event = &startEvent;
if (status != nsEventStatus_eConsumeNoDefault) {
@ -2148,7 +2145,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
if (status != nsEventStatus_eConsumeNoDefault) {
bool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, isSelection);
targetContent, selection);
if (dragStarted) {
sActiveESM = nsnull;
aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
@ -2173,37 +2170,27 @@ void
nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
nsIContent* aSelectionTarget,
nsDOMDataTransfer* aDataTransfer,
bool* aIsSelection,
bool* aIsInEditor,
nsISelection** aSelection,
nsIContent** aTargetNode)
{
*aTargetNode = nsnull;
*aIsInEditor = false;
nsCOMPtr<nsISupports> container = aPresContext->GetContainer();
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
// GetDragData determines if a selection, link or image in the content
// should be dragged, and places the data associated with the drag in the
// data transfer. Skip this check for chrome shells.
// data transfer.
// mGestureDownContent is the node where the mousedown event for the drag
// occurred, and aSelectionTarget is the node to use when a selection is used
bool canDrag;
nsCOMPtr<nsIContent> dragDataNode;
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(container);
if (dsti) {
PRInt32 type = -1;
if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
type != nsIDocShellTreeItem::typeChrome) {
// mGestureDownContent is the node where the mousedown event for the drag
// occurred, and aSelectionTarget is the node to use when a selection is used
nsresult rv =
nsContentAreaDragDrop::GetDragData(window, mGestureDownContent,
aSelectionTarget, mGestureDownAlt,
aDataTransfer, &canDrag, aIsSelection,
getter_AddRefs(dragDataNode));
if (NS_FAILED(rv) || !canDrag)
return;
}
}
nsresult rv = nsContentAreaDragDrop::GetDragData(window, mGestureDownContent,
aSelectionTarget, mGestureDownAlt,
aDataTransfer, &canDrag, aSelection,
getter_AddRefs(dragDataNode));
if (NS_FAILED(rv) || !canDrag)
return;
// if GetDragData returned a node, use that as the node being dragged.
// Otherwise, if a selection is being dragged, use the node within the
@ -2211,7 +2198,7 @@ nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
nsIContent* dragContent = mGestureDownContent;
if (dragDataNode)
dragContent = dragDataNode;
else if (*aIsSelection)
else if (*aSelection)
dragContent = aSelectionTarget;
nsIContent* originalDragContent = dragContent;
@ -2220,7 +2207,7 @@ nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
// draggable property set. If one is found, use that as the target of the
// drag instead of the node that was clicked on. If a draggable node wasn't
// found, just use the clicked node.
if (!*aIsSelection) {
if (!*aSelection) {
while (dragContent) {
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(dragContent);
if (htmlElement) {
@ -2245,17 +2232,6 @@ nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
// otherwise, it's not an HTML or XUL element, so just keep looking
}
dragContent = dragContent->GetParent();
// if an editable parent is encountered, then we don't look at any
// ancestors. This is used because the editor attaches a draggesture
// listener to the editable element and we want to call it without
// making the editable element draggable. This should be removed once
// the editor is switched over to using the proper drag and drop api.
nsCOMPtr<nsIDOMNSEditableElement> editableElement = do_QueryInterface(dragContent);
if (editableElement) {
*aIsInEditor = true;
break;
}
}
}
@ -2279,7 +2255,7 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
nsDragEvent* aDragEvent,
nsDOMDataTransfer* aDataTransfer,
nsIContent* aDragTarget,
bool aIsSelection)
nsISelection* aSelection)
{
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
@ -2333,22 +2309,6 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
PRInt32 imageX, imageY;
nsIDOMElement* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
// If a selection is being dragged, and no custom drag image was
// set, get the selection so that the drag region can be created
// from the selection area. If a custom image was set, it doesn't
// matter what the selection is since the image will be used instead.
nsISelection* selection = nsnull;
if (aIsSelection && !dragImage) {
nsIDocument* doc = aDragTarget->GetCurrentDoc();
if (doc) {
nsIPresShell* presShell = doc->GetShell();
if (presShell) {
selection = presShell->GetCurrentSelection(
nsISelectionController::SELECTION_NORMAL);
}
}
}
nsCOMPtr<nsISupportsArray> transArray;
aDataTransfer->GetTransferables(getter_AddRefs(transArray));
if (!transArray)
@ -2363,8 +2323,13 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
nsCOMPtr<nsIDOMDragEvent> domDragEvent = do_QueryInterface(domEvent);
// if creating a drag event failed, starting a drag session will
// just fail.
if (selection) {
dragService->InvokeDragSessionWithSelection(selection, transArray,
// Use InvokeDragSessionWithSelection if a selection is being dragged,
// such that the image can be generated from the selected text. However,
// use InvokeDragSessionWithImage if a custom image was set or something
// other than a selection is being dragged.
if (!dragImage && aSelection) {
dragService->InvokeDragSessionWithSelection(aSelection, transArray,
action, domDragEvent,
aDataTransfer);
}

Просмотреть файл

@ -417,15 +417,13 @@ protected:
*
* aSelectionTarget - target to check for selection
* aDataTransfer - data transfer object that will contain the data to drag
* aIsSelection - [out] set to true if a selection is being dragged
* aIsInEditor - [out] set to true if the content is in an editor field
* aSelection - [out] set to the selection to be dragged
* aTargetNode - [out] the draggable node, or null if there isn't one
*/
void DetermineDragTarget(nsPresContext* aPresContext,
nsIContent* aSelectionTarget,
nsDOMDataTransfer* aDataTransfer,
bool* aIsSelection,
bool* aIsInEditor,
nsISelection** aSelection,
nsIContent** aTargetNode);
/*
@ -436,13 +434,13 @@ protected:
* aDragEvent - the dragstart/draggesture event
* aDataTransfer - the data transfer that holds the data to be dragged
* aDragTarget - the target of the drag
* aIsSelection - true if a selection is being dragged
* aSelection - the selection to be dragged
*/
bool DoDefaultDragStart(nsPresContext* aPresContext,
nsDragEvent* aDragEvent,
nsDOMDataTransfer* aDataTransfer,
nsIContent* aDragTarget,
bool aIsSelection);
nsISelection* aSelection);
bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nsnull; }
/**

Просмотреть файл

@ -55,7 +55,7 @@ interface nsIEditActionListener;
interface nsIInlineSpellChecker;
interface nsITransferable;
[scriptable, uuid(20ee0b70-c528-11e0-9572-0800200c9a66)]
[scriptable, uuid(B53516F8-270D-4DCF-85B2-01047650CEA0)]
interface nsIEditor : nsISupports
{
@ -361,19 +361,7 @@ interface nsIEditor : nsISupports
void endOfDocument();
/* ------------ Drag/Drop methods -------------- */
/**
* canDrag decides if a drag should be started
* (for example, based on the current selection and mousepoint).
*/
boolean canDrag(in nsIDOMEvent aEvent);
/**
* doDrag transfers the relevant data (as appropriate)
* to a transferable so it can later be dropped.
*/
void doDrag(in nsIDOMEvent aEvent);
/**
* insertFromDrop looks for a dragsession and inserts the
* relevant data in response to a drop.

Просмотреть файл

@ -52,7 +52,7 @@ interface nsIContentFilter;
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
%}
[scriptable, uuid(68890CBB-999D-42D0-A15C-5D534CF25C00)]
[scriptable, uuid(77271525-543F-4432-8BD6-B7686E562D9C)]
interface nsIHTMLEditor : nsISupports
{
@ -201,18 +201,6 @@ interface nsIHTMLEditor : nsISupports
/* ------------ Drag/Drop methods -------------- */
/**
* canDrag decides if a drag should be started
* (for example, based on the current selection and mousepoint).
*/
boolean canDrag(in nsIDOMEvent aEvent);
/**
* doDrag transfers the relevant data (as appropriate)
* to a transferable so it can later be dropped.
*/
void doDrag(in nsIDOMEvent aEvent);
/**
* insertFromDrop looks for a dragsession and inserts the
* relevant data in response to a drop.

Просмотреть файл

@ -1191,18 +1191,6 @@ nsEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsEditor::CanDrag(nsIDOMEvent *aEvent, bool *aCanDrag)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsEditor::DoDrag(nsIDOMEvent *aEvent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsEditor::InsertFromDrop(nsIDOMEvent *aEvent)
{

Просмотреть файл

@ -158,11 +158,6 @@ nsEditorEventListener::InstallToEditor()
NS_LITERAL_STRING("keypress"),
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
// See bug 455215, we cannot use the standard dragstart event yet
elmP->AddEventListenerByType(this,
NS_LITERAL_STRING("draggesture"),
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->AddEventListenerByType(this,
NS_LITERAL_STRING("dragenter"),
NS_EVENT_FLAG_BUBBLE |
@ -255,10 +250,6 @@ nsEditorEventListener::UninstallFromEditor()
NS_LITERAL_STRING("keypress"),
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->RemoveEventListenerByType(this,
NS_LITERAL_STRING("draggesture"),
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->RemoveEventListenerByType(this,
NS_LITERAL_STRING("dragenter"),
NS_EVENT_FLAG_BUBBLE |
@ -332,8 +323,6 @@ nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
if (dragEvent) {
if (eventType.EqualsLiteral("draggesture"))
return DragGesture(dragEvent);
if (eventType.EqualsLiteral("dragenter"))
return DragEnter(dragEvent);
if (eventType.EqualsLiteral("dragover"))
@ -658,18 +647,6 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
* Drag event implementation
*/
nsresult
nsEditorEventListener::DragGesture(nsIDOMDragEvent* aDragEvent)
{
// ...figure out if a drag should be started...
bool canDrag;
nsresult rv = mEditor->CanDrag(aDragEvent, &canDrag);
if ( NS_SUCCEEDED(rv) && canDrag )
rv = mEditor->DoDrag(aDragEvent);
return rv;
}
nsresult
nsEditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
{

Просмотреть файл

@ -1611,119 +1611,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
return rv;
}
NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag)
{
return nsPlaintextEditor::CanDrag(aDragEvent, aCanDrag);
}
nsresult
nsHTMLEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
{
NS_ENSURE_ARG_POINTER(aTransferable);
*aTransferable = nsnull;
nsCOMPtr<nsIDocumentEncoder> docEncoder;
nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
// grab a string
nsAutoString buffer, parents, info;
// find out if we're a plaintext control or not
if (!IsPlaintextEditor())
{
// encode the selection as html with contextual info
rv = docEncoder->EncodeToStringWithContext(parents, info, buffer);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
// encode the selection
rv = docEncoder->EncodeToString(buffer);
NS_ENSURE_SUCCESS(rv, rv);
}
// if we have an empty string, we're done; otherwise continue
if ( buffer.IsEmpty() )
return NS_OK;
nsCOMPtr<nsISupportsString> dataWrapper, contextWrapper, infoWrapper;
dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = dataWrapper->SetData(buffer);
NS_ENSURE_SUCCESS(rv, rv);
/* create html flavor transferable */
nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1");
NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
if (IsPlaintextEditor())
{
// Add the unicode flavor to the transferable
rv = trans->AddDataFlavor(kUnicodeMime);
NS_ENSURE_SUCCESS(rv, rv);
// QI the data object an |nsISupports| so that when the transferable holds
// onto it, it will addref the correct interface.
nsCOMPtr<nsISupports> genericDataObj(do_QueryInterface(dataWrapper));
rv = trans->SetTransferData(kUnicodeMime, genericDataObj,
buffer.Length() * sizeof(PRUnichar));
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE);
infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE);
contextWrapper->SetData(parents);
infoWrapper->SetData(info);
rv = trans->AddDataFlavor(kHTMLMime);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFormatConverter> htmlConverter =
do_CreateInstance("@mozilla.org/widget/htmlformatconverter;1");
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
rv = trans->SetConverter(htmlConverter);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> genericDataObj(do_QueryInterface(dataWrapper));
rv = trans->SetTransferData(kHTMLMime, genericDataObj,
buffer.Length() * sizeof(PRUnichar));
NS_ENSURE_SUCCESS(rv, rv);
if (!parents.IsEmpty())
{
// Add the htmlcontext DataFlavor to the transferable
trans->AddDataFlavor(kHTMLContext);
genericDataObj = do_QueryInterface(contextWrapper);
trans->SetTransferData(kHTMLContext, genericDataObj,
parents.Length() * sizeof(PRUnichar));
}
if (!info.IsEmpty())
{
// Add the htmlinfo DataFlavor to the transferable
trans->AddDataFlavor(kHTMLInfo);
genericDataObj = do_QueryInterface(infoWrapper);
trans->SetTransferData(kHTMLInfo, genericDataObj,
info.Length() * sizeof(PRUnichar));
}
}
*aTransferable = trans;
NS_ADDREF(*aTransferable);
return NS_OK;
}
NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent)
{
return nsPlaintextEditor::DoDrag(aDragEvent);
}
bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
{
// check the clipboard for our special kHTMLContext flavor. If that is there, we know

Просмотреть файл

@ -576,7 +576,6 @@ protected:
// factored methods for handling insertion of data from transferables (drag&drop or clipboard)
NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
NS_IMETHOD PrepareHTMLTransferable(nsITransferable **transferable, bool havePrivFlavor);
nsresult PutDragDataInTransferable(nsITransferable **aTransferable);
NS_IMETHOD InsertFromTransferable(nsITransferable *transferable,
nsIDOMDocument *aSourceDoc,
const nsAString & aContextStr,

Просмотреть файл

@ -307,112 +307,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
return rv;
}
NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag)
{
NS_ENSURE_TRUE(aCanDrag, NS_ERROR_NULL_POINTER);
/* we really should be checking the XY coordinates of the mouseevent and ensure that
* that particular point is actually within the selection (not just that there is a selection)
*/
*aCanDrag = false;
// KLUDGE to work around bug 50703
// After double click and object property editing,
// we get a spurious drag event
if (mIgnoreSpuriousDragEvent)
{
mIgnoreSpuriousDragEvent = false;
return NS_OK;
}
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
bool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(res, res);
// if we are collapsed, we have no selection so nothing to drag
if ( isCollapsed )
return NS_OK;
nsCOMPtr<nsIDOMEventTarget> eventTarget;
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aDragEvent));
if (nsevent) {
res = nsevent->GetTmpRealOriginalTarget(getter_AddRefs(eventTarget));
NS_ENSURE_SUCCESS(res, res);
}
if (eventTarget)
{
nsCOMPtr<nsIDOMNode> eventTargetDomNode = do_QueryInterface(eventTarget);
if ( eventTargetDomNode )
{
bool isTargetedCorrectly = false;
res = selection->ContainsNode(eventTargetDomNode, false, &isTargetedCorrectly);
NS_ENSURE_SUCCESS(res, res);
*aCanDrag = isTargetedCorrectly;
}
}
return res;
}
NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
{
nsresult rv;
nsCOMPtr<nsITransferable> trans;
rv = PutDragDataInTransferable(getter_AddRefs(trans));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(trans, NS_OK); // maybe there was nothing to copy?
/* get the drag service */
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
/* create an array of transferables */
nsCOMPtr<nsISupportsArray> transferableArray;
NS_NewISupportsArray(getter_AddRefs(transferableArray));
NS_ENSURE_TRUE(transferableArray, NS_ERROR_OUT_OF_MEMORY);
/* add the transferable to the array */
rv = transferableArray->AppendElement(trans);
NS_ENSURE_SUCCESS(rv, rv);
// check our transferable hooks (if any)
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
/* invoke drag */
nsCOMPtr<nsIDOMEventTarget> eventTarget;
rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> domnode = do_QueryInterface(eventTarget);
nsCOMPtr<nsIScriptableRegion> selRegion;
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
unsigned int flags;
// in some cases we'll want to cut rather than copy... hmmmmm...
flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE;
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDragEvent));
rv = dragService->InvokeDragSessionWithSelection(selection, transferableArray,
flags, dragEvent, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
aDragEvent->StopPropagation();
aDragEvent->PreventDefault();
return rv;
}
NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
{
if (!FireClipboardEvent(NS_PASTE))
@ -521,102 +415,3 @@ NS_IMETHODIMP nsPlaintextEditor::CanPasteTransferable(nsITransferable *aTransfer
return NS_OK;
}
nsresult
nsPlaintextEditor::SetupDocEncoder(nsIDocumentEncoder **aDocEncoder)
{
nsCOMPtr<nsIDOMDocument> domDoc;
nsresult rv = GetDocument(getter_AddRefs(domDoc));
NS_ENSURE_SUCCESS(rv, rv);
// find out if we're a plaintext control or not
// get correct mimeType and document encoder flags set
nsAutoString mimeType;
PRUint32 docEncoderFlags = 0;
if (IsPlaintextEditor())
{
docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
mimeType.AssignLiteral(kUnicodeMime);
}
else
mimeType.AssignLiteral(kHTMLMime);
// set up docEncoder
nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
NS_ENSURE_TRUE(encoder, NS_ERROR_OUT_OF_MEMORY);
rv = encoder->Init(domDoc, mimeType, docEncoderFlags);
NS_ENSURE_SUCCESS(rv, rv);
/* get the selection to be dragged */
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
rv = encoder->SetSelection(selection);
NS_ENSURE_SUCCESS(rv, rv);
*aDocEncoder = encoder;
NS_ADDREF(*aDocEncoder);
return NS_OK;
}
nsresult
nsPlaintextEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
{
*aTransferable = nsnull;
nsCOMPtr<nsIDocumentEncoder> docEncoder;
nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
NS_ENSURE_SUCCESS(rv, rv);
// grab a string
nsAutoString buffer;
rv = docEncoder->EncodeToString(buffer);
NS_ENSURE_SUCCESS(rv, rv);
// if we have an empty string, we're done; otherwise continue
if (buffer.IsEmpty())
return NS_OK;
nsCOMPtr<nsISupportsString> dataWrapper =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = dataWrapper->SetData(buffer);
NS_ENSURE_SUCCESS(rv, rv);
/* create html flavor transferable */
nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// find out if we're a plaintext control or not
if (IsPlaintextEditor())
{
// Add the unicode flavor to the transferable
rv = trans->AddDataFlavor(kUnicodeMime);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
rv = trans->AddDataFlavor(kHTMLMime);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFormatConverter> htmlConverter = do_CreateInstance("@mozilla.org/widget/htmlformatconverter;1");
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
rv = trans->SetConverter(htmlConverter);
NS_ENSURE_SUCCESS(rv, rv);
}
// QI the data object an |nsISupports| so that when the transferable holds
// onto it, it will addref the correct interface.
nsCOMPtr<nsISupports> nsisupportsDataWrapper = do_QueryInterface(dataWrapper);
rv = trans->SetTransferData(IsPlaintextEditor() ? kUnicodeMime : kHTMLMime,
nsisupportsDataWrapper, buffer.Length() * sizeof(PRUnichar));
NS_ENSURE_SUCCESS(rv, rv);
*aTransferable = trans;
NS_ADDREF(*aTransferable);
return NS_OK;
}

Просмотреть файл

@ -118,8 +118,6 @@ public:
NS_IMETHOD PasteTransferable(nsITransferable *aTransferable);
NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste);
NS_IMETHOD CanDrag(nsIDOMEvent *aDragEvent, bool *aCanDrag);
NS_IMETHOD DoDrag(nsIDOMEvent *aDragEvent);
NS_IMETHOD InsertFromDrop(nsIDOMEvent* aDropEvent);
NS_IMETHOD OutputToString(const nsAString& aFormatType,
@ -205,8 +203,6 @@ protected:
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
bool aDoDeleteSelection);
virtual nsresult SetupDocEncoder(nsIDocumentEncoder **aDocEncoder);
virtual nsresult PutDragDataInTransferable(nsITransferable **aTransferable);
/** shared outputstring; returns whether selection is collapsed and resulting string */
nsresult SharedOutputString(PRUint32 aFlags, bool* aIsCollapsed, nsAString& aResult);