diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-11-30 23:08:24 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-11-30 23:08:24 +0800 |
commit | 740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc (patch) | |
tree | 0e9497b8a933cab09ee209d92097c5f273612ded /src | |
parent | 8d21537a22e1e4a1e6224d5e70190e0be2ef9a40 (diff) | |
parent | 9ec54fdc072173c6676ec2d8ea0b8eabe6936cef (diff) | |
download | gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar.gz gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar.bz2 gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar.lz gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar.xz gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.tar.zst gsoc2013-empathy-740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc.zip |
Merge commit 'shaunm/dndfiles2'
Diffstat (limited to 'src')
-rw-r--r-- | src/empathy-chat-window.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index b9e1e1bf3..ea63f29aa 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -80,6 +80,9 @@ typedef struct { NotifyNotification *notification; NotificationData *notification_data; + GtkTargetList *contact_targets; + GtkTargetList *file_targets; + /* Menu items. */ GtkUIManager *ui_manager; GtkAction *menu_conv_insert_smiley; @@ -106,12 +109,22 @@ static const guint tab_accel_keys[] = { typedef enum { DND_DRAG_TYPE_CONTACT_ID, + DND_DRAG_TYPE_URI_LIST, DND_DRAG_TYPE_TAB } DndDragType; static const GtkTargetEntry drag_types_dest[] = { { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB }, + { "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST }, +}; + +static const GtkTargetEntry drag_types_dest_contact[] = { + { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, +}; + +static const GtkTargetEntry drag_types_dest_file[] = { + { "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST }, }; static void chat_window_update (EmpathyChatWindow *window); @@ -1410,6 +1423,68 @@ chat_window_focus_in_event_cb (GtkWidget *widget, return FALSE; } +static gboolean +chat_window_drag_motion (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + guint time_, + EmpathyChatWindow *window) +{ + GdkAtom target; + EmpathyChatWindowPriv *priv; + GdkAtom dest_target; + + priv = GET_PRIV (window); + + target = gtk_drag_dest_find_target (widget, context, NULL); + + dest_target = gdk_atom_intern_static_string ("text/uri-list"); + if (target == dest_target) { + /* This is a file drag. Ensure the contact is online and set the + drag type to COPY. Note that it's possible that the tab will + be switched by GTK+ after a timeout from drag_motion without + getting another drag_motion to disable the drop. You have + to hold your mouse really still. + */ + EmpathyContact *contact; + + priv = GET_PRIV (window); + contact = empathy_chat_get_remote_contact (priv->current_chat); + /* contact is NULL for multi-user chats. We don't do + * file transfers to MUCs. We also don't send files + * to offline contacts or contacts that don't support + * file transfer. + */ + if ((contact == NULL) || !empathy_contact_is_online (contact)) { + gdk_drag_status (context, 0, time_); + return FALSE; + } + if (!(empathy_contact_get_capabilities (contact) + & EMPATHY_CAPABILITIES_FT)) { + gdk_drag_status (context, 0, time_); + return FALSE; + } + gdk_drag_status (context, GDK_ACTION_COPY, time_); + return TRUE; + } + + dest_target = gdk_atom_intern_static_string ("text/contact-id"); + if (target == dest_target) { + /* This is a drag of a contact from a contact list. Set to COPY. + FIXME: If this drag is to a MUC window, it invites the user. + Otherwise, it opens a chat. Should we use a different drag + type for invites? Should we allow ASK? + */ + gdk_drag_status (context, GDK_ACTION_COPY, time_); + return TRUE; + } + + /* Otherwise, it must be a notebook tab drag. Set to MOVE. */ + gdk_drag_status (context, GDK_ACTION_MOVE, time_); + return TRUE; +} + static void chat_window_drag_data_received (GtkWidget *widget, GdkDragContext *context, @@ -1492,6 +1567,27 @@ chat_window_drag_data_received (GtkWidget *widget, */ gtk_drag_finish (context, TRUE, FALSE, time_); } + else if (info == DND_DRAG_TYPE_URI_LIST) { + EmpathyChatWindowPriv *priv; + EmpathyContact *contact; + const gchar *data; + + priv = GET_PRIV (window); + contact = empathy_chat_get_remote_contact (priv->current_chat); + + /* contact is NULL when current_chat is a multi-user chat. + * We don't do file transfers to MUCs, so just cancel the drag. + */ + if (contact == NULL) { + gtk_drag_finish (context, TRUE, FALSE, time_); + return; + } + + data = (const gchar *) gtk_selection_data_get_data (selection); + empathy_send_file_from_uri_list (contact, data); + + gtk_drag_finish (context, TRUE, FALSE, time_); + } else if (info == DND_DRAG_TYPE_TAB) { EmpathyChat **chat; EmpathyChatWindow *old_window = NULL; @@ -1554,6 +1650,13 @@ chat_window_finalize (GObject *object) } } + if (priv->contact_targets) { + gtk_target_list_unref (priv->contact_targets); + } + if (priv->file_targets) { + gtk_target_list_unref (priv->file_targets); + } + chat_windows = g_list_remove (chat_windows, window); gtk_widget_destroy (priv->dialog); @@ -1665,6 +1768,12 @@ empathy_chat_window_init (EmpathyChatWindow *window) g_object_unref (accel_group); + /* Set up drag target lists */ + priv->contact_targets = gtk_target_list_new (drag_types_dest_contact, + G_N_ELEMENTS (drag_types_dest_contact)); + priv->file_targets = gtk_target_list_new (drag_types_dest_file, + G_N_ELEMENTS (drag_types_dest_file)); + /* Set up smiley menu */ smiley_manager = empathy_smiley_manager_dup_singleton (); submenu = empathy_smiley_menu_new (smiley_manager, @@ -1705,8 +1814,13 @@ empathy_chat_window_init (EmpathyChatWindow *window) GTK_DEST_DEFAULT_ALL, drag_types_dest, G_N_ELEMENTS (drag_types_dest), - GDK_ACTION_MOVE); + GDK_ACTION_MOVE | GDK_ACTION_COPY); + /* connect_after to allow GtkNotebook's built-in tab switching */ + g_signal_connect_after (priv->notebook, + "drag-motion", + G_CALLBACK (chat_window_drag_motion), + window); g_signal_connect (priv->notebook, "drag-data-received", G_CALLBACK (chat_window_drag_data_received), |