afreerdp: migrate to cliprdr callback interface

This commit is contained in:
Marc-André Moreau 2014-11-12 12:25:12 -05:00
parent 19c3b0d457
commit 769eb38217
5 changed files with 403 additions and 461 deletions

View File

@ -22,12 +22,10 @@
#endif
#include <jni.h>
#include <stdlib.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/utils/event.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/cliprdr.h>
@ -36,437 +34,325 @@
#include "android_jni_utils.h"
#include "android_jni_callback.h"
struct clipboard_context
int android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
{
UINT32 index;
UINT32 formatId;
UINT32 numFormats;
UINT32* pFormatIds;
const char* formatName;
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
androidContext* afc = (androidContext*) cliprdr->custom;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
pFormatIds = NULL;
numFormats = ClipboardGetFormatIds(afc->clipboard, &pFormatIds);
formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT));
if (!formats)
return -1;
for (index = 0; index < numFormats; index++)
{
formatId = pFormatIds[index];
formatName = ClipboardGetFormatName(afc->clipboard, formatId);
formats[index].formatId = formatId;
formats[index].formatName = NULL;
if ((formatId > CF_MAX) && formatName)
formats[index].formatName = _strdup(formatName);
}
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = formats;
afc->cliprdr->ClientFormatList(afc->cliprdr, &formatList);
free(pFormatIds);
free(formats);
return 1;
}
int android_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
androidContext* afc = (androidContext*) cliprdr->custom;
ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.msgFlags = 0;
formatDataRequest.requestedFormatId = formatId;
afc->requestedFormatId = formatId;
ResetEvent(afc->clipboardRequestEvent);
cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
return 1;
}
int android_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
{
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = CB_CAPS_VERSION_2;
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
cliprdr->ClientCapabilities(cliprdr, &capabilities);
return 1;
}
int android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady)
{
androidContext* afc = (androidContext*) cliprdr->custom;
afc->clipboardSync = TRUE;
android_cliprdr_send_client_capabilities(cliprdr);
android_cliprdr_send_client_format_list(cliprdr);
return 1;
}
int android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities)
{
UINT32 index;
CLIPRDR_CAPABILITY_SET* capabilitySet;
androidContext* afc = (androidContext*) cliprdr->custom;
for (index = 0; index < capabilities->cCapabilitiesSets; index++)
{
capabilitySet = &(capabilities->capabilitySets[index]);
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
(capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
{
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet
= (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
break;
}
}
return 1;
}
int android_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList)
{
UINT32 index;
CLIPRDR_FORMAT* format;
androidContext* afc = (androidContext*) cliprdr->custom;
if (afc->serverFormats)
{
for (index = 0; index < afc->numServerFormats; index++)
{
free(afc->serverFormats[index].formatName);
}
free(afc->serverFormats);
afc->serverFormats = NULL;
afc->numServerFormats = 0;
}
if (formatList->numFormats < 1)
return 1;
afc->numServerFormats = formatList->numFormats;
afc->serverFormats = (CLIPRDR_FORMAT*) calloc(afc->numServerFormats, sizeof(CLIPRDR_FORMAT));
if (!afc->serverFormats)
return -1;
for (index = 0; index < afc->numServerFormats; index++)
{
afc->serverFormats[index].formatId = formatList->formats[index].formatId;
afc->serverFormats[index].formatName = NULL;
if (formatList->formats[index].formatName)
afc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
}
for (index = 0; index < afc->numServerFormats; index++)
{
format = &(afc->serverFormats[index]);
if (format->formatId == CF_UNICODETEXT)
{
android_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
break;
}
else if (format->formatId == CF_TEXT)
{
android_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
break;
}
}
return 1;
}
int android_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
return 1;
}
int android_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
return 1;
}
int android_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
return 1;
}
int android_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
freerdp* instance;
rdpChannels* channels;
/* server->client data */
UINT32* formats;
int num_formats;
BYTE* data;
UINT32 data_format;
int data_length;
UINT32 size;
UINT32 formatId;
CLIPRDR_FORMAT_DATA_RESPONSE response;
androidContext* afc = (androidContext*) cliprdr->custom;
/* client->server data */
UINT32* android_formats;
int android_num_formats;
BYTE* android_data;
int android_data_length;
};
typedef struct clipboard_context clipboardContext;
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
static BYTE* lf2crlf(BYTE* data, int* size)
{
BYTE c;
BYTE* outbuf;
BYTE* out;
BYTE* in_end;
BYTE* in;
int out_size;
formatId = formatDataRequest->requestedFormatId;
data = (BYTE*) ClipboardGetData(afc->clipboard, formatId, &size);
out_size = (*size) * 2 + 1;
outbuf = (BYTE*) malloc(out_size);
ZeroMemory(outbuf, out_size);
response.msgFlags = CB_RESPONSE_OK;
response.dataLen = size;
response.requestedFormatData = data;
out = outbuf;
in = data;
in_end = data + (*size);
while (in < in_end)
if (!data)
{
c = *in++;
if (c == '\n')
{
*out++ = '\r';
*out++ = '\n';
}
else
{
*out++ = c;
}
response.msgFlags = CB_RESPONSE_FAIL;
response.dataLen = 0;
response.requestedFormatData = NULL;
}
*out++ = 0;
*size = out - outbuf;
cliprdr->ClientFormatDataResponse(cliprdr, &response);
return outbuf;
free(data);
return 1;
}
static void crlf2lf(BYTE* data, int* size)
int android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
BYTE c;
BYTE* out;
BYTE* in;
BYTE* in_end;
BYTE* data;
UINT32 size;
UINT32 index;
UINT32 formatId;
CLIPRDR_FORMAT* format = NULL;
androidContext* afc = (androidContext*) cliprdr->custom;
freerdp* instance = ((rdpContext*) afc)->instance;
out = data;
in = data;
in_end = data + (*size);
while (in < in_end)
for (index = 0; index < afc->numServerFormats; index++)
{
c = *in++;
if (c != '\r')
*out++ = c;
if (afc->requestedFormatId == afc->serverFormats[index].formatId)
format = &(afc->serverFormats[index]);
}
*size = out - data;
}
void android_cliprdr_init(freerdp* inst)
{
clipboardContext* cb;
androidContext* ctx = (androidContext*) inst->context;
cb = (clipboardContext*) calloc(1, sizeof(clipboardContext));
cb->instance = inst;
cb->channels = inst->context->channels;
cb->android_num_formats = 2;
cb->android_formats = (UINT32*) calloc(cb->android_num_formats, sizeof(UINT32));
cb->android_formats[0] = CF_TEXT;
cb->android_formats[1] = CF_UNICODETEXT;
ctx->clipboard_context = cb;
}
void android_cliprdr_uninit(freerdp* inst)
{
androidContext* ctx = (androidContext*)inst->context;
clipboardContext* cb = (clipboardContext*)ctx->clipboard_context;
if (cb)
if (!format)
{
if (cb->formats)
free(cb->formats);
if (cb->data)
free(cb->data);
if (cb->android_formats)
free(cb->android_formats);
if (cb->android_data)
free(cb->android_data);
free(cb);
ctx->clipboard_context = NULL;
}
}
static void android_cliprdr_send_null_format_list(clipboardContext* cb)
{
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->num_formats = 0;
freerdp_channels_send_event(cb->channels, (wMessage*) event);
}
static void android_cliprdr_send_supported_format_list(clipboardContext* cb)
{
int i;
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->formats = (UINT32*) calloc(cb->android_num_formats, sizeof(UINT32));
event->num_formats = cb->android_num_formats;
for (i = 0; i < cb->android_num_formats; i++)
{
event->formats[i] = cb->android_formats[i];
SetEvent(afc->clipboardRequestEvent);
return -1;
}
freerdp_channels_send_event(cb->channels, (wMessage*) event);
}
static void android_cliprdr_send_format_list(clipboardContext* cb)
{
if (cb->android_data)
{
android_cliprdr_send_supported_format_list(cb);
}
if (format->formatName)
formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
else
formatId = format->formatId;
size = formatDataResponse->dataLen;
data = (BYTE*) malloc(size);
CopyMemory(data, formatDataResponse->requestedFormatData, size);
ClipboardSetData(afc->clipboard, formatId, data, size);
SetEvent(afc->clipboardRequestEvent);
if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
{
android_cliprdr_send_null_format_list(cb);
}
}
JNIEnv* env;
jstring jdata;
jboolean attached;
static void android_cliprdr_send_data_request(clipboardContext* cb, UINT32 format)
{
RDP_CB_DATA_REQUEST_EVENT* event;
formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING");
event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_DataRequest, NULL, NULL);
data = (void*) ClipboardGetData(afc->clipboard, formatId, &size);
event->format = format;
attached = jni_attach_thread(&env);
jdata = jniNewStringUTF(env, data, size);
freerdp_channels_send_event(cb->channels, (wMessage*) event);
}
freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", instance, jdata);
static void android_cliprdr_send_data_response(clipboardContext* cb, BYTE* data, int size)
{
RDP_CB_DATA_RESPONSE_EVENT* event;
(*env)->DeleteLocalRef(env, jdata);
event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_DataResponse, NULL, NULL);
event->data = data;
event->size = size;
freerdp_channels_send_event(cb->channels, (wMessage*) event);
}
static void android_cliprdr_send_null_data_response(clipboardContext* cb)
{
android_cliprdr_send_data_response(cb, NULL, 0);
}
static void android_cliprdr_process_cb_monitor_ready_event(clipboardContext* cb)
{
android_cliprdr_send_format_list(cb);
}
static BYTE* android_cliprdr_process_requested_unicodetext(BYTE* data, int* size)
{
char* inbuf;
WCHAR* outbuf = NULL;
int out_size;
inbuf = (char*) lf2crlf(data, size);
out_size = ConvertToUnicode(CP_UTF8, 0, inbuf, -1, &outbuf, 0);
free(inbuf);
*size = (int) ((out_size + 1) * 2);
return (BYTE*) outbuf;
}
static BYTE* android_cliprdr_process_requested_text(BYTE* data, int* size)
{
BYTE* outbuf;
outbuf = lf2crlf(data, size);
return outbuf;
}
static void android_cliprdr_process_cb_data_request_event(clipboardContext* cb, RDP_CB_DATA_REQUEST_EVENT* event)
{
int i;
DEBUG_ANDROID("format %d", event->format);
for (i = 0; i < cb->android_num_formats; i++)
{
if (event->format == cb->android_formats[i])
break;
}
if (i >= cb->android_num_formats)
{
DEBUG_ANDROID("unsupported format requested");
android_cliprdr_send_null_data_response(cb);
}
else if (!cb->android_data)
{
DEBUG_ANDROID("no android clipdata");
android_cliprdr_send_null_data_response(cb);
}
else
{
BYTE* outbuf = NULL;
int size = cb->android_data_length;
switch (event->format)
if (attached == JNI_TRUE)
{
case CF_UNICODETEXT:
outbuf = android_cliprdr_process_requested_unicodetext(cb->android_data, &size);
break;
case CF_TEXT:
outbuf = android_cliprdr_process_requested_text(cb->android_data, &size);
break;
}
if (outbuf)
android_cliprdr_send_data_response(cb, outbuf, size);
else
android_cliprdr_send_null_data_response(cb);
}
/* Resend the format list, otherwise the server won't request again for the next paste */
android_cliprdr_send_format_list(cb);
}
static BOOL android_cliprdr_has_format(UINT32* formats, int num_formats, UINT32 format)
{
int i;
for (i = 0; i < num_formats; i++)
{
if (formats[i] == format)
return TRUE;
}
return FALSE;
}
static void android_cliprdr_process_cb_format_list_event(clipboardContext* cb, RDP_CB_FORMAT_LIST_EVENT* event)
{
if (cb->data)
{
free(cb->data);
cb->data = NULL;
cb->data_length = 0;
}
if (cb->formats)
free(cb->formats);
cb->data_format = 0;
cb->formats = event->formats;
cb->num_formats = event->num_formats;
event->formats = NULL;
event->num_formats = 0;
if (android_cliprdr_has_format(cb->formats, cb->num_formats, CF_TEXT))
{
cb->data_format = CF_TEXT;
android_cliprdr_send_data_request(cb, CF_TEXT);
}
else if (android_cliprdr_has_format(cb->formats, cb->num_formats, CF_UNICODETEXT))
{
cb->data_format = CF_UNICODETEXT;
android_cliprdr_send_data_request(cb, CF_UNICODETEXT);
}
else if (android_cliprdr_has_format(cb->formats, cb->num_formats, CB_FORMAT_HTML))
{
cb->data_format = CB_FORMAT_HTML;
android_cliprdr_send_data_request(cb, CB_FORMAT_HTML);
}
}
static void android_cliprdr_process_text(clipboardContext* cb, BYTE* data, int size)
{
if (size > 0 && data)
{
cb->data = (BYTE*) malloc(size + 1);
memcpy(cb->data, data, size);
cb->data[size] = 0;
cb->data_length = size;
}
}
static void android_cliprdr_process_unicodetext(clipboardContext* cb, BYTE* data, int size)
{
cb->data_length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, size / 2, (CHAR**) &(cb->data), 0, NULL, NULL);
crlf2lf(cb->data, &cb->data_length);
}
static void android_cliprdr_process_cb_data_response_event(clipboardContext* cb, RDP_CB_DATA_RESPONSE_EVENT* event)
{
DEBUG_ANDROID("size=%d", event->size);
if (event->size > 0)
{
if (cb->data)
{
free(cb->data);
cb->data = NULL;
cb->data_length = 0;
}
switch (cb->data_format)
{
case CF_TEXT:
android_cliprdr_process_text(cb, event->data, event->size - 1);
break;
case CF_UNICODETEXT:
android_cliprdr_process_unicodetext(cb, event->data, event->size - 2);
break;
}
DEBUG_ANDROID("computer_clipboard_data %s ", (char*)cb->data);
if (cb->data)
{
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jstring jdata = jniNewStringUTF(env, cb->data, cb->data_length);
freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", cb->instance, jdata);
(*env)->DeleteLocalRef(env, jdata);
if(attached == JNI_TRUE)
{
jni_detach_thread();
}
jni_detach_thread();
}
}
return 1;
}
void android_process_cliprdr_event(freerdp* inst, wMessage* event)
int android_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
androidContext* ctx = (androidContext*)inst->context;
clipboardContext* cb = (clipboardContext*) ctx->clipboard_context;
if (!cb)
return;
switch (GetMessageType(event->id))
{
case CliprdrChannel_MonitorReady:
android_cliprdr_process_cb_monitor_ready_event(cb);
break;
case CliprdrChannel_FormatList:
android_cliprdr_process_cb_format_list_event(cb, (RDP_CB_FORMAT_LIST_EVENT*) event);
break;
case CliprdrChannel_DataRequest:
android_cliprdr_process_cb_data_request_event(cb, (RDP_CB_DATA_REQUEST_EVENT*) event);
break;
case CliprdrChannel_DataResponse:
android_cliprdr_process_cb_data_response_event(cb, (RDP_CB_DATA_RESPONSE_EVENT*) event);
break;
default:
DEBUG_ANDROID("unknown event type %d", GetMessageType(event->id));
break;
}
return 1;
}
void android_process_cliprdr_send_clipboard_data(freerdp* inst, void* data, int len)
int android_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
androidContext* ctx = (androidContext*)inst->context;
clipboardContext* cb = (clipboardContext*) ctx->clipboard_context;
DEBUG_ANDROID("android_clipboard_data %s ", (char*)data);
if (cb && (data == NULL || cb->android_data == NULL ||
len != cb->android_data_length || memcmp(data, cb->android_data, len)))
{
if (cb->android_data)
{
free(cb->android_data);
cb->android_data = NULL;
cb->android_data_length = 0;
}
if (data)
{
cb->android_data = (BYTE*) malloc(len + 1);
memcpy(cb->android_data, data, len);
cb->android_data[len] = 0;
cb->android_data_length = len;
}
android_cliprdr_send_format_list(cb);
}
return 1;
}
int android_cliprdr_init(androidContext* afc, CliprdrClientContext* cliprdr)
{
cliprdr->custom = (void*) afc;
afc->cliprdr = cliprdr;
afc->clipboard = ClipboardCreate();
afc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
cliprdr->MonitorReady = android_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = android_cliprdr_server_capabilities;
cliprdr->ServerFormatList = android_cliprdr_server_format_list;
cliprdr->ServerFormatListResponse = android_cliprdr_server_format_list_response;
cliprdr->ServerLockClipboardData = android_cliprdr_server_lock_clipboard_data;
cliprdr->ServerUnlockClipboardData = android_cliprdr_server_unlock_clipboard_data;
cliprdr->ServerFormatDataRequest = android_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = android_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = android_cliprdr_server_file_contents_request;
cliprdr->ServerFileContentsResponse = android_cliprdr_server_file_contents_response;
return 1;
}
int android_cliprdr_uninit(androidContext* afc, CliprdrClientContext* cliprdr)
{
cliprdr->custom = NULL;
afc->cliprdr = NULL;
ClipboardDestroy(afc->clipboard);
CloseHandle(afc->clipboardRequestEvent);
return 1;
}

