latest version of the omnibus GTK/OSX patch
[ardour.git] / patches / gtk-osx.patch
1 Index: gtk/gtktreeview.c
2 ===================================================================
3 --- gtk/gtktreeview.c   (revision 21770)
4 +++ gtk/gtktreeview.c   (working copy)
5 @@ -99,6 +99,9 @@
6  
7    guint source_set : 1;
8    guint dest_set : 1;
9 +
10 +  GtkTreePath* path;
11 +  GtkTreeModel* model;
12  };
13  
14  
15 @@ -6967,6 +6970,17 @@
16    return path;
17  }
18  
19 +#ifdef GDK_WINDOWING_QUARTZ
20 +static void
21 +gtk_tree_view_catch_drag_begin (GtkWidget* widget,
22 +                               GdkDragContext* context,
23 +                               gpointer user_data)
24 +{
25 +       TreeViewDragInfo* drag_info = (TreeViewDragInfo*) user_data;
26 +       set_source_row (context, drag_info->model, drag_info->path);
27 +}
28 +#endif
29 +
30  static gboolean
31  gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
32                                          GdkEventMotion   *event)
33 @@ -6979,6 +6993,7 @@
34    gint cell_x, cell_y;
35    GtkTreeModel *model;
36    gboolean retval = FALSE;
37 +  gint drag_begin_id;
38  
39    di = get_info (tree_view);
40  
41 @@ -7025,13 +7040,25 @@
42  
43    retval = TRUE;
44  
45 +#ifdef GDK_WINDOWING_QUARTZ
46 +  /* catch drag-being signal */
47 +  di->model = model;
48 +  di->path = path;
49 +  drag_begin_id = g_signal_connect (tree_view, "drag-begin", G_CALLBACK (gtk_tree_view_catch_drag_begin), (gpointer) di);
50 +#endif
51 +
52    context = gtk_drag_begin (widget,
53                              gtk_drag_source_get_target_list (widget),
54                              di->source_actions,
55                              button,
56                              (GdkEvent*)event);
57  
58 +#ifndef GDK_WINDOWING_QUARTZ
59    set_source_row (context, model, path);
60 +#else 
61 +  /* disconnect drag-begin and catch drag-end */
62 +  g_signal_handler_disconnect (tree_view, drag_begin_id);
63 +#endif
64  
65   out:
66    if (path)
67 Index: gtk/gtkquartz.c
68 ===================================================================
69 --- gtk/gtkquartz.c     (revision 21770)
70 +++ gtk/gtkquartz.c     (working copy)
71 @@ -24,6 +24,23 @@
72  #include "gtkalias.h"
73  
74  NSImage *
75 +_gtk_quartz_create_image_from_drawable (GdkDrawable* drawable)
76 +{
77 +       GdkPixbuf* pixbuf;
78 +       NSImage* image = NULL;
79 +
80 +       pixbuf = gdk_pixbuf_get_from_drawable (NULL, drawable, NULL, 
81 +                                                 0, 0, /* src */
82 +                                                 0, 0, /* dst */
83 +                                                 -1, -1);
84 +       if (pixbuf) 
85 +         image = _gtk_quartz_create_image_from_pixbuf (pixbuf);
86 +       
87 +       return image;
88 +}
89 +
90 +
91 +NSImage *
92  _gtk_quartz_create_image_from_pixbuf (GdkPixbuf *pixbuf)
93  {
94    CGColorSpaceRef colorspace;
95 Index: gtk/gtkquartz.h
96 ===================================================================
97 --- gtk/gtkquartz.h     (revision 21770)
98 +++ gtk/gtkquartz.h     (working copy)
99 @@ -41,6 +41,7 @@
100                                                     GtkSelectionData *selection_data);
101                         
102  NSImage *_gtk_quartz_create_image_from_pixbuf (GdkPixbuf *pixbuf);
103 +NSImage *_gtk_quartz_create_image_from_drawable (GdkDrawable *drawable);
104                             
105  G_END_DECLS
106  
107 Index: gtk/gtktooltip.c
108 ===================================================================
109 --- gtk/gtktooltip.c    (revision 21770)
110 +++ gtk/gtktooltip.c    (working copy)
111 @@ -426,6 +426,7 @@
112  gtk_tooltip_trigger_tooltip_query (GdkDisplay *display)
113  {
114    gint x, y;
115 +  gint rx, ry;
116    GdkWindow *window;
117    GdkEvent event;
118  
119 @@ -434,10 +435,14 @@
120    if (!window)
121      return;
122  
123 +  gdk_window_get_origin (window, &rx, &ry);
124 +
125    event.type = GDK_MOTION_NOTIFY;
126    event.motion.window = window;
127    event.motion.x = x;
128 +  event.motion.x_root = rx + x;
129    event.motion.y = y;
130 +  event.motion.y_root = ry + y;
131    event.motion.is_hint = FALSE;
132  
133    _gtk_tooltip_handle_event (&event);
134 Index: gtk/gtkdnd-quartz.c
135 ===================================================================
136 --- gtk/gtkdnd-quartz.c (revision 21770)
137 +++ gtk/gtkdnd-quartz.c (working copy)
138 @@ -63,6 +63,11 @@
139                                                  gboolean          create);
140  static void gtk_drag_source_site_destroy        (gpointer           data);
141  
142 +static GtkDragSourceInfo *gtk_drag_get_source_info (GdkDragContext *context,
143 +                                                   gboolean        create);
144 +
145 +extern GdkDragContext *gdk_quartz_drag_source_context(); /* gdk/quartz/gdkdnd-quartz.c */
146 +
147  struct _GtkDragSourceSite 
148  {
149    GdkModifierType    start_button_mask;
150 @@ -89,6 +94,7 @@
151  
152  struct _GtkDragSourceInfo 
153  {
154 +  GtkWidget         *source_widget;
155    GtkWidget         *widget;
156    GtkTargetList     *target_list; /* Targets for drag data */
157    GdkDragAction      possible_actions; /* Actions allowed by source */
158 @@ -96,6 +102,8 @@
159  
160    gint hot_x, hot_y;             /* Hot spot for drag */
161    GdkPixbuf         *icon_pixbuf;
162 +  gboolean           success;
163 +  gboolean           delete;
164  };
165  
166  struct _GtkDragDestSite 
167 @@ -223,7 +231,9 @@
168                              selection_data,
169                              0, time);
170      }
171 +
172    
173 +  
174    if (site && site->flags & GTK_DEST_DEFAULT_DROP)
175      {
176        gtk_drag_finish (context, 
177 @@ -233,19 +243,23 @@
178      }      
179  }
180  
181 -
182 -GtkWidget *
183 -gtk_drag_get_source_widget (GdkDragContext *context)
184 -{
185 -  return NULL;
186 -}
187 -
188  void 
189  gtk_drag_finish (GdkDragContext *context,
190                  gboolean        success,
191                  gboolean        del,
192                  guint32         time)
193  {
194 +       GtkDragSourceInfo *info;
195 +       GdkDragContext* source_context = gdk_quartz_drag_source_context ();
196 +
197 +       g_assert (source_context);
198 +
199 +       info = gtk_drag_get_source_info (source_context, FALSE);
200 +       if (info) 
201 +         {
202 +            info->success = success;
203 +            info->delete = del;
204 +         }
205  }
206  
207  static void
208 @@ -307,6 +321,22 @@
209    g_object_set_qdata (G_OBJECT (context), dest_info_quark, NULL);
210  }
211  
212 +GtkWidget *
213 +gtk_drag_get_source_widget (GdkDragContext *context)
214 +{
215 +  GtkDragSourceInfo *info;
216 +  GdkDragContext* real_source_context = gdk_quartz_drag_source_context();
217 +
218 +  if (!real_source_context)
219 +    return NULL;
220 +
221 +  info = gtk_drag_get_source_info (real_source_context, FALSE);
222 +  if (!info)
223 +     return NULL;
224 +
225 +  return info->source_widget;
226 +}
227 +
228  /*************************************************************
229   * gtk_drag_highlight_expose:
230   *     Callback for expose_event for highlighted widgets.
231 @@ -857,6 +887,8 @@
232         gtk_drag_get_data (widget, context, target, time);
233      }
234    
235 +  /* leave a note for the source-side context about the action chosen */
236 +  
237    g_signal_emit_by_name (widget, "drag-drop",
238                          context, x, y, time, &retval);
239  
240 @@ -1052,6 +1084,7 @@
241  
242    info = gtk_drag_get_source_info (context, TRUE);
243    
244 +  info->source_widget = g_object_ref (widget);
245    info->widget = g_object_ref (widget);
246    info->target_list = target_list;
247    gtk_target_list_ref (target_list);
248 @@ -1086,13 +1119,13 @@
249                 GdkPixbuf *pixbuf;
250  
251                 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
252 -               gdk_pixbuf_fill (pixbuf, 0xffffff);
253 -           
254 -               gtk_drag_set_icon_pixbuf (context,
255 -                                         pixbuf,
256 +               gdk_pixbuf_fill (pixbuf, 0xffffff);
257 +
258 +               gtk_drag_set_icon_pixbuf (context,
259 +                                         pixbuf,
260                                           0, 0);
261  
262 -               g_object_unref (pixbuf);
263 +               g_object_unref (pixbuf);
264               }
265             break;
266           case GTK_IMAGE_PIXBUF:
267 @@ -1668,7 +1701,20 @@
268                           gint               hot_x,
269                           gint               hot_y)
270  {
271 -  g_warning ("gtk_drag_set_icon_pixmap is not supported on Mac OS X");
272 +  GdkPixbuf *pixbuf;
273 +  
274 +  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
275 +  g_return_if_fail (context->is_source);
276 +  g_return_if_fail (GDK_IS_COLORMAP (colormap));
277 +  g_return_if_fail (GDK_IS_PIXMAP (pixmap));
278 +  
279 +  pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap,
280 +                                        0, 0, /* src */
281 +                                        0, 0, /* dst */
282 +                                        -1, -1);
283 +  
284 +  gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
285 +  g_object_unref (pixbuf);
286  }
287  
288  /**
289 @@ -1760,6 +1806,9 @@
290    g_signal_emit_by_name (info->widget, "drag-end", 
291                          info->context);
292  
293 +  if (info->source_widget)
294 +    g_object_unref (info->source_widget);
295 +
296    if (info->widget)
297      g_object_unref (info->widget);
298  
299 @@ -1781,6 +1830,10 @@
300  static void
301  gtk_drag_drop_finished (GtkDragSourceInfo *info)
302  {
303 +  if (info->success && info->delete) 
304 +     g_signal_emit_by_name (info->source_widget, "drag-data-delete",
305 +                           info->context);
306 +
307    /* Workaround for the fact that the NS API blocks until the drag is
308     * over. This way the context is still valid when returning from
309     * drag_begin, even if it will still be quite useless. See bug #501588.
310 Index: gdk/quartz/gdkevents-quartz.c
311 ===================================================================
312 --- gdk/quartz/gdkevents-quartz.c       (revision 21770)
313 +++ gdk/quartz/gdkevents-quartz.c       (working copy)
314 @@ -112,6 +112,18 @@
315    return ((GdkEventPrivate *) event)->windowing_data;
316  }
317  
318 +/* A category that exposes the protected carbon event for an NSEvent. */
319 +@interface NSEvent (GdkQuartzNSEvent)
320 +- (void *)gdk_quartz_event_ref;
321 +@end 
322 +
323 +@implementation NSEvent (GdkQuartzNSEvent)
324 +- (void *)gdk_quartz_event_ref
325 +{
326 +  return _eventRef;
327 +}
328 +@end
329 +
330  void 
331  _gdk_events_init (void)
332  {
333 @@ -1668,6 +1680,65 @@
334  }
335  
336  static gboolean
337 +_gdk_quartz_possibly_forward_accelerator (NSEvent* nsevent)
338 +{
339 +  /* Special-case menu shortcut events. We create command events for
340 +   * those and forward to the corresponding menu.
341 +   */
342 +  if ((!_gdk_quartz_keyboard_grab_window ||
343 +       (_gdk_quartz_keyboard_grab_window && keyboard_grab_owner_events)) &&
344 +      [nsevent type] == NSKeyDown)
345 +    {
346 +      EventRef event_ref;
347 +      MenuRef menu_ref;
348 +      MenuItemIndex index;
349 +
350 +      event_ref = [nsevent gdk_quartz_event_ref];
351 +      if (IsMenuKeyEvent (NULL, event_ref,
352 +                          kMenuEventQueryOnly, 
353 +                          &menu_ref, &index))
354 +        {
355 +          MenuCommand menu_command;
356 +          HICommand hi_command;
357 +
358 +          if (GetMenuItemCommandID (menu_ref, index, &menu_command) != noErr)
359 +            return FALSE;
360 +   
361 +          hi_command.commandID = menu_command;
362 +          hi_command.menu.menuRef = menu_ref;
363 +          hi_command.menu.menuItemIndex = index;
364 +
365 +          CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 
366 +                       0, kEventAttributeUserEvent, &event_ref);
367 +          SetEventParameter (event_ref, kEventParamDirectObject, 
368 +                             typeHICommand, 
369 +                             sizeof (HICommand), &hi_command);
370 +
371 +          SendEventToEventTarget (event_ref, GetMenuEventTarget (menu_ref));
372 +
373 +          ReleaseEvent (event_ref);
374 +
375 +          return TRUE;
376 +        }
377 +    }
378 +  return FALSE;
379 +}
380 +
381 +gboolean
382 +gdk_quartz_possibly_forward (GdkEvent* event)
383 +{
384 +  NSEvent *nsevent;
385 +  g_return_val_if_fail (event != NULL, FALSE);
386 +
387 +  nsevent = ((GdkEventPrivate*)event)->windowing_data;
388 +
389 +  if (nsevent)
390 +    return _gdk_quartz_possibly_forward_accelerator (nsevent);
391 +
392 +  return FALSE;
393 +}
394 +
395 +static gboolean
396  gdk_event_translate (NSEvent *nsevent)
397  {
398    NSWindow *nswindow;
399 Index: gdk/quartz/gdkdnd-quartz.c
400 ===================================================================
401 --- gdk/quartz/gdkdnd-quartz.c  (revision 21770)
402 +++ gdk/quartz/gdkdnd-quartz.c  (working copy)
403 @@ -101,6 +101,12 @@
404  
405  GdkDragContext *_gdk_quartz_drag_source_context = NULL;
406  
407 +GdkDragContext*
408 +gdk_quartz_drag_source_context()
409 +{
410 +  return _gdk_quartz_drag_source_context;
411 +}
412 +
413  GdkDragContext * 
414  gdk_drag_begin (GdkWindow     *window,
415                 GList         *targets)
416 Index: gdk/quartz/GdkQuartzWindow.c
417 ===================================================================
418 --- gdk/quartz/GdkQuartzWindow.c        (revision 21770)
419 +++ gdk/quartz/GdkQuartzWindow.c        (working copy)
420 @@ -461,8 +461,29 @@
421  {
422    GdkDragAction result = 0;
423  
424 +  /* GDK and Quartz drag operations do not map 1:1.
425 +     This mapping represents about the best that we
426 +     can come up.
427 +
428 +     Note that NSDragOperationPrivate and GDK_ACTION_PRIVATE
429 +     have almost opposite meanings: the GDK one means that the
430 +     destination is solely responsible for the action; the Quartz
431 +     one means that the source and destination will agree
432 +     privately on the action. NSOperationGeneric is close in meaning
433 +     to GDK_ACTION_PRIVATE but there is a problem: it will be
434 +     sent for any ordinary drag, and likely not understood
435 +     by any intra-widget drag (since the source & dest are the
436 +     same)
437 +   */
438 +
439    if (operation & NSDragOperationGeneric)
440 +    result |= GDK_ACTION_MOVE;
441 +  if (operation & NSDragOperationCopy)
442      result |= GDK_ACTION_COPY;
443 +  if (operation & NSDragOperationMove)
444 +    result |= GDK_ACTION_MOVE;
445 +  if (operation & NSDragOperationLink)
446 +    result |= GDK_ACTION_LINK;
447  
448    return result;
449  }
450 @@ -474,6 +495,10 @@
451  
452    if (action & GDK_ACTION_COPY)
453      result |= NSDragOperationCopy;
454 +  if (action & GDK_ACTION_LINK)
455 +    result |= NSDragOperationLink;
456 +  if (action & GDK_ACTION_MOVE)
457 +    result |= NSDragOperationMove;
458  
459    return result;
460  }
461 @@ -485,6 +510,7 @@
462  
463    GDK_DRAG_CONTEXT_PRIVATE (current_context)->dragging_info = sender;
464    current_context->suggested_action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
465 +  current_context->actions = current_context->suggested_action;
466  }
467  
468  - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
469 @@ -510,6 +536,10 @@
470  
471  - (void)draggingEnded:(id <NSDraggingInfo>)sender
472  {
473 +  /* leave a note for the source about what action was taken */
474 +  if (_gdk_quartz_drag_source_context && current_context) 
475 +   _gdk_quartz_drag_source_context->action = current_context->action;
476 +
477    if (current_context)
478      g_object_unref (current_context);
479    current_context = NULL;