afreerdp: migrate to cliprdr callback interface
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 12 Nov 2014 17:25:12 +0000 (12:25 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 12 Nov 2014 17:25:12 +0000 (12:25 -0500)
client/Android/FreeRDPCore/jni/android_cliprdr.c
client/Android/FreeRDPCore/jni/android_cliprdr.h
client/Android/FreeRDPCore/jni/android_event.c
client/Android/FreeRDPCore/jni/android_freerdp.c
client/Android/FreeRDPCore/jni/android_freerdp.h

index 4bb0df0..f3278b3 100644 (file)
 #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>
 
 #include "android_jni_utils.h"
 #include "android_jni_callback.h"
 
-struct clipboard_context
+int android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
 {
-       freerdp* instance;
-       rdpChannels* channels;
-       
-       /* server->client data */
-       UINT32* formats;
-       int num_formats;        
-       BYTE* data;
-       UINT32 data_format;
-       int data_length;
-
-       /* client->server data */
-       UINT32* android_formats;
-       int   android_num_formats;
-       BYTE* android_data;
-       int android_data_length;
-};
-typedef struct clipboard_context clipboardContext;
-
-static BYTE* lf2crlf(BYTE* data, int* size)
-{
-       BYTE c;
-       BYTE* outbuf;
-       BYTE* out;
-       BYTE* in_end;
-       BYTE* in;
-       int out_size;
-
-       out_size = (*size) * 2 + 1;
-       outbuf = (BYTE*) malloc(out_size);
-       ZeroMemory(outbuf, out_size);
-
-       out = outbuf;
-       in = data;
-       in_end = data + (*size);
-
-       while (in < in_end)
-       {
-               c = *in++;
-               if (c == '\n')
-               {
-                       *out++ = '\r';
-                       *out++ = '\n';
-               }
-               else
-               {
-                       *out++ = c;
-               }
-       }
+       UINT32 index;
+       UINT32 formatId;
+       UINT32 numFormats;
+       UINT32* pFormatIds;
+       const char* formatName;
+       CLIPRDR_FORMAT* formats;
+       CLIPRDR_FORMAT_LIST formatList;
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-       *out++ = 0;
-       *size = out - outbuf;
+       ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
 
-       return outbuf;
-}
+       pFormatIds = NULL;
+       numFormats = ClipboardGetFormatIds(afc->clipboard, &pFormatIds);
 
-static void crlf2lf(BYTE* data, int* size)
-{
-       BYTE c;
-       BYTE* out;
-       BYTE* in;
-       BYTE* in_end;
+       formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT));
 
-       out = data;
-       in = data;
-       in_end = data + (*size);
+       if (!formats)
+               return -1;
 
-       while (in < in_end)
+       for (index = 0; index < numFormats; index++)
        {
-               c = *in++;
+               formatId = pFormatIds[index];
+               formatName = ClipboardGetFormatName(afc->clipboard, formatId);
 
-               if (c != '\r')
-                       *out++ = c;
-       }
+               formats[index].formatId = formatId;
+               formats[index].formatName = NULL;
 
-       *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 (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;
+               if ((formatId > CF_MAX) && formatName)
+                       formats[index].formatName = _strdup(formatName);
        }
-}
 
-static void android_cliprdr_send_null_format_list(clipboardContext* cb)
-{
-       RDP_CB_FORMAT_LIST_EVENT* event;
+       formatList.msgFlags = CB_RESPONSE_OK;
+       formatList.numFormats = numFormats;
+       formatList.formats = formats;
 
-       event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
-               CliprdrChannel_FormatList, NULL, NULL);
+       afc->cliprdr->ClientFormatList(afc->cliprdr, &formatList);
 
-       event->num_formats = 0;
+       free(pFormatIds);
+       free(formats);
 
-       freerdp_channels_send_event(cb->channels, (wMessage*) event);
+       return 1;
 }
 
-static void android_cliprdr_send_supported_format_list(clipboardContext* cb)
+int android_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
 {
-       int i;
-       RDP_CB_FORMAT_LIST_EVENT* event;
+       CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-       event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
-               CliprdrChannel_FormatList, NULL, NULL);
+       ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
 
-       event->formats = (UINT32*) calloc(cb->android_num_formats, sizeof(UINT32));
-       event->num_formats = cb->android_num_formats;
+       formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
+       formatDataRequest.msgFlags = 0;
 
-       for (i = 0; i < cb->android_num_formats; i++)
-       {
-               event->formats[i] = cb->android_formats[i];
-       }
+       formatDataRequest.requestedFormatId = formatId;
+       afc->requestedFormatId = formatId;
+       ResetEvent(afc->clipboardRequestEvent);
 
-       freerdp_channels_send_event(cb->channels, (wMessage*) event);
-}
+       cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
 
-static void android_cliprdr_send_format_list(clipboardContext* cb)
-{
-       if (cb->android_data)
-       {
-               android_cliprdr_send_supported_format_list(cb);
-       }
-       else
-       {
-               android_cliprdr_send_null_format_list(cb);
-       }
+       return 1;
 }
 
-static void android_cliprdr_send_data_request(clipboardContext* cb, UINT32 format)
+int android_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
 {
-       RDP_CB_DATA_REQUEST_EVENT* event;
+       CLIPRDR_CAPABILITIES capabilities;
+       CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
 
-       event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
-               CliprdrChannel_DataRequest, NULL, NULL);
+       capabilities.cCapabilitiesSets = 1;
+       capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
 
-       event->format = format;
+       generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
+       generalCapabilitySet.capabilitySetLength = 12;
 
-       freerdp_channels_send_event(cb->channels, (wMessage*) event);
-}
-
-static void android_cliprdr_send_data_response(clipboardContext* cb, BYTE* data, int size)
-{
-       RDP_CB_DATA_RESPONSE_EVENT* event;
-
-       event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
-               CliprdrChannel_DataResponse, NULL, NULL);
+       generalCapabilitySet.version = CB_CAPS_VERSION_2;
+       generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
 
-       event->data = data;
-       event->size = size;
+       cliprdr->ClientCapabilities(cliprdr, &capabilities);
 
-       freerdp_channels_send_event(cb->channels, (wMessage*) event);
+       return 1;
 }
 
-static void android_cliprdr_send_null_data_response(clipboardContext* cb)
+int android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady)
 {
-       android_cliprdr_send_data_response(cb, NULL, 0);
-}
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-static void android_cliprdr_process_cb_monitor_ready_event(clipboardContext* cb)
-{
-       android_cliprdr_send_format_list(cb);
+       afc->clipboardSync = TRUE;
+       android_cliprdr_send_client_capabilities(cliprdr);
+       android_cliprdr_send_client_format_list(cliprdr);
+
+       return 1;
 }
 
-static BYTE* android_cliprdr_process_requested_unicodetext(BYTE* data, int* size)
+int android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities)
 {
-       char* inbuf;
-       WCHAR* outbuf = NULL;
-       int out_size;
+       UINT32 index;
+       CLIPRDR_CAPABILITY_SET* capabilitySet;
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-       inbuf = (char*) lf2crlf(data, size);
-       out_size = ConvertToUnicode(CP_UTF8, 0, inbuf, -1, &outbuf, 0);
-       free(inbuf);
+       for (index = 0; index < capabilities->cCapabilitiesSets; index++)
+       {
+               capabilitySet = &(capabilities->capabilitySets[index]);
 
-       *size = (int) ((out_size + 1) * 2);
+               if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
+                   (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
+               {
+                       CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet
+                       = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
 
-       return (BYTE*) outbuf;
+                       afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
+                       break;
+               }
+       }
+
+       return 1;
 }
 
-static BYTE* android_cliprdr_process_requested_text(BYTE* data, int* size)
+int android_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList)
 {
-       BYTE* outbuf;
+       UINT32 index;
+       CLIPRDR_FORMAT* format;
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-       outbuf = lf2crlf(data, size);
+       if (afc->serverFormats)
+       {
+               for (index = 0; index < afc->numServerFormats; index++)
+               {
+                       free(afc->serverFormats[index].formatName);
+               }
 
-       return outbuf;
-}
+               free(afc->serverFormats);
+               afc->serverFormats = NULL;
+               afc->numServerFormats = 0;
+       }
 
-static void android_cliprdr_process_cb_data_request_event(clipboardContext* cb, RDP_CB_DATA_REQUEST_EVENT* event)
-{
-       int i;
+       if (formatList->numFormats < 1)
+               return 1;
 
-       DEBUG_ANDROID("format %d", event->format);
+       afc->numServerFormats = formatList->numFormats;
+       afc->serverFormats = (CLIPRDR_FORMAT*) calloc(afc->numServerFormats, sizeof(CLIPRDR_FORMAT));
 
-       for (i = 0; i < cb->android_num_formats; i++)
-       {
-               if (event->format == cb->android_formats[i])
-                       break;
-       }
+       if (!afc->serverFormats)
+               return -1;
 
-       if (i >= cb->android_num_formats)
+       for (index = 0; index < afc->numServerFormats; index++)
        {
-               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);
+               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);
        }
-       else
+
+       for (index = 0; index < afc->numServerFormats; index++)
        {
-               BYTE* outbuf = NULL;
-               int size = cb->android_data_length;
+               format = &(afc->serverFormats[index]);
 
-               switch (event->format)
+               if (format->formatId == CF_UNICODETEXT)
                {
-                       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;
+                       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;
                }
-
-               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);
+
+       return 1;
 }
 
-static BOOL android_cliprdr_has_format(UINT32* formats, int num_formats, UINT32 format)
+int android_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
 {
-       int i;
+       return 1;
+}
 
-       for (i = 0; i < num_formats; i++)
-       {
-               if (formats[i] == format)
-                       return TRUE;
-       }
+int android_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
+{
+       return 1;
+}
 
-       return FALSE;
+int android_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
+{
+       return 1;
 }
 
-static void android_cliprdr_process_cb_format_list_event(clipboardContext* cb, RDP_CB_FORMAT_LIST_EVENT* event)
+int android_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
 {
-       if (cb->data)
-       {
-               free(cb->data);
-               cb->data = NULL;
-               cb->data_length = 0;
-       }
+       BYTE* data;
+       UINT32 size;
+       UINT32 formatId;
+       CLIPRDR_FORMAT_DATA_RESPONSE response;
+       androidContext* afc = (androidContext*) cliprdr->custom;
 
-       if (cb->formats)
-               free(cb->formats);
+       ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
 
-       cb->data_format = 0;
-       cb->formats = event->formats;
-       cb->num_formats = event->num_formats;
-       event->formats = NULL;
-       event->num_formats = 0;
+       formatId = formatDataRequest->requestedFormatId;
+       data = (BYTE*) ClipboardGetData(afc->clipboard, formatId, &size);
 
-       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))
+       response.msgFlags = CB_RESPONSE_OK;
+       response.dataLen = size;
+       response.requestedFormatData = data;
+
+       if (!data)
        {
-               cb->data_format = CB_FORMAT_HTML;
-               android_cliprdr_send_data_request(cb, CB_FORMAT_HTML);
+               response.msgFlags = CB_RESPONSE_FAIL;
+               response.dataLen = 0;
+               response.requestedFormatData = NULL;
        }
+
+       cliprdr->ClientFormatDataResponse(cliprdr, &response);
+
+       free(data);
+
+       return 1;
 }
 
-static void android_cliprdr_process_text(clipboardContext* cb, BYTE* data, int size)
+int android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
 {
-       if (size > 0 && data)
+       BYTE* data;
+       UINT32 size;
+       UINT32 index;
+       UINT32 formatId;
+       CLIPRDR_FORMAT* format = NULL;
+       androidContext* afc = (androidContext*) cliprdr->custom;
+       freerdp* instance = ((rdpContext*) afc)->instance;
+
+       for (index = 0; index < afc->numServerFormats; index++)
        {
-               cb->data = (BYTE*) malloc(size + 1);
-               memcpy(cb->data, data, size);
-               cb->data[size] = 0;
-               cb->data_length = size;
+               if (afc->requestedFormatId == afc->serverFormats[index].formatId)
+                       format = &(afc->serverFormats[index]);
        }
-}
 
-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);
-}
+       if (!format)
+       {
+               SetEvent(afc->clipboardRequestEvent);
+               return -1;
+       }
 
-static void android_cliprdr_process_cb_data_response_event(clipboardContext* cb, RDP_CB_DATA_RESPONSE_EVENT* event)
-{
-       DEBUG_ANDROID("size=%d", event->size);  
+       if (format->formatName)
+               formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
+       else
+               formatId = format->formatId;
 
-       if (event->size > 0)
+       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))
        {
-               if (cb->data)
-               {
-                       free(cb->data);
-                       cb->data = NULL;
-                       cb->data_length = 0;
-               }
+               JNIEnv* env;
+               jstring jdata;
+               jboolean attached;
 
-               switch (cb->data_format)
-               {
-                       case CF_TEXT:
-                               android_cliprdr_process_text(cb, event->data, event->size - 1);
-                               break;
+               formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING");
 
-                       case CF_UNICODETEXT:
-                               android_cliprdr_process_unicodetext(cb, event->data, event->size - 2);
-                               break;
-               }
+               data = (void*) ClipboardGetData(afc->clipboard, formatId, &size);
 
-               DEBUG_ANDROID("computer_clipboard_data %s ", (char*)cb->data);          
+               attached = jni_attach_thread(&env);
+               jdata = jniNewStringUTF(env, data, size);
 
-               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", instance, jdata);
 
-                       freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", cb->instance, jdata);
+               (*env)->DeleteLocalRef(env, jdata);
 
-                       (*env)->DeleteLocalRef(env, jdata);
-                       if(attached == JNI_TRUE)
-                       {
-                               jni_detach_thread();
-                       }
+               if (attached == JNI_TRUE)
+               {
+                       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;
+       return 1;
+}
 
-               case CliprdrChannel_DataResponse:
-                       android_cliprdr_process_cb_data_response_event(cb, (RDP_CB_DATA_RESPONSE_EVENT*) event);
-                       break;
+int android_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
+{
+       return 1;
+}
 
-               default:
-                       DEBUG_ANDROID("unknown event type %d", GetMessageType(event->id));
-                       break;
-       }
+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;
 }
 
-void android_process_cliprdr_send_clipboard_data(freerdp* inst, void* data, int len)
+int android_cliprdr_uninit(androidContext* afc, CliprdrClientContext* cliprdr)
 {
-       androidContext* ctx = (androidContext*)inst->context;
-       clipboardContext* cb = (clipboardContext*) ctx->clipboard_context;
+       cliprdr->custom = NULL;
+       afc->cliprdr = NULL;
 
-       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;
-               }
+       ClipboardDestroy(afc->clipboard);
+       CloseHandle(afc->clipboardRequestEvent);
 
-               android_cliprdr_send_format_list(cb);
-       }
+       return 1;
 }
index 233bff3..b431815 100644 (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__ */
index 15452fa..e63511c 100644 (file)
 #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)
index 4d75b52..c1e9594 100644 (file)
 #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);
index 91d9c93..dd36a65 100644 (file)
 #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;