📄 gdkdnd.c
字号:
actions &= ~xdnd_actions_table[i].action; n_atoms++; } } atomlist = g_new (GdkAtom, n_atoms); actions = context->actions; n_atoms = 0; for (i=0; i<xdnd_n_actions; i++) { if (actions & xdnd_actions_table[i].action) { actions &= ~xdnd_actions_table[i].action; atomlist[n_atoms] = xdnd_actions_table[i].atom; n_atoms++; } } XChangeProperty (GDK_WINDOW_XDISPLAY (context->source_window), GDK_WINDOW_XWINDOW (context->source_window), gdk_atom_intern ("XdndActionList", FALSE), XA_ATOM, 32, PropModeReplace, (guchar *)atomlist, n_atoms); g_free (atomlist); private->xdnd_actions_set = 1; private->xdnd_actions = context->actions;}/************************************************************* * xdnd_send_xevent: * Like gdk_send_event, but if the target is the root * window, sets an event mask of ButtonPressMask, otherwise * an event mask of 0. * arguments: * * results: *************************************************************/gintxdnd_send_xevent (Window window, gboolean propagate, XEvent *event_send){ if (window == gdk_root_window) return gdk_send_xevent (window, propagate, ButtonPressMask, event_send); else return gdk_send_xevent (window, propagate, 0, event_send);}static voidxdnd_send_enter (GdkDragContext *context){ XEvent xev; GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_atom_intern ("XdndEnter", FALSE); xev.xclient.format = 32; xev.xclient.window = private->drop_xid ? private->drop_xid : GDK_WINDOW_XWINDOW (context->dest_window); xev.xclient.data.l[0] = GDK_WINDOW_XWINDOW (context->source_window); xev.xclient.data.l[1] = (3 << 24); /* version */ xev.xclient.data.l[2] = 0; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; if (!private->xdnd_selection) private->xdnd_selection = gdk_atom_intern ("XdndSelection", FALSE); if (g_list_length (context->targets) > 3) { if (!private->xdnd_targets_set) xdnd_set_targets (context); xev.xclient.data.l[1] |= 1; } else { GList *tmp_list = context->targets; gint i = 2; while (tmp_list) { xev.xclient.data.l[i] = GPOINTER_TO_INT (tmp_list->data); tmp_list = tmp_list->next; i++; } } if (!xdnd_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, &xev)) { GDK_NOTE (DND, g_message ("Send event to %lx failed", GDK_WINDOW_XWINDOW (context->dest_window))); gdk_window_unref (context->dest_window); context->dest_window = NULL; }}static voidxdnd_send_leave (GdkDragContext *context){ XEvent xev; GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_atom_intern ("XdndLeave", FALSE); xev.xclient.format = 32; xev.xclient.window = private->drop_xid ? private->drop_xid : GDK_WINDOW_XWINDOW (context->dest_window); xev.xclient.data.l[0] = GDK_WINDOW_XWINDOW (context->source_window); xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = 0; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; if (!xdnd_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, &xev)) { GDK_NOTE (DND, g_message ("Send event to %lx failed", GDK_WINDOW_XWINDOW (context->dest_window))); gdk_window_unref (context->dest_window); context->dest_window = NULL; }}static voidxdnd_send_drop (GdkDragContext *context, guint32 time){ GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_atom_intern ("XdndDrop", FALSE); xev.xclient.format = 32; xev.xclient.window = private->drop_xid ? private->drop_xid : GDK_WINDOW_XWINDOW (context->dest_window); xev.xclient.data.l[0] = GDK_WINDOW_XWINDOW (context->source_window); xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = time; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; if (!xdnd_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, &xev)) { GDK_NOTE (DND, g_message ("Send event to %lx failed", GDK_WINDOW_XWINDOW (context->dest_window))); gdk_window_unref (context->dest_window); context->dest_window = NULL; }}static voidxdnd_send_motion (GdkDragContext *context, gint x_root, gint y_root, GdkDragAction action, guint32 time){ GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_atom_intern ("XdndPosition", FALSE); xev.xclient.format = 32; xev.xclient.window = private->drop_xid ? private->drop_xid : GDK_WINDOW_XWINDOW (context->dest_window); xev.xclient.data.l[0] = GDK_WINDOW_XWINDOW (context->source_window); xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = (x_root << 16) | y_root; xev.xclient.data.l[3] = time; xev.xclient.data.l[4] = xdnd_action_to_atom (action); if (!xdnd_send_xevent (GDK_WINDOW_XWINDOW (context->dest_window), FALSE, &xev)) { GDK_NOTE (DND, g_message ("Send event to %lx failed", GDK_WINDOW_XWINDOW (context->dest_window))); gdk_window_unref (context->dest_window); context->dest_window = NULL; } private->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;}static guint32xdnd_check_dest (Window win){ gboolean retval = FALSE; Atom type = None; 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_proxy_atom, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, (guchar **)&proxy_data); 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); } } gdk_error_warnings = old_warnings; gdk_error_code = 0; return retval ? (proxy ? proxy : win) : GDK_NONE;}/* Target side */static voidxdnd_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 voidxdnd_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, 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; GDK_NOTE (DND, g_message ("XdndEnter: source_window: %#x, version: %#x", source_window, version)); if (version != 3) { /* Old source ignore */ GDK_NOTE (DND, g_message ("Ignored old XdndEnter message")); return GDK_FILTER_REMOVE; } if (current_dest_drag != NULL) { gdk_drag_context_unref (current_dest_drag); current_dest_drag = NULL; } new_context = gdk_drag_context_new (); new_context->protocol = GDK_DRAG_PROTO_XDND; 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 GDK_FILTER_REMOVE; } } new_context->dest_window = event->any.window; gdk_window_ref (new_context->dest_window); new_context->targets = NULL; if (get_types) { XGetWindowProperty (GDK_WINDOW_XDISPLAY (event->any.window), source_window, gdk_atom_intern ("XdndTypeList", FALSE), 0, 65536, False, XA_ATOM, &type, &format, &nitems, &after, (guchar **)&data); if ((format != 32) || (type != XA_ATOM)) { gdk_drag_context_unref (new_context); return GDK_FILTER_REMOVE; } for (i=0; i<nitems; i++) new_context->targets = g_list_append (new_context->targets, GUINT_TO_POINTER (data[i])); XFree(data); } else { for (i=0; i<3; i++) if (xevent->xclient.data.l[2+i]) new_context->targets = g_list_append (new_context->targets, GUINT_TO_POINTER (xevent->xclient.data.l[2+i])); }#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); current_dest_drag = new_context; ((GdkDragContextPrivate *)new_context)->xdnd_selection = gdk_atom_intern ("XdndSelection", FALSE); return GDK_FILTER_TRANSLATE;}static GdkFilterReturn xdnd_leave_filter (GdkXEvent *xev, GdkEvent *event, gpointer data){ XEvent *xevent = (XEvent *)xev; guint32 source_window = xevent->xclient.data.l[0]; GDK_NOTE (DND, g_message ("XdndLeave: sou
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -