~ubuntu-branches/ubuntu/maverick/empathy/maverick

1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
/*
3
 * Copyright (C) 2003-2007 Imendio AB
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
4
 * Copyright (C) 2007-2008 Collabora Ltd.
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License as
8
 * published by the Free Software Foundation; either version 2 of the
9
 * License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public
17
 * License along with this program; if not, write to the
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
18
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19
 * Boston, MA  02110-1301  USA
20
 *
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
21
 * Authors: Mikael Hallendal <micke@imendio.com>
22
 *          Richard Hult <richard@imendio.com>
23
 *          Martyn Russell <martyn@imendio.com>
24
 *          Geert-Jan Van den Bogaerde <geertjan@gnome.org>
25
 *          Xavier Claessens <xclaesse@gmail.com>
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
26
 *          RĂ´mulo Fernandes Machado <romulo@castorgroup.net>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
27
 */
28
29
#include <config.h>
30
31
#include <string.h>
32
33
#include <gtk/gtk.h>
34
#include <gdk/gdkkeysyms.h>
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
35
#include <gdk/gdkx.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
36
#include <glib/gi18n.h>
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
37
#include <libnotify/notification.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
38
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
39
/* Add launchpad hooks */
40
#include <launchpad-integration.h>
41
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
42
#include <telepathy-glib/telepathy-glib.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
43
44
#include <libempathy/empathy-contact.h>
45
#include <libempathy/empathy-message.h>
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
46
#include <libempathy/empathy-chatroom-manager.h>
1.1.55 by Robert Ancell
Import upstream version 2.31.4
47
#include <libempathy/empathy-gsettings.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
48
#include <libempathy/empathy-utils.h>
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
49
#include <libempathy/empathy-tp-contact-factory.h>
50
#include <libempathy/empathy-contact-list.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
51
52
#include <libempathy-gtk/empathy-images.h>
53
#include <libempathy-gtk/empathy-contact-dialogs.h>
54
#include <libempathy-gtk/empathy-log-window.h>
55
#include <libempathy-gtk/empathy-geometry.h>
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
56
#include <libempathy-gtk/empathy-smiley-manager.h>
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
57
#include <libempathy-gtk/empathy-sound.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
58
#include <libempathy-gtk/empathy-ui-utils.h>
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
59
#include <libempathy-gtk/empathy-notify-manager.h>
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
60
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
61
#include "empathy-chat-manager.h"
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
62
#include "empathy-chat-window.h"
63
#include "empathy-about-dialog.h"
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
64
#include "empathy-invite-participant-dialog.h"
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
65
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
66
#ifdef HAVE_LIBINDICATE
67
#include "empathy-indicator.h"
68
#include "empathy-indicator-manager.h"
69
#endif
70
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
71
#define DEBUG_FLAG EMPATHY_DEBUG_CHAT
72
#include <libempathy/empathy-debug.h>
73
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
74
/* Macro to compare guint32 X timestamps, while accounting for wrapping around
75
 */
76
#define X_EARLIER_OR_EQL(t1, t2) \
77
	((t1 <= t2 && ((t2 - t1) < G_MAXUINT32/2))  \
78
	  || (t1 >= t2 && (t1 - t2) > (G_MAXUINT32/2)) \
79
	)
80
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
81
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyChatWindow)
82
typedef struct {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
83
	EmpathyChat *current_chat;
84
	GList       *chats;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
85
	GList       *chats_new_msg;
86
	GList       *chats_composing;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
87
	gboolean     page_added;
88
	gboolean     dnd_same_window;
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
89
	EmpathyChatroomManager *chatroom_manager;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
90
	EmpathyNotifyManager *notify_mgr;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
91
	GtkWidget   *dialog;
92
	GtkWidget   *notebook;
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
93
	NotifyNotification *notification;
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
94
#ifdef HAVE_LIBINDICATE
95
	EmpathyIndicatorManager *indicator_manager;
96
	/* EmpathyChat -> EmpathyIndicator for that chat, if any */
97
	GHashTable  *indicators;
98
#endif
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
99
	GtkTargetList *contact_targets;
100
	GtkTargetList *file_targets;
101
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
102
	EmpathyChatManager *chat_manager;
103
	gulong chat_manager_chats_changed_id;
104
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
105
	/* Menu items. */
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
106
	GtkUIManager *ui_manager;
107
	GtkAction   *menu_conv_insert_smiley;
108
	GtkAction   *menu_conv_favorite;
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
109
	GtkAction   *menu_conv_always_urgent;
1.1.32 by Didier Roche
Import upstream version 2.27.4
110
	GtkAction   *menu_conv_toggle_contacts;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
111
112
	GtkAction   *menu_edit_cut;
113
	GtkAction   *menu_edit_copy;
114
	GtkAction   *menu_edit_paste;
1.1.44 by Didier Roche
Import upstream version 2.29.6
115
	GtkAction   *menu_edit_find;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
116
117
	GtkAction   *menu_tabs_next;
118
	GtkAction   *menu_tabs_prev;
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
119
	GtkAction   *menu_tabs_undo_close_tab;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
120
	GtkAction   *menu_tabs_left;
121
	GtkAction   *menu_tabs_right;
122
	GtkAction   *menu_tabs_detach;
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
123
124
	/* Last user action time we acted upon to show a tab */
125
	guint32    x_user_action_time;
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
126
} EmpathyChatWindowPriv;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
127
128
static GList *chat_windows = NULL;
129
130
static const guint tab_accel_keys[] = {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
131
	GDK_1, GDK_2, GDK_3, GDK_4, GDK_5,
132
	GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
133
};
134
135
typedef enum {
136
	DND_DRAG_TYPE_CONTACT_ID,
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
137
	DND_DRAG_TYPE_URI_LIST,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
138
	DND_DRAG_TYPE_TAB
139
} DndDragType;
140
141
static const GtkTargetEntry drag_types_dest[] = {
142
	{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
143
	{ "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB },
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
144
	{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
1.1.50 by Ken VanDine
Import upstream version 2.29.93
145
	{ "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
146
};
147
148
static const GtkTargetEntry drag_types_dest_contact[] = {
149
	{ "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
150
};
151
152
static const GtkTargetEntry drag_types_dest_file[] = {
1.1.50 by Ken VanDine
Import upstream version 2.29.93
153
	/* must be first to be prioritized, in order to receive the
154
	 * note's file path from Tomboy instead of an URI */
155
	{ "text/path-list", 0, DND_DRAG_TYPE_URI_LIST },
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
156
	{ "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST },
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
157
};
158
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
159
static void chat_window_update (EmpathyChatWindow *window);
1.8.1 by Emilio Pozuelo Monfort
Import upstream version 2.91.3
160
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
161
G_DEFINE_TYPE (EmpathyChatWindow, empathy_chat_window, G_TYPE_OBJECT);
162
163
static void
164
chat_window_accel_cb (GtkAccelGroup    *accelgroup,
165
		      GObject          *object,
166
		      guint             key,
167
		      GdkModifierType   mod,
168
		      EmpathyChatWindow *window)
169
{
170
	EmpathyChatWindowPriv *priv;
171
	gint                  num = -1;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
172
	guint                 i;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
173
174
	priv = GET_PRIV (window);
175
176
	for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
177
		if (tab_accel_keys[i] == key) {
178
			num = i;
179
			break;
180
		}
181
	}
182
183
	if (num != -1) {
184
		gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), num);
185
	}
186
}
187
188
static EmpathyChatWindow *
189
chat_window_find_chat (EmpathyChat *chat)
190
{
191
	EmpathyChatWindowPriv *priv;
192
	GList                 *l, *ll;
193
194
	for (l = chat_windows; l; l = l->next) {
195
		priv = GET_PRIV (l->data);
196
		ll = g_list_find (priv->chats, chat);
197
		if (ll) {
198
			return l->data;
199
		}
200
	}
201
202
	return NULL;
203
}
204
205
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
206
chat_window_close_clicked_cb (GtkAction   *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
207
			      EmpathyChat *chat)
208
{
209
	EmpathyChatWindow *window;
210
211
	window = chat_window_find_chat (chat);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
212
	empathy_chat_window_remove_chat (window, chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
213
}
214
215
static void
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
216
chat_tab_style_set_cb (GtkWidget *hbox,
217
				       GtkStyle  *previous_style,
218
				       gpointer   user_data)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
219
{
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
220
	GtkWidget *button;
221
	int char_width, h, w;
222
	PangoContext *context;
223
	PangoFontMetrics *metrics;
224
225
	button = g_object_get_data (G_OBJECT (user_data),
226
		"chat-window-tab-close-button");
227
	context = gtk_widget_get_pango_context (hbox);
228
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
229
	metrics = pango_context_get_metrics (context, gtk_widget_get_style (hbox)->font_desc,
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
230
		pango_context_get_language (context));
231
	char_width = pango_font_metrics_get_approximate_char_width (metrics);
232
	pango_font_metrics_unref (metrics);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
233
234
	gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
235
					   GTK_ICON_SIZE_MENU, &w, &h);
236
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
237
	/* Request at least about 12 chars width plus at least space for the status
238
	 * image and the close button */
239
	gtk_widget_set_size_request (hbox,
240
		12 * PANGO_PIXELS (char_width) + 2 * w, -1);
241
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
242
	gtk_widget_set_size_request (button, w, h);
243
}
244
245
static GtkWidget *
246
chat_window_create_label (EmpathyChatWindow *window,
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
247
			  EmpathyChat       *chat,
248
			  gboolean           is_tab_label)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
249
{
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
250
	EmpathyChatWindowPriv *priv;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
251
	GtkWidget            *hbox;
252
	GtkWidget            *name_label;
253
	GtkWidget            *status_image;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
254
	GtkWidget            *close_button;
255
	GtkWidget            *close_image;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
256
	GtkWidget            *event_box;
257
	GtkWidget            *event_box_hbox;
258
	PangoAttrList        *attr_list;
259
	PangoAttribute       *attr;
260
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
261
	priv = GET_PRIV (window);
262
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
263
	/* The spacing between the button and the label. */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
264
	hbox = gtk_hbox_new (FALSE, 0);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
265
266
	event_box = gtk_event_box_new ();
267
	gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
268
269
	name_label = gtk_label_new (NULL);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
270
	if (is_tab_label)
271
		gtk_label_set_ellipsize (GTK_LABEL (name_label), PANGO_ELLIPSIZE_END);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
272
273
	attr_list = pango_attr_list_new ();
274
	attr = pango_attr_scale_new (1/1.2);
275
	attr->start_index = 0;
276
	attr->end_index = -1;
277
	pango_attr_list_insert (attr_list, attr);
278
	gtk_label_set_attributes (GTK_LABEL (name_label), attr_list);
279
	pango_attr_list_unref (attr_list);
280
281
	gtk_misc_set_padding (GTK_MISC (name_label), 2, 0);
282
	gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
283
	g_object_set_data (G_OBJECT (chat),
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
284
		is_tab_label ? "chat-window-tab-label" : "chat-window-menu-label",
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
285
		name_label);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
286
287
	status_image = gtk_image_new ();
288
289
	/* Spacing between the icon and label. */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
290
	event_box_hbox = gtk_hbox_new (FALSE, 0);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
291
292
	gtk_box_pack_start (GTK_BOX (event_box_hbox), status_image, FALSE, FALSE, 0);
293
	gtk_box_pack_start (GTK_BOX (event_box_hbox), name_label, TRUE, TRUE, 0);
294
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
295
	g_object_set_data (G_OBJECT (chat),
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
296
		is_tab_label ? "chat-window-tab-image" : "chat-window-menu-image",
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
297
		status_image);
298
	g_object_set_data (G_OBJECT (chat),
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
299
		is_tab_label ? "chat-window-tab-tooltip-widget" : "chat-window-menu-tooltip-widget",
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
300
		event_box);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
301
302
	gtk_container_add (GTK_CONTAINER (event_box), event_box_hbox);
303
	gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, TRUE, 0);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
304
305
	if (is_tab_label) {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
306
		close_button = gtk_button_new ();
307
		gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
308
		g_object_set_data (G_OBJECT (chat), "chat-window-tab-close-button", close_button);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
309
310
		/* We don't want focus/keynav for the button to avoid clutter, and
311
		 * Ctrl-W works anyway.
312
		 */
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
313
		gtk_widget_set_can_focus (close_button, FALSE);
314
		gtk_widget_set_can_default (close_button, FALSE);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
315
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
316
		/* Set the name to make the special rc style match. */
317
		gtk_widget_set_name (close_button, "empathy-close-button");
318
319
		close_image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
320
321
		gtk_container_add (GTK_CONTAINER (close_button), close_image);
322
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
323
		gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
324
325
		g_signal_connect (close_button,
326
				  "clicked",
327
				  G_CALLBACK (chat_window_close_clicked_cb),
328
				  chat);
329
330
		/* React to theme changes and also setup the size correctly.  */
331
		g_signal_connect (hbox,
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
332
				  "style-set",
333
				  G_CALLBACK (chat_tab_style_set_cb),
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
334
				  chat);
335
	}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
336
337
	gtk_widget_show_all (hbox);
338
339
	return hbox;
340
}
341
342
static void
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
343
_submenu_notify_visible_changed_cb (GObject    *object,
344
				    GParamSpec *pspec,
345
				    gpointer    userdata)
346
{
347
	g_signal_handlers_disconnect_by_func (object,
348
					      _submenu_notify_visible_changed_cb,
349
					      userdata);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
350
	chat_window_update (EMPATHY_CHAT_WINDOW (userdata));
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
351
}
352
353
static void
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
354
chat_window_menu_context_update (EmpathyChatWindowPriv *priv,
355
			      gint num_pages)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
356
{
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
357
	gboolean first_page;
358
	gboolean last_page;
1.1.52 by Ken VanDine
Import upstream version 2.30.0.1
359
	gboolean wrap_around;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
360
	gboolean is_connected;
361
	gint     page_num;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
362
363
	page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
364
	first_page = (page_num == 0);
365
	last_page = (page_num == (num_pages - 1));
1.1.52 by Ken VanDine
Import upstream version 2.30.0.1
366
	g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
367
		      &wrap_around, NULL);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
368
	is_connected = empathy_chat_get_tp_chat (priv->current_chat) != NULL;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
369
1.1.52 by Ken VanDine
Import upstream version 2.30.0.1
370
	gtk_action_set_sensitive (priv->menu_tabs_next, (!last_page ||
371
							 wrap_around));
372
	gtk_action_set_sensitive (priv->menu_tabs_prev, (!first_page ||
373
							 wrap_around));
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
374
	gtk_action_set_sensitive (priv->menu_tabs_detach, num_pages > 1);
375
	gtk_action_set_sensitive (priv->menu_tabs_left, !first_page);
376
	gtk_action_set_sensitive (priv->menu_tabs_right, !last_page);
377
	gtk_action_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
378
}
379
380
static void
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
381
chat_window_conversation_menu_update (EmpathyChatWindowPriv *priv,
382
                                      EmpathyChatWindow     *self)
383
{
384
	EmpathyTpChat *tp_chat;
385
	TpConnection *connection;
386
	GtkAction *action;
387
	gboolean sensitive = FALSE;
388
389
	g_return_if_fail (priv->current_chat != NULL);
390
391
	action = gtk_ui_manager_get_action (priv->ui_manager,
392
		"/chats_menubar/menu_conv/menu_conv_invite_participant");
393
	tp_chat = empathy_chat_get_tp_chat (priv->current_chat);
394
395
	if (tp_chat != NULL) {
396
		connection = empathy_tp_chat_get_connection (tp_chat);
397
398
		sensitive = empathy_tp_chat_can_add_contact (tp_chat) &&
399
			(tp_connection_get_status (connection, NULL) ==
400
			 TP_CONNECTION_STATUS_CONNECTED);
401
	}
402
403
	gtk_action_set_sensitive (action, sensitive);
404
}
405
406
static void
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
407
chat_window_contact_menu_update (EmpathyChatWindowPriv *priv,
408
				 EmpathyChatWindow     *window)
409
{
410
	GtkWidget *menu, *submenu, *orig_submenu;
411
1.1.30 by Laurent Bigonville
Import upstream version 2.27.2
412
	menu = gtk_ui_manager_get_widget (priv->ui_manager,
413
		"/chats_menubar/menu_contact");
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
414
	orig_submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu));
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
415
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
416
	if (orig_submenu == NULL || !gtk_widget_get_visible (orig_submenu)) {
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
417
		submenu = empathy_chat_get_contact_menu (priv->current_chat);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
418
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu), submenu);
419
		gtk_widget_show (menu);
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
420
	} else {
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
421
		tp_g_signal_connect_object (orig_submenu,
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
422
					     "notify::visible",
423
					     (GCallback)_submenu_notify_visible_changed_cb,
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
424
					     window, 0);
1.1.39 by Ken VanDine
Import upstream version 2.28.1.1
425
	}
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
426
}
427
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
428
static guint
429
get_all_unread_messages (EmpathyChatWindowPriv *priv)
430
{
431
	GList *l;
432
	guint nb = 0;
433
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
434
	for (l = priv->chats_new_msg; l != NULL; l = g_list_next (l)) {
435
		EmpathyChat *chat = l->data;
436
437
		nb += empathy_chat_get_nb_unread_messages (chat);
438
	}
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
439
440
	return nb;
441
}
442
443
static gchar *
444
get_window_title_name (EmpathyChatWindowPriv *priv)
445
{
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
446
	const gchar *active_name;
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
447
	guint nb_chats;
448
	guint current_unread_msgs;
449
450
	nb_chats = g_list_length (priv->chats);
451
	g_assert (nb_chats > 0);
452
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
453
	active_name = empathy_chat_get_name (priv->current_chat);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
454
455
	current_unread_msgs = empathy_chat_get_nb_unread_messages (
456
			priv->current_chat);
457
458
	if (nb_chats == 1) {
459
		/* only one tab */
460
		if (current_unread_msgs == 0)
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
461
			return g_strdup (active_name);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
462
		else
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
463
			return g_strdup_printf (ngettext (
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
464
				"%s (%d unread)",
465
				"%s (%d unread)", current_unread_msgs),
466
				active_name, current_unread_msgs);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
467
	} else {
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
468
		guint nb_others = nb_chats - 1;
469
		guint all_unread_msgs;
470
471
		all_unread_msgs = get_all_unread_messages (priv);
472
473
		if (all_unread_msgs == 0) {
474
			/* no unread message */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
475
			return g_strdup_printf (ngettext (
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
476
				"%s (and %u other)",
477
				"%s (and %u others)", nb_others),
478
				active_name, nb_others);
479
		}
480
481
		else if (all_unread_msgs == current_unread_msgs) {
482
			/* unread messages are in the current tab */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
483
			return g_strdup_printf (ngettext (
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
484
				"%s (%d unread)",
485
				"%s (%d unread)", current_unread_msgs),
486
				active_name, current_unread_msgs);
487
		}
488
489
		else if (current_unread_msgs == 0) {
490
			/* unread messages are in other tabs */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
491
			return g_strdup_printf (ngettext (
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
492
				"%s (%d unread from others)",
493
				"%s (%d unread from others)",
494
				all_unread_msgs),
495
				active_name, all_unread_msgs);
496
		}
497
498
		else {
499
			/* unread messages are in all the tabs */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
500
			return g_strdup_printf (ngettext (
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
501
				"%s (%d unread from all)",
502
				"%s (%d unread from all)",
503
				all_unread_msgs),
504
				active_name, all_unread_msgs);
505
		}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
506
	}
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
507
}
508
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
509
static void
510
chat_window_title_update (EmpathyChatWindowPriv *priv)
511
{
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
512
	gchar *name;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
513
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
514
	name = get_window_title_name (priv);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
515
	gtk_window_set_title (GTK_WINDOW (priv->dialog), name);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
516
	g_free (name);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
517
}
518
519
static void
520
chat_window_icon_update (EmpathyChatWindowPriv *priv)
521
{
522
	GdkPixbuf      *icon;
523
	EmpathyContact *remote_contact;
524
	gboolean        avatar_in_icon;
525
	guint           n_chats;
526
527
	n_chats = g_list_length (priv->chats);
528
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
529
	/* Update window icon */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
530
	if (priv->chats_new_msg) {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
531
		gtk_window_set_icon_name (GTK_WINDOW (priv->dialog),
532
					  EMPATHY_IMAGE_MESSAGE);
533
	} else {
1.1.55 by Robert Ancell
Import upstream version 2.31.4
534
		GSettings *gsettings = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA);
535
536
		avatar_in_icon = g_settings_get_boolean (gsettings,
537
				EMPATHY_PREFS_CHAT_AVATAR_IN_ICON);
1.1.17 by Laurent Bigonville
Import upstream version 2.23.6
538
539
		if (n_chats == 1 && avatar_in_icon) {
540
			remote_contact = empathy_chat_get_remote_contact (priv->current_chat);
541
			icon = empathy_pixbuf_avatar_from_contact_scaled (remote_contact, 0, 0);
542
			gtk_window_set_icon (GTK_WINDOW (priv->dialog), icon);
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
543
544
			if (icon != NULL) {
545
				g_object_unref (icon);
546
			}
1.1.17 by Laurent Bigonville
Import upstream version 2.23.6
547
		} else {
548
			gtk_window_set_icon_name (GTK_WINDOW (priv->dialog), NULL);
549
		}
1.1.55 by Robert Ancell
Import upstream version 2.31.4
550
551
		g_object_unref (gsettings);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
552
	}
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
553
}
554
555
static void
556
chat_window_close_button_update (EmpathyChatWindowPriv *priv,
557
				 gint num_pages)
558
{
559
	GtkWidget *chat;
560
	GtkWidget *chat_close_button;
561
	gint       i;
562
1.1.20 by Laurent Bigonville
Import upstream version 2.23.92
563
	if (num_pages == 1) {
564
		chat = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), 0);
565
		chat_close_button = g_object_get_data (G_OBJECT (chat),
566
				"chat-window-tab-close-button");
567
		gtk_widget_hide (chat_close_button);
568
	} else {
569
		for (i=0; i<num_pages; i++) {
570
			chat = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), i);
571
			chat_close_button = g_object_get_data (G_OBJECT (chat),
572
					"chat-window-tab-close-button");
573
			gtk_widget_show (chat_close_button);
574
		}
575
	}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
576
}
577
578
static void
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
579
chat_window_update (EmpathyChatWindow *window)
580
{
581
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
582
	gint                   num_pages;
583
584
	num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
585
586
	/* Update Tab menu */
587
	chat_window_menu_context_update (priv,
588
					 num_pages);
589
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
590
	chat_window_conversation_menu_update (priv, window);
591
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
592
	chat_window_contact_menu_update (priv,
593
					 window);
594
595
	chat_window_title_update (priv);
596
597
	chat_window_icon_update (priv);
598
599
	chat_window_close_button_update (priv,
600
					 num_pages);
601
}
602
603
static void
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
604
append_markup_printf (GString    *string,
605
		      const char *format,
606
		      ...)
