38 #include <vncdisplay.h> 40 #include <vncaudiopulse.h> 42 #define GVNC_DEFAULT_PORT 5900 44 #ifndef VNC_CHECK_VERSION 45 # define VNC_CHECK_VERSION(a, b, c) 0 47 #if VNC_CHECK_VERSION(1, 2, 0) 48 # define HAVE_VNC_REMOTE_RESIZE 49 # define HAVE_VNC_POWER_CONTROL 70 #ifdef HAVE_VNC_POWER_CONTROL 81 gchar*
str_replace(
const gchar *
string,
const gchar *search,
const gchar *replacement)
86 g_return_val_if_fail(
string != NULL, NULL);
87 g_return_val_if_fail(search != NULL, NULL);
89 if (replacement == NULL)
92 arr = g_strsplit(
string, search, -1);
93 if (arr != NULL && arr[0] != NULL)
94 str = g_strjoinv(replacement, arr);
96 str = g_strdup(
string);
105 TRACE_CALL(__func__);
109 vnc_display_send_keys(VNC_DISPLAY(gpdata->
vnc),
115 #ifdef HAVE_VNC_POWER_CONTROL 119 VncConnection *conn = vnc_display_get_connection(VNC_DISPLAY(gpdata->
vnc));
121 if (!vnc_connection_get_power_control(conn)) {
122 REMMINA_PLUGIN_DEBUG(
"Power control not available on this server");
125 vnc_connection_power_control(conn, action);
132 TRACE_CALL(__func__);
134 VncGrabSequence *seq = vnc_display_get_grab_keys(VNC_DISPLAY(gpdata->
vnc));
135 gchar *seqstr = vnc_grab_sequence_as_string(seq);
137 REMMINA_PLUGIN_DEBUG(
"Pointer grabbed: %s", seqstr);
142 TRACE_CALL(__func__);
143 REMMINA_PLUGIN_DEBUG(
"Pointer ungrabbed");
148 TRACE_CALL(__func__);
151 REMMINA_PLUGIN_DEBUG(
"Error: %s\n", msg);
163 const VncPixelFormat *currentFormat;
170 currentFormat = vnc_connection_get_pixel_format(gpdata->
conn);
173 GdkPixbuf *pix = vnc_display_get_pixbuf(VNC_DISPLAY(gpdata->
vnc));
175 rpsd->
width = gdk_pixbuf_get_width(pix);
176 rpsd->
height = gdk_pixbuf_get_height(pix);
197 TRACE_CALL(__func__);
201 GError *error = NULL;
205 out = g_convert_with_fallback(text, -1,
"iso8859-1//TRANSLIT",
"utf-8", NULL, &a, &b, &error);
207 REMMINA_PLUGIN_DEBUG(
"Pasting text");
208 vnc_display_client_cut_text(VNC_DISPLAY(gpdata->
vnc), out);
211 REMMINA_PLUGIN_DEBUG(
"Error pasting text: %s", error->message);
218 TRACE_CALL(__func__);
222 REMMINA_PLUGIN_DEBUG(
"owner-change event received");
224 if (cb && gtk_clipboard_get_owner(cb) == (GObject *)gp)
227 text = gtk_clipboard_wait_for_text(cb);
239 TRACE_CALL(__func__);
243 gtk_selection_data_set_text(data, gpdata->
clipstr, -1);
244 REMMINA_PLUGIN_DEBUG(
"Text copied");
249 TRACE_CALL(__func__);
252 REMMINA_PLUGIN_DEBUG(
"Got clipboard request for ā%sā", text);
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 },
266 gpdata->
clipstr = g_convert(text, -1,
"utf-8",
"iso8859-1", &a, &b, NULL);
269 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
271 REMMINA_PLUGIN_DEBUG(
"setting clipboard with owner to owner %p", gp);
272 gtk_clipboard_set_with_owner(cb,
274 G_N_ELEMENTS(targets),
286 TRACE_CALL(__func__);
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);
299 TRACE_CALL(__func__);
300 REMMINA_PLUGIN_DEBUG(
"Bell message received");
304 if (remmina_plugin_service->
file_get_int(remminafile,
"disableserverbell", FALSE))
306 GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(gp));
309 gdk_window_beep(window);
310 REMMINA_PLUGIN_DEBUG(
"Beep emitted");
314 TRACE_CALL(__func__);
320 g_object_set(gpdata->display,
326 vnc_display_set_scaling(VNC_DISPLAY(gpdata->
vnc), TRUE);
328 vnc_display_set_scaling(VNC_DISPLAY(gpdata->
vnc), FALSE);
332 gpdata->
width = vnc_display_get_width(VNC_DISPLAY(gpdata->
vnc));
333 gpdata->
height = vnc_display_get_height(VNC_DISPLAY(gpdata->
vnc));
337 gtk_widget_set_size_request(GTK_WIDGET(gpdata->
vnc), -1, -1);
341 g_object_get(gpdata->display_channel,
345 gtk_widget_set_size_request(GTK_WIDGET(gpdata->
vnc), width, height);
347 gtk_widget_set_size_request(GTK_WIDGET(gpdata->
vnc), gpdata->
width, gpdata->
height);
354 TRACE_CALL(__func__);
361 TRACE_CALL(__func__);
368 switch (feature->
id) {
377 keys[0] = GDK_KEY_Control_L;
378 keys[1] = GDK_KEY_Alt_L;
379 keys[2] = GDK_KEY_Delete;
383 keys[0] = GDK_KEY_Control_L;
384 keys[1] = GDK_KEY_Alt_L;
385 keys[2] = GDK_KEY_BackSpace;
389 keys[0] = GDK_KEY_Control_L;
390 keys[1] = GDK_KEY_Alt_L;
391 keys[2] = GDK_KEY_F1;
395 keys[0] = GDK_KEY_Control_L;
396 keys[1] = GDK_KEY_Alt_L;
397 keys[2] = GDK_KEY_F2;
401 keys[0] = GDK_KEY_Control_L;
402 keys[1] = GDK_KEY_Alt_L;
403 keys[2] = GDK_KEY_F3;
407 keys[0] = GDK_KEY_Control_L;
408 keys[1] = GDK_KEY_Alt_L;
409 keys[2] = GDK_KEY_F4;
413 keys[0] = GDK_KEY_Control_L;
414 keys[1] = GDK_KEY_Alt_L;
415 keys[2] = GDK_KEY_F5;
419 keys[0] = GDK_KEY_Control_L;
420 keys[1] = GDK_KEY_Alt_L;
421 keys[2] = GDK_KEY_F6;
425 keys[0] = GDK_KEY_Control_L;
426 keys[1] = GDK_KEY_Alt_L;
427 keys[2] = GDK_KEY_F7;
431 keys[0] = GDK_KEY_Control_L;
432 keys[1] = GDK_KEY_Alt_L;
433 keys[2] = GDK_KEY_F9;
437 keys[0] = GDK_KEY_Control_L;
438 keys[1] = GDK_KEY_Alt_L;
439 keys[2] = GDK_KEY_F10;
443 keys[0] = GDK_KEY_Control_L;
444 keys[1] = GDK_KEY_Alt_L;
445 keys[2] = GDK_KEY_F11;
449 keys[0] = GDK_KEY_Control_L;
450 keys[1] = GDK_KEY_Alt_L;
451 keys[2] = GDK_KEY_F12;
454 #ifdef HAVE_VNC_POWER_CONTROL 472 TRACE_CALL(__func__);
475 g_clear_pointer(&gpdata->
error_msg, g_free);
476 gchar *msg = g_strdup_printf(_(
"Unsupported authentication type %u"), authType);
484 TRACE_CALL(__func__);
487 g_clear_pointer(&gpdata->
error_msg, g_free);
488 gchar *msg = g_strdup_printf(_(
"Authentication failure: %s"), reason);
496 TRACE_CALL(__func__);
499 gboolean disablepasswordstoring;
500 gchar *s_username = NULL, *s_password = NULL;
501 gboolean wantPassword = FALSE, wantUsername = FALSE;
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);
514 REMMINA_PLUGIN_DEBUG(
"Got credential request for %d credential(s)\n", credArray->len);
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:
522 case VNC_DISPLAY_CREDENTIAL_PASSWORD:
525 case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
528 REMMINA_PLUGIN_DEBUG(
"Unsupported credential type %d", g_value_get_enum(cred));
529 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
533 disablepasswordstoring = remmina_plugin_service->
file_get_int(remminafile,
"disablepasswordstoring", FALSE);
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),
543 if (ret == GTK_RESPONSE_OK) {
546 remmina_plugin_service->
file_set_string(remminafile,
"username", s_username);
553 remmina_plugin_service->
file_set_string(remminafile,
"password", s_password);
555 remmina_plugin_service->
file_set_string(remminafile,
"password", NULL);
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:
563 vnc_display_set_credential(VNC_DISPLAY(gpdata->
vnc),
564 g_value_get_enum(cred),
566 g_debug(
"Failed to set credential type %d", g_value_get_enum(cred));
567 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
570 case VNC_DISPLAY_CREDENTIAL_PASSWORD:
572 vnc_display_set_credential(VNC_DISPLAY(gpdata->
vnc),
573 g_value_get_enum(cred),
575 g_debug(
"Failed to set credential type %d", g_value_get_enum(cred));
576 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
579 case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
580 if (vnc_display_set_credential(VNC_DISPLAY(gpdata->
vnc),
581 g_value_get_enum(cred),
583 g_debug(
"Failed to set credential type %d", g_value_get_enum(cred));
584 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
588 g_debug(
"Unsupported credential type %d", g_value_get_enum(cred));
589 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
593 if (s_username) g_free(s_username);
594 if (s_password) g_free(s_password);
611 TRACE_CALL(__func__);
616 REMMINA_PLUGIN_DEBUG(
"Connection initialized");
617 g_return_if_fail(gpdata != NULL);
618 REMMINA_PLUGIN_DEBUG(
"Presenting the window");
620 VncAudioFormat format = {
621 VNC_AUDIO_FORMAT_RAW_S32,
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);
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");
635 REMMINA_PLUGIN_DEBUG(
"VNC audio format returned an error");
639 if (vnc_connection_set_audio(gpdata->
conn, VNC_AUDIO(gpdata->
pa)))
640 REMMINA_PLUGIN_DEBUG(
"VNC audio channel has been set");
642 REMMINA_PLUGIN_DEBUG(
"VNC audio channel cannot be set");
645 REMMINA_PLUGIN_DEBUG(
"Enabling audio");
646 if (vnc_connection_audio_enable(gpdata->
conn))
647 REMMINA_PLUGIN_DEBUG(
"Audio enabled");
649 REMMINA_PLUGIN_DEBUG(
"Audio cannot be enabled");
651 gpdata->
width = vnc_display_get_width(VNC_DISPLAY(gpdata->
vnc));
652 gpdata->
width = vnc_display_get_height(VNC_DISPLAY(gpdata->
vnc));
657 TRACE_CALL(__func__);
660 REMMINA_PLUGIN_DEBUG(
"[%s] Plugin disconnected", PLUGIN_NAME);
664 TRACE_CALL(__func__);
667 REMMINA_PLUGIN_DEBUG(
"[%s] Plugin close connection", PLUGIN_NAME);
672 vnc_display_close(VNC_DISPLAY(gpdata->
vnc));
677 g_object_steal_data(G_OBJECT(gp),
"plugin-data");
684 TRACE_CALL(__func__);
691 g_object_set_data_full(G_OBJECT(gp),
"plugin-data", gpdata, g_free);
695 REMMINA_PLUGIN_DEBUG(
"[%s] Plugin init", PLUGIN_NAME);
699 if (remmina_plugin_service->
file_get_int(remminafile,
"gvncdebug", FALSE))
700 vnc_util_set_debug(TRUE);
702 gpdata->
vnc = vnc_display_new();
703 if (remmina_plugin_service->
file_get_int(remminafile,
"enableaudio", FALSE))
704 gpdata->
pa = vnc_audio_pulse_new();
707 g_signal_connect(gpdata->
vnc,
"vnc-auth-credential",
709 g_signal_connect(gpdata->
vnc,
"vnc-auth-failure",
711 g_signal_connect(gpdata->
vnc,
"vnc-auth-unsupported",
713 g_signal_connect(gpdata->
vnc,
"vnc-disconnected",
715 g_signal_connect(gpdata->
vnc,
"vnc-initialized",
717 g_signal_connect(gpdata->
vnc,
"vnc-desktop-resize",
719 g_signal_connect(gpdata->
vnc,
"vnc-bell",
721 g_signal_connect(gpdata->
vnc,
"vnc-error",
723 g_signal_connect(gpdata->
vnc,
"vnc-pointer-grab",
725 g_signal_connect(gpdata->
vnc,
"vnc-pointer-ungrab",
727 g_signal_connect(gpdata->
vnc,
"vnc-server-cut-text",
734 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
743 TRACE_CALL(__func__);
746 gchar *host = NULL, *tunnel = NULL;
750 REMMINA_PLUGIN_DEBUG(
"[%s] Plugin open connection", PLUGIN_NAME);
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);
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);
765 REMMINA_PLUGIN_DEBUG(
"address after cleaning = %s", val);
767 REMMINA_PLUGIN_DEBUG(
"Unix socket fd: %d", fd);
788 vnc_display_open_fd(VNC_DISPLAY(gpdata->
vnc), gpdata->
fd);
790 vnc_display_open_host(VNC_DISPLAY(gpdata->
vnc), host, g_strdup_printf(
"%d", port));
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);
795 if(host) g_free(host);
796 if(tunnel) g_free(tunnel);
799 vnc_display_set_keyboard_grab(VNC_DISPLAY(gpdata->
vnc), FALSE);
800 vnc_display_set_read_only(VNC_DISPLAY(gpdata->
vnc), gpdata->
viewonly);
802 vnc_display_set_pointer_grab(VNC_DISPLAY(gpdata->
vnc), FALSE);
803 vnc_display_set_pointer_local(VNC_DISPLAY(gpdata->
vnc), TRUE);
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);
812 gtk_widget_show_all(gpdata->
box);
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)"),
894 #ifdef HAVE_VNC_POWER_CONTROL 931 TRACE_CALL(__func__);
932 remmina_plugin_service = service;
934 bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR);
935 bind_textdomain_codeset(GETTEXT_PACKAGE,
"UTF-8");
static void gvnc_plugin_clipboard_cb(GtkClipboard *cb, GdkEvent *event, RemminaProtocolWidget *gp)
RemminaScaleMode(* remmina_protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp)
gint(* open_unix_sock)(const char *unixsock)
static gboolean gvnc_plugin_ask_auth(GtkWidget *vncdisplay, GValueArray *credList, RemminaProtocolWidget *gp)
void(* protocol_plugin_set_error)(RemminaProtocolWidget *gp, const gchar *fmt,...)
static void gvnc_plugin_update_scale_mode(RemminaProtocolWidget *gp)
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
gchar * str_replace(const gchar *string, const gchar *search, const gchar *replacement)
static gboolean gvnc_plugin_get_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd) __attribute__((unused))
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
static void gvnc_plugin_cut_text(VncDisplay *vnc G_GNUC_UNUSED, const gchar *text, RemminaProtocolWidget *gp)
static const RemminaProtocolSetting gvnc_plugin_basic_settings[]
static gpointer colordepth_list[]
void(* protocol_plugin_signal_connection_closed)(RemminaProtocolWidget *gp)
static gboolean gvnc_plugin_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
void(* get_server_port)(const gchar *server, gint defaultport, gchar **host, gint *port)
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
static void gvnc_plugin_desktop_resize(GtkWidget *vncdisplay G_GNUC_UNUSED, int width, int height, RemminaProtocolWidget *gp)
void(* protocol_plugin_update_align)(RemminaProtocolWidget *gp)
void(* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp)
static void gvnc_plugin_disconnected(VncDisplay *vnc G_GNUC_UNUSED, RemminaProtocolWidget *gp)
static RemminaPluginService * remmina_plugin_service
gboolean(* protocol_plugin_init_get_savepassword)(RemminaProtocolWidget *gp)
G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
gboolean(* register_plugin)(RemminaPlugin *plugin)
static void gvnc_plugin_clipboard_copy(GtkClipboard *clipboard G_GNUC_UNUSED, GtkSelectionData *data, guint info G_GNUC_UNUSED, RemminaProtocolWidget *gp)
static void gvnc_plugin_mouse_ungrab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
static void gvnc_plugin_on_bell(RemminaProtocolWidget *gp)
static void gvnc_plugin_initialized(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
static void gvnc_plugin_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
static gboolean gvnc_plugin_close_connection(RemminaProtocolWidget *gp)
static void gvnc_plugin_auth_failure(VncDisplay *vnc G_GNUC_UNUSED, const gchar *reason, RemminaProtocolWidget *gp)
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)
static gboolean gvnc_plugin_open_connection(RemminaProtocolWidget *gp)
static RemminaProtocolPlugin remmina_plugin
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
void(* protocol_plugin_desktop_resize)(RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_init_get_username)(RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_init_get_password)(RemminaProtocolWidget *gp)
static void gvnc_plugin_mouse_grab(GtkWidget *vncdisplay, RemminaProtocolWidget *gp)
void(* protocol_plugin_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget)
static void gvnc_plugin_power_ctrl(RemminaProtocolWidget *gp, VncConnectionPowerAction action)
void(* file_set_string)(RemminaFile *remminafile, const gchar *setting, const gchar *value)
void(* protocol_plugin_set_height)(RemminaProtocolWidget *gp, gint height)
static void gvnc_plugin_init(RemminaProtocolWidget *gp)
void gvnc_plugin_paste_text(RemminaProtocolWidget *gp, const gchar *text)
static void gvnc_plugin_on_vnc_error(GtkWidget *vncdisplay G_GNUC_UNUSED, const gchar *msg, RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus)
static void gvnc_plugin_auth_unsupported(VncDisplay *vnc G_GNUC_UNUSED, unsigned int authType, RemminaProtocolWidget *gp)
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
static const RemminaProtocolFeature gvnc_plugin_features[]
N_("Unable to connect to VNC server")
static void gvnc_plugin_keystroke(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen)
static const RemminaProtocolSetting gvnc_plugin_advanced_settings[]