📄 gtkdnd.c
字号:
info->icon_window = widget; info->hot_x = hot_x; info->hot_y = hot_y; if (widget) { gtk_widget_set_uposition (widget, info->cur_x - info->hot_x, info->cur_y - info->hot_y); gtk_widget_ref (widget); gdk_window_raise (widget->window); gtk_widget_show (widget); } info->destroy_icon = destroy_on_release;}/************************************************************* * gtk_drag_set_icon_widget: * Set a widget as the icon for a drag. * arguments: * context: * widget: * hot_x: Hot spot * hot_y: * results: *************************************************************/void gtk_drag_set_icon_widget (GdkDragContext *context, GtkWidget *widget, gint hot_x, gint hot_y){ g_return_if_fail (context != NULL); g_return_if_fail (widget != NULL); gtk_drag_set_icon_window (context, widget, hot_x, hot_y, FALSE);}/************************************************************* * gtk_drag_set_icon_pixmap: * Set a widget as the icon for a drag. * arguments: * context: * colormap: Colormap for the icon window. * pixmap: * mask: * hot_x: Hot spot * hot_y: * results: *************************************************************/void gtk_drag_set_icon_pixmap (GdkDragContext *context, GdkColormap *colormap, GdkPixmap *pixmap, GdkBitmap *mask, gint hot_x, gint hot_y){ GtkWidget *window; gint width, height; g_return_if_fail (context != NULL); g_return_if_fail (colormap != NULL); g_return_if_fail (pixmap != NULL); gdk_window_get_size (pixmap, &width, &height); gtk_widget_push_visual (gdk_colormap_get_visual (colormap)); gtk_widget_push_colormap (colormap); window = gtk_window_new (GTK_WINDOW_POPUP); gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE); gtk_widget_pop_visual (); gtk_widget_pop_colormap (); gtk_widget_set_usize (window, width, height); gtk_widget_realize (window); gdk_window_set_back_pixmap (window->window, pixmap, FALSE); if (mask) gtk_widget_shape_combine_mask (window, mask, 0, 0); gtk_drag_set_icon_window (context, window, hot_x, hot_y, TRUE);}/************************************************************* * gtk_drag_set_icon_default: * Set the icon for a drag to the default icon. * arguments: * context: * results: *************************************************************/void gtk_drag_set_icon_default (GdkDragContext *context){ g_return_if_fail (context != NULL); if (!default_icon_pixmap) { default_icon_colormap = gdk_colormap_get_system (); default_icon_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, default_icon_colormap, &default_icon_mask, NULL, (gchar **)drag_default_xpm); default_icon_hot_x = -2; default_icon_hot_y = -2; } gtk_drag_set_icon_pixmap (context, default_icon_colormap, default_icon_pixmap, default_icon_mask, default_icon_hot_x, default_icon_hot_y);}/************************************************************* * gtk_drag_set_default_icon: * Set a default icon for all drags as a pixmap. * arguments: * colormap: Colormap for the icon window. * pixmap: * mask: * hot_x: Hot spot * hot_y: * results: *************************************************************/void gtk_drag_set_default_icon (GdkColormap *colormap, GdkPixmap *pixmap, GdkBitmap *mask, gint hot_x, gint hot_y){ g_return_if_fail (colormap != NULL); g_return_if_fail (pixmap != NULL); if (default_icon_colormap) gdk_colormap_unref (default_icon_colormap); if (default_icon_pixmap) gdk_pixmap_unref (default_icon_pixmap); if (default_icon_mask) gdk_pixmap_unref (default_icon_pixmap); default_icon_colormap = colormap; gdk_colormap_ref (colormap); default_icon_pixmap = pixmap; gdk_pixmap_ref (pixmap); default_icon_mask = mask; if (mask) gdk_pixmap_ref (mask); default_icon_hot_x = hot_x; default_icon_hot_y = hot_y;}/************************************************************* * gtk_drag_source_handle_event: * Called from widget event handling code on Drag events * for drag sources. * * arguments: * toplevel: Toplevel widget that received the event * event: * results: *************************************************************/voidgtk_drag_source_handle_event (GtkWidget *widget, GdkEvent *event){ GtkDragSourceInfo *info; GdkDragContext *context; g_return_if_fail (widget != NULL); g_return_if_fail (event != NULL); context = event->dnd.context; info = g_dataset_get_data (context, "gtk-info"); if (!info) return; switch (event->type) { case GDK_DRAG_STATUS: { GdkCursor *cursor; if (info->proxy_dest) { if (!event->dnd.send_event) { if (info->proxy_dest->proxy_drop_wait) { gboolean result = context->action != 0; /* Aha - we can finally pass the MOTIF DROP on... */ gdk_drop_reply (info->proxy_dest->context, result, info->proxy_dest->proxy_drop_time); if (result) gdk_drag_drop (info->context, info->proxy_dest->proxy_drop_time); else gtk_drag_finish (info->proxy_dest->context, FALSE, FALSE, info->proxy_dest->proxy_drop_time); } else { gdk_drag_status (info->proxy_dest->context, event->dnd.context->action, event->dnd.time); } } } else { cursor = gtk_drag_get_cursor (event->dnd.context->action); if (info->cursor != cursor) { XChangeActivePointerGrab (GDK_WINDOW_XDISPLAY (widget->window), PointerMotionMask | PointerMotionHintMask | ButtonReleaseMask, ((GdkCursorPrivate *)cursor)->xcursor, event->dnd.time); info->cursor = cursor; } if (info->last_event) { gtk_drag_update (info, info->cur_x, info->cur_y, info->last_event); info->last_event = NULL; } } } break; case GDK_DROP_FINISHED: gtk_drag_drop_finished (info, TRUE, event->dnd.time); break; default: g_assert_not_reached (); }}/************************************************************* * gtk_drag_source_check_selection: * Check if we've set up handlers/claimed the selection * for a given drag. If not, add them. * arguments: * * results: *************************************************************/static voidgtk_drag_source_check_selection (GtkDragSourceInfo *info, GdkAtom selection, guint32 time){ GList *tmp_list; tmp_list = info->selections; while (tmp_list) { if (GPOINTER_TO_UINT (tmp_list->data) == selection) return; tmp_list = tmp_list->next; } gtk_selection_owner_set (info->ipc_widget, selection, time); info->selections = g_list_prepend (info->selections, GUINT_TO_POINTER (selection)); tmp_list = info->target_list->list; while (tmp_list) { GtkTargetPair *pair = tmp_list->data; gtk_selection_add_target (info->ipc_widget, selection, pair->target, pair->info); tmp_list = tmp_list->next; } if (info->context->protocol == GDK_DRAG_PROTO_MOTIF) { gtk_selection_add_target (info->ipc_widget, selection, gdk_atom_intern ("XmTRANSFER_SUCCESS", FALSE), TARGET_MOTIF_SUCCESS); gtk_selection_add_target (info->ipc_widget, selection, gdk_atom_intern ("XmTRANSFER_FAILURE", FALSE), TARGET_MOTIF_FAILURE); } gtk_selection_add_target (info->ipc_widget, selection, gdk_atom_intern ("DELETE", FALSE), TARGET_DELETE);}/************************************************************* * gtk_drag_drop_finished: * Clean up from the drag, and display snapback, if necessary. * arguments: * info: * success: * time: * results: *************************************************************/static voidgtk_drag_drop_finished (GtkDragSourceInfo *info, gboolean success, guint time){ gtk_drag_source_release_selections (info, time); if (info->proxy_dest) { /* The time from the event isn't reliable for Xdnd drags */ gtk_drag_finish (info->proxy_dest->context, success, FALSE, info->proxy_dest->proxy_drop_time); gtk_drag_source_info_destroy (info); } else { if (success) { gtk_drag_source_info_destroy (info); } else { GtkDragAnim *anim = g_new (GtkDragAnim, 1); anim->info = info; anim->step = 0; anim->n_steps = MAX (info->cur_x - info->start_x, info->cur_y - info->start_y) / ANIM_STEP_LENGTH; anim->n_steps = CLAMP (anim->n_steps, ANIM_MIN_STEPS, ANIM_MAX_STEPS); if (info->icon_window) { gtk_widget_show (info->icon_window); gdk_window_raise (info->icon_window->window); } /* Mark the context as dead, so if the destination decides * to respond really late, we still are OK. */ g_dataset_set_data (info->context, "gtk-info", NULL); gtk_timeout_add (ANIM_STEP_TIME, gtk_drag_anim_timeout, anim); } }}static voidgtk_drag_source_release_selections (GtkDragSourceInfo *info, guint32 time){ GList *tmp_list = info->selections; while (tmp_list) { GdkAtom selection = GPOINTER_TO_UINT (tmp_list->data); if (gdk_selection_owner_get (selection) == info->ipc_widget->window) gtk_selection_owner_set (NULL, selection, time); tmp_list = tmp_list->next; } g_list_free (info->selections); info->selections = NULL;}/************************************************************* * gtk_drag_drop: * Send a drop event. * arguments: * * results: *************************************************************/static voidgtk_drag_drop (GtkDragSourceInfo *info, guint32 time){ if (info->context->protocol == GDK_DRAG_PROTO_ROOTWIN) { GtkSelectionData selection_data; GList *tmp_list; GdkAtom target = gdk_atom_intern ("application/x-rootwin-drop", FALSE); tmp_list = info->target_list->list; while (tmp_list) { GtkTargetPair *pair = tmp_list->data; if (pair->target == target) { selection_data.selection = GDK_NONE; selection_data.target = target; selection_data.data = NULL; selection_data.length = -1; gtk_signal_emit_by_name (GTK_OBJECT (info->widget), "drag_data_get", info->context, &selection_data, pair->info, time); /* FIXME: Should we check for length >= 0 here? */ gtk_drag_drop_finished (info, TRUE, time); return; } tmp_list = tmp_list->next; } gtk_drag_drop_finished (info, FALSE, time); } else { if (info->icon_window) gtk_widget_hide (info->icon_window); gdk_drag_drop (info->context, time); info->drop_timeout = gtk_timeout_add (DROP_ABORT_TIME, gtk_drag_abort_timeout, info); }}/* * Source side callbacks. */static gintgtk_drag_source_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data){ GtkDragSourceSite *site; site = (GtkDragSourceSite *)data; switch (event->type) { case GDK_BUTTON_PRESS: if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask) { site->state |= (GDK_BUTTON1_MASK << (event->button.button - 1)); site->x = event->button.x; site->y = event->button.y; } break; case GDK_BUTTON_RELEASE: if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask) { site->state &= ~(GDK_BUTTON1_MASK << (event->button.button - 1)); } break; case GDK_MOTION_NOTIFY: if (site->state & event->motion.state & site->start_button_mask) { /* FIXME: This is really broken and can leave us
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -