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

« back to all changes in this revision

Viewing changes to gdk/linux-fb/gdkdnd-fb.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
/* GDK - The GIMP Drawing Kit
 
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
#include "gdk.h"          /* For gdk_flush() */
 
29
#include "gdkdnd.h"
 
30
#include "gdkproperty.h"
 
31
#include "gdkinternals.h"
 
32
#include "gdkprivate-fb.h"
 
33
 
 
34
typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
 
35
 
 
36
typedef enum {
 
37
  GDK_DRAG_STATUS_DRAG,
 
38
  GDK_DRAG_STATUS_MOTION_WAIT,
 
39
  GDK_DRAG_STATUS_ACTION_WAIT,
 
40
  GDK_DRAG_STATUS_DROP
 
41
} GtkDragStatus;
 
42
 
 
43
/* Structure that holds information about a drag in progress.
 
44
 * this is used on both source and destination sides.
 
45
 */
 
46
struct _GdkDragContextPrivate {
 
47
  GdkAtom local_selection;
 
48
  
 
49
  guint16 last_x;               /* Coordinates from last event */
 
50
  guint16 last_y;
 
51
  
 
52
  guint drag_status : 4;        /* current status of drag */
 
53
};
 
54
 
 
55
/* Drag Contexts */
 
56
 
 
57
static GList *contexts;
 
58
static gpointer parent_class = NULL;
 
59
 
 
60
#define GDK_DRAG_CONTEXT_PRIVATE_DATA(ctx) ((GdkDragContextPrivate *) GDK_DRAG_CONTEXT (ctx)->windowing_data)
 
61
 
 
62
GdkDragContext *current_dest_drag = NULL;
 
63
 
 
64
static void
 
65
gdk_drag_context_init (GdkDragContext *dragcontext)
 
66
{
 
67
  dragcontext->windowing_data = g_new0 (GdkDragContextPrivate, 1);
 
68
 
 
69
  contexts = g_list_prepend (contexts, dragcontext);
 
70
}
 
71
 
 
72
static void
 
73
gdk_drag_context_finalize (GObject *object)
 
74
{
 
75
  GdkDragContext *context = GDK_DRAG_CONTEXT (object);
 
76
  GdkDragContextPrivate *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (object);
 
77
  
 
78
  g_list_free (context->targets);
 
79
 
 
80
  if (context->source_window)
 
81
    gdk_window_unref (context->source_window);
 
82
  
 
83
  if (context->dest_window)
 
84
    gdk_window_unref (context->dest_window);
 
85
 
 
86
  
 
87
  if (private)
 
88
    {
 
89
      g_free (private);
 
90
      context->windowing_data = NULL;
 
91
    }
 
92
  
 
93
  contexts = g_list_remove (contexts, context);
 
94
 
 
95
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
96
}
 
97
 
 
98
static void
 
99
gdk_drag_context_class_init (GdkDragContextClass *klass)
 
100
{
 
101
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
102
 
 
103
  parent_class = g_type_class_peek_parent (klass);
 
104
 
 
105
  object_class->finalize = gdk_drag_context_finalize;
 
106
}
 
107
 
 
108
 
 
109
GType
 
110
gdk_drag_context_get_type (void)
 
111
{
 
112
  static GType object_type = 0;
 
113
 
 
114
  if (!object_type)
 
115
    {
 
116
      static const GTypeInfo object_info =
 
117
      {
 
118
        sizeof (GdkDragContextClass),
 
119
        (GBaseInitFunc) NULL,
 
120
        (GBaseFinalizeFunc) NULL,
 
121
        (GClassInitFunc) gdk_drag_context_class_init,
 
122
        NULL,           /* class_finalize */
 
123
        NULL,           /* class_data */
 
124
        sizeof (GdkDragContext),
 
125
        0,              /* n_preallocs */
 
126
        (GInstanceInitFunc) gdk_drag_context_init,
 
127
      };
 
128
      
 
129
      object_type = g_type_register_static (G_TYPE_OBJECT,
 
130
                                            "GdkDragContext",
 
131
                                            &object_info,
 
132
                                            0);
 
133
    }
 
134
  
 
135
  return object_type;
 
136
}
 
137
 
 
138
GdkDragContext *
 
139
gdk_drag_context_new        (void)
 
