📄 gdkdnd-x11.c
字号:
return retval;}static voidmotif_send_drop (GdkDragContext *context, guint32 time){ GdkDragContextPrivateX11 *private = PRIVATE_DATA (context); GdkDisplay *display = GDK_DRAWABLE_DISPLAY (context->source_window); XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_AND_DROP_MESSAGE"); xev.xclient.format = 8; xev.xclient.window = GDK_DRAWABLE_XID (context->dest_window); MOTIF_XCLIENT_BYTE (&xev, 0) = XmDROP_START; MOTIF_XCLIENT_BYTE (&xev, 1) = local_byte_order; MOTIF_XCLIENT_SHORT (&xev, 1) = motif_dnd_get_flags (context); MOTIF_XCLIENT_LONG (&xev, 1) = time; MOTIF_XCLIENT_SHORT (&xev, 4) = private->last_x; MOTIF_XCLIENT_SHORT (&xev, 5) = private->last_y; MOTIF_XCLIENT_LONG (&xev, 3) = private->motif_selection; MOTIF_XCLIENT_LONG (&xev, 4) = GDK_DRAWABLE_XID (context->source_window); if (!_gdk_send_xevent (display, GDK_DRAWABLE_XID (context->dest_window), FALSE, 0, &xev)) GDK_NOTE (DND, g_message ("Send event to %lx failed", GDK_DRAWABLE_XID (context->dest_window)));}/* Target Side */static gbooleanmotif_read_initiator_info (GdkDisplay *display, Window source_window, Atom atom, GList **targets, Atom *selection){ GList *tmp_list; Atom type; gint format; gulong nitems; gulong bytes_after; guchar *data; MotifDragInitiatorInfo *initiator_info; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); gdk_error_trap_push (); XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), source_window, atom, 0, sizeof(*initiator_info), FALSE, gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_INITIATOR_INFO"), &type, &format, &nitems, &bytes_after, &data); if (gdk_error_trap_pop () || (format != 8) || (nitems != sizeof (MotifDragInitiatorInfo)) || (bytes_after != 0)) { g_warning ("Error reading initiator info\n"); return FALSE; } initiator_info = (MotifDragInitiatorInfo *)data; motif_read_target_table (display); initiator_info->targets_index = card16_to_host (initiator_info->targets_index, initiator_info->byte_order); initiator_info->selection_atom = card32_to_host (initiator_info->selection_atom, initiator_info->byte_order); if (initiator_info->targets_index >= display_x11->motif_n_target_lists) { g_warning ("Invalid target index in TOP_LEVEL_ENTER MESSAGE"); XFree (initiator_info); return FALSE; } tmp_list = g_list_last (display_x11->motif_target_lists[initiator_info->targets_index]); *targets = NULL; while (tmp_list) { GdkAtom atom = gdk_x11_xatom_to_atom_for_display (display, GPOINTER_TO_UINT (tmp_list->data)); *targets = g_list_prepend (*targets, GDK_ATOM_TO_POINTER (atom)); tmp_list = tmp_list->prev; }#ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_DND) print_target_list (*targets);#endif /* G_ENABLE_DEBUG */ *selection = initiator_info->selection_atom; XFree (initiator_info); return TRUE;}static GdkDragContext *motif_drag_context_new (GdkWindow *dest_window, guint32 timestamp, guint32 source_window, guint32 atom){ GdkDragContext *new_context; GdkDragContextPrivateX11 *private; GdkDisplay *display = GDK_DRAWABLE_DISPLAY (dest_window); GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); /* FIXME, current_dest_drag really shouldn't be NULL'd * if we error below. */ if (display_x11->current_dest_drag != NULL) { if (timestamp >= display_x11->current_dest_drag->start_time) { g_object_unref (display_x11->current_dest_drag); display_x11->current_dest_drag = NULL; } else return NULL; } new_context = gdk_drag_context_new (); private = PRIVATE_DATA (new_context); new_context->protocol = GDK_DRAG_PROTO_MOTIF; new_context->is_source = FALSE; new_context->source_window = gdk_window_lookup_for_display (display, source_window); if (new_context->source_window) g_object_ref (new_context->source_window); else { new_context->source_window = gdk_window_foreign_new_for_display (display, source_window); if (!new_context->source_window) { g_object_unref (new_context); return NULL; } } new_context->dest_window = dest_window; g_object_ref (dest_window); new_context->start_time = timestamp; if (!motif_read_initiator_info (GDK_WINDOW_DISPLAY (dest_window), source_window, atom, &new_context->targets, &private->motif_selection)) { g_object_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){ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (event->any.window)); 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; g_object_ref (new_context); display_x11->current_dest_drag = new_context; return GDK_FILTER_TRANSLATE;}static GdkFilterReturnmotif_top_level_leave (GdkEvent *event, guint16 flags, guint32 timestamp){ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (event->any.window)); GDK_NOTE(DND, g_message ("Motif DND top level leave: flags: %#4x time: %d", flags, timestamp)); if ((display_x11->current_dest_drag != NULL) && (display_x11->current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= display_x11->current_dest_drag->start_time)) { event->dnd.type = GDK_DRAG_LEAVE; /* Pass ownership of context to the event */ event->dnd.context = display_x11->current_dest_drag; display_x11->current_dest_drag = NULL; return GDK_FILTER_TRANSLATE; } else return GDK_FILTER_REMOVE;}static GdkFilterReturnmotif_motion (GdkEvent *event, guint16 flags, guint32 timestamp, gint16 x_root, gint16 y_root){ GdkDragContextPrivateX11 *private; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (event->any.window)); GDK_NOTE(DND, g_message ("Motif DND motion: flags: %#4x time: %d (%d, %d)", flags, timestamp, x_root, y_root)); if ((display_x11->current_dest_drag != NULL) && (display_x11->current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= display_x11->current_dest_drag->start_time)) { private = PRIVATE_DATA (display_x11->current_dest_drag); event->dnd.type = GDK_DRAG_MOTION; event->dnd.context = display_x11->current_dest_drag; g_object_ref (display_x11->current_dest_drag); event->dnd.time = timestamp; motif_dnd_translate_flags (display_x11->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;}static GdkFilterReturnmotif_operation_changed (GdkEvent *event, guint16 flags, guint32 timestamp){ GdkDragContextPrivateX11 *private; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (event->any.window)); GDK_NOTE(DND, g_message ("Motif DND operation changed: flags: %#4x time: %d", flags, timestamp)); if ((display_x11->current_dest_drag != NULL) && (display_x11->current_dest_drag->protocol == GDK_DRAG_PROTO_MOTIF) && (timestamp >= display_x11->current_dest_drag->start_time)) { event->dnd.type = GDK_DRAG_MOTION; event->dnd.send_event = FALSE; event->dnd.context = display_x11->current_dest_drag; g_object_ref (display_x11->current_dest_drag); event->dnd.time = timestamp; private = PRIVATE_DATA (display_x11->current_dest_drag); motif_dnd_translate_flags (display_x11->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;}static GdkFilterReturnmotif_drop_start (GdkEvent *event, guint16 flags, guint32 timestamp, guint32 source_window, guint32 atom, gint16 x_root, gint16 y_root){ GdkDragContext *new_context; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_DRAWABLE_DISPLAY (event->any.window)); 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_x11_window_set_user_time (event->any.window, timestamp); g_object_ref (new_context); display_x11->current_dest_drag = new_context; return GDK_FILTER_TRANSLATE;} static GdkFilterReturnmotif_drag_status (GdkEvent *event, guint16 flags, guint32 timestamp){ GdkDragContext *context; GdkDisplay *display; GDK_NOTE (DND, g_message ("Motif status message: flags %x", flags)); display = gdk_drawable_get_display (event->any.window); if (!display) return GDK_FILTER_REMOVE; context = gdk_drag_context_find (display, TRUE, GDK_DRAWABLE_XID (event->any.window), None); if (context) { GdkDragContextPrivateX11 *private = PRIVATE_DATA (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; g_object_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;}static GdkFilterReturnmotif_dnd_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ XEvent *xevent = (XEvent *)xev; guint8 reason; guint16 flags; guint32 timestamp; guint32 source_window; Atom atom; gint16 x_root, y_root; gboolean is_reply; if (!event->any.window || gdk_window_get_window_type (event->any.window) == GDK_WINDOW_FOREIGN) return GDK_FILTER_CONTINUE; /* Not for us */ /* 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -