diff --git a/ChangeLog b/ChangeLog index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 0b4468d5a3fffa798327acd631325f08b7b3d9cc..4a3ed3a0a89e3fc92150762eceef9e1967b26f41 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,11 @@ +Thu Jan 21 02:11:44 1999 Owen Taylor + + * Set and read the XdndActionList property defined + in the Xdnd spec. We do this always, not just for + XdndActionAsk like the spec says, but if we don't + find it, we fall back to actions = suggested_action, + which is compatible with the language of the spec. + Thu Jan 21 01:15:28 1999 Jeff Garzik * gdk/gdkdnd.c (gdk_drag_context_unref): diff --git a/gdk/gdkdnd.c b/gdk/gdkdnd.c index b2653628a5d5c0232485123267aed9c487a32a66..fd5a26564f44669a97e285ddc9109b64ad20554c 100644 --- a/gdk/gdkdnd.c +++ b/gdk/gdkdnd.c @@ -60,6 +60,8 @@ struct _GdkDragContextPrivate { 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_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 */ @@ -1953,16 +1955,16 @@ static void xdnd_set_targets (GdkDragContext *context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; - GdkAtom *typelist; + GdkAtom *atomlist; GList *tmp_list = context->targets; gint i; - gint n_targets = g_list_length (context->targets); + gint n_atoms = g_list_length (context->targets); - typelist = g_new (GdkAtom, n_targets); + atomlist = g_new (GdkAtom, n_atoms); i = 0; while (tmp_list) { - typelist[i] = GPOINTER_TO_INT (tmp_list->data); + atomlist[i] = GPOINTER_TO_INT (tmp_list->data); tmp_list = tmp_list->next; i++; } @@ -1971,11 +1973,57 @@ xdnd_set_targets (GdkDragContext *context) GDK_WINDOW_XWINDOW (context->source_window), gdk_atom_intern ("XdndTypeList", FALSE), XA_ATOM, 32, PropModeReplace, - (guchar *)typelist, n_targets); + (guchar *)atomlist, n_atoms); private->xdnd_targets_set = 1; } +static void +xdnd_set_actions (GdkDragContext *context) +{ + GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; + GdkAtom *atomlist; + gint i; + gint n_atoms; + guint actions; + + if (!xdnd_actions_initialized) + xdnd_initialize_actions(); + + actions = context->actions; + n_atoms = 0; + for (i=0; iactions; + n_atoms = 0; + for (i=0; isource_window), + GDK_WINDOW_XWINDOW (context->source_window), + gdk_atom_intern ("XdndActionList", FALSE), + XA_ATOM, 32, PropModeReplace, + (guchar *)atomlist, n_atoms); + + private->xdnd_actions_set = 1; +} + static void xdnd_send_enter (GdkDragContext *context) { @@ -2014,6 +2062,9 @@ 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)) { @@ -2188,12 +2239,17 @@ xdnd_check_dest (Window win) static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev, GdkEvent *event, - gpointer data) + gpointer cb_data) { XEvent *xevent = (XEvent *)xev; GdkDragContext *new_context; gint i; + Atom type; + int format; + gulong nitems, after; + Atom *data; + guint32 source_window = xevent->xclient.data.l[0]; gboolean get_types = ((xevent->xclient.data.l[1] & 1) != 0); gint version = (xevent->xclient.data.l[1] & 0xff000000) >> 24; @@ -2237,11 +2293,6 @@ xdnd_enter_filter (GdkXEvent *xev, new_context->targets = NULL; if (get_types) { - Atom type; - int format; - gulong nitems, after; - Atom *data; - XGetWindowProperty (GDK_WINDOW_XDISPLAY (event->any.window), source_window, gdk_atom_intern ("XdndTypeList", FALSE), 0, 65536, @@ -2268,6 +2319,44 @@ 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; iactions |= 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); @@ -2340,6 +2429,8 @@ xdnd_position_filter (GdkXEvent *xev, event->dnd.time = time; current_dest_drag->suggested_action = xdnd_action_from_atom (action); + if (!((GdkDragContextPrivate *)current_dest_drag)->xdnd_have_actions) + current_dest_drag->actions = current_dest_drag->suggested_action; event->dnd.x_root = x_root; event->dnd.y_root = y_root; @@ -2436,6 +2527,7 @@ gdk_drag_do_leave (GdkDragContext *context, guint32 time) xdnd_send_leave (context); break; case GDK_DRAG_PROTO_ROOTWIN: + case GDK_DRAG_PROTO_NONE: break; } @@ -2639,6 +2731,7 @@ gdk_drag_motion (GdkDragContext *context, break; case GDK_DRAG_PROTO_ROOTWIN: + case GDK_DRAG_PROTO_NONE: break; } private->old_action = action; @@ -2710,6 +2803,9 @@ gdk_drag_motion (GdkDragContext *context, gdk_event_put (&temp_event); } break; + case GDK_DRAG_PROTO_NONE: + g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()"); + break; } } else @@ -2741,6 +2837,9 @@ gdk_drag_drop (GdkDragContext *context, case GDK_DRAG_PROTO_ROOTWIN: g_warning ("Drops for GDK_DRAG_PROTO_ROOTWIN must be handled internally"); break; + case GDK_DRAG_PROTO_NONE: + g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()"); + break; } } } diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c index b2653628a5d5c0232485123267aed9c487a32a66..fd5a26564f44669a97e285ddc9109b64ad20554c 100644 --- a/gdk/x11/gdkdnd-x11.c +++ b/gdk/x11/gdkdnd-x11.c @@ -60,6 +60,8 @@ struct _GdkDragContextPrivate { 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_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 */ @@ -1953,16 +1955,16 @@ static void xdnd_set_targets (GdkDragContext *context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; - GdkAtom *typelist; + GdkAtom *atomlist; GList *tmp_list = context->targets; gint i; - gint n_targets = g_list_length (context->targets); + gint n_atoms = g_list_length (context->targets); - typelist = g_new (GdkAtom, n_targets); + atomlist = g_new (GdkAtom, n_atoms); i = 0; while (tmp_list) { - typelist[i] = GPOINTER_TO_INT (tmp_list->data); + atomlist[i] = GPOINTER_TO_INT (tmp_list->data); tmp_list = tmp_list->next; i++; } @@ -1971,11 +1973,57 @@ xdnd_set_targets (GdkDragContext *context) GDK_WINDOW_XWINDOW (context->source_window), gdk_atom_intern ("XdndTypeList", FALSE), XA_ATOM, 32, PropModeReplace, - (guchar *)typelist, n_targets); + (guchar *)atomlist, n_atoms); private->xdnd_targets_set = 1; } +static void +xdnd_set_actions (GdkDragContext *context) +{ + GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; + GdkAtom *atomlist; + gint i; + gint n_atoms; + guint actions; + + if (!xdnd_actions_initialized) + xdnd_initialize_actions(); + + actions = context->actions; + n_atoms = 0; + for (i=0; iactions; + n_atoms = 0; + for (i=0; isource_window), + GDK_WINDOW_XWINDOW (context->source_window), + gdk_atom_intern ("XdndActionList", FALSE), + XA_ATOM, 32, PropModeReplace, + (guchar *)atomlist, n_atoms); + + private->xdnd_actions_set = 1; +} + static void xdnd_send_enter (GdkDragContext *context) { @@ -2014,6 +2062,9 @@ 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)) { @@ -2188,12 +2239,17 @@ xdnd_check_dest (Window win) static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev, GdkEvent *event, - gpointer data) + gpointer cb_data) { XEvent *xevent = (XEvent *)xev; GdkDragContext *new_context; gint i; + Atom type; + int format; + gulong nitems, after; + Atom *data; + guint32 source_window = xevent->xclient.data.l[0]; gboolean get_types = ((xevent->xclient.data.l[1] & 1) != 0); gint version = (xevent->xclient.data.l[1] & 0xff000000) >> 24; @@ -2237,11 +2293,6 @@ xdnd_enter_filter (GdkXEvent *xev, new_context->targets = NULL; if (get_types) { - Atom type; - int format; - gulong nitems, after; - Atom *data; - XGetWindowProperty (GDK_WINDOW_XDISPLAY (event->any.window), source_window, gdk_atom_intern ("XdndTypeList", FALSE), 0, 65536, @@ -2268,6 +2319,44 @@ 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; iactions |= 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); @@ -2340,6 +2429,8 @@ xdnd_position_filter (GdkXEvent *xev, event->dnd.time = time; current_dest_drag->suggested_action = xdnd_action_from_atom (action); + if (!((GdkDragContextPrivate *)current_dest_drag)->xdnd_have_actions) + current_dest_drag->actions = current_dest_drag->suggested_action; event->dnd.x_root = x_root; event->dnd.y_root = y_root; @@ -2436,6 +2527,7 @@ gdk_drag_do_leave (GdkDragContext *context, guint32 time) xdnd_send_leave (context); break; case GDK_DRAG_PROTO_ROOTWIN: + case GDK_DRAG_PROTO_NONE: break; } @@ -2639,6 +2731,7 @@ gdk_drag_motion (GdkDragContext *context, break; case GDK_DRAG_PROTO_ROOTWIN: + case GDK_DRAG_PROTO_NONE: break; } private->old_action = action; @@ -2710,6 +2803,9 @@ gdk_drag_motion (GdkDragContext *context, gdk_event_put (&temp_event); } break; + case GDK_DRAG_PROTO_NONE: + g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()"); + break; } } else @@ -2741,6 +2837,9 @@ gdk_drag_drop (GdkDragContext *context, case GDK_DRAG_PROTO_ROOTWIN: g_warning ("Drops for GDK_DRAG_PROTO_ROOTWIN must be handled internally"); break; + case GDK_DRAG_PROTO_NONE: + g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()"); + break; } } }