Skip to content

Commit fed2c8b

Browse files
committed
libvncclient: rework utf-8 clipboard API to resemble libvncserver one
Public LibVNCServer API has * `rfbSendServerCutTextUTF8(rfbScreenInfoPtr rfbScreen,char *str, int len, char *fallbackLatin1Str, int latin1Len);` * and `typedef void (*rfbSetXCutTextUTF8ProcPtr) (char* str,int len, struct _rfbClientRec* cl);` which is wired up as `setXCutTextUTF8`, i.e. it's got a unicode sender w/ Latin1 fallback and a dedicated unicode receiver. This commit reworks the libvncclient API to have a dedicated UTF8 clipboard sending function and a dedicated on-receive callback. Applications can use those functions instead of changing state with some rfbClient member.
1 parent c0b3601 commit fed2c8b

2 files changed

Lines changed: 41 additions & 40 deletions

File tree

libvncclient/rfbproto.c

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,9 +1448,8 @@ SetFormatAndEncodings(rfbClient* client)
14481448

14491449
#ifdef LIBVNCSERVER_HAVE_LIBZ
14501450
/* extendedclipboard */
1451-
if (client->clipboardCap)
1452-
if (se->nEncodings < MAX_ENCODINGS)
1453-
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingExtendedClipboard);
1451+
if (se->nEncodings < MAX_ENCODINGS)
1452+
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingExtendedClipboard);
14541453
#endif
14551454

14561455
/* client extensions */
@@ -1778,7 +1777,7 @@ SendExtendedKeyEvent(rfbClient* client, uint32_t keysym, uint32_t keycode, rfbBo
17781777

17791778
#ifdef LIBVNCSERVER_HAVE_LIBZ
17801779
/*
1781-
* sendClientCutTextNotify
1780+
* sendExtClientCutTextNotify
17821781
* it is needed when client send utf8 clipboard data
17831782
* please refer to
17841783
* https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#extended-clipboard-pseudo-encoding
@@ -1800,7 +1799,7 @@ sendExtClientCutTextNotify(rfbClient *client)
18001799

18011800

18021801
/*
1803-
* sendClientCutTextProvide
1802+
* sendExtClientCutTextProvide
18041803
* it need send notify first to grab clipboard (server will check that)
18051804
*/
18061805

@@ -1859,19 +1858,23 @@ SendClientCutText(rfbClient* client, char *str, int len)
18591858

18601859
if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
18611860

1862-
#ifdef LIBVNCSERVER_HAVE_LIBZ
1863-
if (client->clipboardEnabledCap) { /* if enabled extended clipboard, use it */
1864-
return sendExtClientCutTextProvide(client, str, len);
1865-
}
1866-
#endif
1867-
18681861
memset(&cct, 0, sizeof(cct));
18691862
cct.type = rfbClientCutText;
18701863
cct.length = rfbClientSwap32IfLE(len);
18711864
return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
18721865
WriteToRFBServer(client, str, len));
18731866
}
18741867

1868+
rfbBool
1869+
SendClientCutTextUTF8(rfbClient* client, char *str, int len)
1870+
{
1871+
#ifdef LIBVNCSERVER_HAVE_LIBZ
1872+
return client->extendedClipboardServerCapabilities && sendExtClientCutTextProvide(client, str, len);
1873+
#else
1874+
return FALSE;
1875+
#endif
1876+
}
1877+
18751878

18761879
#ifdef LIBVNCSERVER_HAVE_LIBZ
18771880
/*
@@ -1905,7 +1908,7 @@ rfbClientProcessExtServerCutText(rfbClient* client, char *data, int len)
19051908
}
19061909
if (flags & rfbExtendedClipboard_Caps) {
19071910
rfbClientLog("rfbClientProcessExtServerCutText. default cap.\n");
1908-
client->clipboardEnabledCap |= rfbExtendedClipboard_Text; /* for now, only text */
1911+
client->extendedClipboardServerCapabilities |= rfbExtendedClipboard_Text; /* for now, only text */
19091912
return TRUE;
19101913
}
19111914

@@ -1959,8 +1962,8 @@ rfbClientProcessExtServerCutText(rfbClient* client, char *data, int len)
19591962
inflateEnd(&stream);
19601963
return FALSE;
19611964
}
1962-
if (client->GotXCutText)
1963-
client->GotXCutText(client, (char *)buf, size);
1965+
if (client->GotXCutTextUTF8)
1966+
client->GotXCutTextUTF8(client, buf, size);
19641967
free(buf);
19651968

19661969
inflateEnd(&stream);
@@ -2514,7 +2517,6 @@ HandleRFBServerMessage(rfbClient* client)
25142517
char *buffer;
25152518
#ifdef LIBVNCSERVER_HAVE_LIBZ
25162519
int32_t ilen; /* also as a flag, if ilen < 0, it is ext clipboard text */
2517-
rfbBool fallback = FALSE;
25182520
#endif
25192521

25202522
if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
@@ -2523,16 +2525,6 @@ HandleRFBServerMessage(rfbClient* client)
25232525

