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.
gvnc_plugin.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of portions of this program with the
22  * OpenSSL library under certain conditions as described in each
23  * individual source file, and distribute linked combinations
24  * including the two.
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL. * If you modify
27  * file(s) with this exception, you may extend this exception to your
28  * version of the file(s), but you are not obligated to do so. * If you
29  * do not wish to do so, delete this exception statement from your
30  * version. * If you delete this exception statement from all source
31  * files in the program, then also delete it here.
32  *
33  */
34 
35 #include "gvnc_plugin_config.h"
36 #include "gvnc_plugin.h"
37 
38 #include <vncdisplay.h>
39 #include <vncutil.h>
40 #include <vncaudiopulse.h>
41 
42 #define GVNC_DEFAULT_PORT 5900
43 
44 #ifndef VNC_CHECK_VERSION
45 # define VNC_CHECK_VERSION(a, b, c) 0
46 #endif
47 #if VNC_CHECK_VERSION(1, 2, 0)
48 # define HAVE_VNC_REMOTE_RESIZE
49 # define HAVE_VNC_POWER_CONTROL
50 #endif
51 
52 enum {
70 #ifdef HAVE_VNC_POWER_CONTROL
74 #endif
76 };
77 
78 
80 
81 gchar* str_replace(const gchar *string, const gchar *search, const gchar *replacement)
82 {
83  TRACE_CALL(__func__);
84  gchar *str, **arr;
85 
86  g_return_val_if_fail(string != NULL, NULL);
87  g_return_val_if_fail(search != NULL, NULL);
88 
89  if (replacement == NULL)
90  replacement = "";
91 
92  arr = g_strsplit(string, search, -1);
93  if (arr != NULL && arr[0] != NULL)
94  str = g_strjoinv(replacement, arr);
95  else
96  str = g_strdup(string);
97 
98  g_strfreev(arr);
99  return str;
100 }
101 
102 /* Send a keystroke to the plugin window */
103 static void gvnc_plugin_keystroke(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen)
104 {
105  TRACE_CALL(__func__);
106  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
107 
108  if (gpdata->vnc) {
109  vnc_display_send_keys(VNC_DISPLAY(gpdata->vnc),
110  keystrokes,
111  keylen);
112  }
113 }
114 
115 #ifdef HAVE_VNC_POWER_CONTROL
116 static void gvnc_plugin_power_ctrl(RemminaProtocolWidget *gp, VncConnectionPowerAction action)
117 {
118  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
119  VncConnection *conn = vnc_display_get_connection(VNC_DISPLAY(gpdata->vnc));
120 
121  if (!vnc_connection_get_power_control(conn)) {
122  REMMINA_PLUGIN_DEBUG("Power control not available on this server");
123  return;
124  }
125  vnc_connection_power_control(conn, action);
126 }
127 #endif
128 
129 
130 static void gvnc_plugin_mouse_grab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
131 {
132  TRACE_CALL(__func__);
133  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
134  VncGrabSequence *seq = vnc_display_get_grab_keys(VNC_DISPLAY(gpdata->vnc));
135  gchar *seqstr = vnc_grab_sequence_as_string(seq);
136 
137  REMMINA_PLUGIN_DEBUG("Pointer grabbed: %s", seqstr);
138 }
139 
140 static void gvnc_plugin_mouse_ungrab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
141 {
142  TRACE_CALL(__func__);
143  REMMINA_PLUGIN_DEBUG("Pointer ungrabbed");
144 }
145 
146 static void gvnc_plugin_on_vnc_error(GtkWidget *vncdisplay G_GNUC_UNUSED, const gchar *msg, RemminaProtocolWidget *gp)
147 {
148  TRACE_CALL(__func__);
149  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
150 
151  REMMINA_PLUGIN_DEBUG("Error: %s\n", msg);
152  /* "vnc-error" is always followed by "vnc-disconnected",
153  * so save the error for that signal */
154  g_free(gpdata->error_msg);
155  gpdata->error_msg = g_strdup(msg);
156 }
157 
158 static gboolean gvnc_plugin_get_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd) __attribute__ ((unused));
160 {
161  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
162  //gsize szmem;
163  const VncPixelFormat *currentFormat;
164  //GError *err = NULL;
165 
166  if (!gpdata)
167  return FALSE;
168 
169  /* Get current pixel format for server */
170  currentFormat = vnc_connection_get_pixel_format(gpdata->conn);
171 
172 
173  GdkPixbuf *pix = vnc_display_get_pixbuf(VNC_DISPLAY(gpdata->vnc));
174 
175  rpsd->width = gdk_pixbuf_get_width(pix);
176  rpsd->height = gdk_pixbuf_get_height(pix);
177  rpsd->bitsPerPixel = currentFormat->bits_per_pixel;
178  rpsd->bytesPerPixel = rpsd->bitsPerPixel / 8;
179  //szmem = gdk_pixbuf_get_byte_length(pix);
180 
181  //szmem = rpsd->width * rpsd->height * rpsd->bytesPerPixel;
182 
183  //REMMINA_PLUGIN_DEBUG("allocating %zu bytes for a full screenshot", szmem);
184  //REMMINA_PLUGIN_DEBUG("Calculated screenshot size: %zu", szcalc);
185  //rpsd->buffer = malloc(szmem);
186 
187  //memcpy(rpsd->buffer, pix, szmem);
188  //gdk_pixbuf_save_to_buffer(pix, &rpsd->buffer, &szmem, "jpeg", &err, "quality", "100", NULL);
189 
190 
191  /* Returning TRUE instruct also the caller to deallocate rpsd->buffer */
192  return TRUE;
193 }
194 
195 void gvnc_plugin_paste_text(RemminaProtocolWidget *gp, const gchar *text)
196 {
197  TRACE_CALL(__func__);
198  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
199  gchar *out;
200  gsize a, b;
201  GError *error = NULL;
202 
203  if (!gpdata) return;
204 
205  out = g_convert_with_fallback(text, -1, "iso8859-1//TRANSLIT", "utf-8", NULL, &a, &b, &error);
206  if (out) {
207  REMMINA_PLUGIN_DEBUG("Pasting text");
208  vnc_display_client_cut_text(VNC_DISPLAY(gpdata->vnc), out);
209  g_free(out);
210  } else {
211  REMMINA_PLUGIN_DEBUG("Error pasting text: %s", error->message);
212  g_error_free(error);
213  }
214 }
215 
216 static void gvnc_plugin_clipboard_cb(GtkClipboard *cb, GdkEvent *event, RemminaProtocolWidget *gp)
217 {
218  TRACE_CALL(__func__);
219  //GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
220  gchar *text;
221 
222  REMMINA_PLUGIN_DEBUG("owner-change event received");
223 
224  if (cb && gtk_clipboard_get_owner(cb) == (GObject *)gp)
225  return;
226 
227  text = gtk_clipboard_wait_for_text(cb);
228  if (!text)
229  return;
230 
231  gvnc_plugin_paste_text(gp, text);
232  g_free(text);
233 }
234 
235 
236 /* text was actually requested */
237 static void gvnc_plugin_clipboard_copy(GtkClipboard *clipboard G_GNUC_UNUSED, GtkSelectionData *data, guint info G_GNUC_UNUSED, RemminaProtocolWidget *gp)
238 {
239  TRACE_CALL(__func__);
240  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
241 
242  if (!gpdata) return;
243  gtk_selection_data_set_text(data, gpdata->clipstr, -1);
244  REMMINA_PLUGIN_DEBUG("Text copied");
245 }
246 
247 static void gvnc_plugin_cut_text(VncDisplay *vnc G_GNUC_UNUSED, const gchar *text, RemminaProtocolWidget *gp)
248 {
249  TRACE_CALL(__func__);
250  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
251 
252  REMMINA_PLUGIN_DEBUG("Got clipboard request for ā€œ%sā€", text);
253 
254  GtkClipboard *cb;
255  gsize a, b;
256  GtkTargetEntry targets[] = {
257  { g_strdup("UTF8_STRING"), 0, 0 },
258  { g_strdup("COMPOUND_TEXT"), 0, 0 },
259  { g_strdup("TEXT"), 0, 0 },
260  { g_strdup("STRING"), 0, 0 },
261  };
262 
263  if (!text)
264  return;
265  g_free(gpdata->clipstr);
266  gpdata->clipstr = g_convert(text, -1, "utf-8", "iso8859-1", &a, &b, NULL);
267 
268  if (gpdata->clipstr) {
269  cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
270 
271  REMMINA_PLUGIN_DEBUG("setting clipboard with owner to owner %p", gp);
272  gtk_clipboard_set_with_owner(cb,
273  targets,
274  G_N_ELEMENTS(targets),
275  (GtkClipboardGetFunc)gvnc_plugin_clipboard_copy,
276  NULL,
277  G_OBJECT(gp));
278  }
279 
280  //g_signal_emit_by_name(session, "session-cut-text", text);
281 }
282 
283 
284 static void gvnc_plugin_desktop_resize(GtkWidget *vncdisplay G_GNUC_UNUSED, int width, int height, RemminaProtocolWidget *gp)
285 {
286  TRACE_CALL(__func__);
287  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
288 
289  REMMINA_PLUGIN_DEBUG("Remote desktop size changed to %dx%d\n", width, height);
290  REMMINA_PLUGIN_DEBUG("Desktop size is set to %dx%d\n", gpdata->width, gpdata->height);
291  remmina_plugin_service->protocol_plugin_set_width(gp, width);
292  remmina_plugin_service->protocol_plugin_set_height(gp, height);
293 
294  remmina_plugin_service->protocol_plugin_desktop_resize(gp);
295 }
296 
298 {
299  TRACE_CALL(__func__);
300  REMMINA_PLUGIN_DEBUG("Bell message received");
301  //GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
302  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
303 
304  if (remmina_plugin_service->file_get_int(remminafile, "disableserverbell", FALSE))
305  return;
306  GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(gp));
307 
308  if (window)
309  gdk_window_beep(window);
310  REMMINA_PLUGIN_DEBUG("Beep emitted");
311 }
313 {
314  TRACE_CALL(__func__);
315 
316  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
317  RemminaScaleMode scaleMode = remmina_plugin_service->remmina_protocol_widget_get_current_scale_mode(gp);
318 
319 #if 0
320  g_object_set(gpdata->display,
321  "scaling", (scaleMode == REMMINA_PROTOCOL_WIDGET_SCALE_MODE_SCALED),
322  "resize-guest", (scaleMode == REMMINA_PROTOCOL_WIDGET_SCALE_MODE_DYNRES),
323  NULL);
324 #endif
326  vnc_display_set_scaling(VNC_DISPLAY(gpdata->vnc), TRUE);
327  else
328  vnc_display_set_scaling(VNC_DISPLAY(gpdata->vnc), FALSE);
329 
330  //width = remmina_plugin_service->protocol_plugin_get_width(gp);
331  //height = remmina_plugin_service->protocol_plugin_get_height(gp);
332  gpdata->width = vnc_display_get_width(VNC_DISPLAY(gpdata->vnc));
333  gpdata->height = vnc_display_get_height(VNC_DISPLAY(gpdata->vnc));
334 
335  if (scaleMode != REMMINA_PROTOCOL_WIDGET_SCALE_MODE_NONE) {
336  /* In scaled mode, the VncDisplay will get its dimensions from its parent */
337  gtk_widget_set_size_request(GTK_WIDGET(gpdata->vnc), -1, -1);
338  } else {
339  /* In non scaled mode, the plugins forces dimensions of the VncDisplay */
340 #if 0
341  g_object_get(gpdata->display_channel,
342  "width", &width,
343  "height", &height,
344  NULL);
345  gtk_widget_set_size_request(GTK_WIDGET(gpdata->vnc), width, height);
346 #endif
347  gtk_widget_set_size_request(GTK_WIDGET(gpdata->vnc), gpdata->width, gpdata->height);
348  }
349  remmina_plugin_service->protocol_plugin_update_align(gp);
350 }
351 
353 {
354  TRACE_CALL(__func__);
355 
356  return TRUE;
357 }
358 
360 {
361  TRACE_CALL(__func__);
362 
363  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
364  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
365 
366  guint keys[3];
367 
368  switch (feature->id) {
370  gpdata->viewonly = remmina_plugin_service->file_get_int(remminafile, "viewonly", FALSE);
371  break;
375  break;
377  keys[0] = GDK_KEY_Control_L;
378  keys[1] = GDK_KEY_Alt_L;
379  keys[2] = GDK_KEY_Delete;
380  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
381  break;
383  keys[0] = GDK_KEY_Control_L;
384  keys[1] = GDK_KEY_Alt_L;
385  keys[2] = GDK_KEY_BackSpace;
386  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
387  break;
389  keys[0] = GDK_KEY_Control_L;
390  keys[1] = GDK_KEY_Alt_L;
391  keys[2] = GDK_KEY_F1;
392  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
393  break;
395  keys[0] = GDK_KEY_Control_L;
396  keys[1] = GDK_KEY_Alt_L;
397  keys[2] = GDK_KEY_F2;
398  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
399  break;
401  keys[0] = GDK_KEY_Control_L;
402  keys[1] = GDK_KEY_Alt_L;
403  keys[2] = GDK_KEY_F3;
404  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
405  break;
407  keys[0] = GDK_KEY_Control_L;
408  keys[1] = GDK_KEY_Alt_L;
409  keys[2] = GDK_KEY_F4;
410  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
411  break;
413  keys[0] = GDK_KEY_Control_L;
414  keys[1] = GDK_KEY_Alt_L;
415  keys[2] = GDK_KEY_F5;
416  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
417  break;
419  keys[0] = GDK_KEY_Control_L;
420  keys[1] = GDK_KEY_Alt_L;
421  keys[2] = GDK_KEY_F6;
422  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
423  break;
425  keys[0] = GDK_KEY_Control_L;
426  keys[1] = GDK_KEY_Alt_L;
427  keys[2] = GDK_KEY_F7;
428  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
429  break;
431  keys[0] = GDK_KEY_Control_L;
432  keys[1] = GDK_KEY_Alt_L;
433  keys[2] = GDK_KEY_F9;
434  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
435  break;
437  keys[0] = GDK_KEY_Control_L;
438  keys[1] = GDK_KEY_Alt_L;
439  keys[2] = GDK_KEY_F10;
440  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
441  break;
443  keys[0] = GDK_KEY_Control_L;
444  keys[1] = GDK_KEY_Alt_L;
445  keys[2] = GDK_KEY_F11;
446  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
447  break;
449  keys[0] = GDK_KEY_Control_L;
450  keys[1] = GDK_KEY_Alt_L;
451  keys[2] = GDK_KEY_F12;
452  gvnc_plugin_keystroke(gp, keys, G_N_ELEMENTS(keys));
453  break;
454 #ifdef HAVE_VNC_POWER_CONTROL
456  gvnc_plugin_power_ctrl(gp, VNC_CONNECTION_POWER_ACTION_REBOOT);
457  break;
459  gvnc_plugin_power_ctrl(gp, VNC_CONNECTION_POWER_ACTION_RESET);
460  break;
462  gvnc_plugin_power_ctrl(gp, VNC_CONNECTION_POWER_ACTION_SHUTDOWN);
463  break;
464 #endif
465  default:
466  break;
467  }
468 }
469 
470 static void gvnc_plugin_auth_unsupported(VncDisplay *vnc G_GNUC_UNUSED, unsigned int authType, RemminaProtocolWidget *gp)
471 {
472  TRACE_CALL(__func__);
473  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
474 
475  g_clear_pointer(&gpdata->error_msg, g_free);
476  gchar *msg = g_strdup_printf(_("Unsupported authentication type %u"), authType);
477 
478  remmina_plugin_service->protocol_plugin_set_error(gp, "%s", msg);
479  g_free(msg);
480 }
481 
482 static void gvnc_plugin_auth_failure(VncDisplay *vnc G_GNUC_UNUSED, const gchar *reason, RemminaProtocolWidget *gp)
483 {
484  TRACE_CALL(__func__);
485  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
486 
487  g_clear_pointer(&gpdata->error_msg, g_free);
488  gchar *msg = g_strdup_printf(_("Authentication failure: %s"), reason);
489 
490  remmina_plugin_service->protocol_plugin_set_error(gp, "%s", msg);
491  g_free(msg);
492 }
493 
494 static gboolean gvnc_plugin_ask_auth(GtkWidget *vncdisplay, GValueArray *credList, RemminaProtocolWidget *gp)
495 {
496  TRACE_CALL(__func__);
497 
498  gint ret;
499  gboolean disablepasswordstoring;
500  gchar *s_username = NULL, *s_password = NULL;
501  gboolean wantPassword = FALSE, wantUsername = FALSE;
502  int i;
503  gboolean save;
504 
505 
506  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
507  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
508 
509 
510  GArray *credArray = g_array_sized_new(FALSE, TRUE, sizeof(GValue), credList->n_values);
511  g_array_set_clear_func(credArray, (GDestroyNotify) g_value_unset);
512  g_array_append_vals(credArray, credList->values, credList->n_values);
513 
514  REMMINA_PLUGIN_DEBUG("Got credential request for %d credential(s)\n", credArray->len);
515 
516  for (i = 0 ; i < credArray->len ; i++) {
517  GValue *cred = &g_array_index(credArray, GValue, i);
518  switch (g_value_get_enum(cred)) {
519  case VNC_DISPLAY_CREDENTIAL_USERNAME:
520  wantUsername = TRUE;
521  break;
522  case VNC_DISPLAY_CREDENTIAL_PASSWORD:
523  wantPassword = TRUE;
524  break;
525  case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
526  break;
527  default:
528  REMMINA_PLUGIN_DEBUG("Unsupported credential type %d", g_value_get_enum(cred));
529  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
530  goto cleanup;
531  }
532  }
533  disablepasswordstoring = remmina_plugin_service->file_get_int(remminafile, "disablepasswordstoring", FALSE);
534 
535  ret = remmina_plugin_service->protocol_plugin_init_auth(gp,
536  (disablepasswordstoring ? 0 : REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD)
537  | (wantUsername ? REMMINA_MESSAGE_PANEL_FLAG_USERNAME : 0),
538  _("Enter VNC authentication credentials"),
539  (wantUsername ? remmina_plugin_service->file_get_string(remminafile, "username") : NULL),
540  (wantPassword ? remmina_plugin_service->file_get_string(remminafile, "password") : NULL),
541  NULL,
542  NULL);
543  if (ret == GTK_RESPONSE_OK) {
544  s_username = remmina_plugin_service->protocol_plugin_init_get_username(gp);
545  s_password = remmina_plugin_service->protocol_plugin_init_get_password(gp);
546  remmina_plugin_service->file_set_string(remminafile, "username", s_username);
547 
548  save = remmina_plugin_service->protocol_plugin_init_get_savepassword(gp);
549  if (save) {
550  // User has requested to save credentials. We put the password
551  // into remminafile->settings. It will be saved later, on successful connection, by
552  // rcw.c
553  remmina_plugin_service->file_set_string(remminafile, "password", s_password);
554  } else {
555  remmina_plugin_service->file_set_string(remminafile, "password", NULL);
556  }
557 
558  for (i = 0 ; i < credArray->len ; i++) {
559  GValue *cred = &g_array_index(credArray, GValue, i);
560  switch (g_value_get_enum(cred)) {
561  case VNC_DISPLAY_CREDENTIAL_USERNAME:
562  if (!s_username ||
563  vnc_display_set_credential(VNC_DISPLAY(gpdata->vnc),
564  g_value_get_enum(cred),
565  s_username)) {
566  g_debug("Failed to set credential type %d", g_value_get_enum(cred));
567  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
568  }
569  break;
570  case VNC_DISPLAY_CREDENTIAL_PASSWORD:
571  if (!s_password ||
572  vnc_display_set_credential(VNC_DISPLAY(gpdata->vnc),
573  g_value_get_enum(cred),
574  s_password)) {
575  g_debug("Failed to set credential type %d", g_value_get_enum(cred));
576  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
577  }
578  break;
579  case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
580  if (vnc_display_set_credential(VNC_DISPLAY(gpdata->vnc),
581  g_value_get_enum(cred),
582  "remmina")) {
583  g_debug("Failed to set credential type %d", g_value_get_enum(cred));
584  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
585  }
586  break;
587  default:
588  g_debug("Unsupported credential type %d", g_value_get_enum(cred));
589  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
590  }
591  }
592 
593  if (s_username) g_free(s_username);
594  if (s_password) g_free(s_password);
595 
596  return TRUE;
597  } else {
598  return FALSE;
599  }
600 
601 cleanup:
602  g_free(s_username);
603  g_free(s_password);
604 
605  //g_object_set(gpdata->session, "password", s_password, NULL);
606  return TRUE;
607 }
608 
609 static void gvnc_plugin_initialized(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
610 {
611  TRACE_CALL(__func__);
612 
613  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
614  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
615 
616  REMMINA_PLUGIN_DEBUG("Connection initialized");
617  g_return_if_fail(gpdata != NULL);
618  REMMINA_PLUGIN_DEBUG("Presenting the window");
619 
620  VncAudioFormat format = {
621  VNC_AUDIO_FORMAT_RAW_S32,
622  2,
623  44100,
624  };
625 
626  REMMINA_PLUGIN_DEBUG("Gathering the VNC connection object");
627  gpdata->conn = vnc_display_get_connection(VNC_DISPLAY(gpdata->vnc));
628  g_return_if_fail(gpdata->conn != NULL);
629 
630  if (remmina_plugin_service->file_get_int(remminafile, "enableaudio", FALSE)) {
631  REMMINA_PLUGIN_DEBUG("Setting up VNC audio channel");
632  if (vnc_connection_set_audio_format(gpdata->conn, &format))
633  REMMINA_PLUGIN_DEBUG("VNC audio format set");
634  else {
635  REMMINA_PLUGIN_DEBUG("VNC audio format returned an error");
636  return;
637  }
638 
639  if (vnc_connection_set_audio(gpdata->conn, VNC_AUDIO(gpdata->pa)))
640  REMMINA_PLUGIN_DEBUG("VNC audio channel has been set");
641  else {
642  REMMINA_PLUGIN_DEBUG("VNC audio channel cannot be set");
643  return;
644  }
645  REMMINA_PLUGIN_DEBUG("Enabling audio");
646  if (vnc_connection_audio_enable(gpdata->conn))
647  REMMINA_PLUGIN_DEBUG("Audio enabled");
648  else
649  REMMINA_PLUGIN_DEBUG("Audio cannot be enabled");
650  }
651  gpdata->width = vnc_display_get_width(VNC_DISPLAY(gpdata->vnc));
652  gpdata->width = vnc_display_get_height(VNC_DISPLAY(gpdata->vnc));
653 }
654 
655 static void gvnc_plugin_disconnected(VncDisplay *vnc G_GNUC_UNUSED, RemminaProtocolWidget *gp)
656 {
657  TRACE_CALL(__func__);
658  //GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
659 
660  REMMINA_PLUGIN_DEBUG("[%s] Plugin disconnected", PLUGIN_NAME);
661 }
663 {
664  TRACE_CALL(__func__);
665  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
666 
667  REMMINA_PLUGIN_DEBUG("[%s] Plugin close connection", PLUGIN_NAME);
668 
669  if (gpdata) {
670  if (gpdata->error_msg) g_free(gpdata->error_msg);
671  if (gpdata->vnc)
672  vnc_display_close(VNC_DISPLAY(gpdata->vnc));
673  //g_object_unref(gpdata->vnc);
674  }
675 
676  /* Remove instance->context from gp object data to avoid double free */
677  g_object_steal_data(G_OBJECT(gp), "plugin-data");
678  remmina_plugin_service->protocol_plugin_signal_connection_closed(gp);
679  return FALSE;
680 }
681 
683 {
684  TRACE_CALL(__func__);
685  GVncPluginData *gpdata;
686  //VncGrabSequence *seq;
687 
688  GtkClipboard *cb;
689 
690  gpdata = g_new0(GVncPluginData, 1);
691  g_object_set_data_full(G_OBJECT(gp), "plugin-data", gpdata, g_free);
692 
693  gpdata->pa = NULL;
694 
695  REMMINA_PLUGIN_DEBUG("[%s] Plugin init", PLUGIN_NAME);
696 
697  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
698 
699  if (remmina_plugin_service->file_get_int(remminafile, "gvncdebug", FALSE))
700  vnc_util_set_debug(TRUE);
701 
702  gpdata->vnc = vnc_display_new();
703  if (remmina_plugin_service->file_get_int(remminafile, "enableaudio", FALSE))
704  gpdata->pa = vnc_audio_pulse_new();
705 
706 
707  g_signal_connect(gpdata->vnc, "vnc-auth-credential",
708  G_CALLBACK(gvnc_plugin_ask_auth), gp);
709  g_signal_connect(gpdata->vnc, "vnc-auth-failure",
710  G_CALLBACK(gvnc_plugin_auth_failure), gp);
711  g_signal_connect(gpdata->vnc, "vnc-auth-unsupported",
712  G_CALLBACK(gvnc_plugin_auth_unsupported), gp);
713  g_signal_connect(gpdata->vnc, "vnc-disconnected",
714  G_CALLBACK(gvnc_plugin_disconnected), gp);
715  g_signal_connect(gpdata->vnc, "vnc-initialized",
716  G_CALLBACK(gvnc_plugin_initialized), gp);
717  g_signal_connect(gpdata->vnc, "vnc-desktop-resize",
718  G_CALLBACK(gvnc_plugin_desktop_resize), gp);
719  g_signal_connect(gpdata->vnc, "vnc-bell",
720  G_CALLBACK(gvnc_plugin_on_bell), gp);
721  g_signal_connect(gpdata->vnc, "vnc-error",
722  G_CALLBACK(gvnc_plugin_on_vnc_error), gp);
723  g_signal_connect(gpdata->vnc, "vnc-pointer-grab",
724  G_CALLBACK(gvnc_plugin_mouse_grab), gp);
725  g_signal_connect(gpdata->vnc, "vnc-pointer-ungrab",
726  G_CALLBACK(gvnc_plugin_mouse_ungrab), gp);
727  g_signal_connect(gpdata->vnc, "vnc-server-cut-text",
728  G_CALLBACK(gvnc_plugin_cut_text), gp);
729  //seq = vnc_grab_sequence_new_from_string ("Control_R");
730  //vnc_display_set_grab_keys(VNC_DISPLAY(gpdata->vnc), seq);
731  //vnc_grab_sequence_free(seq);
732 
733  /* Setup the clipboard */
734  cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
735  gpdata->signal_clipboard = g_signal_connect(cb,
736  "owner-change",
737  G_CALLBACK(gvnc_plugin_clipboard_cb),
738  gp);
739 }
740 
742 {
743  TRACE_CALL(__func__);
744 
745  gint port;
746  gchar *host = NULL, *tunnel = NULL;
747  GVncPluginData *gpdata = GET_PLUGIN_DATA(gp);
748  RemminaFile *remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
749 
750  REMMINA_PLUGIN_DEBUG("[%s] Plugin open connection", PLUGIN_NAME);
751 
752  gpdata->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
753  gtk_container_add(GTK_CONTAINER(gp), gpdata->box);
754  gtk_widget_set_hexpand(GTK_WIDGET(gpdata->vnc), TRUE);
755  gtk_widget_set_vexpand(GTK_WIDGET(gpdata->vnc), TRUE);
756  gtk_container_add(GTK_CONTAINER(gpdata->box), gpdata->vnc);
757 
758  remmina_plugin_service->protocol_plugin_register_hostkey(gp, gpdata->vnc);
759 
760 
761  const gchar *address = remmina_plugin_service->file_get_string(remminafile, "server");
762  if(strstr(g_strdup(address), "unix:///") != NULL) {
763  REMMINA_PLUGIN_DEBUG("address contain unix:// -> %s", address);
764  gchar *val = str_replace (address, "unix://", "");
765  REMMINA_PLUGIN_DEBUG("address after cleaning = %s", val);
766  gint fd = remmina_plugin_service->open_unix_sock(val);
767  REMMINA_PLUGIN_DEBUG("Unix socket fd: %d", fd);
768  gpdata->fd = fd;
769  g_free(val);
770 
771  } else {
772  /* Setup SSH tunnel if needed */
773  tunnel = remmina_plugin_service->protocol_plugin_start_direct_tunnel(gp, GVNC_DEFAULT_PORT, FALSE);
774  if (!tunnel)
775  return FALSE;
776  remmina_plugin_service->get_server_port(tunnel,
777  GVNC_DEFAULT_PORT,
778  &host,
779  &port);
780  }
781 
782 
783 
784  gpdata->depth_profile = remmina_plugin_service->file_get_int(remminafile, "depth_profile", 24);
785  gpdata->viewonly = remmina_plugin_service->file_get_int(remminafile, "viewonly", FALSE);
786  vnc_display_set_depth(VNC_DISPLAY(gpdata->vnc), gpdata->depth_profile);
787  if (gpdata->fd > 0)
788  vnc_display_open_fd(VNC_DISPLAY(gpdata->vnc), gpdata->fd);
789  else
790  vnc_display_open_host(VNC_DISPLAY(gpdata->vnc), host, g_strdup_printf("%d", port));
791  gpdata->lossy_encoding = remmina_plugin_service->file_get_int(remminafile, "lossy_encoding", FALSE);
792  vnc_display_set_lossy_encoding(VNC_DISPLAY(gpdata->vnc), gpdata->lossy_encoding);
793  vnc_display_set_shared_flag(VNC_DISPLAY(gpdata->vnc), gpdata->shared);
794 
795  if(host) g_free(host);
796  if(tunnel) g_free(tunnel);
797 
798  /* TRUE Conflict with remmina? */
799  vnc_display_set_keyboard_grab(VNC_DISPLAY(gpdata->vnc), FALSE);
800  vnc_display_set_read_only(VNC_DISPLAY(gpdata->vnc), gpdata->viewonly);
801  /* TRUE Conflict with remmina? */
802  vnc_display_set_pointer_grab(VNC_DISPLAY(gpdata->vnc), FALSE);
803  vnc_display_set_pointer_local(VNC_DISPLAY(gpdata->vnc), TRUE);
804 
805  vnc_display_set_force_size(VNC_DISPLAY(gpdata->vnc), FALSE);
806  vnc_display_set_scaling(VNC_DISPLAY(gpdata->vnc), TRUE);
807 #ifdef HAVE_VNC_REMOTE_RESIZE
808  vnc_display_set_allow_resize(VNC_DISPLAY(gpdata->vnc), TRUE);
809  vnc_display_set_zoom_level(VNC_DISPLAY(gpdata->vnc), opt_zoom);
810 #endif
811  remmina_plugin_service->protocol_plugin_signal_connection_opened(gp);
812  gtk_widget_show_all(gpdata->box);
813  return TRUE;
814 }
815 
816 /* Array of key/value pairs for color depths */
817 static gpointer colordepth_list[] =
818 {
819  "0", N_("Use server settings"),
820  "1", N_("True colour (24 bits)"),
821  "2", N_("High colour (16 bits)"),
822  "3", N_("Low colour (8 bits)"),
823  "4", N_("Ultra low colour (3 bits)"),
824  NULL
825 };
826 
827 /* Array of RemminaProtocolSetting for basic settings.
828  * Each item is composed by:
829  * a) RemminaProtocolSettingType for setting type
830  * b) Setting name
831  * c) Setting description
832  * d) Compact disposition
833  * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO
834  * f) Setting tooltip
835  * g) Validation data pointer, will be passed to the validation callback method.
836  * h) Validation callback method (Can be NULL. Every entry will be valid then.)
837  * use following prototype:
838  * gboolean mysetting_validator_method(gpointer key, gpointer value,
839  * gpointer validator_data);
840  * gpointer key is a gchar* containing the setting's name,
841  * gpointer value contains the value which should be validated,
842  * gpointer validator_data contains your passed data.
843  */
845 {
846  { REMMINA_PROTOCOL_SETTING_TYPE_SERVER, "server", NULL, FALSE, NULL, NULL, NULL, NULL },
847  { REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD, "password", N_("VNC password"), FALSE, NULL, NULL, NULL, NULL },
848  { REMMINA_PROTOCOL_SETTING_TYPE_SELECT, "depth_profile", N_("Colour depth"), FALSE, colordepth_list, NULL, NULL, NULL },
849  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "lossy_encoding", N_("Use JPEG Compression"), TRUE, NULL, N_("This might not work on all VNC servers"), NULL, NULL },
850  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "gvncdebug", N_("Enable GTK-VNC debug"), FALSE, NULL, NULL, NULL, NULL },
851  { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, FALSE, NULL, NULL, NULL, NULL }
852 };
853 
854 /* Array of RemminaProtocolSetting for advanced settings.
855  * Each item is composed by:
856  * a) RemminaProtocolSettingType for setting type
857  * b) Setting name
858  * c) Setting description
859  * d) Compact disposition
860  * e) Values for REMMINA_PROTOCOL_SETTING_TYPE_SELECT or REMMINA_PROTOCOL_SETTING_TYPE_COMBO
861  * f) Setting Tooltip
862  */
864 {
865  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableclipboard", N_("No clipboard sync"), TRUE, NULL, NULL },
866  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disablepasswordstoring", N_("Forget passwords after use"), FALSE, NULL, NULL },
867  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "disableserverbell", N_("Ignore remote bell messages"), TRUE, NULL, NULL },
868  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "enableaudio", N_("Enable audio channel"), FALSE, NULL, NULL },
869  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "viewonly", N_("View only"), TRUE, NULL, NULL },
870  { REMMINA_PROTOCOL_SETTING_TYPE_CHECK, "shared", N_("Shared connection"), TRUE, NULL, N_("If the server should try to share the desktop by leaving other clients connected") },
871  { REMMINA_PROTOCOL_SETTING_TYPE_END, NULL, NULL, TRUE, NULL, NULL }
872 };
873 
874 /* Array for available features.
875  * The last element of the array must be REMMINA_PROTOCOL_FEATURE_TYPE_END. */
877 {
878  { REMMINA_PROTOCOL_FEATURE_TYPE_PREF, GVNC_PLUGIN_FEATURE_PREF_VIEWONLY, GINT_TO_POINTER(REMMINA_PROTOCOL_FEATURE_PREF_CHECK), "viewonly", N_("View only") },
879  { REMMINA_PROTOCOL_FEATURE_TYPE_PREF, GVNC_PLUGIN_FEATURE_PREF_DISABLECLIPBOARD, GINT_TO_POINTER(REMMINA_PROTOCOL_FEATURE_PREF_CHECK), "disableclipboard", N_("No clipboard sync") },
880  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SENDCTRLALTDEL, N_("Send Ctrl+Alt+_Del"), NULL, NULL },
881  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SENDCTRLALTBACKSPACE, N_("Send Ctrl+Alt+_Backspace"), NULL, NULL },
891  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SENDCTRLALTF10, N_("Send Ctrl+Alt+_F10"), NULL, NULL },
892  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SENDCTRLALTF11, N_("Send Ctrl+Alt+_F11"), NULL, NULL },
893  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SENDCTRLALTF12, N_("Send Ctrl+Alt+_F12"), NULL, NULL },
894 #ifdef HAVE_VNC_POWER_CONTROL
895  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_REBOOT, N_("Reboot remote host"), NULL, NULL },
896  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_RESET, N_("Reset remote host (hard reboot)"), NULL, NULL },
897  { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, GVNC_PLUGIN_FEATURE_TOOL_SHUTDOWN, N_("Shutdown remote host"), NULL, NULL },
898 #endif
901  { REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL }
902 };
903 
904 /* Protocol plugin definition and features */
907  PLUGIN_NAME, // Name
908  PLUGIN_DESCRIPTION, // Description
909  GETTEXT_PACKAGE, // Translation domain
910  PLUGIN_VERSION, // Version number
911  PLUGIN_APPICON, // Icon for normal connection
912  PLUGIN_APPICON, // Icon for SSH connection
913  gvnc_plugin_basic_settings, // Array for basic settings
914  gvnc_plugin_advanced_settings, // Array for advanced settings
915  REMMINA_PROTOCOL_SSH_SETTING_TUNNEL, // SSH settings type
916  gvnc_plugin_features, // Array for available features
917  gvnc_plugin_init, // Plugin initialization
918  gvnc_plugin_open_connection, // Plugin open connection
919  gvnc_plugin_close_connection, // Plugin close connection
920  gvnc_plugin_query_feature, // Query for available features
921  gvnc_plugin_call_feature, // Call a feature
922  gvnc_plugin_keystroke, // Send a keystroke
923  NULL, // No screenshot support available
924  //gvnc_plugin_get_screenshot, // No screenshot support available
925  NULL, // RCW map event
926  NULL // RCW unmap event
927 };
928 
929 G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
930 {
931  TRACE_CALL(__func__);
932  remmina_plugin_service = service;
933 
934  bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR);
935  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
936 
937  if (!service->register_plugin((RemminaPlugin *)&remmina_plugin))
938  return FALSE;
939 
940  return TRUE;
941 }
static void gvnc_plugin_clipboard_cb(GtkClipboard *cb, GdkEvent *event, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:216
RemminaScaleMode(* remmina_protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp)
Definition: plugin.h:172
gint(* open_unix_sock)(const char *unixsock)
Definition: plugin.h:248
static gboolean gvnc_plugin_ask_auth(GtkWidget *vncdisplay, GValueArray *credList, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:494
void(* protocol_plugin_set_error)(RemminaProtocolWidget *gp, const gchar *fmt,...)
Definition: plugin.h:176
static void gvnc_plugin_update_scale_mode(RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:312
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44
gchar * str_replace(const gchar *string, const gchar *search, const gchar *replacement)
Definition: gvnc_plugin.c:81
gchar * error_msg
Definition: gvnc_plugin.h:117
static gboolean gvnc_plugin_get_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd) __attribute__((unused))
Definition: gvnc_plugin.c:159
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
Definition: plugin.h:169
static void gvnc_plugin_cut_text(VncDisplay *vnc G_GNUC_UNUSED, const gchar *text, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:247
VncAudioPulse * pa
Definition: gvnc_plugin.h:116
static const RemminaProtocolSetting gvnc_plugin_basic_settings[]
Definition: gvnc_plugin.c:844
static gpointer colordepth_list[]
Definition: gvnc_plugin.c:817
void(* protocol_plugin_signal_connection_closed)(RemminaProtocolWidget *gp)
Definition: plugin.h:185
static gboolean gvnc_plugin_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
Definition: gvnc_plugin.c:352
void(* get_server_port)(const gchar *server, gint defaultport, gchar **host, gint *port)
Definition: plugin.h:249
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: plugin.h:222
static void gvnc_plugin_desktop_resize(GtkWidget *vncdisplay G_GNUC_UNUSED, int width, int height, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:284
void(* protocol_plugin_update_align)(RemminaProtocolWidget *gp)
Definition: plugin.h:187
void(* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp)
Definition: plugin.h:186
static void gvnc_plugin_disconnected(VncDisplay *vnc G_GNUC_UNUSED, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:655
gboolean viewonly
Definition: gvnc_plugin.h:123
VncConnection * conn
Definition: gvnc_plugin.h:115
static RemminaPluginService * remmina_plugin_service
Definition: gvnc_plugin.c:79
gulong signal_clipboard
Definition: gvnc_plugin.h:119
gboolean(* protocol_plugin_init_get_savepassword)(RemminaProtocolWidget *gp)
Definition: plugin.h:197
G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
Definition: gvnc_plugin.c:929
gboolean(* register_plugin)(RemminaPlugin *plugin)
Definition: plugin.h:166
static void gvnc_plugin_clipboard_copy(GtkClipboard *clipboard G_GNUC_UNUSED, GtkSelectionData *data, guint info G_GNUC_UNUSED, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:237
static void gvnc_plugin_mouse_ungrab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:140
static void gvnc_plugin_on_bell(RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:297
static void gvnc_plugin_initialized(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:609
static void gvnc_plugin_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
Definition: gvnc_plugin.c:359
static gboolean gvnc_plugin_close_connection(RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:662
gboolean lossy_encoding
Definition: gvnc_plugin.h:122
static void gvnc_plugin_auth_failure(VncDisplay *vnc G_GNUC_UNUSED, const gchar *reason, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:482
gint(* protocol_plugin_init_auth)(RemminaProtocolWidget *gp, RemminaMessagePanelFlags pflags, const gchar *title, const gchar *default_username, const gchar *default_password, const gchar *default_domain, const gchar *password_prompt)
Definition: plugin.h:191
static gboolean gvnc_plugin_open_connection(RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:741
static RemminaProtocolPlugin remmina_plugin
Definition: gvnc_plugin.c:905
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
Definition: plugin.h:178
void(* protocol_plugin_desktop_resize)(RemminaProtocolWidget *gp)
Definition: plugin.h:190
GtkWidget * vnc
Definition: gvnc_plugin.h:114
RemminaScaleMode
Definition: types.h:142
gchar *(* protocol_plugin_init_get_username)(RemminaProtocolWidget *gp)
Definition: plugin.h:194
gchar *(* protocol_plugin_init_get_password)(RemminaProtocolWidget *gp)
Definition: plugin.h:195
static void gvnc_plugin_mouse_grab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:130
void(* protocol_plugin_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget)
Definition: plugin.h:180
static void gvnc_plugin_power_ctrl(RemminaProtocolWidget *gp, VncConnectionPowerAction action)
Definition: gvnc_plugin.c:116
void(* file_set_string)(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: plugin.h:218
void(* protocol_plugin_set_height)(RemminaProtocolWidget *gp, gint height)
Definition: plugin.h:171
static void gvnc_plugin_init(RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:682
void gvnc_plugin_paste_text(RemminaProtocolWidget *gp, const gchar *text)
Definition: gvnc_plugin.c:195
static void gvnc_plugin_on_vnc_error(GtkWidget *vncdisplay G_GNUC_UNUSED, const gchar *msg, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:146
gchar *(* protocol_plugin_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus)
Definition: plugin.h:181
static void gvnc_plugin_auth_unsupported(VncDisplay *vnc G_GNUC_UNUSED, unsigned int authType, RemminaProtocolWidget *gp)
Definition: gvnc_plugin.c:470
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
Definition: plugin.h:219
static const RemminaProtocolFeature gvnc_plugin_features[]
Definition: gvnc_plugin.c:876
N_("Unable to connect to VNC server")
Definition: vnc_plugin.c:953
GtkWidget * box
Definition: gvnc_plugin.h:113
static void gvnc_plugin_keystroke(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen)
Definition: gvnc_plugin.c:103
static const RemminaProtocolSetting gvnc_plugin_advanced_settings[]
Definition: gvnc_plugin.c:863