607
{
608
	gchar *tmp;
609
	va_list args;
610
611
	va_start (args, format);
612
613
	tmp = g_markup_vprintf_escaped (format, args);
614
	g_string_append (string, tmp);
615
	g_free (tmp);
616
617
	va_end (args);
618
}
619
620
static void
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
621
chat_window_update_chat_tab (EmpathyChat *chat)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
622
{
623
	EmpathyChatWindow     *window;
624
	EmpathyChatWindowPriv *priv;
625
	EmpathyContact        *remote_contact;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
626
	const gchar           *name;
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
627
	const gchar           *id;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
628
	TpAccount             *account;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
629
	const gchar           *subject;
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
630
	const gchar           *status = NULL;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
631
	GtkWidget             *widget;
632
	GString               *tooltip;
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
633
	gchar                 *markup;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
634
	const gchar           *icon_name;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
635
	GtkWidget             *tab_image;
636
	GtkWidget             *menu_image;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
637
638
	window = chat_window_find_chat (chat);
639
	if (!window) {
640
		return;
641
	}
642
	priv = GET_PRIV (window);
643
644
	/* Get information */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
645
	name = empathy_chat_get_name (chat);
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
646
	account = empathy_chat_get_account (chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
647
	subject = empathy_chat_get_subject (chat);
648
	remote_contact = empathy_chat_get_remote_contact (chat);
649
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
650
	DEBUG ("Updating chat tab, name=%s, account=%s, subject=%s, remote_contact=%p",
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
651
		name, tp_proxy_get_object_path (account), subject, remote_contact);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
652
653
	/* Update tab image */
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
654
	if (empathy_chat_get_tp_chat (chat) == NULL) {
655
		/* No TpChat, we are disconnected */
656
		icon_name = NULL;
657
	}
658
	else if (g_list_find (priv->chats_new_msg, chat)) {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
659
		icon_name = EMPATHY_IMAGE_MESSAGE;
660
	}
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
661
	else if (g_list_find (priv->chats_composing, chat)) {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
662
		icon_name = EMPATHY_IMAGE_TYPING;
663
	}
664
	else if (remote_contact) {
665
		icon_name = empathy_icon_name_for_contact (remote_contact);
666
	} else {
667
		icon_name = EMPATHY_IMAGE_GROUP_MESSAGE;
668
	}
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
669
670
	tab_image = g_object_get_data (G_OBJECT (chat), "chat-window-tab-image");
671
	menu_image = g_object_get_data (G_OBJECT (chat), "chat-window-menu-image");
672
	if (icon_name != NULL) {
673
		gtk_image_set_from_icon_name (GTK_IMAGE (tab_image), icon_name, GTK_ICON_SIZE_MENU);
674
		gtk_widget_show (tab_image);
675
		gtk_image_set_from_icon_name (GTK_IMAGE (menu_image), icon_name, GTK_ICON_SIZE_MENU);
676
		gtk_widget_show (menu_image);
677
	} else {
678
		gtk_widget_hide (tab_image);
679
		gtk_widget_hide (menu_image);
680
	}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
681
682
	/* Update tab tooltip */
683
	tooltip = g_string_new (NULL);
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
684
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
685
	if (remote_contact) {
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
686
		id = empathy_contact_get_id (remote_contact);
687
		status = empathy_contact_get_presence_message (remote_contact);
688
	} else {
689
		id = name;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
690
	}
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
691
692
	append_markup_printf (tooltip,
693
			      "<b>%s</b><small> (%s)</small>",
694
			      id,
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
695
			      tp_account_get_display_name (account));
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
696
697
	if (!EMP_STR_EMPTY (status)) {
698
		append_markup_printf (tooltip, "\n<i>%s</i>", status);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
699
	}
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
700
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
701
	if (subject) {
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
702
		append_markup_printf (tooltip, "\n<b>%s</b> %s",
703
				      _("Topic:"), subject);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
704
	}
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
705
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
706
	if (g_list_find (priv->chats_composing, chat)) {
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
707
		append_markup_printf (tooltip, "\n%s", _("Typing a message."));
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
708
	}
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
709
710
	markup = g_string_free (tooltip, FALSE);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
711
	widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget");
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
712
	gtk_widget_set_tooltip_markup (widget, markup);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
713
	widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-tooltip-widget");
714
	gtk_widget_set_tooltip_markup (widget, markup);
1.1.23 by Laurent Bigonville
Import upstream version 2.25.2
715
	g_free (markup);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
716
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
717
	/* Update tab and menu label */
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
718
	widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
719
	gtk_label_set_text (GTK_LABEL (widget), name);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
720
	widget = g_object_get_data (G_OBJECT (chat), "chat-window-menu-label");
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
721
	gtk_label_set_text (GTK_LABEL (widget), name);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
722
723
	/* Update the window if it's the current chat */
724
	if (priv->current_chat == chat) {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
725
		chat_window_update (window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
726
	}
1.8.10 by Sjoerd Simons
Import upstream version 2.91.91.1
727
}
728
729
static void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
730
chat_window_chat_notify_cb (EmpathyChat *chat)
731
{
732
	EmpathyContact *old_remote_contact;
733
	EmpathyContact *remote_contact = NULL;
734
735
	old_remote_contact = g_object_get_data (G_OBJECT (chat), "chat-window-remote-contact");
736
	remote_contact = empathy_chat_get_remote_contact (chat);
737
738
	if (old_remote_contact != remote_contact) {
739
		/* The remote-contact associated with the chat changed, we need
740
		 * to keep track of any change of that contact and update the
741
		 * window each time. */
742
		if (remote_contact) {
743
			g_signal_connect_swapped (remote_contact, "notify",
744
						  G_CALLBACK (chat_window_update_chat_tab),
745
						  chat);
746
		}
747
		if (old_remote_contact) {
748
			g_signal_handlers_disconnect_by_func (old_remote_contact,
749
							      chat_window_update_chat_tab,
750
							      chat);
751
		}
752
1.1.42 by Laurent Bigonville
Import upstream version 2.29.4
753
		g_object_set_data_full (G_OBJECT (chat), "chat-window-remote-contact",
754
				   g_object_ref (remote_contact), (GDestroyNotify) g_object_unref);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
755
	}
756
757
	chat_window_update_chat_tab (chat);
758
}
759
760
static void
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
761
chat_window_insert_smiley_activate_cb (EmpathySmileyManager *manager,
762
				       EmpathySmiley        *smiley,
763
				       gpointer              window)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
764
{
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
765
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
766
	EmpathyChat           *chat;
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
767
	GtkTextBuffer         *buffer;
768
	GtkTextIter            iter;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
769
770
	chat = priv->current_chat;
771
772
	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
773
	gtk_text_buffer_get_end_iter (buffer, &iter);
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
774
	gtk_text_buffer_insert (buffer, &iter, smiley->str, -1);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
775
}
776
777
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
778
chat_window_conv_activate_cb (GtkAction         *action,
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
779
			      EmpathyChatWindow *window)
780
{
781
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
782
	gboolean               is_room;
1.1.32 by Didier Roche
Import upstream version 2.27.4
783
	gboolean               active;
784
	EmpathyContact        *remote_contact = NULL;
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
785
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
786
	/* Favorite room menu */
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
787
	is_room = empathy_chat_is_room (priv->current_chat);
788
	if (is_room) {
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
789
		const gchar *room;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
790
		TpAccount   *account;
1.1.32 by Didier Roche
Import upstream version 2.27.4
791
		gboolean     found = FALSE;
792
		EmpathyChatroom *chatroom;
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
793
794
		room = empathy_chat_get_id (priv->current_chat);
795
		account = empathy_chat_get_account (priv->current_chat);
1.1.32 by Didier Roche
Import upstream version 2.27.4
796
		chatroom = empathy_chatroom_manager_find (priv->chatroom_manager,
797
						       account, room);
798
		if (chatroom != NULL)
799
			found = empathy_chatroom_is_favorite (chatroom);
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
800
801
		DEBUG ("This room %s favorite", found ? "is" : "is not");
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
802
		gtk_toggle_action_set_active (
803
			GTK_TOGGLE_ACTION (priv->menu_conv_favorite), found);
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
804
805
		if (chatroom != NULL)
806
			found = empathy_chatroom_is_always_urgent (chatroom);
807
808
		gtk_toggle_action_set_active (
809
			GTK_TOGGLE_ACTION (priv->menu_conv_always_urgent),
810
			found);
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
811
	}
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
812
	gtk_action_set_visible (priv->menu_conv_favorite, is_room);
1.1.55 by Robert Ancell
Import upstream version 2.31.4
813
	gtk_action_set_visible (priv->menu_conv_always_urgent, is_room);
1.1.32 by Didier Roche
Import upstream version 2.27.4
814
815
	/* Show contacts menu */
816
	g_object_get (priv->current_chat,
817
		      "remote-contact", &remote_contact,
818
		      "show-contacts", &active,
819
		      NULL);
820
	if (remote_contact == NULL) {
821
		gtk_toggle_action_set_active (
822
			GTK_TOGGLE_ACTION (priv->menu_conv_toggle_contacts),
823
					   active);
824
	}
825
	gtk_action_set_visible (priv->menu_conv_toggle_contacts,
826
				(remote_contact == NULL));
827
	if (remote_contact != NULL) {
828
		g_object_unref (remote_contact);
829
	}
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
830
}
831
832
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
833
chat_window_clear_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
834
			       EmpathyChatWindow *window)
835
{
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
836
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
837
838
	empathy_chat_clear (priv->current_chat);
839
}
840
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
841
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
842
chat_window_favorite_toggled_cb (GtkToggleAction   *toggle_action,
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
843
				 EmpathyChatWindow *window)
844
{
845
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
846
	gboolean               active;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
847
	TpAccount             *account;
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
848
	const gchar           *room;
849
	EmpathyChatroom       *chatroom;
850
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
851
	active = gtk_toggle_action_get_active (toggle_action);
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
852
	account = empathy_chat_get_account (priv->current_chat);
853
	room = empathy_chat_get_id (priv->current_chat);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
854
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
855
	chatroom = empathy_chatroom_manager_ensure_chatroom (
856
		     priv->chatroom_manager,
857
		     account,
858
		     room,
859
		     empathy_chat_get_name (priv->current_chat));
1.1.32 by Didier Roche
Import upstream version 2.27.4
860
861
	empathy_chatroom_set_favorite (chatroom, active);
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
862
	g_object_unref (chatroom);
863
}
864
865
static void
866
chat_window_always_urgent_toggled_cb (GtkToggleAction   *toggle_action,
867
				 EmpathyChatWindow *window)
868
{
869
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
870
	gboolean               active;
871
	TpAccount             *account;
872
	const gchar           *room;
873
	EmpathyChatroom       *chatroom;
874
875
	active = gtk_toggle_action_get_active (toggle_action);
876
	account = empathy_chat_get_account (priv->current_chat);
877
	room = empathy_chat_get_id (priv->current_chat);
878
879
	chatroom = empathy_chatroom_manager_ensure_chatroom (
880
		     priv->chatroom_manager,
881
		     account,
882
		     room,
883
		     empathy_chat_get_name (priv->current_chat));
884
885
	empathy_chatroom_set_always_urgent (chatroom, active);
886
	g_object_unref (chatroom);
1.1.32 by Didier Roche
Import upstream version 2.27.4
887
}
888
889
static void
890
chat_window_contacts_toggled_cb (GtkToggleAction   *toggle_action,
891
				 EmpathyChatWindow *window)
892
{
893
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
894
	gboolean               active;
895
896
	active = gtk_toggle_action_get_active (toggle_action);
897
898
	empathy_chat_set_show_contacts (priv->current_chat, active);
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
899
}
900
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
901
static void
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
902
got_contact_cb (TpConnection            *connection,
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
903
                EmpathyContact          *contact,
904
                const GError            *error,
905
                gpointer                 user_data,
906
                GObject                 *object)
907
{
908
	EmpathyTpChat *tp_chat = EMPATHY_TP_CHAT (user_data);
909
910
	if (error != NULL) {
911
		DEBUG ("Failed: %s", error->message);
912
		return;
913
	} else {
914
		empathy_contact_list_add (EMPATHY_CONTACT_LIST (tp_chat),
915
				contact, _("Inviting you to this room"));
916
	}
917
}
918
919
static void
920
chat_window_invite_participant_activate_cb (GtkAction         *action,
921
					    EmpathyChatWindow *window)
922
{
923
	EmpathyChatWindowPriv *priv;
924
	GtkWidget             *dialog;
925
	EmpathyTpChat         *tp_chat;
926
	TpChannel             *channel;
927
	int                    response;
1.1.50 by Ken VanDine
Import upstream version 2.29.93
928
	TpAccount             *account;
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
929
930
	priv = GET_PRIV (window);
931
932
	g_return_if_fail (priv->current_chat != NULL);
933
934
	tp_chat = empathy_chat_get_tp_chat (priv->current_chat);
935
	channel = empathy_tp_chat_get_channel (tp_chat);
1.1.50 by Ken VanDine
Import upstream version 2.29.93
936
	account = empathy_chat_get_account (priv->current_chat);
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
937
938
	dialog = empathy_invite_participant_dialog_new (
1.1.50 by Ken VanDine
Import upstream version 2.29.93
939
			GTK_WINDOW (priv->dialog), account);
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
940
	gtk_widget_show (dialog);
941
942
	response = gtk_dialog_run (GTK_DIALOG (dialog));
943
944
	if (response == GTK_RESPONSE_ACCEPT) {
945
		TpConnection *connection;
946
		const char *id;
947
948
		id = empathy_contact_selector_dialog_get_selected (
1.7.15 by Laurent Bigonville
Import upstream version 2.31.90
949
				EMPATHY_CONTACT_SELECTOR_DIALOG (dialog), NULL, NULL);
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
950
		if (EMP_STR_EMPTY (id)) goto out;
951
952
		connection = tp_channel_borrow_connection (channel);
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
953
		empathy_tp_contact_factory_get_from_id (connection, id,
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
954
			got_contact_cb, tp_chat,  NULL, NULL);
955
	}
956
957
out:
958
	gtk_widget_destroy (dialog);
959
}
960
961
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
962
chat_window_close_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
963
			       EmpathyChatWindow *window)
964
{
965
	EmpathyChatWindowPriv *priv;
966
967
	priv = GET_PRIV (window);
968
969
	g_return_if_fail (priv->current_chat != NULL);
970
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
971
	empathy_chat_window_remove_chat (window, priv->current_chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
972
}
973
974
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
975
chat_window_edit_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
976
			      EmpathyChatWindow *window)
