From 8715d1c1b38969cd887cb218ba72ae343e7bc275 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Wed, 18 Nov 1998 17:00:48 +0000 Subject: [PATCH] Accept drops that are sent to a toplevel but are not within the toplevels Wed Nov 18 11:54:57 1998 Owen Taylor * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops that are sent to a toplevel but are not within the toplevels bounds. * gdk/gdkdnd.c gdk/gdk.h: Added support for a XdndProxy atom which proxies the drag to another window. --- ChangeLog | 12 +++++- ChangeLog.pre-2-0 | 12 +++++- ChangeLog.pre-2-10 | 12 +++++- ChangeLog.pre-2-2 | 12 +++++- ChangeLog.pre-2-4 | 12 +++++- ChangeLog.pre-2-6 | 12 +++++- ChangeLog.pre-2-8 | 12 +++++- gdk/gdk.h | 4 +- gdk/gdkdnd.c | 100 ++++++++++++++++++++++++++++++------------- gdk/x11/gdkdnd-x11.c | 100 ++++++++++++++++++++++++++++++------------- gtk/gtkdnd.c | 12 ++++-- 11 files changed, 222 insertions(+), 78 deletions(-) diff --git a/ChangeLog b/ChangeLog index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index dee0be2d42..bbe7d6bfe8 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +Wed Nov 18 11:54:57 1998 Owen Taylor + + * gtk/gtkdnd.c (gtk_drag_find_widget): Accept drops + that are sent to a toplevel but are not within the + toplevels bounds. + + * gdk/gdkdnd.c gdk/gdk.h: Added support for a + XdndProxy atom which proxies the drag to another window. + Tue Nov 17 1998 The Rasterman * gdk/gdk.h, gdk/gdkwindow.c: Added gdk_window_get_deskrelative_origin function to correctly determine gdk window position relative to @@ -81,8 +90,7 @@ Tue Nov 17 00:06:29 1998 Lars Hamann Mon Nov 16 15:10:33 1998 Owen Taylor - * gtk/gtktext.c: Optimizations for moving point n - places. + * gtk/gtktext.c: Optimizations for [advance/decrement]_mark_n. (gtk-mailund-980718-0, Thomas Mailund Jensen ) * gtk/gtkfixed.c: Removed gtk_fixed_umap, which was diff --git a/gdk/gdk.h b/gdk/gdk.h index 68feea9f7c..b002d626ed 100644 --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -245,8 +245,8 @@ GdkAtom gdk_drag_get_selection (GdkDragContext *context); GdkDragContext * gdk_drag_begin (GdkWindow *window, GList *targets, GdkDragAction actions); -gboolean gdk_drag_get_protocol (guint32 xid, - GdkDragProtocol *protocol); +guint32 gdk_drag_get_protocol (guint32 xid, + GdkDragProtocol *protocol); void gdk_drag_find_window (GdkDragContext *context, GdkWindow *drag_window, gint x_root, diff --git a/gdk/gdkdnd.c b/gdk/gdkdnd.c index c4dc41a078..9c088cbc62 100644 --- a/gdk/gdkdnd.c +++ b/gdk/gdkdnd.c @@ -1214,7 +1214,7 @@ motif_set_targets (GdkDragContext *context) private->motif_targets_set = 1; } -gboolean +guint32 motif_check_dest (Window win) { gboolean retval = FALSE; @@ -1225,7 +1225,7 @@ motif_check_dest (Window win) if (!motif_drag_receiver_info_atom) motif_drag_receiver_info_atom = gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE); - + XGetWindowProperty (gdk_display, win, motif_drag_receiver_info_atom, 0, (sizeof(*info)+3)/4, False, AnyPropertyType, @@ -1251,7 +1251,7 @@ motif_check_dest (Window win) XFree (info); } - return retval; + return retval ? win : GDK_NONE; } @@ -2098,7 +2098,7 @@ xdnd_send_motion (GdkDragContext *context, private->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; } -static gboolean +static guint32 xdnd_check_dest (Window win) { gboolean retval = FALSE; @@ -2106,31 +2106,70 @@ xdnd_check_dest (Window win) int format; unsigned long nitems, after; GdkAtom *version; + Window *proxy_data; + Window proxy; + static GdkAtom xdnd_proxy_atom = GDK_NONE; + + gint old_warnings = gdk_error_warnings; + + if (!xdnd_proxy_atom) + xdnd_proxy_atom = gdk_atom_intern ("XdndProxy", FALSE); if (!xdnd_aware_atom) xdnd_aware_atom = gdk_atom_intern ("XdndAware", FALSE); + proxy = GDK_NONE; + + gdk_error_code = 0; + gdk_error_warnings = 0; + XGetWindowProperty (gdk_display, win, - xdnd_aware_atom, 0, + xdnd_proxy_atom, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, - (guchar **)&version); - - if (type != None) - { - if ((format == 32) && (nitems == 1)) - { - if (*version == 3) - retval = TRUE; - } - else - GDK_NOTE (DND, - g_warning ("Invalid XdndAware property on window %ld\n", win)); + (guchar **)&proxy_data); - XFree (version); + if (!gdk_error_code) + { + if (type != None) + { + if ((format == 32) && (nitems == 1)) + { + proxy = *proxy_data; + } + else + GDK_NOTE (DND, + g_warning ("Invalid XdndOwner property on window %ld\n", win)); + + XFree (proxy_data); + } + + XGetWindowProperty (gdk_display, proxy ? proxy : win, + xdnd_aware_atom, 0, + 1, False, AnyPropertyType, + &type, &format, &nitems, &after, + (guchar **)&version); + + if (!gdk_error_code && type != None) + { + if ((format == 32) && (nitems == 1)) + { + if (*version == 3) + retval = TRUE; + } + else + GDK_NOTE (DND, + g_warning ("Invalid XdndAware property on window %ld\n", win)); + + XFree (version); + } + } - return retval; + gdk_error_warnings = old_warnings; + gdk_error_code = 0; + + return retval ? (proxy ? proxy : win) : GDK_NONE; } /* Target side */ @@ -2423,21 +2462,23 @@ gdk_drag_begin (GdkWindow *window, return new_context; } -gboolean +guint32 gdk_drag_get_protocol (guint32 xid, GdkDragProtocol *protocol) { - if (xdnd_check_dest (xid)) + guint32 retval; + + if ((retval = xdnd_check_dest (xid))) { *protocol = GDK_DRAG_PROTO_XDND; GDK_NOTE (DND, g_message ("Entering dnd window %#x\n", xid)); - return TRUE; + return retval; } - else if (motif_check_dest (xid)) + else if ((retval = motif_check_dest (xid))) { *protocol = GDK_DRAG_PROTO_MOTIF; GDK_NOTE (DND, g_message ("Entering motif window %#x\n", xid)); - return TRUE; + return retval; } else { @@ -2491,11 +2532,11 @@ gdk_drag_get_protocol (guint32 xid, if (rootwin) { *protocol = GDK_DRAG_PROTO_ROOTWIN; - return TRUE; + return xid; } } - return FALSE; + return GDK_NONE; } void @@ -2519,17 +2560,18 @@ gdk_drag_find_window (GdkDragContext *context, if (private->dest_xid != dest) { + Window recipient; private->dest_xid = dest; /* Check if new destination accepts drags, and which protocol */ - if (gdk_drag_get_protocol (dest, protocol)) + if ((recipient = gdk_drag_get_protocol (dest, protocol))) { - *dest_window = gdk_window_lookup (dest); + *dest_window = gdk_window_lookup (recipient); if (*dest_window) gdk_window_ref (*dest_window); else - *dest_window = gdk_window_foreign_new (dest); + *dest_window = gdk_window_foreign_new (recipient); } else *dest_window = NULL; diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c index c4dc41a078..9c088cbc62 100644 --- a/gdk/x11/gdkdnd-x11.c +++ b/gdk/x11/gdkdnd-x11.c @@ -1214,7 +1214,7 @@ motif_set_targets (GdkDragContext *context) private->motif_targets_set = 1; } -gboolean +guint32 motif_check_dest (Window win) { gboolean retval = FALSE; @@ -1225,7 +1225,7 @@ motif_check_dest (Window win) if (!motif_drag_receiver_info_atom) motif_drag_receiver_info_atom = gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE); - + XGetWindowProperty (gdk_display, win, motif_drag_receiver_info_atom, 0, (sizeof(*info)+3)/4, False, AnyPropertyType, @@ -1251,7 +1251,7 @@ motif_check_dest (Window win) XFree (info); } - return retval; + return retval ? win : GDK_NONE; } @@ -2098,7 +2098,7 @@ xdnd_send_motion (GdkDragContext *context, private->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; } -static gboolean +static guint32 xdnd_check_dest (Window win) { gboolean retval = FALSE; @@ -2106,31 +2106,70 @@ xdnd_check_dest (Window win) int format; unsigned long nitems, after; GdkAtom *version; + Window *proxy_data; + Window proxy; + static GdkAtom xdnd_proxy_atom = GDK_NONE; + + gint old_warnings = gdk_error_warnings; + + if (!xdnd_proxy_atom) + xdnd_proxy_atom = gdk_atom_intern ("XdndProxy", FALSE); if (!xdnd_aware_atom) xdnd_aware_atom = gdk_atom_intern ("XdndAware", FALSE); + proxy = GDK_NONE; + + gdk_error_code = 0; + gdk_error_warnings = 0; + XGetWindowProperty (gdk_display, win, - xdnd_aware_atom, 0, + xdnd_proxy_atom, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, - (guchar **)&version); - - if (type != None) - { - if ((format == 32) && (nitems == 1)) - { - if (*version == 3) - retval = TRUE; - } - else - GDK_NOTE (DND, - g_warning ("Invalid XdndAware property on window %ld\n", win)); + (guchar **)&proxy_data); - XFree (version); + if (!gdk_error_code) + { + if (type != None) + { + if ((format == 32) && (nitems == 1)) + { + proxy = *proxy_data; + } + else + GDK_NOTE (DND, + g_warning ("Invalid XdndOwner property on window %ld\n", win)); + + XFree (proxy_data); + } + + XGetWindowProperty (gdk_display, proxy ? proxy : win, + xdnd_aware_atom, 0, + 1, False, AnyPropertyType, + &type, &format, &nitems, &after, + (guchar **)&version); + + if (!gdk_error_code && type != None) + { + if ((format == 32) && (nitems == 1)) + { + if (*version == 3) + retval = TRUE; + } + else + GDK_NOTE (DND, + g_warning ("Invalid XdndAware property on window %ld\n", win)); + + XFree (version); + } + } - return retval; + gdk_error_warnings = old_warnings; + gdk_error_code = 0; + + return retval ? (proxy ? proxy : win) : GDK_NONE; } /* Target side */ @@ -2423,21 +2462,23 @@ gdk_drag_begin (GdkWindow *window, return new_context; } -gboolean +guint32 gdk_drag_get_protocol (guint32 xid, GdkDragProtocol *protocol) { - if (xdnd_check_dest (xid)) + guint32 retval; + + if ((retval = xdnd_check_dest (xid))) { *protocol = GDK_DRAG_PROTO_XDND; GDK_NOTE (DND, g_message ("Entering dnd window %#x\n", xid)); - return TRUE; + return retval; } - else if (motif_check_dest (xid)) + else if ((retval = motif_check_dest (xid))) { *protocol = GDK_DRAG_PROTO_MOTIF; GDK_NOTE (DND, g_message ("Entering motif window %#x\n", xid)); - return TRUE; + return retval; } else { @@ -2491,11 +2532,11 @@ gdk_drag_get_protocol (guint32 xid, if (rootwin) { *protocol = GDK_DRAG_PROTO_ROOTWIN; - return TRUE; + return xid; } } - return FALSE; + return GDK_NONE; } void @@ -2519,17 +2560,18 @@ gdk_drag_find_window (GdkDragContext *context, if (private->dest_xid != dest) { + Window recipient; private->dest_xid = dest; /* Check if new destination accepts drags, and which protocol */ - if (gdk_drag_get_protocol (dest, protocol)) + if ((recipient = gdk_drag_get_protocol (dest, protocol))) { - *dest_window = gdk_window_lookup (dest); + *dest_window = gdk_window_lookup (recipient); if (*dest_window) gdk_window_ref (*dest_window); else - *dest_window = gdk_window_foreign_new (dest); + *dest_window = gdk_window_foreign_new (recipient); } else *dest_window = NULL; diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 04909165af..71866638f8 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -121,6 +121,7 @@ struct _GtkDragFindData { GdkDragContext *context; GtkDragDestInfo *info; gboolean found; + gboolean toplevel; gboolean (*callback) (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint32 time); guint32 time; @@ -829,9 +830,10 @@ gtk_drag_dest_handle_event (GtkWidget *toplevel, data.x = event->dnd.x_root - tx; data.y = event->dnd.y_root - ty; - data.context = context; + data.context = context; data.info = info; data.found = FALSE; + data.toplevel = TRUE; data.callback = (event->type == GDK_DRAG_MOTION) ? gtk_drag_dest_motion : gtk_drag_dest_drop; data.time = event->dnd.time; @@ -1048,9 +1050,10 @@ gtk_drag_find_widget (GtkWidget *widget, } } - if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) && - (data->x < new_allocation.x + new_allocation.width) && - (data->y < new_allocation.y + new_allocation.height)) + if (data->toplevel || + ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) && + (data->x < new_allocation.x + new_allocation.width) && + (data->y < new_allocation.y + new_allocation.height))) { /* First, check if the drag is in a valid drop site in * one of our children @@ -1062,6 +1065,7 @@ gtk_drag_find_widget (GtkWidget *widget, new_data.x -= x_offset; new_data.y -= y_offset; new_data.found = FALSE; + new_data.toplevel = FALSE; gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback)gtk_drag_find_widget,