Index: gtk/gtktreeview.c
===================================================================
--- gtk/gtktreeview.c	(revision 21770)
+++ gtk/gtktreeview.c	(working copy)
@@ -2534,6 +2534,7 @@
       gboolean row_double_click = FALSE;
       gboolean rtl;
       gboolean node_selected;
+      gboolean edits_allowed;
 
       /* Empty tree? */
       if (tree_view->priv->tree == NULL)
@@ -2643,9 +2644,17 @@
 
       tree_view->priv->focus_column = column;
 
+      /* ARDOUR HACK */
+
+      if (g_object_get_data (G_OBJECT(tree_view), "mouse-edits-require-mod1")) {
+	      edits_allowed = (event->state & GDK_MOD1_MASK);
+      } else {
+	      /* regular GTK design: do edits if none of the default modifiers are active */
+	      edits_allowed = !(event->state & gtk_accelerator_get_default_mod_mask ());
+      }
+
       /* decide if we edit */
-      if (event->type == GDK_BUTTON_PRESS && event->button == 1 &&
-	  !(event->state & gtk_accelerator_get_default_mod_mask ()))
+      if (event->type == GDK_BUTTON_PRESS && event->button == 1 && edits_allowed)
 	{
 	  GtkTreePath *anchor;
 	  GtkTreeIter iter;
Index: gtk/gtkquartz.c
===================================================================
--- gtk/gtkquartz.c	(revision 21770)
+++ gtk/gtkquartz.c	(working copy)
@@ -24,6 +24,23 @@
 #include "gtkalias.h"
 
 NSImage *
+_gtk_quartz_create_image_from_drawable (GdkDrawable* drawable)
+{
+	GdkPixbuf* pixbuf;
+	NSImage* image = NULL;
+
+	pixbuf = gdk_pixbuf_get_from_drawable (NULL, drawable, NULL, 
+						  0, 0, /* src */
+						  0, 0, /* dst */
+						  -1, -1);
+	if (pixbuf) 
+   	  image = _gtk_quartz_create_image_from_pixbuf (pixbuf);
+	
+	return image;
+}
+
+
+NSImage *
 _gtk_quartz_create_image_from_pixbuf (GdkPixbuf *pixbuf)
 {
   CGColorSpaceRef colorspace;
Index: gtk/gtkquartz.h
===================================================================
--- gtk/gtkquartz.h	(revision 21770)
+++ gtk/gtkquartz.h	(working copy)
@@ -41,6 +41,7 @@
 						    GtkSelectionData *selection_data);
 			
 NSImage *_gtk_quartz_create_image_from_pixbuf (GdkPixbuf *pixbuf);
+NSImage *_gtk_quartz_create_image_from_drawable (GdkDrawable *drawable);
 			    
 G_END_DECLS
 
Index: gtk/gtktooltip.c
===================================================================
--- gtk/gtktooltip.c	(revision 21770)
+++ gtk/gtktooltip.c	(working copy)
@@ -426,6 +426,7 @@
 gtk_tooltip_trigger_tooltip_query (GdkDisplay *display)
 {
   gint x, y;
+  gint rx, ry;
   GdkWindow *window;
   GdkEvent event;
 
@@ -434,10 +435,14 @@
   if (!window)
     return;
 
+  gdk_window_get_origin (window, &rx, &ry);
+
   event.type = GDK_MOTION_NOTIFY;
   event.motion.window = window;
   event.motion.x = x;
+  event.motion.x_root = rx + x;
   event.motion.y = y;
+  event.motion.y_root = ry + y;
   event.motion.is_hint = FALSE;
 
   _gtk_tooltip_handle_event (&event);
Index: gtk/gtkdnd-quartz.c
===================================================================
--- gtk/gtkdnd-quartz.c	(revision 21770)
+++ gtk/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,13 +94,16 @@
 
 struct _GtkDragSourceInfo 
 {
+  GtkWidget         *source_widget;
   GtkWidget         *widget;
   GtkTargetList     *target_list; /* Targets for drag data */
   GdkDragAction      possible_actions; /* Actions allowed by source */
   GdkDragContext    *context;	  /* drag context */
-
+  NSEvent           *nsevent;     /* what started it */
   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,24 @@
     }      
 }
 
-
-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 ();
+
+	if (source_context) 
+	  {
+	     info = gtk_drag_get_source_info (source_context, FALSE);
+	     if (info) 
+	       {
+   	          info->success = success;
+	          info->delete = del;
+	       }
+	  }
 }
 
 static void
