📄 gdkdnd.c
字号:
return NULL; } new_context = gdk_drag_context_new (); private = (GdkDragContextPrivate *)new_context; new_context->protocol = GDK_DRAG_PROTO_MOTIF; new_context->is_source = FALSE; new_context->source_window = gdk_window_lookup (source_window); if (new_context->source_window) gdk_window_ref (new_context->source_window); else { new_context->source_window = gdk_window_foreign_new (source_window); if (!new_context->source_window) { gdk_drag_context_unref (new_context); return NULL; } } new_context->dest_window = dest_window; gdk_window_ref (dest_window); new_context->start_time = timestamp; if (!motif_read_initiator_info(source_window, atom, &new_context->targets, &private->motif_selection)) { gdk_drag_context_unref (new_context); return NULL; } return new_context;}/* * The MOTIF drag protocol has no real provisions for distinguishing * multiple simultaneous drops. If the sources grab the pointer * when doing drags, that shouldn't happen, in any case. If it * does, we can't do much except hope for the best. */static GdkFilterReturnmotif_top_level_enter (GdkEvent *event, guint16 flags, guint32 timestamp, guint32 source_window, guint32 atom){ GdkDragContext *new_context; GDK_NOTE(DND, g_message ("Motif DND top level enter: flags: %#4x time: %d source_widow: %#4x atom: %d", flags, timestamp, source_window, atom)); new_context = motif_drag_context_new (event->any.window, timestamp, source_window, atom); if (!new_context) return GDK_FILTER_REMOVE; event->dnd.type = GDK_DRAG_ENTER; event->dnd.context = new_context; gdk_drag_context_ref (new_context); current_dest_drag = new_context; return GDK_FILTER_TRANSLATE;}GdkFilterReturnmotif_top_level_leave (GdkEvent *event, guint16 flags, guint32 timestamp){ GDK_NOTE(DND, g_message ("Motif DND top level leave: flags: %#4x time: %d", flags, timestamp)); if ((current_dest_drag != NULL) && (current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= current_dest_drag->start_time)) { event->dnd.type = GDK_DRAG_LEAVE; /* Pass ownership of context to the event */ event->dnd.context = current_dest_drag; current_dest_drag = NULL; return GDK_FILTER_TRANSLATE; } else return GDK_FILTER_REMOVE;}GdkFilterReturnmotif_motion (GdkEvent *event, guint16 flags, guint32 timestamp, gint16 x_root, gint16 y_root){ GdkDragContextPrivate *private; GDK_NOTE(DND, g_message ("Motif DND motion: flags: %#4x time: %d (%d, %d)", flags, timestamp, x_root, y_root)); if ((current_dest_drag != NULL) && (current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= current_dest_drag->start_time)) { private = (GdkDragContextPrivate *)current_dest_drag; event->dnd.type = GDK_DRAG_MOTION; event->dnd.context = current_dest_drag; gdk_drag_context_ref (current_dest_drag); event->dnd.time = timestamp; motif_dnd_translate_flags (current_dest_drag, flags); event->dnd.x_root = x_root; event->dnd.y_root = y_root; private->last_x = x_root; private->last_y = y_root; private->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; return GDK_FILTER_TRANSLATE; } return GDK_FILTER_REMOVE;}GdkFilterReturnmotif_operation_changed (GdkEvent *event, guint16 flags, guint32 timestamp){ GdkDragContextPrivate *private; GDK_NOTE(DND, g_message ("Motif DND operation changed: flags: %#4x time: %d", flags, timestamp)); if ((current_dest_drag != NULL) && (current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= current_dest_drag->start_time)) { event->dnd.type = GDK_DRAG_MOTION; event->dnd.send_event = FALSE; event->dnd.context = current_dest_drag; gdk_drag_context_ref (current_dest_drag); event->dnd.time = timestamp; private = (GdkDragContextPrivate *)current_dest_drag; motif_dnd_translate_flags (current_dest_drag, flags); event->dnd.x_root = private->last_x; event->dnd.y_root = private->last_y; private->drag_status = GDK_DRAG_STATUS_ACTION_WAIT; return GDK_FILTER_TRANSLATE; } return GDK_FILTER_REMOVE;}GdkFilterReturnmotif_drop_start (GdkEvent *event, guint16 flags, guint32 timestamp, guint32 source_window, guint32 atom, gint16 x_root, gint16 y_root){ GdkDragContext *new_context; GDK_NOTE(DND, g_message ("Motif DND drop start: flags: %#4x time: %d (%d, %d) source_widow: %#4x atom: %d", flags, timestamp, x_root, y_root, source_window, atom)); new_context = motif_drag_context_new (event->any.window, timestamp, source_window, atom); if (!new_context) return GDK_FILTER_REMOVE; motif_dnd_translate_flags (new_context, flags); event->dnd.type = GDK_DROP_START; event->dnd.context = new_context; event->dnd.time = timestamp; event->dnd.x_root = x_root; event->dnd.y_root = y_root; gdk_drag_context_ref (new_context); current_dest_drag = new_context; return GDK_FILTER_TRANSLATE;} GdkFilterReturnmotif_drag_status (GdkEvent *event, guint16 flags, guint32 timestamp){ GdkDragContext *context; GDK_NOTE (DND, g_message ("Motif status message: flags %x", flags)); context = gdk_drag_context_find (TRUE, GDK_WINDOW_XWINDOW (event->any.window), None); if (context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; 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; event->dnd.send_event = FALSE; event->dnd.context = context; gdk_drag_context_ref (context); event->dnd.time = timestamp; if ((flags & 0x00f0) >> 4 == XmDROP_SITE_VALID) { switch (flags & 0x000f) { case XmDROP_NOOP: context->action = 0; break; case XmDROP_MOVE: context->action = GDK_ACTION_MOVE; break; case XmDROP_COPY: context->action = GDK_ACTION_COPY; break; case XmDROP_LINK: context->action = GDK_ACTION_LINK; break; } } else context->action = 0; return GDK_FILTER_TRANSLATE; } return GDK_FILTER_REMOVE;}GdkFilterReturnmotif_dnd_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ XEvent *xevent = (XEvent *)xev; guint8 reason; guint16 flags; guint32 timestamp; guint32 source_window; GdkAtom atom; gint16 x_root, y_root; gboolean is_reply; /* First read some fields common to all Motif DND messages */ reason = MOTIF_UNPACK_BYTE (xevent, 0); flags = MOTIF_UNPACK_SHORT (xevent, 1); timestamp = MOTIF_UNPACK_LONG (xevent, 1); is_reply = ((reason & 0x80) != 0); switch (reason & 0x7f) { case XmTOP_LEVEL_ENTER: source_window = MOTIF_UNPACK_LONG (xevent, 2); atom = MOTIF_UNPACK_LONG (xevent, 3); return motif_top_level_enter (event, flags, timestamp, source_window, atom); case XmTOP_LEVEL_LEAVE: return motif_top_level_leave (event, flags, timestamp); case XmDRAG_MOTION: x_root = MOTIF_UNPACK_SHORT (xevent, 4); y_root = MOTIF_UNPACK_SHORT (xevent, 5); if (!is_reply) return motif_motion (event, flags, timestamp, x_root, y_root); else return motif_drag_status (event, flags, timestamp); case XmDROP_SITE_ENTER: return motif_drag_status (event, flags, timestamp); case XmDROP_SITE_LEAVE: return motif_drag_status (event, XmNO_DROP_SITE << 8 | XmDROP_NOOP, timestamp); case XmDROP_START: x_root = MOTIF_UNPACK_SHORT (xevent, 4); y_root = MOTIF_UNPACK_SHORT (xevent, 5); atom = MOTIF_UNPACK_LONG (xevent, 3); source_window = MOTIF_UNPACK_LONG (xevent, 4); if (!is_reply) return motif_drop_start (event, flags, timestamp, source_window, atom, x_root, y_root); break; case XmOPERATION_CHANGED: if (!is_reply) return motif_operation_changed (event, flags, timestamp); else return motif_drag_status (event, flags, timestamp); break; /* To the best of my knowledge, these next two messages are * not part of the protocol, though they are defined in * the header files. */ case XmDROP_FINISH: case XmDRAG_DROP_FINISH: break; } return GDK_FILTER_REMOVE;}/************************************************************* ***************************** XDND ************************** *************************************************************//* Utility functions */static struct { gchar *name; GdkAtom atom; GdkDragAction action;} xdnd_actions_table[] = { { "XdndActionCopy", GDK_NONE, GDK_ACTION_COPY }, { "XdndActionMove", GDK_NONE, GDK_ACTION_MOVE }, { "XdndActionLink", GDK_NONE, GDK_ACTION_LINK }, { "XdndActionAsk", GDK_NONE, GDK_ACTION_ASK }, { "XdndActionPrivate", GDK_NONE, GDK_ACTION_COPY }, };static const gint xdnd_n_actions = sizeof(xdnd_actions_table) / sizeof(xdnd_actions_table[0]);static gboolean xdnd_actions_initialized = FALSE;static voidxdnd_initialize_actions (void){ gint i; xdnd_actions_initialized = TRUE; for (i=0; i < xdnd_n_actions; i++) xdnd_actions_table[i].atom = gdk_atom_intern (xdnd_actions_table[i].name, FALSE);}static GdkDragActionxdnd_action_from_atom (GdkAtom atom){ gint i; if (!xdnd_actions_initialized) xdnd_initialize_actions(); for (i=0; i<xdnd_n_actions; i++) if (atom == xdnd_actions_table[i].atom) return xdnd_actions_table[i].action; return 0;}static GdkAtomxdnd_action_to_atom (GdkDragAction action){ gint i; if (!xdnd_actions_initialized) xdnd_initialize_actions(); for (i=0; i<xdnd_n_actions; i++) if (action == xdnd_actions_table[i].action) return xdnd_actions_table[i].atom; return GDK_NONE;}static GdkAtom xdnd_aware_atom = GDK_NONE;/* Source side */static GdkFilterReturn xdnd_status_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ XEvent *xevent = (XEvent *)xev; guint32 dest_window = xevent->xclient.data.l[0]; guint32 flags = xevent->xclient.data.l[1]; GdkAtom action = xevent->xclient.data.l[4]; GdkDragContext *context; GDK_NOTE (DND, g_message ("XdndStatus: dest_window: %#x action: %ld", dest_window, action)); context = gdk_drag_context_find (TRUE, xevent->xclient.window, dest_window); if (context) { GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) private->drag_status = GDK_DRAG_STATUS_DRAG; event->dnd.send_event = FALSE; event->dnd.type = GDK_DRAG_STATUS; event->dnd.context = context; gdk_drag_context_ref (context); event->dnd.time = GDK_CURRENT_TIME; /* FIXME? */ if (!(action != 0) != !(flags & 1)) { GDK_NOTE (DND, g_warning ("Received status event with flags not corresponding to action!\n")); action = 0; } context->action = xdnd_action_from_atom (action); return GDK_FILTER_TRANSLATE; } return GDK_FILTER_REMOVE;}static GdkFilterReturn xdnd_finished_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ XEvent *xevent = (XEvent *)xev; guint32 dest_window = xevent->xclient.data.l[0]; GdkDragContext *context; GDK_NOTE (DND, g_message ("XdndFinished: dest_window: %#x", dest_window)); context = gdk_drag_context_find (TRUE, xevent->xclient.window, dest_window); if (context) { event->dnd.type = GDK_DROP_FINISHED; event->dnd.context = context; gdk_drag_context_ref (context); return GDK_FILTER_TRANSLATE; } return GDK_FILTER_REMOVE;}static voidxdnd_set_targets (GdkDragContext *context){ GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; GdkAtom *atomlist; GList *tmp_list = context->targets; gint i; gint n_atoms = g_list_length (context->targets); atomlist = g_new (GdkAtom, n_atoms); i = 0; while (tmp_list) { atomlist[i] = GPOINTER_TO_INT (tmp_list->data); tmp_list = tmp_list->next; i++; } XChangeProperty (GDK_WINDOW_XDISPLAY (context->source_window), GDK_WINDOW_XWINDOW (context->source_window), gdk_atom_intern ("XdndTypeList", FALSE), XA_ATOM, 32, PropModeReplace, (guchar *)atomlist, n_atoms); g_free (atomlist); private->xdnd_targets_set = 1;}static voidxdnd_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; i<xdnd_n_actions; i++) { if (actions & xdnd_actions_table[i].action) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -