~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gtk/gtkdnd-quartz.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GTK - The GIMP Toolkit
 
2
 * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 
22
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
23
 * files for a list of changes.  These files are distributed with
 
24
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 
25
 */
 
26
 
 
27
#include <config.h>
 
28
 
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
 
 
32
#include "gdkconfig.h"
 
33
 
 
34
#include "gdk/gdkkeysyms.h"
 
35
 
 
36
#include "gtkdnd.h"
 
37
#include "gtkiconfactory.h"
 
38
#include "gtkicontheme.h"
 
39
#include "gtkimage.h"
 
40
#include "gtkinvisible.h"
 
41
#include "gtkmain.h"
 
42
#include "gtkplug.h"
 
43
#include "gtkstock.h"
 
44
#include "gtkwindow.h"
 
45
#include "gtkintl.h"
 
46
#include "gtkquartz.h"
 
47
#include "gtkalias.h"
 
48
#include "gdk/quartz/gdkquartz.h"
 
49
 
 
50
typedef struct _GtkDragSourceSite GtkDragSourceSite;
 
51
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
 
52
typedef struct _GtkDragDestSite GtkDragDestSite;
 
53
typedef struct _GtkDragDestInfo GtkDragDestInfo;
 
54
typedef struct _GtkDragFindData GtkDragFindData;
 
55
 
 
56
static void     gtk_drag_find_widget            (GtkWidget        *widget,
 
57
                                                 GtkDragFindData  *data);
 
58
static void     gtk_drag_dest_site_destroy      (gpointer          data);
 
59
static void     gtk_drag_dest_leave             (GtkWidget        *widget,
 
60
                                                 GdkDragContext   *context,
 
61
                                                 guint             time);
 
62
static GtkDragDestInfo *gtk_drag_get_dest_info  (GdkDragContext   *context,
 
63
                                                 gboolean          create);
 
64
static void gtk_drag_source_site_destroy        (gpointer           data);
 
65
 
 
66
struct _GtkDragSourceSite 
 
67
{
 
68
  GdkModifierType    start_button_mask;
 
69
  GtkTargetList     *target_list;        /* Targets for drag data */
 
70
  GdkDragAction      actions;            /* Possible actions */
 
71
 
 
72
  /* Drag icon */
 
73
  GtkImageType icon_type;
 
74
  union
 
75
  {
 
76
    GtkImagePixmapData pixmap;
 
77
    GtkImagePixbufData pixbuf;
 
78
    GtkImageStockData stock;
 
79
    GtkImageIconNameData name;
 
80
  } icon_data;
 
81
  GdkBitmap *icon_mask;
 
82
 
 
83
  GdkColormap       *colormap;           /* Colormap for drag icon */
 
84
 
 
85
  /* Stored button press information to detect drag beginning */
 
86
  gint               state;
 
87
  gint               x, y;
 
88
};
 
89
 
 
90
struct _GtkDragSourceInfo 
 
91
{
 
92
  GtkWidget         *widget;
 
93
  GtkTargetList     *target_list; /* Targets for drag data */
 
94
  GdkDragAction      possible_actions; /* Actions allowed by source */
 
95
  GdkDragContext    *context;     /* drag context */
 
96
 
 
97
  gint hot_x, hot_y;              /* Hot spot for drag */
 
98
  GdkPixbuf         *icon_pixbuf;
 
99
};
 
100
 
 
101
struct _GtkDragDestSite 
 
102
{
 
103
  GtkDestDefaults    flags;
 
104
  GtkTargetList     *target_list;
 
105
  GdkDragAction      actions;
 
106
  guint              have_drag : 1;
 
107
  guint              track_motion : 1;
 
108
};
 
109
 
 
110
struct _GtkDragDestInfo 
 
111
{
 
112
  GtkWidget         *widget;       /* Widget in which drag is in */
 
113
  GdkDragContext    *context;      /* Drag context */
 
114
  guint              dropped : 1;     /* Set after we receive a drop */
 
115
  gint               drop_x, drop_y; /* Position of drop */
 
116
};
 
117
 
 
118
struct _GtkDragFindData 
 
119
{
 
120
  gint x;
 
121
  gint y;
 
122
  GdkDragContext *context;
 
123
  GtkDragDestInfo *info;
 
124
  gboolean found;
 
125
  gboolean toplevel;
 
126
  gboolean (*callback) (GtkWidget *widget, GdkDragContext *context,
 
127
                        gint x, gint y, guint32 time);
 
128
  guint32 time;
 
129
};
 
130
 
 
131
 
 
132
@interface GtkDragSourceOwner : NSObject {
 
133
  GtkDragSourceInfo *info;
 
134
}
 
135
 
 
136
@end
 
137
 
 
138
@implementation GtkDragSourceOwner
 
139
-(void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type
 
140
{
 
141
  guint target_info;
 
142
  GtkSelectionData selection_data;
 
143
 
 
144
  selection_data.selection = GDK_NONE;
 
145
  selection_data.data = NULL;
 
146
  selection_data.target = _gtk_quartz_pasteboard_type_to_atom (type);
 
147
 
 
148
  if (gtk_target_list_find (info->target_list, 
 
149
                            selection_data.target, 
 
150
                            &target_info)) 
 
151
    {
 
152
      g_signal_emit_by_name (info->widget, "drag_data_get",
 
153
                             info->context,
 
154
                             &selection_data,
 
155
                             target_info,
 
156
                             time);
 
157
 
 
158
      _gtk_quartz_set_selection_data_for_pasteboard (sender, &selection_data);
 
159
      
 
160
      g_free (selection_data.data);
 
161
    }
 
162
}
 
163
 
 
164
- (id)initWithInfo:(GtkDragSourceInfo *)anInfo
 
165
{
 
166
  self = [super init];
 
167
 
 
168
  if (self) 
 
169
    {
 
170
      info = anInfo;
 
171
    }
 
172
 
 
173
  return self;
 
174
}
 
175
 
 
176
@end
 
177
 
 
178
void 
 
179
gtk_drag_get_data (GtkWidget      *widget,
 
180
                   GdkDragContext *context,
 
181
                   GdkAtom         target,
 
182
                   guint32         time)
 
183
{
 
184
  id <NSDraggingInfo> dragging_info = GDK_DRAG_CONTEXT_PRIVATE (context)->dragging_info;
 
185
  NSPasteboard *pasteboard = [dragging_info draggingPasteboard];
 
186
  GtkSelectionData *selection_data;
 
187
  GtkDragDestInfo *info;
 
188
  GtkDragDestSite *site;
 
189
 
 
190
  info = gtk_drag_get_dest_info (context, FALSE);
 
191
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
192
 
 
193
  selection_data = _gtk_quartz_get_selection_data_from_pasteboard (pasteboard,
 
194
                                                                   target, 0);
 
195
 
 
196
  if (site && site->target_list)
 
197
    {
 
198
      guint target_info;
 
199
      
 
200
      if (gtk_target_list_find (site->target_list, 
 
201
                                selection_data->target,
 
202
                                &target_info))
 
203
        {
 
204
          if (!(site->flags & GTK_DEST_DEFAULT_DROP) ||
 
205
              selection_data->length >= 0)
 
206
            g_signal_emit_by_name (widget,
 
207
                                   "drag_data_received",
 
208
                                   context, info->drop_x, info->drop_y,
 
209
                                   selection_data,
 
210
                                   target_info, time);
 
211
        }
 
212
    }
 
213
  else
 
214
    {
 
215
      g_signal_emit_by_name (widget,
 
216
                             "drag_data_received",
 
217
                             context, info->drop_x, info->drop_y,
 
218
                             selection_data,
 
219
                             0, time);
 
220
    }
 
221
  
 
222
  if (site && site->flags & GTK_DEST_DEFAULT_DROP)
 
223
    {
 
224
      gtk_drag_finish (context, 
 
225
                       (selection_data->length >= 0),
 
226
                       (context->action == GDK_ACTION_MOVE),
 
227
                       time);
 
228
    }      
 
229
}
 
230
 
 
231
 
 
232
GtkWidget *
 
233
gtk_drag_get_source_widget (GdkDragContext *context)
 
234
{
 
235
  return NULL;
 
236
}
 
237
 
 
238
void 
 
239
gtk_drag_finish (GdkDragContext *context,
 
240
                 gboolean        success,
 
241
                 gboolean        del,
 
242
                 guint32         time)
 
243
{
 
244
}
 
245
 
 
246
static void
 
247
gtk_drag_dest_info_destroy (gpointer data)
 
248
{
 
249
  GtkDragDestInfo *info = data;
 
250
 
 
251
  g_free (info);
 
252
}
 
253
 
 
254
static GtkDragDestInfo *
 
255
gtk_drag_get_dest_info (GdkDragContext *context,
 
256
                        gboolean        create)
 
257
{
 
258
  GtkDragDestInfo *info;
 
259
  static GQuark info_quark = 0;
 
260
  if (!info_quark)
 
261
    info_quark = g_quark_from_static_string ("gtk-dest-info");
 
262
  
 
263
  info = g_object_get_qdata (G_OBJECT (context), info_quark);
 
264
  if (!info && create)
 
265
    {
 
266
      info = g_new (GtkDragDestInfo, 1);
 
267
      info->widget = NULL;
 
268
      info->context = context;
 
269
      info->dropped = FALSE;
 
270
      g_object_set_qdata_full (G_OBJECT (context), info_quark,
 
271
                               info, gtk_drag_dest_info_destroy);
 
272
    }
 
273
 
 
274
  return info;
 
275
}
 
276
 
 
277
static GQuark dest_info_quark = 0;
 
278
 
 
279
static GtkDragSourceInfo *
 
280
gtk_drag_get_source_info (GdkDragContext *context,
 
281
                          gboolean        create)
 
282
{
 
283
  GtkDragSourceInfo *info;
 
284
 
 
285
  if (!dest_info_quark)
 
286
    dest_info_quark = g_quark_from_static_string ("gtk-source-info");
 
287
  
 
288
  info = g_object_get_qdata (G_OBJECT (context), dest_info_quark);
 
289
  if (!info && create)
 
290
    {
 
291
      info = g_new0 (GtkDragSourceInfo, 1);
 
292
      info->context = context;
 
293
      g_object_set_qdata (G_OBJECT (context), dest_info_quark, info);
 
294
    }
 
295
 
 
296
  return info;
 
297
}
 
298
 
 
299
static void
 
300
gtk_drag_clear_source_info (GdkDragContext *context)
 
301
{
 
302
  g_object_set_qdata (G_OBJECT (context), dest_info_quark, NULL);
 
303
}
 
304
 
 
305
/*************************************************************
 
306
 * gtk_drag_highlight_expose:
 
307
 *     Callback for expose_event for highlighted widgets.
 
308
 *   arguments:
 
309
 *     widget:
 
310
 *     event:
 
311
 *     data:
 
312
 *   results:
 
313
 *************************************************************/
 
314
 
 
315
static gboolean
 
316
gtk_drag_highlight_expose (GtkWidget      *widget,
 
317
                           GdkEventExpose *event,
 
318
                           gpointer        data)
 
319
{
 
320
  gint x, y, width, height;
 
321
  
 
322
  if (GTK_WIDGET_DRAWABLE (widget))
 
323
    {
 
324
      cairo_t *cr;
 
325
      
 
326
      if (GTK_WIDGET_NO_WINDOW (widget))
 
327
        {
 
328
          x = widget->allocation.x;
 
329
          y = widget->allocation.y;
 
330
          width = widget->allocation.width;
 
331
          height = widget->allocation.height;
 
332
        }
 
333
      else
 
334
        {
 
335
          x = 0;
 
336
          y = 0;
 
337
          gdk_drawable_get_size (widget->window, &width, &height);
 
338
        }
 
339
      
 
340
      gtk_paint_shadow (widget->style, widget->window,
 
341
                        GTK_STATE_NORMAL, GTK_SHADOW_OUT,
 
342
                        NULL, widget, "dnd",
 
343
                        x, y, width, height);
 
344
 
 
345
      cr = gdk_cairo_create (widget->window);
 
346
      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
 
347
      cairo_set_line_width (cr, 1.0);
 
348
      cairo_rectangle (cr,
 
349
                       x + 0.5, y + 0.5,
 
350
                       width - 1, height - 1);
 
351
      cairo_stroke (cr);
 
352
      cairo_destroy (cr);
 
353
    }
 
354
 
 
355
  return FALSE;
 
356
}
 
357
 
 
358
/*************************************************************
 
359
 * gtk_drag_highlight:
 
360
 *     Highlight the given widget in the default manner.
 
361
 *   arguments:
 
362
 *     widget:
 
363
 *   results:
 
364
 *************************************************************/
 
365
 
 
366
void 
 
367
gtk_drag_highlight (GtkWidget  *widget)
 
368
{
 
369
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
370
 
 
371
  g_signal_connect_after (widget, "expose_event",
 
372
                          G_CALLBACK (gtk_drag_highlight_expose),
 
373
                          NULL);
 
374
 
 
375
  gtk_widget_queue_draw (widget);
 
376
}
 
377
 
 
378
/*************************************************************
 
379
 * gtk_drag_unhighlight:
 
380
 *     Refresh the given widget to remove the highlight.
 
381
 *   arguments:
 
382
 *     widget:
 
383
 *   results:
 
384
 *************************************************************/
 
385
 
 
386
void 
 
387
gtk_drag_unhighlight (GtkWidget *widget)
 
388
{
 
389
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
390
 
 
391
  g_signal_handlers_disconnect_by_func (widget,
 
392
                                        gtk_drag_highlight_expose,
 
393
                                        NULL);
 
394
  
 
395
  gtk_widget_queue_draw (widget);
 
396
}
 
397
 
 
398
static NSWindow *
 
399
get_toplevel_nswindow (GtkWidget *widget)
 
400
{
 
401
  GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
 
402
  
 
403
  if (GTK_WIDGET_TOPLEVEL (toplevel) && toplevel->window)
 
404
    return [gdk_quartz_window_get_nsview (toplevel->window) window];
 
405
  else
 
406
    return NULL;
 
407
}
 
408
 
 
409
static void
 
410
register_types (GtkWidget *widget, GtkDragDestSite *site)
 
411
{
 
412
  if (site->target_list)
 
413
    {
 
414
      NSWindow *nswindow = get_toplevel_nswindow (widget);
 
415
      NSArray *types;
 
416
      NSAutoreleasePool *pool;
 
417
 
 
418
      if (!nswindow)
 
419
        return;
 
420
 
 
421
      pool = [[NSAutoreleasePool alloc] init];
 
422
      types = _gtk_quartz_target_list_to_pasteboard_types (site->target_list);
 
423
 
 
424
      [nswindow registerForDraggedTypes:types];
 
425
      [pool release];
 
426
    }
 
427
}
 
428
 
 
429
static void
 
430
gtk_drag_dest_realized (GtkWidget *widget, 
 
431
                        gpointer   user_data)
 
432
{
 
433
  GtkDragDestSite *site = user_data;
 
434
 
 
435
  register_types (widget, site);
 
436
}
 
437
 
 
438
static void
 
439
gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
 
440
                                 GtkWidget *previous_toplevel,
 
441
                                 gpointer   user_data)
 
442
{
 
443
  GtkDragDestSite *site = user_data;
 
444
 
 
445
  register_types (widget, site);
 
446
}
 
447
 
 
448
static void
 
449
gtk_drag_dest_site_destroy (gpointer data)
 
450
{
 
451
  GtkDragDestSite *site = data;
 
452
    
 
453
  if (site->target_list)
 
454
    gtk_target_list_unref (site->target_list);
 
455
 
 
456
  g_free (site);
 
457
}
 
458
 
 
459
void 
 
460
gtk_drag_dest_set (GtkWidget            *widget,
 
461
                   GtkDestDefaults       flags,
 
462
                   const GtkTargetEntry *targets,
 
463
                   gint                  n_targets,
 
464
                   GdkDragAction         actions)
 
465
{
 
466
  GtkDragDestSite *old_site, *site;
 
467
 
 
468
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
469
 
 
470
  old_site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
471
 
 
472
  gtk_drag_dest_unset (widget);
 
473
 
 
474
  site = g_new (GtkDragDestSite, 1);
 
475
  site->flags = flags;
 
476
  site->have_drag = FALSE;
 
477
  if (targets)
 
478
    site->target_list = gtk_target_list_new (targets, n_targets);
 
479
  else
 
480
    site->target_list = NULL;
 
481
  site->actions = actions;
 
482
 
 
483
  if (old_site)
 
484
    site->track_motion = old_site->track_motion;
 
485
  else
 
486
    site->track_motion = FALSE;
 
487
 
 
488
  if (GTK_WIDGET_REALIZED (widget))
 
489
    gtk_drag_dest_realized (widget, site);
 
490
 
 
491
  g_signal_connect (widget, "realize",
 
492
                    G_CALLBACK (gtk_drag_dest_realized), site);
 
493
  g_signal_connect (widget, "hierarchy_changed",
 
494
                    G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
 
495
 
 
496
  g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"),
 
497
                          site, gtk_drag_dest_site_destroy);
 
498
}
 
499
 
 
500
void 
 
501
gtk_drag_dest_set_proxy (GtkWidget      *widget,
 
502
                         GdkWindow      *proxy_window,
 
503
                         GdkDragProtocol protocol,
 
504
                         gboolean        use_coordinates)
 
505
{
 
506
  g_warning ("gtk_drag_dest_set_proxy is not supported on Mac OS X.");
 
507
}
 
508
 
 
509
void 
 
510
gtk_drag_dest_unset (GtkWidget *widget)
 
511
{
 
512
  GtkDragDestSite *old_site;
 
513
 
 
514
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
515
 
 
516
  old_site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
517
  if (old_site)
 
518
    {
 
519
      g_signal_handlers_disconnect_by_func (widget,
 
520
                                            gtk_drag_dest_realized,
 
521
                                            old_site);
 
522
      g_signal_handlers_disconnect_by_func (widget,
 
523
                                            gtk_drag_dest_hierarchy_changed,
 
524
                                            old_site);
 
525
    }
 
526
 
 
527
  g_object_set_data (G_OBJECT (widget), I_("gtk-drag-dest"), NULL);
 
528
}
 
529
 
 
530
GtkTargetList*
 
531
gtk_drag_dest_get_target_list (GtkWidget *widget)
 
532
{
 
533
  GtkDragDestSite *site;
 
534
 
 
535
  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
536
  
 
537
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
538
 
 
539
  return site ? site->target_list : NULL;  
 
540
}
 
541
 
 
542
void
 
543
gtk_drag_dest_set_target_list (GtkWidget      *widget,
 
544
                               GtkTargetList  *target_list)
 
545
{
 
546
  GtkDragDestSite *site;
 
547
 
 
548
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
549
  
 
550
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
551
  
 
552
  if (!site)
 
553
    {
 
554
      g_warning ("Can't set a target list on a widget until you've called gtk_drag_dest_set() "
 
555
                 "to make the widget into a drag destination");
 
556
      return;
 
557
    }
 
558
 
 
559
  if (target_list)
 
560
    gtk_target_list_ref (target_list);
 
561
  
 
562
  if (site->target_list)
 
563
    gtk_target_list_unref (site->target_list);
 
564
 
 
565
  site->target_list = target_list;
 
566
 
 
567
  register_types (widget, site);
 
568
}
 
569
 
 
570
void
 
571
gtk_drag_dest_add_text_targets (GtkWidget *widget)
 
572
{
 
573
  GtkTargetList *target_list;
 
574
 
 
575
  target_list = gtk_drag_dest_get_target_list (widget);
 
576
  if (target_list)
 
577
    gtk_target_list_ref (target_list);
 
578
  else
 
579
    target_list = gtk_target_list_new (NULL, 0);
 
580
  gtk_target_list_add_text_targets (target_list, 0);
 
581
  gtk_drag_dest_set_target_list (widget, target_list);
 
582
  gtk_target_list_unref (target_list);
 
583
}
 
584
 
 
585
void
 
586
gtk_drag_dest_add_image_targets (GtkWidget *widget)
 
587
{
 
588
  GtkTargetList *target_list;
 
589
 
 
590
  target_list = gtk_drag_dest_get_target_list (widget);
 
591
  if (target_list)
 
592
    gtk_target_list_ref (target_list);
 
593
  else
 
594
    target_list = gtk_target_list_new (NULL, 0);
 
595
  gtk_target_list_add_image_targets (target_list, 0, FALSE);
 
596
  gtk_drag_dest_set_target_list (widget, target_list);
 
597
  gtk_target_list_unref (target_list);
 
598
}
 
599
 
 
600
void
 
601
gtk_drag_dest_add_uri_targets (GtkWidget *widget)
 
602
{
 
603
  GtkTargetList *target_list;
 
604
 
 
605
  target_list = gtk_drag_dest_get_target_list (widget);
 
606
  if (target_list)
 
607
    gtk_target_list_ref (target_list);
 
608
  else
 
609
    target_list = gtk_target_list_new (NULL, 0);
 
610
  gtk_target_list_add_uri_targets (target_list, 0);
 
611
  gtk_drag_dest_set_target_list (widget, target_list);
 
612
  gtk_target_list_unref (target_list);
 
613
}
 
614
 
 
615
static void
 
616
prepend_and_ref_widget (GtkWidget *widget,
 
617
                        gpointer   data)
 
618
{
 
619
  GSList **slist_p = data;
 
620
 
 
621
  *slist_p = g_slist_prepend (*slist_p, g_object_ref (widget));
 
622
}
 
623
 
 
624
static void
 
625
gtk_drag_find_widget (GtkWidget       *widget,
 
626
                      GtkDragFindData *data)
 
627
{
 
628
  GtkAllocation new_allocation;
 
629
  gint allocation_to_window_x = 0;
 
630
  gint allocation_to_window_y = 0;
 
631
  gint x_offset = 0;
 
632
  gint y_offset = 0;
 
633
 
 
634
  if (data->found || !GTK_WIDGET_MAPPED (widget) || !GTK_WIDGET_SENSITIVE (widget))
 
635
    return;
 
636
 
 
637
  /* Note that in the following code, we only count the
 
638
   * position as being inside a WINDOW widget if it is inside
 
639
   * widget->window; points that are outside of widget->window
 
640
   * but within the allocation are not counted. This is consistent
 
641
   * with the way we highlight drag targets.
 
642
   *
 
643
   * data->x,y are relative to widget->parent->window (if
 
644
   * widget is not a toplevel, widget->window otherwise).
 
645
   * We compute the allocation of widget in the same coordinates,
 
646
   * clipping to widget->window, and all intermediate
 
647
   * windows. If data->x,y is inside that, then we translate
 
648
   * our coordinates to be relative to widget->window and
 
649
   * recurse.
 
650
   */  
 
651
  new_allocation = widget->allocation;
 
652
 
 
653
  if (widget->parent)
 
654
    {
 
655
      gint tx, ty;
 
656
      GdkWindow *window = widget->window;
 
657
 
 
658
      /* Compute the offset from allocation-relative to
 
659
       * window-relative coordinates.
 
660
       */
 
661
      allocation_to_window_x = widget->allocation.x;
 
662
      allocation_to_window_y = widget->allocation.y;
 
663
 
 
664
      if (!GTK_WIDGET_NO_WINDOW (widget))
 
665
        {
 
666
          /* The allocation is relative to the parent window for
 
667
           * window widgets, not to widget->window.
 
668
           */
 
669
          gdk_window_get_position (window, &tx, &ty);
 
670
          
 
671
          allocation_to_window_x -= tx;
 
672
          allocation_to_window_y -= ty;
 
673
        }
 
674
 
 
675
      new_allocation.x = 0 + allocation_to_window_x;
 
676
      new_allocation.y = 0 + allocation_to_window_y;
 
677
      
 
678
      while (window && window != widget->parent->window)
 
679
        {
 
680
          GdkRectangle window_rect = { 0, 0, 0, 0 };
 
681
          
 
682
          gdk_drawable_get_size (window, &window_rect.width, &window_rect.height);
 
683
 
 
684
          gdk_rectangle_intersect (&new_allocation, &window_rect, &new_allocation);
 
685
 
 
686
          gdk_window_get_position (window, &tx, &ty);
 
687
          new_allocation.x += tx;
 
688
          x_offset += tx;
 
689
          new_allocation.y += ty;
 
690
          y_offset += ty;
 
691
          
 
692
          window = gdk_window_get_parent (window);
 
693
        }
 
694
 
 
695
      if (!window)              /* Window and widget heirarchies didn't match. */
 
696
        return;
 
697
    }
 
698
 
 
699
  if (data->toplevel ||
 
700
      ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
 
701
       (data->x < new_allocation.x + new_allocation.width) && 
 
702
       (data->y < new_allocation.y + new_allocation.height)))
 
703
    {
 
704
      /* First, check if the drag is in a valid drop site in
 
705
       * one of our children 
 
706
       */
 
707
      if (GTK_IS_CONTAINER (widget))
 
708
        {
 
709
          GtkDragFindData new_data = *data;
 
710
          GSList *children = NULL;
 
711
          GSList *tmp_list;
 
712
          
 
713
          new_data.x -= x_offset;
 
714
          new_data.y -= y_offset;
 
715
          new_data.found = FALSE;
 
716
          new_data.toplevel = FALSE;
 
717
          
 
718
          /* need to reference children temporarily in case the
 
719
           * ::drag_motion/::drag_drop callbacks change the widget heirarchy.
 
720
           */
 
721
          gtk_container_forall (GTK_CONTAINER (widget), prepend_and_ref_widget, &children);
 
722
          for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
 
723
            {
 
724
              if (!new_data.found && GTK_WIDGET_DRAWABLE (tmp_list->data))
 
725
                gtk_drag_find_widget (tmp_list->data, &new_data);
 
726
              g_object_unref (tmp_list->data);
 
727
            }
 
728
          g_slist_free (children);
 
729
          
 
730
          data->found = new_data.found;
 
731
        }
 
732
 
 
733
      /* If not, and this widget is registered as a drop site, check to
 
734
       * emit "drag_motion" to check if we are actually in
 
735
       * a drop site.
 
736
       */
 
737
      if (!data->found &&
 
738
          g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
 
739
        {
 
740
          data->found = data->callback (widget,
 
741
                                        data->context,
 
742
                                        data->x - x_offset - allocation_to_window_x,
 
743
                                        data->y - y_offset - allocation_to_window_y,
 
744
                                        data->time);
 
745
          /* If so, send a "drag_leave" to the last widget */
 
746
          if (data->found)
 
747
            {
 
748
              if (data->info->widget && data->info->widget != widget)
 
749
                {
 
750
                  gtk_drag_dest_leave (data->info->widget, data->context, data->time);
 
751
                }
 
752
              data->info->widget = widget;
 
753
            }
 
754
        }
 
755
    }
 
756
}
 
757
 
 
758
static void  
 
759
gtk_drag_dest_leave (GtkWidget      *widget,
 
760
                     GdkDragContext *context,
 
761
                     guint           time)
 
762
{
 
763
  GtkDragDestSite *site;
 
764
 
 
765
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
766
  g_return_if_fail (site != NULL);
 
767
 
 
768
  if ((site->flags & GTK_DEST_DEFAULT_HIGHLIGHT) && site->have_drag)
 
769
    gtk_drag_unhighlight (widget);
 
770
  
 
771
  if (!(site->flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag ||
 
772
      site->track_motion)
 
773
    g_signal_emit_by_name (widget, "drag_leave", context, time);
 
774
  
 
775
  site->have_drag = FALSE;
 
776
}
 
777
 
 
778
static gboolean
 
779
gtk_drag_dest_motion (GtkWidget      *widget,
 
780
                      GdkDragContext *context,
 
781
                      gint            x,
 
782
                      gint            y,
 
783
                      guint           time)
 
784
{
 
785
  GtkDragDestSite *site;
 
786
  GdkDragAction action = 0;
 
787
  gboolean retval;
 
788
 
 
789
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
790
  g_return_val_if_fail (site != NULL, FALSE);
 
791
 
 
792
  if (site->track_motion || site->flags & GTK_DEST_DEFAULT_MOTION)
 
793
    {
 
794
      if (context->suggested_action & site->actions)
 
795
        action = context->suggested_action;
 
796
      
 
797
      if (action && gtk_drag_dest_find_target (widget, context, NULL))
 
798
        {
 
799
          if (!site->have_drag)
 
800
            {
 
801
              site->have_drag = TRUE;
 
802
              if (site->flags & GTK_DEST_DEFAULT_HIGHLIGHT)
 
803
                gtk_drag_highlight (widget);
 
804
            }
 
805
          
 
806
          gdk_drag_status (context, action, time);
 
807
        }
 
808
      else
 
809
        {
 
810
          gdk_drag_status (context, 0, time);
 
811
          if (!site->track_motion)
 
812
            return TRUE;
 
813
        }
 
814
    }
 
815
 
 
816
  g_signal_emit_by_name (widget, "drag_motion",
 
817
                         context, x, y, time, &retval);
 
818
 
 
819
  return (site->flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval;
 
820
}
 
821
 
 
822
static gboolean
 
823
gtk_drag_dest_drop (GtkWidget        *widget,
 
824
                    GdkDragContext   *context,
 
825
                    gint              x,
 
826
                    gint              y,
 
827
                    guint             time)
 
828
{
 
829
  GtkDragDestSite *site;
 
830
  GtkDragDestInfo *info;
 
831
  gboolean retval;
 
832
 
 
833
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
834
  g_return_val_if_fail (site != NULL, FALSE);
 
835
 
 
836
  info = gtk_drag_get_dest_info (context, FALSE);
 
837
  g_return_val_if_fail (info != NULL, FALSE);
 
838
 
 
839
  info->drop_x = x;
 
840
  info->drop_y = y;
 
841
 
 
842
  if (site->flags & GTK_DEST_DEFAULT_DROP)
 
843
    {
 
844
      GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
 
845
 
 
846
      if (target == GDK_NONE)
 
847
        {
 
848
          gtk_drag_finish (context, FALSE, FALSE, time);
 
849
          return TRUE;
 
850
        }
 
851
      else
 
852
        gtk_drag_get_data (widget, context, target, time);
 
853
    }
 
854
  
 
855
  g_signal_emit_by_name (widget, "drag_drop",
 
856
                         context, x, y, time, &retval);
 
857
 
 
858
  return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
 
859
}
 
860
 
 
861
void
 
862
gtk_drag_dest_set_track_motion (GtkWidget *widget,
 
863
                                gboolean   track_motion)
 
864
{
 
865
  GtkDragDestSite *site;
 
866
 
 
867
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
868
 
 
869
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
870
  
 
871
  g_return_if_fail (site != NULL);
 
872
 
 
873
  site->track_motion = track_motion != FALSE;
 
874
}
 
875
 
 
876
gboolean
 
877
gtk_drag_dest_get_track_motion (GtkWidget *widget)
 
878
{
 
879
  GtkDragDestSite *site;
 
880
 
 
881
  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
882
 
 
883
  site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
 
884
 
 
885
  if (site)
 
886
    return site->track_motion;
 
887
 
 
888
  return FALSE;
 
889
}
 
890
 
 
891
void
 
892
_gtk_drag_dest_handle_event (GtkWidget *toplevel,
 
893
                             GdkEvent  *event)
 
894
{
 
895
  GtkDragDestInfo *info;
 
896
  GdkDragContext *context;
 
897
 
 
898
  g_return_if_fail (toplevel != NULL);
 
899
  g_return_if_fail (event != NULL);
 
900
 
 
901
  context = event->dnd.context;
 
902
 
 
903
  info = gtk_drag_get_dest_info (context, TRUE);
 
904
 
 
905
  /* Find the widget for the event */
 
906
  switch (event->type)
 
907
    {
 
908
    case GDK_DRAG_ENTER:
 
909
      break;
 
910
 
 
911
    case GDK_DRAG_LEAVE:
 
912
      if (info->widget)
 
913
        {
 
914
          gtk_drag_dest_leave (info->widget, context, event->dnd.time);
 
915
          info->widget = NULL;
 
916
        }
 
917
      break;
 
918
 
 
919
    case GDK_DRAG_MOTION:
 
920
    case GDK_DROP_START:
 
921
      {
 
922
        GtkDragFindData data;
 
923
        gint tx, ty;
 
924
 
 
925
        if (event->type == GDK_DROP_START)
 
926
          {
 
927
            info->dropped = TRUE;
 
928
            /* We send a leave here so that the widget unhighlights
 
929
             * properly.
 
930
             */
 
931
            if (info->widget)
 
932
              {
 
933
                gtk_drag_dest_leave (info->widget, context, event->dnd.time);
 
934
                info->widget = NULL;
 
935
              }
 
936
          }
 
937
 
 
938
        gdk_window_get_position (toplevel->window, &tx, &ty);
 
939
        
 
940
        data.x = event->dnd.x_root - tx;
 
941
        data.y = event->dnd.y_root - ty;
 
942
        data.context = context;
 
943
        data.info = info;
 
944
        data.found = FALSE;
 
945
        data.toplevel = TRUE;
 
946
        data.callback = (event->type == GDK_DRAG_MOTION) ?
 
947
          gtk_drag_dest_motion : gtk_drag_dest_drop;
 
948
        data.time = event->dnd.time;
 
949
        
 
950
        gtk_drag_find_widget (toplevel, &data);
 
951
 
 
952
        if (info->widget && !data.found)
 
953
          {
 
954
            gtk_drag_dest_leave (info->widget, context, event->dnd.time);
 
955
            info->widget = NULL;
 
956
          }
 
957
 
 
958
        /* Send a reply.
 
959
         */
 
960
        if (event->type == GDK_DRAG_MOTION)
 
961
          {
 
962
            if (!data.found)
 
963
              gdk_drag_status (context, 0, event->dnd.time);
 
964
          }
 
965
 
 
966
        break;
 
967
      default:
 
968
        g_assert_not_reached ();
 
969
      }
 
970
    }
 
971
}
 
972
 
 
973
 
 
974
GdkAtom
 
975
gtk_drag_dest_find_target (GtkWidget      *widget,
 
976
                           GdkDragContext *context,
 
977
                           GtkTargetList  *target_list)
 
978
{
 
979
  id <NSDraggingInfo> dragging_info = GDK_DRAG_CONTEXT_PRIVATE (context)->dragging_info;
 
980
  NSPasteboard *pasteboard = [dragging_info draggingPasteboard];
 
981
  GtkWidget *source_widget;
 
982
  GList *tmp_target;
 
983
  GList *tmp_source = NULL;
 
984
  GList *source_targets;
 
985
 
 
986
  g_return_val_if_fail (GTK_IS_WIDGET (widget), GDK_NONE);
 
987
  g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_NONE);
 
988
  g_return_val_if_fail (!context->is_source, GDK_NONE);
 
989
 
 
990
  source_widget = gtk_drag_get_source_widget (context);
 
991
 
 
992
  if (target_list == NULL)
 
993
    target_list = gtk_drag_dest_get_target_list (widget);
 
994
  
 
995
  if (target_list == NULL)
 
996
    return GDK_NONE;
 
997
 
 
998
  source_targets = _gtk_quartz_pasteboard_types_to_atom_list ([pasteboard types]);
 
999
  tmp_target = target_list->list;
 
1000
  while (tmp_target)
 
1001
    {
 
1002
      GtkTargetPair *pair = tmp_target->data;
 
1003
      tmp_source = source_targets;
 
1004
      while (tmp_source)
 
1005
        {
 
1006
          if (tmp_source->data == GUINT_TO_POINTER (pair->target))
 
1007
            {
 
1008
              if ((!(pair->flags & GTK_TARGET_SAME_APP) || source_widget) &&
 
1009
                  (!(pair->flags & GTK_TARGET_SAME_WIDGET) || (source_widget == widget)))
 
1010
                {
 
1011
                  g_list_free (source_targets);
 
1012
                  return pair->target;
 
1013
                }
 
1014
              else
 
1015
                break;
 
1016
            }
 
1017
          tmp_source = tmp_source->next;
 
1018
        }
 
1019
      tmp_target = tmp_target->next;
 
1020
    }
 
1021
 
 
1022
  g_list_free (source_targets);
 
1023
  return GDK_NONE;
 
1024
}
 
1025
 
 
1026
static GdkDragContext *
 
1027
gtk_drag_begin_internal (GtkWidget         *widget,
 
1028
                         GtkDragSourceSite *site,
 
1029
                         GtkTargetList     *target_list,
 
1030
                         GdkDragAction      actions,
 
1031
                         gint               button,
 
1032
                         GdkEvent          *event)
 
1033
{
 
1034
  GtkDragSourceInfo *info;
 
1035
  GdkDragContext *context;
 
1036
  NSWindow *nswindow;
 
1037
  NSPasteboard *pasteboard;
 
1038
  GtkDragSourceOwner *owner;
 
1039
  NSEvent *nsevent;
 
1040
  NSPoint point;
 
1041
 
 
1042
  context = gdk_drag_begin (NULL, NULL);
 
1043
  context->is_source = TRUE;
 
1044
 
 
1045
  info = gtk_drag_get_source_info (context, TRUE);
 
1046
  
 
1047
  info->widget = gtk_widget_ref (widget);
 
1048
  info->target_list = target_list;
 
1049
  gtk_target_list_ref (target_list);
 
1050
 
 
1051
  info->possible_actions = actions;
 
1052
  
 
1053
  g_signal_emit_by_name (widget, "drag_begin", info->context);
 
1054
 
 
1055
  /* Ensure that we have an icon before we start the drag; the
 
1056
   * application may have set one in ::drag_begin, or it may
 
1057
   * not have set one.
 
1058
   */
 
1059
  if (!info->icon_pixbuf)
 
1060
    {
 
1061
      if (!site || site->icon_type == GTK_IMAGE_EMPTY)
 
1062
        gtk_drag_set_icon_default (context);
 
1063
      else
 
1064
        switch (site->icon_type)
 
1065
          {
 
1066
          case GTK_IMAGE_PIXMAP:
 
1067
            /* This is not supported, so just set a small transparent pixbuf
 
1068
             * since we need to have something.
 
1069
             */
 
1070
            if (0)
 
1071
              gtk_drag_set_icon_pixmap (context,
 
1072
                                        site->colormap,
 
1073
                                        site->icon_data.pixmap.pixmap,
 
1074
                                        site->icon_mask,
 
1075
                                        -2, -2);
 
1076
            else
 
1077
              {
 
1078
                GdkPixbuf *pixbuf;
 
1079
 
 
1080
                pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
 
1081
                gdk_pixbuf_fill (pixbuf, 0xffffff);
 
1082
            
 
1083
                gtk_drag_set_icon_pixbuf (context,
 
1084
                                          pixbuf,
 
1085
                                          0, 0);
 
1086
 
 
1087
                g_object_unref (pixbuf);
 
1088
              }
 
1089
            break;
 
1090
          case GTK_IMAGE_PIXBUF:
 
1091
            gtk_drag_set_icon_pixbuf (context,
 
1092
                                      site->icon_data.pixbuf.pixbuf,
 
1093
                                      -2, -2);
 
1094
            break;
 
1095
          case GTK_IMAGE_STOCK:
 
1096
            gtk_drag_set_icon_stock (context,
 
1097
                                     site->icon_data.stock.stock_id,
 
1098
                                     -2, -2);
 
1099
            break;
 
1100
          case GTK_IMAGE_ICON_NAME:
 
1101
            gtk_drag_set_icon_name (context,
 
1102
                                    site->icon_data.name.icon_name,
 
1103
                                    -2, -2);
 
1104
            break;
 
1105
          case GTK_IMAGE_EMPTY:
 
1106
          default:
 
1107
            g_assert_not_reached();
 
1108
            break;
 
1109
          }
 
1110
    }
 
1111
 
 
1112
  gdk_pointer_ungrab (0);
 
1113
  
 
1114
  pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
 
1115
  owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
 
1116
 
 
1117
  [pasteboard declareTypes:_gtk_quartz_target_list_to_pasteboard_types (target_list) owner:owner];
 
1118
 
 
1119
  /* Ref the context. It's unreffed when the drag has been aborted */
 
1120
  g_object_ref (info->context);
 
1121
 
 
1122
  nswindow = get_toplevel_nswindow (widget);
 
1123
 
 
1124
  /* FIXME: If the event isn't a mouse event, use the global cursor position instead */
 
1125
  nsevent = [nswindow currentEvent];
 
1126
  point = [nsevent locationInWindow];
 
1127
 
 
1128
  [nswindow dragImage:_gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf)
 
1129
                   at:point
 
1130
               offset:NSMakeSize(0, 0)
 
1131
                event:nsevent
 
1132
           pasteboard:pasteboard
 
1133
               source:nswindow
 
1134
            slideBack:YES];
 
1135
 
 
1136
  return info->context;
 
1137
}
 