@@ -307,6 +322,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 +888,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);
 
@@ -1031,6 +1064,45 @@
   return GDK_NONE;
 }
 
+static gboolean
+gtk_drag_begin_idle (gpointer arg)
+{
+  GdkDragContext* context = (GdkDragContext*) arg;
+  GtkDragSourceInfo* info = gtk_drag_get_source_info (context, FALSE);
+  NSWindow *nswindow;
+  NSPasteboard *pasteboard;
+  GtkDragSourceOwner *owner;
+  NSPoint point;
+
+  g_assert (info != NULL);
+
+  pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+  owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
+
+  [pasteboard declareTypes:_gtk_quartz_target_list_to_pasteboard_types (info->target_list) owner:owner];
+
+  if ((nswindow = get_toplevel_nswindow (info->source_widget)) == NULL)
+     return FALSE;
+  
+  /* Ref the context. It's unreffed when the drag has been aborted */
+  g_object_ref (info->context);
+
+  /* FIXME: If the event isn't a mouse event, use the global cursor position instead */
+  point = [info->nsevent locationInWindow];
+
+  [nswindow dragImage:_gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf)
+                   at:point
+               offset:NSMakeSize(0, 0)
+                event:info->nsevent
+           pasteboard:pasteboard
+               source:nswindow
+            slideBack:YES];
+
+  [info->nsevent release];
+
+  return FALSE;
+}
+
 static GdkDragContext *
 gtk_drag_begin_internal (GtkWidget         *widget,
 			 GtkDragSourceSite *site,
@@ -1042,16 +1114,13 @@
   GtkDragSourceInfo *info;
   GdkDragContext *context;
   NSWindow *nswindow;
-  NSPasteboard *pasteboard;
-  GtkDragSourceOwner *owner;
-  NSEvent *nsevent;
-  NSPoint point;
 
   context = gdk_drag_begin (NULL, NULL);
   context->is_source = TRUE;
 
   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 +1155,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:
@@ -1117,31 +1186,17 @@
 	  }
     }
 
-  gdk_pointer_ungrab (0);
-  
-  pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
-  owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
+  nswindow = get_toplevel_nswindow (widget);
+  info->nsevent = [nswindow currentEvent];
+  [info->nsevent retain];
 
-  [pasteboard declareTypes:_gtk_quartz_target_list_to_pasteboard_types (target_list) owner:owner];
+  /* drag will begin in an idle handler to avoid nested run loops */
 
-  /* Ref the context. It's unreffed when the drag has been aborted */
-  g_object_ref (info->context);
+  g_idle_add_full (G_PRIORITY_HIGH_IDLE, gtk_drag_begin_idle, context, NULL);
 
-  nswindow = get_toplevel_nswindow (widget);
+  gdk_pointer_ungrab (0);
 
-  /* FIXME: If the event isn't a mouse event, use the global cursor position instead */
-  nsevent = [nswindow currentEvent];
-  point = [nsevent locationInWindow];
-
-  [nswindow dragImage:_gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf)
-                   at:point
-               offset:NSMakeSize(0, 0)
-                event:nsevent
-           pasteboard:pasteboard
-               source:nswindow
-            slideBack:YES];
-
-  return info->context;
+  return context;
 }
 
 GdkDragContext *
@@ -1668,7 +1723,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 +1828,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 +1852,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.
Index: gdk/quartz/gdkevents-quartz.c
===================================================================
--- gdk/quartz/gdkevents-quartz.c	(revision 21770)
+++ gdk/quartz/gdkevents-quartz.c	(working copy)
@@ -112,6 +112,18 @@
   return ((GdkEventPrivate *) event)->windowing_data;
 }
 
+/* A category that exposes the protected carbon event for an NSEvent. */
+@interface NSEvent (GdkQuartzNSEvent)
+- (void *)gdk_quartz_event_ref;
+@end 
+
+@implementation NSEvent (GdkQuartzNSEvent)
+- (void *)gdk_quartz_event_ref
+{
+  return _eventRef;
+}
+@end
+
 void 
 _gdk_events_init (void)
 {
@@ -1668,6 +1680,65 @@
 }
 
 static gboolean
