40 #include <rfb/rfbclient.h>
42 #define REMMINA_PLUGIN_VNC_FEATURE_PREF_QUALITY 1
43 #define REMMINA_PLUGIN_VNC_FEATURE_PREF_VIEWONLY 2
44 #define REMMINA_PLUGIN_VNC_FEATURE_PREF_DISABLESERVERINPUT 3
45 #define REMMINA_PLUGIN_VNC_FEATURE_TOOL_REFRESH 4
46 #define REMMINA_PLUGIN_VNC_FEATURE_TOOL_CHAT 5
47 #define REMMINA_PLUGIN_VNC_FEATURE_SCALE 6
48 #define REMMINA_PLUGIN_VNC_FEATURE_UNFOCUS 7
49 #define REMMINA_PLUGIN_VNC_FEATURE_TOOL_SENDCTRLALTDEL 8
50 #define REMMINA_PLUGIN_VNC_FEATURE_PREF_COLOR 9
51 #define REMMINA_PLUGIN_VNC_FEATURE_DYNRESUPDATE 10
53 #define VNC_DEFAULT_PORT 5900
55 #define GET_PLUGIN_DATA(gp) (RemminaPluginVncData *)g_object_get_data(G_OBJECT(gp), "plugin-data")
62 {
"5 5 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
" ... ",
".+++.",
".+ +.",
".+++.",
" ... " };
65 #define LOCK_BUFFER(t) if (t) { CANCEL_DEFER } pthread_mutex_lock(&gpdata->buffer_mutex);
66 #define UNLOCK_BUFFER(t) pthread_mutex_unlock(&gpdata->buffer_mutex); if (t) { CANCEL_ASYNC }
86 case FUNC_UPDATE_SCALE:
90 pthread_mutex_unlock(&d->
mu);
95 return G_SOURCE_REMOVE;
101 TRACE_CALL(__func__);
110 TRACE_CALL(__func__);
113 pthread_mutex_init(&d->
mu, NULL);
114 pthread_mutex_lock(&d->
mu);
117 pthread_mutex_lock(&d->
mu);
119 pthread_cleanup_pop(0);
120 pthread_mutex_unlock(&d->
mu);
121 pthread_mutex_destroy(&d->
mu);
131 char *c = (
char *)&
x;
138 TRACE_CALL(__func__);
143 event->event_type = event_type;
144 switch (event_type) {
146 event->event_data.key.keyval = GPOINTER_TO_UINT(p1);
147 event->event_data.key.pressed = GPOINTER_TO_INT(p2);
150 event->event_data.pointer.x = GPOINTER_TO_INT(p1);
151 event->event_data.pointer.y = GPOINTER_TO_INT(p2);
152 event->event_data.pointer.button_mask = GPOINTER_TO_INT(p3);
156 event->event_data.text.text = g_strdup((
char *)p1);
173 TRACE_CALL(__func__);
187 TRACE_CALL(__func__);
199 TRACE_CALL(__func__);
201 GtkAllocation widget_allocation;
211 gtk_widget_get_allocation(GTK_WIDGET(
gp), &widget_allocation);
213 if (widget_allocation.width ==
width && widget_allocation.height ==
height)
217 sx = MIN(MAX(0, (*
x) * widget_allocation.width /
width - widget_allocation.width /
width - 2), widget_allocation.width - 1);
218 sy = MIN(MAX(0, (*
y) * widget_allocation.height /
height - widget_allocation.height /
height - 2), widget_allocation.height - 1);
219 sw = MIN(widget_allocation.width - sx, (*
w) * widget_allocation.width /
width + widget_allocation.width /
width + 4);
220 sh = MIN(widget_allocation.height - sy, (*h) * widget_allocation.height /
height + widget_allocation.height /
height + 4);
230 TRACE_CALL(__func__);
247 gpdata = GET_PLUGIN_DATA(
gp);
253 gtk_widget_set_size_request(GTK_WIDGET(gpdata->
drawing_area), -1, -1);
263 TRACE_CALL(__func__);
273 gdk_window_set_cursor(gtk_widget_get_window(gpdata->
drawing_area), cur);
278 gdk_window_set_cursor(gtk_widget_get_window(gpdata->
drawing_area), NULL);
280 UNLOCK_BUFFER(FALSE);
287 TRACE_CALL(__func__);
307 { rfbNoAuth, rfbVncAuth, rfbMSLogon, 0 };
326 TRACE_CALL(__func__);
332 cl = (rfbClient *)gpdata->
client;
345 rfbClientLog(
"sending clipboard text '%s'\n", event->
event_data.
text.text);
360 rfbClientLog(
"Ignoring VNC event: 0x%x\n", event->
event_type);
379 TRACE_CALL(__func__);
392 cl->appData.useBGR233 = 0;
393 cl->appData.encodingsString =
"copyrect zlib hextile raw";
394 cl->appData.compressLevel = 1;
395 cl->appData.qualityLevel = 9;
398 cl->appData.useBGR233 = 0;
399 cl->appData.encodingsString =
"tight zrle ultra copyrect hextile zlib corre rre raw";
400 cl->appData.compressLevel = 2;
401 cl->appData.qualityLevel = 7;
404 cl->appData.useBGR233 = 0;
405 cl->appData.encodingsString =
"tight zrle ultra copyrect hextile zlib corre rre raw";
406 cl->appData.compressLevel = 3;
407 cl->appData.qualityLevel = 5;
412 cl->appData.useBGR233 = 1;
413 cl->appData.encodingsString =
"copyrect zrle ultra zlib hextile corre rre raw";
414 cl->appData.qualityLevel = 1;
420 cl->appData.encodingsString = g_strdup(enc);
421 g_free (enc), enc = NULL;
425 if (!g_strrstr ( g_strdup(cl->appData.encodingsString),
"tight\0")) {
426 cl->appData.encodingsString = g_strdup_printf(
"%s %s",
"tight", g_strdup(cl->appData.encodingsString));
430 REMMINA_PLUGIN_DEBUG(
"Quality: %d", quality);
431 REMMINA_PLUGIN_DEBUG(
"Encodings: %s", cl->appData.encodingsString);
436 TRACE_CALL(__func__);
438 cl->format.depth = colordepth;
439 cl->appData.requestedDepth = colordepth;
441 cl->format.trueColour = 1;
444 switch (colordepth) {
446 cl->format.depth = 8;
447 cl->format.bitsPerPixel = 8;
448 cl->format.blueMax = 3;
449 cl->format.blueShift = 6;
450 cl->format.greenMax = 7;
451 cl->format.greenShift = 3;
452 cl->format.redMax = 7;
453 cl->format.redShift = 0;
456 cl->format.depth = 15;
457 cl->format.bitsPerPixel = 16;
458 cl->format.redShift = 11;
459 cl->format.greenShift = 6;
460 cl->format.blueShift = 1;
461 cl->format.redMax = 31;
462 cl->format.greenMax = 31;
463 cl->format.blueMax = 31;
467 cl->format.depth = 24;
468 cl->format.bitsPerPixel = 32;
469 cl->format.blueShift = 0;
470 cl->format.redShift = 16;
471 cl->format.greenShift = 8;
472 cl->format.blueMax = 0xff;
473 cl->format.redMax = 0xff;
474 cl->format.greenMax = 0xff;
478 rfbClientLog(
"colordepth = %d\n", colordepth);
479 rfbClientLog(
"format.depth = %d\n", cl->format.depth);
480 rfbClientLog(
"format.bitsPerPixel = %d\n", cl->format.bitsPerPixel);
481 rfbClientLog(
"format.blueShift = %d\n", cl->format.blueShift);
482 rfbClientLog(
"format.redShift = %d\n", cl->format.redShift);
483 rfbClientLog(
"format.trueColour = %d\n", cl->format.trueColour);
484 rfbClientLog(
"format.greenShift = %d\n", cl->format.greenShift);
485 rfbClientLog(
"format.blueMax = %d\n", cl->format.blueMax);
486 rfbClientLog(
"format.redMax = %d\n", cl->format.redMax);
487 rfbClientLog(
"format.greenMax = %d\n", cl->format.greenMax);
488 rfbClientLog(
"format.bigEndian = %d\n", cl->format.bigEndian);
493 TRACE_CALL(__func__);
496 gint width, height, depth, size;
498 cairo_surface_t *new_surface, *old_surface;
502 depth = cl->format.bitsPerPixel;
503 size = width * height * (depth / 8);
505 new_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
506 if (cairo_surface_status(new_surface) != CAIRO_STATUS_SUCCESS)
519 gpdata->
vnc_buffer = (guchar *)g_malloc(size);
525 cairo_surface_destroy(old_surface);
534 cl->updateRect.w = width;
535 cl->updateRect.h = height;
542 TRACE_CALL(__func__);
554 TRACE_CALL(__func__);
558 if (GTK_IS_WIDGET(gp) && gpdata->
connected) {
565 UNLOCK_BUFFER(FALSE);
567 gtk_widget_queue_draw_area(GTK_WIDGET(gp), x, y, w, h);
574 TRACE_CALL(__func__);
576 gint nx2, ny2, ox2, oy2;
599 gint src_rowstride, guchar *mask, gint w, gint h)
601 TRACE_CALL(__func__);
608 gint rs, gs, bs, rm, gm, bm, rl, gl, bl, rr, gr, br;
619 bytesPerPixel = cl->format.bitsPerPixel / 8;
620 switch (cl->format.bitsPerPixel) {
623 for (iy = 0; iy < h; iy++) {
624 destptr = (guint32 *)(dest + iy * dest_rowstride);
625 srcptr = src + iy * src_rowstride;
626 for (ix = 0; ix < w; ix++) {
627 if (!mask || *mask++) {
628 dst_pixel.colors.a = 0xff;
629 dst_pixel.colors.r = *(srcptr + 2);
630 dst_pixel.colors.g = *(srcptr + 1);
631 dst_pixel.colors.b = *srcptr;
632 *destptr++ = ntohl(dst_pixel.argb);
641 rm = cl->format.redMax;
642 gm = cl->format.greenMax;
643 bm = cl->format.blueMax;
650 rs = cl->format.redShift;
651 gs = cl->format.greenShift;
652 bs = cl->format.blueShift;
653 for (iy = 0; iy < h; iy++) {
654 destptr = (guint32 *)(dest + iy * dest_rowstride);
655 srcptr = src + iy * src_rowstride;
656 for (ix = 0; ix < w; ix++) {
658 for (i = 0; i < bytesPerPixel; i++)
659 src_pixel += (*srcptr++) << (8 * i);
661 if (!mask || *mask++) {
662 dst_pixel.colors.a = 0xff;
663 c = (guchar)((src_pixel >> rs) & rm) << rl;
664 for (r = rr; r < 8; r *= 2)
666 dst_pixel.colors.r = c;
667 c = (guchar)((src_pixel >> gs) & gm) << gl;
668 for (r = gr; r < 8; r *= 2)
670 dst_pixel.colors.g = c;
671 c = (guchar)((src_pixel >> bs) & bm) << bl;
672 for (r = br; r < 8; r *= 2)
674 dst_pixel.colors.b = c;
675 *destptr++ = ntohl(dst_pixel.argb);
687 TRACE_CALL(__func__);
696 if (w >= 1 || h >= 1) {
698 bytesPerPixel = cl->format.bitsPerPixel / 8;
699 rowstride = cairo_image_surface_get_stride(gpdata->
rgb_buffer);
702 rowstride, gpdata->
vnc_buffer + ((y * width + x) * bytesPerPixel), width * bytesPerPixel, NULL,
718 TRACE_CALL(__func__);
719 REMMINA_PLUGIN_DEBUG(
"FinishedFrameBufferUpdate");
724 TRACE_CALL(__func__);
725 REMMINA_PLUGIN_DEBUG(
"Led state - value: %d, pad: %d", value, pad);
730 TRACE_CALL(__func__);
735 const char *cur_charset;
739 if (GTK_IS_WIDGET(gp) && gpdata->
connected) {
740 t = g_date_time_new_now_utc();
746 g_get_charset(&cur_charset);
747 text = g_convert_with_fallback(param->
text, param->
textlen, cur_charset,
"ISO-8859-1",
"?", &br, &bw, NULL);
748 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), text, bw);
751 g_date_time_unref(t);
761 TRACE_CALL(__func__);
766 param->
text = g_malloc(textlen);
767 memcpy(param->
text, text, textlen);
775 TRACE_CALL(__func__);
792 _(
"Enter VNC password"),
797 if (ret != GTK_RESPONSE_OK) {
811 static rfbCredential *
814 TRACE_CALL(__func__);
821 gboolean disablepasswordstoring;
826 cred = g_new0(rfbCredential, 1);
828 switch (credentialType) {
829 case rfbCredentialTypeUser:
836 cred->userCredential.username = s1;
837 cred->userCredential.password = s2;
845 _(
"Enter VNC authentication credentials"),
850 if (ret == GTK_RESPONSE_OK) {
869 case rfbCredentialTypeX509:
879 if (ret == GTK_RESPONSE_OK) {
902 TRACE_CALL(__func__);
906 if (!gtk_widget_get_window(GTK_WIDGET(gp)))
909 if (width && height) {
910 gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
911 guchar *data = g_malloc(stride * height);
913 width * cl->format.bitsPerPixel / 8, cl->rcMask, width, height);
914 cairo_surface_t *surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, stride);
915 if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
919 if (cairo_surface_set_user_data(surface, NULL, NULL, g_free) != CAIRO_STATUS_SUCCESS) {
932 TRACE_CALL(__func__);
933 REMMINA_PLUGIN_DEBUG(
"Bell message received");
944 window = gtk_widget_get_window(GTK_WIDGET(gp));
947 gdk_window_beep(window);
948 REMMINA_PLUGIN_DEBUG(
"Beep emitted");
952 #ifdef __DO_NOT_COMPILE_ME__
953 N_(
"Unable to connect to VNC server")
954 N_("Couldn’t convert '%s' to host address")
955 N_("VNC connection failed: %s")
956 N_("Your connection has been rejected.")
959 #define MAX_ERROR_LENGTH 1000
960 static gchar vnc_error[MAX_ERROR_LENGTH + 1];
961 static gboolean vnc_encryption_disable_requested;
963 static void remmina_plugin_vnc_rfb_output(
const char *format, ...)
965 TRACE_CALL(__func__);
968 if (!rfbEnableClientLogging)
972 va_start(args, format);
974 f = g_strdup(format);
975 if (f[strlen(f) - 1] ==
'\n') f[strlen(f) - 1] =
'\0';
977 if (g_strcmp0(f,
"VNC connection failed: %s") == 0) {
978 p = va_arg(args, gchar *);
979 g_snprintf(vnc_error, MAX_ERROR_LENGTH, _(f), _(p));
980 }
else if (g_strcmp0(f,
"The VNC server requested an unknown authentication method. %s") == 0) {
981 p = va_arg(args, gchar *);
982 if (vnc_encryption_disable_requested) {
983 ff = g_strconcat(_(
"The VNC server requested an unknown authentication method. %s"),
985 _(
"Please retry after turning on encryption for this profile."),
987 g_snprintf(vnc_error, MAX_ERROR_LENGTH, ff, p);
990 g_snprintf(vnc_error, MAX_ERROR_LENGTH, _(f), p);
993 g_vsnprintf(vnc_error, MAX_ERROR_LENGTH, _(f), args);
998 REMMINA_PLUGIN_DEBUG(
"VNC returned: %s", vnc_error);
1003 TRACE_CALL(__func__);
1007 ptr = g_strdup_printf(
"%s\n", text);
1014 TRACE_CALL(__func__);
1021 TRACE_CALL(__func__);
1022 guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete };
1026 keys, G_N_ELEMENTS(keys), GDK_KEY_PRESS | GDK_KEY_RELEASE);
1031 TRACE_CALL(__func__);
1038 TRACE_CALL(__func__);
1042 cl = (rfbClient *)gpdata->
client;
1052 TRACE_CALL(__func__);
1057 case rfbTextChatOpen:
1060 case rfbTextChatClose:
1063 case rfbTextChatFinished:
1075 TRACE_CALL(__func__);
1083 gpdata->
listen_sock = ListenAtTcpPort(cl->listenPort);
1095 select(gpdata->
listen_sock + 1, &fds, NULL, NULL, NULL);
1104 cl->sock = AcceptTcpConnection(gpdata->
listen_sock);
1105 if (cl->sock >= 0) {
1109 if (cl->sock < 0 || !SetNonBlocking(cl->sock))
1118 TRACE_CALL(__func__);
1124 struct timeval timeout;
1131 cl = (rfbClient *)gpdata->
client;
1140 goto handle_buffered;
1142 timeout.tv_sec = 10;
1143 timeout.tv_usec = 0;
1145 FD_SET(cl->sock, &fds);
1147 ret = select(MAX(cl->sock, gpdata->
vnc_event_pipe[0]) + 1, &fds, NULL, NULL, &timeout);
1156 if (FD_ISSET(cl->sock, &fds)) {
1157 i = WaitForMessage(cl, 500);
1161 if (!HandleRFBServerMessage(cl)) {
1174 TRACE_CALL(__func__);
1177 rfbClient *cl = NULL;
1184 rfbClientLog = rfbClientErr = remmina_plugin_vnc_rfb_output;
1195 REMMINA_PLUGIN_DEBUG(
"host is null");
1201 switch (colordepth) {
1203 cl = rfbGetClient(2, 3, 1);
1207 cl = rfbGetClient(5, 3, 2);
1210 cl = rfbGetClient(6, 3, 3);
1214 cl = rfbGetClient(8, 3, 4);
1217 REMMINA_PLUGIN_DEBUG(
"Color depth: %d", colordepth);
1219 cl->canHandleNewFBSize = TRUE;
1245 rfbClientSetClientData(cl, NULL, gp);
1247 if (host[0] ==
'\0') {
1248 cl->serverHost = g_strdup(host);
1249 cl->listenSpecified = TRUE;
1254 cl->listenPort = 5500;
1260 if (strstr(host,
"unix://") == host) {
1261 cl->serverHost = g_strdup(host + strlen(
"unix://"));
1265 cl->serverHost = g_strdup(s);
1268 if (cl->serverPort < 100)
1269 cl->serverPort += VNC_DEFAULT_PORT;
1286 REMMINA_PLUGIN_DEBUG(
"cl->serverHost: %s", cl->serverHost);
1287 REMMINA_PLUGIN_DEBUG(
"cl->serverPort: %d", cl->serverPort);
1288 REMMINA_PLUGIN_DEBUG(
"cl->destHost: %s", cl->destHost);
1289 REMMINA_PLUGIN_DEBUG(
"cl->destPort: %d", cl->destPort);
1292 cl->appData.useRemoteCursor = (
1297 if ((cl->format.depth == 8) && (quality == 9))
1298 cl->appData.encodingsString =
"copyrect zlib hextile raw";
1299 else if ((cl->format.depth == 8) && (quality == 2))
1300 cl->appData.encodingsString =
"zrle ultra copyrect hextile zlib corre rre raw";
1301 else if ((cl->format.depth == 8) && (quality == 1))
1302 cl->appData.encodingsString =
"zrle ultra copyrect hextile zlib corre rre raw";
1303 else if ((cl->format.depth == 8) && (quality == 0))
1304 cl->appData.encodingsString =
"zrle ultra copyrect hextile zlib corre rre raw";
1305 SetFormatAndEncodings(cl);
1308 vnc_encryption_disable_requested = TRUE;
1311 vnc_encryption_disable_requested = FALSE;
1314 if (rfbInitClient(cl, NULL, NULL)) {
1315 REMMINA_PLUGIN_DEBUG(
"Client initialization successfull");
1318 REMMINA_PLUGIN_DEBUG(
"Client initialization failed");
1323 REMMINA_PLUGIN_DEBUG(
"Client not authenticated");
1329 if (strstr(vnc_error,
"The server is already in use")) {
1336 if (strstr(vnc_error,
"read (") || strstr(vnc_error,
"select\n") ||
1337 strstr(vnc_error,
"write\n") || strstr(vnc_error,
"Connection timed out")) {
1358 REMMINA_PLUGIN_DEBUG(
"Client not connected with error: %s", vnc_error);
1368 REMMINA_PLUGIN_DEBUG(
"Client connected");
1376 PermitServerInput(cl, 1);
1393 TRACE_CALL(__func__);
1394 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1404 GtkAllocation widget_allocation;
1408 gtk_widget_get_allocation(widget, &widget_allocation);
1421 TRACE_CALL(__func__);
1440 TRACE_CALL(__func__);
1453 if (event->button < 1 || event->button > 3)
1456 if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE)
1459 mask = (1 << (
event->button - 1));
1469 static gint
delta_to_mask(
float delta,
float *accum, gint mask_plus, gint mask_minus)
1472 if (*accum >= 1.0) {
1475 }
else if (*accum <= -1.0) {
1484 TRACE_CALL(__func__);
1496 switch (event->direction) {
1501 case GDK_SCROLL_DOWN:
1505 case GDK_SCROLL_LEFT:
1509 case GDK_SCROLL_RIGHT:
1513 #if GTK_CHECK_VERSION(3, 4, 0)
1514 case GDK_SCROLL_SMOOTH:
1538 TRACE_CALL(__func__);
1551 GINT_TO_POINTER(FALSE), NULL);
1561 g_ptr_array_remove_index_fast(gpdata->
pressed_keys, i);
1570 TRACE_CALL(__func__);
1589 event_keyval =
event->keyval;
1590 if (event->type == GDK_KEY_RELEASE) {
1593 if (k->
keycode == event->hardware_keycode) {
1594 event_keyval = k->
keyval;
1604 GINT_TO_POINTER(event->type == GDK_KEY_PRESS ? TRUE : FALSE), NULL);
1607 if (event->type == GDK_KEY_PRESS) {
1610 k->
keycode =
event->hardware_keycode;
1620 TRACE_CALL(__func__);
1626 const char *cur_charset;
1630 t = g_date_time_new_now_utc();
1638 g_get_charset(&cur_charset);
1639 latin1_text = g_convert_with_fallback(text, -1,
"ISO-8859-1", cur_charset,
"?", &br, &bw, NULL);
1641 g_free(latin1_text);
1647 TRACE_CALL(__func__);
1662 TRACE_CALL(__func__);
1673 g_object_unref(pixbuf);
1674 gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(gp)), cursor);
1675 g_object_unref(cursor);
1683 TRACE_CALL(__func__);
1692 const gchar* raw_server;
1705 gpdata->
clipboard_handler = g_signal_connect(G_OBJECT(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)),
1711 g_print(
"Could not initialize pthread. Falling back to non-thread mode…\n");
1718 if (raw_server && strstr(raw_server,
"unix://") == raw_server) {
1719 REMMINA_PLUGIN_AUDIT(_(
"Connected to %s via VNC"), raw_server);
1726 REMMINA_PLUGIN_AUDIT(_(
"Connected to %s:%d via VNC"), server, port);
1727 g_free(server), server = NULL;
1729 #if LIBVNCSERVER_CHECK_VERSION_VERSION(0, 9, 14)
1737 TRACE_CALL(__func__);
1749 REMMINA_PLUGIN_AUDIT(_(
"Disconnected from %s:%d via VNC"), server, port);
1750 g_free(server), server = NULL;
1758 g_signal_handler_disconnect(G_OBJECT(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)), gpdata->
clipboard_handler);
1778 rfbClientCleanup((rfbClient *)gpdata->
client);
1806 TRACE_CALL(__func__);
1812 pthread_cancel(gpdata->
thread);
1813 if (gpdata->
thread) pthread_join(gpdata->
thread, NULL);
1825 TRACE_CALL(__func__);
1827 switch (feature->
id) {
1828 case REMMINA_PLUGIN_VNC_FEATURE_PREF_DISABLESERVERINPUT:
1829 return SupportsClient2Server((rfbClient *)(gpdata->
client), rfbSetServerInput) ? TRUE : FALSE;
1830 case REMMINA_PLUGIN_VNC_FEATURE_TOOL_CHAT:
1831 return SupportsClient2Server((rfbClient *)(gpdata->
client), rfbTextChat) ? TRUE : FALSE;
1839 TRACE_CALL(__func__);
1843 uint8_t previous_bpp;
1845 switch (feature->
id) {
1846 case REMMINA_PLUGIN_VNC_FEATURE_PREF_QUALITY:
1851 SetFormatAndEncodings((rfbClient *)(gpdata->
client));
1853 case REMMINA_PLUGIN_VNC_FEATURE_PREF_COLOR:
1854 client = (rfbClient *)(gpdata->
client);
1855 previous_bpp = client->format.bitsPerPixel;
1858 SetFormatAndEncodings(client);
1860 if (client->format.bitsPerPixel > previous_bpp){
1862 SendFramebufferUpdateRequest((rfbClient *)(gpdata->
client), 0, 0,
1867 case REMMINA_PLUGIN_VNC_FEATURE_PREF_VIEWONLY:
1869 case REMMINA_PLUGIN_VNC_FEATURE_PREF_DISABLESERVERINPUT:
1870 PermitServerInput((rfbClient *)(gpdata->
client),
1873 case REMMINA_PLUGIN_VNC_FEATURE_UNFOCUS:
1876 case REMMINA_PLUGIN_VNC_FEATURE_SCALE:
1879 case REMMINA_PLUGIN_VNC_FEATURE_TOOL_REFRESH:
1880 SendFramebufferUpdateRequest((rfbClient *)(gpdata->
client), 0, 0,
1884 case REMMINA_PLUGIN_VNC_FEATURE_TOOL_CHAT:
1887 case REMMINA_PLUGIN_VNC_FEATURE_TOOL_SENDCTRLALTDEL:
1898 TRACE_CALL(__func__);
1902 keystrokes, keylen, GDK_KEY_PRESS | GDK_KEY_RELEASE);
1906 #if LIBVNCSERVER_CHECK_VERSION_VERSION(0, 9, 14)
1909 TRACE_CALL(__func__);
1915 sprintf(str,
"DEBUG: %d x %d", alloc->width, alloc->height);
1918 SendExtDesktopSize(gpdata->
client, alloc->width, alloc->height);
1927 TRACE_CALL(__func__);
1929 cairo_surface_t *surface;
1931 GtkAllocation widget_allocation;
1937 UNLOCK_BUFFER(FALSE);
1945 gtk_widget_get_allocation(widget, &widget_allocation);
1946 cairo_scale(context,
1947 (
double)widget_allocation.width / width,
1948 (
double)widget_allocation.height / height);
1951 cairo_rectangle(context, 0, 0, width, height);
1952 cairo_set_source_surface(context, surface, 0, 0);
1953 cairo_fill(context);
1955 UNLOCK_BUFFER(FALSE);
1961 TRACE_CALL(__func__);
1964 gdouble aspect_ratio;
1967 g_object_set_data_full(G_OBJECT(gp),
"plugin-data", gpdata, g_free);
1969 gboolean disable_smooth_scrolling = FALSE;
1973 REMMINA_PLUGIN_DEBUG(
"Disable smooth scrolling is set to %d", disable_smooth_scrolling);
1979 if (aspect_ratio > 0){
1980 GtkWidget* aspectframe = gtk_aspect_frame_new(NULL, 0, 0, aspect_ratio, FALSE);
1982 gtk_frame_set_shadow_type(GTK_FRAME(aspectframe), GTK_SHADOW_NONE);
1983 gtk_widget_show(aspectframe);
1984 gtk_container_add(GTK_CONTAINER(aspectframe), gpdata->
drawing_area);
1985 gtk_container_add(GTK_CONTAINER(gp), aspectframe);
1988 gtk_container_add(GTK_CONTAINER(gp), gpdata->
drawing_area);
1991 gtk_widget_add_events(
1993 GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
1994 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK
1995 | GDK_KEY_RELEASE_MASK
1999 if (!disable_smooth_scrolling) {
2000 REMMINA_PLUGIN_DEBUG(
"Adding GDK_SMOOTH_SCROLL_MASK");
2001 gtk_widget_add_events(gpdata->
drawing_area, GDK_SMOOTH_SCROLL_MASK);
2006 #if LIBVNCSERVER_CHECK_VERSION_VERSION(0, 9, 14)
2016 g_print(
"Error creating pipes.\n");
2029 "32",
N_(
"True colour (32 bpp)"),
2030 "16",
N_(
"High colour (16 bpp)"),
2031 "8",
N_(
"256 colours (8 bpp)"),
2039 "9",
N_(
"Best (slowest)"),
2041 "0",
N_(
"Poor (fastest)"),
2046 N_(
"Connect to VNC using a repeater:\n"
2047 " • The server field must contain the repeater ID, e.g. ID:123456789\n"
2048 " • The repeater field have to be set to the repeater IP and port, like:\n"
2049 " 10.10.10.12:5901\n"
2050 " • From the remote VNC server, you will connect to\n"
2051 " the repeater, e.g. with x11vnc:\n"
2052 " x11vnc -connect repeater=ID:123456789+10.10.10.12:5500");
2055 N_(
"Listening for remote VNC connection:\n"
2056 " • The “Listen on port” field is the port Remmina will listen to,\n"
2058 " • From the remote VNC server, you will connect to\n"
2059 " Remmina, e.g. with x11vnc:\n"
2060 " x11vnc -display :0 -connect 192.168.1.36:8888");
2063 N_(
"Lock the aspect ratio when dynamic resolution is enabled:\n"
2065 " • The aspect ratio should be entered as a decimal number, e.g. 1.777\n"
2066 " • 16:9 corresponds roughly to 1.7777, 4:3 corresponds roughly to 1.333\n"
2067 " • The default value of 0 does not enforce any aspect ratio");
2070 N_(
"Overriding the pre-set VNC encoding quality:\n"
2072 " • “Poor (fastest)” sets encoding to “copyrect zlib hextile raw”\n"
2073 " • “Medium” sets encoding to “tight zrle ultra copyrect hextile zlib corre rre raw”\n"
2074 " • “Good” sets encoding to “tight zrle ultra copyrect hextile zlib corre rre raw”\n"
2075 " • “Best (slowest)” sets encoding to “copyrect zrle ultra zlib hextile corre rre raw”");
2153 {
REMMINA_PROTOCOL_FEATURE_TYPE_PREF, REMMINA_PLUGIN_VNC_FEATURE_PREF_DISABLESERVERINPUT, GINT_TO_POINTER(REMMINA_PROTOCOL_FEATURE_PREF_CHECK),
"disableserverinput",
N_(
"Prevent local interaction on the server") },
2159 #if LIBVNCSERVER_CHECK_VERSION_VERSION(0, 9, 14)
2170 VNC_PLUGIN_DESCRIPTION,
2174 VNC_PLUGIN_SSH_APPICON,
2192 VNCI_PLUGIN_DESCRIPTION,
2195 VNCI_PLUGIN_APPICON,
2196 VNCI_PLUGIN_SSH_APPICON,
2212 G_MODULE_EXPORT gboolean
2215 TRACE_CALL(__func__);
2218 bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR);
2219 bind_textdomain_codeset(GETTEXT_PACKAGE,
"UTF-8");
@ REMMINA_PLUGIN_TYPE_PROTOCOL
guint(* pref_keymap_get_keyval)(const gchar *keymap, guint keyval)
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
void(* protocol_plugin_set_height)(RemminaProtocolWidget *gp, gint height)
void(* protocol_plugin_init_show_listen)(RemminaProtocolWidget *gp, gint port)
void(* protocol_plugin_send_keys_signals)(GtkWidget *widget, const guint *keyvals, int length, GdkEventType action)
void(* file_set_string)(RemminaFile *remminafile, const gchar *setting, const gchar *value)
gboolean(* protocol_plugin_is_closed)(RemminaProtocolWidget *gp)
gboolean(* register_plugin)(RemminaPlugin *plugin)
gint(* protocol_plugin_init_authx509)(RemminaProtocolWidget *gp)
void(* protocol_plugin_init_show_retry)(RemminaProtocolWidget *gp)
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
void(* get_server_port)(const gchar *server, gint defaultport, gchar **host, gint *port)
void(* protocol_plugin_desktop_resize)(RemminaProtocolWidget *gp)
void(* protocol_plugin_set_error)(RemminaProtocolWidget *gp, const gchar *fmt,...)
gchar *(* protocol_plugin_init_get_clientkey)(RemminaProtocolWidget *gp)
gdouble(* file_get_double)(RemminaFile *remminafile, const gchar *setting, gdouble default_value)
gchar *(* protocol_plugin_init_get_clientcert)(RemminaProtocolWidget *gp)
void(* protocol_plugin_chat_close)(RemminaProtocolWidget *gp)
void(* protocol_plugin_chat_receive)(RemminaProtocolWidget *gp, const gchar *text)
gchar *(* protocol_plugin_init_get_cacrl)(RemminaProtocolWidget *gp)
gboolean(* is_main_thread)(void)
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)
gchar *(* protocol_plugin_init_get_cacert)(RemminaProtocolWidget *gp)
void(* protocol_plugin_unlock_dynres)(RemminaProtocolWidget *gp)
gint(* protocol_plugin_get_height)(RemminaProtocolWidget *gp)
void(* protocol_plugin_update_align)(RemminaProtocolWidget *gp)
void(* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp)
void(* protocol_plugin_signal_connection_closed)(RemminaProtocolWidget *gp)
void(* protocol_plugin_chat_open)(RemminaProtocolWidget *gp, const gchar *name, void(*on_send)(RemminaProtocolWidget *gp, const gchar *text), void(*on_destroy)(RemminaProtocolWidget *gp))
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
gboolean(* protocol_plugin_has_error)(RemminaProtocolWidget *gp)
void(* protocol_plugin_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget)
void(* protocol_plugin_init_save_cred)(RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_init_get_username)(RemminaProtocolWidget *gp)
gboolean(* protocol_plugin_start_reverse_tunnel)(RemminaProtocolWidget *gp, gint local_port)
gchar *(* protocol_plugin_init_get_password)(RemminaProtocolWidget *gp)
gint(* protocol_plugin_get_width)(RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus)
RemminaScaleMode(* remmina_protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp)
gboolean(* protocol_plugin_init_get_savepassword)(RemminaProtocolWidget *gp)
RemminaProtocolWidget * gp
float scroll_y_accumulator
float scroll_x_accumulator
cairo_surface_t * rgb_buffer
cairo_surface_t * queuecursor_surface
pthread_mutex_t vnc_event_queue_mutex
pthread_mutex_t buffer_mutex
GDateTime * clipboard_timer
guint queuecursor_handler
struct _RemminaPluginVncEvent::@63::@65 pointer
union _RemminaPluginVncEvent::@63 event_data
struct _RemminaPluginVncEvent::@63::@64 key
enum onMainThread_cb_data::@61 func
RemminaProtocolWidget * gp
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
@ REMMINA_MESSAGE_PANEL_FLAG_USERNAME
@ REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD
@ REMMINA_PROTOCOL_SSH_SETTING_REVERSE_TUNNEL
@ REMMINA_PROTOCOL_SSH_SETTING_TUNNEL
@ REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS
@ REMMINA_PROTOCOL_FEATURE_TYPE_DYNRESUPDATE
@ REMMINA_PROTOCOL_FEATURE_TYPE_PREF
@ REMMINA_PROTOCOL_FEATURE_TYPE_END
@ REMMINA_PROTOCOL_FEATURE_TYPE_TOOL
@ REMMINA_PROTOCOL_FEATURE_TYPE_SCALE
@ REMMINA_PROTOCOL_SETTING_TYPE_SELECT
@ REMMINA_PROTOCOL_SETTING_TYPE_CHECK
@ REMMINA_PROTOCOL_SETTING_TYPE_SERVER
@ REMMINA_PROTOCOL_SETTING_TYPE_TEXT
@ REMMINA_PROTOCOL_SETTING_TYPE_END
@ REMMINA_PROTOCOL_SETTING_TYPE_KEYMAP
@ REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD
@ REMMINA_PROTOCOL_WIDGET_SCALE_MODE_DYNRES
@ REMMINA_PROTOCOL_WIDGET_SCALE_MODE_NONE
static int dot_cursor_y_hot
static gchar aspect_ratio_tooltip[]
static gboolean remmina_plugin_vnc_main_loop(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_rfb_fill_buffer(rfbClient *cl, guchar *dest, gint dest_rowstride, guchar *src, gint src_rowstride, guchar *mask, gint w, gint h)
static gpointer remmina_plugin_vnc_main_thread(gpointer data)
static void remmina_plugin_vnc_on_realize(RemminaProtocolWidget *gp, gpointer data)
static void remmina_plugin_vnc_rfb_chat(rfbClient *cl, int value, char *text)
static void remmina_plugin_vnc_update_scale(RemminaProtocolWidget *gp, gboolean scale)
struct _RemminaKeyVal RemminaKeyVal
struct _RemminaPluginVncCuttextParam RemminaPluginVncCuttextParam
static gchar vnciport_tooltip[]
static RemminaProtocolPlugin remmina_plugin_vnci
static gboolean remmina_plugin_vnc_open_connection(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_event_free_all(RemminaProtocolWidget *gp)
static RemminaPluginVncCoordinates remmina_plugin_vnc_scale_coordinates(GtkWidget *widget, RemminaProtocolWidget *gp, gint x, gint y)
static void onMainThread_schedule_callback_and_wait(struct onMainThread_cb_data *d)
static void remmina_plugin_vnc_release_key(RemminaProtocolWidget *gp, guint16 keycode)
static void remmina_plugin_vnc_rfb_led_state(rfbClient *cl, int value, int pad)
static gboolean remmina_plugin_vnc_on_motion(GtkWidget *widget, GdkEventMotion *event, RemminaProtocolWidget *gp)
static gboolean remmina_plugin_vnc_open_chat(RemminaProtocolWidget *gp)
static gboolean remmina_plugin_vnc_on_button(GtkWidget *widget, GdkEventButton *event, RemminaProtocolWidget *gp)
static gboolean remmina_plugin_vnc_on_key(GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
static gboolean remmina_plugin_vnc_incoming_connection(RemminaProtocolWidget *gp, rfbClient *cl)
static gboolean remmina_plugin_vnc_on_draw(GtkWidget *widget, cairo_t *context, RemminaProtocolWidget *gp)
G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
static void remmina_plugin_vnc_init(RemminaProtocolWidget *gp)
static gboolean remmina_plugin_vnc_close_connection_timeout(RemminaProtocolWidget *gp)
static void onMainThread_cleanup_handler(gpointer data)
static gboolean remmina_plugin_vnc_close_chat(RemminaProtocolWidget *gp)
static gchar repeater_tooltip[]
static gint delta_to_mask(float delta, float *accum, gint mask_plus, gint mask_minus)
static void remmina_plugin_vnc_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
static gpointer quality_list[]
static gboolean remmina_plugin_vnc_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
static gboolean remmina_plugin_vnc_on_scroll(GtkWidget *widget, GdkEventScroll *event, RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_update_colordepth(rfbClient *cl, gint colordepth)
static gboolean check_for_endianness()
Function check_for_endianness() returns 1, if architecture is little endian, 0 in case of big endian.
static void remmina_plugin_vnc_on_cuttext(GtkClipboard *clipboard, GdkEvent *event, RemminaProtocolWidget *gp)
static gpointer colordepth_list[]
static void remmina_plugin_vnc_rfb_cursor_shape(rfbClient *cl, int xhot, int yhot, int width, int height, int bytesPerPixel)
static gboolean remmina_plugin_vnc_close_connection(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_queuecursor(RemminaProtocolWidget *gp, cairo_surface_t *surface, gint x, gint y)
static const RemminaProtocolSetting remmina_plugin_vnc_advanced_settings[]
static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_event_push(RemminaProtocolWidget *gp, gint event_type, gpointer p1, gpointer p2, gpointer p3)
static gboolean remmina_plugin_vnc_queue_draw_area_real(RemminaProtocolWidget *gp)
static const RemminaProtocolSetting remmina_plugin_vnc_basic_settings[]
static rfbBool remmina_plugin_vnc_rfb_allocfb(rfbClient *cl)
static RemminaPluginService * remmina_plugin_service
static RemminaProtocolPlugin remmina_plugin_vnc
static gchar vncencodings_tooltip[]
static void remmina_plugin_vnc_on_cuttext_request(GtkClipboard *clipboard, const gchar *text, RemminaProtocolWidget *gp)
static gboolean onMainThread_cb(struct onMainThread_cb_data *d)
static void remmina_plugin_vnc_update_quality(rfbClient *cl, gint quality)
static gboolean remmina_plugin_vnc_queue_cuttext(RemminaPluginVncCuttextParam *param)
static gboolean remmina_plugin_vnc_on_size_allocate(GtkWidget *widget, GtkAllocation *alloc, RemminaProtocolWidget *gp)
static const uint32_t remmina_plugin_vnc_no_encrypt_auth_types[]
static void remmina_plugin_vnc_keystroke(RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen)
static void remmina_plugin_vnc_rfb_finished(rfbClient *cl) __attribute__((unused))
static void remmina_plugin_vnc_chat_on_send(RemminaProtocolWidget *gp, const gchar *text)
static rfbCredential * remmina_plugin_vnc_rfb_credential(rfbClient *cl, int credentialType)
static char * remmina_plugin_vnc_rfb_password(rfbClient *cl)
N_("Unable to connect to VNC server")
static const RemminaProtocolFeature remmina_plugin_vnc_features[]
static void remmina_plugin_vnc_scale_area(RemminaProtocolWidget *gp, gint *x, gint *y, gint *w, gint *h)
static const RemminaProtocolSetting remmina_plugin_vnci_basic_settings[]
gboolean remmina_plugin_vnc_setcursor(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_send_ctrlaltdel(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_chat_on_destroy(RemminaProtocolWidget *gp)
static void remmina_plugin_vnc_rfb_cuttext(rfbClient *cl, const char *text, int textlen)
static const gchar * dot_cursor_xpm[]
static void remmina_plugin_vnc_queue_draw_area(RemminaProtocolWidget *gp, gint x, gint y, gint w, gint h)
static RemminaPluginVncEvent * remmina_plugin_vnc_event_queue_pop_head(RemminaPluginVncData *gpdata)
static void remmina_plugin_vnc_rfb_bell(rfbClient *cl)
static void remmina_plugin_vnc_event_free(RemminaPluginVncEvent *event)
static void remmina_plugin_vnc_process_vnc_event(RemminaProtocolWidget *gp)
static int dot_cursor_x_hot
static gint remmina_plugin_vnc_bits(gint n)
static void remmina_plugin_vnc_rfb_updatefb(rfbClient *cl, int x, int y, int w, int h)
@ REMMINA_PLUGIN_VNC_EVENT_CUTTEXT
@ REMMINA_PLUGIN_VNC_EVENT_CHAT_SEND
@ REMMINA_PLUGIN_VNC_EVENT_POINTER
@ REMMINA_PLUGIN_VNC_EVENT_CHAT_CLOSE
@ REMMINA_PLUGIN_VNC_EVENT_KEY
@ REMMINA_PLUGIN_VNC_EVENT_CHAT_OPEN