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.
nx_session_manager.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2010 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 "common/remmina_plugin.h"
38 #include <X11/Xlib.h>
39 #include "nx_plugin.h"
40 #include "nx_session_manager.h"
41 
43 {
44  TRACE_CALL(__func__);
45  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
46 
47  if (gpdata->attach_session) {
48  gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_TERMINATE, sensitive);
49  gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_ATTACH, sensitive);
50  }else {
51  gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_TERMINATE, sensitive);
52  gtk_dialog_set_response_sensitive(GTK_DIALOG(gpdata->manager_dialog), REMMINA_NX_EVENT_RESTORE, sensitive);
53  }
54 }
55 
56 static gboolean remmina_nx_session_manager_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path,
57  gboolean path_currently_selected, gpointer user_data)
58 {
59  TRACE_CALL(__func__);
61  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
62 
63  gpdata->manager_selected = FALSE;
64  if (path_currently_selected) {
66  return TRUE;
67  }
68 
69  if (!gtk_tree_model_get_iter(model, &gpdata->iter, path))
70  return TRUE;
71  gpdata->manager_selected = TRUE;
73  return TRUE;
74 }
75 
76 static void remmina_nx_session_manager_send_signal(RemminaPluginNxData *gpdata, gint event_type)
77 {
78  TRACE_CALL(__func__);
79  guchar dummy = (guchar)event_type;
80  /* Signal the NX thread to resume execution */
81  if (write(gpdata->event_pipe[1], &dummy, 1)) {
82  }
83 }
84 
85 static void remmina_nx_session_manager_on_response(GtkWidget *dialog, gint response_id, RemminaProtocolWidget *gp)
86 {
87  TRACE_CALL(__func__);
88  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
89  gint event_type;
90 
92  if (response_id <= 0) {
93  event_type = REMMINA_NX_EVENT_CANCEL;
94  }else {
95  event_type = response_id;
96  }
97  if (response_id == REMMINA_NX_EVENT_TERMINATE && gpdata->manager_selected) {
98  remmina_nx_session_iter_set(gpdata->nx, &gpdata->iter, REMMINA_NX_SESSION_COLUMN_STATUS, _("Terminating…"));
99  }
100  if (response_id != REMMINA_NX_EVENT_TERMINATE) {
101  gtk_widget_destroy(dialog);
102  gpdata->manager_dialog = NULL;
103  }
104  if (response_id != REMMINA_NX_EVENT_TERMINATE && response_id != REMMINA_NX_EVENT_CANCEL) {
106  }
107  remmina_nx_session_manager_send_signal(gpdata, event_type);
108 }
109 
110 /* Handle double click on a row in the NX Session manager
111  * Automatically close the dialog using the default response ID */
112 void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, RemminaProtocolWidget *gp)
113 {
114  TRACE_CALL(__func__);
115  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
116  remmina_plugin_nx_service->debug("Default response_id %d",
117  gpdata->default_response);
118 
119  if (gpdata->default_response >= 0) {
120  gtk_dialog_response(GTK_DIALOG(gpdata->manager_dialog), gpdata->default_response);
121  }
122 }
123 
125 {
126  TRACE_CALL(__func__);
127  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
128  RemminaFile *remminafile;
129  GtkWidget *dialog;
130  gchar *s;
131  GtkWidget *scrolledwindow;
132  GtkWidget *tree;
133  GtkCellRenderer *renderer;
134  GtkTreeViewColumn *column;
135 
137 
138  gpdata->default_response = -1;
139  if (!gpdata->manager_started) {
141 
142  dialog = gtk_dialog_new();
143  s = g_strdup_printf(_("NX sessions on %s"), remmina_plugin_nx_service->file_get_string(remminafile, "server"));
144  gtk_window_set_title(GTK_WINDOW(dialog), s);
145  g_free(s);
146  if (gpdata->attach_session) {
147  gtk_dialog_add_button(GTK_DIALOG(dialog), _("Attach"), REMMINA_NX_EVENT_ATTACH);
148  /* Set default response id for attach */
150  }else {
151  gtk_dialog_add_button(GTK_DIALOG(dialog), _("Restore"), REMMINA_NX_EVENT_RESTORE);
152  gtk_dialog_add_button(GTK_DIALOG(dialog), _("Start"), REMMINA_NX_EVENT_START);
153  /* Set default response id for restore */
155  }
156  gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Cancel"), REMMINA_NX_EVENT_CANCEL);
157 
158  gtk_dialog_add_button(GTK_DIALOG(dialog), _("Terminate"), REMMINA_NX_EVENT_TERMINATE);
159 
160  gtk_window_set_default_size(GTK_WINDOW(dialog), 640, 300);
161  gpdata->manager_dialog = dialog;
162 
163  scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
164  gtk_widget_show(scrolledwindow);
165  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
166  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), scrolledwindow, TRUE, TRUE, 0);
167 
168  tree = gtk_tree_view_new();
169  gtk_container_add(GTK_CONTAINER(scrolledwindow), tree);
170  gtk_widget_show(tree);
171  remmina_nx_session_set_tree_view(gpdata->nx, GTK_TREE_VIEW(tree));
172  /* Handle double click on the row */
173  g_signal_connect(G_OBJECT(tree), "row-activated",
175 
176  renderer = gtk_cell_renderer_text_new();
177  column = gtk_tree_view_column_new_with_attributes("#", renderer, "text", REMMINA_NX_SESSION_COLUMN_ID, NULL);
178  gtk_tree_view_column_set_resizable(column, TRUE);
179  gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_ID);
180  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
181 
182  renderer = gtk_cell_renderer_text_new();
183  column = gtk_tree_view_column_new_with_attributes(_("Type"), renderer, "text", REMMINA_NX_SESSION_COLUMN_TYPE,
184  NULL);
185  gtk_tree_view_column_set_resizable(column, TRUE);
186  gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_TYPE);
187  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
188 
189  renderer = gtk_cell_renderer_text_new();
190  column = gtk_tree_view_column_new_with_attributes(_("Display"), renderer, "text",
192  gtk_tree_view_column_set_resizable(column, TRUE);
193  gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_DISPLAY);
194  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
195 
196  renderer = gtk_cell_renderer_text_new();
197  column = gtk_tree_view_column_new_with_attributes(_("Status"), renderer, "text",
199  gtk_tree_view_column_set_resizable(column, TRUE);
200  gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_STATUS);
201  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
202 
203  renderer = gtk_cell_renderer_text_new();
204  column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", REMMINA_NX_SESSION_COLUMN_NAME,
205  NULL);
206  gtk_tree_view_column_set_resizable(column, TRUE);
207  gtk_tree_view_column_set_sort_column_id(column, REMMINA_NX_SESSION_COLUMN_NAME);
208  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
209 
210  gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)),
212 
213  g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(remmina_nx_session_manager_on_response), gp);
214  gpdata->manager_started = TRUE;
215  }
216  gpdata->manager_selected = FALSE;
217  if (gpdata->manager_dialog) {
219  gtk_widget_show(gpdata->manager_dialog);
220  }
221  if (remmina_nx_session_has_error(gpdata->nx)) {
222  dialog = gtk_message_dialog_new((gpdata->manager_dialog ? GTK_WINDOW(gpdata->manager_dialog) : NULL),
223  GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s",
226  gtk_dialog_run(GTK_DIALOG(dialog));
227  gtk_widget_destroy(dialog);
229  }
230 
231  gpdata->session_manager_start_handler = 0;
232  return FALSE;
233 }
234 
236 {
237  TRACE_CALL(__func__);
238  RemminaPluginNxData *gpdata = GET_PLUGIN_DATA(gp);
239 
240  if (gpdata->session_manager_start_handler == 0) {
241  gpdata->session_manager_start_handler = IDLE_ADD((GSourceFunc)remmina_nx_session_manager_main, gp);
242  }
243 }
244 
RemminaNXSession * nx
Definition: nx_plugin.h:59
void(* debug)(const gchar *fmt,...)
Definition: plugin.h:214
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:41
static gboolean remmina_nx_session_manager_main(RemminaProtocolWidget *gp)
gboolean manager_started
Definition: nx_plugin.h:66
void remmina_nx_session_manager_on_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, RemminaProtocolWidget *gp)
const gchar * remmina_nx_session_get_error(RemminaNXSession *nx)
Definition: nx_session.c:223
void remmina_nx_session_manager_start(RemminaProtocolWidget *gp)
GtkWidget * manager_dialog
Definition: nx_plugin.h:67
gboolean remmina_nx_session_has_error(RemminaNXSession *nx)
Definition: nx_session.c:216
gboolean attach_session
Definition: nx_plugin.h:73
static void remmina_nx_session_manager_send_signal(RemminaPluginNxData *gpdata, gint event_type)
GtkTreeIter iter
Definition: nx_plugin.h:74
gboolean manager_selected
Definition: nx_plugin.h:68
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
Definition: plugin.h:160
void(* protocol_plugin_init_show)(RemminaProtocolWidget *gp)
Definition: plugin.h:187
void(* protocol_plugin_init_hide)(RemminaProtocolWidget *gp)
Definition: plugin.h:188
static void remmina_nx_session_manager_set_sensitive(RemminaProtocolWidget *gp, gboolean sensitive)
guint session_manager_start_handler
Definition: nx_plugin.h:72
void remmina_nx_session_iter_set(RemminaNXSession *nx, GtkTreeIter *iter, gint column, const gchar *data)
Definition: nx_session.c:715
void remmina_nx_session_clear_error(RemminaNXSession *nx)
Definition: nx_session.c:229
void remmina_nx_session_set_tree_view(RemminaNXSession *nx, GtkTreeView *tree)
Definition: nx_session.c:683
RemminaPluginService * remmina_plugin_nx_service
Definition: nx_plugin.c:56
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
Definition: plugin.h:200
static void remmina_nx_session_manager_on_response(GtkWidget *dialog, gint response_id, RemminaProtocolWidget *gp)
static gboolean remmina_nx_session_manager_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer user_data)