Bug 666348, move drag icon initialization into drag-begin signal to prevent potential flickering, r=karlt

This commit is contained in:
Neil Deakin 2011-07-04 10:39:08 -04:00
parent 7618552aa5
commit 6501175fcf
2 changed files with 59 additions and 34 deletions

View File

@ -101,6 +101,11 @@ static const char gMozUrlType[] = "_NETSCAPE_URL";
static const char gTextUriListType[] = "text/uri-list";
static const char gTextPlainUTF8Type[] = "text/plain;charset=utf-8";
static void
invisibleSourceDragBegin(GtkWidget *aWidget,
GdkDragContext *aContext,
gpointer aData);
static void
invisibleSourceDragEnd(GtkWidget *aWidget,
GdkDragContext *aContext,
@ -135,6 +140,8 @@ nsDragService::nsDragService()
gtk_widget_realize(mHiddenWidget);
// hook up our internal signals so that we can get some feedback
// from our drag source
g_signal_connect(mHiddenWidget, "drag_begin",
G_CALLBACK(invisibleSourceDragBegin), this);
g_signal_connect(mHiddenWidget, "drag_data_get",
G_CALLBACK(invisibleSourceDragDataGet), this);
g_signal_connect(mHiddenWidget, "drag_end",
@ -302,6 +309,9 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
if (!sourceList)
return NS_OK;
// stored temporarily until the drag-begin signal has been received
mSourceRegion = aRegion;
// save our action type
GdkDragAction action = GDK_ACTION_DEFAULT;
@ -331,41 +341,9 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
1,
&event);
if (!context) {
rv = NS_ERROR_FAILURE;
} else {
PRBool needsFallbackIcon = PR_FALSE;
nsIntRect dragRect;
nsPresContext* pc;
nsRefPtr<gfxASurface> surface;
if (mHasImage || mSelection) {
DrawDrag(aDOMNode, aRegion, mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface), &pc);
}
if (surface) {
PRInt32 sx = mScreenX, sy = mScreenY;
ConvertToUnscaledDevPixels(pc, &sx, &sy);
PRInt32 offsetX = sx - dragRect.x;
PRInt32 offsetY = sy - dragRect.y;
if (!SetAlphaPixmap(surface, context, offsetX, offsetY, dragRect)) {
GdkPixbuf* dragPixbuf =
nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height);
if (dragPixbuf) {
gtk_drag_set_icon_pixbuf(context, dragPixbuf, offsetX, offsetY);
g_object_unref(dragPixbuf);
} else {
needsFallbackIcon = PR_TRUE;
}
}
} else {
needsFallbackIcon = PR_TRUE;
}
if (needsFallbackIcon)
gtk_drag_set_icon_default(context);
mSourceRegion = nsnull;
if (context) {
// GTK uses another hidden window for receiving mouse events.
mGrabWidget = gtk_grab_get_current();
if (mGrabWidget) {
@ -376,6 +354,9 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
G_CALLBACK(OnSourceGrabEventAfter), NULL);
}
}
else {
rv = NS_ERROR_FAILURE;
}
gtk_target_list_unref(sourceList);
@ -1585,6 +1566,44 @@ nsDragService::SourceDataGet(GtkWidget *aWidget,
}
}
void nsDragService::SetDragIcon(GdkDragContext* aContext)
{
nsIntRect dragRect;
nsPresContext* pc;
nsRefPtr<gfxASurface> surface;
if (mHasImage || mSelection) {
DrawDrag(mSourceNode, mSourceRegion, mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface), &pc);
}
if (surface) {
PRInt32 sx = mScreenX, sy = mScreenY;
ConvertToUnscaledDevPixels(pc, &sx, &sy);
PRInt32 offsetX = sx - dragRect.x;
PRInt32 offsetY = sy - dragRect.y;
if (!SetAlphaPixmap(surface, aContext, offsetX, offsetY, dragRect)) {
GdkPixbuf* dragPixbuf =
nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height);
if (dragPixbuf) {
gtk_drag_set_icon_pixbuf(aContext, dragPixbuf, offsetX, offsetY);
g_object_unref(dragPixbuf);
}
}
}
}
static void
invisibleSourceDragBegin(GtkWidget *aWidget,
GdkDragContext *aContext,
gpointer aData)
{
PR_LOG(sDragLm, PR_LOG_DEBUG, ("invisibleSourceDragBegin"));
nsDragService *dragService = (nsDragService *)aData;
dragService->SetDragIcon(aContext);
}
static void
invisibleSourceDragDataGet(GtkWidget *aWidget,
GdkDragContext *aContext,

View File

@ -111,6 +111,9 @@ public:
guint info,
guint32 aTime);
// set the drag icon during drag-begin
void SetDragIcon(GdkDragContext* aContext);
private:
// target side vars
@ -142,6 +145,9 @@ private:
GtkWidget *mGrabWidget;
// our source data items
nsCOMPtr<nsISupportsArray> mSourceDataItems;
nsCOMPtr<nsIScriptableRegion> mSourceRegion;
// get a list of the sources in gtk's format
GtkTargetList *GetSourceList(void);