22#include <freerdp/config.h>
27#include <winpr/stream.h>
29#include <freerdp/client/channels.h>
30#include <freerdp/client/cliprdr.h>
32#include "android_cliprdr.h"
33#include "android_jni_utils.h"
34#include "android_jni_callback.h"
36UINT android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
38 UINT rc = ERROR_INTERNAL_ERROR;
42 const char* formatName;
47 return ERROR_INVALID_PARAMETER;
51 if (!afc || !afc->cliprdr)
52 return ERROR_INVALID_PARAMETER;
55 numFormats = ClipboardGetFormatIds(afc->clipboard, &pFormatIds);
61 for (UINT32 index = 0; index < numFormats; index++)
63 formatId = pFormatIds[index];
64 formatName = ClipboardGetFormatName(afc->clipboard, formatId);
65 formats[index].formatId = formatId;
66 formats[index].formatName =
nullptr;
68 if ((formatId > CF_MAX) && formatName)
70 formats[index].formatName = _strdup(formatName);
72 if (!formats[index].formatName)
77 formatList.common.msgFlags = 0;
78 formatList.numFormats = numFormats;
79 formatList.formats = formats;
80 formatList.common.msgType = CB_FORMAT_LIST;
82 if (!afc->cliprdr->ClientFormatList)
85 rc = afc->cliprdr->ClientFormatList(afc->cliprdr, &formatList);
92static UINT android_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr,
95 UINT rc = ERROR_INVALID_PARAMETER;
104 if (!afc || !afc->clipboardRequestEvent || !cliprdr->ClientFormatDataRequest)
107 formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
108 formatDataRequest.common.msgFlags = 0;
109 formatDataRequest.requestedFormatId = formatId;
110 afc->requestedFormatId = formatId;
111 (void)ResetEvent(afc->clipboardRequestEvent);
112 rc = cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
117static UINT android_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
122 if (!cliprdr || !cliprdr->ClientCapabilities)
123 return ERROR_INVALID_PARAMETER;
125 capabilities.cCapabilitiesSets = 1;
127 generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
128 generalCapabilitySet.capabilitySetLength = 12;
129 generalCapabilitySet.version = CB_CAPS_VERSION_2;
130 generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
131 return cliprdr->ClientCapabilities(cliprdr, &capabilities);
139static UINT android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
145 if (!cliprdr || !monitorReady)
146 return ERROR_INVALID_PARAMETER;
151 return ERROR_INVALID_PARAMETER;
153 if ((rc = android_cliprdr_send_client_capabilities(cliprdr)) != CHANNEL_RC_OK)
156 if ((rc = android_cliprdr_send_client_format_list(cliprdr)) != CHANNEL_RC_OK)
159 afc->clipboardSync = TRUE;
160 return CHANNEL_RC_OK;
168static UINT android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr,
174 if (!cliprdr || !capabilities)
175 return ERROR_INVALID_PARAMETER;
180 return ERROR_INVALID_PARAMETER;
182 for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
184 capabilitySet = &(capabilities->capabilitySets[index]);
186 if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
187 (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
191 afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
196 return CHANNEL_RC_OK;
204static UINT android_cliprdr_server_format_list(CliprdrClientContext* cliprdr,
211 if (!cliprdr || !formatList)
212 return ERROR_INVALID_PARAMETER;
217 return ERROR_INVALID_PARAMETER;
219 if (afc->serverFormats)
221 for (UINT32 index = 0; index < afc->numServerFormats; index++)
222 free(afc->serverFormats[index].formatName);
224 free(afc->serverFormats);
225 afc->serverFormats =
nullptr;
226 afc->numServerFormats = 0;
229 if (formatList->numFormats < 1)
230 return CHANNEL_RC_OK;
232 afc->numServerFormats = formatList->numFormats;
235 if (!afc->serverFormats)
236 return CHANNEL_RC_NO_MEMORY;
238 for (UINT32 index = 0; index < afc->numServerFormats; index++)
240 afc->serverFormats[index].formatId = formatList->formats[index].formatId;
241 afc->serverFormats[index].formatName =
nullptr;
243 if (formatList->formats[index].formatName)
245 afc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
247 if (!afc->serverFormats[index].formatName)
248 return CHANNEL_RC_NO_MEMORY;
254 for (UINT32 index = 0; index < afc->numServerFormats; index++)
256 format = &(afc->serverFormats[index]);
258 if (format->formatId == CF_UNICODETEXT)
260 if ((rc = android_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT)) !=
264 return CHANNEL_RC_OK;
266 else if (format->formatId == CF_TEXT)
268 if ((rc = android_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT)) !=
272 return CHANNEL_RC_OK;
277 for (UINT32 index = 0; index < afc->numServerFormats; index++)
279 format = &(afc->serverFormats[index]);
281 if (format->formatId == CF_DIB || format->formatId == CF_DIBV5)
283 if ((rc = android_cliprdr_send_client_format_data_request(cliprdr, format->formatId)) !=
291 return CHANNEL_RC_OK;
300android_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr,
303 if (!cliprdr || !formatListResponse)
304 return ERROR_INVALID_PARAMETER;
306 return CHANNEL_RC_OK;
315android_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr,
318 if (!cliprdr || !lockClipboardData)
319 return ERROR_INVALID_PARAMETER;
321 return CHANNEL_RC_OK;
329static UINT android_cliprdr_server_unlock_clipboard_data(
332 if (!cliprdr || !unlockClipboardData)
333 return ERROR_INVALID_PARAMETER;
335 return CHANNEL_RC_OK;
344android_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr,
354 if (!cliprdr || !formatDataRequest || !cliprdr->ClientFormatDataResponse)
355 return ERROR_INVALID_PARAMETER;
360 return ERROR_INVALID_PARAMETER;
362 formatId = formatDataRequest->requestedFormatId;
363 data = (BYTE*)ClipboardGetData(afc->clipboard, formatId, &size);
364 response.common.msgFlags = CB_RESPONSE_OK;
365 response.common.dataLen = size;
366 response.requestedFormatData = data;
370 response.common.msgFlags = CB_RESPONSE_FAIL;
371 response.common.dataLen = 0;
372 response.requestedFormatData =
nullptr;
375 rc = cliprdr->ClientFormatDataResponse(cliprdr, &response);
386android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr,
391 if (!cliprdr || !formatDataResponse)
392 return ERROR_INVALID_PARAMETER;
397 return ERROR_INVALID_PARAMETER;
399 freerdp* instance = ((rdpContext*)afc)->instance;
402 return ERROR_INVALID_PARAMETER;
404 for (UINT32 index = 0; index < afc->numServerFormats; index++)
406 if (afc->requestedFormatId == afc->serverFormats[index].formatId)
407 format = &(afc->serverFormats[index]);
412 (void)SetEvent(afc->clipboardRequestEvent);
413 return ERROR_INTERNAL_ERROR;
416 UINT32 formatId = format->formatId;
417 if (format->formatName)
418 formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
420 uint32_t size = formatDataResponse->common.dataLen;
422 if (!ClipboardSetData(afc->clipboard, formatId, formatDataResponse->requestedFormatData, size))
423 return ERROR_INTERNAL_ERROR;
425 (void)SetEvent(afc->clipboardRequestEvent);
432 JNIEnv* env =
nullptr;
433 UINT32 plainFormatId = ClipboardRegisterFormat(afc->clipboard,
"text/plain");
434 char* data = (
char*)ClipboardGetData(afc->clipboard, plainFormatId, &size);
437 jboolean attached = jni_attach_thread(&env);
438 size = strnlen(data, size);
439 jstring jdata = jniNewStringUTF(env, data, size);
440 freerdp_callback(
"OnRemoteClipboardChanged",
"(JLjava/lang/String;)V", (jlong)instance,
442 (*env)->DeleteLocalRef(env, jdata);
445 if (attached == JNI_TRUE)
452 UINT32 pngFormatId = ClipboardRegisterFormat(afc->clipboard,
"image/png");
453 BYTE* pngData = (BYTE*)ClipboardGetData(afc->clipboard, pngFormatId, &size);
457 JNIEnv* env =
nullptr;
458 jboolean attached = jni_attach_thread(&env);
459 jbyteArray jpngData = (*env)->NewByteArray(env, (jsize)size);
463 (*env)->SetByteArrayRegion(env, jpngData, 0, (jsize)size,
464 (
const jbyte*)pngData);
465 freerdp_callback(
"OnRemoteClipboardImageChanged",
"(J[B)V", (jlong)instance,
467 (*env)->DeleteLocalRef(env, jpngData);
472 if (attached == JNI_TRUE)
481 return CHANNEL_RC_OK;
489static UINT android_cliprdr_server_file_contents_request(
492 if (!cliprdr || !fileContentsRequest)
493 return ERROR_INVALID_PARAMETER;
495 return CHANNEL_RC_OK;
503static UINT android_cliprdr_server_file_contents_response(
506 if (!cliprdr || !fileContentsResponse)
507 return ERROR_INVALID_PARAMETER;
509 return CHANNEL_RC_OK;
512BOOL android_cliprdr_init(
androidContext* afc, CliprdrClientContext* cliprdr)
514 wClipboard* clipboard;
517 if (!afc || !cliprdr)
520 if (!(hevent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
523 if (!(clipboard = ClipboardCreate()))
525 (void)CloseHandle(hevent);
529 afc->cliprdr = cliprdr;
530 afc->clipboard = clipboard;
531 afc->clipboardRequestEvent = hevent;
532 cliprdr->custom = (
void*)afc;
533 cliprdr->MonitorReady = android_cliprdr_monitor_ready;
534 cliprdr->ServerCapabilities = android_cliprdr_server_capabilities;
535 cliprdr->ServerFormatList = android_cliprdr_server_format_list;
536 cliprdr->ServerFormatListResponse = android_cliprdr_server_format_list_response;
537 cliprdr->ServerLockClipboardData = android_cliprdr_server_lock_clipboard_data;
538 cliprdr->ServerUnlockClipboardData = android_cliprdr_server_unlock_clipboard_data;
539 cliprdr->ServerFormatDataRequest = android_cliprdr_server_format_data_request;
540 cliprdr->ServerFormatDataResponse = android_cliprdr_server_format_data_response;
541 cliprdr->ServerFileContentsRequest = android_cliprdr_server_file_contents_request;
542 cliprdr->ServerFileContentsResponse = android_cliprdr_server_file_contents_response;
546BOOL android_cliprdr_uninit(
androidContext* afc, CliprdrClientContext* cliprdr)
548 if (!afc || !cliprdr)
551 cliprdr->custom =
nullptr;
552 afc->cliprdr =
nullptr;
553 ClipboardDestroy(afc->clipboard);
554 (void)CloseHandle(afc->clipboardRequestEvent);