+_gdk_quartz_possibly_forward_accelerator (NSEvent* nsevent)
+{
+  /* Special-case menu shortcut events. We create command events for
+   * those and forward to the corresponding menu.
+   */
+  if ((!_gdk_quartz_keyboard_grab_window ||
+       (_gdk_quartz_keyboard_grab_window && keyboard_grab_owner_events)) &&
+      [nsevent type] == NSKeyDown)
+    {
+      EventRef event_ref;
+      MenuRef menu_ref;
+      MenuItemIndex index;
+
+      event_ref = [nsevent gdk_quartz_event_ref];
+      if (IsMenuKeyEvent (NULL, event_ref,
+                          kMenuEventQueryOnly, 
+                          &menu_ref, &index))
+        {
+          MenuCommand menu_command;
+          HICommand hi_command;
+
+          if (GetMenuItemCommandID (menu_ref, index, &menu_command) != noErr)
+            return FALSE;
+   
+          hi_command.commandID = menu_command;
+          hi_command.menu.menuRef = menu_ref;
+          hi_command.menu.menuItemIndex = index;
+
+          CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 
+                       0, kEventAttributeUserEvent, &event_ref);
+          SetEventParameter (event_ref, kEventParamDirectObject, 
+                             typeHICommand, 
+                             sizeof (HICommand), &hi_command);
+
+          SendEventToEventTarget (event_ref, GetMenuEventTarget (menu_ref));
+
+          ReleaseEvent (event_ref);
+
+          return TRUE;
+        }
+    }
+  return FALSE;
+}
+
+gboolean
+gdk_quartz_possibly_forward (GdkEvent* event)
+{
+  NSEvent *nsevent;
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  nsevent = ((GdkEventPrivate*)event)->windowing_data;
+
+  if (nsevent)
+    return _gdk_quartz_possibly_forward_accelerator (nsevent);
+
+  return FALSE;
+}
+
+static gboolean
 gdk_event_translate (NSEvent *nsevent)
 {
   NSWindow *nswindow;
Index: gdk/quartz/gdkdnd-quartz.c
===================================================================
--- gdk/quartz/gdkdnd-quartz.c	(revision 21770)
+++ gdk/quartz/gdkdnd-quartz.c	(working copy)
@@ -101,6 +101,12 @@
 
 GdkDragContext *_gdk_quartz_drag_source_context = NULL;
 
+GdkDragContext*
+gdk_quartz_drag_source_context()
+{
+  return _gdk_quartz_drag_source_context;
+}
+
 GdkDragContext * 
 gdk_drag_begin (GdkWindow     *window,
 		GList         *targets)
Index: gdk/quartz/GdkQuartzWindow.c
===================================================================
--- gdk/quartz/GdkQuartzWindow.c	(revision 21770)
+++ gdk/quartz/GdkQuartzWindow.c	(working copy)
@@ -461,8 +461,29 @@
 {
   GdkDragAction result = 0;
 
+  /* GDK and Quartz drag operations do not map 1:1.
+     This mapping represents about the best that we
+     can come up.
+
+     Note that NSDragOperationPrivate and GDK_ACTION_PRIVATE
+     have almost opposite meanings: the GDK one means that the
+     destination is solely responsible for the action; the Quartz
+     one means that the source and destination will agree
+     privately on the action. NSOperationGeneric is close in meaning
+     to GDK_ACTION_PRIVATE but there is a problem: it will be
+     sent for any ordinary drag, and likely not understood
+     by any intra-widget drag (since the source & dest are the
+     same)
+   */
+
   if (operation & NSDragOperationGeneric)
+    result |= GDK_ACTION_MOVE;
+  if (operation & NSDragOperationCopy)
     result |= GDK_ACTION_COPY;
+  if (operation & NSDragOperationMove)
+    result |= GDK_ACTION_MOVE;
+  if (operation & NSDragOperationLink)
+    result |= GDK_ACTION_LINK;
 
   return result;
 }
@@ -474,6 +495,10 @@
 
   if (action & GDK_ACTION_COPY)
     result |= NSDragOperationCopy;
+  if (action & GDK_ACTION_LINK)
+    result |= NSDragOperationLink;
+  if (action & GDK_ACTION_MOVE)
+    result |= NSDragOperationMove;
 
   return result;
 }
@@ -485,6 +510,7 @@
 
   GDK_DRAG_CONTEXT_PRIVATE (current_context)->dragging_info = sender;
   current_context->suggested_action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
+  current_context->actions = current_context->suggested_action;
 }
 
 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
@@ -510,6 +536,10 @@
 
 - (void)draggingEnded:(id <NSDraggingInfo>)sender
 {
+  /* leave a note for the source about what action was taken */
+  if (_gdk_quartz_drag_source_context && current_context) 
+   _gdk_quartz_drag_source_context->action = current_context->action;
+
   if (current_context)
     g_object_unref (current_context);
   current_context = NULL;
