📄 gdkdnd-x11.c
字号:
if (gdk_error_trap_pop () || (format != 8) || (bytes_after != 0) || (nitems != header->total_size - sizeof(MotifTargetTableHeader))) goto error; display_x11->motif_n_target_lists = header->n_lists; display_x11->motif_target_lists = g_new0 (GList *, display_x11->motif_n_target_lists); p = target_bytes; for (i=0; i<header->n_lists; i++) { gint n_targets; guint32 *targets; if (p + sizeof(guint16) - target_bytes > nitems) goto error; n_targets = card16_to_host (*(gushort *)p, header->byte_order); /* We need to make a copy of the targets, since it may * be unaligned */ targets = g_new (guint32, n_targets); memcpy (targets, p + sizeof(guint16), sizeof(guint32) * n_targets); p += sizeof(guint16) + n_targets * sizeof(guint32); if (p - target_bytes > nitems) goto error; for (j=0; j<n_targets; j++) display_x11->motif_target_lists[i] = g_list_prepend (display_x11->motif_target_lists[i], GUINT_TO_POINTER (card32_to_host (targets[j], header->byte_order))); g_free (targets); display_x11->motif_target_lists[i] = g_list_reverse (display_x11->motif_target_lists[i]); } success = TRUE; error: if (header) XFree (header); if (target_bytes) XFree (target_bytes); if (!success) { if (display_x11->motif_target_lists) { g_free (display_x11->motif_target_lists); display_x11->motif_target_lists = NULL; display_x11->motif_n_target_lists = 0; } g_warning ("Error reading Motif target table\n"); } }}static ginttargets_sort_func (gconstpointer a, gconstpointer b){ return (GPOINTER_TO_UINT (a) < GPOINTER_TO_UINT (b)) ? -1 : ((GPOINTER_TO_UINT (a) > GPOINTER_TO_UINT (b)) ? 1 : 0);}/* Check if given (sorted) list is in the targets table */static gintmotif_target_table_check (GdkDisplay *display, GList *sorted){ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); GList *tmp_list1, *tmp_list2; gint i; for (i=0; i<display_x11->motif_n_target_lists; i++) { tmp_list1 = display_x11->motif_target_lists[i]; tmp_list2 = sorted; while (tmp_list1 && tmp_list2) { if (tmp_list1->data != tmp_list2->data) break; tmp_list1 = tmp_list1->next; tmp_list2 = tmp_list2->next; } if (!tmp_list1 && !tmp_list2) /* Found it */ return i; } return -1;}static gintmotif_add_to_target_table (GdkDisplay *display, GList *targets) /* targets is list of GdkAtom */{ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); GList *sorted = NULL; gint index = -1; gint i; GList *tmp_list; /* make a sorted copy of the list */ while (targets) { Atom xatom = gdk_x11_atom_to_xatom_for_display (display, GDK_POINTER_TO_ATOM (targets->data)); sorted = g_list_insert_sorted (sorted, GUINT_TO_POINTER (xatom), targets_sort_func); targets = targets->next; } /* First check if it is there already */ if (display_x11->motif_target_lists) index = motif_target_table_check (display, sorted); /* We need to grab the server while doing this, to ensure * atomiticity. Ugh */ if (index < 0) { /* We need to make sure that it exists _before_ we grab the * server, since we can't open a new connection after we * grab the server. */ motif_find_drag_window (display, TRUE); gdk_x11_display_grab (display); motif_read_target_table (display); /* Check again, in case it was added in the meantime */ if (display_x11->motif_target_lists) index = motif_target_table_check (display, sorted); if (index < 0) { guint32 total_size = 0; guchar *data; guchar *p; guint16 *p16; MotifTargetTableHeader *header; if (!display_x11->motif_target_lists) { display_x11->motif_target_lists = g_new (GList *, 1); display_x11->motif_n_target_lists = 1; } else { display_x11->motif_n_target_lists++; display_x11->motif_target_lists = g_realloc (display_x11->motif_target_lists, sizeof(GList *) * display_x11->motif_n_target_lists); } display_x11->motif_target_lists[display_x11->motif_n_target_lists - 1] = sorted; sorted = NULL; index = display_x11->motif_n_target_lists - 1; total_size = sizeof (MotifTargetTableHeader); for (i = 0; i < display_x11->motif_n_target_lists ; i++) total_size += sizeof(guint16) + sizeof(guint32) * g_list_length (display_x11->motif_target_lists[i]); data = g_malloc (total_size); header = (MotifTargetTableHeader *)data; p = data + sizeof(MotifTargetTableHeader); header->byte_order = local_byte_order; header->protocol_version = 0; header->n_lists = display_x11->motif_n_target_lists; header->total_size = total_size; for (i = 0; i < display_x11->motif_n_target_lists ; i++) { guint16 n_targets = g_list_length (display_x11->motif_target_lists[i]); guint32 *targets = g_new (guint32, n_targets); guint32 *p32 = targets; tmp_list = display_x11->motif_target_lists[i]; while (tmp_list) { *p32 = GPOINTER_TO_UINT (tmp_list->data); tmp_list = tmp_list->next; p32++; } p16 = (guint16 *)p; p += sizeof(guint16); memcpy (p, targets, n_targets * sizeof(guint32)); *p16 = n_targets; p += sizeof(guint32) * n_targets; g_free (targets); } XChangeProperty (display_x11->xdisplay, display_x11->motif_drag_window, gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_TARGETS"), gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_TARGETS"), 8, PropModeReplace, data, total_size); } gdk_x11_display_ungrab (display); } g_list_free (sorted); return index;}/* Translate flags */static voidmotif_dnd_translate_flags (GdkDragContext *context, guint16 flags){ guint recommended_op = flags & 0x000f; guint possible_ops = (flags & 0x0f0) >> 4; switch (recommended_op) { case XmDROP_MOVE: context->suggested_action = GDK_ACTION_MOVE; break; case XmDROP_COPY: context->suggested_action = GDK_ACTION_COPY; break; case XmDROP_LINK: context->suggested_action = GDK_ACTION_LINK; break; default: context->suggested_action = GDK_ACTION_COPY; break; } context->actions = 0; if (possible_ops & XmDROP_MOVE) context->actions |= GDK_ACTION_MOVE; if (possible_ops & XmDROP_COPY) context->actions |= GDK_ACTION_COPY; if (possible_ops & XmDROP_LINK) context->actions |= GDK_ACTION_LINK;}static guint16motif_dnd_get_flags (GdkDragContext *context){ guint16 flags = 0; switch (context->suggested_action) { case GDK_ACTION_MOVE: flags = XmDROP_MOVE; break; case GDK_ACTION_COPY: flags = XmDROP_COPY; break; case GDK_ACTION_LINK: flags = XmDROP_LINK; break; default: flags = XmDROP_NOOP; break; } if (context->actions & GDK_ACTION_MOVE) flags |= XmDROP_MOVE << 8; if (context->actions & GDK_ACTION_COPY) flags |= XmDROP_COPY << 8; if (context->actions & GDK_ACTION_LINK) flags |= XmDROP_LINK << 8; return flags;}/* Source Side */static voidmotif_set_targets (GdkDragContext *context){ GdkDragContextPrivateX11 *private = PRIVATE_DATA (context); MotifDragInitiatorInfo info; gint i; GdkDisplay *display = GDK_DRAWABLE_DISPLAY (context->source_window); info.byte_order = local_byte_order; info.protocol_version = 0; info.targets_index = motif_add_to_target_table (display, context->targets); for (i=0; ; i++) { gchar buf[20]; g_snprintf(buf, 20, "_GDK_SELECTION_%d", i); private->motif_selection = gdk_x11_get_xatom_by_name_for_display (display, buf); if (!XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), private->motif_selection)) break; } info.selection_atom = private->motif_selection; XChangeProperty (GDK_DRAWABLE_XDISPLAY (context->source_window), GDK_DRAWABLE_XID (context->source_window), private->motif_selection, gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_INITIATOR_INFO"), 8, PropModeReplace, (guchar *)&info, sizeof (info)); private->motif_targets_set = 1;}static guint32motif_check_dest (GdkDisplay *display, Window win){ gboolean retval = FALSE; guchar *data; MotifDragReceiverInfo *info; Atom type = None; int format; unsigned long nitems, after; Atom motif_drag_receiver_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO"); gdk_error_trap_push (); XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), win, motif_drag_receiver_info_atom, 0, (sizeof(*info)+3)/4, False, AnyPropertyType, &type, &format, &nitems, &after, &data); if (gdk_error_trap_pop() == 0) { if (type != None) { info = (MotifDragReceiverInfo *)data; if ((format == 8) && (nitems == sizeof(*info))) { if ((info->protocol_version == 0) && ((info->protocol_style == XmDRAG_PREFER_PREREGISTER) || (info->protocol_style == XmDRAG_PREFER_DYNAMIC) || (info->protocol_style == XmDRAG_DYNAMIC))) retval = TRUE; } else { GDK_NOTE (DND, g_warning ("Invalid Motif drag receiver property on window %ld\n", win)); } XFree (info); } } return retval ? win : None;}static voidmotif_send_enter (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) = XmTOP_LEVEL_ENTER; MOTIF_XCLIENT_BYTE (&xev, 1) = local_byte_order; MOTIF_XCLIENT_SHORT (&xev, 1) = 0; MOTIF_XCLIENT_LONG (&xev, 1) = time; MOTIF_XCLIENT_LONG (&xev, 2) = GDK_DRAWABLE_XID (context->source_window); if (!private->motif_targets_set) motif_set_targets (context); MOTIF_XCLIENT_LONG (&xev, 3) = private->motif_selection; MOTIF_XCLIENT_LONG (&xev, 4) = 0; 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)));}static voidmotif_send_leave (GdkDragContext *context, guint32 time){ 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) = XmTOP_LEVEL_LEAVE; MOTIF_XCLIENT_BYTE (&xev, 1) = local_byte_order; MOTIF_XCLIENT_SHORT (&xev, 1) = 0; MOTIF_XCLIENT_LONG (&xev, 1) = time; MOTIF_XCLIENT_LONG (&xev, 2) = 0; MOTIF_XCLIENT_LONG (&xev, 3) = 0; MOTIF_XCLIENT_LONG (&xev, 4) = 0; 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)));}static gbooleanmotif_send_motion (GdkDragContext *context, gint x_root, gint y_root, GdkDragAction action, guint32 time){ GdkDragContextPrivateX11 *private = PRIVATE_DATA (context); GdkDisplay *display = GDK_DRAWABLE_DISPLAY (context->source_window); gboolean retval; 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, 1) = local_byte_order; MOTIF_XCLIENT_SHORT (&xev, 1) = motif_dnd_get_flags (context); MOTIF_XCLIENT_LONG (&xev, 1) = time; MOTIF_XCLIENT_LONG (&xev, 3) = 0; MOTIF_XCLIENT_LONG (&xev, 4) = 0; 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; */ retval = TRUE; } else { MOTIF_XCLIENT_BYTE (&xev, 0) = XmDRAG_MOTION; MOTIF_XCLIENT_SHORT (&xev, 4) = x_root; MOTIF_XCLIENT_SHORT (&xev, 5) = y_root; private->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; retval = FALSE; } 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)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -