mfreerdp: rewrite and update clipboard code
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 5 Nov 2014 22:14:32 +0000 (17:14 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 5 Nov 2014 22:14:32 +0000 (17:14 -0500)
client/Mac/CMakeLists.txt
client/Mac/Clipboard.h [new file with mode: 0644]
client/Mac/Clipboard.m [new file with mode: 0644]
client/Mac/MRDPView.h
client/Mac/MRDPView.m
client/Mac/mf_client.m
client/Mac/mfreerdp.h

index 863ec82..8f0aca4 100644 (file)
@@ -32,6 +32,7 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES
        MRDPCursor.m
        MRDPView.m
        Keyboard.m
+       Clipboard.m
        PasswordDialog.m)
 
 list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES})
@@ -42,6 +43,7 @@ set(${MODULE_PREFIX}_HEADERS
        MRDPCursor.h
        MRDPView.h
        Keyboard.h
+       Clipboard.h
        PasswordDialog.h)
 
 set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings")
diff --git a/client/Mac/Clipboard.h b/client/Mac/Clipboard.h
new file mode 100644 (file)
index 0000000..2445ab8
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ *
+ * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "mfreerdp.h"
+#import "mf_client.h"
+
+#import "freerdp/freerdp.h"
+#import "freerdp/channels/channels.h"
+#import "freerdp/client/cliprdr.h"
+
+int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr);
+
+void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr);
+void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr);
diff --git a/client/Mac/Clipboard.m b/client/Mac/Clipboard.m
new file mode 100644 (file)
index 0000000..d0e9575
--- /dev/null
@@ -0,0 +1,328 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ *
+ * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "Clipboard.h"
+
+int mac_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;
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       
+       ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
+       
+       pFormatIds = NULL;
+       numFormats = ClipboardGetFormatIds(mfc->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(mfc->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;
+       
+       mfc->cliprdr->ClientFormatList(mfc->cliprdr, &formatList);
+       
+       free(pFormatIds);
+       free(formats);
+       
+       return 1;
+}
+
+int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
+{
+       CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       
+       ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
+       
+       formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
+       formatDataRequest.msgFlags = 0;
+       
+       formatDataRequest.requestedFormatId = formatId;
+       mfc->requestedFormatId = formatId;
+       ResetEvent(mfc->clipboardRequestEvent);
+       
+       cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
+       
+       return 1;
+}
+
+int mac_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 mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady)
+{
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       
+       mfc->clipboardSync = TRUE;
+       mac_cliprdr_send_client_capabilities(cliprdr);
+       mac_cliprdr_send_client_format_list(cliprdr);
+       
+       return 1;
+}
+
+int mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities)
+{
+       UINT32 index;
+       CLIPRDR_CAPABILITY_SET* capabilitySet;
+       mfContext* mfc = (mfContext*) 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;
+                       
+                       mfc->clipboardCapabilities = generalCapabilitySet->generalFlags;
+                       break;
+               }
+       }
+       
+       return 1;
+}
+
+int mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList)
+{
+       UINT32 index;
+       CLIPRDR_FORMAT* format;
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       
+       if (mfc->serverFormats)
+       {
+               for (index = 0; index < mfc->numServerFormats; index++)
+               {
+                       free(mfc->serverFormats[index].formatName);
+               }
+               
+               free(mfc->serverFormats);
+               mfc->serverFormats = NULL;
+               mfc->numServerFormats = 0;
+       }
+       
+       if (formatList->numFormats < 1)
+               return 1;
+       
+       mfc->numServerFormats = formatList->numFormats;
+       mfc->serverFormats = (CLIPRDR_FORMAT*) calloc(mfc->numServerFormats, sizeof(CLIPRDR_FORMAT));
+       
+       if (!mfc->serverFormats)
+               return -1;
+       
+       for (index = 0; index < mfc->numServerFormats; index++)
+       {
+               mfc->serverFormats[index].formatId = formatList->formats[index].formatId;
+               mfc->serverFormats[index].formatName = NULL;
+               
+               if (formatList->formats[index].formatName)
+                       mfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
+       }
+       
+       for (index = 0; index < mfc->numServerFormats; index++)
+       {
+               format = &(mfc->serverFormats[index]);
+               
+               if (format->formatId == CF_UNICODETEXT)
+               {
+                       mac_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
+                       break;
+               }
+               else if (format->formatId == CF_TEXT)
+               {
+                       mac_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
+                       break;
+               }
+       }
+       
+       return 1;
+}
+
+int mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
+{
+       return 1;
+}
+
+int mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
+{
+       return 1;
+}
+
+int mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
+{
+       return 1;
+}
+
+int mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
+{
+       BYTE* data;
+       UINT32 size;
+       UINT32 formatId;
+       CLIPRDR_FORMAT_DATA_RESPONSE response;
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       
+       ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
+       
+       formatId = formatDataRequest->requestedFormatId;
+       data = (BYTE*) ClipboardGetData(mfc->clipboard, formatId, &size);
+       
+       response.msgFlags = CB_RESPONSE_OK;
+       response.dataLen = size;
+       response.requestedFormatData = data;
+       
+       if (!data)
+       {
+               response.msgFlags = CB_RESPONSE_FAIL;
+               response.dataLen = 0;
+               response.requestedFormatData = NULL;
+       }
+       
+       cliprdr->ClientFormatDataResponse(cliprdr, &response);
+       
+       free(data);
+       
+       return 1;
+}
+
+int mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
+{
+       BYTE* data;
+       UINT32 size;
+       UINT32 index;
+       UINT32 formatId;
+       CLIPRDR_FORMAT* format = NULL;
+       mfContext* mfc = (mfContext*) cliprdr->custom;
+       MRDPView* view = (MRDPView*) mfc->view;
+       
+       for (index = 0; index < mfc->numServerFormats; index++)
+       {
+               if (mfc->requestedFormatId == mfc->serverFormats[index].formatId)
+                       format = &(mfc->serverFormats[index]);
+       }
+       
+       if (!format)
+       {
+               SetEvent(mfc->clipboardRequestEvent);
+               return -1;
+       }
+       
+       if (format->formatName)
+               formatId = ClipboardRegisterFormat(mfc->clipboard, format->formatName);
+       else
+               formatId = format->formatId;
+       
+       size = formatDataResponse->dataLen;
+       data = (BYTE*) malloc(size);
+       CopyMemory(data, formatDataResponse->requestedFormatData, size);
+       
+       ClipboardSetData(mfc->clipboard, formatId, data, size);
+       
+       SetEvent(mfc->clipboardRequestEvent);
+       
+       if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
+       {
+               formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
+               
+               data = (void*) ClipboardGetData(mfc->clipboard, formatId, &size);
+               NSString* str = [[NSString alloc] initWithBytes: (void*) data length:size encoding:NSUTF8StringEncoding];
+               free(data);
+               
+               NSArray* types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil];
+               [view->pasteboard_wr declareTypes:types owner:view];
+               [view->pasteboard_wr setString:str forType:NSStringPboardType];
+       }
+       
+       return 1;
+}
+
+int mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
+{
+       return 1;
+}
+
+int mac_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
+{
+       return 1;
+}
+
+void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr)
+{
+       cliprdr->custom = (void*) mfc;
+       mfc->cliprdr = cliprdr;
+       
+       mfc->clipboard = ClipboardCreate();
+       mfc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+       
+       cliprdr->MonitorReady = mac_cliprdr_monitor_ready;
+       cliprdr->ServerCapabilities = mac_cliprdr_server_capabilities;
+       cliprdr->ServerFormatList = mac_cliprdr_server_format_list;
+       cliprdr->ServerFormatListResponse = mac_cliprdr_server_format_list_response;
+       cliprdr->ServerLockClipboardData = mac_cliprdr_server_lock_clipboard_data;
+       cliprdr->ServerUnlockClipboardData = mac_cliprdr_server_unlock_clipboard_data;
+       cliprdr->ServerFormatDataRequest = mac_cliprdr_server_format_data_request;
+       cliprdr->ServerFormatDataResponse = mac_cliprdr_server_format_data_response;
+       cliprdr->ServerFileContentsRequest = mac_cliprdr_server_file_contents_request;
+       cliprdr->ServerFileContentsResponse = mac_cliprdr_server_file_contents_response;
+}
+
+void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr)
+{
+       cliprdr->custom = NULL;
+       mfc->cliprdr = NULL;
+       
+       ClipboardDestroy(mfc->clipboard);
+       CloseHandle(mfc->clipboardRequestEvent);
+}
index 70ef313..7231d06 100644 (file)
@@ -51,8 +51,8 @@
        BOOL skipMoveWindowOnce;
        
 @public
-       NSPasteboard* pasteboard_rd; /* for reading from clipboard */
-       NSPasteboard* pasteboard_wr; /* for writing to clipboard */
+       NSPasteboard* pasteboard_rd;
+       NSPasteboard* pasteboard_wr;
        int pasteboard_changecount;
        int pasteboard_format;
        int is_connected;
@@ -63,6 +63,8 @@
 - (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height;
 
 - (void) onPasteboardTimerFired :(NSTimer *) timer;
+- (void) pause;
+- (void) resume;
 - (void) releaseResources;
 
 @property (assign) int is_connected;
index ded7f9b..4d96325 100644 (file)
@@ -23,6 +23,7 @@
 #import "mfreerdp.h"
 #import "MRDPView.h"
 #import "MRDPCursor.h"
+#import "Clipboard.h"
 #import "PasswordDialog.h"
 
 #include <winpr/crt.h>
@@ -39,8 +40,6 @@
 #import "freerdp/gdi/dc.h"
 #import "freerdp/gdi/region.h"
 #import "freerdp/graphics.h"
-#import "freerdp/utils/event.h"
-#import "freerdp/client/cliprdr.h"
 #import "freerdp/client/file.h"
 #import "freerdp/client/cmdline.h"
 #import "freerdp/log.h"
@@ -59,39 +58,9 @@ void mac_desktop_resize(rdpContext* context);
 
 static void update_activity_cb(freerdp* instance);
 static void input_activity_cb(freerdp* instance);
-static void channel_activity_cb(freerdp* instance);
-
-int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data);
-int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
-
-void process_cliprdr_event(freerdp* instance, wMessage* event);
-void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event);
-void cliprdr_send_data_request(freerdp* instance, UINT32 format);
-void cliprdr_process_cb_monitor_ready_event(freerdp* inst);
-void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event);
-void cliprdr_process_text(freerdp* instance, BYTE* data, int len);
-void cliprdr_send_supported_format_list(freerdp* instance);
-int register_channel_fds(int* fds, int count, freerdp* instance);
 
 DWORD mac_client_thread(void* param);
 
-struct cursor
-{
-       rdpPointer* pointer;
-       BYTE* cursor_data;
-       void* bmiRep; /* NSBitmapImageRep */
-       void* nsCursor; /* NSCursor */
-       void* nsImage; /* NSImage */
-};
-
-struct rgba_data
-{
-       char red;
-       char green;
-       char blue;
-       char alpha;
-};
-
 @implementation MRDPView
 
 @synthesize is_connected;
@@ -183,43 +152,6 @@ DWORD mac_client_input_thread(void* param)
        return 0;
 }
 
-DWORD mac_client_channels_thread(void* param)
-{
-       int status;
-       wMessage* event;
-       HANDLE channelsEvent;
-       rdpChannels* channels;
-       rdpContext* context = (rdpContext*) param;
-       
-       channels = context->channels;
-       channelsEvent = freerdp_channels_get_event_handle(context->instance);
-       
-       while (WaitForSingleObject(channelsEvent, INFINITE) == WAIT_OBJECT_0)
-       {
-               status = freerdp_channels_process_pending_messages(context->instance);
-               
-               if (!status)
-                       break;
-               
-               event = freerdp_channels_pop_event(context->channels);
-               
-               if (event)
-               {
-                       switch (GetMessageClass(event->id))
-                       {
-                               case CliprdrChannel_Class:
-                                       process_cliprdr_event(context->instance, event);
-                                       break;
-                       }
-                       
-                       freerdp_event_free(event);
-               }
-       }
-       
-       ExitThread(0);
-       return 0;
-}
-
 DWORD mac_client_thread(void* param)
 {
        @autoreleasepool
@@ -231,7 +163,6 @@ DWORD mac_client_thread(void* param)
                HANDLE updateEvent;
                HANDLE updateThread;
                HANDLE channelsEvent;
-               HANDLE channelsThread;
                
                DWORD nCount;
                rdpContext* context = (rdpContext*) param;
@@ -272,14 +203,7 @@ DWORD mac_client_thread(void* param)
                        events[nCount++] = inputEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
                }
                
-               if (settings->AsyncChannels)
-               {
-                       channelsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_channels_thread, context, 0, NULL);
-               }
-               else
-               {
-                       events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance);
-               }
+               events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance);
                
                while (1)
                {
@@ -307,12 +231,9 @@ DWORD mac_client_thread(void* param)
                                }
                        }
                        
-                       if (!settings->AsyncChannels)
+                       if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0)
                        {
-                               if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0)
-                               {
-                                       channel_activity_cb(instance);
-                               }
+                               freerdp_channels_process_pending_messages(instance);
                        }
                }
                
@@ -332,12 +253,6 @@ DWORD mac_client_thread(void* param)
                        CloseHandle(inputThread);
                }
                
-               if (settings->AsyncChannels)
-               {
-                       WaitForSingleObject(channelsThread, INFINITE);
-                       CloseHandle(channelsThread);
-               }
-               
                ExitThread(0);
                return 0;
        }
@@ -798,21 +713,87 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
 
 - (void) onPasteboardTimerFired :(NSTimer*) timer
 {
-       int i;
-       NSArray* types;
+       BYTE* data;
+       UINT32 size;
+       UINT32 formatId;
+       BOOL formatMatch;
+       int changeCount;
+       NSData* formatData;
+       const char* formatType;
+       NSPasteboardItem* item;
+       
+       changeCount = (int) [pasteboard_rd changeCount];
+       
+       if (changeCount == pasteboard_changecount)
+               return;
+       
+       pasteboard_changecount = changeCount;
+       
+       NSArray* items = [pasteboard_rd pasteboardItems];
+               
+       if ([items count] < 1)
+               return;
+       
+       item = [items objectAtIndex:0];
+       
+       /**
+        * System-Declared Uniform Type Identifiers:
+        * https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
+        */
        
-       i = (int) [pasteboard_rd changeCount];
+       formatMatch = FALSE;
        
-       if (i != pasteboard_changecount)
+       for (NSString* type in [item types])
        {
-               pasteboard_changecount = i;
-               types = [NSArray arrayWithObject:NSStringPboardType];
-               NSString *str = [pasteboard_rd availableTypeFromArray:types];
-               if (str != nil)
+               formatType = [type UTF8String];
+               
+               if (strcmp(formatType, "public.utf8-plain-text") == 0)
                {
-                       cliprdr_send_supported_format_list(instance);
+                       formatData = [item dataForType:type];
+                       formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
+               
+                       size = (UINT32) [formatData length];
+                       
+                       data = (BYTE*) malloc(size);
+                       [formatData getBytes:data length:size];
+                       
+                       ClipboardSetData(mfc->clipboard, formatId, (void*) data, size);
+                       formatMatch = TRUE;
+                       
+                       break;
                }
        }
+       
+       if (!formatMatch)
+               ClipboardEmpty(mfc->clipboard);
+       
+       if (mfc->clipboardSync)
+               mac_cliprdr_send_client_format_list(mfc->cliprdr);
+}
+
+- (void) pause
+{
+       dispatch_async(dispatch_get_main_queue(), ^{
+               [self->pasteboard_timer invalidate];
+       });
+       
+       NSArray* trackingAreas = self.trackingAreas;
+       
+       for (NSTrackingArea* ta in trackingAreas)
+       {
+               [self removeTrackingArea:ta];
+       }
+}
+
+- (void)resume
+{
+       dispatch_async(dispatch_get_main_queue(), ^{
+               self->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
+       });
+       
+       NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
+       [self addTrackingArea:trackingArea];
+       [trackingArea release];
 }
 
 - (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height
@@ -826,6 +807,7 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
 void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
 {
        rdpSettings* settings = context->settings;
+       mfContext* mfc = (mfContext*) context;
        
        if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
        {
@@ -836,6 +818,10 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve
                if (settings->SoftwareGdi)
                        gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface);
        }
+       else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
+       {
+               mac_cliprdr_init(mfc, (CliprdrClientContext*) e->pInterface);
+       }
        else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
        {
                
@@ -845,6 +831,7 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve
 void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
 {
        rdpSettings* settings = context->settings;
+       mfContext* mfc = (mfContext*) context;
        
        if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
        {
@@ -855,6 +842,10 @@ void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnec
                if (settings->SoftwareGdi)
                        gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface);
        }
+       else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
+       {
+               mac_cliprdr_uninit(mfc, (CliprdrClientContext*) e->pInterface);
+       }
        else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
        {
                
@@ -963,9 +954,12 @@ BOOL mac_post_connect(freerdp* instance)
        view->pasteboard_wr = [NSPasteboard generalPasteboard];
        
        /* setup pasteboard for read operations */
-       view->pasteboard_rd = [NSPasteboard generalPasteboard];
-       view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount];
-       view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
+       dispatch_async(dispatch_get_main_queue(), ^{
+               view->pasteboard_rd = [NSPasteboard generalPasteboard];
+               view->pasteboard_changecount = -1;
+       });
+       
+       [view resume];
        
        mfc->appleKeyboardType = mac_detect_keyboard_type();
 
@@ -1272,212 +1266,6 @@ static void input_activity_cb(freerdp* instance)
        }
 }
 