977
{
978
	EmpathyChatWindowPriv *priv;
979
	GtkClipboard         *clipboard;
980
	GtkTextBuffer        *buffer;
981
	gboolean              text_available;
982
983
	priv = GET_PRIV (window);
984
985
	g_return_if_fail (priv->current_chat != NULL);
986
987
	if (!empathy_chat_get_tp_chat (priv->current_chat)) {
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
988
		gtk_action_set_sensitive (priv->menu_edit_copy, FALSE);
989
		gtk_action_set_sensitive (priv->menu_edit_cut, FALSE);
990
		gtk_action_set_sensitive (priv->menu_edit_paste, FALSE);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
991
		return;
992
	}
993
994
	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->current_chat->input_text_view));
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
995
	if (gtk_text_buffer_get_has_selection (buffer)) {
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
996
		gtk_action_set_sensitive (priv->menu_edit_copy, TRUE);
997
		gtk_action_set_sensitive (priv->menu_edit_cut, TRUE);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
998
	} else {
999
		gboolean selection;
1000
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1001
		selection = empathy_chat_view_get_has_selection (priv->current_chat->view);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1002
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1003
		gtk_action_set_sensitive (priv->menu_edit_cut, FALSE);
1004
		gtk_action_set_sensitive (priv->menu_edit_copy, selection);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1005
	}
1006
1007
	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1008
	text_available = gtk_clipboard_wait_is_text_available (clipboard);
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1009
	gtk_action_set_sensitive (priv->menu_edit_paste, text_available);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1010
}
1011
1012
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1013
chat_window_cut_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1014
			     EmpathyChatWindow *window)
1015
{
1016
	EmpathyChatWindowPriv *priv;
1017
1018
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
1019
1020
	priv = GET_PRIV (window);
1021
1022
	empathy_chat_cut (priv->current_chat);
1023
}
1024
1025
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1026
chat_window_copy_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1027
			      EmpathyChatWindow *window)
1028
{
1029
	EmpathyChatWindowPriv *priv;
1030
1031
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
1032
1033
	priv = GET_PRIV (window);
1034
1035
	empathy_chat_copy (priv->current_chat);
1036
}
1037
1038
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1039
chat_window_paste_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1040
			       EmpathyChatWindow *window)
1041
{
1042
	EmpathyChatWindowPriv *priv;
1043
1044
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
1045
1046
	priv = GET_PRIV (window);
1047
1048
	empathy_chat_paste (priv->current_chat);
1049
}
1050
1051
static void
1.1.44 by Didier Roche
Import upstream version 2.29.6
1052
chat_window_find_activate_cb (GtkAction         *action,
1053
			      EmpathyChatWindow *window)
1054
{
1055
	EmpathyChatWindowPriv *priv;
1056
1057
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
1058
1059
	priv = GET_PRIV (window);
1060
1061
	empathy_chat_find (priv->current_chat);
1062
}
1063
1064
static void
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1065
chat_window_tabs_next_activate_cb (GtkAction         *action,
1066
				   EmpathyChatWindow *window)
1067
{
1068
	EmpathyChatWindowPriv *priv;
1069
	EmpathyChat           *chat;
1070
	gint                  index_, numPages;
1.1.51 by Didier Roche
Import upstream version 2.30.0
1071
	gboolean              wrap_around;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1072
1073
	priv = GET_PRIV (window);
1074
1.1.51 by Didier Roche
Import upstream version 2.30.0
1075
	g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
1076
                      &wrap_around, NULL);
1077
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1078
	chat = priv->current_chat;
1079
	index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
1080
	numPages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
1081
1.1.51 by Didier Roche
Import upstream version 2.30.0
1082
	if (index_ == (numPages - 1) && wrap_around) {
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1083
		gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
1084
		return;
1085
	}
1086
1087
	gtk_notebook_next_page (GTK_NOTEBOOK (priv->notebook));
1088
}
1089
1090
static void
1091
chat_window_tabs_previous_activate_cb (GtkAction         *action,
1092
				   EmpathyChatWindow *window)
1093
{
1094
	EmpathyChatWindowPriv *priv;
1095
	EmpathyChat           *chat;
1096
	gint                  index_, numPages;
1.1.51 by Didier Roche
Import upstream version 2.30.0
1097
	gboolean              wrap_around;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1098
1099
	priv = GET_PRIV (window);
1100
1.1.51 by Didier Roche
Import upstream version 2.30.0
1101
	g_object_get (gtk_settings_get_default (), "gtk-keynav-wrap-around",
1102
                      &wrap_around, NULL);
1103
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1104
	chat = priv->current_chat;
1105
	index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
1106
	numPages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
1107
1.1.51 by Didier Roche
Import upstream version 2.30.0
1108
	if (index_ <= 0 && wrap_around) {
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1109
		gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), numPages - 1);
1110
		return;
1111
	}
1112
1113
	gtk_notebook_prev_page (GTK_NOTEBOOK (priv->notebook));
1114
}
1115
1116
static void
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1117
chat_window_tabs_undo_close_tab_activate_cb (GtkAction         *action,
1118
					     EmpathyChatWindow *window)
1119
{
1120
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1121
	empathy_chat_manager_undo_closed_chat (priv->chat_manager);
1122
}
1123
1124
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1125
chat_window_tabs_left_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1126
				   EmpathyChatWindow *window)
1127
{
1128
	EmpathyChatWindowPriv *priv;
1129
	EmpathyChat           *chat;
1.1.53 by Didier Roche
Import upstream version 2.30.1
1130
	gint                  index_, num_pages;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1131
1132
	priv = GET_PRIV (window);
1133
1134
	chat = priv->current_chat;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1135
	index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
1136
	if (index_ <= 0) {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1137
		return;
1138
	}
1139
1140
	gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
1141
				    GTK_WIDGET (chat),
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1142
				    index_ - 1);
1.1.53 by Didier Roche
Import upstream version 2.30.1
1143
1144
	num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
1145
	chat_window_menu_context_update (priv, num_pages);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1146
}
1147
1148
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1149
chat_window_tabs_right_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1150
				    EmpathyChatWindow *window)
1151
{
1152
	EmpathyChatWindowPriv *priv;
1153
	EmpathyChat           *chat;
1.1.53 by Didier Roche
Import upstream version 2.30.1
1154
	gint                  index_, num_pages;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1155
1156
	priv = GET_PRIV (window);
1157
1158
	chat = priv->current_chat;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1159
	index_ = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1160
1161
	gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
1162
				    GTK_WIDGET (chat),
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1163
				    index_ + 1);
1.1.53 by Didier Roche
Import upstream version 2.30.1
1164
1165
	num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
1166
	chat_window_menu_context_update (priv, num_pages);
1.8.1 by Emilio Pozuelo Monfort
Import upstream version 2.91.3
1167
}
1168
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1169
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1170
chat_window_detach_activate_cb (GtkAction         *action,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1171
				EmpathyChatWindow *window)
1172
{
1173
	EmpathyChatWindowPriv *priv;
1174
	EmpathyChatWindow     *new_window;
1175
	EmpathyChat           *chat;
1176
1177
	priv = GET_PRIV (window);
1178
1179
	chat = priv->current_chat;
1180
	new_window = empathy_chat_window_new ();
1181
1182
	empathy_chat_window_move_chat (window, new_window, chat);
1183
1184
	priv = GET_PRIV (new_window);
1185
	gtk_widget_show (priv->dialog);
1186
}
1187
1188
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1189
chat_window_help_contents_activate_cb (GtkAction         *action,
1190
				       EmpathyChatWindow *window)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1191
{
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1192
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1193
1.5.2 by Laurent Bigonville
Import upstream version 2.27.91.1
1194
	empathy_url_show (priv->dialog, "ghelp:empathy");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1195
}
1196
1197
static void
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1198
chat_window_help_about_activate_cb (GtkAction         *action,
1199
				    EmpathyChatWindow *window)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1200
{
1201
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1202
1203
	empathy_about_dialog_new (GTK_WINDOW (priv->dialog));
1204
}
1205
1206
static gboolean
1207
chat_window_delete_event_cb (GtkWidget        *dialog,
1208
			     GdkEvent         *event,
1209
			     EmpathyChatWindow *window)