140
{
 
141
  return (GdkDragContext *)g_object_new (gdk_drag_context_get_type (), NULL);
 
142
}
 
143
 
 
144
void            
 
145
gdk_drag_context_ref (GdkDragContext *context)
 
146
{
 
147
  g_object_ref (context);
 
148
}
 
149
 
 
150
void            
 
151
gdk_drag_context_unref (GdkDragContext *context)
 
152
{
 
153
  g_object_unref (context);
 
154
}
 
155
 
 
156
static GdkDragContext *
 
157
gdk_drag_context_find (gboolean     is_source,
 
158
                       GdkWindow   *source,
 
159
                       GdkWindow   *dest)
 
160
{
 
161
  GList *tmp_list = contexts;
 
162
  
 
163
  GdkDragContext *context;
 
164
  GdkDragContextPrivate *private;
 
165
 
 
166
  while (tmp_list)
 
167
    {
 
168
      context = (GdkDragContext *)tmp_list->data;
 
169
      private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
170
 
 
171
      if ((!context->is_source == !is_source) &&
 
172
          ((source == NULL) || (context->source_window && (context->source_window == source))) &&
 
173
          ((dest == NULL) || (context->dest_window && (context->dest_window == dest))))
 
174
          return context;
 
175
      
 
176
      tmp_list = tmp_list->next;
 
177
    }
 
178
  
 
179
  return NULL;
 
180
}
 
181
 
 
182
 
 
183
/*************************************************************
 
184
 ************************** Public API ***********************
 
185
 *************************************************************/
 
186
 
 
187
void
 
188
_gdk_dnd_init (void)
 
189
{
 
190
}
 
191
 
 
192
/* Source side */
 
193
 
 
194
static void
 
195
local_send_leave (GdkDragContext  *context,
 
196
                  guint32          time)
 
197
{
 
198
  GdkEvent tmp_event;
 
199
  
 
200
  if ((current_dest_drag != NULL) &&
 
201
      (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
 
202
      (current_dest_drag->source_window == context->source_window))
 
203
    {
 
204
      tmp_event.dnd.type = GDK_DRAG_LEAVE;
 
205
      tmp_event.dnd.window = context->dest_window;
 
206
      /* Pass ownership of context to the event */
 
207
      tmp_event.dnd.context = current_dest_drag;
 
208
      tmp_event.dnd.send_event = FALSE;
 
209
      tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
 
210
 
 
211
      current_dest_drag = NULL;
 
212
      
 
213
      gdk_event_put (&tmp_event);
 
214
    }
 
215
  
 
216
}
 
217
 
 
218
static void
 
219
local_send_enter (GdkDragContext  *context,
 
220
                  guint32          time)
 
221
{
 
222
  GdkEvent tmp_event;
 
223
  GdkDragContextPrivate *private;
 
224
  GdkDragContext *new_context;
 
225
 
 
226
  private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
227
  
 
228
  if (!private->local_selection)
 
229
    private->local_selection = gdk_atom_intern ("LocalDndSelection", FALSE);
 
230
 
 
231
  if (current_dest_drag != NULL)
 
232
    {
 
233
      gdk_drag_context_unref (current_dest_drag);
 
234
      current_dest_drag = NULL;
 
235
    }
 
236
 
 
237
  new_context = gdk_drag_context_new ();
 
238
  new_context->protocol = GDK_DRAG_PROTO_LOCAL;
 
239
  new_context->is_source = FALSE;
 
240
 
 
241
  new_context->source_window = context->source_window;
 
242
  gdk_window_ref (new_context->source_window);
 
243
  new_context->dest_window = context->dest_window;
 
244
  gdk_window_ref (new_context->dest_window);
 
245
 
 
246
  new_context->targets = g_list_copy (context->targets);
 
247
 
 
248
  gdk_window_set_events (new_context->source_window,
 
249
                         gdk_window_get_events (new_context->source_window) |
 
250
                         GDK_PROPERTY_CHANGE_MASK);
 
251
 new_context->actions = context->actions;
 
252
 
 
253
  tmp_event.dnd.type = GDK_DRAG_ENTER;
 
254
  tmp_event.dnd.window = context->dest_window;
 
255
  tmp_event.dnd.send_event = FALSE;
 
256
  tmp_event.dnd.context = new_context;
 
257
  gdk_drag_context_ref (new_context);
 
258
 
 
259
  tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
 
260
  
 
261
  current_dest_drag = new_context;
 
262
  
 
263
  (GDK_DRAG_CONTEXT_PRIVATE_DATA (new_context))->local_selection = 
 
264
    private->local_selection;
 
265
 
 
266
  gdk_event_put (&tmp_event);
 
267
}
 
268
 
 
269
static void
 
270
local_send_motion (GdkDragContext  *context,
 
271
                    gint            x_root, 
 
272
                    gint            y_root,
 
273
                    GdkDragAction   action,
 
274
                    guint32         time)
 
275
{
 
276
  GdkEvent tmp_event;
 
277
  
 
278
  if ((current_dest_drag != NULL) &&
 
279
      (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
 
280
      (current_dest_drag->source_window == context->source_window))
 
281
    {
 
282
      tmp_event.dnd.type = GDK_DRAG_MOTION;
 
283
      tmp_event.dnd.window = current_dest_drag->dest_window;
 
284
      tmp_event.dnd.send_event = FALSE;
 
285
      tmp_event.dnd.context = current_dest_drag;
 
286
      gdk_drag_context_ref (current_dest_drag);
 
287
 
 
288
      tmp_event.dnd.time = time;
 
289
 
 
290
      current_dest_drag->suggested_action = action;
 
291
      current_dest_drag->actions = current_dest_drag->suggested_action;
 
292
 
 
293
      tmp_event.dnd.x_root = x_root;
 
294
      tmp_event.dnd.y_root = y_root;
 
295
 
 
296
      (GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag))->last_x = x_root;
 
297
      (GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag))->last_y = y_root;
 
298
 
 
299
      GDK_DRAG_CONTEXT_PRIVATE_DATA (context)->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;
 
300
      
 
301
      gdk_event_put (&tmp_event);
 
302
    }
 
303
}
 
304
 
 
305
static void
 
306
local_send_drop (GdkDragContext *context, guint32 time)
 
307
{
 
308
  GdkEvent tmp_event;
 
309
  
 
310
  if ((current_dest_drag != NULL) &&
 
311
      (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
 
312
      (current_dest_drag->source_window == context->source_window))
 
313
    {
 
314
      GdkDragContextPrivate *private;
 
315
      private = GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag);
 
316
 
 
317
      tmp_event.dnd.type = GDK_DROP_START;
 
318
      tmp_event.dnd.window = current_dest_drag->dest_window;
 
319
      tmp_event.dnd.send_event = FALSE;
 
320
 
 
321
      tmp_event.dnd.context = current_dest_drag;
 
322
      gdk_drag_context_ref (current_dest_drag);
 
323
 
 
324
      tmp_event.dnd.time = GDK_CURRENT_TIME;
 
325
      
 
326
      tmp_event.dnd.x_root = private->last_x;
 
327
      tmp_event.dnd.y_root = private->last_y;
 
328
      
 
329
      gdk_event_put (&tmp_event);
 
330
    }
 
331
 
 
332
}
 
333
 
 
334
static void
 
335
gdk_drag_do_leave (GdkDragContext *context, guint32 time)
 
336
{
 
337
  if (context->dest_window)
 
338
    {
 
339
      switch (context->protocol)
 
340
        {
 
341
        case GDK_DRAG_PROTO_LOCAL:
 
342
          local_send_leave (context, time);
 
343
          break;
 
344
        default:
 
345
          break;
 
346
        }
 
347
 
 
348
      gdk_window_unref (context->dest_window);
 
349
      context->dest_window = NULL;
 
350
    }
 
351
}
 
352
 
 
353
GdkDragContext * 
 
354
gdk_drag_begin (GdkWindow     *window,
 
355
                GList         *targets)
 
356
{
 
357
  GList *tmp_list;
 
358
  GdkDragContext *new_context;
 
359
 
 
360
  g_return_val_if_fail (window != NULL, NULL);
 
361
 
 
362
  new_context = gdk_drag_context_new ();
 
363
  new_context->is_source = TRUE;
 
364
  new_context->source_window = window;
 
365
  gdk_window_ref (window);
 
366
 
 
367
  tmp_list = g_list_last (targets);
 
368
  new_context->targets = NULL;
 
369
  while (tmp_list)
 
370
    {
 
371
      new_context->targets = g_list_prepend (new_context->targets,
 
372
                                             tmp_list->data);
 
373
      tmp_list = tmp_list->prev;
 
374
    }
 
375
 
 
376
  new_context->actions = 0;
 
377
 
 
378
  return new_context;
 
379
}
 
