]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-password-dialog.c
Don't turn on echo cancellation on the sink if it's for raw conferences
[empathy.git] / libempathy-gtk / empathy-password-dialog.c
1 /*
2  * empathy-password-dialog.c - Source for EmpathyPasswordDialog
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include <config.h>
21
22 #include "empathy-password-dialog.h"
23
24 #include <glib/gi18n-lib.h>
25
26 #define DEBUG_FLAG EMPATHY_DEBUG_SASL
27 #include <libempathy/empathy-debug.h>
28 #include <libempathy/empathy-utils.h>
29
30 G_DEFINE_TYPE (EmpathyPasswordDialog, empathy_password_dialog,
31     GTK_TYPE_MESSAGE_DIALOG)
32
33 enum {
34   PROP_HANDLER = 1,
35
36   LAST_PROPERTY,
37 };
38
39 typedef struct {
40   EmpathyServerSASLHandler *handler;
41
42   GtkWidget *entry;
43   GtkWidget *ticky;
44   GtkWidget *ok_button;
45
46   gboolean grabbing;
47
48   gboolean dispose_run;
49 } EmpathyPasswordDialogPriv;
50
51 static void
52 empathy_password_dialog_get_property (GObject *object,
53     guint property_id,
54     GValue *value,
55     GParamSpec *pspec)
56 {
57   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
58
59   switch (property_id)
60     {
61     case PROP_HANDLER:
62       g_value_set_object (value, priv->handler);
63       break;
64     default:
65       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
66       break;
67     }
68 }
69
70 static void
71 empathy_password_dialog_set_property (GObject *object,
72     guint property_id,
73     const GValue *value,
74     GParamSpec *pspec)
75 {
76   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
77
78   switch (property_id)
79     {
80     case PROP_HANDLER:
81       g_assert (priv->handler == NULL); /* construct only */
82       priv->handler = g_value_dup_object (value);
83       break;
84     default:
85       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
86       break;
87     }
88 }
89
90 static void
91 empathy_password_dialog_dispose (GObject *object)
92 {
93   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
94
95   if (priv->dispose_run)
96     return;
97
98   priv->dispose_run = TRUE;
99
100   tp_clear_object (&priv->handler);
101
102   G_OBJECT_CLASS (empathy_password_dialog_parent_class)->dispose (object);
103 }
104
105 static void
106 password_dialog_response_cb (GtkDialog *dialog,
107     gint response,
108     gpointer user_data)
109 {
110   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
111
112   if (response == GTK_RESPONSE_OK)
113     {
114       empathy_server_sasl_handler_provide_password (priv->handler,
115           gtk_entry_get_text (GTK_ENTRY (priv->entry)),
116           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->ticky)));
117     }
118   else
119     {
120       empathy_server_sasl_handler_cancel (priv->handler);
121     }
122
123   gtk_widget_destroy (GTK_WIDGET (dialog));
124 }
125
126 static void
127 clear_icon_released_cb (GtkEntry *entry,
128     GtkEntryIconPosition icon_pos,
129     GdkEvent *event,
130     gpointer user_data)
131 {
132   gtk_entry_set_text (entry, "");
133 }
134
135 static void
136 password_entry_changed_cb (GtkEditable *entry,
137     gpointer user_data)
138 {
139   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
140   const gchar *str;
141
142   str = gtk_entry_get_text (GTK_ENTRY (entry));
143
144   gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
145       GTK_ENTRY_ICON_SECONDARY, !EMP_STR_EMPTY (str));
146
147   gtk_widget_set_sensitive (priv->ok_button,
148       !EMP_STR_EMPTY (str));
149 }
150
151 static void
152 password_entry_activate_cb (GtkEntry *entry,
153     EmpathyPasswordDialog *self)
154 {
155   gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
156 }
157
158 static gboolean
159 password_dialog_grab_keyboard (GtkWidget *widget,
160     GdkEvent *event,
161     gpointer user_data)
162 {
163   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
164
165   if (!priv->grabbing)
166     {
167       GdkDevice *device = gdk_event_get_device (event);
168
169       if (device != NULL)
170         {
171           GdkGrabStatus status = gdk_device_grab (device,
172               gtk_widget_get_window (widget),
173               GDK_OWNERSHIP_WINDOW,
174               FALSE,
175               GDK_ALL_EVENTS_MASK,
176               NULL,
177               gdk_event_get_time (event));
178
179           if (status != GDK_GRAB_SUCCESS)
180             DEBUG ("Could not grab keyboard; grab status was %u", status);
181           else
182             priv->grabbing = TRUE;
183         }
184       else
185         DEBUG ("Could not get the event device!");
186     }
187
188   return FALSE;
189 }
190
191 static gboolean
192 password_dialog_ungrab_keyboard (GtkWidget *widget,
193     GdkEvent *event,
194     gpointer user_data)
195 {
196   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
197
198   if (priv->grabbing)
199     {
200       GdkDevice *device = gdk_event_get_device (event);
201
202       if (device != NULL)
203         {
204           gdk_device_ungrab (device, gdk_event_get_time (event));
205           priv->grabbing = FALSE;
206         }
207       else
208         DEBUG ("Could not get the event device!");
209     }
210
211   return FALSE;
212 }
213
214 static gboolean
215 password_dialog_window_state_changed (GtkWidget *widget,
216     GdkEventWindowState *event,
217     gpointer data)
218 {
219   GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (widget));
220
221   if (state & GDK_WINDOW_STATE_WITHDRAWN
222       || state & GDK_WINDOW_STATE_ICONIFIED
223       || state & GDK_WINDOW_STATE_FULLSCREEN
224       || state & GDK_WINDOW_STATE_MAXIMIZED)
225     {
226       password_dialog_ungrab_keyboard (widget, (GdkEvent *) event, data);
227     }
228   else
229     {
230       password_dialog_grab_keyboard (widget, (GdkEvent *) event, data);
231     }
232
233   return FALSE;
234 }
235
236 static void
237 password_dialog_handler_invalidated_cb (EmpathyServerSASLHandler *handler,
238     EmpathyPasswordDialog *dialog)
239 {
240   gtk_widget_destroy (GTK_WIDGET (dialog));
241 }
242
243 static void
244 empathy_password_dialog_constructed (GObject *object)
245 {
246   EmpathyPasswordDialog *dialog;
247   EmpathyPasswordDialogPriv *priv;
248   TpAccount *account;
249   GtkWidget *icon;
250   GtkBox *box;
251   gchar *text;
252
253   dialog = EMPATHY_PASSWORD_DIALOG (object);
254   priv = dialog->priv;
255
256   g_assert (priv->handler != NULL);
257
258   priv->grabbing = FALSE;
259
260   account = empathy_server_sasl_handler_get_account (priv->handler);
261
262   tp_g_signal_connect_object (priv->handler, "invalidated",
263       G_CALLBACK (password_dialog_handler_invalidated_cb),
264       object, 0);
265
266   /* dialog */
267   gtk_dialog_add_button (GTK_DIALOG (dialog),
268       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
269
270   priv->ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
271       GTK_STOCK_OK, GTK_RESPONSE_OK);
272   gtk_widget_set_sensitive (priv->ok_button, FALSE);
273
274   text = g_strdup_printf (_("Enter your password for account\n<b>%s</b>"),
275       tp_account_get_display_name (account));
276   gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), text);
277   g_free (text);
278
279   gtk_window_set_icon_name (GTK_WINDOW (dialog),
280       GTK_STOCK_DIALOG_AUTHENTICATION);
281
282   box = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
283
284   /* dialog icon */
285   icon = gtk_image_new_from_icon_name (tp_account_get_icon_name (account),
286       GTK_ICON_SIZE_DIALOG);
287   gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), icon);
288   gtk_widget_show (icon);
289
290   /* entry */
291   priv->entry = gtk_entry_new ();
292   gtk_entry_set_visibility (GTK_ENTRY (priv->entry), FALSE);
293
294   /* entry clear icon */
295   gtk_entry_set_icon_from_stock (GTK_ENTRY (priv->entry),
296       GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
297   gtk_entry_set_icon_sensitive (GTK_ENTRY (priv->entry),
298       GTK_ENTRY_ICON_SECONDARY, FALSE);
299
300   g_signal_connect (priv->entry, "icon-release",
301       G_CALLBACK (clear_icon_released_cb), NULL);
302   g_signal_connect (priv->entry, "changed",
303       G_CALLBACK (password_entry_changed_cb), dialog);
304   g_signal_connect (priv->entry, "activate",
305       G_CALLBACK (password_entry_activate_cb), dialog);
306
307   gtk_box_pack_start (box, priv->entry, FALSE, FALSE, 0);
308   gtk_widget_show (priv->entry);
309
310   /* remember password ticky box */
311   priv->ticky = gtk_check_button_new_with_label (_("Remember password"));
312
313   gtk_box_pack_start (box, priv->ticky, FALSE, FALSE, 0);
314
315   /* only show it if we actually support it */
316   if (empathy_server_sasl_handler_can_save_response_somewhere (priv->handler))
317     gtk_widget_show (priv->ticky);
318
319   g_signal_connect (dialog, "response",
320       G_CALLBACK (password_dialog_response_cb), dialog);
321   g_signal_connect (dialog, "window-state-event",
322       G_CALLBACK (password_dialog_window_state_changed), dialog);
323   g_signal_connect (dialog, "map-event",
324       G_CALLBACK (password_dialog_grab_keyboard), dialog);
325   g_signal_connect (dialog, "unmap-event",
326       G_CALLBACK (password_dialog_ungrab_keyboard), dialog);
327
328   gtk_widget_grab_focus (priv->entry);
329
330   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
331 }
332
333 static void
334 empathy_password_dialog_init (EmpathyPasswordDialog *self)
335 {
336   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
337       EMPATHY_TYPE_PASSWORD_DIALOG, EmpathyPasswordDialogPriv);
338 }
339
340 static void
341 empathy_password_dialog_class_init (EmpathyPasswordDialogClass *klass)
342 {
343   GParamSpec *pspec;
344   GObjectClass *oclass = G_OBJECT_CLASS (klass);
345
346   g_type_class_add_private (klass, sizeof (EmpathyPasswordDialogPriv));
347
348   oclass->set_property = empathy_password_dialog_set_property;
349   oclass->get_property = empathy_password_dialog_get_property;
350   oclass->dispose = empathy_password_dialog_dispose;
351   oclass->constructed = empathy_password_dialog_constructed;
352
353   pspec = g_param_spec_object ("handler", "The EmpathyServerSASLHandler",
354       "The EmpathyServerSASLHandler to be used.",
355       EMPATHY_TYPE_SERVER_SASL_HANDLER,
356       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
357   g_object_class_install_property (oclass, PROP_HANDLER, pspec);
358 }
359
360 GtkWidget *
361 empathy_password_dialog_new (EmpathyServerSASLHandler *handler)
362 {
363   g_assert (EMPATHY_IS_SERVER_SASL_HANDLER (handler));
364
365   return g_object_new (EMPATHY_TYPE_PASSWORD_DIALOG,
366       "handler", handler, NULL);
367 }