1210
{
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1211
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1212
1213
	DEBUG ("Delete event received");
1214
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1215
	g_object_ref (window);
1216
	while (priv->chats) {
1217
		empathy_chat_window_remove_chat (window, priv->chats->data);
1218
	}
1219
	g_object_unref (window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1220
1221
	return TRUE;
1222
}
1223
1224
static void
1225
chat_window_composing_cb (EmpathyChat       *chat,
1226
			  gboolean          is_composing,
1227
			  EmpathyChatWindow *window)
1228
{
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1229
	EmpathyChatWindowPriv *priv;
1230
1231
	priv = GET_PRIV (window);
1232
1233
	if (is_composing && !g_list_find (priv->chats_composing, chat)) {
1234
		priv->chats_composing = g_list_prepend (priv->chats_composing, chat);
1235
	} else {
1236
		priv->chats_composing = g_list_remove (priv->chats_composing, chat);
1237
	}
1238
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1239
	chat_window_update_chat_tab (chat);
1240
}
1241
1242
static void
1243
chat_window_set_urgency_hint (EmpathyChatWindow *window,
1244
			      gboolean          urgent)
1245
{
1246
	EmpathyChatWindowPriv *priv;
1247
1248
	priv = GET_PRIV (window);
1249
1250
	gtk_window_set_urgency_hint (GTK_WINDOW (priv->dialog), urgent);
1251
}
1252
1.1.36 by Iain Lane
Import upstream version 2.28.0
1253
static void
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1254
chat_window_notification_closed_cb (NotifyNotification *notify,
1.1.52 by Ken VanDine
Import upstream version 2.30.0.1
1255
				    EmpathyChatWindow *self)
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1256
{
1.1.52 by Ken VanDine
Import upstream version 2.30.0.1
1257
	EmpathyChatWindowPriv *priv = GET_PRIV (self);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1258
1259
	g_object_unref (notify);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1260
	if (priv->notification == notify) {
1261
		priv->notification = NULL;
1262
	}
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1263
}
1264
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1265
#ifdef HAVE_LIBINDICATE
1266
static void
1267
chat_window_indicator_activate_cb (EmpathyIndicator *indicator, guint timestamp,
1268
				    EmpathyChat *chat)
1269
{
1270
	empathy_chat_window_present_chat (chat, timestamp);
1271
	empathy_indicator_hide (indicator);
1272
}
1273
1274
static void
1275
chat_window_add_indicator (EmpathyChatWindow *window,
1276
					 EmpathyMessage *message,
1277
					 EmpathyChat    *chat)
1278
{
1279
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1280
	EmpathyContact *sender;
1281
	const char *body;
1282
	gboolean use_libindicate;
1283
	EmpathyIndicator *indicator = NULL;
107.1.2 by Robert Ancell
* New upstream release
1284
	GSettings *gsettings;
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1285
107.1.2 by Robert Ancell
* New upstream release
1286
	gsettings = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
1287
	use_libindicate = g_settings_get_boolean (gsettings, EMPATHY_PREFS_UI_USE_LIBINDICATE);
1288
	g_object_unref (gsettings);
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1289
1290
	if (!use_libindicate) {
1291
		return;
1292
	}
1293
1294
	sender = empathy_message_get_sender (message);
1295
	body = empathy_message_get_body (message);
1296
1297
	indicator = g_hash_table_lookup (priv->indicators, chat);
1298
	if (indicator != NULL) {
1299
		DEBUG ("indicator exists");
1300
		empathy_indicator_update (indicator, body);
1301
	} else {
1302
		DEBUG ("indicator doesn't exist yet, creating a new indicator");
1303
		indicator = empathy_indicator_manager_create_indicator (priv->indicator_manager,
1304
			sender, body);
1305
		g_signal_connect (indicator, "activate",
1306
				  G_CALLBACK (chat_window_indicator_activate_cb), chat);
1307
1308
		g_hash_table_insert (priv->indicators, chat, indicator);
1309
	}
1310
	empathy_indicator_show (indicator);
1311
}
1312
1313
static void
1314
chat_window_remove_indicator (EmpathyChatWindow *window, EmpathyChat *chat)
1315
{
1316
	EmpathyIndicator *indicator = NULL;
1317
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1318
1319
	indicator = g_hash_table_lookup (priv->indicators, chat);
1320
1321
	if ((indicator) && (indicator != NULL)) {
1322
		DEBUG ("indicator is %p", indicator);
1323
		empathy_indicator_hide (indicator);
1324
		g_hash_table_remove (priv->indicators, chat);
1325
	} else {
1326
		DEBUG ("indicator is NULL, nothing to remove");
1327
	}
1328
}
1329
#endif
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1330
1331
static void
1332
chat_window_show_or_update_notification (EmpathyChatWindow *window,
1333
					 EmpathyMessage *message,
1334
					 EmpathyChat *chat)
1335
{
1336
	EmpathyContact *sender;
1.1.32 by Didier Roche
Import upstream version 2.27.4
1337
	const gchar *header;
1338
	char *escaped;
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1339
	const char *body;
1340
	GdkPixbuf *pixbuf;
1341
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1342
	gboolean res, has_x_canonical_append;
1343
	NotifyNotification *notification = priv->notification;
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1344
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1345
	if (!empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1346
		return;
1347
	} else {
1.1.55 by Robert Ancell
Import upstream version 2.31.4
1348
		GSettings *gsettings = g_settings_new (
1349
				EMPATHY_PREFS_NOTIFICATIONS_SCHEMA);
1350
1351
		res = g_settings_get_boolean (gsettings,
1352
				EMPATHY_PREFS_NOTIFICATIONS_FOCUS);
1353
1354
		g_object_unref (gsettings);
1355
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1356
		if (!res) {
1357
			return;
1358
		}
1359
	}
1360
1361
	sender = empathy_message_get_sender (message);
1.1.57 by Robert Ancell
Import upstream version 2.31.6
1362
	header = empathy_contact_get_alias (sender);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1363
	body = empathy_message_get_body (message);
1364
	escaped = g_markup_escape_text (body, -1);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1365
	has_x_canonical_append = empathy_notify_manager_has_capability (
1366
		priv->notify_mgr, EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1367
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1368
	if (notification != NULL && !has_x_canonical_append) {
1369
		/* if the notification server supports x-canonical-append, it is
1370
		   better to not use notify_notification_update to avoid
1371
		   overwriting the current notification message */
1372
		notify_notification_update (notification,
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1373
					    header, escaped, NULL);
1374
	} else {
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1375
		/* if the notification server supports x-canonical-append,
1376
		   the hint will be added, so that the message from the
1377
		   just created notification will be automatically appended
1378
		   to an existing notification with the same title.
1379
		   In this way the previous message will not be lost: the new
1380
		   message will appear below it, in the same notification */
1381
		notification = notify_notification_new (header, escaped, NULL, NULL);
1382
1383
		if (priv->notification == NULL) {
1384
			priv->notification = notification;
1385
		}
1386
1387
		notify_notification_set_timeout (notification, NOTIFY_EXPIRES_DEFAULT);
1388
1.1.55 by Robert Ancell
Import upstream version 2.31.4
1389
		tp_g_signal_connect_object (notification, "closed",
1390
				  G_CALLBACK (chat_window_notification_closed_cb), window, 0);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1391
1392
		if (has_x_canonical_append) {
1393
			notify_notification_set_hint_string (notification,
1394
				EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND, "");
1395
		}
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1396
	}
1397
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1398
	pixbuf = empathy_notify_manager_get_pixbuf_for_notification (priv->notify_mgr,
1399
		sender, EMPATHY_IMAGE_NEW_MESSAGE);
1.1.34 by Laurent Bigonville
Import upstream version 2.27.91.1
1400
1401
	if (pixbuf != NULL) {
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1402
		notify_notification_set_icon_from_pixbuf (notification, pixbuf);
1.1.34 by Laurent Bigonville
Import upstream version 2.27.91.1
1403
		g_object_unref (pixbuf);
1404
	}
1405
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1406
	notify_notification_show (notification, NULL);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1407
1408
	g_free (escaped);
1409
}
1410
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1411
static void
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
1412
chat_window_set_highlight_room_tab_label (EmpathyChat *chat)
1413
{
1414
	gchar *markup;
1415
	GtkWidget *widget;
1416
1417
	if (!empathy_chat_is_room (chat))
1418
		return;
1419
1.5.2 by Laurent Bigonville
Import upstream version 2.27.91.1
1420
	markup = g_markup_printf_escaped (
1421
		"<span color=\"red\" weight=\"bold\">%s</span>",
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
1422
		empathy_chat_get_name (chat));
1423
1424
	widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
1425
	gtk_label_set_markup (GTK_LABEL (widget), markup);
1426
	g_free (markup);
1427
}
1428
1.1.33 by Sebastien Bacher
Import upstream version 2.27.5
1429
static void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1430
chat_window_new_message_cb (EmpathyChat       *chat,
1431
			    EmpathyMessage    *message,
1432
			    EmpathyChatWindow *window)
1433
{
1434
	EmpathyChatWindowPriv *priv;
1435
	gboolean              has_focus;
1436
	gboolean              needs_urgency;
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1437
	EmpathyContact        *sender;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1438
1439
	priv = GET_PRIV (window);
1440
1441
	has_focus = empathy_chat_window_has_focus (window);
1442
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1443
	/* - if we're the sender, we play the sound if it's specified in the
1444
	 *   preferences and we're not away.
1445
	 * - if we receive a message, we play the sound if it's specified in the
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
1446
	 *   preferences and the window does not have focus on the chat receiving
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1447
	 *   the message.
1448
	 */
1449
1450
	sender = empathy_message_get_sender (message);
1451
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
1452
	if (empathy_contact_is_user (sender)) {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1453
		empathy_sound_play (GTK_WIDGET (priv->dialog),
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1454
				    EMPATHY_SOUND_MESSAGE_OUTGOING);
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1455
	}
1456
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1457
	if (has_focus && priv->current_chat == chat) {
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1458
		/* window and tab are focused so consider the message to be read */
1.1.47 by Ken VanDine
Import upstream version 2.29.91.1
1459
1460
		/* FIXME: see Bug#610994 and coments about it in EmpathyChatPriv */
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1461
		empathy_chat_messages_read (chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1462
		return;
1463
	}
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1464
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
1465
	if (!g_list_find (priv->chats_new_msg, chat)) {
1466
		priv->chats_new_msg = g_list_prepend (priv->chats_new_msg, chat);
1.1.33 by Sebastien Bacher
Import upstream version 2.27.5
1467
		chat_window_update_chat_tab (chat);
1468
	}
1469
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1470
	/* If empathy_chat_is_room () returns TRUE, that means it's a named MUC.
1471
	 * If empathy_chat_get_remote_contact () returns NULL, that means it's
1.4.1 by Laurent Bigonville
Import upstream version 2.26.2
1472
	 * an unamed MUC (msn-like).
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
1473
	 * In case of a MUC, we set urgency if either:
1474
	 *   a) the chatroom's always_urgent property is TRUE
1475
	 *   b) the message contains our alias
1476
	 */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1477
	if (empathy_chat_is_room (chat) ||
1478
	    empathy_chat_get_remote_contact (chat) == NULL) {
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
1479
		TpAccount             *account;
1480
		const gchar           *room;
1481
		EmpathyChatroom       *chatroom;
1482
1483
		account = empathy_chat_get_account (chat);
1484
		room = empathy_chat_get_id (chat);
1485
1486
		chatroom = empathy_chatroom_manager_find (priv->chatroom_manager,
1487
							  account, room);
1488
1489
		if (empathy_chatroom_is_always_urgent (chatroom)) {
1490
			needs_urgency = TRUE;
1491
		} else {
1492
			needs_urgency = empathy_message_should_highlight (message);
1493
		}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1494
	} else {
1495
		needs_urgency = TRUE;
1496
	}
1497
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
1498
	if (needs_urgency) {
1.1.33 by Sebastien Bacher
Import upstream version 2.27.5
1499
		if (!has_focus) {
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
1500
			chat_window_set_urgency_hint (window, TRUE);
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
1501
			chat_window_set_highlight_room_tab_label (chat);
1502
		}
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1503
1504
		empathy_sound_play (GTK_WIDGET (priv->dialog),
1505
		    EMPATHY_SOUND_MESSAGE_INCOMING);
1506
		chat_window_show_or_update_notification (window, message, chat);
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1507
#ifdef HAVE_LIBINDICATE
1508
		chat_window_add_indicator (window, message, chat);
1509
#endif
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1510
	}
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1511
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1512
	/* update the number of unread messages */
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1513
	chat_window_title_update (priv);
1.8.14 by Laurent Bigonville
Import upstream version 3.1.2.1
1514
}
1515
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1516
static GtkNotebook *
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1517
chat_window_detach_hook (GtkNotebook *source,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1518
			 GtkWidget   *page,
1519
			 gint         x,
1520
			 gint         y,
1521
			 gpointer     user_data)
1522
{
1523
	EmpathyChatWindowPriv *priv;
1524
	EmpathyChatWindow     *window, *new_window;
1525
	EmpathyChat           *chat;
1526
1527
	chat = EMPATHY_CHAT (page);
1528
	window = chat_window_find_chat (chat);
1529
1530
	new_window = empathy_chat_window_new ();
1531
	priv = GET_PRIV (new_window);
1532
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1533
	DEBUG ("Detach hook called");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1534
1535
	empathy_chat_window_move_chat (window, new_window, chat);
1536
1.1.59 by Didier Roche
Import upstream version 2.31.91.1
1537
	gtk_widget_show (priv->dialog);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1538
	gtk_window_move (GTK_WINDOW (priv->dialog), x, y);
1539
1540
	return NULL;
1541
}
1542
1543
static void
1544
chat_window_page_switched_cb (GtkNotebook      *notebook,
1.1.57 by Robert Ancell
Import upstream version 2.31.6
1545
			      gpointer          ignore, /* see note below */
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1546
			      gint	        page_num,
1547
			      EmpathyChatWindow *window)
1548
{
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1549
	EmpathyChatWindowPriv *priv;
1550
	EmpathyChat           *chat;
1551
	GtkWidget            *child;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1552
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1553
	DEBUG ("Page switched");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1554
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1555
	priv = GET_PRIV (window);
1556
1.1.57 by Robert Ancell
Import upstream version 2.31.6
1557
	/* N.B. in GTK+ 3 child is passed as the first argument to the signal,
1558
	 * but we can't use that while trying to retain GTK+ 2.x compatibility.
1559
	 */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1560
	child = gtk_notebook_get_nth_page (notebook, page_num);
1561
	chat = EMPATHY_CHAT (child);
1562
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1563
	if (priv->page_added) {
1564
		priv->page_added = FALSE;
1565
		empathy_chat_scroll_down (chat);
1566
	}
1567
	else if (priv->current_chat == chat) {
1568
		return;
1569
	}
1570
1571
	priv->current_chat = chat;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1572
	priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1573
	empathy_chat_messages_read (chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1574
1575
	chat_window_update_chat_tab (chat);
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1576
1577
#ifdef HAVE_LIBINDICATE
1578
	chat_window_remove_indicator (window, chat);
1579
#endif
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1580
}
1581
1582
static void
1583
chat_window_page_added_cb (GtkNotebook      *notebook,
1584
			   GtkWidget	    *child,
1585
			   guint             page_num,
1586
			   EmpathyChatWindow *window)
1587
{
1588
	EmpathyChatWindowPriv *priv;
1589
	EmpathyChat           *chat;
1590
1591
	priv = GET_PRIV (window);
1592
1593
	/* If we just received DND to the same window, we don't want
1594
	 * to do anything here like removing the tab and then readding
1595
	 * it, so we return here and in "page-added".
1596
	 */
1597
	if (priv->dnd_same_window) {
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1598
		DEBUG ("Page added (back to the same window)");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1599
		priv->dnd_same_window = FALSE;
1600
		return;
1601
	}
1602
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1603
	DEBUG ("Page added");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1604
1605
	/* Get chat object */
1606
	chat = EMPATHY_CHAT (child);
1607
1608
	/* Connect chat signals for this window */
1609
	g_signal_connect (chat, "composing",
1610
			  G_CALLBACK (chat_window_composing_cb),
1611
			  window);
1612
	g_signal_connect (chat, "new-message",
1613
			  G_CALLBACK (chat_window_new_message_cb),
1614
			  window);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1615
	g_signal_connect (chat, "notify::tp-chat",
1616
			  G_CALLBACK (chat_window_update_chat_tab),
1617
			  window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1618
1619
	/* Set flag so we know to perform some special operations on
1620
	 * switch page due to the new page being added.
1621
	 */
1622
	priv->page_added = TRUE;
1623
1624
	/* Get list of chats up to date */
1625
	priv->chats = g_list_append (priv->chats, chat);
1626
1627
	chat_window_update_chat_tab (chat);
1628
}
1629
1630
static void
1631
chat_window_page_removed_cb (GtkNotebook      *notebook,
1632
			     GtkWidget	      *child,
1633
			     guint             page_num,
1634
			     EmpathyChatWindow *window)
1635
{
1636
	EmpathyChatWindowPriv *priv;
1637
	EmpathyChat           *chat;
1638
1639
	priv = GET_PRIV (window);
1640
1641
	/* If we just received DND to the same window, we don't want
1642
	 * to do anything here like removing the tab and then readding
1643
	 * it, so we return here and in "page-added".
1644
	 */
1645
	if (priv->dnd_same_window) {
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1646
		DEBUG ("Page removed (and will be readded to same window)");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1647
		return;
1648
	}
1649
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1650
	DEBUG ("Page removed");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1651
1652
	/* Get chat object */
1653
	chat = EMPATHY_CHAT (child);
1654
1655
	/* Disconnect all signal handlers for this chat and this window */
1656
	g_signal_handlers_disconnect_by_func (chat,
1657
					      G_CALLBACK (chat_window_composing_cb),
1658
					      window);
1659
	g_signal_handlers_disconnect_by_func (chat,
1660
					      G_CALLBACK (chat_window_new_message_cb),
1661
					      window);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1662
	g_signal_handlers_disconnect_by_func (chat,
1663
					      G_CALLBACK (chat_window_update_chat_tab),
1664
					      window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1665
1666
	/* Keep list of chats up to date */
1667
	priv->chats = g_list_remove (priv->chats, chat);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1668
	priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1669
	empathy_chat_messages_read (chat);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1670
	priv->chats_composing = g_list_remove (priv->chats_composing, chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1671
1672
	if (priv->chats == NULL) {
1673
		g_object_unref (window);
1674
	} else {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1675
		chat_window_update (window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1676
	}
1677
}
1678
1679
static gboolean
1680
chat_window_focus_in_event_cb (GtkWidget        *widget,
1681
			       GdkEvent         *event,
1682
			       EmpathyChatWindow *window)
1683
{
1684
	EmpathyChatWindowPriv *priv;
1685
1686
	priv = GET_PRIV (window);
1687
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1688
	priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1689
	empathy_chat_messages_read (priv->current_chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1690
1691
	chat_window_set_urgency_hint (window, FALSE);
1.1.32 by Didier Roche
Import upstream version 2.27.4
1692
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1693
	/* Update the title, since we now mark all unread messages as read. */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1694
	chat_window_update_chat_tab (priv->current_chat);
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1695
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
1696
#ifdef HAVE_LIBINDICATE
1697
	/* Remove the indicator for the active chat */
1698
	chat_window_remove_indicator (window, priv->current_chat);
1699
#endif
1700
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1701
	return FALSE;
1702
}
1703
1704
static gboolean
1705
chat_window_drag_drop (GtkWidget        *widget,
1706
			 GdkDragContext   *context,
1707
			 int               x,
1708
			 int               y,
1709
			 guint             time_,
1.1.50 by Ken VanDine
Import upstream version 2.29.93
1710
			 EmpathyChatWindow *window)
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1711
{
1.1.50 by Ken VanDine
Import upstream version 2.29.93
1712
	GdkAtom target;
1713
	EmpathyChatWindowPriv *priv;
1714
1715
	priv = GET_PRIV (window);
1716
1717
	target = gtk_drag_dest_find_target (widget, context, priv->file_targets);
1718
	if (target == GDK_NONE)
1719
		target = gtk_drag_dest_find_target (widget, context, priv->contact_targets);
1720
1721
	if (target != GDK_NONE) {
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1722
		gtk_drag_get_data (widget, context, target, time_);
1723
		return TRUE;
1724
	}
83 by Laurent Bigonville
* Really merge from debian experimental, remaining changes (LP: #509081):
1725
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1726
	return FALSE;
1727
}
1728
1729
static gboolean
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1730
chat_window_drag_motion (GtkWidget        *widget,
1731
			 GdkDragContext   *context,
1732
			 int               x,
1733
			 int               y,
1734
			 guint             time_,
1735
			 EmpathyChatWindow *window)
1736
{
1737
	GdkAtom target;
1738
	EmpathyChatWindowPriv *priv;
1739
1740
	priv = GET_PRIV (window);
1741
1.1.50 by Ken VanDine
Import upstream version 2.29.93
1742
	target = gtk_drag_dest_find_target (widget, context, priv->file_targets);
1743
	if (target != GDK_NONE) {
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1744
		/* This is a file drag.  Ensure the contact is online and set the
1745
		   drag type to COPY.  Note that it's possible that the tab will
1746
		   be switched by GTK+ after a timeout from drag_motion without
1747
		   getting another drag_motion to disable the drop.  You have
1748
		   to hold your mouse really still.
1749
		 */
1750
		EmpathyContact *contact;
1751
1752
		priv = GET_PRIV (window);
1753
		contact = empathy_chat_get_remote_contact (priv->current_chat);
1754
		/* contact is NULL for multi-user chats.  We don't do
1755
		 * file transfers to MUCs.  We also don't send files
1756
		 * to offline contacts or contacts that don't support
1757
		 * file transfer.
1758
		 */
1759
		if ((contact == NULL) || !empathy_contact_is_online (contact)) {
1760
			gdk_drag_status (context, 0, time_);
1761
			return FALSE;
1762
		}
1763
		if (!(empathy_contact_get_capabilities (contact)
1764
			   & EMPATHY_CAPABILITIES_FT)) {
1765
			gdk_drag_status (context, 0, time_);
1766
			return FALSE;
1767
		}
1768
		gdk_drag_status (context, GDK_ACTION_COPY, time_);
1769
		return TRUE;
1770
	}
1771
1.1.50 by Ken VanDine
Import upstream version 2.29.93
1772
	target = gtk_drag_dest_find_target (widget, context, priv->contact_targets);
1773
	if (target != GDK_NONE) {
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1774
		/* This is a drag of a contact from a contact list.  Set to COPY.
1775
		   FIXME: If this drag is to a MUC window, it invites the user.
1776
		   Otherwise, it opens a chat.  Should we use a different drag
1777
		   type for invites?  Should we allow ASK?
1778
		 */
1779
		gdk_drag_status (context, GDK_ACTION_COPY, time_);
1780
		return TRUE;
1781
	}
1782
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1783
	return FALSE;
1.6.10 by Sjoerd Simons
Import upstream version 3.3.90.2
1784
}
1785
1786
static void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1787
chat_window_drag_data_received (GtkWidget        *widget,
1788
				GdkDragContext   *context,
1789
				int               x,
1790
				int               y,
1791
				GtkSelectionData *selection,
1792
				guint             info,
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1793
				guint             time_,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1794
				EmpathyChatWindow *window)
1795
{
1796
	if (info == DND_DRAG_TYPE_CONTACT_ID) {
1.1.36 by Iain Lane
Import upstream version 2.28.0
1797
		EmpathyChat           *chat = NULL;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1798
		EmpathyChatWindow     *old_window;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1799
		TpAccount             *account = NULL;
1800
		TpAccountManager      *account_manager;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1801
		const gchar           *id;
1802
		gchar                **strv;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1803
		const gchar           *account_id;
1804
		const gchar           *contact_id;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1805
1.1.32 by Didier Roche
Import upstream version 2.27.4
1806
		id = (const gchar*) gtk_selection_data_get_data (selection);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1807
1808
		/* FIXME: Perhaps should be sure that the account manager is
1809
		 * prepared before calling _ensure_account on it. */
1810
		account_manager = tp_account_manager_dup ();
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1811
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1812
		DEBUG ("DND contact from roster with id:'%s'", id);
1.1.32 by Didier Roche
Import upstream version 2.27.4
1813
1.1.36 by Iain Lane
Import upstream version 2.28.0
1814
		strv = g_strsplit (id, ":", 2);
1815
		if (g_strv_length (strv) == 2) {
1816
			account_id = strv[0];
1817
			contact_id = strv[1];
1818
			account =
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1819
				tp_account_manager_ensure_account (account_manager, account_id);
1.1.36 by Iain Lane
Import upstream version 2.28.0
1820
			if (account != NULL)
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1821
				chat = empathy_chat_window_find_chat (account, contact_id);
1.1.36 by Iain Lane
Import upstream version 2.28.0
1822
		}
1823
1824
		if (account == NULL) {
1825
			g_strfreev (strv);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1826
			gtk_drag_finish (context, FALSE, FALSE, time_);
1.1.36 by Iain Lane
Import upstream version 2.28.0
1827
			return;
1828
		}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1829
1830
		if (!chat) {
1.7.15 by Laurent Bigonville
Import upstream version 2.31.90
1831
			empathy_dispatcher_chat_with_contact_id (
1832
				account, contact_id, gtk_get_current_event_time ());
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1833
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1834
			g_strfreev (strv);
1835
			return;
1836
		}
1.5.1 by Laurent Bigonville
Import upstream version 2.27.5
1837
		g_object_unref (account_manager);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1838
		g_strfreev (strv);
1839
1.1.32 by Didier Roche
Import upstream version 2.27.4
1840
		old_window = chat_window_find_chat (chat);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1841
		if (old_window) {
1842
			if (old_window == window) {
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1843
				gtk_drag_finish (context, TRUE, FALSE, time_);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1844
				return;
1845
			}
1.1.32 by Didier Roche
Import upstream version 2.27.4
1846
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1847
			empathy_chat_window_move_chat (old_window, window, chat);
1848
		} else {
1849
			empathy_chat_window_add_chat (window, chat);
1850
		}
1.1.32 by Didier Roche
Import upstream version 2.27.4
1851
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1852
		/* Added to take care of any outstanding chat events */
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1853
		empathy_chat_window_present_chat (chat,
1.7.15 by Laurent Bigonville
Import upstream version 2.31.90
1854
			TP_USER_ACTION_TIME_NOT_USER_ACTION);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1855
1856
		/* We should return TRUE to remove the data when doing
1857
		 * GDK_ACTION_MOVE, but we don't here otherwise it has
1858
		 * weird consequences, and we handle that internally
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1859
		 * anyway with add_chat () and remove_chat ().
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1860
		 */
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1861
		gtk_drag_finish (context, TRUE, FALSE, time_);
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1862
	}
1863
	else if (info == DND_DRAG_TYPE_URI_LIST) {
1864
		EmpathyChatWindowPriv *priv;
1865
		EmpathyContact *contact;
1866
		const gchar *data;
1867
1868
		priv = GET_PRIV (window);
1869
		contact = empathy_chat_get_remote_contact (priv->current_chat);
1870
1871
		/* contact is NULL when current_chat is a multi-user chat.
1872
		 * We don't do file transfers to MUCs, so just cancel the drag.
1873
		 */
1874
		if (contact == NULL) {
1875
			gtk_drag_finish (context, TRUE, FALSE, time_);
1876
			return;
1877
		}
1878
1879
		data = (const gchar *) gtk_selection_data_get_data (selection);
1880
		empathy_send_file_from_uri_list (contact, data);
1881
1882
		gtk_drag_finish (context, TRUE, FALSE, time_);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1883
	}
1884
	else if (info == DND_DRAG_TYPE_TAB) {
1885
		EmpathyChat        **chat;
1886
		EmpathyChatWindow   *old_window = NULL;
1887
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1888
		DEBUG ("DND tab");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1889
1.1.32 by Didier Roche
Import upstream version 2.27.4
1890
		chat = (void *) gtk_selection_data_get_data (selection);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1891
		old_window = chat_window_find_chat (*chat);
1892
1893
		if (old_window) {
1894
			EmpathyChatWindowPriv *priv;
1895
1896
			priv = GET_PRIV (window);
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
1897
			priv->dnd_same_window = (old_window == window);
1898
			DEBUG ("DND tab (within same window: %s)",
1899
				priv->dnd_same_window ? "Yes" : "No");
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1900
		}
1901
	} else {
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1902
		DEBUG ("DND from unknown source");
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1903
		gtk_drag_finish (context, FALSE, FALSE, time_);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1904
	}
1905
}
1906
1907
static void
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1908
chat_window_chat_manager_chats_changed_cb (EmpathyChatManager *chat_manager,
1909
					   guint num_chats_in_manager,
1910
					   EmpathyChatWindow *window)
1911
{
1912
	EmpathyChatWindowPriv *priv = GET_PRIV (window);
1913
1914
	gtk_action_set_sensitive (priv->menu_tabs_undo_close_tab,
1915
				  num_chats_in_manager > 0);
1916
}
1917
1918
static void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1919
chat_window_finalize (GObject *object)
1920
{
1921
	EmpathyChatWindow     *window;
1922
	EmpathyChatWindowPriv *priv;
1923
1924
	window = EMPATHY_CHAT_WINDOW (object);
1925
	priv = GET_PRIV (window);
1926
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1927
	DEBUG ("Finalized: %p", object);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1928
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1929
	g_object_unref (priv->ui_manager);
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
1930
	g_object_unref (priv->chatroom_manager);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1931
	g_object_unref (priv->notify_mgr);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1932
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
1933
	if (priv->notification != NULL) {
1934
		notify_notification_close (priv->notification, NULL);
1935
		priv->notification = NULL;
1936
	}
1937
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
1938
	if (priv->contact_targets) {
1939
		gtk_target_list_unref (priv->contact_targets);
1940
	}
1941
	if (priv->file_targets) {
1942
		gtk_target_list_unref (priv->file_targets);
1943
	}
1944
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
1945
	if (priv->chat_manager) {
1946
		g_signal_handler_disconnect (priv->chat_manager,
1947
					     priv->chat_manager_chats_changed_id);
1948
		g_object_unref (priv->chat_manager);
1949
		priv->chat_manager = NULL;
1950
	}
1951
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1952
	chat_windows = g_list_remove (chat_windows, window);
1953
	gtk_widget_destroy (priv->dialog);
1954
1955
	G_OBJECT_CLASS (empathy_chat_window_parent_class)->finalize (object);
1956
}
1957
1958
static void
1959
empathy_chat_window_class_init (EmpathyChatWindowClass *klass)
1960
{
1961
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
1962
1963
	object_class->finalize = chat_window_finalize;
1964
1965
	g_type_class_add_private (object_class, sizeof (EmpathyChatWindowPriv));
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
1966
1967
	/* Set up a style for the close button with no focus padding. */
1968
	gtk_rc_parse_string (
1969
		"style \"empathy-close-button-style\"\n"
1970
		"{\n"
1971
		"  GtkWidget::focus-padding = 0\n"
1972
		"  xthickness = 0\n"
1973
		"  ythickness = 0\n"
1974
		"}\n"
1975
		"widget \"*.empathy-close-button\" style \"empathy-close-button-style\"");
1976
1977
	gtk_notebook_set_window_creation_hook (chat_window_detach_hook, NULL, NULL);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1978
}
1979
1980
static void
1981
empathy_chat_window_init (EmpathyChatWindow *window)
1982
{
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1983
	GtkBuilder            *gui;
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1984
	GtkAccelGroup         *accel_group;
1985
	GClosure              *closure;
1986
	GtkWidget             *menu;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1987
	GtkWidget             *submenu;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
1988
	guint                  i;
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1989
	GtkWidget             *chat_vbox;
1990
	gchar                 *filename;
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
1991
	EmpathySmileyManager  *smiley_manager;
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
1992
	EmpathyChatWindowPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1993
		EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowPriv);
1994
1995
	window->priv = priv;
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
1996
	filename = empathy_file_lookup ("empathy-chat-window.ui", "src");
1997
	gui = empathy_builder_get_file (filename,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
1998
				       "chat_window", &priv->dialog,
1999
				       "chat_vbox", &chat_vbox,
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2000
				       "ui_manager", &priv->ui_manager,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2001
				       "menu_conv_insert_smiley", &priv->menu_conv_insert_smiley,
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
2002
				       "menu_conv_favorite", &priv->menu_conv_favorite,
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
2003
				       "menu_conv_always_urgent", &priv->menu_conv_always_urgent,
1.1.32 by Didier Roche
Import upstream version 2.27.4
2004
				       "menu_conv_toggle_contacts", &priv->menu_conv_toggle_contacts,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2005
				       "menu_edit_cut", &priv->menu_edit_cut,
2006
				       "menu_edit_copy", &priv->menu_edit_copy,
2007
				       "menu_edit_paste", &priv->menu_edit_paste,
1.1.44 by Didier Roche
Import upstream version 2.29.6
2008
				       "menu_edit_find", &priv->menu_edit_find,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2009
				       "menu_tabs_next", &priv->menu_tabs_next,
2010
				       "menu_tabs_prev", &priv->menu_tabs_prev,
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2011
				       "menu_tabs_undo_close_tab", &priv->menu_tabs_undo_close_tab,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2012
				       "menu_tabs_left", &priv->menu_tabs_left,
2013
				       "menu_tabs_right", &priv->menu_tabs_right,
2014
				       "menu_tabs_detach", &priv->menu_tabs_detach,
2015
				       NULL);
2016
	g_free (filename);
2017
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2018
	empathy_builder_connect (gui, window,
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
2019
			      "menu_conv", "activate", chat_window_conv_activate_cb,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2020
			      "menu_conv_clear", "activate", chat_window_clear_activate_cb,
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
2021
			      "menu_conv_favorite", "toggled", chat_window_favorite_toggled_cb,
1.7.11 by Laurent Bigonville
Import upstream version 2.31.3
2022
			      "menu_conv_always_urgent", "toggled", chat_window_always_urgent_toggled_cb,
1.1.32 by Didier Roche
Import upstream version 2.27.4
2023
			      "menu_conv_toggle_contacts", "toggled", chat_window_contacts_toggled_cb,
1.1.43 by Ken VanDine
Import upstream version 2.29.5.1
2024
			      "menu_conv_invite_participant", "activate", chat_window_invite_participant_activate_cb,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2025
			      "menu_conv_close", "activate", chat_window_close_activate_cb,
2026
			      "menu_edit", "activate", chat_window_edit_activate_cb,
2027
			      "menu_edit_cut", "activate", chat_window_cut_activate_cb,
2028
			      "menu_edit_copy", "activate", chat_window_copy_activate_cb,
2029
			      "menu_edit_paste", "activate", chat_window_paste_activate_cb,
1.1.44 by Didier Roche
Import upstream version 2.29.6
2030
			      "menu_edit_find", "activate", chat_window_find_activate_cb,
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2031
			      "menu_tabs_next", "activate", chat_window_tabs_next_activate_cb,
2032
			      "menu_tabs_prev", "activate", chat_window_tabs_previous_activate_cb,
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2033
			      "menu_tabs_undo_close_tab", "activate", chat_window_tabs_undo_close_tab_activate_cb,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2034
			      "menu_tabs_left", "activate", chat_window_tabs_left_activate_cb,
2035
			      "menu_tabs_right", "activate", chat_window_tabs_right_activate_cb,
2036
			      "menu_tabs_detach", "activate", chat_window_detach_activate_cb,
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2037
			      "menu_help_contents", "activate", chat_window_help_contents_activate_cb,
2038
			      "menu_help_about", "activate", chat_window_help_about_activate_cb,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2039
			      NULL);
2040
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2041
	g_object_ref (priv->ui_manager);
2042
	g_object_unref (gui);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2043
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
2044
	priv->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
2045
#ifdef HAVE_LIBINDICATE
2046
	priv->indicator_manager = empathy_indicator_manager_dup_singleton ();
2047
	priv->indicators = g_hash_table_new_full (g_direct_hash, g_direct_equal,
2048
			      NULL, g_object_unref);
2049
#endif
1.1.19 by Laurent Bigonville
Import upstream version 2.23.91
2050
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2051
	priv->notebook = gtk_notebook_new ();
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2052
	gtk_notebook_set_group (GTK_NOTEBOOK (priv->notebook), "EmpathyChatWindow");
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
2053
	gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE);
2054
	gtk_notebook_popup_enable (GTK_NOTEBOOK (priv->notebook));
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2055
	gtk_box_pack_start (GTK_BOX (chat_vbox), priv->notebook, TRUE, TRUE, 0);
2056
	gtk_widget_show (priv->notebook);
2057
2058
	/* Set up accels */
2059
	accel_group = gtk_accel_group_new ();
2060
	gtk_window_add_accel_group (GTK_WINDOW (priv->dialog), accel_group);
2061
2062
	for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
2063
		closure =  g_cclosure_new (G_CALLBACK (chat_window_accel_cb),
2064
					   window,
2065
					   NULL);
2066
		gtk_accel_group_connect (accel_group,
2067
					 tab_accel_keys[i],
2068
					 GDK_MOD1_MASK,
2069
					 0,
2070
					 closure);
2071
	}
2072
2073
	g_object_unref (accel_group);
2074
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
2075
	/* Set up drag target lists */
2076
	priv->contact_targets = gtk_target_list_new (drag_types_dest_contact,
2077
						     G_N_ELEMENTS (drag_types_dest_contact));
2078
	priv->file_targets = gtk_target_list_new (drag_types_dest_file,
2079
						  G_N_ELEMENTS (drag_types_dest_file));
2080
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2081
	/* Set up smiley menu */
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
2082
	smiley_manager = empathy_smiley_manager_dup_singleton ();
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2083
	submenu = empathy_smiley_menu_new (smiley_manager,
2084
					   chat_window_insert_smiley_activate_cb,
2085
					   window);
2086
	menu = gtk_ui_manager_get_widget (priv->ui_manager,
2087
		"/chats_menubar/menu_conv/menu_conv_insert_smiley");
2088
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu), submenu);
1.1.24 by Laurent Bigonville
Import upstream version 2.25.4
2089
	g_object_unref (smiley_manager);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2090
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2091
	/* Set up signals we can't do with ui file since we may need to
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2092
	 * block/unblock them at some later stage.
2093
	 */
2094
2095
	g_signal_connect (priv->dialog,
2096
			  "delete_event",
2097
			  G_CALLBACK (chat_window_delete_event_cb),
2098
			  window);
2099
	g_signal_connect (priv->dialog,
2100
			  "focus_in_event",
2101
			  G_CALLBACK (chat_window_focus_in_event_cb),
2102
			  window);
2103
	g_signal_connect_after (priv->notebook,
2104
				"switch_page",
2105
				G_CALLBACK (chat_window_page_switched_cb),
2106
				window);
2107
	g_signal_connect (priv->notebook,
2108
			  "page_added",
2109
			  G_CALLBACK (chat_window_page_added_cb),
2110
			  window);
2111
	g_signal_connect (priv->notebook,
2112
			  "page_removed",
2113
			  G_CALLBACK (chat_window_page_removed_cb),
2114
			  window);
2115
2116
	/* Set up drag and drop */
2117
	gtk_drag_dest_set (GTK_WIDGET (priv->notebook),
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
2118
			   GTK_DEST_DEFAULT_HIGHLIGHT,
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2119
			   drag_types_dest,
2120
			   G_N_ELEMENTS (drag_types_dest),
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
2121
			   GDK_ACTION_MOVE | GDK_ACTION_COPY);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2122
1.1.41 by Laurent Bigonville
Import upstream version 2.29.3
2123
	/* connect_after to allow GtkNotebook's built-in tab switching */
2124
	g_signal_connect_after (priv->notebook,
2125
				"drag-motion",
2126
				G_CALLBACK (chat_window_drag_motion),
2127
				window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2128
	g_signal_connect (priv->notebook,
2129
			  "drag-data-received",
2130
			  G_CALLBACK (chat_window_drag_data_received),
2131
			  window);
1.7.4 by Laurent Bigonville
Import upstream version 2.29.91
2132
	g_signal_connect (priv->notebook,
2133
			  "drag-drop",
2134
			  G_CALLBACK (chat_window_drag_drop),
2135
			  window);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2136
2137
	chat_windows = g_list_prepend (chat_windows, window);
2138
2139
	/* Set up private details */
2140
	priv->chats = NULL;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2141
	priv->chats_new_msg = NULL;
2142
	priv->chats_composing = NULL;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2143
	priv->current_chat = NULL;
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2144
	priv->notification = NULL;
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2145
2146
	priv->notify_mgr = empathy_notify_manager_dup_singleton ();
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2147
2148
	priv->chat_manager = empathy_chat_manager_dup_singleton ();
2149
	priv->chat_manager_chats_changed_id =
2150
		g_signal_connect (priv->chat_manager, "chats-changed",
2151
				  G_CALLBACK (chat_window_chat_manager_chats_changed_cb),
2152
				  window);
2153
2154
	chat_window_chat_manager_chats_changed_cb (priv->chat_manager,
2155
						   empathy_chat_manager_get_num_chats (priv->chat_manager),
2156
						   window);
107.1.1 by Sebastien Bacher, Robert Ancell
* debian/control, debian/rules:
2157
2158
	/* Add launchpad hooks */
2159
	launchpad_integration_add_ui (priv->ui_manager, "/chats_menubar/menu_help/LaunchpadItems");
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2160
}
2161
2162
EmpathyChatWindow *
2163
empathy_chat_window_new (void)
2164
{
2165
	return EMPATHY_CHAT_WINDOW (g_object_new (EMPATHY_TYPE_CHAT_WINDOW, NULL));
2166
}
2167
2168
/* Returns the window to open a new tab in if there is only one window
2169
 * visble, otherwise, returns NULL indicating that a new window should
2170
 * be added.
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2171
 */
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2172
EmpathyChatWindow *
1.1.42 by Laurent Bigonville
Import upstream version 2.29.4
2173
empathy_chat_window_get_default (gboolean room)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2174
{
1.1.55 by Robert Ancell
Import upstream version 2.31.4
2175
	GSettings *gsettings = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2176
	GList    *l;
2177
	gboolean  separate_windows = TRUE;
2178
1.1.55 by Robert Ancell
Import upstream version 2.31.4
2179
	separate_windows = g_settings_get_boolean (gsettings,
2180
			EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS);
2181
2182
	g_object_unref (gsettings);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2183
2184
	if (separate_windows) {
2185
		/* Always create a new window */
2186
		return NULL;
2187
	}
2188
2189
	for (l = chat_windows; l; l = l->next) {
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2190
		EmpathyChatWindowPriv *priv;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2191
		EmpathyChatWindow *chat_window;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2192
		GtkWidget         *dialog;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2193
2194
		chat_window = l->data;
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2195
		priv = GET_PRIV (chat_window);
2196
2197
		dialog = empathy_chat_window_get_dialog (chat_window);
2198
		if (empathy_window_get_is_visible (GTK_WINDOW (dialog))) {
2199
			guint nb_rooms, nb_private;
2200
			empathy_chat_window_get_nb_chats (chat_window, &nb_rooms, &nb_private);
2201
2202
			/* Skip the window if there aren't any rooms in it */
2203
			if (room && nb_rooms == 0)
2204
				continue;
2205
2206
			/* Skip the window if there aren't any 1-1 chats in it */
2207
			if (!room && nb_private == 0)
2208
				continue;
2209
2210
			/* Found a visible window on this desktop */
2211
			return chat_window;
2212
		}
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2213
	}
2214
2215
	return NULL;
2216
}
2217
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2218
GtkWidget *
2219
empathy_chat_window_get_dialog (EmpathyChatWindow *window)
2220
{
2221
	EmpathyChatWindowPriv *priv;
2222
2223
	g_return_val_if_fail (window != NULL, NULL);
2224
2225
	priv = GET_PRIV (window);
2226
2227
	return priv->dialog;
2228
}
2229
2230
void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2231
empathy_chat_window_add_chat (EmpathyChatWindow *window,
2232
			      EmpathyChat	*chat)
2233
{
2234
	EmpathyChatWindowPriv *priv;
2235
	GtkWidget             *label;
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
2236
	GtkWidget             *popup_label;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2237
	GtkWidget             *child;
1.1.45 by Ken VanDine
Import upstream version 2.29.90
2238
	GValue                value = { 0, };
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2239
2240
	g_return_if_fail (window != NULL);
2241
	g_return_if_fail (EMPATHY_IS_CHAT (chat));
2242
2243
	priv = GET_PRIV (window);
2244
2245
	/* Reference the chat object */
2246
	g_object_ref (chat);
2247
1.1.17 by Laurent Bigonville
Import upstream version 2.23.6
2248
	/* If this window has just been created, position it */
2249
	if (priv->chats == NULL) {
1.1.55 by Robert Ancell
Import upstream version 2.31.4
2250
		GSettings *gsettings = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2251
		const gchar *name = "chat-window";
2252
		gboolean     separate_windows;
2253
1.1.55 by Robert Ancell
Import upstream version 2.31.4
2254
		separate_windows = g_settings_get_boolean (gsettings,
2255
				EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS);
2256
2257
		g_object_unref (gsettings);
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2258
2259
		if (separate_windows) {
2260
			name = empathy_chat_get_id (chat);
2261
		}
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2262
		else if (empathy_chat_is_room (chat)) {
2263
			name = "room-window";
2264
		}
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2265
2266
		empathy_geometry_bind (GTK_WINDOW (priv->dialog), name);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2267
	}
2268
2269
	child = GTK_WIDGET (chat);
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
2270
	label = chat_window_create_label (window, chat, TRUE);
2271
	popup_label = chat_window_create_label (window, chat, FALSE);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2272
	gtk_widget_show (child);
2273
2274
	g_signal_connect (chat, "notify::name",
2275
			  G_CALLBACK (chat_window_chat_notify_cb),
2276
			  NULL);
2277
	g_signal_connect (chat, "notify::subject",
2278
			  G_CALLBACK (chat_window_chat_notify_cb),
2279
			  NULL);
2280
	g_signal_connect (chat, "notify::remote-contact",
2281
			  G_CALLBACK (chat_window_chat_notify_cb),
2282
			  NULL);
2283
	chat_window_chat_notify_cb (chat);
2284
1.1.31 by Laurent Bigonville
Import upstream version 2.27.3
2285
	gtk_notebook_append_page_menu (GTK_NOTEBOOK (priv->notebook), child, label, popup_label);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2286
	gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
2287
	gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
1.1.45 by Ken VanDine
Import upstream version 2.29.90
2288
	g_value_init (&value, G_TYPE_BOOLEAN);
2289
	g_value_set_boolean (&value, TRUE);
2290
	gtk_container_child_set_property (GTK_CONTAINER (priv->notebook),
2291
					  child, "tab-expand" , &value);
2292
	gtk_container_child_set_property (GTK_CONTAINER (priv->notebook),
2293
					  child,  "tab-fill" , &value);
2294
	g_value_unset (&value);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2295
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
2296
	DEBUG ("Chat added (%d references)", G_OBJECT (chat)->ref_count);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2297
}
2298
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2299
void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2300
empathy_chat_window_remove_chat (EmpathyChatWindow *window,
2301
				 EmpathyChat	   *chat)
2302
{
2303
	EmpathyChatWindowPriv *priv;
2304
	gint                   position;
2305
	EmpathyContact        *remote_contact;
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2306
	EmpathyChatManager    *chat_manager;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2307
2308
	g_return_if_fail (window != NULL);
2309
	g_return_if_fail (EMPATHY_IS_CHAT (chat));
2310
2311
	priv = GET_PRIV (window);
2312
2313
	g_signal_handlers_disconnect_by_func (chat,
2314
					      chat_window_chat_notify_cb,
2315
					      NULL);
2316
	remote_contact = g_object_get_data (G_OBJECT (chat),
2317
					    "chat-window-remote-contact");
2318
	if (remote_contact) {
2319
		g_signal_handlers_disconnect_by_func (remote_contact,
2320
						      chat_window_update_chat_tab,
2321
						      chat);
2322
	}
2323
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2324
	chat_manager = empathy_chat_manager_dup_singleton ();
2325
	empathy_chat_manager_closed_chat (chat_manager, chat);
2326
	g_object_unref (chat_manager);
2327
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2328
	position = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
2329
					  GTK_WIDGET (chat));
2330
	gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), position);
2331
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
2332
	DEBUG ("Chat removed (%d references)", G_OBJECT (chat)->ref_count - 1);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2333
2334
	g_object_unref (chat);
2335
}
2336
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2337
void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2338
empathy_chat_window_move_chat (EmpathyChatWindow *old_window,
2339
			       EmpathyChatWindow *new_window,
2340
			       EmpathyChat       *chat)
2341
{
2342
	GtkWidget *widget;
2343
2344
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (old_window));
2345
	g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (new_window));
2346
	g_return_if_fail (EMPATHY_IS_CHAT (chat));
2347
2348
	widget = GTK_WIDGET (chat);
2349
1.1.16 by Sjoerd Simons
Import upstream version 0.23.3
2350
	DEBUG ("Chat moving with widget:%p (%d references)", widget,
2351
		G_OBJECT (widget)->ref_count);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2352
2353
	/* We reference here to make sure we don't loose the widget
2354
	 * and the EmpathyChat object during the move.
2355
	 */
2356
	g_object_ref (chat);
2357
	g_object_ref (widget);
2358
2359
	empathy_chat_window_remove_chat (old_window, chat);
2360
	empathy_chat_window_add_chat (new_window, chat);
2361
2362
	g_object_unref (widget);
2363
	g_object_unref (chat);
2364
}
2365
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2366
void
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2367
empathy_chat_window_switch_to_chat (EmpathyChatWindow *window,
2368
				    EmpathyChat	      *chat)
2369
{
2370
	EmpathyChatWindowPriv *priv;
2371
	gint                  page_num;
2372
2373
	g_return_if_fail (window != NULL);
2374
	g_return_if_fail (EMPATHY_IS_CHAT (chat));
2375
2376
	priv = GET_PRIV (window);
2377
2378
	page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
2379
					  GTK_WIDGET (chat));
2380
	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
2381
				       page_num);
