Remmina - The GTK+ Remote Desktop Client  v1.4.33
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-2023 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 <glib/gi18n.h>
38 #include "config.h"
39 #include "remmina_public.h"
40 #include "remmina_widget_pool.h"
41 #include "remmina_main.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), 0);
386  gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
387  gtk_entry_set_icon_from_icon_name(GTK_ENTRY(password_entry), GTK_ENTRY_ICON_SECONDARY, "org.remmina.Remmina-password-reveal-symbolic");
388  gtk_entry_set_icon_activatable(GTK_ENTRY(password_entry), GTK_ENTRY_ICON_SECONDARY, TRUE);
389  g_signal_connect(password_entry, "icon-press", G_CALLBACK(remmina_main_toggle_password_view), NULL);
390 
391  grid_row++;
392 
393  if (flags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) {
394  widget = gtk_label_new(_("Domain"));
395  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
396  gtk_widget_set_margin_top (GTK_WIDGET(widget), 3);
397  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
398  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
399  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
400  gtk_widget_show(widget);
401  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
402 
403  domain_entry = gtk_entry_new();
404  gtk_widget_set_halign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
405  gtk_widget_set_valign(GTK_WIDGET(domain_entry), GTK_ALIGN_FILL);
406  gtk_widget_set_margin_top (GTK_WIDGET(domain_entry), 3);
407  gtk_widget_set_margin_bottom (GTK_WIDGET(domain_entry), 3);
408  gtk_widget_set_margin_start (GTK_WIDGET(domain_entry), 6);
409  gtk_widget_set_margin_end (GTK_WIDGET(domain_entry), 18);
410  gtk_entry_set_activates_default (GTK_ENTRY(domain_entry), TRUE);
411  gtk_widget_show(domain_entry);
412  gtk_grid_attach(GTK_GRID(grid), domain_entry, 1, grid_row, 2, 1);
413  gtk_entry_set_max_length(GTK_ENTRY(domain_entry), 100);
414  /* if (default_domain && default_domain[0] != '\0') {
415  gtk_entry_set_text(GTK_ENTRY(domain_entry), default_domain);
416  } */
417  grid_row ++;
418  } else {
419  domain_entry = NULL;
420  }
421 
422 
423  widget = gtk_label_new(_("Save password"));
424  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
425  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
426  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
427  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
428  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
429  gtk_widget_show(widget);
430  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
431  save_password_switch = gtk_switch_new();
432  gtk_widget_set_halign(GTK_WIDGET(save_password_switch), GTK_ALIGN_START);
433  gtk_widget_set_valign(GTK_WIDGET(save_password_switch), GTK_ALIGN_FILL);
434  gtk_widget_set_margin_top (GTK_WIDGET(save_password_switch), 9);
435  gtk_widget_set_margin_bottom (GTK_WIDGET(save_password_switch), 9);
436  gtk_widget_set_margin_start (GTK_WIDGET(save_password_switch), 6);
437  gtk_widget_set_margin_end (GTK_WIDGET(save_password_switch), 18);
438  gtk_grid_attach(GTK_GRID(grid), save_password_switch, 1, grid_row, 2, 1);
440  gtk_switch_set_active(GTK_SWITCH(save_password_switch), TRUE);
441  }else {
442  gtk_switch_set_active(GTK_SWITCH(save_password_switch), FALSE);
443  gtk_widget_set_sensitive(GTK_WIDGET(save_password_switch), FALSE);
444  }
445  grid_row ++;
446 
447  /* Buttons, ok and cancel */
448  bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
449  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
450  gtk_box_set_spacing (GTK_BOX (bbox), 40);
451  gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
452  gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
453  gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
454  gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
455  button_ok = gtk_button_new_with_label(_("_OK"));
456  gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
457  gtk_widget_set_can_default(button_ok, TRUE);
458  gtk_container_add (GTK_CONTAINER (bbox), button_ok);
459  /* Buttons, ok and cancel */
460  button_cancel = gtk_button_new_with_label(_("_Cancel"));
461  gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
462  gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
463  gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
464  /* Pack it into the panel */
465  gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);
466 
467  priv->w[REMMINA_MESSAGE_PANEL_USERNAME] = username_entry;
468  priv->w[REMMINA_MESSAGE_PANEL_PASSWORD] = password_entry;
469  priv->w[REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD] = save_password_switch;
470  priv->w[REMMINA_MESSAGE_PANEL_DOMAIN] = domain_entry;
471  priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;
472 
473  priv->response_callback = response_callback;
474  priv->response_callback_data = response_callback_data;
475 
476  if (username_entry) g_signal_connect_swapped (username_entry, "activate", (GCallback)gtk_widget_grab_focus, password_entry);
477  g_signal_connect_swapped (password_entry, "activate", (GCallback)gtk_widget_grab_focus, button_ok);
478  g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
479  g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
480  g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
481  g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
482 }
483 
484 void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
485 {
486  TRACE_CALL(__func__);
487 
488  GtkWidget *grid;
489  GtkWidget *widget;
490  GtkWidget *bbox;
491  GtkWidget *button_ok;
492  GtkWidget *button_cancel;
493  GtkWidget *cacert_file;
494  GtkWidget *cacrl_file;
495  GtkWidget *clientcert_file;
496  GtkWidget *clientkey_file;
497  int grid_row;
498 
499  RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp);
500 
502  printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__);
503  raise(SIGINT);
504  }
505 
506  /* Create grid */
507  grid = gtk_grid_new();
508  gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
509  gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER);
510  gtk_widget_show(grid);
511  gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
512  gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
513 
514  /* Entries */
515  grid_row = 0;
516  widget = gtk_label_new(_("Enter certificate authentication files"));
517  gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label");
518  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
519  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL);
520  gtk_widget_set_margin_top (GTK_WIDGET(widget), 18);
521  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9);
522  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
523  gtk_widget_set_margin_end (GTK_WIDGET(widget), 18);
524  gtk_widget_show(widget);
525  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1);
526  grid_row++;
527 
528  const gchar *lbl_cacert = _("CA Certificate File");
529  widget = gtk_label_new(lbl_cacert);
530  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
531  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
532  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
533  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
534  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
535  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
536  gtk_widget_show(widget);
537  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
538  cacert_file = gtk_file_chooser_button_new(lbl_cacert, GTK_FILE_CHOOSER_ACTION_OPEN);
539  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
540  gtk_widget_show(cacert_file);
541  gtk_widget_set_halign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
542  gtk_widget_set_valign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL);
543  gtk_widget_set_margin_top (GTK_WIDGET(cacert_file), 9);
544  gtk_widget_set_margin_bottom (GTK_WIDGET(cacert_file), 3);
545  gtk_widget_set_margin_start (GTK_WIDGET(cacert_file), 6);
546  gtk_widget_set_margin_end (GTK_WIDGET(cacert_file), 18);
547  gtk_grid_attach(GTK_GRID(grid), cacert_file, 1, grid_row, 2, 1);
548  grid_row++;
549 
550  const gchar *lbl_cacrl = _("CA CRL File");
551  widget = gtk_label_new(lbl_cacrl);
552  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
553  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
554  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
555  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
556  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
557  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
558  gtk_widget_show(widget);
559  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
560  cacrl_file = gtk_file_chooser_button_new(lbl_cacrl, GTK_FILE_CHOOSER_ACTION_OPEN);
561  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
562  gtk_widget_show(cacrl_file);
563  gtk_widget_set_halign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
564  gtk_widget_set_valign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL);
565  gtk_widget_set_margin_top (GTK_WIDGET(cacrl_file), 9);
566  gtk_widget_set_margin_bottom (GTK_WIDGET(cacrl_file), 3);
567  gtk_widget_set_margin_start (GTK_WIDGET(cacrl_file), 6);
568  gtk_widget_set_margin_end (GTK_WIDGET(cacrl_file), 18);
569  gtk_grid_attach(GTK_GRID(grid), cacrl_file, 1, grid_row, 2, 1);
570  grid_row++;
571 
572  const gchar *lbl_clicert = _("Client Certificate File");
573  widget = gtk_label_new(lbl_clicert);
574  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
575  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
576  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
577  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
578  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
579  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
580  gtk_widget_show(widget);
581  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
582  clientcert_file = gtk_file_chooser_button_new(lbl_clicert, GTK_FILE_CHOOSER_ACTION_OPEN);
583  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
584  gtk_widget_show(clientcert_file);
585  gtk_widget_set_halign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
586  gtk_widget_set_valign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL);
587  gtk_widget_set_margin_top (GTK_WIDGET(clientcert_file), 9);
588  gtk_widget_set_margin_bottom (GTK_WIDGET(clientcert_file), 3);
589  gtk_widget_set_margin_start (GTK_WIDGET(clientcert_file), 6);
590  gtk_widget_set_margin_end (GTK_WIDGET(clientcert_file), 18);
591  gtk_grid_attach(GTK_GRID(grid), clientcert_file, 1, grid_row, 2, 1);
592  grid_row++;
593 
594  const gchar *lbl_clikey = _("Client Certificate Key");
595  widget = gtk_label_new(lbl_clikey);
596  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
597  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
598  gtk_widget_set_margin_top (GTK_WIDGET(widget), 9);
599  gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3);
600  gtk_widget_set_margin_start (GTK_WIDGET(widget), 18);
601  gtk_widget_set_margin_end (GTK_WIDGET(widget), 6);
602  gtk_widget_show(widget);
603  gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1);
604  clientkey_file = gtk_file_chooser_button_new(lbl_clikey, GTK_FILE_CHOOSER_ACTION_OPEN);
605  // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry");
606  gtk_widget_show(clientkey_file);
607  gtk_widget_set_halign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
608  gtk_widget_set_valign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL);
609  gtk_widget_set_margin_top (GTK_WIDGET(clientkey_file), 9);
610  gtk_widget_set_margin_bottom (GTK_WIDGET(clientkey_file), 3);
611  gtk_widget_set_margin_start (GTK_WIDGET(clientkey_file), 6);
612  gtk_widget_set_margin_end (GTK_WIDGET(clientkey_file), 18);
613  gtk_grid_attach(GTK_GRID(grid), clientkey_file, 1, grid_row, 2, 1);
614  grid_row++;
615 
616  /* Buttons, ok and cancel */
617  bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
618  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
619  gtk_box_set_spacing (GTK_BOX (bbox), 40);
620  gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9);
621  gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18);
622  gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18);
623  gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18);
624  button_ok = gtk_button_new_with_label(_("_OK"));
625  gtk_widget_set_can_default (button_ok, TRUE);
626 
627  gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE);
628  //gtk_widget_show(button_ok);
629  gtk_container_add (GTK_CONTAINER (bbox), button_ok);
630  //gtk_grid_attach(GTK_GRID(grid), button_ok, 0, grid_row, 1, 1);
631  /* Buttons, ok and cancel */
632  button_cancel = gtk_button_new_with_label(_("_Cancel"));
633  gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE);
634  //gtk_widget_show(button_cancel);
635  gtk_container_add (GTK_CONTAINER (bbox), button_cancel);
636  gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1);
637  /* Pack it into the panel */
638  gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4);
639 
640  priv->response_callback = response_callback;
641  priv->response_callback_data = response_callback_data;
642 
643  priv->w[REMMINA_MESSAGE_PANEL_CACERTFILE] = cacert_file;
644  priv->w[REMMINA_MESSAGE_PANEL_CACRLFILE] = cacrl_file;
645  priv->w[REMMINA_MESSAGE_PANEL_CLIENTCERTFILE] = clientcert_file;
646  priv->w[REMMINA_MESSAGE_PANEL_CLIENTKEYFILE] = clientkey_file;
647  priv->w[REMMINA_MESSAGE_PANEL_BUTTONTOFOCUS] = button_ok;
648 
649  g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL);
650  g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
651  g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK);
652  g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp);
653 
654 }
655 
656 void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
657 {
658  TRACE_CALL(__func__);
659 
661  GtkWidget *w;
662  const gchar *username;
663 
664  if (mp == NULL)
665  return;
666  priv = remmina_message_panel_get_instance_private(mp);
667 
668  /* Activate default button */
670  if (w && G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_button_get_type()))
671  gtk_widget_grab_default(w);
672 
674  if (w == NULL)
675  {
677  }else {
678  username = gtk_entry_get_text(GTK_ENTRY(w));
679  if (username[0] != 0)
681  }
682  if (w == NULL)
683  return;
684 
685  if (!G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_entry_get_type()))
686  return;
687 
688  gtk_widget_grab_focus(w);
689 }
690 
691 void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text)
692 {
694 
695  if (mp == NULL)
696  return;
697  priv = remmina_message_panel_get_instance_private(mp);
698 
699  if (priv->w[entryid] == NULL)
700  return;
701  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
702  return;
703 
704  gtk_entry_set_text(GTK_ENTRY(priv->w[entryid]), text != NULL ? text : "");
705 }
706 
707 gchar* remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid)
708 {
709  TRACE_CALL(__func__);
710 
712 
713  if (mp == NULL)
714  return NULL;
715  priv = remmina_message_panel_get_instance_private(mp);
716 
717  if (priv->w[entryid] == NULL)
718  return NULL;
719  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type()))
720  return NULL;
721 
722  return g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->w[entryid])));
723 }
724 
725 void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state)
726 {
727  TRACE_CALL(__func__);
728 
730 
731  if (mp == NULL)
732  return;
733  priv = remmina_message_panel_get_instance_private(mp);
734 
735  if (priv->w[entryid] == NULL)
736  return;
737  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
738  return;
739 
740  gtk_switch_set_state(GTK_SWITCH(priv->w[entryid]), state);
741 }
742 
743 gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid)
744 {
745  TRACE_CALL(__func__);
746 
748 
749  if (mp == NULL)
750  return FALSE;
751  priv = remmina_message_panel_get_instance_private(mp);
752 
753  if (priv->w[entryid] == NULL)
754  return FALSE;
755  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type()))
756  return FALSE;
757 
758  return gtk_switch_get_state(GTK_SWITCH(priv->w[entryid]));
759 }
760 
761 
762 void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename)
763 {
764  TRACE_CALL(__func__);
765 
767 
768  if (mp == NULL)
769  return;
770  priv = remmina_message_panel_get_instance_private(mp);
771  if (priv->w[entryid] == NULL)
772  return;
773  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
774  return;
775 
776  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->w[entryid]), filename);
777 }
778 
779 gchar* remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid)
780 {
781  TRACE_CALL(__func__);
782 
784 
785  if (mp == NULL)
786  return NULL;
787  priv = remmina_message_panel_get_instance_private(mp);
788 
789  if (priv->w[entryid] == NULL)
790  return NULL;
791  if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type()))
792  return NULL;
793 
794  return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->w[entryid]));
795 }
796 
797 void remmina_message_panel_response(RemminaMessagePanel *mp, gint response_id)
798 {
799  g_signal_emit(mp, messagepanel_signals[RESPONSE], 0, response_id);
800 }
801 
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_main_toggle_password_view(GtkWidget *widget, gpointer 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)