380
 
 
381
guint32
 
382
gdk_drag_get_protocol_for_display (GdkDisplay      *display,
 
383
                                   guint32          xid,
 
384
                                   GdkDragProtocol *protocol)
 
385
{
 
386
  GdkWindow *window;
 
387
 
 
388
  window = gdk_window_lookup ((GdkNativeWindow) xid);
 
389
 
 
390
  if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
 
391
    {
 
392
      *protocol = GDK_DRAG_PROTO_LOCAL;
 
393
      return xid;
 
394
    }
 
395
  
 
396
  *protocol = GDK_DRAG_PROTO_NONE;
 
397
  return 0;
 
398
}
 
399
 
 
400
static GdkWindow *
 
401
get_toplevel_window_at (GdkWindow *ignore,
 
402
                        gint       x_root,
 
403
                        gint       y_root)
 
404
{
 
405
 
 
406
  GdkWindowObject *private;
 
407
  GdkWindowObject *sub;
 
408
  GdkWindowObject *child;
 
409
  GList *ltmp, *ltmp2;
 
410
  
 
411
  private = (GdkWindowObject *)_gdk_parent_root;
 
412
 
 
413
  for (ltmp = private->children; ltmp; ltmp = ltmp->next)
 
414
    {
 
415
      sub = ltmp->data;
 
416
          
 
417
      if ((GDK_WINDOW (sub) != ignore) &&
 
418
          (GDK_WINDOW_IS_MAPPED (sub)) &&
 
419
          (x_root >= sub->x) &&
 
420
          (x_root < sub->x + GDK_DRAWABLE_IMPL_FBDATA (sub)->width) &&
 
421
          (y_root >= sub->y) &&
 
422
          (y_root < sub->y + GDK_DRAWABLE_IMPL_FBDATA (sub)->height))
 
423
        {
 
424
          if (g_object_get_data (G_OBJECT (sub), "gdk-window-child-handler"))
 
425
            {
 
426
              /* Managed window, check children */
 
427
              for (ltmp2 = sub->children; ltmp2; ltmp2 = ltmp2->next)
 
428
                {
 
429
                  child = ltmp2->data;
 
430
                  
 
431
                  if ((GDK_WINDOW (child) != ignore) &&
 
432
                      (GDK_WINDOW_IS_MAPPED (child)) &&
 
433
                      (x_root >= sub->x + child->x) &&
 
434
                      (x_root < sub->x + child->x + GDK_DRAWABLE_IMPL_FBDATA (child)->width) &&
 
435
                      (y_root >= sub->y + child->y) &&
 
436
                      (y_root < sub->y + child->y + GDK_DRAWABLE_IMPL_FBDATA (child)->height))
 
437
                    return GDK_WINDOW (child);
 
438
                }
 
439
            }
 
440
          else
 
441
            return GDK_WINDOW (sub);
 
442
        }
 
443
    }
 
444
  return NULL;
 
445
}
 
446
 
 
447
 
 
448
void
 
449
gdk_drag_find_window_for_screen (GdkDragContext  *context,
 
450
                                 GdkWindow       *drag_window,
 
451
                                 GdkScreen       *screen,
 
452
                                 gint             x_root,
 
453
                                 gint             y_root,
 
454
                                 GdkWindow      **dest_window,
 
455
                                 GdkDragProtocol *protocol)
 
456
{
 
457
  GdkWindow *dest;
 
458
 
 
459
  g_return_if_fail (context != NULL);
 
460
 
 
461
  dest = get_toplevel_window_at (drag_window, x_root, y_root);
 
462
  if (dest == NULL)
 
463
    dest = _gdk_parent_root;
 
464
  
 
465
  if (context->dest_window != dest)
 
466
    {
 
467
      guint32 recipient;
 
468
 
 
469
      /* Check if new destination accepts drags, and which protocol */
 
470
      if ((recipient = gdk_drag_get_protocol ((guint32)dest, protocol)))
 
471
        {
 
472
          *dest_window = gdk_window_lookup ((GdkNativeWindow) recipient);
 
473
          gdk_window_ref (*dest_window);
 
474
        }
 
475
      else
 
476
        *dest_window = NULL;
 
477
    }
 
478
  else
 
479
    {
 
480
      *dest_window = context->dest_window;
 
481
      if (*dest_window)
 
482
        gdk_window_ref (*dest_window);
 
483
      *protocol = context->protocol;
 
484
    }
 
485
  
 
486
}
 
