Mozilla/mozilla/widget/src/photon/nsDragService.cpp
pinkerton%netscape.com c1421e9b63 Make the document where the drag originated available from the drag session. bug 39326
git-svn-id: svn://10.0.0.236/trunk@75249 18797224-902f-48f8-a5cc-f745e15eee43
2000-07-31 20:51:42 +00:00

450 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDragService.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsClipboard.h"
#include "nsIRegion.h"
#include "nsVoidArray.h"
#include "nsISupportsPrimitives.h"
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsWidgetsCID.h"
#include "nsPhWidgetLog.h"
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
#define DEBUG_DRAG 1
//-------------------------------------------------------------------------
//
// DragService constructor
//
//-------------------------------------------------------------------------
nsDragService::nsDragService()
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::nsDragService this=<%p>\n", this));
NS_INIT_REFCNT();
mWidget = nsnull;
mNumFlavors = 0;
}
//-------------------------------------------------------------------------
//
// DragService destructor
//
//-------------------------------------------------------------------------
nsDragService::~nsDragService()
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::~nsDragService this=<%p>\n", this));
if (mWidget)
{
PtDestroyWidget(mWidget);
mWidget=nsnull;
}
/* free the target list */
}
NS_IMETHODIMP nsDragService::StartDragSession()
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::StartDragSession this=<%p>\n", this));
NS_WARNING("nsDragService::StartDragSession() - Not Supported Yet");
nsBaseDragService::StartDragSession();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsDragService::EndDragSession()
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::EndDragSession this=<%p>\n", this));
NS_WARNING("nsDragService::EndDragSession()\n");
nsBaseDragService::EndDragSession();
//gtk_drag_source_unset(mWidget);
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode,
nsISupportsArray *aTransferableArray,
nsIScriptableRegion *aRegion,
PRUint32 aActionType)
{
nsBaseDragService::InvokeDragSession ( aDOMNode, aTransferableArray, aRegion, aActionType );
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::InvokeDragSession this=<%p> aActionType=<%d>\n", this, aActionType));
//mWidget = gtk_invisible_new();
//gtk_widget_show(mWidget);
// add the flavors from the transferables. Cache this array for the send data proc
//GtkTargetList *targetlist = RegisterDragItemsAndFlavors(aTransferableArray);
switch (aActionType)
{
case DRAGDROP_ACTION_NONE:
//mActionType = GDK_ACTION_DEFAULT;
break;
case DRAGDROP_ACTION_COPY:
//mActionType = GDK_ACTION_COPY;
break;
case DRAGDROP_ACTION_MOVE:
//mActionType = GDK_ACTION_MOVE;
break;
case DRAGDROP_ACTION_LINK:
//mActionType = GDK_ACTION_LINK;
break;
}
StartDragSession();
// XXX 3rd param ??? & last param should be a real event...
//gtk_drag_begin(mWidget, targetlist, mActionType, 1, gdk_event_get());
return NS_OK;
}
#if 0
GtkTargetList *nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray *inArray)
{
unsigned int numDragItems = 0;
inArray->Count(&numDragItems);
GtkTargetList *targetlist;
targetlist = gtk_target_list_new(nsnull, numDragItems);
printf("nsDragService::RegisterDragItemsAndFlavors\n");
for (unsigned int i = 0; i < numDragItems; ++i)
{
nsCOMPtr<nsISupports> genericItem;
inArray->GetElementAt (i, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
if (currItem)
{
nsCOMPtr<nsISupportsArray> flavorList;
if (NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))))
{
flavorList->Count (&mNumFlavors);
for (PRUint32 flavorIndex = 0; flavorIndex < mNumFlavors; ++flavorIndex)
{
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor )
{
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
// register native flavors
GdkAtom atom = gdk_atom_intern(flavorStr, PR_TRUE);
gtk_target_list_add(targetlist, atom, 1, atom);
}
} // foreach flavor in item
} // if valid flavor list
} // if item is a transferable
} // foreach drag item
return targetlist;
}
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
PRBool nsDragService::DoConvert(GdkAtom type)
{
printf("nsDragService::DoRealConvert(%li)\n {\n", type);
int e = 0;
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
//
// ask X what kind of data we can get
//
#ifdef DEBUG_DRAG
printf(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
#endif
gtk_selection_convert(mWidget,
GDK_SELECTION_PRIMARY,
type,
GDK_CURRENT_TIME);
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
#ifdef DEBUG_DRAG
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
#endif /* DEBUG_CLIPBOARD */
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_DRAG
printf(" }\n");
#endif
if (mSelectionData.length > 0)
return PR_TRUE;
return PR_FALSE;
}
#endif
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems this=<%p>\n", this));
*aNumItems = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 anItem)
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::GetData this=<%p>\n", this));
#ifdef DEBUG_DRAG
printf("nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
#if 0
// make sure we have a good transferable
if (!aTransferable) {
printf(" GetData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// Walk through flavors and see which flavor matches the one being pasted:
PRUint32 cnt;
flavorList->Count(&cnt);
nsCAutoString foundFlavor;
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
if (DoConvert(gdk_atom_intern(flavorStr, 1))) {
foundFlavor = flavorStr;
break;
}
}
}
#ifdef DEBUG_CLIPBOARD
printf(" Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
#if 0
// pinkerton - we have the flavor already from above, so we don't need
// to re-derrive it.
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
int format = GetFormat(*name);
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
#endif
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
aTransferable->SetTransferData(foundFlavor,
genericDataWrapper,
mSelectionData.length);
//delete name;
// transferable is now copying the data, so we can free it.
// g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
gtk_drag_source_unset(mWidget);
#endif
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported this=<%p>\n", this));
printf("nsDragService::IsDataFlavorSupported\n");
if (!aDataFlavor || !_retval)
return NS_ERROR_FAILURE;
*_retval = PR_TRUE;
return NS_OK;
}
#if 0
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession **aSession)
{
PR_LOG(PhWidLog, PR_LOG_DEBUG, ("nsDragService::GetCurrentSession this=<%p>\n", this));
printf("nsDragService::GetCurrentSession\n");
if (!aSession)
return NS_ERROR_FAILURE;
*aSession = (nsIDragSession *)this;
NS_ADDREF(*aSession);
return NS_OK;
}
#endif
#if 0
//-------------------------------------------------------------------------
void
nsDragService::DragLeave (GtkWidget *widget,
GdkDragContext *context,
guint time)
{
printf("leave\n");
//gHaveDrag = PR_FALSE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
printf("drag motion\n");
GtkWidget *source_widget;
#if 0
if (!gHaveDrag) {
gHaveDrag = PR_TRUE;
}
#endif
source_widget = gtk_drag_get_source_widget (context);
printf("motion, source %s\n", source_widget ?
gtk_type_name (GTK_OBJECT (source_widget)->klass->type) :
"unknown");
gdk_drag_status (context, context->suggested_action, time);
return PR_TRUE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
printf("drop\n");
//gHaveDrag = PR_FALSE;
if (context->targets){
gtk_drag_get_data (widget, context,
GPOINTER_TO_INT (context->targets->data),
time);
return PR_TRUE;
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataReceived (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time)
{
if ((data->length >= 0) && (data->format == 8)) {
printf ("Received \"%s\"\n", (gchar *)data->data);
gtk_drag_finish (context, PR_TRUE, PR_FALSE, time);
return;
}
gtk_drag_finish (context, PR_FALSE, PR_FALSE, time);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
gtk_selection_data_set (selection_data,
selection_data->target,
8, (guchar *)"I'm Data!", 9);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
printf ("Delete the data!\n");
}
#endif