Index: gtkdnd-quartz.c
===================================================================
--- gtkdnd-quartz.c	(revision 21770)
+++ gtkdnd-quartz.c	(working copy)
@@ -63,6 +63,11 @@
 						 gboolean          create);
 static void gtk_drag_source_site_destroy        (gpointer           data);
 
+static GtkDragSourceInfo *gtk_drag_get_source_info (GdkDragContext *context,
+						    gboolean        create);
+
+extern GdkDragContext *gdk_quartz_drag_source_context(); /* gdk/quartz/gdkdnd-quartz.c */
+
 struct _GtkDragSourceSite 
 {
   GdkModifierType    start_button_mask;
@@ -89,6 +94,7 @@
 
 struct _GtkDragSourceInfo 
 {
+  GtkWidget         *source_widget;
   GtkWidget         *widget;
   GtkTargetList     *target_list; /* Targets for drag data */
   GdkDragAction      possible_actions; /* Actions allowed by source */
@@ -96,6 +102,8 @@
 
   gint hot_x, hot_y;		  /* Hot spot for drag */
   GdkPixbuf         *icon_pixbuf;
+  gboolean           success;
+  gboolean           delete;
 };
 
 struct _GtkDragDestSite 
@@ -223,7 +231,9 @@
 			     selection_data,
 			     0, time);
     }
+
   
+  
   if (site && site->flags & GTK_DEST_DEFAULT_DROP)
     {
       gtk_drag_finish (context, 
@@ -233,19 +243,23 @@
     }      
 }
 
-
-GtkWidget *
-gtk_drag_get_source_widget (GdkDragContext *context)
-{
-  return NULL;
-}
-
 void 
 gtk_drag_finish (GdkDragContext *context,
 		 gboolean        success,
 		 gboolean        del,
 		 guint32         time)
 {
+	GtkDragSourceInfo *info;
+	GdkDragContext* source_context = gdk_quartz_drag_source_context ();
+
+	g_assert (source_context);
+
+	info = gtk_drag_get_source_info (source_context, FALSE);
+	if (info) 
+	  {
+   	     info->success = success;
+	     info->delete = del;
+	  }
 }
 
 static void
@@ -307,6 +321,22 @@
   g_object_set_qdata (G_OBJECT (context), dest_info_quark, NULL);
 }
 
+GtkWidget *
+gtk_drag_get_source_widget (GdkDragContext *context)
+{
+  GtkDragSourceInfo *info;
+  GdkDragContext* real_source_context = gdk_quartz_drag_source_context();
+
+  if (!real_source_context)
+    return NULL;
+
+  info = gtk_drag_get_source_info (real_source_context, FALSE);
+  if (!info)
+     return NULL;
+
+  return info->source_widget;
+}
+
 /*************************************************************
  * gtk_drag_highlight_expose:
  *     Callback for expose_event for highlighted widgets.
@@ -857,6 +887,8 @@
 	gtk_drag_get_data (widget, context, target, time);
     }
   
+  /* leave a note for the source-side context about the action chosen */
+  
   g_signal_emit_by_name (widget, "drag-drop",
 			 context, x, y, time, &retval);
 
@@ -1052,6 +1084,7 @@
 
   info = gtk_drag_get_source_info (context, TRUE);
   
+  info->source_widget = g_object_ref (widget);
   info->widget = g_object_ref (widget);
   info->target_list = target_list;
   gtk_target_list_ref (target_list);
@@ -1086,13 +1119,13 @@
 		GdkPixbuf *pixbuf;
 
 		pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
-		gdk_pixbuf_fill (pixbuf, 0xffffff);
-	    
-		gtk_drag_set_icon_pixbuf (context,
-					  pixbuf,
+ 		gdk_pixbuf_fill (pixbuf, 0xffffff);
+
+ 		gtk_drag_set_icon_pixbuf (context,
+ 					  pixbuf,
 					  0, 0);
 
-		g_object_unref (pixbuf);
+ 		g_object_unref (pixbuf);
 	      }
 	    break;
 	  case GTK_IMAGE_PIXBUF:
@@ -1668,7 +1701,20 @@
 			  gint               hot_x,
 			  gint               hot_y)
 {
-  g_warning ("gtk_drag_set_icon_pixmap is not supported on Mac OS X");
+  GdkPixbuf *pixbuf;
+  
+  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
+  g_return_if_fail (context->is_source);
+  g_return_if_fail (GDK_IS_COLORMAP (colormap));
+  g_return_if_fail (GDK_IS_PIXMAP (pixmap));
+  
+  pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap,
+					 0, 0, /* src */
+					 0, 0, /* dst */
+					 -1, -1);
+  
+  gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
+  g_object_unref (pixbuf);
 }
 
 /**
@@ -1760,6 +1806,9 @@
   g_signal_emit_by_name (info->widget, "drag-end", 
 			 info->context);
 
+  if (info->source_widget)
+    g_object_unref (info->source_widget);
+
   if (info->widget)
     g_object_unref (info->widget);
 
@@ -1781,6 +1830,10 @@
 static void
 gtk_drag_drop_finished (GtkDragSourceInfo *info)
 {
+  if (info->success && info->delete) 
+     g_signal_emit_by_name (info->source_widget, "drag-data-delete",
+			    info->context);
+
   /* Workaround for the fact that the NS API blocks until the drag is
    * over. This way the context is still valid when returning from
    * drag_begin, even if it will still be quite useless. See bug #501588.
