diff options
author | Owen Taylor <otaylor@redhat.com> | 1999-01-28 01:03:15 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1999-01-28 01:03:15 +0000 |
commit | 77e99440df31909f584f660de762783a467a14c4 (patch) | |
tree | 8be59e235d1d1f40ada467a830a603b54ebb48f1 | |
parent | 4998934dcba802627c798b981ef271ec6cd29880 (diff) | |
download | gdk-pixbuf-77e99440df31909f584f660de762783a467a14c4.tar.gz |
Change signatures for gdk_drag_begin() and gdk_drag_motion() so that the
Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdk.h gdk/gdkdnd.c: Change signatures for
gdk_drag_begin() and gdk_drag_motion() so that the set
of possible actions is passed on each motion, not just at
the beginning of the drag. We do this so that
we can restrict the set of possible drag events
when the user presses a modifier key during a
drag.
* gdk/gdkdnd.c: Send a motif Operation-changed
message when the set of possible actions change,
as well as when the suggested action change.
* gdk/gdkdnd.c: Change the XdndActionList whenever
the set of actions change.
* gdk/gdkdnd.c: Add a filter to catch changes to
the XdndActionList property for the source widget.
* gtk/gtkdnd.c: Change the set of possible actions
when the user presses Control, Shift, or Control-Shift,
to only include the corresponding action.
* gtk/gtkdnd.c (gtk_drag_button_release_cb):
Disconnect button signals before we possibly
free info structure.
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 33 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 33 | ||||
-rw-r--r-- | gdk/gdk.h | 6 | ||||
-rw-r--r-- | gdk/gdkdnd.c | 230 | ||||
-rw-r--r-- | gdk/x11/gdkdnd-x11.c | 230 | ||||
-rw-r--r-- | gtk/gtkdnd.c | 117 |
11 files changed, 659 insertions, 155 deletions
@@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 2b4f31237..899805c7b 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,36 @@ +Wed Jan 27 20:06:06 1999 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklayout.c (gtk_layout_adjustment_changed): + Removed some g_print()'s + +Wed Jan 27 18:57:57 1999 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.h gdk/gdkdnd.c: Change signatures for + gdk_drag_begin() and gdk_drag_motion() so that the set + of possible actions is passed on each motion, not just at + the beginning of the drag. We do this so that + we can restrict the set of possible drag events + when the user presses a modifier key during a + drag. + + * gdk/gdkdnd.c: Send a motif Operation-changed + message when the set of possible actions change, + as well as when the suggested action change. + + * gdk/gdkdnd.c: Change the XdndActionList whenever + the set of actions change. + + * gdk/gdkdnd.c: Add a filter to catch changes to + the XdndActionList property for the source widget. + + * gtk/gtkdnd.c: Change the set of possible actions + when the user presses Control, Shift, or Control-Shift, + to only include the corresponding action. + + * gtk/gtkdnd.c (gtk_drag_button_release_cb): + Disconnect button signals before we possibly + free info structure. + Wed Jan 27 18:40:50 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkmain.c (gtk_main_do_event): Hack scrollwheel @@ -262,8 +262,7 @@ GdkAtom gdk_drag_get_selection (GdkDragContext *context); /* Source side */ GdkDragContext * gdk_drag_begin (GdkWindow *window, - GList *targets, - GdkDragAction actions); + GList *targets); guint32 gdk_drag_get_protocol (guint32 xid, GdkDragProtocol *protocol); void gdk_drag_find_window (GdkDragContext *context, @@ -277,7 +276,8 @@ gboolean gdk_drag_motion (GdkDragContext *context, GdkDragProtocol protocol, gint x_root, gint y_root, - GdkDragAction action, + GdkDragAction suggested_action, + GdkDragAction possible_actions, guint32 time); void gdk_drag_drop (GdkDragContext *context, guint32 time); diff --git a/gdk/gdkdnd.c b/gdk/gdkdnd.c index 7c951e986..a4244bd35 100644 --- a/gdk/gdkdnd.c +++ b/gdk/gdkdnd.c @@ -56,11 +56,13 @@ struct _GdkDragContextPrivate { guint16 last_x; /* Coordinates from last event */ guint16 last_y; - GdkDragAction old_action; /* The last action we sent to the source */ + GdkDragAction old_action; /* The last action we sent to the source */ + GdkDragAction old_actions; /* The last actions we sent to the source */ + GdkDragAction xdnd_actions; /* What is currently set in XdndActionList */ Window dest_xid; guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */ - guint xdnd_actions_set : 1; /* Whether we've already set XdndActionsList */ + guint xdnd_actions_set : 1; /* Whether we've already set XdndActionList */ guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */ guint motif_targets_set : 1; /* Whether we've already set motif initiator info */ guint drag_status : 4; /* current status of drag */ @@ -103,6 +105,10 @@ static GdkFilterReturn xdnd_drop_filter (GdkXEvent *xev, GdkEvent *event, gpointer data); +static void xdnd_manage_source_filter (GdkDragContext *context, + GdkWindow *window, + gboolean add_filter); + /* Drag Contexts */ static GList *contexts; @@ -145,7 +151,13 @@ gdk_drag_context_unref (GdkDragContext *context) g_list_free (context->targets); if (context->source_window) - gdk_window_unref (context->source_window); + { + if ((context->protocol == GDK_DRAG_PROTO_XDND) && + !context->is_source) + xdnd_manage_source_filter (context, context->source_window, FALSE); + + gdk_window_unref (context->source_window); + } if (context->dest_window) gdk_window_unref (context->dest_window); @@ -1361,11 +1373,12 @@ motif_send_motion (GdkDragContext *context, MOTIF_XCLIENT_SHORT (&xev, 1) = motif_dnd_get_flags (context); MOTIF_XCLIENT_LONG (&xev, 1) = time; - if (context->suggested_action != private->old_action) + if ((context->suggested_action != private->old_action) || + (context->actions != private->old_actions)) { MOTIF_XCLIENT_BYTE (&xev, 0) = XmOPERATION_CHANGED; - private->drag_status = GDK_DRAG_STATUS_ACTION_WAIT; + /* private->drag_status = GDK_DRAG_STATUS_ACTION_WAIT; */ retval = TRUE; } else @@ -1724,7 +1737,8 @@ motif_drag_status (GdkEvent *event, if (context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; - if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) + if ((private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) || + (private->drag_status == GDK_DRAG_STATUS_ACTION_WAIT)) private->drag_status = GDK_DRAG_STATUS_DRAG; event->dnd.type = GDK_DRAG_STATUS; @@ -2009,7 +2023,7 @@ xdnd_set_actions (GdkDragContext *context) if (!xdnd_actions_initialized) xdnd_initialize_actions(); - + actions = context->actions; n_atoms = 0; for (i=0; i<xdnd_n_actions; i++) @@ -2042,6 +2056,7 @@ xdnd_set_actions (GdkDragContext *context) (guchar *)atomlist, n_atoms); private->xdnd_actions_set = 1; + private->xdnd_actions = context->actions; } static void @@ -2082,9 +2097,6 @@ xdnd_send_enter (GdkDragContext *context) } } - if (!private->xdnd_actions_set) - xdnd_set_actions (context); - if (!gdk_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, 0, &xev)) { @@ -2256,6 +2268,133 @@ xdnd_check_dest (Window win) /* Target side */ +static void +xdnd_read_actions (GdkDragContext *context) +{ + Atom type; + int format; + gulong nitems, after; + Atom *data; + + gint i; + + gint old_warnings = gdk_error_warnings; + + gdk_error_code = 0; + gdk_error_warnings = 0; + + /* Get the XdndActionList, if set */ + + XGetWindowProperty (GDK_WINDOW_XDISPLAY (context->source_window), + GDK_WINDOW_XWINDOW (context->source_window), + gdk_atom_intern ("XdndActionList", FALSE), 0, 65536, + False, XA_ATOM, &type, &format, &nitems, + &after, (guchar **)&data); + + if (!gdk_error_code && (format == 32) && (type == XA_ATOM)) + { + context->actions = 0; + + for (i=0; i<nitems; i++) + context->actions |= xdnd_action_from_atom (data[i]); + + ((GdkDragContextPrivate *)context)->xdnd_have_actions = TRUE; + +#ifdef G_ENABLE_DEBUG + if (gdk_debug_flags & GDK_DEBUG_DND) + { + GString *action_str = g_string_new (NULL); + if (context->actions & GDK_ACTION_MOVE) + g_string_append(action_str, "MOVE "); + if (context->actions & GDK_ACTION_COPY) + g_string_append(action_str, "COPY "); + if (context->actions & GDK_ACTION_LINK) + g_string_append(action_str, "LINK "); + if (context->actions & GDK_ACTION_ASK) + g_string_append(action_str, "ASK "); + + g_message("Xdnd actions = %s", action_str->str); + g_string_free (action_str, TRUE); + } +#endif /* G_ENABLE_DEBUG */ + + XFree(data); + } + + gdk_error_warnings = old_warnings; + gdk_error_code = 0; +} + +/* We have to make sure that the XdndActionList we keep internally + * is up to date with the XdndActionList on the source window + * because we get no notification, because Xdnd wasn't meant + * to continually send actions. So we select on PropertyChangeMask + * and add this filter. + */ +static GdkFilterReturn +xdnd_source_window_filter (GdkXEvent *xev, + GdkEvent *event, + gpointer cb_data) +{ + XEvent *xevent = (XEvent *)xev; + GdkDragContext *context = cb_data; + + if ((xevent->xany.type == PropertyNotify) && + (xevent->xproperty.atom == gdk_atom_intern ("XdndActionList", FALSE))) + { + xdnd_read_actions (context); + + return GDK_FILTER_REMOVE; + } + + return GDK_FILTER_CONTINUE; +} + +static void +xdnd_manage_source_filter (GdkDragContext *context, + GdkWindow *window, + gboolean add_filter) +{ + gint old_warnings = 0; /* quiet gcc */ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + + gboolean is_foreign = (private->window_type == GDK_WINDOW_FOREIGN); + + if (is_foreign) + { + old_warnings = gdk_error_warnings; + gdk_error_warnings = 0; + } + + if (!private->destroyed) + { + if (add_filter) + { + gdk_window_set_events (window, + gdk_window_get_events (window) | + GDK_PROPERTY_CHANGE_MASK); + gdk_window_add_filter (window, xdnd_source_window_filter, context); + + } + else + { + gdk_window_remove_filter (window, + xdnd_source_window_filter, + context); + /* Should we remove the GDK_PROPERTY_NOTIFY mask? + * but we might want it for other reasons. (Like + * INCR selection transactions). + */ + } + } + + if (is_foreign) + { + gdk_flush(); + gdk_error_warnings = old_warnings; + } +} + static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev, GdkEvent *event, @@ -2339,49 +2478,14 @@ xdnd_enter_filter (GdkXEvent *xev, GUINT_TO_POINTER (xevent->xclient.data.l[2+i])); } - /* Get the XdndActionList, if set */ - - XGetWindowProperty (GDK_WINDOW_XDISPLAY (event->any.window), - source_window, - gdk_atom_intern ("XdndActionList", FALSE), 0, 65536, - False, XA_ATOM, &type, &format, &nitems, - &after, (guchar **)&data); - - if ((format == 32) && (type == XA_ATOM)) - { - new_context->actions = 0; - - for (i=0; i<nitems; i++) - new_context->actions |= xdnd_action_from_atom (data[i]); - - ((GdkDragContextPrivate *)new_context)->xdnd_have_actions = TRUE; - -#ifdef G_ENABLE_DEBUG - if (gdk_debug_flags & GDK_DEBUG_DND) - { - GString *action_str = g_string_new (NULL); - if (new_context->actions & GDK_ACTION_MOVE) - g_string_append(action_str, "MOVE "); - if (new_context->actions & GDK_ACTION_COPY) - g_string_append(action_str, "COPY "); - if (new_context->actions & GDK_ACTION_LINK) - g_string_append(action_str, "LINK "); - if (new_context->actions & GDK_ACTION_ASK) - g_string_append(action_str, "ASK "); - - g_message("\tactions = %s", action_str->str); - g_string_free (action_str, TRUE); - } -#endif /* G_ENABLE_DEBUG */ - - XFree(data); - } - #ifdef G_ENABLE_DEBUG if (gdk_debug_flags & GDK_DEBUG_DND) print_target_list (new_context->targets); #endif /* G_ENABLE_DEBUG */ + xdnd_manage_source_filter (new_context, new_context->source_window, TRUE); + xdnd_read_actions (new_context); + event->dnd.type = GDK_DRAG_ENTER; event->dnd.context = new_context; gdk_drag_context_ref (new_context); @@ -2558,8 +2662,7 @@ gdk_drag_do_leave (GdkDragContext *context, guint32 time) GdkDragContext * gdk_drag_begin (GdkWindow *window, - GList *targets, - GdkDragAction actions) + GList *targets) { GList *tmp_list; GdkDragContext *new_context; @@ -2580,7 +2683,7 @@ gdk_drag_begin (GdkWindow *window, tmp_list = tmp_list->prev; } - new_context->actions = actions; + new_context->actions = 0; return new_context; } @@ -2717,13 +2820,25 @@ gdk_drag_motion (GdkDragContext *context, GdkDragProtocol protocol, gint x_root, gint y_root, - GdkDragAction action, + GdkDragAction suggested_action, + GdkDragAction possible_actions, guint32 time) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; g_return_val_if_fail (context != NULL, FALSE); + /* When we have a Xdnd target, make sure our XdndActionList + * matches the current actions; + */ + private->old_actions = context->actions; + context->actions = possible_actions; + + if ((protocol == GDK_DRAG_PROTO_XDND) && + (!private->xdnd_actions_set || + private->xdnd_actions != possible_actions)) + xdnd_set_actions (context); + if (context->dest_window != dest_window) { GdkEvent temp_event; @@ -2754,8 +2869,9 @@ gdk_drag_motion (GdkDragContext *context, case GDK_DRAG_PROTO_NONE: break; } - private->old_action = action; - context->suggested_action = action; + private->old_action = suggested_action; + context->suggested_action = suggested_action; + private->old_actions = possible_actions; } else { @@ -2782,7 +2898,7 @@ gdk_drag_motion (GdkDragContext *context, else { private->old_action = context->suggested_action; - context->suggested_action = action; + context->suggested_action = suggested_action; } /* Send a drag-motion event */ @@ -2797,11 +2913,11 @@ gdk_drag_motion (GdkDragContext *context, switch (context->protocol) { case GDK_DRAG_PROTO_MOTIF: - motif_send_motion (context, x_root, y_root, action, time); + motif_send_motion (context, x_root, y_root, suggested_action, time); break; case GDK_DRAG_PROTO_XDND: - xdnd_send_motion (context, x_root, y_root, action, time); + xdnd_send_motion (context, x_root, y_root, suggested_action, time); break; case GDK_DRAG_PROTO_ROOTWIN: diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c index 7c951e986..a4244bd35 100644 --- a/gdk/x11/gdkdnd-x11.c +++ b/gdk/x11/gdkdnd-x11.c @@ -56,11 +56,13 @@ struct _GdkDragContextPrivate { guint16 last_x; /* Coordinates from last event */ guint16 last_y; - GdkDragAction old_action; /* The last action we sent to the source */ + GdkDragAction old_action; /* The last action we sent to the source */ + GdkDragAction old_actions; /* The last actions we sent to the source */ + GdkDragAction xdnd_actions; /* What is currently set in XdndActionList */ Window dest_xid; guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */ - guint xdnd_actions_set : 1; /* Whether we've already set XdndActionsList */ + guint xdnd_actions_set : 1; /* Whether we've already set XdndActionList */ guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */ guint motif_targets_set : 1; /* Whether we've already set motif initiator info */ guint drag_status : 4; /* current status of drag */ @@ -103,6 +105,10 @@ static GdkFilterReturn xdnd_drop_filter (GdkXEvent *xev, GdkEvent *event, gpointer data); +static void xdnd_manage_source_filter (GdkDragContext *context, + GdkWindow *window, + gboolean add_filter); + /* Drag Contexts */ static GList *contexts; @@ -145,7 +151,13 @@ gdk_drag_context_unref (GdkDragContext *context) g_list_free (context->targets); if (context->source_window) - gdk_window_unref (context->source_window); + { + if ((context->protocol == GDK_DRAG_PROTO_XDND) && + !context->is_source) + xdnd_manage_source_filter (context, context->source_window, FALSE); + + gdk_window_unref (context->source_window); + } if (context->dest_window) gdk_window_unref (context->dest_window); @@ -1361,11 +1373,12 @@ motif_send_motion (GdkDragContext *context, MOTIF_XCLIENT_SHORT (&xev, 1) = motif_dnd_get_flags (context); MOTIF_XCLIENT_LONG (&xev, 1) = time; - if (context->suggested_action != private->old_action) + if ((context->suggested_action != private->old_action) || + (context->actions != private->old_actions)) { MOTIF_XCLIENT_BYTE (&xev, 0) = XmOPERATION_CHANGED; - private->drag_status = GDK_DRAG_STATUS_ACTION_WAIT; + /* private->drag_status = GDK_DRAG_STATUS_ACTION_WAIT; */ retval = TRUE; } else @@ -1724,7 +1737,8 @@ motif_drag_status (GdkEvent *event, if (context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; - if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) + if ((private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) || + (private->drag_status == GDK_DRAG_STATUS_ACTION_WAIT)) private->drag_status = GDK_DRAG_STATUS_DRAG; event->dnd.type = GDK_DRAG_STATUS; @@ -2009,7 +2023,7 @@ xdnd_set_actions (GdkDragContext *context) if (!xdnd_actions_initialized) xdnd_initialize_actions(); - + actions = context->actions; n_atoms = 0; for (i=0; i<xdnd_n_actions; i++) @@ -2042,6 +2056,7 @@ xdnd_set_actions (GdkDragContext *context) (guchar *)atomlist, n_atoms); private->xdnd_actions_set = 1; + private->xdnd_actions = context->actions; } static void @@ -2082,9 +2097,6 @@ xdnd_send_enter (GdkDragContext *context) } } - if (!private->xdnd_actions_set) - xdnd_set_actions (context); - if (!gdk_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, 0, &xev)) { @@ -2256,6 +2268,133 @@ xdnd_check_dest (Window win) /* Target side */ +static void +xdnd_read_actions (GdkDragContext *context) +{ + Atom type; + int format; + gulong nitems, after; + Atom *data; + + gint i; + + gint old_warnings = gdk_error_warnings; + + gdk_error_code = 0; + gdk_error_warnings = 0; + + /* Get the XdndActionList, if set */ + + XGetWindowProperty (GDK_WINDOW_XDISPLAY (context->source_window), + GDK_WINDOW_XWINDOW (context->source_window), + gdk_atom_intern ("XdndActionList", FALSE), 0, 65536, + False, XA_ATOM, &type, &format, &nitems, + &after, (guchar **)&data); + + if (!gdk_error_code && (format == 32) && (type == XA_ATOM)) + { + context->actions = 0; + + for (i=0; i<nitems; i++) + context->actions |= xdnd_action_from_atom (data[i]); + + ((GdkDragContextPrivate *)context)->xdnd_have_actions = TRUE; + +#ifdef G_ENABLE_DEBUG + if (gdk_debug_flags & GDK_DEBUG_DND) + { + GString *action_str = g_string_new (NULL); + if (context->actions & GDK_ACTION_MOVE) + g_string_append(action_str, "MOVE "); + if (context->actions & GDK_ACTION_COPY) + g_string_append(action_str, "COPY "); + if (context->actions & GDK_ACTION_LINK) + g_string_append(action_str, "LINK "); + if (context->actions & GDK_ACTION_ASK) + g_string_append(action_str, "ASK "); + + g_message("Xdnd actions = %s", action_str->str); + g_string_free (action_str, TRUE); + } +#endif /* G_ENABLE_DEBUG */ + + XFree(data); + } + + gdk_error_warnings = old_warnings; + gdk_error_code = 0; +} + +/* We have to make sure that the XdndActionList we keep internally + * is up to date with the XdndActionList on the source window + * because we get no notification, because Xdnd wasn't meant + * to continually send actions. So we select on PropertyChangeMask + * and add this filter. + */ +static GdkFilterReturn +xdnd_source_window_filter (GdkXEvent *xev, + GdkEvent *event, + gpointer cb_data) +{ + XEvent *xevent = (XEvent *)xev; + GdkDragContext *context = cb_data; + + if ((xevent->xany.type == PropertyNotify) && + (xevent->xproperty.atom == gdk_atom_intern ("XdndActionList", FALSE))) + { + xdnd_read_actions (context); + + return GDK_FILTER_REMOVE; + } + + return GDK_FILTER_CONTINUE; +} + +static void +xdnd_manage_source_filter (GdkDragContext *context, + GdkWindow *window, + gboolean add_filter) +{ + gint old_warnings = 0; /* quiet gcc */ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + + gboolean is_foreign = (private->window_type == GDK_WINDOW_FOREIGN); + + if (is_foreign) + { + old_warnings = gdk_error_warnings; + gdk_error_warnings = 0; + } + + if (!private->destroyed) + { + if (add_filter) + { + gdk_window_set_events (window, + gdk_window_get_events (window) | + GDK_PROPERTY_CHANGE_MASK); + gdk_window_add_filter (window, xdnd_source_window_filter, context); + + } + else + { + gdk_window_remove_filter (window, + xdnd_source_window_filter, + context); + /* Should we remove the GDK_PROPERTY_NOTIFY mask? + * but we might want it for other reasons. (Like + * INCR selection transactions). + */ + } + } + + if (is_foreign) + { + gdk_flush(); + gdk_error_warnings = old_warnings; + } +} + static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev, GdkEvent *event, @@ -2339,49 +2478,14 @@ xdnd_enter_filter (GdkXEvent *xev, GUINT_TO_POINTER (xevent->xclient.data.l[2+i])); } - /* Get the XdndActionList, if set */ - - XGetWindowProperty (GDK_WINDOW_XDISPLAY (event->any.window), - source_window, - gdk_atom_intern ("XdndActionList", FALSE), 0, 65536, - False, XA_ATOM, &type, &format, &nitems, - &after, (guchar **)&data); - - if ((format == 32) && (type == XA_ATOM)) - { - new_context->actions = 0; - - for (i=0; i<nitems; i++) - new_context->actions |= xdnd_action_from_atom (data[i]); - - ((GdkDragContextPrivate *)new_context)->xdnd_have_actions = TRUE; - -#ifdef G_ENABLE_DEBUG - if (gdk_debug_flags & GDK_DEBUG_DND) - { - GString *action_str = g_string_new (NULL); - if (new_context->actions & GDK_ACTION_MOVE) - g_string_append(action_str, "MOVE "); - if (new_context->actions & GDK_ACTION_COPY) - g_string_append(action_str, "COPY "); - if (new_context->actions & GDK_ACTION_LINK) - g_string_append(action_str, "LINK "); - if (new_context->actions & GDK_ACTION_ASK) - g_string_append(action_str, "ASK "); - - g_message("\tactions = %s", action_str->str); - g_string_free (action_str, TRUE); - } -#endif /* G_ENABLE_DEBUG */ - - XFree(data); - } - #ifdef G_ENABLE_DEBUG if (gdk_debug_flags & GDK_DEBUG_DND) print_target_list (new_context->targets); #endif /* G_ENABLE_DEBUG */ + xdnd_manage_source_filter (new_context, new_context->source_window, TRUE); + xdnd_read_actions (new_context); + event->dnd.type = GDK_DRAG_ENTER; event->dnd.context = new_context; gdk_drag_context_ref (new_context); @@ -2558,8 +2662,7 @@ gdk_drag_do_leave (GdkDragContext *context, guint32 time) GdkDragContext * gdk_drag_begin (GdkWindow *window, - GList *targets, - GdkDragAction actions) + GList *targets) { GList *tmp_list; GdkDragContext *new_context; @@ -2580,7 +2683,7 @@ gdk_drag_begin (GdkWindow *window, tmp_list = tmp_list->prev; } - new_context->actions = actions; + new_context->actions = 0; return new_context; } @@ -2717,13 +2820,25 @@ gdk_drag_motion (GdkDragContext *context, GdkDragProtocol protocol, gint x_root, gint y_root, - GdkDragAction action, + GdkDragAction suggested_action, + GdkDragAction possible_actions, guint32 time) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; g_return_val_if_fail (context != NULL, FALSE); + /* When we have a Xdnd target, make sure our XdndActionList + * matches the current actions; + */ + private->old_actions = context->actions; + context->actions = possible_actions; + + if ((protocol == GDK_DRAG_PROTO_XDND) && + (!private->xdnd_actions_set || + private->xdnd_actions != possible_actions)) + xdnd_set_actions (context); + if (context->dest_window != dest_window) { GdkEvent temp_event; @@ -2754,8 +2869,9 @@ gdk_drag_motion (GdkDragContext *context, case GDK_DRAG_PROTO_NONE: break; } - private->old_action = action; - context->suggested_action = action; + private->old_action = suggested_action; + context->suggested_action = suggested_action; + private->old_actions = possible_actions; } else { @@ -2782,7 +2898,7 @@ gdk_drag_motion (GdkDragContext *context, else { private->old_action = context->suggested_action; - context->suggested_action = action; + context->suggested_action = suggested_action; } /* Send a drag-motion event */ @@ -2797,11 +2913,11 @@ gdk_drag_motion (GdkDragContext *context, switch (context->protocol) { case GDK_DRAG_PROTO_MOTIF: - motif_send_motion (context, x_root, y_root, action, time); + motif_send_motion (context, x_root, y_root, suggested_action, time); break; case GDK_DRAG_PROTO_XDND: - xdnd_send_motion (context, x_root, y_root, action, time); + xdnd_send_motion (context, x_root, y_root, suggested_action, time); break; case GDK_DRAG_PROTO_ROOTWIN: diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 1c5efd714..8ffdd2abf 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -58,6 +58,7 @@ struct _GtkDragSourceSite { struct _GtkDragSourceInfo { GtkWidget *widget; GtkTargetList *target_list; /* Targets for drag data */ + GdkDragAction possible_actions; /* Actions allowed by source */ GdkDragContext *context; /* drag context */ GtkWidget *icon_window; /* Window for drag */ GtkWidget *ipc_widget; /* GtkInvisible for grab, message passing */ @@ -145,9 +146,11 @@ static gint default_icon_hot_x; static gint default_icon_hot_y; /* Forward declarations */ -static GdkDragAction gtk_drag_get_event_action (GdkEvent *event, - gint button, - GdkDragAction actions); +static void gtk_drag_get_event_actions (GdkEvent *event, + gint button, + GdkDragAction actions, + GdkDragAction *suggested_action, + GdkDragAction *possible_actions); static GdkCursor * gtk_drag_get_cursor (GdkDragAction action); static GtkWidget *gtk_drag_get_ipc_widget (void); static void gtk_drag_release_ipc_widget (GtkWidget *widget); @@ -391,9 +394,16 @@ gtk_drag_release_ipc_widget (GtkWidget *widget) drag_widgets = g_slist_prepend (drag_widgets, widget); } -static GdkDragAction -gtk_drag_get_event_action (GdkEvent *event, gint button, GdkDragAction actions) +static void +gtk_drag_get_event_actions (GdkEvent *event, + gint button, + GdkDragAction actions, + GdkDragAction *suggested_action, + GdkDragAction *possible_actions) { + *suggested_action = 0; + *possible_actions = 0; + if (event) { GdkModifierType state = 0; @@ -422,32 +432,55 @@ gtk_drag_get_event_action (GdkEvent *event, gint button, GdkDragAction actions) } if (((button == 2) || (button == 3)) && (actions & GDK_ACTION_ASK)) - return GDK_ACTION_ASK; - - if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) + { + *suggested_action = GDK_ACTION_ASK; + *possible_actions = actions; + } + else if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) { if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK)) - return (actions & GDK_ACTION_LINK) ? GDK_ACTION_LINK : 0; + { + if (actions & GDK_ACTION_LINK) + { + *suggested_action = GDK_ACTION_LINK; + *possible_actions = GDK_ACTION_LINK; + } + } else if (state & GDK_CONTROL_MASK) - return (actions & GDK_ACTION_COPY) ? GDK_ACTION_COPY : 0; + { + if (actions & GDK_ACTION_COPY) + { + *suggested_action = GDK_ACTION_COPY; + *possible_actions = GDK_ACTION_COPY; + } + return; + } else - return (actions & GDK_ACTION_MOVE) ? GDK_ACTION_MOVE : 0; + { + if (actions & GDK_ACTION_MOVE) + { + *suggested_action = GDK_ACTION_MOVE; + *possible_actions = GDK_ACTION_MOVE; + } + return; + } } else { - if ((state & (GDK_MOD1_MASK)) && (actions & GDK_ACTION_ASK)) - return GDK_ACTION_ASK; + *possible_actions = actions; - if (actions & GDK_ACTION_COPY) - return GDK_ACTION_COPY; + if ((state & (GDK_MOD1_MASK)) && (actions & GDK_ACTION_ASK)) + *suggested_action = GDK_ACTION_ASK; + else if (actions & GDK_ACTION_COPY) + *suggested_action = GDK_ACTION_COPY; else if (actions & GDK_ACTION_MOVE) - return GDK_ACTION_MOVE; + *suggested_action = GDK_ACTION_MOVE; else if (actions & GDK_ACTION_LINK) - return GDK_ACTION_LINK; + *suggested_action = GDK_ACTION_LINK; } } - return 0; + return; } static GdkCursor * @@ -1164,8 +1197,7 @@ gtk_drag_proxy_begin (GtkWidget *widget, GtkDragDestInfo *dest_info) source_info->widget = widget; gtk_widget_ref (source_info->widget); source_info->context = gdk_drag_begin (source_info->ipc_widget->window, - dest_info->context->targets, - dest_info->context->actions); + dest_info->context->targets); source_info->target_list = gtk_target_list_new (NULL, 0); tmp_list = dest_info->context->targets; @@ -1295,7 +1327,8 @@ gtk_drag_dest_motion (GtkWidget *widget, dest_window, proto, current_event->dnd.x_root, current_event->dnd.y_root, - context->suggested_action, time); + context->suggested_action, + context->actions, time); selection = gdk_drag_get_selection (info->proxy_source->context); if (selection && @@ -1411,7 +1444,8 @@ gtk_drag_dest_drop (GtkWidget *widget, dest_window, proto, current_event->dnd.x_root, current_event->dnd.y_root, - context->suggested_action, time); + context->suggested_action, + context->actions, time); selection = gdk_drag_get_selection (info->proxy_source->context); if (selection && @@ -1472,6 +1506,7 @@ gtk_drag_begin (GtkWidget *widget, GList *targets = NULL; GList *tmp_list; guint32 time = GDK_CURRENT_TIME; + GdkDragAction possible_actions, suggested_action; g_return_val_if_fail (widget != NULL, NULL); g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL); @@ -1498,8 +1533,7 @@ gtk_drag_begin (GtkWidget *widget, info->widget = widget; gtk_widget_ref (info->widget); - info->context = gdk_drag_begin (info->ipc_widget->window, - targets, actions); + info->context = gdk_drag_begin (info->ipc_widget->window, targets); g_list_free (targets); g_dataset_set_data (info->context, "gtk-info", info); @@ -1508,15 +1542,19 @@ gtk_drag_begin (GtkWidget *widget, info->target_list = target_list; gtk_target_list_ref (target_list); + info->possible_actions = actions; + info->cursor = NULL; info->status = GTK_DRAG_STATUS_DRAG; info->last_event = NULL; info->selections = NULL; info->icon_window = NULL; + + gtk_drag_get_event_actions (event, info->button, actions, + &suggested_action, &possible_actions); if (event) - info->cursor = gtk_drag_get_cursor ( - gtk_drag_get_event_action (event, info->button, 0)); + info->cursor = gtk_drag_get_cursor (suggested_action); gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_begin", info->context); @@ -2371,6 +2409,7 @@ gtk_drag_motion_cb (GtkWidget *widget, GtkDragSourceInfo *info = (GtkDragSourceInfo *)data; GdkAtom selection; GdkDragAction action; + GdkDragAction possible_actions; GdkWindow *window = NULL; GdkWindow *dest_window; GdkDragProtocol protocol; @@ -2383,9 +2422,10 @@ gtk_drag_motion_cb (GtkWidget *widget, event->y_root = y_root; } - action = gtk_drag_get_event_action ((GdkEvent *)event, - info->button, - info->context->actions); + gtk_drag_get_event_actions ((GdkEvent *)event, + info->button, + info->possible_actions, + &action, &possible_actions); info->cur_x = event->x_root - info->hot_x; info->cur_y = event->y_root - info->hot_y; @@ -2402,7 +2442,8 @@ gtk_drag_motion_cb (GtkWidget *widget, &dest_window, &protocol); if (gdk_drag_motion (info->context, dest_window, protocol, - event->x_root, event->y_root, action, + event->x_root, event->y_root, action, + possible_actions, event->time)) { if (info->last_event) @@ -2452,6 +2493,14 @@ gtk_drag_button_release_cb (GtkWidget *widget, gdk_pointer_ungrab (event->time); + gtk_grab_remove (widget); + gtk_signal_disconnect_by_func (GTK_OBJECT (widget), + GTK_SIGNAL_FUNC (gtk_drag_button_release_cb), + info); + gtk_signal_disconnect_by_func (GTK_OBJECT (widget), + GTK_SIGNAL_FUNC (gtk_drag_motion_cb), + info); + if ((info->context->action != 0) && (info->context->dest_window != NULL)) { gtk_drag_drop (info, event->time); @@ -2462,14 +2511,6 @@ gtk_drag_button_release_cb (GtkWidget *widget, gtk_drag_drop_finished (info, FALSE, event->time); } - gtk_grab_remove (widget); - gtk_signal_disconnect_by_func (GTK_OBJECT (widget), - GTK_SIGNAL_FUNC (gtk_drag_button_release_cb), - info); - gtk_signal_disconnect_by_func (GTK_OBJECT (widget), - GTK_SIGNAL_FUNC (gtk_drag_motion_cb), - info); - /* Send on a release pair to the the original * widget to convince it to release its grab. We need to * call gtk_propagate_event() here, instead of |