Remmina - The GTK+ Remote Desktop Client  v1.4.2
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
remmina_message_panel.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include <gtk/gtk.h>
38 #include <glib/gi18n.h>
39 #include "config.h"
40 #include "remmina_public.h"
41 #include "remmina_widget_pool.h"
42 #include "remmina_message_panel.h"
45 
46 
47 typedef struct
48 {
49 
53 
55 G_DEFINE_TYPE_WITH_PRIVATE (RemminaMessagePanel, remmina_message_panel, GTK_TYPE_BOX)
56 
57 
58 enum {
59  RESPONSE,
61 };
62 
63 static guint messagepanel_signals[LAST_SIGNAL];
64 
65 static const gchar btn_response_key[] = "btn_response";
66 
67 static void remmina_message_panel_init (RemminaMessagePanel *mp)
68 {
69  TRACE_CALL(__func__);
70 }
71 
72 static void remmina_message_panel_class_init(RemminaMessagePanelClass *class)
73 {
74  TRACE_CALL(__func__);
75  // class->transform_text = my_app_label_real_transform_text;
76 
77  messagepanel_signals[RESPONSE] =
78  g_signal_new ("response",
79  G_OBJECT_CLASS_TYPE (class),
80  G_SIGNAL_RUN_LAST,
81  G_STRUCT_OFFSET (RemminaMessagePanelClass, response),
82  NULL, NULL,
83  NULL,
84  G_TYPE_NONE, 1,
85  G_TYPE_INT);
86 }
87 
88 RemminaMessagePanel *remmina_message_panel_new()
89 {
90  TRACE_CALL(__func__);
92  RemminaMessagePanel* mp;
93  mp = (RemminaMessagePanel*)g_object_new(REMMINA_TYPE_MESSAGE_PANEL,
94  "orientation", GTK_ORIENTATION_VERTICAL,
95  "spacing", 0,
96  NULL);
97 
98  priv = remmina_message_panel_get_instance_private(mp);
99 
100  priv->response_callback = NULL;
101  priv->response_callback_data = NULL;
102 
103  /* Set widget class, for CSS styling */
104  // gtk_widget_set_name(GTK_WIDGET(mp), "remmina-cw-message-panel");
105  gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(mp)), "message_panel");
106  gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(mp)), "background");
107 
108  return mp;
109 }
110 
112  GtkButton *button, gpointer user_data)
113 {
114  TRACE_CALL(__func__);
115  RemminaMessagePanel *mp = (RemminaMessagePanel*)user_data;
116  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
117 
118  gint btn_data;
119 
120  btn_data = (gint)((gint64)g_object_get_data(G_OBJECT(button), btn_response_key));
121 
122  /* Calls the callback, if defined */
123  if (priv->response_callback != NULL)
124  (*priv->response_callback)(priv->response_callback_data, btn_data);
125 
126 }
127 
128 void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
129 {
130  /*
131  * Setup a message panel to show a spinner, a message like "Connecting…",
132  * and a button to cancel the action in progress
133  *
134  */
135 
136  TRACE_CALL(__func__);
137  GtkBox *hbox;
138  GtkWidget *w;
139  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
140 
142  printf("WARNING: %s called in a subthread. This should not happen.\n", __func__);
143  raise(SIGINT);
144  }
145 
146  hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
147 
148  /* A spinner */
149  w = gtk_spinner_new();
150  gtk_box_pack_start(hbox, w, FALSE, FALSE, 0);
151  gtk_spinner_start(GTK_SPINNER(w));
152 
153  /* A message */
154  w = gtk_label_new(message);
155  gtk_box_pack_start(hbox, w, TRUE, TRUE, 0);
156 
157  priv->response_callback = response_callback;
158  priv->response_callback_data = response_callback_data;
159 
160  /* A button to cancel the action. The cancel button is available
161  * only when a response_callback function is defined. */
162  if (response_callback) {
163  w = gtk_button_new_with_label(_("Cancel"));
164  gtk_box_pack_end(hbox, w, FALSE, FALSE, 0);
165  g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
166  g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
167  }
168 
169  gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0);
170 
171  gtk_widget_show_all(GTK_WIDGET(mp));
172 
173 }
174 
175 void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
176 {
177  /*
178  * Setup a message panel to a message to read like "Cannot connect…",
179  * and a button to close the panel
180  *
181  */
182 
183  TRACE_CALL(__func__);
184  GtkBox *hbox;
185  GtkWidget *w;
186  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
187 
189  printf("WARNING: %s called in a subthread. This should not happen.\n", __func__);
190  }
191 
192  hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
193 
194  /* A message */
195  w = gtk_label_new(message);
196  gtk_box_pack_start(hbox, w, TRUE, TRUE, 0);
197 
198  /* A button to confirm reading */
199  w = gtk_button_new_with_label(_("Close"));
200  gtk_box_pack_end(hbox, w, FALSE, FALSE, 0);
201 
202  priv->response_callback = response_callback;
203  priv->response_callback_data = response_callback_data;
204 
205  g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_OK);
206  g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
207 
208  gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0);
209 
210  gtk_widget_show_all(GTK_WIDGET(mp));
211 
212 }
213 
214 void remmina_message_panel_setup_question(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
215 {
216  /*
217  * Setup a message panel to a message to read like "Do you accept ?",
218  * and a pair of button for Yes and No
219  * message is an HTML string
220  * Callback will receive GTK_RESPONSE_NO for No, GTK_RESPONSE_YES for Yes
221  *
222  */
223 
224  TRACE_CALL(__func__);
225  GtkWidget *grid;
226  GtkWidget *bbox;
227  GtkWidget *w;
228  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
229 
231  printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT for debugging.\n", __func__);
232  raise(SIGINT);
233  }
234 
235  /* Create grid */
236  grid = gtk_grid_new();
237  gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
238  gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
239  gtk_widget_show(grid);
240  gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
241  gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
242 
243  /* A message, in HTML format */
244  w = gtk_label_new(NULL);
245  gtk_label_set_markup(GTK_LABEL(w), message);
246 
247  gtk_widget_set_halign(GTK_WIDGET(w), GTK_ALIGN_START);
248  gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_FILL);
249  gtk_widget_set_margin_top (GTK_WIDGET(w), 18);
250  gtk_widget_set_margin_bottom (GTK_WIDGET(w), 9);
251  gtk_widget_set_margin_start (GTK_WIDGET(w), 18);
252  gtk_widget_set_margin_end (GTK_WIDGET(w), 18);
253  gtk_widget_show(w);
254  gtk_grid_attach(GTK_GRID(grid), w, 0, 0, 2, 1);
255 
256  /* A button for yes and one for no */
257  bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
258  gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
259  gtk_grid_attach(GTK_GRID(grid), bbox, 0, 1, 1, 1);
260  w = gtk_button_new_with_label(_("Yes"));
261  gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_CENTER);
262  g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_YES);
263 
264  g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
265  gtk_container_add(GTK_CONTAINER(bbox), w);
266 
267  w = gtk_button_new_with_label(_("No"));
268  gtk_widget_set_valign(GTK_WIDGET(w), GTK_ALIGN_CENTER);
269  g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_NO);
270 
271  priv->response_callback = response_callback;
272  priv->response_callback_data = response_callback_data;
273 
274  g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
275  gtk_container_add(GTK_CONTAINER(bbox), w);
276 
277  gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(grid), TRUE, TRUE, 0);
278 
279  gtk_widget_show_all(GTK_WIDGET(mp));
280 
281 }
282 
283 void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, const gchar *title, const gchar *password_prompt, unsigned flags)
284 {
285  TRACE_CALL(__func__);
286  GtkWidget *grid;
287  GtkWidget *password_entry;
288  GtkWidget *username_entry;
289  GtkWidget *domain_entry;
290  GtkWidget *save_password_switch;
291  GtkWidget *widget;
292  GtkWidget *bbox;
293  GtkWidget *button_ok;
294  GtkWidget *button_cancel;
295  int grid_row;
296 
297  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
298 
300  printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__);
301  raise(SIGINT);
302  }
303 
304  /* Create grid */
305  grid = gtk_grid_new();
306  gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
307  gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
308  gtk_widget_show(grid);
309  gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
310  gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
311  //gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
312 
313  /* Entries */
314 
315  grid_row = 0;
316  widget = gtk_label_new(title);
317  gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label");
318  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
319  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL);
320  gtk_widget_set_margin_top (GTK_WIDGET(widget), 18);
321  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
322  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
323  gtk_widget_set_margin_end (GTK_WIDGET(widget), 18);
324  gtk_widget_show(widget);
325  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1);
326  grid_row++;
327 
328 
330  widget = gtk_label_new(_("Username"));
331  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
332  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
333  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
334  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
335  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
336  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
337  gtk_widget_show(widget);
338  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
339 
340  username_entry = gtk_entry_new();
341  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
342  gtk_widget_set_halign(GTK_WIDGET(username_entry), GTK_ALIGN_FILL);
343  gtk_widget_set_valign(GTK_WIDGET(username_entry), GTK_ALIGN_FILL);
344  gtk_widget_set_margin_top (GTK_WIDGET(username_entry), 9);
345  gtk_widget_set_margin_bottom (GTK_WIDGET(username_entry), 3);
346  gtk_widget_set_margin_start (GTK_WIDGET(username_entry), 6);
347  gtk_widget_set_margin_end (GTK_WIDGET(username_entry), 18);
348  //gtk_entry_set_activates_default (GTK_ENTRY(username_entry), TRUE);
349  gtk_grid_attach(GTK_GRID(grid), username_entry, 1, grid_row, 2, 1);
350  gtk_entry_set_max_length(GTK_ENTRY(username_entry), 100);
351 
353  g_object_set(username_entry, "editable", FALSE, NULL);
354  }
355 
356  /*
357  if (default_username && default_username[0] != '\0') {
358  gtk_entry_set_text(GTK_ENTRY(username_entry), default_username);
359  }
360  */
361  grid_row++;
362  } else {
363  username_entry = NULL;
364  }
365 
366  /* The password/key field */
367  widget = gtk_label_new(password_prompt);
368  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
369  gtk_widget_set_margin_top (GTK_WIDGET(widget), 3);
370  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
371  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
372  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
373  gtk_widget_show(widget);
374  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
375 
376  password_entry = gtk_entry_new();
377  gtk_widget_set_halign(GTK_WIDGET(password_entry), GTK_ALIGN_FILL);
378  gtk_widget_set_valign(GTK_WIDGET(password_entry), GTK_ALIGN_FILL);
379  gtk_widget_set_margin_top (GTK_WIDGET(password_entry), 3);
380  gtk_widget_set_margin_bottom (GTK_WIDGET(password_entry), 3);
381  gtk_widget_set_margin_start (GTK_WIDGET(password_entry), 6);
382  gtk_widget_set_margin_end (GTK_WIDGET(password_entry), 18);
383  gtk_entry_set_activates_default (GTK_ENTRY(password_entry), TRUE);
384  gtk_grid_attach(GTK_GRID(grid), password_entry, 1, grid_row, 2, 1);
385  gtk_entry_set_max_length(GTK_ENTRY(password_entry), 100);
386  gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
387 
388  grid_row++;
389 
390  if (flags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) {
391  widget = gtk_label_new(_("Domain"));
392  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
393  gtk_widget_set_margin_top (GTK_WIDGET(widget), 3);
394  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
395  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
396  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
397  gtk_widget_show(widget);
398  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
399 
400  domain_entry = gtk_entry_new();
401  gtk_widget_set_halign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
402  gtk_widget_set_valign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
403  gtk_widget_set_margin_top (GTK_WIDGET(domain_entry), 3);
404  gtk_widget_set_margin_bottom (GTK_WIDGET(domain_entry), 3);
405  gtk_widget_set_margin_start (GTK_WIDGET(domain_entry), 6);
406  gtk_widget_set_margin_end (GTK_WIDGET(domain_entry), 18);
407  gtk_entry_set_activates_default (GTK_ENTRY(domain_entry), TRUE);
408  gtk_widget_show(domain_entry);
409  gtk_grid_attach(GTK_GRID(grid), domain_entry, 1, grid_row, 2, 1);
410  gtk_entry_set_max_length(GTK_ENTRY(domain_entry), 100);
411  /* if (default_domain && default_domain[0] != '\0') {
412  gtk_entry_set_text(GTK_ENTRY(domain_entry), default_domain);
413  } */
414  grid_row ++;
415  } else {
416  domain_entry = NULL;
417  }
418 
419 
420  widget = gtk_label_new(_("Save password"));
421  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
422  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
423  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
424  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
425  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
426  gtk_widget_show(widget);
427  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
428  save_password_switch = gtk_switch_new();
429  gtk_widget_set_halign(GTK_WIDGET(save_password_switch), GTK_ALIGN_START);
430  gtk_widget_set_valign(GTK_WIDGET(save_password_switch), GTK_ALIGN_FILL);
431  gtk_widget_set_margin_top (GTK_WIDGET(save_password_switch), 9);
432  gtk_widget_set_margin_bottom (GTK_WIDGET(save_password_switch), 9);
433  gtk_widget_set_margin_start (GTK_WIDGET(save_password_switch), 6);
434  gtk_widget_set_margin_end (GTK_WIDGET(save_password_switch), 18);
435  gtk_grid_attach(GTK_GRID(grid), save_password_switch, 1, grid_row, 2, 1);
437  gtk_switch_set_active(GTK_SWITCH(save_password_switch), TRUE);
438  }else {
439  gtk_switch_set_active(GTK_SWITCH(save_password_switch), FALSE);
440  gtk_widget_set_sensitive(GTK_WIDGET(save_password_switch), FALSE);
441  }
442  grid_row ++;
443 
444  /* Buttons, ok and cancel */
445  bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
446  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
447  gtk_box_set_spacing (GTK_BOX (bbox), 40);
448  gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
449  gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
450  gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
451  gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
452  button_ok = gtk_button_new_with_label(_("_OK"));
453  gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
454  gtk_widget_set_can_default(button_ok, TRUE);
455  gtk_container_add (GTK_CONTAINER (bbox), button_ok);
456  /* Buttons, ok and cancel */
457  button_cancel = gtk_button_new_with_label(_("_Cancel"));
458  gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
459  gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
460  gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
461  /* Pack it into the panel */
462  gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);
463 
464  priv->w[REMMINA_MESSAGE_PANEL_USERNAME] = username_entry;
465  priv->w[REMMINA_MESSAGE_PANEL_PASSWORD] = password_entry;
466  priv->w[REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD] = save_password_switch;
467  priv->w[REMMINA_MESSAGE_PANEL_DOMAIN] = domain_entry;
468  priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;
469 
470  priv->response_callback = response_callback;
471  priv->response_callback_data = response_callback_data;
472 
473  if (username_entry) g_signal_connect_swapped (username_entry, "activate", (GCallback)gtk_widget_grab_focus, password_entry);
474  g_signal_connect_swapped (password_entry, "activate", (GCallback)gtk_widget_grab_focus, button_ok);
475  g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
476  g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
477  g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
478  g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
479 }
480 
481 void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
482 {
483  TRACE_CALL(__func__);
484 
485  GtkWidget *grid;
486  GtkWidget *widget;
487  GtkWidget *bbox;
488  GtkWidget *button_ok;
489  GtkWidget *button_cancel;
490  GtkWidget *cacert_file;
491  GtkWidget *cacrl_file;
492  GtkWidget *clientcert_file;
493  GtkWidget *clientkey_file;
494  int grid_row;
495 
496  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
497 
499  printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__);
500  raise(SIGINT);
501  }
502 
503  /* Create grid */
504  grid = gtk_grid_new();
505  gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
506  gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
507  gtk_widget_show(grid);
508  gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
509  gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
510 
511  /* Entries */
512  grid_row = 0;
513  widget = gtk_label_new(_("Enter certificate authentication files"));
514  gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label");
515  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
516  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL);
517  gtk_widget_set_margin_top (GTK_WIDGET(widget), 18);
518  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
519  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
520  gtk_widget_set_margin_end (GTK_WIDGET(widget), 18);
521  gtk_widget_show(widget);
522  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1);
523  grid_row++;
524 
525  const gchar *lbl_cacert = _("CA Certificate File");
526  widget = gtk_label_new(lbl_cacert);
527  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
528  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
529  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
530  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
531  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
532  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
533  gtk_widget_show(widget);
534  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
535  cacert_file = gtk_file_chooser_button_new(lbl_cacert, GTK_FILE_CHOOSER_ACTION_OPEN);
536  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
537  gtk_widget_show(cacert_file);
538  gtk_widget_set_halign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
539  gtk_widget_set_valign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
540  gtk_widget_set_margin_top (GTK_WIDGET(cacert_file), 9);
541  gtk_widget_set_margin_bottom (GTK_WIDGET(cacert_file), 3);
542  gtk_widget_set_margin_start (GTK_WIDGET(cacert_file), 6);
543  gtk_widget_set_margin_end (GTK_WIDGET(cacert_file), 18);
544  gtk_grid_attach(GTK_GRID(grid), cacert_file, 1, grid_row, 2, 1);
545  grid_row++;
546 
547  const gchar *lbl_cacrl = _("CA CRL File");
548  widget = gtk_label_new(lbl_cacrl);
549  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
550  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
551  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
552  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
553  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
554  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
555  gtk_widget_show(widget);
556  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
557  cacrl_file = gtk_file_chooser_button_new(lbl_cacrl, GTK_FILE_CHOOSER_ACTION_OPEN);
558  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
559  gtk_widget_show(cacrl_file);
560  gtk_widget_set_halign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
561  gtk_widget_set_valign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
562  gtk_widget_set_margin_top (GTK_WIDGET(cacrl_file), 9);
563  gtk_widget_set_margin_bottom (GTK_WIDGET(cacrl_file), 3);
564  gtk_widget_set_margin_start (GTK_WIDGET(cacrl_file), 6);
565  gtk_widget_set_margin_end (GTK_WIDGET(cacrl_file), 18);
566  gtk_grid_attach(GTK_GRID(grid), cacrl_file, 1, grid_row, 2, 1);
567  grid_row++;
568 
569  const gchar *lbl_clicert = _("Client Certificate File");
570  widget = gtk_label_new(lbl_clicert);
571  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
572  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
573  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
574  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
575  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
576  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
577  gtk_widget_show(widget);
578  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
579  clientcert_file = gtk_file_chooser_button_new(lbl_clicert, GTK_FILE_CHOOSER_ACTION_OPEN);
580  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
581  gtk_widget_show(clientcert_file);
582  gtk_widget_set_halign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
583  gtk_widget_set_valign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
584  gtk_widget_set_margin_top (GTK_WIDGET(clientcert_file), 9);
585  gtk_widget_set_margin_bottom (GTK_WIDGET(clientcert_file), 3);
586  gtk_widget_set_margin_start (GTK_WIDGET(clientcert_file), 6);
587  gtk_widget_set_margin_end (GTK_WIDGET(clientcert_file), 18);
588  gtk_grid_attach(GTK_GRID(grid), clientcert_file, 1, grid_row, 2, 1);
589  grid_row++;
590 
591  const gchar *lbl_clikey = _("Client Certificate Key");
592  widget = gtk_label_new(lbl_clikey);
593  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
594  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
595  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
596  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
597  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
598  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
599  gtk_widget_show(widget);
600  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
601  clientkey_file = gtk_file_chooser_button_new(lbl_clikey, GTK_FILE_CHOOSER_ACTION_OPEN);
602  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
603  gtk_widget_show(clientkey_file);
604  gtk_widget_set_halign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
605  gtk_widget_set_valign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
606  gtk_widget_set_margin_top (GTK_WIDGET(clientkey_file), 9);
607  gtk_widget_set_margin_bottom (GTK_WIDGET(clientkey_file), 3);
608  gtk_widget_set_margin_start (GTK_WIDGET(clientkey_file), 6);
609  gtk_widget_set_margin_end (GTK_WIDGET(clientkey_file), 18);
610  gtk_grid_attach(GTK_GRID(grid), clientkey_file, 1, grid_row, 2, 1);
611  grid_row++;
612 
613  /* Buttons, ok and cancel */
614  bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
615  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
616  gtk_box_set_spacing (GTK_BOX (bbox), 40);
617  gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
618  gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
619  gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
620  gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
621  button_ok = gtk_button_new_with_label(_("_OK"));
622  gtk_widget_set_can_default (button_ok, TRUE);
623 
624  gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
625  //gtk_widget_show(button_ok);
626  gtk_container_add (GTK_CONTAINER (bbox), button_ok);
627  //gtk_grid_attach(GTK_GRID(grid), button_ok, 0, grid_row, 1, 1);
628  /* Buttons, ok and cancel */
629  button_cancel = gtk_button_new_with_label(_("_Cancel"));
630  gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
631  //gtk_widget_show(button_cancel);
632  gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
633  gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
634  /* Pack it into the panel */
635  gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);
636 
637  priv->response_callback = response_callback;
638  priv->response_callback_data = response_callback_data;
639 
640  priv->w[REMMINA_MESSAGE_PANEL_CACERTFILE] = cacert_file;
641  priv->w[REMMINA_MESSAGE_PANEL_CACRLFILE] = cacrl_file;
642  priv->w[REMMINA_MESSAGE_PANEL_CLIENTCERTFILE] = clientcert_file;
643  priv->w[REMMINA_MESSAGE_PANEL_CLIENTKEYFILE] = clientkey_file;
644  priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;
645 
646  g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
647  g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
648  g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
649  g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
650 
651 }
652 
653 void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
654 {
655  TRACE_CALL(__func__);
656 
658  GtkWidget *w;
659  const gchar *username;
660 
661  if (mp == NULL)
662  return;
663  priv = remmina_message_panel_get_instance_private(mp);
664 
665  /* Activate default button */
667  if (w && G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_button_get_type()))
668  gtk_widget_grab_default(w);
669 
671  if (w == NULL)
672  {
674  }else {
675  username = gtk_entry_get_text(GTK_ENTRY(w));
676  if (username[0] != 0)
678  }
679  if (w == NULL)
680  return;
681 
682  if (!G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_entry_get_type()))
683  return;
684 
685  gtk_widget_grab_focus(w);
686 }
687 
688 void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text)
689 {
691 
692  if (mp == NULL)
693  return;
694  priv = remmina_message_panel_get_instance_private(mp);
695 
696  if (priv->w[entryid] == NULL)
697  return;
698  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
699  return;
700 
701  gtk_entry_set_text(GTK_ENTRY(priv->w[entryid]), text != NULL ? text : "");
702 }
703 
704 gchar* remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid)
705 {
706  TRACE_CALL(__func__);
707 
709 
710  if (mp == NULL)
711  return NULL;
712  priv = remmina_message_panel_get_instance_private(mp);
713 
714  if (priv->w[entryid] == NULL)
715  return NULL;
716  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
717  return NULL;
718 
719  return g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->w[entryid])));
720 }
721 
722 void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state)
723 {
724  TRACE_CALL(__func__);
725 
727 
728  if (mp == NULL)
729  return;
730  priv = remmina_message_panel_get_instance_private(mp);
731 
732  if (priv->w[entryid] == NULL)
733  return;
734  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
735  return;
736 
737  gtk_switch_set_state(GTK_SWITCH(priv->w[entryid]), state);
738 }
739 
740 gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid)
741 {
742  TRACE_CALL(__func__);
743 
745 
746  if (mp == NULL)
747  return FALSE;
748  priv = remmina_message_panel_get_instance_private(mp);
749 
750  if (priv->w[entryid] == NULL)
751  return FALSE;
752  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
753  return FALSE;
754 
755  return gtk_switch_get_state(GTK_SWITCH(priv->w[entryid]));
756 }
757 
758 
759 void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename)
760 {
761  TRACE_CALL(__func__);
762 
764 
765  if (mp == NULL)
766  return;
767  priv = remmina_message_panel_get_instance_private(mp);
768  if (priv->w[entryid] == NULL)
769  return;
770  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
771  return;
772 
773  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->w[entryid]), filename);
774 }
775 
776 gchar* remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid)
777 {
778  TRACE_CALL(__func__);
779 
781 
782  if (mp == NULL)
783  return NULL;
784  priv = remmina_message_panel_get_instance_private(mp);
785 
786  if (priv->w[entryid] == NULL)
787  return NULL;
788  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
789  return NULL;
790 
791  return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->w[entryid]));
792 }
793 
794 void remmina_message_panel_response(RemminaMessagePanel *mp, gint response_id)
795 {
796  g_signal_emit(mp, messagepanel_signals[RESPONSE], 0, response_id);
797 }
798 
static void remmina_message_panel_init(RemminaMessagePanel *mp)
static guint messagepanel_signals[LAST_SIGNAL]
void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, const gchar *title, const gchar *password_prompt, unsigned flags)
void remmina_message_panel_setup_question(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
gchar * remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid)
void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
static void remmina_message_panel_class_init(RemminaMessagePanelClass *class)
void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text)
void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename)
gboolean remmina_masterthread_exec_is_main_thread()
void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state)
void(* RemminaMessagePanelCallback)(void *user_data, int button)
G_DEFINE_TYPE_WITH_PRIVATE(RemminaMessagePanel, remmina_message_panel, GTK_TYPE_BOX)
gchar * remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid)
void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid)
static const gchar btn_response_key[]
void remmina_message_panel_response(RemminaMessagePanel *mp, gint response_id)
RemminaMessagePanelCallback response_callback
GtkWidget * w[REMMINA_MESSAGE_PANEL_MAXWIDGETID]
RemminaMessagePanel * remmina_message_panel_new()
static void remmina_message_panel_button_clicked_callback(GtkButton *button, gpointer user_data)