2382
}
2383
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2384
gboolean
2385
empathy_chat_window_has_focus (EmpathyChatWindow *window)
2386
{
2387
	EmpathyChatWindowPriv *priv;
2388
	gboolean              has_focus;
2389
2390
	g_return_val_if_fail (EMPATHY_IS_CHAT_WINDOW (window), FALSE);
2391
2392
	priv = GET_PRIV (window);
2393
2394
	g_object_get (priv->dialog, "has-toplevel-focus", &has_focus, NULL);
2395
2396
	return has_focus;
2397
}
2398
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2399
EmpathyChat *
1.5.4 by Laurent Bigonville
Import upstream version 2.29.2
2400
empathy_chat_window_find_chat (TpAccount   *account,
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2401
			       const gchar *id)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2402
{
2403
	GList *l;
2404
1.2.1 by Jonny Lamb
Import upstream version 2.25.91
2405
	g_return_val_if_fail (!EMP_STR_EMPTY (id), NULL);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2406
2407
	for (l = chat_windows; l; l = l->next) {
2408
		EmpathyChatWindowPriv *priv;
2409
		EmpathyChatWindow     *window;
2410
		GList                *ll;
2411
2412
		window = l->data;
2413
		priv = GET_PRIV (window);
2414
2415
		for (ll = priv->chats; ll; ll = ll->next) {
2416
			EmpathyChat *chat;
2417
2418
			chat = ll->data;
2419
1.1.34 by Laurent Bigonville
Import upstream version 2.27.91.1
2420
			if (account == empathy_chat_get_account (chat) &&
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2421
			    !tp_strdiff (id, empathy_chat_get_id (chat))) {
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2422
				return chat;
2423
			}
2424
		}
2425
	}
2426
2427
	return NULL;
2428
}
2429
2430
void
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2431
empathy_chat_window_present_chat (EmpathyChat *chat,
2432
				  gint64 timestamp)
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2433
{
2434
	EmpathyChatWindow     *window;
2435
	EmpathyChatWindowPriv *priv;
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2436
	guint32 x_timestamp;
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2437
2438
	g_return_if_fail (EMPATHY_IS_CHAT (chat));
2439
2440
	window = chat_window_find_chat (chat);
2441
2442
	/* If the chat has no window, create one */
2443
	if (window == NULL) {
1.1.42 by Laurent Bigonville
Import upstream version 2.29.4
2444
		window = empathy_chat_window_get_default (empathy_chat_is_room (chat));
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2445
		if (!window) {
2446
			window = empathy_chat_window_new ();
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2447
			gtk_widget_show_all (GET_PRIV (window)->dialog);
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2448
		}
2449
2450
		empathy_chat_window_add_chat (window, chat);
2451
	}
2452
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2453
	/* Don't force the window to show itself when it wasn't
2454
	 * an action by the user
2455
	 */
1.7.15 by Laurent Bigonville
Import upstream version 2.31.90
2456
	if (!tp_user_action_time_should_present (timestamp, &x_timestamp))
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2457
		return;
2458
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2459
	priv = GET_PRIV (window);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2460
1.7.15 by Laurent Bigonville
Import upstream version 2.31.90
2461
	if (x_timestamp != GDK_CURRENT_TIME) {
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2462
		/* Don't present or switch tab if the action was earlier than the
2463
		 * last actions X time, accounting for overflow and the first ever
2464
		* presentation */
2465
2466
		if (priv->x_user_action_time != 0
2467
			&& X_EARLIER_OR_EQL (x_timestamp, priv->x_user_action_time))
2468
			return;
2469
2470
		priv->x_user_action_time = x_timestamp;
2471
	}
2472
1.1.15 by Sjoerd Simons
Import upstream version 0.23.1
2473
	empathy_chat_window_switch_to_chat (window, chat);
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2474
	empathy_window_present_with_time (GTK_WINDOW (priv->dialog),
2475
	  x_timestamp);
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2476
1.7.9 by Laurent Bigonville
Import upstream version 2.31.1
2477
	gtk_widget_grab_focus (chat->input_text_view);
1.4.2 by Laurent Bigonville
Import upstream version 2.27.1.1
2478
}
2479
1.6.12 by Laurent Bigonville
Import upstream version 2.29.4
2480
void
1.1.42 by Laurent Bigonville
Import upstream version 2.29.4
2481
empathy_chat_window_get_nb_chats (EmpathyChatWindow *self,
2482
			       guint *nb_rooms,
2483
			       guint *nb_private)
2484
{
2485
	EmpathyChatWindowPriv *priv = GET_PRIV (self);
2486
	GList *l;
2487
	guint _nb_rooms = 0, _nb_private = 0;
2488
2489
	for (l = priv->chats; l != NULL; l = g_list_next (l)) {
2490
		if (empathy_chat_is_room (EMPATHY_CHAT (l->data)))
2491
			_nb_rooms++;
2492
		else
2493
			_nb_private++;
2494
	}
2495
2496
	if (nb_rooms != NULL)
2497
		*nb_rooms = _nb_rooms;
2498
	if (nb_private != NULL)
2499
		*nb_private = _nb_private;
2500
}