View File

@ -22,9 +22,9 @@
#include "android_freerdp.h"
void android_cliprdr_init(freerdp* inst);
void android_cliprdr_uninit(freerdp* inst);
void android_process_cliprdr_send_clipboard_data(freerdp* inst, void* data, int len);
void android_process_cliprdr_event(freerdp* inst, wMessage* event);
int android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr);
int android_cliprdr_init(androidContext* afc, CliprdrClientContext* cliprdr);
int android_cliprdr_uninit(androidContext* afc, CliprdrClientContext* cliprdr);
#endif /* __ANDROID_CLIPRDR_H__ */

View File

@ -14,11 +14,11 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <sys/select.h>
#include <sys/types.h>
#include <freerdp/freerdp.h>
#include <freerdp/log.h>
@ -115,11 +115,13 @@ ANDROID_EVENT* android_pop_event(ANDROID_EVENT_QUEUE * queue)
return event;
}
int android_process_event(ANDROID_EVENT_QUEUE * queue, freerdp * inst)
int android_process_event(ANDROID_EVENT_QUEUE* queue, freerdp* inst)
{
ANDROID_EVENT* event;
rdpContext* context = inst->context;
androidContext* afc = (androidContext*) context;
while (android_peek_event(queue) != NULL)
while (android_peek_event(queue))
{
event = android_pop_event(queue);
@ -143,8 +145,33 @@ int android_process_event(ANDROID_EVENT_QUEUE * queue, freerdp * inst)
}
else if (event->type == EVENT_TYPE_CLIPBOARD)
{
ANDROID_EVENT_CLIPBOARD* clipboard_event = (ANDROID_EVENT_CLIPBOARD*)event;
android_process_cliprdr_send_clipboard_data(inst, clipboard_event->data, clipboard_event->data_length);
BYTE* data;
UINT32 size;
UINT32 formatId;
ANDROID_EVENT_CLIPBOARD* clipboard_event = (ANDROID_EVENT_CLIPBOARD*) event;
formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING");
size = clipboard_event->data_length;
if (size)
{
data = (BYTE*) malloc(size);
if (!data)
return -1;
CopyMemory(data, clipboard_event->data, size);
ClipboardSetData(afc->clipboard, formatId, (void*) data, size);
}
else
{
ClipboardEmpty(afc->clipboard);
}
android_cliprdr_send_client_format_list(afc->cliprdr);
android_event_clipboard_free(clipboard_event);
}
else if (event->type == EVENT_TYPE_DISCONNECT)

View File

@ -20,12 +20,17 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <freerdp/graphics.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/gfx.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/channels/channels.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/utils/event.h>
#include <freerdp/constants.h>
#include <freerdp/locale/keyboard.h>
#include <freerdp/primitives.h>
@ -39,7 +44,6 @@
#include "android_debug.h"
#include "android_cliprdr.h"
#if defined(WITH_GPROF)
#include "jni/prof.h"
#endif
@ -57,6 +61,45 @@ void android_context_free(freerdp* instance, rdpContext* context)
android_event_queue_uninit(instance);
}
void android_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
{
rdpSettings* settings = context->settings;
androidContext* afc = (androidContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
android_cliprdr_init(afc, (CliprdrClientContext*) e->pInterface);
}
}
void android_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
rdpSettings* settings = context->settings;
androidContext* afc = (androidContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
android_cliprdr_uninit(afc, (CliprdrClientContext*) e->pInterface);
}
}
void android_begin_paint(rdpContext* context)
{
@ -65,7 +108,6 @@ void android_begin_paint(rdpContext* context)
gdi->primary->hdc->hwnd->ninvalid = 0;
}
void android_end_paint(rdpContext* context)
{
androidContext *ctx = (androidContext*)context;
@ -97,7 +139,6 @@ void android_desktop_resize(rdpContext* context)
context->settings->DesktopHeight, context->settings->ColorDepth);
}
BOOL android_pre_connect(freerdp* instance)
{
DEBUG_ANDROID("android_pre_connect");
@ -131,6 +172,12 @@ BOOL android_pre_connect(freerdp* instance)
settings->FrameAcknowledge = 10;
PubSub_SubscribeChannelConnected(instance->context->pubSub,
(pChannelConnectedEventHandler) android_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
(pChannelDisconnectedEventHandler) android_OnChannelDisconnectedEventHandler);
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
freerdp_client_load_addins(instance->context->channels, instance->settings);
@ -166,11 +213,8 @@ static BOOL android_post_connect(freerdp* instance)
instance->update->EndPaint = android_end_paint;
instance->update->DesktopResize = android_desktop_resize;
android_cliprdr_init(instance);
freerdp_channels_post_connect(instance->context->channels, instance);
// send notifications
freerdp_callback("OnConnectionSuccess", "(I)V", instance);
return TRUE;
@ -180,7 +224,6 @@ static void android_post_disconnect(freerdp* instance)
{
gdi_free(instance);
cache_free(instance->context->cache);
android_cliprdr_uninit(instance);
}
BOOL android_authenticate(freerdp* instance, char** username, char** password, char** domain)
@ -196,26 +239,27 @@ BOOL android_authenticate(freerdp* instance, char** username, char** password, c
jobject jstr3 = create_string_builder(env, *password);
jboolean res = freerdp_callback_bool_result("OnAuthenticate", "(ILjava/lang/StringBuilder;Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;)Z", instance, jstr1, jstr2, jstr3);
if(res == JNI_TRUE)
if (res == JNI_TRUE)
{
// read back string values
if(*username != NULL)
if (*username != NULL)
free(*username);
*username = get_string_from_string_builder(env, jstr1);
if(*domain != NULL)
if (*domain != NULL)
free(*domain);
*domain = get_string_from_string_builder(env, jstr2);
if(*password == NULL)
if (*password == NULL)
free(*password);
*password = get_string_from_string_builder(env, jstr3);
}
if(attached == JNI_TRUE)
if (attached == JNI_TRUE)
jni_detach_thread();
return ((res == JNI_TRUE) ? TRUE : FALSE);
@ -239,7 +283,7 @@ BOOL android_verify_certificate(freerdp* instance, char* subject, char* issuer,
jboolean res = freerdp_callback_bool_result("OnVerifyCertificate", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", instance, jstr1, jstr2, jstr3);
if(attached == JNI_TRUE)
if (attached == JNI_TRUE)
jni_detach_thread();
return ((res == JNI_TRUE) ? TRUE : FALSE);
@ -250,30 +294,6 @@ BOOL android_verify_changed_certificate(freerdp* instance, char* subject, char*
return android_verify_certificate(instance, subject, issuer, new_fingerprint);
}
static void android_process_channel_event(rdpChannels* channels, freerdp* instance)
{
wMessage* event;
event = freerdp_channels_pop_event(channels);
if (event)
{
int ev = GetMessageClass(event->id);
switch(ev)
{
case CliprdrChannel_Class:
android_process_cliprdr_event(instance, event);
break;
default:
DEBUG_ANDROID("Unsupported channel event %08X", ev);
break;
}
freerdp_event_free(event);
}
}
static void* jni_input_thread(void* arg)
{
HANDLE event[3];
@ -330,14 +350,13 @@ static void* jni_channels_thread(void* arg)
channels = instance->context->channels;
event = freerdp_channels_get_event_handle(instance);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(instance);
if (!status)
break;
android_process_channel_event(channels, instance);
break;
}
DEBUG_ANDROID("Quit.");
@ -513,14 +532,12 @@ static int android_freerdp_run(freerdp* instance)
DEBUG_ANDROID("Failed to check channel manager file descriptor\n");
break;
}
android_process_channel_event(instance->context->channels, instance);
}
}
DEBUG_ANDROID("Prepare shutdown...");
// issue another OnDisconnecting here in case the disconnect was initiated by the sever and not our client
// issue another OnDisconnecting here in case the disconnect was initiated by the server and not our client
freerdp_callback("OnDisconnecting", "(I)V", instance);
DEBUG_ANDROID("Close channels...");
@ -701,10 +718,10 @@ JNIEXPORT void JNICALL jni_freerdp_set_connection_info(JNIEnv *env, jclass cls,
settings->ServerHostname = strdup(hostname);
if(username && strlen(username) > 0)
if (username && strlen(username) > 0)
settings->Username = strdup(username);
if(password && strlen(password) > 0)
if (password && strlen(password) > 0)
{
settings->Password = strdup(password);
settings->AutoLogonEnabled = TRUE;
@ -712,7 +729,7 @@ JNIEXPORT void JNICALL jni_freerdp_set_connection_info(JNIEnv *env, jclass cls,
settings->Domain = strdup(domain);
if(certname && strlen(certname) > 0)
if (certname && strlen(certname) > 0)
settings->CertificateName = strdup(certname);
settings->ConsoleSession = (console == JNI_TRUE) ? TRUE : FALSE;
@ -823,10 +840,10 @@ JNIEXPORT void JNICALL jni_freerdp_set_advanced_settings(JNIEnv *env, jclass cls
settings->AsyncTransport = async_transport;
settings->AsyncInput = async_input;
if(remote_program && strlen(remote_program) > 0)
if (remote_program && strlen(remote_program) > 0)
settings->AlternateShell = strdup(remote_program);
if(work_dir && strlen(work_dir) > 0)
if (work_dir && strlen(work_dir) > 0)
settings->ShellWorkingDirectory = strdup(work_dir);
(*env)->ReleaseStringUTFChars(env, jRemoteProgram, remote_program);

View File

@ -11,7 +11,12 @@
#define __ANDROID_FREERDP_H
#include <jni.h>
#include <winpr/crt.h>
#include <winpr/clipboard.h>
#include <freerdp/freerdp.h>
#include <freerdp/client/cliprdr.h>
#include "android_event.h"
@ -24,7 +29,14 @@ struct android_context
BOOL is_connected;
void* clipboard_context;
BOOL clipboardSync;
wClipboard* clipboard;
UINT32 numServerFormats;
UINT32 requestedFormatId;
HANDLE clipboardRequestEvent;
CLIPRDR_FORMAT* serverFormats;
CliprdrClientContext* cliprdr;
UINT32 clipboardCapabilities;
};
typedef struct android_context androidContext;