-static void channel_activity_cb(freerdp* instance)
-{
-       wMessage* event;
-
-       freerdp_channels_process_pending_messages(instance);
-       event = freerdp_channels_pop_event(instance->context->channels);
-
-       if (event)
-       {
-               WLog_DBG(TAG,  "channel_activity_cb: message %d", event->id);
-
-               switch (GetMessageClass(event->id))
-               {
-               case CliprdrChannel_Class:
-                       process_cliprdr_event(instance, event);
-                       break;
-               }
-
-               freerdp_event_free(event);
-       }
-}
-
-int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data)
-{
-       rdpChannels* channels = (rdpChannels*) user_data;
-       
-       freerdp_channels_load_plugin(channels, settings, name, plugin_data);
-       
-       return 1;
-}
-
-/*
- * stuff related to clipboard redirection
- */
-
-void cliprdr_process_cb_data_request_event(freerdp* instance)
-{
-       int len;
-       NSArray* types;
-       RDP_CB_DATA_RESPONSE_EVENT* event;
-       mfContext* mfc = (mfContext*) instance->context;
-       MRDPView* view = (MRDPView*) mfc->view;
-
-       event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL);
-       
-       types = [NSArray arrayWithObject:NSStringPboardType];
-       NSString* str = [view->pasteboard_rd availableTypeFromArray:types];
-       
-       if (str == nil)
-       {
-               event->data = NULL;
-               event->size = 0;
-       }
-       else
-       {
-               NSString* data = [view->pasteboard_rd stringForType:NSStringPboardType];
-               len = (int) ([data length] * 2 + 2);
-               event->data = malloc(len);
-               [data getCString:(char *) event->data maxLength:len encoding:NSUnicodeStringEncoding];
-               event->size = len;
-       }
-       
-       freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
-}
-
-void cliprdr_send_data_request(freerdp* instance, UINT32 format)
-{
-       RDP_CB_DATA_REQUEST_EVENT* event;
-       
-       event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataRequest, NULL, NULL);
-       
-       event->format = format;
-       freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
-}
-
-/**
- * at the moment, only the following formats are supported
- *    CF_TEXT
- *    CF_UNICODETEXT
- */
-
-void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event)
-{
-       NSString* str;
-       NSArray* types;
-       mfContext* mfc = (mfContext*) instance->context;
-       MRDPView* view = (MRDPView*) mfc->view;
-
-       if (event->size == 0)
-               return;
-       
-       if (view->pasteboard_format == CF_TEXT || view->pasteboard_format == CF_UNICODETEXT)
-       {
-               str = [[NSString alloc] initWithCharacters:(unichar *) event->data length:event->size / 2];
-               types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil];
-               [view->pasteboard_wr declareTypes:types owner:mfc->view];
-               [view->pasteboard_wr setString:str forType:NSStringPboardType];
-       }
-}
-
-void cliprdr_process_cb_monitor_ready_event(freerdp* instance)
-{
-       wMessage* event;
-       RDP_CB_FORMAT_LIST_EVENT* format_list_event;
-       
-       event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
-       
-       format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
-       format_list_event->num_formats = 0;
-       
-       freerdp_channels_send_event(instance->context->channels, event);
-}
-
-/**
- * list of supported clipboard formats; currently only the following are supported
- *    CF_TEXT
- *    CF_UNICODETEXT
- */
-
-void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event)
-{
-       int i;
-       mfContext* mfc = (mfContext*) instance->context;
-       MRDPView* view = (MRDPView*) mfc->view;
-
-       if (event->num_formats == 0)
-               return;
-       
-       for (i = 0; i < event->num_formats; i++)
-       {
-               switch (event->formats[i])
-               {
-               case CF_TEXT:
-               case CF_UNICODETEXT:
-                       view->pasteboard_format = CF_UNICODETEXT;
-                       cliprdr_send_data_request(instance, CF_UNICODETEXT);
-                       return;
-                       break;
-               }
-       }
-}
-
-void process_cliprdr_event(freerdp* instance, wMessage* event)
-{
-       if (event)
-       {
-               switch (GetMessageType(event->id))
-               {
-               /*
-                                * Monitor Ready PDU is sent by server to indicate that it has been
-                                * initialized and is ready. This PDU is transmitted by the server after it has sent
-                                * Clipboard Capabilities PDU
-                                */
-               case CliprdrChannel_MonitorReady:
-                       cliprdr_process_cb_monitor_ready_event(instance);
-                       break;
-
-                       /*
-                                * The Format List PDU is sent either by the client or the server when its
-                                * local system clipboard is updated with new clipboard data. This PDU
-                                * contains the Clipboard Format ID and name pairs of the new Clipboard
-                                * Formats on the clipboard
-                                */
-               case CliprdrChannel_FormatList:
-                       cliprdr_process_cb_format_list_event(instance, (RDP_CB_FORMAT_LIST_EVENT*) event);
-                       break;
-
-                       /*
-                                * The Format Data Request PDU is sent by the receipient of the Format List PDU.
-                                * It is used to request the data for one of the formats that was listed in the
-                                * Format List PDU
-                                */
-               case CliprdrChannel_DataRequest:
-                       cliprdr_process_cb_data_request_event(instance);
-                       break;
-
-                       /*
-                                * The Format Data Response PDU is sent as a reply to the Format Data Request PDU.
-                                * It is used to indicate whether processing of the Format Data Request PDU
-                                * was successful. If the processing was successful, the Format Data Response PDU
-                                * includes the contents of the requested clipboard data
-                                */
-               case CliprdrChannel_DataResponse:
-                       cliprdr_process_cb_data_response_event(instance, (RDP_CB_DATA_RESPONSE_EVENT*) event);
-                       break;
-
-               default:
-                       WLog_ERR(TAG, "process_cliprdr_event: unknown event type %d", GetMessageType(event->id));
-                       break;
-               }
-       }
-}
-
-void cliprdr_send_supported_format_list(freerdp* instance)
-{
-       RDP_CB_FORMAT_LIST_EVENT* event;
-       
-       event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
-       
-       event->formats = (UINT32*) malloc(sizeof(UINT32) * 1);
-       event->num_formats = 1;
-       event->formats[0] = CF_UNICODETEXT;
-       
-       freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
-}
-
 /**
  * given a rect with 0,0 at the top left (windows cords)
  * convert it to a rect with 0,0 at the bottom left (apple cords)
index 9b22e94..9b54277 100644 (file)
@@ -99,10 +99,8 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
        settings = instance->settings;
 
        settings->AsyncTransport = TRUE;
-       
        settings->AsyncUpdate = TRUE;
        settings->AsyncInput = TRUE;
-       settings->AsyncChannels = TRUE;
 
        return 0;
 }
index 37eb3b4..a84a5d5 100644 (file)
@@ -19,11 +19,13 @@ typedef struct mf_context mfContext;
 #include <freerdp/client/channels.h>
 #include <freerdp/client/rdpei.h>
 #include <freerdp/client/rdpgfx.h>
+#include <freerdp/client/cliprdr.h>
 #include <freerdp/client/encomsp.h>
 
 #include <winpr/crt.h>
 #include <winpr/synch.h>
 #include <winpr/thread.h>
+#include <winpr/clipboard.h>
 
 #include "MRDPView.h"
 #include "Keyboard.h"
@@ -63,6 +65,15 @@ struct mf_context
        DWORD keyboardThreadId;
        BOOL disconnect;
        BOOL sw_gdi;
+       
+       BOOL clipboardSync;
+       wClipboard* clipboard;
+       UINT32 numServerFormats;
+       UINT32 requestedFormatId;
+       HANDLE clipboardRequestEvent;
+       CLIPRDR_FORMAT* serverFormats;
+       CliprdrClientContext* cliprdr;
+       UINT32 clipboardCapabilities;
 
        rdpFile* connectionRdpFile;