Skip to content

Commit

Permalink
Implement 'Extended Clipboard' support
Browse files Browse the repository at this point in the history
This enables UTF-8 encoded clipboard sharing.

Re: #121
  • Loading branch information
gujjwal00 committed Mar 10, 2023
1 parent 06e5407 commit 53ac22d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 11 deletions.
25 changes: 19 additions & 6 deletions app/src/main/cpp/native-vnc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,23 @@ static void onBell(rfbClient *client) {
env->CallVoidMethod(obj, mid);
}

static void onGotXCutText(rfbClient *client, const char *text, int len) {
static void onGotXCutText(rfbClient *client, const char *text, int len, bool is_utf8) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;

jmethodID mid = env->GetMethodID(cls, "cbGotXCutText", "([B)V");
jmethodID mid = env->GetMethodID(cls, "cbGotXCutText", "([BZ)V");
jbyteArray bytes = env->NewByteArray(len);
env->SetByteArrayRegion(bytes, 0, len, reinterpret_cast<const jbyte *>(text));
env->CallVoidMethod(obj, mid, bytes);
env->CallVoidMethod(obj, mid, bytes, is_utf8);
}

static void onGotXCutTextLatin1(rfbClient *client, const char *text, int len) {
onGotXCutText(client, text, len, false);
}

static void onGotXCutTextUTF8(rfbClient *client, const char *text, int len) {
onGotXCutText(client, text, len, true);
}

static rfbBool onHandleCursorPos(rfbClient *client, int x, int y) {
Expand Down Expand Up @@ -231,7 +239,8 @@ static void setCallbacks(rfbClient *client) {
client->GetPassword = onGetPassword;
client->GetCredential = onGetCredential;
client->Bell = onBell;
client->GotXCutText = onGotXCutText;
client->GotXCutText = onGotXCutTextLatin1;
client->GotXCutTextUTF8 = onGotXCutTextUTF8;
client->HandleCursorPos = onHandleCursorPos;
client->FinishedFrameBufferUpdate = onFinishedFrameBufferUpdate;
client->MallocFrameBuffer = onMallocFrameBuffer;
Expand Down Expand Up @@ -377,12 +386,16 @@ Java_com_gaurav_avnc_vnc_VncClient_nativeSendPointerEvent(JNIEnv *env, jobject t

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSendCutText(JNIEnv *env, jobject thiz, jlong client_ptr, jbyteArray bytes) {
Java_com_gaurav_avnc_vnc_VncClient_nativeSendCutText(JNIEnv *env, jobject thiz, jlong client_ptr, jbyteArray bytes,
jboolean is_utf8) {
auto client = (rfbClient *) client_ptr;
auto textBuffer = env->GetByteArrayElements(bytes, nullptr);
auto textLen = env->GetArrayLength(bytes);
auto textChars = reinterpret_cast<char *>(textBuffer);

rfbBool result = SendClientCutText((rfbClient *) client_ptr, textChars, textLen);
rfbBool result = is_utf8
? SendClientCutTextUTF8(client, textChars, textLen)
: SendClientCutText(client, textChars, textLen);

env->ReleaseByteArrayElements(bytes, textBuffer, JNI_ABORT);
return (jboolean) result;
Expand Down
11 changes: 7 additions & 4 deletions app/src/main/java/com/gaurav/avnc/vnc/VncClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ class VncClient(private val observer: Observer) {
* Sends text to remote desktop's clipboard.
*/
fun sendCutText(text: String) = executeSend {
nativeSendCutText(nativePtr, text.toByteArray(StandardCharsets.ISO_8859_1))
if (!nativeSendCutText(nativePtr, text.toByteArray(StandardCharsets.UTF_8), true))
nativeSendCutText(nativePtr, text.toByteArray(StandardCharsets.ISO_8859_1), false)
}

/**
Expand Down Expand Up @@ -227,7 +228,7 @@ class VncClient(private val observer: Observer) {
private external fun nativeProcessServerMessage(clientPtr: Long, uSecTimeout: Int): Boolean
private external fun nativeSendKeyEvent(clientPtr: Long, keySym: Int, xtCode: Int, isDown: Boolean): Boolean
private external fun nativeSendPointerEvent(clientPtr: Long, x: Int, y: Int, mask: Int): Boolean
private external fun nativeSendCutText(clientPtr: Long, bytes: ByteArray): Boolean
private external fun nativeSendCutText(clientPtr: Long, bytes: ByteArray, isUTF8: Boolean): Boolean
private external fun nativeRefreshFrameBuffer(clientPtr: Long): Boolean
private external fun nativeGetDesktopName(clientPtr: Long): String
private external fun nativeGetWidth(clientPtr: Long): Int
Expand All @@ -245,8 +246,10 @@ class VncClient(private val observer: Observer) {
private fun cbGetCredential() = observer.onCredentialRequired()

@Keep
private fun cbGotXCutText(bytes: ByteArray) {
observer.onGotXCutText(StandardCharsets.ISO_8859_1.decode(ByteBuffer.wrap(bytes)).toString())
private fun cbGotXCutText(bytes: ByteArray, isUTF8: Boolean) {
(if (isUTF8) StandardCharsets.UTF_8 else StandardCharsets.ISO_8859_1).let {
observer.onGotXCutText(it.decode(ByteBuffer.wrap(bytes)).toString())
}
}

@Keep
Expand Down
2 changes: 1 addition & 1 deletion extern/libvncserver

0 comments on commit 53ac22d

Please sign in to comment.