1138
 
 
1139
GdkDragContext *
 
1140
gtk_drag_begin (GtkWidget         *widget,
 
1141
                GtkTargetList     *targets,
 
1142
                GdkDragAction      actions,
 
1143
                gint               button,
 
1144
                GdkEvent          *event)
 
1145
{
 
1146
  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
1147
  g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
 
1148
  g_return_val_if_fail (targets != NULL, NULL);
 
1149
 
 
1150
  return gtk_drag_begin_internal (widget, NULL, targets,
 
1151
                                  actions, button, event);
 
1152
}
 
1153
 
 
1154
 
 
1155
static gboolean
 
1156
gtk_drag_source_event_cb (GtkWidget      *widget,
 
1157
                          GdkEvent       *event,
 
1158
                          gpointer        data)
 
1159
{
 
1160
  GtkDragSourceSite *site;
 
1161
  gboolean retval = FALSE;
 
1162
  site = (GtkDragSourceSite *)data;
 
1163
 
 
1164
  switch (event->type)
 
1165
    {
 
1166
    case GDK_BUTTON_PRESS:
 
1167
      if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask)
 
1168
        {
 
1169
          site->state |= (GDK_BUTTON1_MASK << (event->button.button - 1));
 
1170
          site->x = event->button.x;
 
1171
          site->y = event->button.y;
 
1172
        }
 
1173
      break;
 
1174
      
 
1175
    case GDK_BUTTON_RELEASE:
 
1176
      if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask)
 
1177
        site->state &= ~(GDK_BUTTON1_MASK << (event->button.button - 1));
 
1178
      break;
 
1179
      
 
1180
    case GDK_MOTION_NOTIFY:
 
1181
      if (site->state & event->motion.state & site->start_button_mask)
 
1182
        {
 
1183
          /* FIXME: This is really broken and can leave us
 
1184
           * with a stuck grab
 
1185
           */
 
1186
          int i;
 
1187
          for (i=1; i<6; i++)
 
1188
            {
 
1189
              if (site->state & event->motion.state & 
 
1190
                  GDK_BUTTON1_MASK << (i - 1))
 
1191
                break;
 
1192
            }
 
1193
 
 
1194
          if (gtk_drag_check_threshold (widget, site->x, site->y,
 
1195
                                        event->motion.x, event->motion.y))
 
1196
            {
 
1197
              site->state = 0;
 
1198
              gtk_drag_begin_internal (widget, site, site->target_list,
 
1199
                                       site->actions, 
 
1200
                                       i, event);
 
1201
 
 
1202
              retval = TRUE;
 
1203
            }
 
1204
        }
 
1205
      break;
 
1206
      
 
1207
    default:                    /* hit for 2/3BUTTON_PRESS */
 
1208
      break;
 
1209
    }
 
1210
  
 
1211
  return retval;
 
1212
}
 
1213
 
 
1214
void 
 
1215
gtk_drag_source_set (GtkWidget            *widget,
 
1216
                     GdkModifierType       start_button_mask,
 
1217
                     const GtkTargetEntry *targets,
 
1218
                     gint                  n_targets,
 
1219
                     GdkDragAction         actions)
 
1220
{
 
1221
  GtkDragSourceSite *site;
 
1222
 
 
1223
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1224
 
 
1225
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1226
 
 
1227
  gtk_widget_add_events (widget,
 
1228
                         gtk_widget_get_events (widget) |
 
1229
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 
1230
                         GDK_BUTTON_MOTION_MASK);
 
1231
 
 
1232
  if (site)
 
1233
    {
 
1234
      if (site->target_list)
 
1235
        gtk_target_list_unref (site->target_list);
 
1236
    }
 
1237
  else
 
1238
    {
 
1239
      site = g_new0 (GtkDragSourceSite, 1);
 
1240
 
 
1241
      site->icon_type = GTK_IMAGE_EMPTY;
 
1242
      
 
1243
      g_signal_connect (widget, "button_press_event",
 
1244
                        G_CALLBACK (gtk_drag_source_event_cb),
 
1245
                        site);
 
1246
      g_signal_connect (widget, "button_release_event",
 
1247
                        G_CALLBACK (gtk_drag_source_event_cb),
 
1248
                        site);
 
1249
      g_signal_connect (widget, "motion_notify_event",
 
1250
                        G_CALLBACK (gtk_drag_source_event_cb),
 
1251
                        site);
 
1252
      
 
1253
      g_object_set_data_full (G_OBJECT (widget),
 
1254
                              I_("gtk-site-data"), 
 
1255
                              site, gtk_drag_source_site_destroy);
 
1256
    }
 
1257
 
 
1258
  site->start_button_mask = start_button_mask;
 
1259
 
 
1260
  site->target_list = gtk_target_list_new (targets, n_targets);
 
1261
 
 
1262
  site->actions = actions;
 
1263
}
 
1264
 
 
1265
/*************************************************************
 
1266
 * gtk_drag_source_unset
 
1267
 *     Unregister this widget as a drag source.
 
1268
 *   arguments:
 
1269
 *     widget:
 
1270
 *   results:
 
1271
 *************************************************************/
 
1272
 
 
1273
void 
 
1274
gtk_drag_source_unset (GtkWidget *widget)
 
1275
{
 
1276
  GtkDragSourceSite *site;
 
1277
 
 
1278
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1279
 
 
1280
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1281
 
 
1282
  if (site)
 
1283
    {
 
1284
      g_signal_handlers_disconnect_by_func (widget,
 
1285
                                            gtk_drag_source_event_cb,
 
1286
                                            site);
 
1287
      g_object_set_data (G_OBJECT (widget), I_("gtk-site-data"), NULL);
 
1288
    }
 
1289
}
 
1290
 
 
1291
GtkTargetList *
 
1292
gtk_drag_source_get_target_list (GtkWidget *widget)
 
1293
{
 
1294
  GtkDragSourceSite *site;
 
1295
 
 
1296
  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
1297
 
 
1298
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1299
 
 
1300
  return site ? site->target_list : NULL;
 
1301
 
 
1302
}
 
1303
 
 
1304
void
 
1305
gtk_drag_source_set_target_list (GtkWidget     *widget,
 
1306
                                 GtkTargetList *target_list)
 
1307
{
 
1308
  GtkDragSourceSite *site;
 
1309
 
 
1310
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1311
 
 
1312
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1313
  if (site == NULL)
 
1314
    {
 
1315
      g_warning ("gtk_drag_source_set_target_list() requires the widget "
 
1316
                 "to already be a drag source.");
 
1317
      return;
 
1318
    }
 
1319
 
 
1320
  if (target_list)
 
1321
    gtk_target_list_ref (target_list);
 
1322
 
 
1323
  if (site->target_list)
 
1324
    gtk_target_list_unref (site->target_list);
 
1325
 
 
1326
  site->target_list = target_list;
 
1327
}
 
1328
 
 
1329
/**
 
1330
 * gtk_drag_source_add_text_targets:
 
1331
 * @widget: a #GtkWidget that's is a drag source
 
1332
 *
 
1333
 * Add the text targets supported by #GtkSelection to
 
1334
 * the target list of the drag source.  The targets
 
1335
 * are added with @info = 0. If you need another value, 
 
1336
 * use gtk_target_list_add_text_targets() and
 
1337
 * gtk_drag_source_set_target_list().
 
1338
 * 
 
1339
 * Since: 2.6
 
1340
 **/
 
1341
void
 
1342
gtk_drag_source_add_text_targets (GtkWidget *widget)
 
1343
{
 
1344
  GtkTargetList *target_list;
 
1345
 
 
1346
  target_list = gtk_drag_source_get_target_list (widget);
 
1347
  if (target_list)
 
1348
    gtk_target_list_ref (target_list);
 
1349
  else
 
1350
    target_list = gtk_target_list_new (NULL, 0);
 
1351
  gtk_target_list_add_text_targets (target_list, 0);
 
1352
  gtk_drag_source_set_target_list (widget, target_list);
 
1353
  gtk_target_list_unref (target_list);
 
1354
}
 
1355
 
 
1356
void
 
1357
gtk_drag_source_add_image_targets (GtkWidget *widget)
 
1358
{
 
1359
  GtkTargetList *target_list;
 
1360
 
 
1361
  target_list = gtk_drag_source_get_target_list (widget);
 
1362
  if (target_list)
 
1363
    gtk_target_list_ref (target_list);
 
1364
  else
 
1365
    target_list = gtk_target_list_new (NULL, 0);
 
1366
  gtk_target_list_add_image_targets (target_list, 0, TRUE);
 
1367
  gtk_drag_source_set_target_list (widget, target_list);
 
1368
  gtk_target_list_unref (target_list);
 
1369
}
 
1370
 
 
1371
void
 
1372
gtk_drag_source_add_uri_targets (GtkWidget *widget)
 
1373
{
 
1374
  GtkTargetList *target_list;
 
1375
 
 
1376
  target_list = gtk_drag_source_get_target_list (widget);
 
1377
  if (target_list)
 
1378
    gtk_target_list_ref (target_list);
 
1379
  else
 
1380
    target_list = gtk_target_list_new (NULL, 0);
 
1381
  gtk_target_list_add_uri_targets (target_list, 0);
 
1382
  gtk_drag_source_set_target_list (widget, target_list);
 
1383
  gtk_target_list_unref (target_list);
 
1384
}
 
1385
 
 
1386
static void
 
1387
gtk_drag_source_unset_icon (GtkDragSourceSite *site)
 
1388
{
 
1389
  switch (site->icon_type)
 
1390
    {
 
1391
    case GTK_IMAGE_EMPTY:
 
1392
      break;
 
1393
    case GTK_IMAGE_PIXMAP:
 
1394
      if (site->icon_data.pixmap.pixmap)
 
1395
        g_object_unref (site->icon_data.pixmap.pixmap);
 
1396
      if (site->icon_mask)
 
1397
        g_object_unref (site->icon_mask);
 
1398
      break;
 
1399
    case GTK_IMAGE_PIXBUF:
 
1400
      g_object_unref (site->icon_data.pixbuf.pixbuf);
 
1401
      break;
 
1402
    case GTK_IMAGE_STOCK:
 
1403
      g_free (site->icon_data.stock.stock_id);
 
1404
      break;
 
1405
    case GTK_IMAGE_ICON_NAME:
 
1406
      g_free (site->icon_data.name.icon_name);
 
1407
      break;
 
1408
    default:
 
1409
      g_assert_not_reached();
 
1410
      break;
 
1411
    }
 
1412
  site->icon_type = GTK_IMAGE_EMPTY;
 
1413
  
 
1414
  if (site->colormap)
 
1415
    g_object_unref (site->colormap);
 
1416
  site->colormap = NULL;
 
1417
}
 
1418
 
 
1419
static void 
 
1420
gtk_drag_source_site_destroy (gpointer data)
 
1421
{
 
1422
  GtkDragSourceSite *site = data;
 
1423
 
 
1424
  if (site->target_list)
 
1425
    gtk_target_list_unref (site->target_list);
 
1426
 
 
1427
  gtk_drag_source_unset_icon (site);
 
1428
  g_free (site);
 
1429
}
 
1430
 
 
1431
void 
 
1432
gtk_drag_source_set_icon (GtkWidget     *widget,
 
1433
                          GdkColormap   *colormap,
 
1434
                          GdkPixmap     *pixmap,
 
1435
                          GdkBitmap     *mask)
 
1436
{
 
1437
  GtkDragSourceSite *site;
 
1438
 
 
1439
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1440
  g_return_if_fail (GDK_IS_COLORMAP (colormap));
 
1441
  g_return_if_fail (GDK_IS_PIXMAP (pixmap));
 
1442
  g_return_if_fail (!mask || GDK_IS_PIXMAP (mask));
 
1443
 
 
1444
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1445
  g_return_if_fail (site != NULL);
 
1446
  
 
1447
  g_object_ref (colormap);
 
1448
  g_object_ref (pixmap);
 
1449
  if (mask)
 
1450
    g_object_ref (mask);
 
1451
 
 
1452
  gtk_drag_source_unset_icon (site);
 
1453
 
 
1454
  site->icon_type = GTK_IMAGE_PIXMAP;
 
1455
  
 
1456
  site->icon_data.pixmap.pixmap = pixmap;
 
1457
  site->icon_mask = mask;
 
1458
  site->colormap = colormap;
 
1459
}
 
1460
 
 
1461
void 
 
1462
gtk_drag_source_set_icon_pixbuf (GtkWidget   *widget,
 
1463
                                 GdkPixbuf   *pixbuf)
 
1464
{
 
1465
  GtkDragSourceSite *site;
 
1466
 
 
1467
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1468
  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
 
1469
 
 
1470
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1471
  g_return_if_fail (site != NULL); 
 
1472
  g_object_ref (pixbuf);
 
1473
 
 
1474
  gtk_drag_source_unset_icon (site);
 
1475
 
 
1476
  site->icon_type = GTK_IMAGE_PIXBUF;
 
1477
  site->icon_data.pixbuf.pixbuf = pixbuf;
 
1478
}
 
1479
 
 
1480
/**
 
1481
 * gtk_drag_source_set_icon_stock:
 
1482
 * @widget: a #GtkWidget
 
1483
 * @stock_id: the ID of the stock icon to use
 
1484
 *
 
1485
 * Sets the icon that will be used for drags from a particular source
 
1486
 * to a stock icon. 
 
1487
 **/
 
1488
void 
 
1489
gtk_drag_source_set_icon_stock (GtkWidget   *widget,
 
1490
                                const gchar *stock_id)
 
1491
{
 
1492
  GtkDragSourceSite *site;
 
1493
 
 
1494
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1495
  g_return_if_fail (stock_id != NULL);
 
1496
 
 
1497
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1498
  g_return_if_fail (site != NULL);
 
1499
  
 
1500
  gtk_drag_source_unset_icon (site);
 
1501
 
 
1502
  site->icon_type = GTK_IMAGE_STOCK;
 
1503
  site->icon_data.stock.stock_id = g_strdup (stock_id);
 
1504
}
 
1505
 
 
1506
/**
 
1507
 * gtk_drag_source_set_icon_name:
 
1508
 * @widget: a #GtkWidget
 
1509
 * @icon_name: name of icon to use
 
1510
 * 
 
1511
 * Sets the icon that will be used for drags from a particular source
 
1512
 * to a themed icon. See the docs for #GtkIconTheme for more details.
 
1513
 *
 
1514
 * Since: 2.8
 
1515
 **/
 
1516
void 
 
1517
gtk_drag_source_set_icon_name (GtkWidget   *widget,
 
1518
                               const gchar *icon_name)
 
1519
{
 
1520
  GtkDragSourceSite *site;
 
1521
 
 
1522
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1523
  g_return_if_fail (icon_name != NULL);
 
1524
 
 
1525
  site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
 
1526
  g_return_if_fail (site != NULL);
 
1527
 
 
1528
  gtk_drag_source_unset_icon (site);
 
1529
 
 
1530
  site->icon_type = GTK_IMAGE_ICON_NAME;
 
1531
  site->icon_data.name.icon_name = g_strdup (icon_name);
 
1532
}
 
1533
 
 
1534
 
 
1535
/**
 
1536
 * gtk_drag_set_icon_widget:
 
1537
 * @context: the context for a drag. (This must be called 
 
1538
          with a  context for the source side of a drag)
 
1539
 * @widget: a toplevel window to use as an icon.
 
1540
 * @hot_x: the X offset within @widget of the hotspot.
 
1541
 * @hot_y: the Y offset within @widget of the hotspot.
 
1542
 * 
 
1543
 * Changes the icon for a widget to a given widget. GTK+
 
1544
 * will not destroy the icon, so if you don't want
 
1545
 * it to persist, you should connect to the "drag_end" 
 
1546
 * signal and destroy it yourself.
 
1547
 **/
 
1548
void 
 
1549
gtk_drag_set_icon_widget (GdkDragContext    *context,
 
1550
                          GtkWidget         *widget,
 
1551
                          gint               hot_x,
 
1552
                          gint               hot_y)
 
1553
{
 
1554
  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
1555
  g_return_if_fail (context->is_source);
 
1556
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
1557
 
 
1558
  g_warning ("gtk_drag_set_icon_widget is not supported on Mac OS X");
 
1559
}
 
1560
 
 
1561
static void
 
1562
set_icon_stock_pixbuf (GdkDragContext    *context,
 
1563
                       const gchar       *stock_id,
 
1564
                       GdkPixbuf         *pixbuf,
 
1565
                       gint               hot_x,
 
1566
                       gint               hot_y)
 
1567
{
 
1568
  GtkDragSourceInfo *info;
 
1569
 
 
1570
  info = gtk_drag_get_source_info (context, FALSE);
 
1571
 
 
1572
  if (stock_id)
 
1573
    {
 
1574
      pixbuf = gtk_widget_render_icon (info->widget, stock_id,
 
1575
                                       GTK_ICON_SIZE_DND, NULL);
 
1576
 
 
1577
      if (!pixbuf)
 
1578
        {
 
1579
          g_warning ("Cannot load drag icon from stock_id %s", stock_id);
 
1580
          return;
 
1581
        }
 
1582
    }
 
1583
  else
 
1584
    g_object_ref (pixbuf);
 
1585
 
 
1586
  if (info->icon_pixbuf)
 
1587
    g_object_unref (info->icon_pixbuf);
 
1588
  info->icon_pixbuf = pixbuf;
 
1589
  info->hot_x = hot_x;
 
1590
  info->hot_y = hot_y;
 
1591
}
 
1592
 
 
1593
/**
 
1594
 * gtk_drag_set_icon_pixbuf:
 
1595
 * @context: the context for a drag. (This must be called 
 
1596
 *            with a  context for the source side of a drag)
 
1597
 * @pixbuf: the #GdkPixbuf to use as the drag icon.
 
1598
 * @hot_x: the X offset within @widget of the hotspot.
 
1599
 * @hot_y: the Y offset within @widget of the hotspot.
 
1600
 * 
 
1601
 * Sets @pixbuf as the icon for a given drag.
 
1602
 **/
 
1603
void 
 
1604
gtk_drag_set_icon_pixbuf  (GdkDragContext *context,
 
1605
                           GdkPixbuf      *pixbuf,
 
1606
                           gint            hot_x,
 
1607
                           gint            hot_y)
 
1608
{
 
1609
  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
1610
  g_return_if_fail (context->is_source);
 
1611
  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
 
1612
 
 
1613
  set_icon_stock_pixbuf (context, NULL, pixbuf, hot_x, hot_y);
 
1614
}
 
1615
 
 
1616
/**
 
1617
 * gtk_drag_set_icon_stock:
 
1618
 * @context: the context for a drag. (This must be called 
 
1619
 *            with a  context for the source side of a drag)
 
1620
 * @stock_id: the ID of the stock icon to use for the drag.
 
1621
 * @hot_x: the X offset within the icon of the hotspot.
 
1622
 * @hot_y: the Y offset within the icon of the hotspot.
 
1623
 * 
 
1624
 * Sets the icon for a given drag from a stock ID.
 
1625
 **/
 
1626
void 
 
1627
gtk_drag_set_icon_stock  (GdkDragContext *context,
 
1628
                          const gchar    *stock_id,
 
1629
                          gint            hot_x,
 
1630
                          gint            hot_y)
 
1631
{
 
1632
 
 
1633
  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
1634
  g_return_if_fail (context->is_source);
 
1635
  g_return_if_fail (stock_id != NULL);
 
1636
 
 
1637
  set_icon_stock_pixbuf (context, stock_id, NULL, hot_x, hot_y);
 
1638
}
 
1639
 
 
1640
/**
 
1641
 * gtk_drag_set_icon_pixmap:
 
1642
 * @context: the context for a drag. (This must be called 
 
1643
 *            with a  context for the source side of a drag)
 
1644
 * @colormap: the colormap of the icon 
 
1645
 * @pixmap: the image data for the icon 
 
1646
 * @mask: the transparency mask for the icon
 
1647
 * @hot_x: the X offset within @pixmap of the hotspot.
 
1648
 * @hot_y: the Y offset within @pixmap of the hotspot.
 
1649
 * 
 
1650
 * Sets @pixmap as the icon for a given drag. GTK+ retains
 
1651
 * references for the arguments, and will release them when
 
1652
 * they are no longer needed. In general, gtk_drag_set_icon_pixbuf()
 
1653
 * will be more convenient to use.
 
1654
 **/
 
1655
void 
 
1656
gtk_drag_set_icon_pixmap (GdkDragContext    *context,
 
1657
                          GdkColormap       *colormap,
 
1658
                          GdkPixmap         *pixmap,
 
1659
                          GdkBitmap         *mask,
 
1660
                          gint               hot_x,
 
1661
                          gint               hot_y)
 
1662
{
 
1663
  g_warning ("gtk_drag_set_icon_pixmap is not supported on Mac OS X");
 
1664
}
 
1665
 
 
1666
/**
 
1667
 * gtk_drag_set_icon_name:
 
1668
 * @context: the context for a drag. (This must be called 
 
1669
 *            with a context for the source side of a drag)
 
1670
 * @icon_name: name of icon to use
 
1671
 * @hot_x: the X offset of the hotspot within the icon
 
1672
 * @hot_y: the Y offset of the hotspot within the icon
 
1673
 * 
 
1674
 * Sets the icon for a given drag from a named themed icon. See
 
1675
 * the docs for #GtkIconTheme for more details. Note that the
 
1676
 * size of the icon depends on the icon theme (the icon is
 
1677
 * loaded at the symbolic size #GTK_ICON_SIZE_DND), thus 
 
1678
 * @hot_x and @hot_y have to be used with care.
 
1679
 *
 
1680
 * Since: 2.8
 
1681
 **/
 
1682
void 
 
1683
gtk_drag_set_icon_name (GdkDragContext *context,
 
1684
                        const gchar    *icon_name,
 
1685
                        gint            hot_x,
 
1686
                        gint            hot_y)
 
1687
{
 
1688
  GdkScreen *screen;
 
1689
  GtkSettings *settings;
 
1690
  GtkIconTheme *icon_theme;
 
1691
  GdkPixbuf *pixbuf;
 
1692
  gint width, height, icon_size;
 
1693
 
 
1694
  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
1695
  g_return_if_fail (context->is_source);
 
1696
  g_return_if_fail (icon_name != NULL);
 
1697
 
 
1698
  screen = gdk_drawable_get_screen (context->source_window);
 
1699
  g_return_if_fail (screen != NULL);
 
1700
 
 
1701
  settings = gtk_settings_get_for_screen (screen);
 
1702
  if (gtk_icon_size_lookup_for_settings (settings,
 
1703
                                         GTK_ICON_SIZE_DND,
 
1704
                                         &width, &height))
 
1705
    icon_size = MAX (width, height);
 
1706
  else 
 
1707
    icon_size = 32; /* default value for GTK_ICON_SIZE_DND */ 
 
1708
 
 
1709
  icon_theme = gtk_icon_theme_get_for_screen (screen);
 
1710
 
 
1711
  pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name,
 
1712
                                     icon_size, 0, NULL);
 
1713
  if (pixbuf)
 
1714
    set_icon_stock_pixbuf (context, NULL, pixbuf, hot_x, hot_y);
 
1715
  else
 
1716
    g_warning ("Cannot load drag icon from icon name %s", icon_name);
 
1717
}
 
1718
 
 
1719
/**
 
1720
 * gtk_drag_set_icon_default:
 
1721
 * @context: the context for a drag. (This must be called 
 
1722
             with a  context for the source side of a drag)
 
1723
 * 
 
1724
 * Sets the icon for a particular drag to the default
 
1725
 * icon.
 
1726
 **/
 
1727
void 
 
1728
gtk_drag_set_icon_default (GdkDragContext    *context)
 
1729
{
 
1730
  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
1731
  g_return_if_fail (context->is_source);
 
1732
 
 
1733
  gtk_drag_set_icon_stock (context, GTK_STOCK_DND, -2, -2);
 
1734
}
 
1735
 
 
1736
void 
 
1737
gtk_drag_set_default_icon (GdkColormap   *colormap,
 
1738
                           GdkPixmap     *pixmap,
 
1739
                           GdkBitmap     *mask,
 
1740
                           gint           hot_x,
 
1741
                           gint           hot_y)
 
1742
{
 
1743
  g_warning ("gtk_drag_set_default_icon is not supported on Mac OS X.");
 
1744
}
 
1745
 
 
1746
static void
 
1747
gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
 
1748
{
 
1749
  if (info->icon_pixbuf)
 
1750
    g_object_unref (info->icon_pixbuf);
 
1751
 
 
1752
  g_signal_emit_by_name (info->widget, "drag_end", 
 
1753
                         info->context);
 
1754
 
 
1755
  if (info->widget)
 
1756
    g_object_unref (info->widget);
 
1757
 
 
1758
  gtk_target_list_unref (info->target_list);
 
1759
 
 
1760
  gtk_drag_clear_source_info (info->context);
 
1761
  g_object_unref (info->context);
 
1762
 
 
1763
  g_free (info);
 
1764
}
 
1765
 
 
1766
static void
 
1767
gtk_drag_drop_finished (GtkDragSourceInfo *info)
 
1768
{
 
1769
  gtk_drag_source_info_destroy (info);
 
1770
}
 
1771
 
 
1772
/*************************************************************
 
1773
 * _gtk_drag_source_handle_event:
 
1774
 *     Called from widget event handling code on Drag events
 
1775
 *     for drag sources.
 
1776
 *
 
1777
 *   arguments:
 
1778
 *     toplevel: Toplevel widget that received the event
 
1779
 *     event:
 
1780
 *   results:
 
1781
 *************************************************************/
 
1782
 
 
1783
void
 
1784
_gtk_drag_source_handle_event (GtkWidget *widget,
 
1785
                               GdkEvent  *event)
 
1786
{
 
1787
  GtkDragSourceInfo *info;
 
1788
  GdkDragContext *context;
 
1789
 
 
1790
  g_return_if_fail (widget != NULL);
 
1791
  g_return_if_fail (event != NULL);
 
1792
 
 
1793
  context = event->dnd.context;
 
1794
  info = gtk_drag_get_source_info (context, FALSE);
 
1795
  if (!info)
 
1796
    return;
 
1797
 
 
1798
  switch (event->type)
 
1799
    {
 
1800
    case GDK_DROP_FINISHED:
 
1801
      gtk_drag_drop_finished (info);
 
1802
      break;
 
1803
    default:
 
1804
      g_assert_not_reached ();
 
1805
    }  
 
1806
}
 
1807
 
 
1808
 
 
1809
gboolean
 
1810
gtk_drag_check_threshold (GtkWidget *widget,
 
1811
                          gint       start_x,
 
1812
                          gint       start_y,
 
1813
                          gint       current_x,
 
1814
                          gint       current_y)
 
1815
{
 
1816
  gint drag_threshold;
 
1817
 
 
1818
  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
1819
 
 
1820
  g_object_get (gtk_widget_get_settings (widget),
 
1821
                "gtk-dnd-drag-threshold", &drag_threshold,
 
1822
                NULL);
 
1823
  
 
1824
  return (ABS (current_x - start_x) > drag_threshold ||
 
1825
          ABS (current_y - start_y) > drag_threshold);
 
1826
}
 
1827
 
 
1828
#define __GTK_DND_C__
 
1829
#include "gtkaliasdef.c"