зеркало из https://github.com/mozilla/gecko-dev.git
b=479995 handle drag-failed signal when available. r=enndeakin sr=roc
This commit is contained in:
Родитель
3199b6a2ae
Коммит
2d4728db9e
|
@ -252,8 +252,9 @@ interface nsIDOMNSDataTransfer : nsISupports
|
|||
nsIVariant mozGetDataAt(in DOMString format, in unsigned long index);
|
||||
|
||||
/**
|
||||
* Will be true if the user cancelled the drag (typically by pressing Escape).
|
||||
* This will be false otherwise, including if a drag failed for any other reason.
|
||||
* Will be true when the user has cancelled the drag (typically by pressing
|
||||
* Escape) and when the drag has been cancelled unexpectedly. This will be
|
||||
* false otherwise, including when the drop has been rejected by its target.
|
||||
* This property is only relevant for the dragend event.
|
||||
*/
|
||||
readonly attribute boolean mozUserCancelled;
|
||||
|
|
|
@ -72,6 +72,15 @@
|
|||
// This sets how opaque the drag image is
|
||||
#define DRAG_IMAGE_ALPHA_LEVEL 0.5
|
||||
|
||||
// These values are copied from GtkDragResult (rather than using GtkDragResult
|
||||
// directly) so that this code can be compiled against versions of GTK+ that
|
||||
// do not have GtkDragResult.
|
||||
// GtkDragResult is available from GTK+ version 2.12.
|
||||
enum {
|
||||
MOZ_GTK_DRAG_RESULT_SUCCESS,
|
||||
MOZ_GTK_DRAG_RESULT_NO_TARGET
|
||||
};
|
||||
|
||||
static PRLogModuleInfo *sDragLm = NULL;
|
||||
|
||||
static const char gMimeListType[] = "application/x-moz-internal-item-list";
|
||||
|
@ -83,6 +92,12 @@ invisibleSourceDragEnd(GtkWidget *aWidget,
|
|||
GdkDragContext *aContext,
|
||||
gpointer aData);
|
||||
|
||||
static gboolean
|
||||
invisibleSourceDragFailed(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
gint aResult,
|
||||
gpointer aData);
|
||||
|
||||
static void
|
||||
invisibleSourceDragDataGet(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
|
@ -110,10 +125,19 @@ nsDragService::nsDragService()
|
|||
G_CALLBACK(invisibleSourceDragDataGet), this);
|
||||
g_signal_connect(GTK_OBJECT(mHiddenWidget), "drag_end",
|
||||
G_CALLBACK(invisibleSourceDragEnd), this);
|
||||
// drag-failed is available from GTK+ version 2.12
|
||||
guint dragFailedID = g_signal_lookup("drag-failed",
|
||||
G_TYPE_FROM_INSTANCE(mHiddenWidget));
|
||||
if (dragFailedID) {
|
||||
g_signal_connect_closure_by_id(mHiddenWidget, dragFailedID, 0,
|
||||
g_cclosure_new(G_CALLBACK(invisibleSourceDragFailed),
|
||||
this, NULL),
|
||||
FALSE);
|
||||
}
|
||||
|
||||
// set up our logging module
|
||||
if (!sDragLm)
|
||||
sDragLm = PR_NewLogModule("nsDragService");
|
||||
sDragLm = PR_NewLogModule("nsDragService");
|
||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::nsDragService"));
|
||||
mTargetWidget = 0;
|
||||
mTargetDragContext = 0;
|
||||
|
@ -1155,37 +1179,59 @@ nsDragService::GetSourceList(void)
|
|||
}
|
||||
|
||||
void
|
||||
nsDragService::SourceEndDrag(GdkDragContext *aContext)
|
||||
nsDragService::SourceEndDragSession(GdkDragContext *aContext,
|
||||
gint aResult)
|
||||
{
|
||||
// this just releases the list of data items that we provide
|
||||
mSourceDataItems = nsnull;
|
||||
|
||||
if (!mDoingDrag)
|
||||
return; // EndDragSession() was called on drop
|
||||
return; // EndDragSession() was already called on drop or drag-failed
|
||||
|
||||
gint x, y;
|
||||
GdkDisplay* display = gdk_display_get_default();
|
||||
if (display) {
|
||||
gdk_display_get_pointer(display, NULL, &x, &y, NULL);
|
||||
SetDragEndPoint(nsIntPoint(x, y));
|
||||
}
|
||||
|
||||
// Either the drag was aborted or the drop occurred outside the app.
|
||||
// The dropEffect of mDataTransfer is not updated for motion outside the
|
||||
// app, but is needed for the dragend event, so set it now.
|
||||
|
||||
// aContext->dest_window will be non-NULL only if the drop succeeded .
|
||||
GdkDragAction action =
|
||||
aContext->dest_window ? aContext->action : (GdkDragAction)0;
|
||||
|
||||
// Only one bit of action should be set, but, just in case someone does
|
||||
// something funny, erring away from MOVE, and not recording unusual
|
||||
// action combinations as NONE.
|
||||
PRUint32 dropEffect;
|
||||
if (!action)
|
||||
|
||||
if (aResult == MOZ_GTK_DRAG_RESULT_SUCCESS) {
|
||||
|
||||
// With GTK+ versions 2.10.x and prior the drag may have been
|
||||
// cancelled (but no drag-failed signal would have been sent).
|
||||
// aContext->dest_window will be non-NULL only if the drop was sent.
|
||||
GdkDragAction action =
|
||||
aContext->dest_window ? aContext->action : (GdkDragAction)0;
|
||||
|
||||
// Only one bit of action should be set, but, just in case someone
|
||||
// does something funny, erring away from MOVE, and not recording
|
||||
// unusual action combinations as NONE.
|
||||
if (!action)
|
||||
dropEffect = DRAGDROP_ACTION_NONE;
|
||||
else if (action & GDK_ACTION_COPY)
|
||||
dropEffect = DRAGDROP_ACTION_COPY;
|
||||
else if (action & GDK_ACTION_LINK)
|
||||
dropEffect = DRAGDROP_ACTION_LINK;
|
||||
else if (action & GDK_ACTION_MOVE)
|
||||
dropEffect = DRAGDROP_ACTION_MOVE;
|
||||
else
|
||||
dropEffect = DRAGDROP_ACTION_COPY;
|
||||
|
||||
} else {
|
||||
|
||||
dropEffect = DRAGDROP_ACTION_NONE;
|
||||
else if (action & GDK_ACTION_COPY)
|
||||
dropEffect = DRAGDROP_ACTION_COPY;
|
||||
else if (action & GDK_ACTION_LINK)
|
||||
dropEffect = DRAGDROP_ACTION_LINK;
|
||||
else if (action & GDK_ACTION_MOVE)
|
||||
dropEffect = DRAGDROP_ACTION_MOVE;
|
||||
else
|
||||
dropEffect = DRAGDROP_ACTION_COPY;
|
||||
|
||||
|
||||
if (aResult != MOZ_GTK_DRAG_RESULT_NO_TARGET) {
|
||||
mUserCancelled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNSDataTransfer> dataTransfer =
|
||||
do_QueryInterface(mDataTransfer);
|
||||
|
||||
|
@ -1386,6 +1432,26 @@ invisibleSourceDragDataGet(GtkWidget *aWidget,
|
|||
aSelectionData, aInfo, aTime);
|
||||
}
|
||||
|
||||
/* static */
|
||||
gboolean
|
||||
invisibleSourceDragFailed(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
gint aResult,
|
||||
gpointer aData)
|
||||
{
|
||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("invisibleSourceDragFailed %i", aResult));
|
||||
nsDragService *dragService = (nsDragService *)aData;
|
||||
// End the drag session now (rather than waiting for the drag-end signal)
|
||||
// so that operations performed on dropEffect == none can start immediately
|
||||
// rather than waiting for the drag-failed animation to finish.
|
||||
dragService->SourceEndDragSession(aContext, aResult);
|
||||
|
||||
// We should return TRUE to disable the drag-failed animation iff the
|
||||
// source performed an operation when dropEffect was none, but the handler
|
||||
// of the dragend DOM event doesn't provide this information.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
invisibleSourceDragEnd(GtkWidget *aWidget,
|
||||
|
@ -1395,14 +1461,7 @@ invisibleSourceDragEnd(GtkWidget *aWidget,
|
|||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("invisibleSourceDragEnd"));
|
||||
nsDragService *dragService = (nsDragService *)aData;
|
||||
|
||||
gint x, y;
|
||||
GdkDisplay* display = gdk_display_get_default();
|
||||
if (display) {
|
||||
gdk_display_get_pointer(display, NULL, &x, &y, NULL);
|
||||
dragService->SetDragEndPoint(nsIntPoint(x, y));
|
||||
}
|
||||
|
||||
// The drag has ended. Release the hostages!
|
||||
dragService->SourceEndDrag(aContext);
|
||||
dragService->SourceEndDragSession(aContext, MOZ_GTK_DRAG_RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -98,18 +98,19 @@ public:
|
|||
|
||||
NS_IMETHOD TargetSetTimeCallback (nsIDragSessionGTKTimeCB aCallback);
|
||||
|
||||
// This is called when the drag started with the invisible widget
|
||||
// finishes. It's called from within the drag service code but from
|
||||
// a callback - it needs to be public.
|
||||
void SourceEndDrag(GdkDragContext *aContext);
|
||||
// END PUBLIC API
|
||||
|
||||
// These methods are public only so that they can be called from functions
|
||||
// with C calling conventions. They are called for drags started with the
|
||||
// invisible widget.
|
||||
void SourceEndDragSession(GdkDragContext *aContext,
|
||||
gint aResult);
|
||||
void SourceDataGet(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint32 aTime);
|
||||
|
||||
// END PUBLIC API
|
||||
|
||||
private:
|
||||
|
||||
// target side vars
|
||||
|
|
Загрузка…
Ссылка в новой задаче