25242526
#ifdef LIBVNCSERVER_HAVE_LIBZ
25252527
ilen = rfbClientSwap32IfLE(msg.sct.length);
2526-
if (client->clipboardEnabledCap && ilen >= 0) {
2527-
if (!client->GotXCutTextFallback) {
2528-
rfbClientLog("extend clipboardCap enabled but msg len:%d >= 0. no fallback callback. ignore\n", ilen);
2529-
return FALSE;
2530-
} else {
2531-
rfbClientLog("extend clipboardCap enabled but msg len:%d >= 0. fallback\n", ilen);
2532-
fallback = TRUE;
2533-
}
2534-
}
2535-
25362528
msg.sct.length = ilen < 0 ? -ilen : ilen;
25372529
#else
25382530
msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);
@@ -2553,9 +2545,7 @@ HandleRFBServerMessage(rfbClient* client)
25532545
buffer[msg.sct.length] = 0;
25542546

25552547
#ifdef LIBVNCSERVER_HAVE_LIBZ
2556-
if (fallback) {
2557-
client->GotXCutTextFallback(client, buffer, msg.sct.length);
2558-
} else if (ilen < 0) {
2548+
if (ilen < 0 && client->GotXCutTextUTF8) {
25592549
if (!rfbClientProcessExtServerCutText(client, buffer, -ilen)) {
25602550
free(buffer);
25612551
return FALSE;

rfb/rfbclient.h

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ typedef char* (*GetPasswordProc)(struct _rfbClient* client);
217217
typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType);
218218
typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client);
219219
typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen);
220+
typedef void (*GotXCutTextUTF8Proc)(struct _rfbClient* client, const char* buffer, int buffer_len);
220221
typedef void (*BellProc)(struct _rfbClient* client);
221222
/**
222223
Called when a cursor shape update was received from the server. The decoded cursor shape
@@ -479,17 +480,12 @@ typedef struct _rfbClient {
479480
rfbExtDesktopScreen screen;
480481

481482
#ifdef LIBVNCSERVER_HAVE_LIBZ
482-
uint32_t clipboardCap; /**extended clipboard pseudo-encoding cap */
483-
/**it is bitset as rfb3.8, current only support text */
484-
/**client set it to rfbExtendedClipboard_Text for now */
485-
uint32_t clipboardEnabledCap; /**enabled cap which confirmed by server */
486-
/**client can use it as a check for server cap */
487-
/**
488-
* Used for extended clipboard text fallback
489-
* When server announce cap of utf8, but still send latin-1
490-
*/
491-
GotXCutTextProc GotXCutTextFallback;
483+
uint32_t extendedClipboardServerCapabilities;
492484
#endif
485+
/**
486+
* Callback fired when "Extended Clipboard" UTF-8 text data is received.
487+
*/
488+
GotXCutTextUTF8Proc GotXCutTextUTF8;
493489
} rfbClient;
494490

495491
/* cursor.c */
@@ -609,18 +605,33 @@ extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down);
609605
*/
610606
extern rfbBool SendExtendedKeyEvent(rfbClient* client, uint32_t keysym, uint32_t keycode, rfbBool down);
611607
/**
612-
* Places a string on the server's clipboard. Use this function if you want to
608+
* Places a Latin-1-encoded string on the server's clipboard. Use this function if you want to
613609
* be able to copy and paste between the server and your application. For
614610
* instance, when your application is notified that the user copied some text
615611
* onto the clipboard, you would call this function to synchronize the server's
616612
* clipboard with your local clipboard.
617613
* @param client The client structure through which to send the client cut text
618614
* message
619-
* @param str The string to send (doesn't need to be NULL terminated)
615+
* @param str The string to send (needs to be Latin-1-encoded, doesn't need to be NULL terminated)
620616
* @param len The length of the string
621617
* @return true if the client cut message was sent successfully, false otherwise
622618
*/
623619
extern rfbBool SendClientCutText(rfbClient* client,char *str, int len);
620+
/**
621+
* Places a UTF-8-encoded string on the server's clipboard if the server supports it.
622+
* Use this function if you want to be able to copy and paste between the server and your application. For
623+
* instance, when your application is notified that the user copied some text
624+
* onto the clipboard, you would call this function to synchronize the server's
625+
* clipboard with your local clipboard. This is the more modern equivalent of
626+
* SendClientCutText().
627+
* @param client The client structure through which to send the client cut text
628+
* message
629+
* @param str The string to send (needs to be UTF-8-encoded, doesn't need to be NULL terminated)
630+
* @param len The length of the string in bytes
631+
* @return true if the message was sent successfully, false otherwise - you might want to
632+
* fall back to SendClientCutText() in this case.
633+
*/
634+
extern rfbBool SendClientCutTextUTF8(rfbClient* client, char *str, int len);
624635
/**
625636
* Handles messages from the RFB server. You must call this function
626637
* intermittently so LibVNCClient can parse messages from the server. For

0 commit comments

Comments
 (0)