Bug Summary

File:cdk/x11/cdkdnd-x11.c
Warning:line 1284, column 33
Out of bound memory access (access exceeds upper limit of memory block)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdkdnd-x11.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/cdk/x11 -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -D G_LOG_DOMAIN="Cdk" -D G_LOG_USE_STRUCTURED=1 -D CDK_COMPILATION -I ../.. -I ../../cdk -I ../../cdk -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/cdk/x11 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172241-43638-1 -x c cdkdnd-x11.c
1/* CDK - 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, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the CTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * CTK+ at ftp://ftp.ctk.org/pub/ctk/.
23 */
24
25#include "config.h"
26
27#include "cdkx11dnd.h"
28#include "cdkdndprivate.h"
29
30#include "cdkmain.h"
31#include "cdkinternals.h"
32#include "cdkasync.h"
33#include "cdkproperty.h"
34#include "cdkprivate-x11.h"
35#include "cdkscreen-x11.h"
36#include "cdkdisplay-x11.h"
37
38#include <X11/Xlib.h>
39#include <X11/Xutil.h>
40#include <X11/Xatom.h>
41#include <X11/extensions/shape.h>
42#ifdef HAVE_XCOMPOSITE1
43#include <X11/extensions/Xcomposite.h>
44#endif
45
46#include <string.h>
47
48typedef enum {
49 CDK_DRAG_STATUS_DRAG,
50 CDK_DRAG_STATUS_MOTION_WAIT,
51 CDK_DRAG_STATUS_ACTION_WAIT,
52 CDK_DRAG_STATUS_DROP
53} CtkDragStatus;
54
55typedef struct {
56 guint32 xid;
57 gint x, y, width, height;
58 gboolean mapped;
59 gboolean shape_selected;
60 gboolean shape_valid;
61 cairo_region_t *shape;
62} CdkCacheChild;
63
64typedef struct {
65 GList *children;
66 GHashTable *child_hash;
67 guint old_event_mask;
68 CdkScreen *screen;
69 gint ref_count;
70} CdkWindowCache;
71
72
73struct _CdkX11DragContext
74{
75 CdkDragContext context;
76
77 gint start_x; /* Where the drag started */
78 gint start_y;
79 guint16 last_x; /* Coordinates from last event */
80 guint16 last_y;
81 CdkDragAction old_action; /* The last action we sent to the source */
82 CdkDragAction old_actions; /* The last actions we sent to the source */
83 CdkDragAction xdnd_actions; /* What is currently set in XdndActionList */
84 guint version; /* Xdnd protocol version */
85
86 GSList *window_caches;
87
88 CdkWindow *drag_window;
89
90 CdkWindow *ipc_window;
91 CdkCursor *cursor;
92 CdkSeat *grab_seat;
93 CdkDragAction actions;
94 CdkDragAction current_action;
95
96 gint hot_x;
97 gint hot_y;
98
99 Window dest_xid; /* The last window we looked up */
100 Window drop_xid; /* The (non-proxied) window that is receiving drops */
101 guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */
102 guint xdnd_actions_set : 1; /* Whether we've already set XdndActionList */
103 guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */
104 guint drag_status : 4; /* current status of drag */
105 guint drop_failed : 1; /* Whether the drop was unsuccessful */
106};
107
108struct _CdkX11DragContextClass
109{
110 CdkDragContextClass parent_class;
111};
112
113typedef struct {
114 gint keysym;
115 gint modifiers;
116} GrabKey;
117
118static GrabKey grab_keys[] = {
119 { XK_Escape0xff1b, 0 },
120 { XK_space0x0020, 0 },
121 { XK_KP_Space0xff80, 0 },
122 { XK_Return0xff0d, 0 },
123 { XK_KP_Enter0xff8d, 0 },
124 { XK_Up0xff52, 0 },
125 { XK_Up0xff52, Mod1Mask(1<<3) },
126 { XK_Down0xff54, 0 },
127 { XK_Down0xff54, Mod1Mask(1<<3) },
128 { XK_Left0xff51, 0 },
129 { XK_Left0xff51, Mod1Mask(1<<3) },
130 { XK_Right0xff53, 0 },
131 { XK_Right0xff53, Mod1Mask(1<<3) },
132 { XK_KP_Up0xff97, 0 },
133 { XK_KP_Up0xff97, Mod1Mask(1<<3) },
134 { XK_KP_Down0xff99, 0 },
135 { XK_KP_Down0xff99, Mod1Mask(1<<3) },
136 { XK_KP_Left0xff96, 0 },
137 { XK_KP_Left0xff96, Mod1Mask(1<<3) },
138 { XK_KP_Right0xff98, 0 },
139 { XK_KP_Right0xff98, Mod1Mask(1<<3) }
140};
141
142/* Forward declarations */
143
144static CdkWindowCache *cdk_window_cache_get (CdkScreen *screen);
145static CdkWindowCache *cdk_window_cache_ref (CdkWindowCache *cache);
146static void cdk_window_cache_unref (CdkWindowCache *cache);
147
148static CdkFilterReturn xdnd_enter_filter (CdkXEvent *xev,
149 CdkEvent *event,
150 gpointer data);
151static CdkFilterReturn xdnd_leave_filter (CdkXEvent *xev,
152 CdkEvent *event,
153 gpointer data);
154static CdkFilterReturn xdnd_position_filter (CdkXEvent *xev,
155 CdkEvent *event,
156 gpointer data);
157static CdkFilterReturn xdnd_status_filter (CdkXEvent *xev,
158 CdkEvent *event,
159 gpointer data);
160static CdkFilterReturn xdnd_finished_filter (CdkXEvent *xev,
161 CdkEvent *event,
162 gpointer data);
163static CdkFilterReturn xdnd_drop_filter (CdkXEvent *xev,
164 CdkEvent *event,
165 gpointer data);
166
167static void xdnd_manage_source_filter (CdkDragContext *context,
168 CdkWindow *window,
169 gboolean add_filter);
170
171gboolean cdk_x11_drag_context_handle_event (CdkDragContext *context,
172 const CdkEvent *event);
173void cdk_x11_drag_context_action_changed (CdkDragContext *context,
174 CdkDragAction action);
175
176static GList *contexts;
177static GSList *window_caches;
178
179static const struct {
180 const char *atom_name;
181 CdkFilterFunc func;
182} xdnd_filters[] = {
183 { "XdndEnter", xdnd_enter_filter },
184 { "XdndLeave", xdnd_leave_filter },
185 { "XdndPosition", xdnd_position_filter },
186 { "XdndStatus", xdnd_status_filter },
187 { "XdndFinished", xdnd_finished_filter },
188 { "XdndDrop", xdnd_drop_filter },
189};
190
191
192G_DEFINE_TYPE (CdkX11DragContext, cdk_x11_drag_context, CDK_TYPE_DRAG_CONTEXT)static void cdk_x11_drag_context_init (CdkX11DragContext *self
); static void cdk_x11_drag_context_class_init (CdkX11DragContextClass
*klass); static GType cdk_x11_drag_context_get_type_once (void
); static gpointer cdk_x11_drag_context_parent_class = ((void
*)0); static gint CdkX11DragContext_private_offset; static void
cdk_x11_drag_context_class_intern_init (gpointer klass) { cdk_x11_drag_context_parent_class
= g_type_class_peek_parent (klass); if (CdkX11DragContext_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CdkX11DragContext_private_offset
); cdk_x11_drag_context_class_init ((CdkX11DragContextClass*)
klass); } __attribute__ ((__unused__)) static inline gpointer
cdk_x11_drag_context_get_instance_private (CdkX11DragContext
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CdkX11DragContext_private_offset
)))); } GType cdk_x11_drag_context_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cdk_x11_drag_context_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cdk_x11_drag_context_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((cdk_drag_context_get_type ()), g_intern_static_string ("CdkX11DragContext"
), sizeof (CdkX11DragContextClass), (GClassInitFunc)(void (*)
(void)) cdk_x11_drag_context_class_intern_init, sizeof (CdkX11DragContext
), (GInstanceInitFunc)(void (*)(void)) cdk_x11_drag_context_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
193
194static void
195cdk_x11_drag_context_init (CdkX11DragContext *context)
196{
197 contexts = g_list_prepend (contexts, context);
198}
199
200static void cdk_x11_drag_context_finalize (GObject *object);
201static CdkWindow * cdk_x11_drag_context_find_window (CdkDragContext *context,
202 CdkWindow *drag_window,
203 CdkScreen *screen,
204 gint x_root,
205 gint y_root,
206 CdkDragProtocol *protocol);
207static gboolean cdk_x11_drag_context_drag_motion (CdkDragContext *context,
208 CdkWindow *dest_window,
209 CdkDragProtocol protocol,
210 gint x_root,
211 gint y_root,
212 CdkDragAction suggested_action,
213 CdkDragAction possible_actions,
214 guint32 time);
215static void cdk_x11_drag_context_drag_status (CdkDragContext *context,
216 CdkDragAction action,
217 guint32 time_);
218static void cdk_x11_drag_context_drag_abort (CdkDragContext *context,
219 guint32 time_);
220static void cdk_x11_drag_context_drag_drop (CdkDragContext *context,
221 guint32 time_);
222static void cdk_x11_drag_context_drop_reply (CdkDragContext *context,
223 gboolean accept,
224 guint32 time_);
225static void cdk_x11_drag_context_drop_finish (CdkDragContext *context,
226 gboolean success,
227 guint32 time_);
228static gboolean cdk_x11_drag_context_drop_status (CdkDragContext *context);
229static CdkAtom cdk_x11_drag_context_get_selection (CdkDragContext *context);
230static CdkWindow * cdk_x11_drag_context_get_drag_window (CdkDragContext *context);
231static void cdk_x11_drag_context_set_hotspot (CdkDragContext *context,
232 gint hot_x,
233 gint hot_y);
234static void cdk_x11_drag_context_drop_done (CdkDragContext *context,
235 gboolean success);
236static gboolean cdk_x11_drag_context_manage_dnd (CdkDragContext *context,
237 CdkWindow *window,
238 CdkDragAction actions);
239static void cdk_x11_drag_context_set_cursor (CdkDragContext *context,
240 CdkCursor *cursor);
241static void cdk_x11_drag_context_cancel (CdkDragContext *context,
242 CdkDragCancelReason reason);
243static void cdk_x11_drag_context_drop_performed (CdkDragContext *context,
244 guint32 time);
245
246static void
247cdk_x11_drag_context_class_init (CdkX11DragContextClass *klass)
248{
249 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
250 CdkDragContextClass *context_class = CDK_DRAG_CONTEXT_CLASS (klass)((((CdkDragContextClass*) (void *) g_type_check_class_cast ((
GTypeClass*) ((klass)), ((cdk_drag_context_get_type ()))))))
;
251
252 object_class->finalize = cdk_x11_drag_context_finalize;
253
254 context_class->find_window = cdk_x11_drag_context_find_window;
255 context_class->drag_status = cdk_x11_drag_context_drag_status;
256 context_class->drag_motion = cdk_x11_drag_context_drag_motion;
257 context_class->drag_abort = cdk_x11_drag_context_drag_abort;
258 context_class->drag_drop = cdk_x11_drag_context_drag_drop;
259 context_class->drop_reply = cdk_x11_drag_context_drop_reply;
260 context_class->drop_finish = cdk_x11_drag_context_drop_finish;
261 context_class->drop_status = cdk_x11_drag_context_drop_status;
262 context_class->get_selection = cdk_x11_drag_context_get_selection;
263 context_class->get_drag_window = cdk_x11_drag_context_get_drag_window;
264 context_class->set_hotspot = cdk_x11_drag_context_set_hotspot;
265 context_class->drop_done = cdk_x11_drag_context_drop_done;
266 context_class->manage_dnd = cdk_x11_drag_context_manage_dnd;
267 context_class->set_cursor = cdk_x11_drag_context_set_cursor;
268 context_class->cancel = cdk_x11_drag_context_cancel;
269 context_class->drop_performed = cdk_x11_drag_context_drop_performed;
270 context_class->handle_event = cdk_x11_drag_context_handle_event;
271 context_class->action_changed = cdk_x11_drag_context_action_changed;
272}
273
274static void
275cdk_x11_drag_context_finalize (GObject *object)
276{
277 CdkDragContext *context = CDK_DRAG_CONTEXT (object)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cdk_drag_context_get_type ()))))))
;
278 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (object)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((cdk_x11_drag_context_get_type (
)))))))
;
279 CdkWindow *drag_window;
280
281 if (context->source_window)
282 {
283 if ((context->protocol == CDK_DRAG_PROTO_XDND) && !context->is_source)
284 xdnd_manage_source_filter (context, context->source_window, FALSE(0));
285 }
286
287 g_slist_free_full (x11_context->window_caches, (GDestroyNotify)cdk_window_cache_unref);
288 x11_context->window_caches = NULL((void*)0);
289
290 contexts = g_list_remove (contexts, context);
291
292 drag_window = context->drag_window;
293
294 G_OBJECT_CLASS (cdk_x11_drag_context_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cdk_x11_drag_context_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
295
296 if (drag_window)
297 cdk_window_destroy (drag_window);
298}
299
300/* Drag Contexts */
301
302static CdkDragContext *
303cdk_drag_context_find (CdkDisplay *display,
304 gboolean is_source,
305 Window source_xid,
306 Window dest_xid)
307{
308 GList *tmp_list;
309 CdkDragContext *context;
310 Window context_dest_xid;
311
312 for (tmp_list = contexts; tmp_list; tmp_list = tmp_list->next)
313 {
314 CdkX11DragContext *context_x11;
315
316 context = (CdkDragContext *)tmp_list->data;
317 context_x11 = (CdkX11DragContext *)context;
318
319 if ((context->source_window && cdk_window_get_display (context->source_window) != display) ||
320 (context->dest_window && cdk_window_get_display (context->dest_window) != display))
321 continue;
322
323 context_dest_xid = context->dest_window
324 ? (context_x11->drop_xid
325 ? context_x11->drop_xid
326 : CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
)
327 : None0L;
328
329 if ((!context->is_source == !is_source) &&
330 ((source_xid == None0L) || (context->source_window &&
331 (CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
== source_xid))) &&
332 ((dest_xid == None0L) || (context_dest_xid == dest_xid)))
333 return context;
334 }
335
336 return NULL((void*)0);
337}
338
339static void
340precache_target_list (CdkDragContext *context)
341{
342 if (context->targets)
343 {
344 GPtrArray *targets = g_ptr_array_new ();
345 GList *tmp_list;
346 int i;
347
348 for (tmp_list = context->targets; tmp_list; tmp_list = tmp_list->next)
349 g_ptr_array_add (targets, cdk_atom_name (CDK_POINTER_TO_ATOM (tmp_list->data)((CdkAtom)(tmp_list->data))));
350
351 _cdk_x11_precache_atoms (CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
,
352 (const gchar **)targets->pdata,
353 targets->len);
354
355 for (i =0; i < targets->len; i++)
356 g_free (targets->pdata[i]);
357
358 g_ptr_array_free (targets, TRUE(!(0)));
359 }
360}
361
362/* Utility functions */
363
364static void
365free_cache_child (CdkCacheChild *child,
366 CdkDisplay *display)
367{
368 if (child->shape)
369 cairo_region_destroy (child->shape);
370
371 if (child->shape_selected && display)
372 {
373 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
374
375 XShapeSelectInput (display_x11->xdisplay, child->xid, 0);
376 }
377
378 g_free (child);
379}
380
381static void
382cdk_window_cache_add (CdkWindowCache *cache,
383 guint32 xid,
384 gint x,
385 gint y,
386 gint width,
387 gint height,
388 gboolean mapped)
389{
390 CdkCacheChild *child = g_new (CdkCacheChild, 1)((CdkCacheChild *) g_malloc_n ((1), sizeof (CdkCacheChild)));
391
392 child->xid = xid;
393 child->x = x;
394 child->y = y;
395 child->width = width;
396 child->height = height;
397 child->mapped = mapped;
398 child->shape_selected = FALSE(0);
399 child->shape_valid = FALSE(0);
400 child->shape = NULL((void*)0);
401
402 cache->children = g_list_prepend (cache->children, child);
403 g_hash_table_insert (cache->child_hash, GUINT_TO_POINTER (xid)((gpointer) (gulong) (xid)),
404 cache->children);
405}
406
407static CdkFilterReturn
408cdk_window_cache_shape_filter (CdkXEvent *xev,
409 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
410 gpointer data)
411{
412 XEvent *xevent = (XEvent *)xev;
413 CdkWindowCache *cache = data;
414
415 CdkX11Display *display = CDK_X11_DISPLAY (cdk_screen_get_display (cache->screen))((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cdk_screen_get_display (cache->screen))), ((cdk_x11_display_get_type
()))))))
;
416
417 if (display->have_shapes &&
418 xevent->type == display->shape_event_base + ShapeNotify0)
419 {
420 XShapeEvent *xse = (XShapeEvent*)xevent;
421 GList *node;
422
423 node = g_hash_table_lookup (cache->child_hash,
424 GUINT_TO_POINTER (xse->window)((gpointer) (gulong) (xse->window)));
425 if (node)
426 {
427 CdkCacheChild *child = node->data;
428 child->shape_valid = FALSE(0);
429 if (child->shape)
430 {
431 cairo_region_destroy (child->shape);
432 child->shape = NULL((void*)0);
433 }
434 }
435
436 return CDK_FILTER_REMOVE;
437 }
438
439 return CDK_FILTER_CONTINUE;
440}
441
442static CdkFilterReturn
443cdk_window_cache_filter (CdkXEvent *xev,
444 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
445 gpointer data)
446{
447 XEvent *xevent = (XEvent *)xev;
448 CdkWindowCache *cache = data;
449
450 switch (xevent->type)
451 {
452 case CirculateNotify26:
453 break;
454 case ConfigureNotify22:
455 {
456 XConfigureEvent *xce = &xevent->xconfigure;
457 GList *node;
458
459 node = g_hash_table_lookup (cache->child_hash,
460 GUINT_TO_POINTER (xce->window)((gpointer) (gulong) (xce->window)));
461 if (node)
462 {
463 CdkCacheChild *child = node->data;
464 child->x = xce->x;
465 child->y = xce->y;
466 child->width = xce->width;
467 child->height = xce->height;
468 if (xce->above == None0L && (node->next))
469 {
470 GList *last = g_list_last (cache->children);
471 cache->children = g_list_remove_link (cache->children, node);
472 last->next = node;
473 node->next = NULL((void*)0);
474 node->prev = last;
475 }
476 else
477 {
478 GList *above_node = g_hash_table_lookup (cache->child_hash,
479 GUINT_TO_POINTER (xce->above)((gpointer) (gulong) (xce->above)));
480 if (above_node && node->next != above_node)
481 {
482 /* Put the window above (before in the list) above_node */
483 cache->children = g_list_remove_link (cache->children, node);
484 node->prev = above_node->prev;
485 if (node->prev)
486 node->prev->next = node;
487 else
488 cache->children = node;
489 node->next = above_node;
490 above_node->prev = node;
491 }
492 }
493 }
494 break;
495 }
496 case CreateNotify16:
497 {
498 XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
499
500 if (!g_hash_table_lookup (cache->child_hash,
501 GUINT_TO_POINTER (xcwe->window)((gpointer) (gulong) (xcwe->window))))
502 cdk_window_cache_add (cache, xcwe->window,
503 xcwe->x, xcwe->y, xcwe->width, xcwe->height,
504 FALSE(0));
505 break;
506 }
507 case DestroyNotify17:
508 {
509 XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
510 GList *node;
511
512 node = g_hash_table_lookup (cache->child_hash,
513 GUINT_TO_POINTER (xdwe->window)((gpointer) (gulong) (xdwe->window)));
514 if (node)
515 {
516 CdkCacheChild *child = node->data;
517
518 g_hash_table_remove (cache->child_hash,
519 GUINT_TO_POINTER (xdwe->window)((gpointer) (gulong) (xdwe->window)));
520 cache->children = g_list_remove_link (cache->children, node);
521 /* window is destroyed, no need to disable ShapeNotify */
522 free_cache_child (child, NULL((void*)0));
523 g_list_free_1 (node);
524 }
525 break;
526 }
527 case MapNotify19:
528 {
529 XMapEvent *xme = &xevent->xmap;
530 GList *node;
531
532 node = g_hash_table_lookup (cache->child_hash,
533 GUINT_TO_POINTER (xme->window)((gpointer) (gulong) (xme->window)));
534 if (node)
535 {
536 CdkCacheChild *child = node->data;
537 child->mapped = TRUE(!(0));
538 }
539 break;
540 }
541 case ReparentNotify21:
542 break;
543 case UnmapNotify18:
544 {
545 XMapEvent *xume = &xevent->xmap;
546 GList *node;
547
548 node = g_hash_table_lookup (cache->child_hash,
549 GUINT_TO_POINTER (xume->window)((gpointer) (gulong) (xume->window)));
550 if (node)
551 {
552 CdkCacheChild *child = node->data;
553 child->mapped = FALSE(0);
554 }
555 break;
556 }
557 default:
558 return CDK_FILTER_CONTINUE;
559 }
560 return CDK_FILTER_REMOVE;
561}
562
563static CdkWindowCache *
564cdk_window_cache_new (CdkScreen *screen)
565{
566 XWindowAttributes xwa;
567 Display *xdisplay = CDK_SCREEN_XDISPLAY (screen)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))->xdisplay
)
;
568 CdkWindow *root_window = cdk_screen_get_root_window (screen);
569 CdkChildInfoX11 *children;
570 guint nchildren, i;
571#ifdef HAVE_XCOMPOSITE1
572 Window cow;
573#endif
574
575 CdkWindowCache *result = g_new (CdkWindowCache, 1)((CdkWindowCache *) g_malloc_n ((1), sizeof (CdkWindowCache))
)
;
576
577 result->children = NULL((void*)0);
578 result->child_hash = g_hash_table_new (g_direct_hash, NULL((void*)0));
579 result->screen = screen;
580 result->ref_count = 1;
581
582 XGetWindowAttributes (xdisplay, CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
, &xwa);
583 result->old_event_mask = xwa.your_event_mask;
584
585 if (G_UNLIKELY (!CDK_X11_DISPLAY (CDK_X11_SCREEN (screen)->display)->trusted_client)(!((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CdkX11Screen*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((screen)), ((cdk_x11_screen_get_type ()))))
))->display)), ((cdk_x11_display_get_type()))))))->trusted_client
)
)
586 {
587 GList *toplevel_windows, *list;
588 gint x, y, width, height;
589
590 toplevel_windows = cdk_screen_get_toplevel_windows (screen);
591 for (list = toplevel_windows; list; list = list->next)
592 {
593 CdkWindow *window;
594 CdkWindowImplX11 *impl;
595
596 window = CDK_WINDOW (list->data)((((CdkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((list->data)), ((cdk_window_get_type ()))))))
;
597 impl = CDK_WINDOW_IMPL_X11 (window->impl)((((CdkWindowImplX11*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((window->impl)), ((cdk_window_impl_x11_get_type
()))))))
;
598 cdk_window_get_geometry (window, &x, &y, &width, &height);
599 cdk_window_cache_add (result, CDK_WINDOW_XID (window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((cdk_window_get_type ()))))))
->impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
,
600 x * impl->window_scale, y * impl->window_scale,
601 width * impl->window_scale,
602 height * impl->window_scale,
603 cdk_window_is_visible (window));
604 }
605 g_list_free (toplevel_windows);
606 return result;
607 }
608
609 XSelectInput (xdisplay, CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
,
610 result->old_event_mask | SubstructureNotifyMask(1L<<19));
611 cdk_window_add_filter (root_window, cdk_window_cache_filter, result);
612 cdk_window_add_filter (NULL((void*)0), cdk_window_cache_shape_filter, result);
613
614 if (!_cdk_x11_get_window_child_info (cdk_screen_get_display (screen),
615 CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
,
616 FALSE(0), NULL((void*)0),
617 &children, &nchildren))
618 return result;
619
620 for (i = 0; i < nchildren ; i++)
621 {
622 cdk_window_cache_add (result, children[i].window,
623 children[i].x, children[i].y, children[i].width, children[i].height,
624 children[i].is_mapped);
625 }
626
627 g_free (children);
628
629#ifdef HAVE_XCOMPOSITE1
630 /*
631 * Add the composite overlay window to the cache, as this can be a reasonable
632 * Xdnd proxy as well.
633 * This is only done when the screen is composited in order to avoid mapping
634 * the COW. We assume that the CM is using the COW (which is true for pretty
635 * much any CM currently in use).
636 */
637 if (cdk_screen_is_composited (screen))
638 {
639 cdk_x11_display_error_trap_push (CDK_X11_SCREEN (screen)((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))
->display);
640 cow = XCompositeGetOverlayWindow (xdisplay, CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
);
641 cdk_window_cache_add (result, cow, 0, 0,
642 cdk_x11_screen_get_width (screen) * CDK_X11_SCREEN(screen)((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))
->window_scale,
643 cdk_x11_screen_get_height (screen) * CDK_X11_SCREEN(screen)((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))
->window_scale,
644 TRUE(!(0)));
645 XCompositeReleaseOverlayWindow (xdisplay, CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
);
646 cdk_x11_display_error_trap_pop_ignored (CDK_X11_SCREEN (screen)((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))
->display);
647 }
648#endif
649
650 return result;
651}
652
653static void
654cdk_window_cache_destroy (CdkWindowCache *cache)
655{
656 CdkWindow *root_window = cdk_screen_get_root_window (cache->screen);
657 CdkDisplay *display;
658
659 XSelectInput (CDK_WINDOW_XDISPLAY (root_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (root_window)))), ((cdk_x11_screen_get_type
()))))))->xdisplay)
,
660 CDK_WINDOW_XID (root_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
,
661 cache->old_event_mask);
662 cdk_window_remove_filter (root_window, cdk_window_cache_filter, cache);
663 cdk_window_remove_filter (NULL((void*)0), cdk_window_cache_shape_filter, cache);
664
665 display = cdk_screen_get_display (cache->screen);
666
667 cdk_x11_display_error_trap_push (display);
668 g_list_foreach (cache->children, (GFunc)free_cache_child, display);
669 cdk_x11_display_error_trap_pop_ignored (display);
670
671 g_list_free (cache->children);
672 g_hash_table_destroy (cache->child_hash);
673
674 g_free (cache);
675}
676
677static CdkWindowCache *
678cdk_window_cache_ref (CdkWindowCache *cache)
679{
680 cache->ref_count += 1;
681
682 return cache;
683}
684
685static void
686cdk_window_cache_unref (CdkWindowCache *cache)
687{
688 g_assert (cache->ref_count > 0)do { if (cache->ref_count > 0) ; else g_assertion_message_expr
("Cdk", "cdkdnd-x11.c", 688, ((const char*) (__func__)), "cache->ref_count > 0"
); } while (0)
;
689
690 cache->ref_count -= 1;
691
692 if (cache->ref_count == 0)
693 {
694 window_caches = g_slist_remove (window_caches, cache);
695 cdk_window_cache_destroy (cache);
696 }
697}
698
699CdkWindowCache *
700cdk_window_cache_get (CdkScreen *screen)
701{
702 GSList *list;
703 CdkWindowCache *cache;
704
705 for (list = window_caches; list; list = list->next)
706 {
707 cache = list->data;
708 if (cache->screen == screen)
709 return cdk_window_cache_ref (cache);
710 }
711
712 cache = cdk_window_cache_new (screen);
713
714 window_caches = g_slist_prepend (window_caches, cache);
715
716 return cache;
717}
718
719static gboolean
720is_pointer_within_shape (CdkDisplay *display,
721 CdkCacheChild *child,
722 gint x_pos,
723 gint y_pos)
724{
725 if (!child->shape_selected)
726 {
727 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
728
729 XShapeSelectInput (display_x11->xdisplay, child->xid, ShapeNotifyMask(1L << 0));
730 child->shape_selected = TRUE(!(0));
731 }
732 if (!child->shape_valid)
733 {
734 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
735 cairo_region_t *input_shape;
736
737 child->shape = NULL((void*)0);
738 if (cdk_display_supports_shapes (display))
739 child->shape = _cdk_x11_xwindow_get_shape (display_x11->xdisplay,
740 child->xid, 1, ShapeBounding0);
741#ifdef ShapeInput2
742 input_shape = NULL((void*)0);
743 if (cdk_display_supports_input_shapes (display))
744 input_shape = _cdk_x11_xwindow_get_shape (display_x11->xdisplay,
745 child->xid, 1, ShapeInput2);
746
747 if (child->shape && input_shape)
748 {
749 cairo_region_intersect (child->shape, input_shape);
750 cairo_region_destroy (input_shape);
751 }
752 else if (input_shape)
753 {
754 child->shape = input_shape;
755 }
756#endif
757
758 child->shape_valid = TRUE(!(0));
759 }
760
761 return child->shape == NULL((void*)0) ||
762 cairo_region_contains_point (child->shape, x_pos, y_pos);
763}
764
765static Window
766get_client_window_at_coords_recurse (CdkDisplay *display,
767 Window win,
768 gboolean is_toplevel,
769 gint x,
770 gint y)
771{
772 CdkChildInfoX11 *children;
773 unsigned int nchildren;
774 int i;
775 gboolean found_child = FALSE(0);
776 CdkChildInfoX11 child = { 0, };
777 gboolean has_wm_state = FALSE(0);
778
779 if (!_cdk_x11_get_window_child_info (display, win, TRUE(!(0)),
780 is_toplevel? &has_wm_state : NULL((void*)0),
781 &children, &nchildren))
782 return None0L;
783
784 if (has_wm_state)
785 {
786 g_free (children);
787
788 return win;
789 }
790
791 for (i = nchildren - 1; (i >= 0) && !found_child; i--)
792 {
793 CdkChildInfoX11 *cur_child = &children[i];
794
795 if ((cur_child->is_mapped) && (cur_child->window_class == InputOutput1) &&
796 (x >= cur_child->x) && (x < cur_child->x + cur_child->width) &&
797 (y >= cur_child->y) && (y < cur_child->y + cur_child->height))
798 {
799 x -= cur_child->x;
800 y -= cur_child->y;
801 child = *cur_child;
802 found_child = TRUE(!(0));
803 }
804 }
805
806 g_free (children);
807
808 if (found_child)
809 {
810 if (child.has_wm_state)
811 return child.window;
812 else
813 return get_client_window_at_coords_recurse (display, child.window, FALSE(0), x, y);
814 }
815 else
816 return None0L;
817}
818
819static Window
820get_client_window_at_coords (CdkWindowCache *cache,
821 Window ignore,
822 gint x_root,
823 gint y_root)
824{
825 GList *tmp_list;
826 Window retval = None0L;
827 CdkDisplay *display;
828
829 display = cdk_screen_get_display (cache->screen);
830
831 cdk_x11_display_error_trap_push (display);
832
833 tmp_list = cache->children;
834
835 while (tmp_list && !retval)
836 {
837 CdkCacheChild *child = tmp_list->data;
838
839 if ((child->xid != ignore) && (child->mapped))
840 {
841 if ((x_root >= child->x) && (x_root < child->x + child->width) &&
842 (y_root >= child->y) && (y_root < child->y + child->height))
843 {
844 if (!is_pointer_within_shape (display, child,
845 x_root - child->x,
846 y_root - child->y))
847 {
848 tmp_list = tmp_list->next;
849 continue;
850 }
851
852 retval = get_client_window_at_coords_recurse (display,
853 child->xid, TRUE(!(0)),
854 x_root - child->x,
855 y_root - child->y);
856 if (!retval)
857 retval = child->xid;
858 }
859 }
860 tmp_list = tmp_list->next;
861 }
862
863 cdk_x11_display_error_trap_pop_ignored (display);
864
865 if (retval)
866 return retval;
867 else
868 return CDK_WINDOW_XID (cdk_screen_get_root_window (cache->screen))(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((cdk_screen_get_root_window (cache->screen
))), ((cdk_window_get_type ()))))))->impl)), ((cdk_window_impl_x11_get_type
()))))))->xid)
;
869}
870
871#ifdef G_ENABLE_DEBUG1
872static void
873print_target_list (GList *targets)
874{
875 while (targets)
876 {
877 gchar *name = cdk_atom_name (CDK_POINTER_TO_ATOM (targets->data)((CdkAtom)(targets->data)));
878 g_message ("\t%s", name);
879 g_free (name);
880 targets = targets->next;
881 }
882}
883#endif /* G_ENABLE_DEBUG */
884
885/*************************************************************
886 ***************************** XDND **************************
887 *************************************************************/
888
889/* Utility functions */
890
891static struct {
892 const gchar *name;
893 CdkAtom atom;
894 CdkDragAction action;
895} xdnd_actions_table[] = {
896 { "XdndActionCopy", None0L, CDK_ACTION_COPY },
897 { "XdndActionMove", None0L, CDK_ACTION_MOVE },
898 { "XdndActionLink", None0L, CDK_ACTION_LINK },
899 { "XdndActionAsk", None0L, CDK_ACTION_ASK },
900 { "XdndActionPrivate", None0L, CDK_ACTION_COPY },
901 };
902
903static const gint xdnd_n_actions = G_N_ELEMENTS (xdnd_actions_table)(sizeof (xdnd_actions_table) / sizeof ((xdnd_actions_table)[0
]))
;
904static gboolean xdnd_actions_initialized = FALSE(0);
905
906static void
907xdnd_initialize_actions (void)
908{
909 gint i;
910
911 xdnd_actions_initialized = TRUE(!(0));
912 for (i = 0; i < xdnd_n_actions; i++)
913 xdnd_actions_table[i].atom = cdk_atom_intern_static_string (xdnd_actions_table[i].name);
914}
915
916static CdkDragAction
917xdnd_action_from_atom (CdkDisplay *display,
918 Atom xatom)
919{
920 CdkAtom atom;
921 gint i;
922
923 if (xatom == None0L)
924 return 0;
925
926 atom = cdk_x11_xatom_to_atom_for_display (display, xatom);
927
928 if (!xdnd_actions_initialized)
929 xdnd_initialize_actions();
930
931 for (i = 0; i < xdnd_n_actions; i++)
932 if (atom == xdnd_actions_table[i].atom)
933 return xdnd_actions_table[i].action;
934
935 return 0;
936}
937
938static Atom
939xdnd_action_to_atom (CdkDisplay *display,
940 CdkDragAction action)
941{
942 gint i;
943
944 if (!xdnd_actions_initialized)
945 xdnd_initialize_actions();
946
947 for (i = 0; i < xdnd_n_actions; i++)
948 if (action == xdnd_actions_table[i].action)
949 return cdk_x11_atom_to_xatom_for_display (display, xdnd_actions_table[i].atom);
950
951 return None0L;
952}
953
954/* Source side */
955
956static CdkFilterReturn
957xdnd_status_filter (CdkXEvent *xev,
958 CdkEvent *event,
959 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
960{
961 CdkDisplay *display;
962 XEvent *xevent = (XEvent *)xev;
963 guint32 dest_window = xevent->xclient.data.l[0];
964 guint32 flags = xevent->xclient.data.l[1];
965 Atom action = xevent->xclient.data.l[4];
966 CdkDragContext *context;
967
968 if (!event->any.window ||
969 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
970 return CDK_FILTER_CONTINUE; /* Not for us */
971
972 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndStatus: dest_window: %#x action: %ld", dest_window, action
); }; } while (0)
973 g_message ("XdndStatus: dest_window: %#x action: %ld",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndStatus: dest_window: %#x action: %ld", dest_window, action
); }; } while (0)
974 dest_window, action))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndStatus: dest_window: %#x action: %ld", dest_window, action
); }; } while (0)
;
975
976 display = cdk_window_get_display (event->any.window);
977 context = cdk_drag_context_find (display, TRUE(!(0)), xevent->xclient.window, dest_window);
978
979 if (context)
980 {
981 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
982 if (context_x11->drag_status == CDK_DRAG_STATUS_MOTION_WAIT)
983 context_x11->drag_status = CDK_DRAG_STATUS_DRAG;
984
985 event->dnd.send_event = FALSE(0);
986 event->dnd.type = CDK_DRAG_STATUS;
987 event->dnd.context = context;
988 cdk_event_set_device (event, cdk_drag_context_get_device (context));
989 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
990
991 event->dnd.time = CDK_CURRENT_TIME0L; /* FIXME? */
992 if (!(action != 0) != !(flags & 1))
993 {
994 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Received status event with flags not corresponding to action!"
); }; } while (0)
995 g_warning ("Received status event with flags not corresponding to action!"))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Received status event with flags not corresponding to action!"
); }; } while (0)
;
996 action = 0;
997 }
998
999 context->action = xdnd_action_from_atom (display, action);
1000
1001 return CDK_FILTER_TRANSLATE;
1002 }
1003
1004 return CDK_FILTER_REMOVE;
1005}
1006
1007static CdkFilterReturn
1008xdnd_finished_filter (CdkXEvent *xev,
1009 CdkEvent *event,
1010 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1011{
1012 CdkDisplay *display;
1013 XEvent *xevent = (XEvent *)xev;
1014 guint32 dest_window = xevent->xclient.data.l[0];
1015 CdkDragContext *context;
1016
1017 if (!event->any.window ||
1018 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
1019 return CDK_FILTER_CONTINUE; /* Not for us */
1020
1021 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndFinished: dest_window: %#x", dest_window); }; } while (0
)
1022 g_message ("XdndFinished: dest_window: %#x", dest_window))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndFinished: dest_window: %#x", dest_window); }; } while (0
)
;
1023
1024 display = cdk_window_get_display (event->any.window);
1025 context = cdk_drag_context_find (display, TRUE(!(0)), xevent->xclient.window, dest_window);
1026
1027 if (context)
1028 {
1029 CdkX11DragContext *context_x11;
1030
1031 context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
1032 if (context_x11->version == 5)
1033 context_x11->drop_failed = xevent->xclient.data.l[1] == 0;
1034
1035 event->dnd.type = CDK_DROP_FINISHED;
1036 event->dnd.context = context;
1037 cdk_event_set_device (event, cdk_drag_context_get_device (context));
1038 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1039
1040 event->dnd.time = CDK_CURRENT_TIME0L; /* FIXME? */
1041
1042 return CDK_FILTER_TRANSLATE;
1043 }
1044
1045 return CDK_FILTER_REMOVE;
1046}
1047
1048static void
1049xdnd_set_targets (CdkX11DragContext *context_x11)
1050{
1051 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1052 Atom *atomlist;
1053 GList *tmp_list = context->targets;
1054 gint i;
1055 gint n_atoms = g_list_length (context->targets);
1056 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1057
1058 atomlist = g_new (Atom, n_atoms)((Atom *) g_malloc_n ((n_atoms), sizeof (Atom)));
1059 i = 0;
1060 while (tmp_list)
1061 {
1062 atomlist[i] = cdk_x11_atom_to_xatom_for_display (display, CDK_POINTER_TO_ATOM (tmp_list->data)((CdkAtom)(tmp_list->data)));
1063 tmp_list = tmp_list->next;
1064 i++;
1065 }
1066
1067 XChangeProperty (CDK_WINDOW_XDISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
1068 CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
,
1069 cdk_x11_get_xatom_by_name_for_display (display, "XdndTypeList"),
1070 XA_ATOM((Atom) 4), 32, PropModeReplace0,
1071 (guchar *)atomlist, n_atoms);
1072
1073 g_free (atomlist);
1074
1075 context_x11->xdnd_targets_set = 1;
1076}
1077
1078static void
1079xdnd_set_actions (CdkX11DragContext *context_x11)
1080{
1081 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1082 Atom *atomlist;
1083 gint i;
1084 gint n_atoms;
1085 guint actions;
1086 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1087
1088 if (!xdnd_actions_initialized)
1089 xdnd_initialize_actions();
1090
1091 actions = context->actions;
1092 n_atoms = 0;
1093 for (i = 0; i < xdnd_n_actions; i++)
1094 {
1095 if (actions & xdnd_actions_table[i].action)
1096 {
1097 actions &= ~xdnd_actions_table[i].action;
1098 n_atoms++;
1099 }
1100 }
1101
1102 atomlist = g_new (Atom, n_atoms)((Atom *) g_malloc_n ((n_atoms), sizeof (Atom)));
1103
1104 actions = context->actions;
1105 n_atoms = 0;
1106 for (i = 0; i < xdnd_n_actions; i++)
1107 {
1108 if (actions & xdnd_actions_table[i].action)
1109 {
1110 actions &= ~xdnd_actions_table[i].action;
1111 atomlist[n_atoms] = cdk_x11_atom_to_xatom_for_display (display, xdnd_actions_table[i].atom);
1112 n_atoms++;
1113 }
1114 }
1115
1116 XChangeProperty (CDK_WINDOW_XDISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
1117 CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
,
1118 cdk_x11_get_xatom_by_name_for_display (display, "XdndActionList"),
1119 XA_ATOM((Atom) 4), 32, PropModeReplace0,
1120 (guchar *)atomlist, n_atoms);
1121
1122 g_free (atomlist);
1123
1124 context_x11->xdnd_actions_set = TRUE(!(0));
1125 context_x11->xdnd_actions = context->actions;
1126}
1127
1128static void
1129send_client_message_async_cb (Window window,
1130 gboolean success,
1131 gpointer data)
1132{
1133 CdkDragContext *context = data;
1134 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Got async callback for #%lx, success = %d", window, success)
; }; } while (0)
1135 g_message ("Got async callback for #%lx, success = %d",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Got async callback for #%lx, success = %d", window, success)
; }; } while (0)
1136 window, success))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Got async callback for #%lx, success = %d", window, success)
; }; } while (0)
;
1137
1138 /* On failure, we immediately continue with the protocol
1139 * so we don't end up blocking for a timeout
1140 */
1141 if (!success &&
1142 context->dest_window &&
1143 window == CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
)
1144 {
1145 CdkEvent *temp_event;
1146 CdkX11DragContext *context_x11 = data;
1147
1148 g_object_unref (context->dest_window);
1149 context->dest_window = NULL((void*)0);
1150 context->action = 0;
1151
1152 context_x11->drag_status = CDK_DRAG_STATUS_DRAG;
1153
1154 temp_event = cdk_event_new (CDK_DRAG_STATUS);
1155 temp_event->dnd.window = g_object_ref (context->source_window)((__typeof__ (context->source_window)) (g_object_ref) (context
->source_window))
;
1156 temp_event->dnd.send_event = TRUE(!(0));
1157 temp_event->dnd.context = g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1158 temp_event->dnd.time = CDK_CURRENT_TIME0L;
1159 cdk_event_set_device (temp_event, cdk_drag_context_get_device (context));
1160
1161 cdk_event_put (temp_event);
1162
1163 cdk_event_free (temp_event);
1164 }
1165
1166 g_object_unref (context);
1167}
1168
1169
1170static CdkDisplay *
1171cdk_drag_context_get_display (CdkDragContext *context)
1172{
1173 if (context->source_window)
1174 return CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1175 else if (context->dest_window)
1176 return CDK_WINDOW_DISPLAY (context->dest_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->dest_window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1177
1178 g_assert_not_reached ()do { g_assertion_message_expr ("Cdk", "cdkdnd-x11.c", 1178, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
1179 return NULL((void*)0);
1180}
1181
1182static void
1183send_client_message_async (CdkDragContext *context,
1184 Window window,
1185 gboolean propagate,
1186 glong event_mask,
1187 XClientMessageEvent *event_send)
1188{
1189 CdkDisplay *display = cdk_drag_context_get_display (context);
1190
1191 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1192
1193 _cdk_x11_send_client_message_async (display, window,
1194 propagate, event_mask, event_send,
1195 send_client_message_async_cb, context);
1196}
1197
1198static gboolean
1199xdnd_send_xevent (CdkX11DragContext *context_x11,
1200 CdkWindow *window,
1201 gboolean propagate,
1202 XEvent *event_send)
1203{
1204 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1205 CdkDisplay *display = cdk_drag_context_get_display (context);
1206 Window xwindow;
1207 glong event_mask;
1208
1209 g_assert (event_send->xany.type == ClientMessage)do { if (event_send->xany.type == 33) ; else g_assertion_message_expr
("Cdk", "cdkdnd-x11.c", 1209, ((const char*) (__func__)), "event_send->xany.type == ClientMessage"
); } while (0)
;
1210
1211 /* We short-circuit messages to ourselves */
1212 if (cdk_window_get_window_type (window) != CDK_WINDOW_FOREIGN)
1213 {
1214 gint i;
1215
1216 for (i = 0; i < G_N_ELEMENTS (xdnd_filters)(sizeof (xdnd_filters) / sizeof ((xdnd_filters)[0])); i++)
1217 {
1218 if (cdk_x11_get_xatom_by_name_for_display (display, xdnd_filters[i].atom_name) ==
1219 event_send->xclient.message_type)
1220 {
1221 CdkEvent *temp_event;
1222
1223 temp_event = cdk_event_new (CDK_NOTHING);
1224 temp_event->any.window = g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
1225
1226 if ((*xdnd_filters[i].func) (event_send, temp_event, NULL((void*)0)) == CDK_FILTER_TRANSLATE)
1227 cdk_event_put (temp_event);
1228
1229 cdk_event_free (temp_event);
1230
1231 return TRUE(!(0));
1232 }
1233 }
1234 }
1235
1236 xwindow = CDK_WINDOW_XID (window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((cdk_window_get_type ()))))))
->impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
;
1237
1238 if (_cdk_x11_display_is_root_window (display, xwindow))
1239 event_mask = ButtonPressMask(1L<<2);
1240 else
1241 event_mask = 0;
1242
1243 send_client_message_async (context, xwindow, propagate, event_mask,
1244 &event_send->xclient);
1245
1246 return TRUE(!(0));
1247}
1248
1249static void
1250xdnd_send_enter (CdkX11DragContext *context_x11)
1251{
1252 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1253 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->dest_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->dest_window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1254 XEvent xev;
1255
1256 xev.xclient.type = ClientMessage33;
1257 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndEnter");
1258 xev.xclient.format = 32;
1259 xev.xclient.window = context_x11->drop_xid
14
Assuming field 'drop_xid' is not equal to 0
15
'?' condition is true
1260 ? context_x11->drop_xid
1261 : CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1262 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1263 xev.xclient.data.l[1] = (context_x11->version << 24); /* version */
1264 xev.xclient.data.l[2] = 0;
1265 xev.xclient.data.l[3] = 0;
1266 xev.xclient.data.l[4] = 0;
1267
1268 CDK_NOTE(DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Sending enter source window %#lx XDND protocol version %d\n"
, (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid), context_x11->version); }; } while (0)
16
Assuming the condition is false
17
Taking false branch
18
Loop condition is false. Exiting loop
1269 g_message ("Sending enter source window %#lx XDND protocol version %d\n",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Sending enter source window %#lx XDND protocol version %d\n"
, (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid), context_x11->version); }; } while (0)
1270 CDK_WINDOW_XID (context->source_window), context_x11->version))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Sending enter source window %#lx XDND protocol version %d\n"
, (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid), context_x11->version); }; } while (0)
;
1271 if (g_list_length (context->targets) > 3)
19
Assuming the condition is false
20
Taking false branch
1272 {
1273 if (!context_x11->xdnd_targets_set)
1274 xdnd_set_targets (context_x11);
1275 xev.xclient.data.l[1] |= 1;
1276 }
1277 else
1278 {
1279 GList *tmp_list = context->targets;
1280 gint i = 2;
1281
1282 while (tmp_list)
21
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
23
Loop condition is true. Entering loop body
24
Loop condition is true. Entering loop body
1283 {
1284 xev.xclient.data.l[i] = cdk_x11_atom_to_xatom_for_display (display,
25
Out of bound memory access (access exceeds upper limit of memory block)
1285 CDK_POINTER_TO_ATOM (tmp_list->data)((CdkAtom)(tmp_list->data)));
1286 tmp_list = tmp_list->next;
1287 i++;
1288 }
1289 }
1290
1291 if (!xdnd_send_xevent (context_x11, context->dest_window, FALSE(0), &xev))
1292 {
1293 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1294 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1295 CDK_WINDOW_XID (context->dest_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
1296 g_object_unref (context->dest_window);
1297 context->dest_window = NULL((void*)0);
1298 }
1299}
1300
1301static void
1302xdnd_send_leave (CdkX11DragContext *context_x11)
1303{
1304 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1305 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1306 XEvent xev;
1307
1308 xev.xclient.type = ClientMessage33;
1309 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndLeave");
1310 xev.xclient.format = 32;
1311 xev.xclient.window = context_x11->drop_xid
1312 ? context_x11->drop_xid
1313 : CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1314 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1315 xev.xclient.data.l[1] = 0;
1316 xev.xclient.data.l[2] = 0;
1317 xev.xclient.data.l[3] = 0;
1318 xev.xclient.data.l[4] = 0;
1319
1320 if (!xdnd_send_xevent (context_x11, context->dest_window, FALSE(0), &xev))
1321 {
1322 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1323 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1324 CDK_WINDOW_XID (context->dest_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
1325 g_object_unref (context->dest_window);
1326 context->dest_window = NULL((void*)0);
1327 }
1328}
1329
1330static void
1331xdnd_send_drop (CdkX11DragContext *context_x11,
1332 guint32 time)
1333{
1334 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1335 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1336 XEvent xev;
1337
1338 xev.xclient.type = ClientMessage33;
1339 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndDrop");
1340 xev.xclient.format = 32;
1341 xev.xclient.window = context_x11->drop_xid
1342 ? context_x11->drop_xid
1343 : CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1344 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1345 xev.xclient.data.l[1] = 0;
1346 xev.xclient.data.l[2] = time;
1347 xev.xclient.data.l[3] = 0;
1348 xev.xclient.data.l[4] = 0;
1349
1350 if (!xdnd_send_xevent (context_x11, context->dest_window, FALSE(0), &xev))
1351 {
1352 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1353 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1354 CDK_WINDOW_XID (context->dest_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
1355 g_object_unref (context->dest_window);
1356 context->dest_window = NULL((void*)0);
1357 }
1358}
1359
1360static void
1361xdnd_send_motion (CdkX11DragContext *context_x11,
1362 gint x_root,
1363 gint y_root,
1364 CdkDragAction action,
1365 guint32 time)
1366{
1367 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1368 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1369 XEvent xev;
1370
1371 xev.xclient.type = ClientMessage33;
1372 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndPosition");
1373 xev.xclient.format = 32;
1374 xev.xclient.window = context_x11->drop_xid
1375 ? context_x11->drop_xid
1376 : CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1377 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
1378 xev.xclient.data.l[1] = 0;
1379 xev.xclient.data.l[2] = (x_root << 16) | y_root;
1380 xev.xclient.data.l[3] = time;
1381 xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
1382
1383 if (!xdnd_send_xevent (context_x11, context->dest_window, FALSE(0), &xev))
1384 {
1385 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1386 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
1387 CDK_WINDOW_XID (context->dest_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
1388 g_object_unref (context->dest_window);
1389 context->dest_window = NULL((void*)0);
1390 }
1391 context_x11->drag_status = CDK_DRAG_STATUS_MOTION_WAIT;
1392}
1393
1394static guint32
1395xdnd_check_dest (CdkDisplay *display,
1396 Window win,
1397 guint *xdnd_version)
1398{
1399 gboolean retval = FALSE(0);
1400 Atom type = None0L;
1401 int format;
1402 unsigned long nitems, after;
1403 guchar *data;
1404 Window proxy;
1405 Atom xdnd_proxy_atom = cdk_x11_get_xatom_by_name_for_display (display, "XdndProxy");
1406 Atom xdnd_aware_atom = cdk_x11_get_xatom_by_name_for_display (display, "XdndAware");
1407
1408 proxy = None0L;
1409
1410 cdk_x11_display_error_trap_push (display);
1411 if (XGetWindowProperty (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
, win,
1412 xdnd_proxy_atom, 0,
1413 1, False0, AnyPropertyType0L,
1414 &type, &format, &nitems, &after,
1415 &data) == Success0)
1416 {
1417 if (type != None0L)
1418 {
1419 Window *proxy_data;
1420
1421 proxy_data = (Window *)data;
1422
1423 if ((format == 32) && (nitems == 1))
1424 {
1425 proxy = *proxy_data;
1426 }
1427 else
1428 {
1429 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Invalid XdndProxy property on window %ld", win); }; } while (
0)
1430 g_warning ("Invalid XdndProxy property on window %ld", win))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Invalid XdndProxy property on window %ld", win); }; } while (
0)
;
1431 }
1432
1433 XFree (proxy_data);
1434 }
1435
1436 if ((XGetWindowProperty (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
, proxy ? proxy : win,
1437 xdnd_aware_atom, 0,
1438 1, False0, AnyPropertyType0L,
1439 &type, &format, &nitems, &after,
1440 &data) == Success0) &&
1441 type != None0L)
1442 {
1443 Atom *version;
1444
1445 version = (Atom *)data;
1446
1447 if ((format == 32) && (nitems == 1))
1448 {
1449 if (*version >= 3)
1450 retval = TRUE(!(0));
1451 if (xdnd_version)
1452 *xdnd_version = *version;
1453 }
1454 else
1455 {
1456 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Invalid XdndAware property on window %ld", win); }; } while (
0)
1457 g_warning ("Invalid XdndAware property on window %ld", win))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_warning (
"Invalid XdndAware property on window %ld", win); }; } while (
0)
;
1458 }
1459
1460 XFree (version);
1461 }
1462 }
1463
1464 cdk_x11_display_error_trap_pop_ignored (display);
1465
1466 return retval ? (proxy ? proxy : win) : None0L;
1467}
1468
1469/* Target side */
1470
1471static void
1472xdnd_read_actions (CdkX11DragContext *context_x11)
1473{
1474 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1475 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
1476 Atom type;
1477 int format;
1478 gulong nitems, after;
1479 guchar *data;
1480 Atom *atoms;
1481 gint i;
1482
1483 context_x11->xdnd_have_actions = FALSE(0);
1484
1485 if (cdk_window_get_window_type (context->source_window) == CDK_WINDOW_FOREIGN)
1486 {
1487 /* Get the XdndActionList, if set */
1488
1489 cdk_x11_display_error_trap_push (display);
1490 if (XGetWindowProperty (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
,
1491 CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
,
1492 cdk_x11_get_xatom_by_name_for_display (display, "XdndActionList"),
1493 0, 65536,
1494 False0, XA_ATOM((Atom) 4), &type, &format, &nitems,
1495 &after, &data) == Success0 &&
1496 type == XA_ATOM((Atom) 4))
1497 {
1498 atoms = (Atom *)data;
1499
1500 context->actions = 0;
1501
1502 for (i = 0; i < nitems; i++)
1503 context->actions |= xdnd_action_from_atom (display, atoms[i]);
1504
1505 context_x11->xdnd_have_actions = TRUE(!(0));
1506
1507#ifdef G_ENABLE_DEBUG1
1508 if (CDK_DEBUG_CHECK (DND)(_cdk_debug_flags & CDK_DEBUG_DND))
1509 {
1510 GString *action_str = g_string_new (NULL((void*)0));
1511 if (context->actions & CDK_ACTION_MOVE)
1512 g_string_append(action_str, "MOVE ")(__builtin_constant_p ("MOVE ") ? __extension__ ({ const char
* const __val = ("MOVE "); g_string_append_len_inline (action_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (action_str
, "MOVE ", (gssize) -1))
;
1513 if (context->actions & CDK_ACTION_COPY)
1514 g_string_append(action_str, "COPY ")(__builtin_constant_p ("COPY ") ? __extension__ ({ const char
* const __val = ("COPY "); g_string_append_len_inline (action_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (action_str
, "COPY ", (gssize) -1))
;
1515 if (context->actions & CDK_ACTION_LINK)
1516 g_string_append(action_str, "LINK ")(__builtin_constant_p ("LINK ") ? __extension__ ({ const char
* const __val = ("LINK "); g_string_append_len_inline (action_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (action_str
, "LINK ", (gssize) -1))
;
1517 if (context->actions & CDK_ACTION_ASK)
1518 g_string_append(action_str, "ASK ")(__builtin_constant_p ("ASK ") ? __extension__ ({ const char *
const __val = ("ASK "); g_string_append_len_inline (action_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (action_str
, "ASK ", (gssize) -1))
;
1519
1520 g_message("Xdnd actions = %s", action_str->str);
1521 g_string_free (action_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(action_str), ((!(0)))) : g_string_free_and_steal (action_str
)) : (g_string_free) ((action_str), ((!(0)))))
;
1522 }
1523#endif /* G_ENABLE_DEBUG */
1524
1525 }
1526
1527 if (data)
1528 XFree (data);
1529
1530 cdk_x11_display_error_trap_pop_ignored (display);
1531 }
1532 else
1533 {
1534 /* Local drag
1535 */
1536 CdkDragContext *source_context;
1537
1538 source_context = cdk_drag_context_find (display, TRUE(!(0)),
1539 CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
,
1540 CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
);
1541
1542 if (source_context)
1543 {
1544 context->actions = source_context->actions;
1545 context_x11->xdnd_have_actions = TRUE(!(0));
1546 }
1547 }
1548}
1549
1550/* We have to make sure that the XdndActionList we keep internally
1551 * is up to date with the XdndActionList on the source window
1552 * because we get no notification, because Xdnd wasn’t meant
1553 * to continually send actions. So we select on PropertyChangeMask
1554 * and add this filter.
1555 */
1556static CdkFilterReturn
1557xdnd_source_window_filter (CdkXEvent *xev,
1558 CdkEvent *event,
1559 gpointer cb_data)
1560{
1561 XEvent *xevent = (XEvent *)xev;
1562 CdkX11DragContext *context_x11 = cb_data;
1563 CdkDisplay *display = CDK_WINDOW_DISPLAY(event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1564
1565 if ((xevent->xany.type == PropertyNotify28) &&
1566 (xevent->xproperty.atom == cdk_x11_get_xatom_by_name_for_display (display, "XdndActionList")))
1567 {
1568 xdnd_read_actions (context_x11);
1569
1570 return CDK_FILTER_REMOVE;
1571 }
1572
1573 return CDK_FILTER_CONTINUE;
1574}
1575
1576static void
1577xdnd_manage_source_filter (CdkDragContext *context,
1578 CdkWindow *window,
1579 gboolean add_filter)
1580{
1581 if (!CDK_WINDOW_DESTROYED (window)(((CdkWindow *)(window))->destroyed) &&
1582 cdk_window_get_window_type (window) == CDK_WINDOW_FOREIGN)
1583 {
1584 cdk_x11_display_error_trap_push (CDK_WINDOW_DISPLAY (window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (window)))), ((cdk_x11_screen_get_type
()))))))->display)
);
1585
1586 if (add_filter)
1587 {
1588 cdk_window_set_events (window,
1589 cdk_window_get_events (window) |
1590 CDK_PROPERTY_CHANGE_MASK);
1591 cdk_window_add_filter (window, xdnd_source_window_filter, context);
1592 }
1593 else
1594 {
1595 cdk_window_remove_filter (window,
1596 xdnd_source_window_filter,
1597 context);
1598 /* Should we remove the CDK_PROPERTY_NOTIFY mask?
1599 * but we might want it for other reasons. (Like
1600 * INCR selection transactions).
1601 */
1602 }
1603
1604 cdk_x11_display_error_trap_pop_ignored (CDK_WINDOW_DISPLAY (window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (window)))), ((cdk_x11_screen_get_type
()))))))->display)
);
1605 }
1606}
1607
1608static void
1609base_precache_atoms (CdkDisplay *display)
1610{
1611 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1612
1613 if (!display_x11->base_dnd_atoms_precached)
1614 {
1615 static const char *const precache_atoms[] = {
1616 "WM_STATE",
1617 "XdndAware",
1618 "XdndProxy"
1619 };
1620
1621 _cdk_x11_precache_atoms (display,
1622 precache_atoms, G_N_ELEMENTS (precache_atoms)(sizeof (precache_atoms) / sizeof ((precache_atoms)[0])));
1623
1624 display_x11->base_dnd_atoms_precached = TRUE(!(0));
1625 }
1626}
1627
1628static void
1629xdnd_precache_atoms (CdkDisplay *display)
1630{
1631 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1632
1633 if (!display_x11->xdnd_atoms_precached)
1634 {
1635 static const gchar *const precache_atoms[] = {
1636 "XdndActionAsk",
1637 "XdndActionCopy",
1638 "XdndActionLink",
1639 "XdndActionList",
1640 "XdndActionMove",
1641 "XdndActionPrivate",
1642 "XdndDrop",
1643 "XdndEnter",
1644 "XdndFinished",
1645 "XdndLeave",
1646 "XdndPosition",
1647 "XdndSelection",
1648 "XdndStatus",
1649 "XdndTypeList"
1650 };
1651
1652 _cdk_x11_precache_atoms (display,
1653 precache_atoms, G_N_ELEMENTS (precache_atoms)(sizeof (precache_atoms) / sizeof ((precache_atoms)[0])));
1654
1655 display_x11->xdnd_atoms_precached = TRUE(!(0));
1656 }
1657}
1658
1659static CdkFilterReturn
1660xdnd_enter_filter (CdkXEvent *xev,
1661 CdkEvent *event,
1662 gpointer cb_data G_GNUC_UNUSED__attribute__ ((__unused__)))
1663{
1664 CdkDisplay *display;
1665 CdkX11Display *display_x11;
1666 XEvent *xevent = (XEvent *)xev;
1667 CdkDragContext *context;
1668 CdkX11DragContext *context_x11;
1669 CdkSeat *seat;
1670 gint i;
1671 Atom type;
1672 int format;
1673 gulong nitems, after;
1674 guchar *data;
1675 Atom *atoms;
1676 guint32 source_window;
1677 gboolean get_types;
1678 gint version;
1679
1680 if (!event->any.window ||
1681 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
1682 return CDK_FILTER_CONTINUE; /* Not for us */
1683
1684 source_window = xevent->xclient.data.l[0];
1685 get_types = ((xevent->xclient.data.l[1] & 1) != 0);
1686 version = (xevent->xclient.data.l[1] & 0xff000000) >> 24;
1687
1688 display = CDK_WINDOW_DISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1689 display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1690
1691 xdnd_precache_atoms (display);
1692
1693 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndEnter: source_window: %#x, version: %#x", source_window,
version); }; } while (0)
1694 g_message ("XdndEnter: source_window: %#x, version: %#x",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndEnter: source_window: %#x, version: %#x", source_window,
version); }; } while (0)
1695 source_window, version))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndEnter: source_window: %#x, version: %#x", source_window,
version); }; } while (0)
;
1696
1697 if (version < 3)
1698 {
1699 /* Old source ignore */
1700 CDK_NOTE (DND, g_message ("Ignored old XdndEnter message"))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Ignored old XdndEnter message"); }; } while (0)
;
1701 return CDK_FILTER_REMOVE;
1702 }
1703
1704 if (display_x11->current_dest_drag != NULL((void*)0))
1705 {
1706 g_object_unref (display_x11->current_dest_drag);
1707 display_x11->current_dest_drag = NULL((void*)0);
1708 }
1709
1710 context_x11 = (CdkX11DragContext *)g_object_new (CDK_TYPE_X11_DRAG_CONTEXT(cdk_x11_drag_context_get_type ()), NULL((void*)0));
1711 context = (CdkDragContext *)context_x11;
1712
1713 context->display = display;
1714 context->protocol = CDK_DRAG_PROTO_XDND;
1715 context_x11->version = version;
1716
1717 /* FIXME: Should extend DnD protocol to have device info */
1718 seat = cdk_display_get_default_seat (display);
1719 cdk_drag_context_set_device (context, cdk_seat_get_pointer (seat));
1720
1721 context->source_window = cdk_x11_window_foreign_new_for_display (display, source_window);
1722 if (!context->source_window)
1723 {
1724 g_object_unref (context);
1725 return CDK_FILTER_REMOVE;
1726 }
1727 context->dest_window = event->any.window;
1728 g_object_ref (context->dest_window)((__typeof__ (context->dest_window)) (g_object_ref) (context
->dest_window))
;
1729
1730 context->targets = NULL((void*)0);
1731 if (get_types)
1732 {
1733 cdk_x11_display_error_trap_push (display);
1734 XGetWindowProperty (CDK_WINDOW_XDISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->xdisplay)
,
1735 source_window,
1736 cdk_x11_get_xatom_by_name_for_display (display, "XdndTypeList"),
1737 0, 65536,
1738 False0, XA_ATOM((Atom) 4), &type, &format, &nitems,
1739 &after, &data);
1740
1741 if (cdk_x11_display_error_trap_pop (display) || (format != 32) || (type != XA_ATOM((Atom) 4)))
1742 {
1743 g_object_unref (context);
1744
1745 if (data)
1746 XFree (data);
1747
1748 return CDK_FILTER_REMOVE;
1749 }
1750
1751 atoms = (Atom *)data;
1752
1753 for (i = 0; i < nitems; i++)
1754 context->targets =
1755 g_list_append (context->targets,
1756 CDK_ATOM_TO_POINTER (cdk_x11_xatom_to_atom_for_display (display,(cdk_x11_xatom_to_atom_for_display (display, atoms[i]))
1757 atoms[i]))(cdk_x11_xatom_to_atom_for_display (display, atoms[i])));
1758
1759 XFree (atoms);
1760 }
1761 else
1762 {
1763 for (i = 0; i < 3; i++)
1764 if (xevent->xclient.data.l[2 + i])
1765 context->targets =
1766 g_list_append (context->targets,
1767 CDK_ATOM_TO_POINTER (cdk_x11_xatom_to_atom_for_display (display,(cdk_x11_xatom_to_atom_for_display (display, xevent->xclient
.data.l[2 + i]))
1768 xevent->xclient.data.l[2 + i]))(cdk_x11_xatom_to_atom_for_display (display, xevent->xclient
.data.l[2 + i]))
);
1769 }
1770
1771#ifdef G_ENABLE_DEBUG1
1772 if (CDK_DEBUG_CHECK (DND)(_cdk_debug_flags & CDK_DEBUG_DND))
1773 print_target_list (context->targets);
1774#endif /* G_ENABLE_DEBUG */
1775
1776 xdnd_manage_source_filter (context, context->source_window, TRUE(!(0)));
1777 xdnd_read_actions (context_x11);
1778
1779 event->dnd.type = CDK_DRAG_ENTER;
1780 event->dnd.context = context;
1781 cdk_event_set_device (event, cdk_drag_context_get_device (context));
1782 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1783
1784 display_x11->current_dest_drag = context;
1785
1786 return CDK_FILTER_TRANSLATE;
1787}
1788
1789static CdkFilterReturn
1790xdnd_leave_filter (CdkXEvent *xev,
1791 CdkEvent *event,
1792 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1793{
1794 XEvent *xevent = (XEvent *)xev;
1795 guint32 source_window = xevent->xclient.data.l[0];
1796 CdkDisplay *display;
1797 CdkX11Display *display_x11;
1798
1799 if (!event->any.window ||
1800 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
1801 return CDK_FILTER_CONTINUE; /* Not for us */
1802
1803 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndLeave: source_window: %#x", source_window); }; } while (
0)
1804 g_message ("XdndLeave: source_window: %#x",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndLeave: source_window: %#x", source_window); }; } while (
0)
1805 source_window))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndLeave: source_window: %#x", source_window); }; } while (
0)
;
1806
1807 display = CDK_WINDOW_DISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1808 display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1809
1810 xdnd_precache_atoms (display);
1811
1812 if ((display_x11->current_dest_drag != NULL((void*)0)) &&
1813 (display_x11->current_dest_drag->protocol == CDK_DRAG_PROTO_XDND) &&
1814 (CDK_WINDOW_XID (display_x11->current_dest_drag->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((display_x11->current_dest_drag->source_window
)), ((cdk_window_get_type ()))))))->impl)), ((cdk_window_impl_x11_get_type
()))))))->xid)
== source_window))
1815 {
1816 event->dnd.type = CDK_DRAG_LEAVE;
1817 /* Pass ownership of context to the event */
1818 event->dnd.context = display_x11->current_dest_drag;
1819 cdk_event_set_device (event, cdk_drag_context_get_device (event->dnd.context));
1820
1821 display_x11->current_dest_drag = NULL((void*)0);
1822
1823 return CDK_FILTER_TRANSLATE;
1824 }
1825 else
1826 return CDK_FILTER_REMOVE;
1827}
1828
1829static CdkFilterReturn
1830xdnd_position_filter (CdkXEvent *xev,
1831 CdkEvent *event,
1832 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1833{
1834 XEvent *xevent = (XEvent *)xev;
1835 guint32 source_window = xevent->xclient.data.l[0];
1836 gint16 x_root = xevent->xclient.data.l[2] >> 16;
1837 gint16 y_root = xevent->xclient.data.l[2] & 0xffff;
1838 guint32 time = xevent->xclient.data.l[3];
1839 Atom action = xevent->xclient.data.l[4];
1840 CdkDisplay *display;
1841 CdkX11Display *display_x11;
1842 CdkDragContext *context;
1843
1844 if (!event->any.window ||
1845 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
1846 return CDK_FILTER_CONTINUE; /* Not for us */
1847
1848 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndPosition: source_window: %#x position: (%d, %d) time: %d action: %ld"
, source_window, x_root, y_root, time, action); }; } while (0
)
1849 g_message ("XdndPosition: source_window: %#x position: (%d, %d) time: %d action: %ld",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndPosition: source_window: %#x position: (%d, %d) time: %d action: %ld"
, source_window, x_root, y_root, time, action); }; } while (0
)
1850 source_window, x_root, y_root, time, action))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndPosition: source_window: %#x position: (%d, %d) time: %d action: %ld"
, source_window, x_root, y_root, time, action); }; } while (0
)
;
1851
1852 display = CDK_WINDOW_DISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1853 display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1854
1855 xdnd_precache_atoms (display);
1856
1857 context = display_x11->current_dest_drag;
1858
1859 if ((context != NULL((void*)0)) &&
1860 (context->protocol == CDK_DRAG_PROTO_XDND) &&
1861 (CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
== source_window))
1862 {
1863 CdkWindowImplX11 *impl;
1864 CdkX11DragContext *context_x11;
1865
1866 impl = CDK_WINDOW_IMPL_X11 (event->any.window->impl)((((CdkWindowImplX11*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((event->any.window->impl)), ((cdk_window_impl_x11_get_type
()))))))
;
1867
1868 context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
1869
1870 event->dnd.type = CDK_DRAG_MOTION;
1871 event->dnd.context = context;
1872 cdk_event_set_device (event, cdk_drag_context_get_device (context));
1873 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1874
1875 event->dnd.time = time;
1876
1877 context->suggested_action = xdnd_action_from_atom (display, action);
1878
1879 if (!context_x11->xdnd_have_actions)
1880 context->actions = context->suggested_action;
1881
1882 event->dnd.x_root = x_root / impl->window_scale;
1883 event->dnd.y_root = y_root / impl->window_scale;
1884
1885 context_x11->last_x = x_root / impl->window_scale;
1886 context_x11->last_y = y_root / impl->window_scale;
1887
1888 return CDK_FILTER_TRANSLATE;
1889 }
1890
1891 return CDK_FILTER_REMOVE;
1892}
1893
1894static CdkFilterReturn
1895xdnd_drop_filter (CdkXEvent *xev,
1896 CdkEvent *event,
1897 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1898{
1899 XEvent *xevent = (XEvent *)xev;
1900 guint32 source_window = xevent->xclient.data.l[0];
1901 guint32 time = xevent->xclient.data.l[2];
1902 CdkDisplay *display;
1903 CdkX11Display *display_x11;
1904 CdkDragContext *context;
1905 CdkX11DragContext *context_x11;
1906
1907 if (!event->any.window ||
1908 cdk_window_get_window_type (event->any.window) == CDK_WINDOW_FOREIGN)
1909 return CDK_FILTER_CONTINUE; /* Not for us */
1910
1911 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndDrop: source_window: %#x time: %d", source_window, time
); }; } while (0)
1912 g_message ("XdndDrop: source_window: %#x time: %d",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndDrop: source_window: %#x time: %d", source_window, time
); }; } while (0)
1913 source_window, time))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"XdndDrop: source_window: %#x time: %d", source_window, time
); }; } while (0)
;
1914
1915 display = CDK_WINDOW_DISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1916 display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1917
1918 xdnd_precache_atoms (display);
1919
1920 context = display_x11->current_dest_drag;
1921
1922 if ((context != NULL((void*)0)) &&
1923 (context->protocol == CDK_DRAG_PROTO_XDND) &&
1924 (CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
== source_window))
1925 {
1926 context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
1927 event->dnd.type = CDK_DROP_START;
1928
1929 event->dnd.context = context;
1930 cdk_event_set_device (event, cdk_drag_context_get_device (context));
1931 g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
1932
1933 event->dnd.time = time;
1934 event->dnd.x_root = context_x11->last_x;
1935 event->dnd.y_root = context_x11->last_y;
1936
1937 cdk_x11_window_set_user_time (event->any.window, time);
1938
1939 return CDK_FILTER_TRANSLATE;
1940 }
1941
1942 return CDK_FILTER_REMOVE;
1943}
1944
1945CdkFilterReturn
1946_cdk_x11_dnd_filter (CdkXEvent *xev,
1947 CdkEvent *event,
1948 gpointer data)
1949{
1950 XEvent *xevent = (XEvent *) xev;
1951 CdkDisplay *display;
1952 int i;
1953
1954 if (!CDK_IS_X11_WINDOW (event->any.window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(event->any.window)); GType __t = ((cdk_x11_window_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
1955 return CDK_FILTER_CONTINUE;
1956
1957 if (xevent->type != ClientMessage33)
1958 return CDK_FILTER_CONTINUE;
1959
1960 display = CDK_WINDOW_DISPLAY (event->any.window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (event->any.window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
1961
1962 for (i = 0; i < G_N_ELEMENTS (xdnd_filters)(sizeof (xdnd_filters) / sizeof ((xdnd_filters)[0])); i++)
1963 {
1964 if (xevent->xclient.message_type != cdk_x11_get_xatom_by_name_for_display (display, xdnd_filters[i].atom_name))
1965 continue;
1966
1967 return xdnd_filters[i].func (xev, event, data);
1968 }
1969
1970 return CDK_FILTER_CONTINUE;
1971}
1972
1973/* Source side */
1974
1975static void
1976cdk_drag_do_leave (CdkX11DragContext *context_x11,
1977 guint32 time G_GNUC_UNUSED__attribute__ ((__unused__)))
1978{
1979 CdkDragContext *context = CDK_DRAG_CONTEXT (context_x11)((((CdkDragContext*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context_x11)), ((cdk_drag_context_get_type ()))))))
;
1980
1981 if (context->dest_window)
1982 {
1983 switch (context->protocol)
1984 {
1985 case CDK_DRAG_PROTO_XDND:
1986 xdnd_send_leave (context_x11);
1987 break;
1988 case CDK_DRAG_PROTO_ROOTWIN:
1989 case CDK_DRAG_PROTO_NONE:
1990 default:
1991 break;
1992 }
1993
1994 g_object_unref (context->dest_window);
1995 context->dest_window = NULL((void*)0);
1996 }
1997}
1998
1999static CdkWindow *
2000create_drag_window (CdkScreen *screen)
2001{
2002 CdkWindowAttr attrs = { 0 };
2003 guint mask;
2004
2005 attrs.x = attrs.y = 0;
2006 attrs.width = attrs.height = 100;
2007 attrs.wclass = CDK_INPUT_OUTPUT;
2008 attrs.window_type = CDK_WINDOW_TEMP;
2009 attrs.type_hint = CDK_WINDOW_TYPE_HINT_DND;
2010 attrs.visual = cdk_screen_get_rgba_visual (screen);
2011 if (!attrs.visual)
2012 attrs.visual = cdk_screen_get_system_visual (screen);
2013
2014 mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL | CDK_WA_TYPE_HINT;
2015
2016 return cdk_window_new (cdk_screen_get_root_window (screen), &attrs, mask);
2017}
2018
2019CdkDragContext *
2020_cdk_x11_window_drag_begin (CdkWindow *window,
2021 CdkDevice *device,
2022 GList *targets,
2023 gint x_root,
2024 gint y_root)
2025{
2026 CdkDragContext *context;
2027
2028 context = (CdkDragContext *) g_object_new (CDK_TYPE_X11_DRAG_CONTEXT(cdk_x11_drag_context_get_type ()), NULL((void*)0));
2029
2030 context->display = cdk_window_get_display (window);
2031 context->is_source = TRUE(!(0));
2032 context->source_window = window;
2033 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
2034
2035 context->targets = g_list_copy (targets);
2036 precache_target_list (context);
2037
2038 context->actions = 0;
2039
2040 cdk_drag_context_set_device (context, device);
2041
2042 CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->start_x = x_root;
2043 CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->start_y = y_root;
2044 CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->last_x = x_root;
2045 CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->last_y = y_root;
2046
2047 CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->drag_window = create_drag_window (cdk_window_get_screen (window));
2048
2049 return context;
2050}
2051
2052Window
2053_cdk_x11_display_get_drag_protocol (CdkDisplay *display,
2054 Window xid,
2055 CdkDragProtocol *protocol,
2056 guint *version)
2057
2058{
2059 CdkWindow *window;
2060 Window retval;
2061
2062 base_precache_atoms (display);
2063
2064 /* Check for a local drag */
2065 window = cdk_x11_window_lookup_for_display (display, xid);
2066 if (window && cdk_window_get_window_type (window) != CDK_WINDOW_FOREIGN)
2067 {
2068 if (g_object_get_data (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, "cdk-dnd-registered") != NULL((void*)0))
2069 {
2070 *protocol = CDK_DRAG_PROTO_XDND;
2071 *version = 5;
2072 xdnd_precache_atoms (display);
2073 CDK_NOTE (DND, g_message ("Entering local Xdnd window %#x\n", (guint) xid))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Entering local Xdnd window %#x\n", (guint) xid); }; } while (
0)
;
2074 return xid;
2075 }
2076 else if (_cdk_x11_display_is_root_window (display, xid))
2077 {
2078 *protocol = CDK_DRAG_PROTO_ROOTWIN;
2079 CDK_NOTE (DND, g_message ("Entering root window\n"))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Entering root window\n"); }; } while (0)
;
2080 return xid;
2081 }
2082 }
2083 else if ((retval = xdnd_check_dest (display, xid, version)))
2084 {
2085 *protocol = CDK_DRAG_PROTO_XDND;
2086 xdnd_precache_atoms (display);
2087 CDK_NOTE (DND, g_message ("Entering Xdnd window %#x\n", (guint) xid))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Entering Xdnd window %#x\n", (guint) xid); }; } while (0)
;
2088 return retval;
2089 }
2090 else
2091 {
2092 /* Check if this is a root window */
2093 gboolean rootwin = FALSE(0);
2094
2095 if (_cdk_x11_display_is_root_window (display, (Window) xid))
2096 rootwin = TRUE(!(0));
2097
2098 if (rootwin)
2099 {
2100 CDK_NOTE (DND, g_message ("Entering root window\n"))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Entering root window\n"); }; } while (0)
;
2101 *protocol = CDK_DRAG_PROTO_ROOTWIN;
2102 return xid;
2103 }
2104 }
2105
2106 *protocol = CDK_DRAG_PROTO_NONE;
2107
2108 return 0; /* a.k.a. None */
2109}
2110
2111static CdkWindowCache *
2112drag_context_find_window_cache (CdkX11DragContext *context_x11,
2113 CdkScreen *screen)
2114{
2115 GSList *list;
2116 CdkWindowCache *cache;
2117
2118 for (list = context_x11->window_caches; list; list = list->next)
2119 {
2120 cache = list->data;
2121 if (cache->screen == screen)
2122 return cache;
2123 }
2124
2125 cache = cdk_window_cache_get (screen);
2126 context_x11->window_caches = g_slist_prepend (context_x11->window_caches, cache);
2127
2128 return cache;
2129}
2130
2131static CdkWindow *
2132cdk_x11_drag_context_find_window (CdkDragContext *context,
2133 CdkWindow *drag_window,
2134 CdkScreen *screen,
2135 gint x_root,
2136 gint y_root,
2137 CdkDragProtocol *protocol)
2138{
2139 CdkX11Screen *screen_x11 = CDK_X11_SCREEN(screen)((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), ((cdk_x11_screen_get_type ()))))))
;
2140 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2141 CdkWindowCache *window_cache;
2142 CdkDisplay *display;
2143 Window dest;
2144 CdkWindow *dest_window;
2145
2146 display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
2147
2148 window_cache = drag_context_find_window_cache (context_x11, screen);
2149
2150 dest = get_client_window_at_coords (window_cache,
2151 drag_window && CDK_WINDOW_IS_X11 (drag_window)((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*)
(((drag_window)->impl)); GType __t = ((cdk_window_impl_x11_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))
?
2152 CDK_WINDOW_XID (drag_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((drag_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
: None0L,
2153 x_root * screen_x11->window_scale,
2154 y_root * screen_x11->window_scale);
2155
2156 if (context_x11->dest_xid != dest)
2157 {
2158 Window recipient;
2159 context_x11->dest_xid = dest;
2160
2161 /* Check if new destination accepts drags, and which protocol */
2162
2163 /* There is some ugliness here. We actually need to pass
2164 * _three_ pieces of information to drag_motion - dest_window,
2165 * protocol, and the XID of the unproxied window. The first
2166 * two are passed explicitly, the third implicitly through
2167 * protocol->dest_xid.
2168 */
2169 recipient = _cdk_x11_display_get_drag_protocol (display,
2170 dest,
2171 protocol,
2172 &context_x11->version);
2173
2174 if (recipient != None0L)
2175 dest_window = cdk_x11_window_foreign_new_for_display (display, recipient);
2176 else
2177 dest_window = NULL((void*)0);
2178 }
2179 else
2180 {
2181 dest_window = context->dest_window;
2182 if (dest_window)
2183 g_object_ref (dest_window)((__typeof__ (dest_window)) (g_object_ref) (dest_window));
2184 *protocol = context->protocol;
2185 }
2186
2187 return dest_window;
2188}
2189
2190static void
2191move_drag_window (CdkDragContext *context,
2192 guint x_root,
2193 guint y_root)
2194{
2195 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2196
2197 cdk_window_move (context_x11->drag_window,
2198 x_root - context_x11->hot_x,
2199 y_root - context_x11->hot_y);
2200 cdk_window_raise (context_x11->drag_window);
2201}
2202
2203static gboolean
2204cdk_x11_drag_context_drag_motion (CdkDragContext *context,
2205 CdkWindow *dest_window,
2206 CdkDragProtocol protocol,
2207 gint x_root,
2208 gint y_root,
2209 CdkDragAction suggested_action,
2210 CdkDragAction possible_actions,
2211 guint32 time)
2212{
2213 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2214
2215 if (context_x11->drag_window)
1
Assuming field 'drag_window' is null
2
Taking false branch
2216 move_drag_window (context, x_root, y_root);
2217
2218 context_x11->old_actions = context->actions;
2219 context->actions = possible_actions;
2220
2221 if (context_x11->old_actions != possible_actions)
3
Assuming 'possible_actions' is equal to field 'old_actions'
2222 context_x11->xdnd_actions_set = FALSE(0);
2223
2224 if (protocol == CDK_DRAG_PROTO_XDND && context_x11->version == 0)
4
Assuming 'protocol' is equal to CDK_DRAG_PROTO_XDND
5
Assuming field 'version' is not equal to 0
2225 {
2226 /* This ugly hack is necessary since CTK+ doesn't know about
2227 * the XDND protocol version, and in particular doesn't know
2228 * that cdk_drag_find_window_for_screen() has the side-effect
2229 * of setting context_x11->version, and therefore sometimes call
2230 * cdk_drag_motion() without a prior call to
2231 * cdk_drag_find_window_for_screen(). This happens, e.g.
2232 * when CTK+ is proxying DND events to embedded windows.
2233 */
2234 if (dest_window)
2235 {
2236 CdkDisplay *display = CDK_WINDOW_DISPLAY (dest_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (dest_window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
2237
2238 xdnd_check_dest (display,
2239 CDK_WINDOW_XID (dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dest_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
,
2240 &context_x11->version);
2241 }
2242 }
2243
2244 /* When we have a Xdnd target, make sure our XdndActionList
2245 * matches the current actions;
2246 */
2247 if (protocol
5.1
'protocol' is equal to CDK_DRAG_PROTO_XDND
== CDK_DRAG_PROTO_XDND && !context_x11->xdnd_actions_set)
6
Assuming field 'xdnd_actions_set' is not equal to 0
7
Taking false branch
2248 {
2249 if (dest_window)
2250 {
2251 if (cdk_window_get_window_type (dest_window) == CDK_WINDOW_FOREIGN)
2252 xdnd_set_actions (context_x11);
2253 else if (context->dest_window == dest_window)
2254 {
2255 CdkDisplay *display = CDK_WINDOW_DISPLAY (dest_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (dest_window)))), ((cdk_x11_screen_get_type
()))))))->display)
;
2256 CdkDragContext *dest_context;
2257
2258 dest_context = cdk_drag_context_find (display, FALSE(0),
2259 CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
,
2260 CDK_WINDOW_XID (dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dest_window)), ((cdk_window_get_type ())
)))))->impl)), ((cdk_window_impl_x11_get_type ()))))))->
xid)
);
2261
2262 if (dest_context)
2263 {
2264 dest_context->actions = context->actions;
2265 CDK_X11_DRAG_CONTEXT (dest_context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((dest_context)), ((cdk_x11_drag_context_get_type
()))))))
->xdnd_have_actions = TRUE(!(0));
2266 }
2267 }
2268 }
2269 }
2270
2271 if (context->dest_window != dest_window)
8
Assuming 'dest_window' is not equal to field 'dest_window'
9
Taking true branch
2272 {
2273 CdkEvent *temp_event;
2274
2275 /* Send a leave to the last destination */
2276 cdk_drag_do_leave (context_x11, time);
2277 context_x11->drag_status = CDK_DRAG_STATUS_DRAG;
2278
2279 /* Check if new destination accepts drags, and which protocol */
2280
2281 if (dest_window)
10
Assuming 'dest_window' is non-null
11
Taking true branch
2282 {
2283 context->dest_window = dest_window;
2284 context_x11->drop_xid = context_x11->dest_xid;
2285 g_object_ref (context->dest_window)((__typeof__ (context->dest_window)) (g_object_ref) (context
->dest_window))
;
2286 context->protocol = protocol;
2287
2288 switch (protocol)
12
Control jumps to 'case CDK_DRAG_PROTO_XDND:' at line 2290
2289 {
2290 case CDK_DRAG_PROTO_XDND:
2291 xdnd_send_enter (context_x11);
13
Calling 'xdnd_send_enter'
2292 break;
2293
2294 case CDK_DRAG_PROTO_ROOTWIN:
2295 case CDK_DRAG_PROTO_NONE:
2296 default:
2297 break;
2298 }
2299 context_x11->old_action = suggested_action;
2300 context->suggested_action = suggested_action;
2301 context_x11->old_actions = possible_actions;
2302 }
2303 else
2304 {
2305 context->dest_window = NULL((void*)0);
2306 context_x11->drop_xid = None0L;
2307 context->action = 0;
2308 }
2309
2310 /* Push a status event, to let the client know that
2311 * the drag changed
2312 */
2313 temp_event = cdk_event_new (CDK_DRAG_STATUS);
2314 temp_event->dnd.window = g_object_ref (context->source_window)((__typeof__ (context->source_window)) (g_object_ref) (context
->source_window))
;
2315 /* We use this to signal a synthetic status. Perhaps
2316 * we should use an extra field...
2317 */
2318 temp_event->dnd.send_event = TRUE(!(0));
2319
2320 temp_event->dnd.context = g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
2321 temp_event->dnd.time = time;
2322 cdk_event_set_device (temp_event, cdk_drag_context_get_device (context));
2323
2324 cdk_event_put (temp_event);
2325 cdk_event_free (temp_event);
2326 }
2327 else
2328 {
2329 context_x11->old_action = context->suggested_action;
2330 context->suggested_action = suggested_action;
2331 }
2332
2333 /* Send a drag-motion event */
2334
2335 context_x11->last_x = x_root;
2336 context_x11->last_y = y_root;
2337
2338 if (context->dest_window)
2339 {
2340 CdkWindowImplX11 *impl;
2341
2342 impl = CDK_WINDOW_IMPL_X11 (context->dest_window->impl)((((CdkWindowImplX11*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((context->dest_window->impl)), ((cdk_window_impl_x11_get_type
()))))))
;
2343
2344 if (context_x11->drag_status == CDK_DRAG_STATUS_DRAG)
2345 {
2346 switch (context->protocol)
2347 {
2348 case CDK_DRAG_PROTO_XDND:
2349 xdnd_send_motion (context_x11, x_root * impl->window_scale, y_root * impl->window_scale, suggested_action, time);
2350 break;
2351
2352 case CDK_DRAG_PROTO_ROOTWIN:
2353 {
2354 CdkEvent *temp_event;
2355 /* CTK+ traditionally has used application/x-rootwin-drop,
2356 * but the XDND spec specifies x-rootwindow-drop.
2357 */
2358 CdkAtom target1 = cdk_atom_intern_static_string ("application/x-rootwindow-drop");
2359 CdkAtom target2 = cdk_atom_intern_static_string ("application/x-rootwin-drop");
2360
2361 if (g_list_find (context->targets,
2362 CDK_ATOM_TO_POINTER (target1)(target1)) ||
2363 g_list_find (context->targets,
2364 CDK_ATOM_TO_POINTER (target2)(target2)))
2365 context->action = context->suggested_action;
2366 else
2367 context->action = 0;
2368
2369 temp_event = cdk_event_new (CDK_DRAG_STATUS);
2370 temp_event->dnd.window = g_object_ref (context->source_window)((__typeof__ (context->source_window)) (g_object_ref) (context
->source_window))
;
2371 temp_event->dnd.send_event = FALSE(0);
2372 temp_event->dnd.context = g_object_ref (context)((__typeof__ (context)) (g_object_ref) (context));
2373 temp_event->dnd.time = time;
2374 cdk_event_set_device (temp_event, cdk_drag_context_get_device (context));
2375
2376 cdk_event_put (temp_event);
2377 cdk_event_free (temp_event);
2378 }
2379 break;
2380 case CDK_DRAG_PROTO_NONE:
2381 g_warning ("CDK_DRAG_PROTO_NONE is not valid in cdk_drag_motion()");
2382 break;
2383 default:
2384 break;
2385 }
2386 }
2387 else
2388 return TRUE(!(0));
2389 }
2390
2391 return FALSE(0);
2392}
2393
2394static void
2395cdk_x11_drag_context_drag_abort (CdkDragContext *context,
2396 guint32 time)
2397{
2398 cdk_drag_do_leave (CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
, time);
2399}
2400
2401static void
2402cdk_x11_drag_context_drag_drop (CdkDragContext *context,
2403 guint32 time)
2404{
2405 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2406
2407 if (context->dest_window)
2408 {
2409 switch (context->protocol)
2410 {
2411 case CDK_DRAG_PROTO_XDND:
2412 xdnd_send_drop (context_x11, time);
2413 break;
2414
2415 case CDK_DRAG_PROTO_ROOTWIN:
2416 g_warning ("Drops for CDK_DRAG_PROTO_ROOTWIN must be handled internally");
2417 break;
2418 case CDK_DRAG_PROTO_NONE:
2419 g_warning ("CDK_DRAG_PROTO_NONE is not valid in cdk_drag_drop()");
2420 break;
2421 default:
2422 break;
2423 }
2424 }
2425}
2426
2427/* Destination side */
2428
2429static void
2430cdk_x11_drag_context_drag_status (CdkDragContext *context,
2431 CdkDragAction action,
2432 guint32 time_ G_GNUC_UNUSED__attribute__ ((__unused__)))
2433{
2434 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2435 XEvent xev;
2436 CdkDisplay *display;
2437
2438 display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
2439
2440 context->action = action;
2441
2442 if (context->protocol == CDK_DRAG_PROTO_XDND)
2443 {
2444 xev.xclient.type = ClientMessage33;
2445 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndStatus");
2446 xev.xclient.format = 32;
2447 xev.xclient.window = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
2448
2449 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
2450 xev.xclient.data.l[1] = (action != 0) ? (2 | 1) : 0;
2451 xev.xclient.data.l[2] = 0;
2452 xev.xclient.data.l[3] = 0;
2453 xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
2454 if (!xdnd_send_xevent (context_x11, context->source_window, FALSE(0), &xev))
2455 {
2456 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
2457 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
2458 CDK_WINDOW_XID (context->source_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
2459 }
2460 }
2461
2462 context_x11->old_action = action;
2463}
2464
2465static void
2466cdk_x11_drag_context_drop_reply (CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
2467 gboolean accepted G_GNUC_UNUSED__attribute__ ((__unused__)),
2468 guint32 time_ G_GNUC_UNUSED__attribute__ ((__unused__)))
2469{
2470}
2471
2472static void
2473cdk_x11_drag_context_drop_finish (CdkDragContext *context,
2474 gboolean success,
2475 guint32 time G_GNUC_UNUSED__attribute__ ((__unused__)))
2476{
2477 if (context->protocol == CDK_DRAG_PROTO_XDND)
2478 {
2479 CdkDisplay *display = CDK_WINDOW_DISPLAY (context->source_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (context->source_window)))), (
(cdk_x11_screen_get_type ()))))))->display)
;
2480 XEvent xev;
2481
2482 xev.xclient.type = ClientMessage33;
2483 xev.xclient.message_type = cdk_x11_get_xatom_by_name_for_display (display, "XdndFinished");
2484 xev.xclient.format = 32;
2485 xev.xclient.window = CDK_WINDOW_XID (context->source_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
2486
2487 xev.xclient.data.l[0] = CDK_WINDOW_XID (context->dest_window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->dest_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)
;
2488 if (success)
2489 {
2490 xev.xclient.data.l[1] = 1;
2491 xev.xclient.data.l[2] = xdnd_action_to_atom (display,
2492 context->action);
2493 }
2494 else
2495 {
2496 xev.xclient.data.l[1] = 0;
2497 xev.xclient.data.l[2] = None0L;
2498 }
2499 xev.xclient.data.l[3] = 0;
2500 xev.xclient.data.l[4] = 0;
2501
2502 if (!xdnd_send_xevent (CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
, context->source_window, FALSE(0), &xev))
2503 {
2504 CDK_NOTE (DND,do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
2505 g_message ("Send event to %lx failed",do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
2506 CDK_WINDOW_XID (context->source_window)))do { if ((_cdk_debug_flags & CDK_DEBUG_DND)) { g_message (
"Send event to %lx failed", (((((CdkWindowImplX11*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context->source_window)), ((cdk_window_get_type
()))))))->impl)), ((cdk_window_impl_x11_get_type ()))))))
->xid)); }; } while (0)
;
2507 }
2508 }
2509}
2510
2511void
2512_cdk_x11_window_register_dnd (CdkWindow *window)
2513{
2514 static const gulong xdnd_version = 5;
2515 CdkDisplay *display = cdk_window_get_display (window);
2516
2517 g_return_if_fail (window != NULL)do { if ((window != ((void*)0))) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "window != NULL"); return
; } } while (0)
;
2518
2519 if (cdk_window_get_window_type (window) == CDK_WINDOW_OFFSCREEN)
2520 return;
2521
2522 base_precache_atoms (display);
2523
2524 if (g_object_get_data (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, "cdk-dnd-registered") != NULL((void*)0))
2525 return;
2526 else
2527 g_object_set_data (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, "cdk-dnd-registered", GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
2528
2529 /* Set XdndAware */
2530
2531 /* The property needs to be of type XA_ATOM, not XA_INTEGER. Blech */
2532 XChangeProperty (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
,
2533 CDK_WINDOW_XID (window)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((cdk_window_get_type ()))))))
->impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
,
2534 cdk_x11_get_xatom_by_name_for_display (display, "XdndAware"),
2535 XA_ATOM((Atom) 4), 32, PropModeReplace0,
2536 (guchar *)&xdnd_version, 1);
2537}
2538
2539static CdkAtom
2540cdk_x11_drag_context_get_selection (CdkDragContext *context)
2541{
2542 if (context->protocol == CDK_DRAG_PROTO_XDND)
2543 return cdk_atom_intern_static_string ("XdndSelection");
2544 else
2545 return CDK_NONE((CdkAtom)((gpointer) (gulong) (0)));
2546}
2547
2548static gboolean
2549cdk_x11_drag_context_drop_status (CdkDragContext *context)
2550{
2551 return ! CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->drop_failed;
2552}
2553
2554static CdkWindow *
2555cdk_x11_drag_context_get_drag_window (CdkDragContext *context)
2556{
2557 return CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
->drag_window;
2558}
2559
2560static void
2561cdk_x11_drag_context_set_hotspot (CdkDragContext *context,
2562 gint hot_x,
2563 gint hot_y)
2564{
2565 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2566
2567 x11_context->hot_x = hot_x;
2568 x11_context->hot_y = hot_y;
2569
2570 if (x11_context->grab_seat)
2571 {
2572 /* DnD is managed, update current position */
2573 move_drag_window (context, x11_context->last_x, x11_context->last_y);
2574 }
2575}
2576
2577static double
2578ease_out_cubic (double t)
2579{
2580 double p = t - 1;
2581 return p * p * p + 1;
2582}
2583
2584
2585#define ANIM_TIME500000 500000 /* half a second */
2586
2587typedef struct _CdkDragAnim CdkDragAnim;
2588struct _CdkDragAnim {
2589 CdkX11DragContext *context;
2590 CdkFrameClock *frame_clock;
2591 gint64 start_time;
2592};
2593
2594static void
2595cdk_drag_anim_destroy (CdkDragAnim *anim)
2596{
2597 g_object_unref (anim->context);
2598 g_slice_free (CdkDragAnim, anim)do { if (1) g_slice_free1 (sizeof (CdkDragAnim), (anim)); else
(void) ((CdkDragAnim*) 0 == (anim)); } while (0)
;
2599}
2600
2601static gboolean
2602cdk_drag_anim_timeout (gpointer data)
2603{
2604 CdkDragAnim *anim = data;
2605 CdkX11DragContext *context = anim->context;
2606 CdkFrameClock *frame_clock = anim->frame_clock;
2607 gint64 current_time;
2608 double f;
2609 double t;
2610
2611 if (!frame_clock)
2612 return G_SOURCE_REMOVE(0);
2613
2614 current_time = cdk_frame_clock_get_frame_time (frame_clock);
2615
2616 f = (current_time - anim->start_time) / (double) ANIM_TIME500000;
2617
2618 if (f >= 1.0)
2619 return G_SOURCE_REMOVE(0);
2620
2621 t = ease_out_cubic (f);
2622
2623 cdk_window_show (context->drag_window);
2624 cdk_window_move (context->drag_window,
2625 (context->last_x - context->hot_x) +
2626 (context->start_x - context->last_x) * t,
2627 (context->last_y - context->hot_y) +
2628 (context->start_y - context->last_y) * t);
2629 cdk_window_set_opacity (context->drag_window, 1.0 - f);
2630
2631 return G_SOURCE_CONTINUE(!(0));
2632}
2633
2634static void
2635cdk_x11_drag_context_drop_done (CdkDragContext *context,
2636 gboolean success)
2637{
2638 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2639 CdkDragAnim *anim;
2640 cairo_surface_t *win_surface;
2641 cairo_surface_t *surface;
2642 cairo_pattern_t *pattern;
2643 cairo_t *cr;
2644
2645 if (success)
2646 {
2647 cdk_window_hide (x11_context->drag_window);
2648 return;
2649 }
2650
2651 win_surface = _cdk_window_ref_cairo_surface (x11_context->drag_window);
2652 surface = cdk_window_create_similar_surface (x11_context->drag_window,
2653 cairo_surface_get_content (win_surface),
2654 cdk_window_get_width (x11_context->drag_window),
2655 cdk_window_get_height (x11_context->drag_window));
2656 cr = cairo_create (surface);
2657 cairo_set_source_surface (cr, win_surface, 0, 0);
2658 cairo_paint (cr);
2659 cairo_destroy (cr);
2660 cairo_surface_destroy (win_surface);
2661
2662 pattern = cairo_pattern_create_for_surface (surface);
2663
2664 cdk_window_set_background_pattern (x11_context->drag_window, pattern);
2665
2666 cairo_pattern_destroy (pattern);
2667 cairo_surface_destroy (surface);
2668
2669 anim = g_slice_new0 (CdkDragAnim)((CdkDragAnim*) g_slice_alloc0 (sizeof (CdkDragAnim)));
2670 anim->context = g_object_ref (x11_context)((__typeof__ (x11_context)) (g_object_ref) (x11_context));
2671 anim->frame_clock = cdk_window_get_frame_clock (x11_context->drag_window);
2672 anim->start_time = cdk_frame_clock_get_frame_time (anim->frame_clock);
2673
2674 cdk_threads_add_timeout_full (G_PRIORITY_DEFAULT0, 17,
2675 cdk_drag_anim_timeout, anim,
2676 (GDestroyNotify) cdk_drag_anim_destroy);
2677}
2678
2679static gboolean
2680drag_context_grab (CdkDragContext *context)
2681{
2682 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2683 CdkDevice *device = cdk_drag_context_get_device (context);
2684 CdkSeatCapabilities capabilities;
2685 CdkWindow *root;
2686 CdkSeat *seat;
2687 gint keycode, i;
2688 CdkCursor *cursor;
2689
2690 if (!x11_context->ipc_window)
2691 return FALSE(0);
2692
2693 root = cdk_screen_get_root_window (cdk_window_get_screen (x11_context->ipc_window));
2694 seat = cdk_device_get_seat (cdk_drag_context_get_device (context));
2695
2696#ifdef XINPUT_21
2697 if (CDK_IS_X11_DEVICE_XI2 (device)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(device)); GType __t = ((cdk_x11_device_xi2_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2698 capabilities = CDK_SEAT_CAPABILITY_ALL_POINTING;
2699 else
2700#endif
2701 capabilities = CDK_SEAT_CAPABILITY_ALL;
2702
2703 cursor = cdk_drag_get_cursor (context, x11_context->current_action);
2704 g_set_object (&x11_context->cursor, cursor)(__extension__ ({ _Static_assert (sizeof *(&x11_context->
cursor) == sizeof (cursor), "Expression evaluates to false");
union { char *in; GObject **out; } _object_ptr; _object_ptr.
in = (char *) (&x11_context->cursor); (void) (0 ? *(&
x11_context->cursor) = (cursor), (0) : (0)); (g_set_object
) (_object_ptr.out, (GObject *) cursor); }))
;
2705
2706 if (cdk_seat_grab (seat, x11_context->ipc_window,
2707 capabilities, FALSE(0),
2708 x11_context->cursor, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != CDK_GRAB_SUCCESS)
2709 return FALSE(0);
2710
2711 g_set_object (&x11_context->grab_seat, seat)(__extension__ ({ _Static_assert (sizeof *(&x11_context->
grab_seat) == sizeof (seat), "Expression evaluates to false")
; union { char *in; GObject **out; } _object_ptr; _object_ptr
.in = (char *) (&x11_context->grab_seat); (void) (0 ? *
(&x11_context->grab_seat) = (seat), (0) : (0)); (g_set_object
) (_object_ptr.out, (GObject *) seat); }))
;
2712
2713 cdk_x11_display_error_trap_push (cdk_window_get_display (x11_context->ipc_window));
2714
2715 for (i = 0; i < G_N_ELEMENTS (grab_keys)(sizeof (grab_keys) / sizeof ((grab_keys)[0])); ++i)
2716 {
2717 keycode = XKeysymToKeycode (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2718 grab_keys[i].keysym);
2719 if (keycode == NoSymbol0L)
2720 continue;
2721
2722#ifdef XINPUT_21
2723 if (CDK_IS_X11_DEVICE_XI2 (device)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(device)); GType __t = ((cdk_x11_device_xi2_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2724 {
2725 gint deviceid = cdk_x11_device_get_id (cdk_seat_get_keyboard (seat));
2726 unsigned char mask[XIMaskLen(XI_LASTEVENT)(((32) >> 3) + 1)];
2727 XIGrabModifiers mods;
2728 XIEventMask evmask;
2729 gint num_mods;
2730
2731 memset (mask, 0, sizeof (mask));
2732 XISetMask (mask, XI_KeyPress)(((unsigned char*)(mask))[(2)>>3] |= (1 << ((2) &
7)))
;
2733 XISetMask (mask, XI_KeyRelease)(((unsigned char*)(mask))[(3)>>3] |= (1 << ((3) &
7)))
;
2734
2735 evmask.deviceid = deviceid;
2736 evmask.mask_len = sizeof (mask);
2737 evmask.mask = mask;
2738
2739 num_mods = 1;
2740 mods.modifiers = grab_keys[i].modifiers;
2741
2742 XIGrabKeycode (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2743 deviceid,
2744 keycode,
2745 CDK_WINDOW_XID (root)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root)), ((cdk_window_get_type ()))))))->
impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
,
2746 GrabModeAsync1,
2747 GrabModeAsync1,
2748 False0,
2749 &evmask,
2750 num_mods,
2751 &mods);
2752 }
2753 else
2754#endif
2755 {
2756 XGrabKey (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2757 keycode, grab_keys[i].modifiers,
2758 CDK_WINDOW_XID (root)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root)), ((cdk_window_get_type ()))))))->
impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
,
2759 FALSE(0),
2760 GrabModeAsync1,
2761 GrabModeAsync1);
2762 }
2763 }
2764
2765 cdk_x11_display_error_trap_pop_ignored (cdk_window_get_display (x11_context->ipc_window));
2766
2767 return TRUE(!(0));
2768}
2769
2770static void
2771drag_context_ungrab (CdkDragContext *context)
2772{
2773 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2774 CdkDevice *keyboard;
2775 CdkWindow *root;
2776 gint keycode, i;
2777
2778 if (!x11_context->grab_seat)
2779 return;
2780
2781 cdk_seat_ungrab (x11_context->grab_seat);
2782
2783 keyboard = cdk_seat_get_keyboard (x11_context->grab_seat);
2784 root = cdk_screen_get_root_window (cdk_window_get_screen (x11_context->ipc_window));
2785 g_clear_object (&x11_context->grab_seat)do { _Static_assert (sizeof *((&x11_context->grab_seat
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&x11_context->grab_seat))) _pp = ((&x11_context
->grab_seat)); __typeof__ (*((&x11_context->grab_seat
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
2786
2787 for (i = 0; i < G_N_ELEMENTS (grab_keys)(sizeof (grab_keys) / sizeof ((grab_keys)[0])); ++i)
2788 {
2789 keycode = XKeysymToKeycode (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2790 grab_keys[i].keysym);
2791 if (keycode == NoSymbol0L)
2792 continue;
2793
2794#ifdef XINPUT_21
2795 if (CDK_IS_X11_DEVICE_XI2 (keyboard)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(keyboard)); GType __t = ((cdk_x11_device_xi2_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2796 {
2797 XIGrabModifiers mods;
2798 gint num_mods;
2799
2800 num_mods = 1;
2801 mods.modifiers = grab_keys[i].modifiers;
2802
2803 XIUngrabKeycode (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2804 cdk_x11_device_get_id (keyboard),
2805 keycode,
2806 CDK_WINDOW_XID (root)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root)), ((cdk_window_get_type ()))))))->
impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
,
2807 num_mods,
2808 &mods);
2809 }
2810 else
2811#endif /* XINPUT_2 */
2812 {
2813 XUngrabKey (CDK_WINDOW_XDISPLAY (x11_context->ipc_window)(((((CdkX11Screen*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((cdk_window_get_screen (x11_context->ipc_window)))), (
(cdk_x11_screen_get_type ()))))))->xdisplay)
,
2814 keycode, grab_keys[i].modifiers,
2815 CDK_WINDOW_XID (root)(((((CdkWindowImplX11*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((((((CdkWindow*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((root)), ((cdk_window_get_type ()))))))->
impl)), ((cdk_window_impl_x11_get_type ()))))))->xid)
);
2816 }
2817 }
2818}
2819
2820static gboolean
2821cdk_x11_drag_context_manage_dnd (CdkDragContext *context,
2822 CdkWindow *ipc_window,
2823 CdkDragAction actions)
2824{
2825 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2826
2827 if (x11_context->ipc_window)
2828 return FALSE(0);
2829
2830 context->protocol = CDK_DRAG_PROTO_XDND;
2831 x11_context->ipc_window = g_object_ref (ipc_window)((__typeof__ (ipc_window)) (g_object_ref) (ipc_window));
2832
2833 if (drag_context_grab (context))
2834 {
2835 x11_context->actions = actions;
2836 move_drag_window (context, x11_context->start_x, x11_context->start_y);
2837 return TRUE(!(0));
2838 }
2839 else
2840 {
2841 g_clear_object (&x11_context->ipc_window)do { _Static_assert (sizeof *((&x11_context->ipc_window
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&x11_context->ipc_window))) _pp = ((&x11_context
->ipc_window)); __typeof__ (*((&x11_context->ipc_window
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
2842 return FALSE(0);
2843 }
2844}
2845
2846static void
2847cdk_x11_drag_context_set_cursor (CdkDragContext *context,
2848 CdkCursor *cursor)
2849{
2850 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2851
2852 if (!g_set_object (&x11_context->cursor, cursor)(__extension__ ({ _Static_assert (sizeof *(&x11_context->
cursor) == sizeof (cursor), "Expression evaluates to false");
union { char *in; GObject **out; } _object_ptr; _object_ptr.
in = (char *) (&x11_context->cursor); (void) (0 ? *(&
x11_context->cursor) = (cursor), (0) : (0)); (g_set_object
) (_object_ptr.out, (GObject *) cursor); }))
)
2853 return;
2854
2855 if (x11_context->grab_seat)
2856 {
2857 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
2858 cdk_device_grab (cdk_seat_get_pointer (x11_context->grab_seat),
2859 x11_context->ipc_window,
2860 CDK_OWNERSHIP_APPLICATION, FALSE(0),
2861 CDK_POINTER_MOTION_MASK | CDK_BUTTON_RELEASE_MASK,
2862 cursor, CDK_CURRENT_TIME0L);
2863 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
2864 }
2865}
2866
2867static void
2868cdk_x11_drag_context_cancel (CdkDragContext *context,
2869 CdkDragCancelReason reason G_GNUC_UNUSED__attribute__ ((__unused__)))
2870{
2871 drag_context_ungrab (context);
2872 cdk_drag_drop_done (context, FALSE(0));
2873}
2874
2875static void
2876cdk_x11_drag_context_drop_performed (CdkDragContext *context,
2877 guint32 time_ G_GNUC_UNUSED__attribute__ ((__unused__)))
2878{
2879 drag_context_ungrab (context);
2880}
2881
2882#define BIG_STEP20 20
2883#define SMALL_STEP1 1
2884
2885static void
2886cdk_drag_get_current_actions (CdkModifierType state,
2887 gint button,
2888 CdkDragAction actions,
2889 CdkDragAction *suggested_action,
2890 CdkDragAction *possible_actions)
2891{
2892 *suggested_action = 0;
2893 *possible_actions = 0;
2894
2895 if ((button == CDK_BUTTON_MIDDLE(2) || button == CDK_BUTTON_SECONDARY(3)) && (actions & CDK_ACTION_ASK))
2896 {
2897 *suggested_action = CDK_ACTION_ASK;
2898 *possible_actions = actions;
2899 }
2900 else if (state & (CDK_SHIFT_MASK | CDK_CONTROL_MASK))
2901 {
2902 if ((state & CDK_SHIFT_MASK) && (state & CDK_CONTROL_MASK))
2903 {
2904 if (actions & CDK_ACTION_LINK)
2905 {
2906 *suggested_action = CDK_ACTION_LINK;
2907 *possible_actions = CDK_ACTION_LINK;
2908 }
2909 }
2910 else if (state & CDK_CONTROL_MASK)
2911 {
2912 if (actions & CDK_ACTION_COPY)
2913 {
2914 *suggested_action = CDK_ACTION_COPY;
2915 *possible_actions = CDK_ACTION_COPY;
2916 }
2917 }
2918 else
2919 {
2920 if (actions & CDK_ACTION_MOVE)
2921 {
2922 *suggested_action = CDK_ACTION_MOVE;
2923 *possible_actions = CDK_ACTION_MOVE;
2924 }
2925 }
2926 }
2927 else
2928 {
2929 *possible_actions = actions;
2930
2931 if ((state & (CDK_MOD1_MASK)) && (actions & CDK_ACTION_ASK))
2932 *suggested_action = CDK_ACTION_ASK;
2933 else if (actions & CDK_ACTION_COPY)
2934 *suggested_action = CDK_ACTION_COPY;
2935 else if (actions & CDK_ACTION_MOVE)
2936 *suggested_action = CDK_ACTION_MOVE;
2937 else if (actions & CDK_ACTION_LINK)
2938 *suggested_action = CDK_ACTION_LINK;
2939 }
2940}
2941
2942static void
2943cdk_drag_update (CdkDragContext *context,
2944 gdouble x_root,
2945 gdouble y_root,
2946 CdkModifierType mods,
2947 guint32 evtime)
2948{
2949 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2950 CdkDragAction action, possible_actions;
2951 CdkWindow *dest_window;
2952 CdkDragProtocol protocol;
2953
2954 cdk_drag_get_current_actions (mods, CDK_BUTTON_PRIMARY(1), x11_context->actions,
2955 &action, &possible_actions);
2956
2957 cdk_drag_find_window_for_screen (context,
2958 x11_context->drag_window,
2959 cdk_display_get_default_screen (cdk_display_get_default ()),
2960 x_root, y_root, &dest_window, &protocol);
2961
2962 cdk_drag_motion (context, dest_window, protocol, x_root, y_root,
2963 action, possible_actions, evtime);
2964}
2965
2966static gboolean
2967cdk_dnd_handle_motion_event (CdkDragContext *context,
2968 const CdkEventMotion *event)
2969{
2970 CdkModifierType state;
2971
2972 if (!cdk_event_get_state ((CdkEvent *) event, &state))
2973 return FALSE(0);
2974
2975 cdk_drag_update (context, event->x_root, event->y_root, state,
2976 cdk_event_get_time ((CdkEvent *) event));
2977 return TRUE(!(0));
2978}
2979
2980static gboolean
2981cdk_dnd_handle_key_event (CdkDragContext *context,
2982 const CdkEventKey *event)
2983{
2984 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
2985 CdkModifierType state;
2986 CdkWindow *root_window;
2987 CdkDevice *pointer;
2988 gint dx, dy;
2989
2990 dx = dy = 0;
2991 state = event->state;
2992 pointer = cdk_device_get_associated_device (cdk_event_get_device ((CdkEvent *) event));
2993
2994 if (event->type == CDK_KEY_PRESS)
2995 {
2996 switch (event->keyval)
2997 {
2998 case CDK_KEY_Escape0xff1b:
2999 cdk_drag_context_cancel (context, CDK_DRAG_CANCEL_USER_CANCELLED);
3000 return TRUE(!(0));
3001
3002 case CDK_KEY_space0x020:
3003 case CDK_KEY_Return0xff0d:
3004 case CDK_KEY_ISO_Enter0xfe34:
3005 case CDK_KEY_KP_Enter0xff8d:
3006 case CDK_KEY_KP_Space0xff80:
3007 if ((cdk_drag_context_get_selected_action (context) != 0) &&
3008 (cdk_drag_context_get_dest_window (context) != NULL((void*)0)))
3009 {
3010 g_signal_emit_by_name (context, "drop-performed",
3011 cdk_event_get_time ((CdkEvent *) event));
3012 }
3013 else
3014 cdk_drag_context_cancel (context, CDK_DRAG_CANCEL_NO_TARGET);
3015
3016 return TRUE(!(0));
3017
3018 case CDK_KEY_Up0xff52:
3019 case CDK_KEY_KP_Up0xff97:
3020 dy = (state & CDK_MOD1_MASK) ? -BIG_STEP20 : -SMALL_STEP1;
3021 break;
3022
3023 case CDK_KEY_Down0xff54:
3024 case CDK_KEY_KP_Down0xff99:
3025 dy = (state & CDK_MOD1_MASK) ? BIG_STEP20 : SMALL_STEP1;
3026 break;
3027
3028 case CDK_KEY_Left0xff51:
3029 case CDK_KEY_KP_Left0xff96:
3030 dx = (state & CDK_MOD1_MASK) ? -BIG_STEP20 : -SMALL_STEP1;
3031 break;
3032
3033 case CDK_KEY_Right0xff53:
3034 case CDK_KEY_KP_Right0xff98:
3035 dx = (state & CDK_MOD1_MASK) ? BIG_STEP20 : SMALL_STEP1;
3036 break;
3037 }
3038 }
3039
3040 /* The state is not yet updated in the event, so we need
3041 * to query it here. We could use XGetModifierMapping, but
3042 * that would be overkill.
3043 */
3044 root_window = cdk_screen_get_root_window (cdk_window_get_screen (x11_context->ipc_window));
3045 cdk_window_get_device_position (root_window, pointer, NULL((void*)0), NULL((void*)0), &state);
3046
3047 if (dx != 0 || dy != 0)
3048 {
3049 x11_context->last_x += dx;
3050 x11_context->last_y += dy;
3051 cdk_device_warp (pointer,
3052 cdk_window_get_screen (x11_context->ipc_window),
3053 x11_context->last_x, x11_context->last_y);
3054 }
3055
3056 cdk_drag_update (context, x11_context->last_x, x11_context->last_y, state,
3057 cdk_event_get_time ((CdkEvent *) event));
3058
3059 return TRUE(!(0));
3060}
3061
3062static gboolean
3063cdk_dnd_handle_grab_broken_event (CdkDragContext *context,
3064 const CdkEventGrabBroken *event)
3065{
3066 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
3067
3068 /* Don't cancel if we break the implicit grab from the initial button_press.
3069 * Also, don't cancel if we re-grab on the widget or on our IPC window, for
3070 * example, when changing the drag cursor.
3071 */
3072 if (event->implicit ||
3073 event->grab_window == x11_context->drag_window ||
3074 event->grab_window == x11_context->ipc_window)
3075 return FALSE(0);
3076
3077 if (cdk_event_get_device ((CdkEvent *) event) !=
3078 cdk_drag_context_get_device (context))
3079 return FALSE(0);
3080
3081 cdk_drag_context_cancel (context, CDK_DRAG_CANCEL_ERROR);
3082 return TRUE(!(0));
3083}
3084
3085static gboolean
3086cdk_dnd_handle_button_event (CdkDragContext *context,
3087 const CdkEventButton *event)
3088{
3089#if 0
3090 /* FIXME: Check the button matches */
3091 if (event->button != x11_context->button)
3092 return FALSE(0);
3093#endif
3094
3095 if ((cdk_drag_context_get_selected_action (context) != 0) &&
3096 (cdk_drag_context_get_dest_window (context) != NULL((void*)0)))
3097 {
3098 g_signal_emit_by_name (context, "drop-performed",
3099 cdk_event_get_time ((CdkEvent *) event));
3100 }
3101 else
3102 cdk_drag_context_cancel (context, CDK_DRAG_CANCEL_NO_TARGET);
3103
3104 return TRUE(!(0));
3105}
3106
3107gboolean
3108cdk_dnd_handle_drag_status (CdkDragContext *context,
3109 const CdkEventDND *event)
3110{
3111 CdkX11DragContext *context_x11 = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
3112 CdkDragAction action;
3113
3114 if (context != event->context)
3115 return FALSE(0);
3116
3117 action = cdk_drag_context_get_selected_action (context);
3118
3119 if (action != context_x11->current_action)
3120 {
3121 context_x11->current_action = action;
3122 g_signal_emit_by_name (context, "action-changed", action);
3123 }
3124
3125 return TRUE(!(0));
3126}
3127
3128static gboolean
3129cdk_dnd_handle_drop_finished (CdkDragContext *context,
3130 const CdkEventDND *event)
3131{
3132 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
3133
3134 if (context != event->context)
3135 return FALSE(0);
3136
3137 g_signal_emit_by_name (context, "dnd-finished");
3138 cdk_drag_drop_done (context, !x11_context->drop_failed);
3139 return TRUE(!(0));
3140}
3141
3142gboolean
3143cdk_x11_drag_context_handle_event (CdkDragContext *context,
3144 const CdkEvent *event)
3145{
3146 CdkX11DragContext *x11_context = CDK_X11_DRAG_CONTEXT (context)((((CdkX11DragContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((cdk_x11_drag_context_get_type
()))))))
;
3147
3148 if (!context->is_source)
3149 return FALSE(0);
3150 if (!x11_context->grab_seat && event->type != CDK_DROP_FINISHED)
3151 return FALSE(0);
3152
3153 switch (event->type)
3154 {
3155 case CDK_MOTION_NOTIFY:
3156 return cdk_dnd_handle_motion_event (context, &event->motion);
3157 case CDK_BUTTON_RELEASE:
3158 return cdk_dnd_handle_button_event (context, &event->button);
3159 case CDK_KEY_PRESS:
3160 case CDK_KEY_RELEASE:
3161 return cdk_dnd_handle_key_event (context, &event->key);
3162 case CDK_GRAB_BROKEN:
3163 return cdk_dnd_handle_grab_broken_event (context, &event->grab_broken);
3164 case CDK_DRAG_STATUS:
3165 return cdk_dnd_handle_drag_status (context, &event->dnd);
3166 case CDK_DROP_FINISHED:
3167 return cdk_dnd_handle_drop_finished (context, &event->dnd);
3168 default:
3169 break;
3170 }
3171
3172 return FALSE(0);
3173}
3174
3175void
3176cdk_x11_drag_context_action_changed (CdkDragContext *context,
3177 CdkDragAction action)
3178{
3179 CdkCursor *cursor;
3180
3181 cursor = cdk_drag_get_cursor (context, action);
3182 cdk_drag_context_set_cursor (context, cursor);
3183}