aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-11-30 23:08:24 +0800
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-11-30 23:08:24 +0800
commit740a34efd932ad1bf6d5cd1d4580fd3b6af0eacc (patch)
tree0e9497b8a933cab09ee209d92097c5f273612ded /src
parent8d21537a22e1e4a1e6224d5e70190e0be2ef9a40 (diff)
parent9ec54fdc072173c6676ec2d8ea0b8eabe6936cef (diff)
downloadgsoc2013-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.c116
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),