487
 
 
488
gboolean        
 
489
gdk_drag_motion (GdkDragContext *context,
 
490
                 GdkWindow      *dest_window,
 
491
                 GdkDragProtocol protocol,
 
492
                 gint            x_root, 
 
493
                 gint            y_root,
 
494
                 GdkDragAction   suggested_action,
 
495
                 GdkDragAction   possible_actions,
 
496
                 guint32         time)
 
497
{
 
498
  GdkDragContextPrivate *private;
 
499
 
 
500
  g_return_val_if_fail (context != NULL, FALSE);
 
501
 
 
502
  private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
503
  
 
504
  if (context->dest_window != dest_window)
 
505
    {
 
506
      GdkEvent temp_event;
 
507
 
 
508
      /* Send a leave to the last destination */
 
509
      gdk_drag_do_leave (context, time);
 
510
      private->drag_status = GDK_DRAG_STATUS_DRAG;
 
511
 
 
512
      /* Check if new destination accepts drags, and which protocol */
 
513
      if (dest_window)
 
514
        {
 
515
          context->dest_window = dest_window;
 
516
          gdk_window_ref (context->dest_window);
 
517
          context->protocol = protocol;
 
518
 
 
519
          switch (protocol)
 
520
            {
 
521
            case GDK_DRAG_PROTO_LOCAL:
 
522
              local_send_enter (context, time);
 
523
              break;
 
524
 
 
525
            default:
 
526
              break;
 
527
            }
 
528
          context->suggested_action = suggested_action;
 
529
        }
 
530
      else
 
531
        {
 
532
          context->dest_window = NULL;
 
533
          context->action = 0;
 
534
        }
 
535
 
 
536
      /* Push a status event, to let the client know that
 
537
       * the drag changed 
 
538
       */
 
539
 
 
540
      temp_event.dnd.type = GDK_DRAG_STATUS;
 
541
      temp_event.dnd.window = context->source_window;
 
542
      /* We use this to signal a synthetic status. Perhaps
 
543
       * we should use an extra field...
 
544
       */
 
545
      temp_event.dnd.send_event = TRUE;
 
546
 
 
547
      temp_event.dnd.context = context;
 
548
      temp_event.dnd.time = time;
 
549
 
 
550
      gdk_event_put (&temp_event);
 
551
    }
 
552
  else
 
553
    {
 
554
      context->suggested_action = suggested_action;
 
555
    }
 
556
 
 
557
  /* Send a drag-motion event */
 
558
 
 
559
  private->last_x = x_root;
 
560
  private->last_y = y_root;
 
561
      
 
562
  if (context->dest_window)
 
563
    {
 
564
      if (private->drag_status == GDK_DRAG_STATUS_DRAG)
 
565
        {
 
566
          switch (context->protocol)
 
567
            {
 
568
            case GDK_DRAG_PROTO_LOCAL:
 
569
              local_send_motion (context, x_root, y_root, suggested_action, time);
 
570
              break;
 
571
              
 
572
            case GDK_DRAG_PROTO_NONE:
 
573
              g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()");
 
574
              break;
 
575
            default:
 
576
              break;
 
577
            }
 
578
        }
 
579
      else
 
580
        return TRUE;
 
581
    }
 
582
 
 
583
  return FALSE;
 
584
}
 
585
 
 
586
void
 
587
gdk_drag_drop (GdkDragContext *context,
 
588
               guint32         time)
 
589
{
 
590
  g_return_if_fail (context != NULL);
 
591
 
 
592
  if (context->dest_window)
 
593
    {
 
594
      switch (context->protocol)
 
595
        {
 
596
        case GDK_DRAG_PROTO_LOCAL:
 
597
          local_send_drop (context, time);
 
598
          break;
 
599
 
 
600
        case GDK_DRAG_PROTO_NONE:
 
601
          g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()");
 
602
          break;
 
603
        default:
 
604
          break;
 
605
        }
 
606
    }
 
607
}
 
608
 
 
609
void
 
610
gdk_drag_abort (GdkDragContext *context,
 
611
                guint32         time)
 
612
{
 
613
  g_return_if_fail (context != NULL);
 
614
 
 
615
  gdk_drag_do_leave (context, time);
 
616
}
 
617
 
 
618
/* Destination side */
 
619
 
 
620
void             
 
621
gdk_drag_status (GdkDragContext   *context,
 
622
                 GdkDragAction     action,
 
623
                 guint32           time)
 
624
{
 
625
  GdkDragContextPrivate *private;
 
626
  GdkDragContext *src_context;
 
627
  GdkEvent tmp_event;
 
628
 
 
629
  g_return_if_fail (context != NULL);
 
630
 
 
631
  private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
632
 
 
633
  src_context = gdk_drag_context_find (TRUE,
 
634
                                       context->source_window,
 
635
                                       context->dest_window);
 
636
 
 
637
  if (src_context)
 
638
    {
 
639
      GdkDragContextPrivate *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (src_context);
 
640
      
 
641
      if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
 
642
        private->drag_status = GDK_DRAG_STATUS_DRAG;
 
643
 
 
644
      tmp_event.dnd.type = GDK_DRAG_STATUS;
 
645
      tmp_event.dnd.window = context->source_window;
 
646
      tmp_event.dnd.send_event = FALSE;
 
647
      tmp_event.dnd.context = src_context;
 
648
      gdk_drag_context_ref (src_context);
 
649
 
 
650
      tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
 
651
 
 
652
      if (action == GDK_ACTION_DEFAULT)
 
653
        action = 0;
 
654
      
 
655
      src_context->action = action;
 
656
      
 
657
      gdk_event_put (&tmp_event);
 
658
    }
 
659
}
 
660
 
 
661
void 
 
662
gdk_drop_reply (GdkDragContext   *context,
 
663
                gboolean          ok,
 
664
                guint32           time)
 
665
{
 
666
  g_return_if_fail (context != NULL);
 
667
}
 
668
 
 
669
void             
 
670
gdk_drop_finish (GdkDragContext   *context,
 
671
                 gboolean          success,
 
672
                 guint32           time)
 
673
{
 
674
  GdkDragContextPrivate *private;
 
675
  GdkDragContext *src_context;
 
676
  GdkEvent tmp_event;
 
677
        
 
678
  g_return_if_fail (context != NULL);
 
679
 
 
680
  private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
681
 
 
682
  src_context = gdk_drag_context_find (TRUE,
 
683
                                       context->source_window,
 
684
                                       context->dest_window);
 
685
  if (src_context)
 
686
    {
 
687
      tmp_event.dnd.type = GDK_DROP_FINISHED;
 
688
      tmp_event.dnd.window = src_context->source_window;
 
689
      tmp_event.dnd.send_event = FALSE;
 
690
      tmp_event.dnd.context = src_context;
 
691
      gdk_drag_context_ref (src_context);
 
692
 
 
693
      gdk_event_put (&tmp_event);
 
694
    }
 
695
}
 
696
 
 
697
 
 
698
void            
 
699
gdk_window_register_dnd (GdkWindow      *window)
 
700
{
 
701
  g_return_if_fail (window != NULL);
 
702
 
 
703
  if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
 
704
    return;
 
705
  else
 
706
    gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
 
707
}
 
708
 
 
709
/*************************************************************
 
710
 * gdk_drag_get_selection:
 
711
 *     Returns the selection atom for the current source window
 
712
 *   arguments:
 
713
 *     
 
714
 *   results:
 
715
 *************************************************************/
 
716
 
 
717
GdkAtom       
 
718
gdk_drag_get_selection (GdkDragContext *context)
 
719
{
 
720
  g_return_val_if_fail (context != NULL, GDK_NONE);
 
721
 
 
722
  if (context->protocol == GDK_DRAG_PROTO_LOCAL)
 
723
    return (GDK_DRAG_CONTEXT_PRIVATE_DATA (context))->local_selection;
 
724
  else 
 
725
    return GDK_NONE;
 
726
}
 
727