📄 gtkdnd.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include "gdk/gdkx.h"#include "gdk/gdkkeysyms.h"#include "gtkdnd.h"#include "gtkinvisible.h"#include "gtkmain.h"#include "gtksignal.h"#include "gtkwindow.h"static GSList *drag_widgets = NULL;static GSList *source_widgets = NULL;typedef struct _GtkDragSourceSite GtkDragSourceSite;typedef struct _GtkDragSourceInfo GtkDragSourceInfo;typedef struct _GtkDragDestSite GtkDragDestSite;typedef struct _GtkDragDestInfo GtkDragDestInfo;typedef struct _GtkDragAnim GtkDragAnim;typedef struct _GtkDragFindData GtkDragFindData;typedef enum { GTK_DRAG_STATUS_DRAG, GTK_DRAG_STATUS_WAIT, GTK_DRAG_STATUS_DROP} GtkDragStatus;struct _GtkDragSourceSite { GdkModifierType start_button_mask; GtkTargetList *target_list; /* Targets for drag data */ GdkDragAction actions; /* Possible actions */ GdkColormap *colormap; /* Colormap for drag icon */ GdkPixmap *pixmap; /* Icon for drag data */ GdkBitmap *mask; /* Stored button press information to detect drag beginning */ gint state; gint x, y;}; struct _GtkDragSourceInfo { GtkWidget *widget; GtkTargetList *target_list; /* Targets for drag data */ GdkDragAction possible_actions; /* Actions allowed by source */ GdkDragContext *context; /* drag context */ GtkWidget *icon_window; /* Window for drag */ GtkWidget *ipc_widget; /* GtkInvisible for grab, message passing */ GdkCursor *cursor; /* Cursor for drag */ gint hot_x, hot_y; /* Hot spot for drag */ gint button; /* mouse button starting drag */ GtkDragStatus status; /* drag status */ GdkEvent *last_event; /* motion event waiting for response */ gint start_x, start_y; /* Initial position */ gint cur_x, cur_y; /* Current Position */ GList *selections; /* selections we've claimed */ GtkDragDestInfo *proxy_dest; /* Set if this is a proxy drag */ guint drop_timeout; /* Timeout for aborting drop */ guint destroy_icon : 1; /* If true, destroy icon_window */};struct _GtkDragDestSite { GtkDestDefaults flags; GtkTargetList *target_list; GdkDragAction actions; GdkWindow *proxy_window; GdkDragProtocol proxy_protocol; gboolean do_proxy : 1; gboolean proxy_coords : 1; gboolean have_drag : 1;}; struct _GtkDragDestInfo { GtkWidget *widget; /* Widget in which drag is in */ GdkDragContext *context; /* Drag context */ GtkDragSourceInfo *proxy_source; /* Set if this is a proxy drag */ GtkSelectionData *proxy_data; /* Set while retrieving proxied data */ gboolean dropped : 1; /* Set after we receive a drop */ guint32 proxy_drop_time; /* Timestamp for proxied drop */ gboolean proxy_drop_wait : 1; /* Set if we are waiting for a * status reply before sending * a proxied drop on. */ gint drop_x, drop_y; /* Position of drop */};#define DROP_ABORT_TIME 300000#define ANIM_STEP_TIME 50#define ANIM_STEP_LENGTH 50#define ANIM_MIN_STEPS 5#define ANIM_MAX_STEPS 10struct _GtkDragAnim { GtkDragSourceInfo *info; gint step; gint n_steps;};struct _GtkDragFindData { gint x; gint y; GdkDragContext *context; GtkDragDestInfo *info; gboolean found; gboolean toplevel; gboolean (*callback) (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint32 time); guint32 time;};/* Enumeration for some targets we handle internally */enum { TARGET_MOTIF_SUCCESS = 0x40000000, TARGET_MOTIF_FAILURE, TARGET_DELETE};/* Drag icons */static GdkPixmap *default_icon_pixmap = NULL;static GdkPixmap *default_icon_mask = NULL;static GdkColormap *default_icon_colormap = NULL;static gint default_icon_hot_x;static gint default_icon_hot_y;/* Forward declarations */static void gtk_drag_get_event_actions (GdkEvent *event, gint button, GdkDragAction actions, GdkDragAction *suggested_action, GdkDragAction *possible_actions);static GdkCursor * gtk_drag_get_cursor (GdkDragAction action);static GtkWidget *gtk_drag_get_ipc_widget (void);static void gtk_drag_release_ipc_widget (GtkWidget *widget);static void gtk_drag_highlight_paint (GtkWidget *widget);static gboolean gtk_drag_highlight_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data);static GdkAtom gtk_drag_dest_find_target (GtkWidget *widget, GtkDragDestSite *site, GdkDragContext *context);static void gtk_drag_selection_received (GtkWidget *widget, GtkSelectionData *selection_data, guint32 time, gpointer data);static void gtk_drag_find_widget (GtkWidget *widget, GtkDragFindData *data);static void gtk_drag_proxy_begin (GtkWidget *widget, GtkDragDestInfo *dest_info);static void gtk_drag_dest_info_destroy (gpointer data);static void gtk_drag_dest_realized (GtkWidget *widget);static void gtk_drag_dest_site_destroy (gpointer data);static void gtk_drag_dest_leave (GtkWidget *widget, GdkDragContext *context, guint time);static gboolean gtk_drag_dest_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time);static gboolean gtk_drag_dest_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time);static void gtk_drag_source_check_selection (GtkDragSourceInfo *info, GdkAtom selection, guint32 time);static void gtk_drag_source_release_selections (GtkDragSourceInfo *info, guint32 time);static void gtk_drag_drop (GtkDragSourceInfo *info, guint32 time);static void gtk_drag_drop_finished (GtkDragSourceInfo *info, gboolean success, guint time);static gint gtk_drag_source_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data);static void gtk_drag_source_site_destroy (gpointer data);static void gtk_drag_selection_get (GtkWidget *widget, GtkSelectionData *selection_data, guint sel_info, guint32 time, gpointer data);static gint gtk_drag_anim_timeout (gpointer data);static void gtk_drag_remove_icon (GtkDragSourceInfo *info);static void gtk_drag_source_info_destroy (gpointer data);static void gtk_drag_update (GtkDragSourceInfo *info, gint x_root, gint y_root, GdkEvent *event);static gint gtk_drag_motion_cb (GtkWidget *widget, GdkEventMotion *event, gpointer data);static gint gtk_drag_key_cb (GtkWidget *widget, GdkEventKey *event, gpointer data);static gint gtk_drag_button_release_cb (GtkWidget *widget, GdkEventButton *event, gpointer data);static gint gtk_drag_abort_timeout (gpointer data);/************************ * Cursor and Icon data * ************************/#define action_ask_width 16#define action_ask_height 16static const guchar action_ask_bits[] = { 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x1f, 0x06, 0xc0, 0x76, 0xf8, 0xb6, 0xf7, 0xd6, 0xec, 0x66, 0xdb, 0x66, 0xdb, 0x96, 0xec, 0x76, 0xf7, 0x76, 0xfb, 0xf6, 0xfc, 0x72, 0xfb, 0x7a, 0xfb, 0xf8, 0xfc, };#define action_ask_mask_width 16#define action_ask_mask_height 16static const guchar action_ask_mask_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x8f, 0x07, 0xcf, 0x0f, 0xef, 0x1f, 0xff, 0x3c, 0xff, 0x3c, 0x6f, 0x1f, 0x8f, 0x0f, 0x8f, 0x07, 0x0f, 0x03, 0x8f, 0x07, 0x87, 0x07, 0x07, 0x03, };#define action_copy_width 16#define action_copy_height 16static const guchar action_copy_bits[] = { 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x1f, 0x06, 0xc0, 0x76, 0xfb, 0x76, 0xfb, 0x76, 0xfb, 0x06, 0x83, 0xf6, 0xbf, 0xf6, 0xbf, 0x06, 0x83, 0x76, 0xfb, 0x76, 0xfb, 0x72, 0xfb, 0x7a, 0xf8, 0xf8, 0xff, };#define action_copy_mask_width 16#define action_copy_mask_height 16static const guchar action_copy_mask_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x8f, 0x07, 0x8f, 0x07, 0x8f, 0x07, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x8f, 0x07, 0x8f, 0x07, 0x8f, 0x07, 0x87, 0x07, 0x07, 0x00, };#define action_move_width 16#define action_move_height 16static const guchar action_move_bits[] = { 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x1f, 0x06, 0xc0, 0x96, 0xff, 0x26, 0xff, 0xc6, 0xf8, 0xd6, 0xe3, 0x96, 0x8f, 0xb6, 0xbf, 0x36, 0xc3, 0x76, 0xfb, 0x76, 0xfa, 0xf2, 0xfa, 0xfa, 0xf8, 0xf8, 0xff, };#define action_move_mask_width 16#define action_move_mask_height 16static const guchar action_move_mask_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x6f, 0x00, 0xff, 0x00, 0xff, 0x07, 0xef, 0x1f, 0xef, 0x7f, 0xcf, 0x7f, 0xcf, 0x3f, 0x8f, 0x07, 0x8f, 0x07, 0x0f, 0x07, 0x07, 0x07, 0x07, 0x00, };#define action_link_width 16#define action_link_height 16static const guchar action_link_bits[] = { 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x1f, 0x06, 0xc0, 0x36, 0xf8, 0xd6, 0xf7, 0x66, 0xec, 0xa6, 0xe8, 0x26, 0xdf, 0xe6, 0xbd, 0xd6, 0xa7, 0xb6, 0xa8, 0xb6, 0xb1, 0x72, 0xdf, 0xfa, 0xe0, 0xf8, 0xff, };#define action_link_mask_width 16#define action_link_mask_height 16static const guchar action_link_mask_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xcf, 0x07, 0xef, 0x0f, 0xff, 0x1f, 0x7f, 0x1f, 0xff, 0x3f, 0xff, 0x7f, 0xef, 0x7f, 0xcf, 0x77, 0xcf, 0x7f, 0x8f, 0x3f, 0x07, 0x1f, 0x07, 0x00, };#define action_none_width 16#define action_none_height 16static const guchar action_none_bits[] = { 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x1f, 0x06, 0xc0, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf2, 0xff, 0xfa, 0xff, 0xf8, 0xff, };#define action_none_mask_width 16#define action_none_mask_height 16static const guchar action_none_mask_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x07, 0x00, };#define CURSOR_WIDTH 16#define CURSOR_HEIGHT 16static struct { GdkDragAction action; const char *bits; const char *mask; GdkCursor *cursor;} drag_cursors[] = { { GDK_ACTION_DEFAULT, 0 }, { GDK_ACTION_ASK, action_ask_bits, action_ask_mask_bits, NULL }, { GDK_ACTION_COPY, action_copy_bits, action_copy_mask_bits, NULL }, { GDK_ACTION_MOVE, action_move_bits, action_move_mask_bits, NULL }, { GDK_ACTION_LINK, action_link_bits, action_link_mask_bits, NULL }, { 0 , action_none_bits, action_none_mask_bits, NULL },};static const gint n_drag_cursors = sizeof (drag_cursors) / sizeof (drag_cursors[0]);/* XPM */static const char *drag_default_xpm[] = {"32 32 3 1"," c None",". c #000000","+ c #FFFFFF"," "," "," .. "," ..+. "," ..++.. "," ...++++. "," ...++++++.. "," ...+++++++++. "," ...+++++++++++.. "," ..+.++++++++++++.. "," .++.++++++++++++.. "," .+++.++++++++++++.. "," .++++.++++++++++++. "," .+++.+++++++++++++.. "," .++.+++++++++++++++.. "," .+.+++++++++++++++++.. "," ..+++++++++++++++++++.. "," ..++++++++++++++++++++. "," .++++++++++++++++++++.. "," ..+++++++++++++++++.. "," .++++++++++++++++.. "," ..+++++++++++++... "," .++++++++++++.. "," ..+++++++++.. "," .++++++++.. "," ..++++++.. "," .+++++.. "," .++.. "," ... "," .. "," "," "};/********************* * Utility functions * *********************//************************************************************* * gtk_drag_get_ipc_widget: * Return a invisible, off-screen, override-redirect * widget for IPC. * arguments: * * results: *************************************************************/static GtkWidget *gtk_drag_get_ipc_widget (void){ GtkWidget *result; if (drag_widgets) { GSList *tmp = drag_widgets; result = drag_widgets->data; drag_widgets = drag_widgets->next; g_slist_free_1 (tmp); } else { result = gtk_invisible_new (); gtk_widget_show (result); } return result;}/*************************************************************** * gtk_drag_release_ipc_widget: * Releases widget retrieved with gtk_drag_get_ipc_widget () * arguments: * widget: the widget to release. * results: ***************************************************************/static voidgtk_drag_release_ipc_widget (GtkWidget *widget){ drag_widgets = g_slist_prepend (drag_widgets, widget);}static guint32gtk_drag_get_event_time (GdkEvent *event){ guint32 tm = GDK_CURRENT_TIME; if (event) switch (event->type) { case GDK_MOTION_NOTIFY: tm = event->motion.time; break; case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: case GDK_BUTTON_RELEASE: tm = event->button.time; break; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: tm = event->key.time; break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: tm = event->crossing.time; break; case GDK_PROPERTY_NOTIFY: tm = event->property.time; break; case GDK_SELECTION_CLEAR: case GDK_SELECTION_REQUEST: case GDK_SELECTION_NOTIFY: tm = event->selection.time; break; case GDK_PROXIMITY_IN: case GDK_PROXIMITY_OUT: tm = event->proximity.time; break; default: /* use current time */ break; } return tm;}static voidgtk_drag_get_event_actions (GdkEvent *event, gint button, GdkDragAction actions, GdkDragAction *suggested_action, GdkDragAction *possible_actions){ *suggested_action = 0; *possible_actions = 0; if (event)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -