diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index d498454a9..9d7f58b31 100755 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -41,10 +41,6 @@ @interface MRDPView : NSView { - CFRunLoopSourceRef run_loop_src_channels; - CFRunLoopSourceRef run_loop_src_update; - CFRunLoopSourceRef run_loop_src_input; - NSBitmapImageRep* bmiRep; NSMutableArray* cursors; NSMutableArray* windows; @@ -98,7 +94,7 @@ - (void) rdpRemoteAppError; - (void) onPasteboardTimerFired :(NSTimer *) timer; - (void) releaseResources; -- (void) setViewSize : (int) width : (int) height; +- (void) setViewSize : (int) w : (int) h; @property (assign) int is_connected; @@ -118,3 +114,4 @@ BOOL mac_pre_connect(freerdp* instance); BOOL mac_post_connect(freerdp* instance); BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain); int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size); +DWORD mac_client_thread(void* param); diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 5893a3791..40d73a4a0 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -82,11 +82,9 @@ void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap); void mac_begin_paint(rdpContext* context); void mac_end_paint(rdpContext* context); void mac_save_state_info(freerdp* instance, rdpContext* context); -static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info); -static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info); -static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info); -int register_update_fds(freerdp* instance); -int register_input_fds(freerdp* instance); +static void update_activity_cb(freerdp* instance); +static void input_activity_cb(freerdp* instance); +static void channel_activity_cb(freerdp* instance); int invoke_draw_rect(rdpContext* context); 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); @@ -101,7 +99,7 @@ void cliprdr_send_supported_format_list(freerdp* instance); int register_channel_fds(int* fds, int count, freerdp* instance); -DWORD mf_client_thread(void* param); +DWORD mac_client_thread(void* param); struct cursor { @@ -141,42 +139,93 @@ struct rgba_data e.embed = TRUE; e.handle = (void*) self; PubSub_OnEmbedWindow(context->pubSub, context, &e); + [self setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight]; - /* register update message queue with the RunLoop */ - register_update_fds(context->instance); - - /* register update message queue with the RunLoop */ - register_input_fds(context->instance); - - /* register channel events with the RunLoop */ - register_channels_fds(context->instance); - - freerdp_check_fds(context->instance); - - mfc->thread = CreateThread(NULL, 0, mf_client_thread, (void*) context, 0, &mfc->mainThreadId); + mfc->thread = CreateThread(NULL, 0, mac_client_thread, (void*) context, 0, &mfc->mainThreadId); return 0; } -DWORD mf_client_thread(void* param) +DWORD mac_client_thread(void* param) { - int status; - rdpContext* context = (rdpContext*) param; - mfContext* mfc = (mfContext*) context; - MRDPView* view = mfc->view; - - status = freerdp_connect(context->instance); - - if (!status) - { - [view setIs_connected:0]; - [view rdpConnectError]; - return 0; - } + int status; + HANDLE events[4]; + HANDLE input_event; + HANDLE update_event; + HANDLE channels_event; - [view setIs_connected:1]; - - return 0; + DWORD nCount; + rdpContext* context = (rdpContext*) param; + mfContext* mfc = (mfContext*) context; + freerdp* instance = context->instance; + MRDPView* view = mfc->view; + + status = freerdp_connect(context->instance); + + if (!status) + { + [view setIs_connected:0]; + [view rdpConnectError]; + return 0; + } + + [view setIs_connected:1]; + + nCount = 0; + + events[nCount++] = mfc->stopEvent; + + if (instance->settings->AsyncUpdate) + { + events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); + } + + if (instance->settings->AsyncInput) + { + events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); + } + + if (instance->settings->AsyncChannels) + { + events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance); + } + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(mfc->stopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (instance->settings->AsyncUpdate) + { + if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0) + { + update_activity_cb(instance); + } + } + + if (instance->settings->AsyncInput) + { + if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) + { + input_activity_cb(instance); + } + } + + if (instance->settings->AsyncChannels) + { + if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0) + { + channel_activity_cb(instance); + } + } + } + + ExitThread(0); + return 0; } /************************************************************************ @@ -626,7 +675,16 @@ DWORD mf_client_thread(void* param) - (void) releaseResources { int i; - + + mfContext* mfc = (mfContext*) context; + + if (mfc && mfc->thread) + { + WaitForSingleObject(mfc->thread, INFINITE); + CloseHandle(mfc->thread); + mfc->thread = NULL; + } + for (i = 0; i < argc; i++) { if (argv[i]) @@ -640,15 +698,6 @@ DWORD mf_client_thread(void* param) if (pixel_data) free(pixel_data); - - if (run_loop_src_update != 0) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_update, kCFRunLoopDefaultMode); - - if (run_loop_src_input != 0) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_input, kCFRunLoopDefaultMode); - - if (run_loop_src_channels != 0) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode); } /** ********************************************************************* @@ -858,7 +907,6 @@ BOOL mac_pre_connect(freerdp* instance) settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; - [view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight]; freerdp_channels_pre_connect(instance->context->channels, instance); return TRUE; @@ -1152,16 +1200,15 @@ void mac_end_paint(rdpContext* context) * called when update data is available ***********************************************************************/ -static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) +static void update_activity_cb(freerdp* instance) { int status; wMessage message; wMessageQueue* queue; - freerdp* instance = (freerdp*) info; status = 1; queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE); - + if (queue) { while (MessageQueue_Peek(queue, &message, TRUE)) @@ -1172,21 +1219,21 @@ static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBack break; } } - - CFRelease(fdref); - register_update_fds(instance); + else + { + fprintf(stderr, "update_activity_cb: No queue!\n"); + } } /** ********************************************************************* * called when input data is available ***********************************************************************/ -static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) +static void input_activity_cb(freerdp* instance) { int status; wMessage message; - wMessageQueue* queue; - freerdp* instance = (freerdp*) info; + wMessageQueue* queue; status = 1; queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); @@ -1195,33 +1242,32 @@ static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackT { while (MessageQueue_Peek(queue, &message, TRUE)) { - fprintf(stderr, "input_activity_cb: message %d\n", message.id); - status = freerdp_message_queue_process_message(instance, FREERDP_INPUT_MESSAGE_QUEUE, &message); if (!status) break; } } - - CFRelease(fdref); - register_input_fds(instance); + else + { + fprintf(stderr, "input_activity_cb: No queue!\n"); + } } /** ********************************************************************* * called when data is available on a virtual channel ***********************************************************************/ -static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) +static void channel_activity_cb(freerdp* instance) { - wMessage* event; - freerdp* instance = (freerdp*) info; + wMessage* event; freerdp_channels_process_pending_messages(instance); event = freerdp_channels_pop_event(instance->context->channels); if (event) { - switch (GetMessageClass(event->id)) + fprintf(stderr, "channel_activity_cb: message %d\n", event->id); + switch (GetMessageClass(event->id)) { case CliprdrChannel_Class: process_cliprdr_event(instance, event); @@ -1230,90 +1276,6 @@ static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBac freerdp_event_free(event); } - - CFRelease(fdref); - register_channels_fds(instance); -} - -/** ********************************************************************* - * setup callbacks for data availability on update message queue - ***********************************************************************/ - -int register_update_fds(freerdp* instance) -{ - int fd_update_event; - HANDLE update_event; - CFFileDescriptorRef fdref; - CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL }; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - if (instance->settings->AsyncUpdate) - { - update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); - fd_update_event = GetEventFileDescriptor(update_event); - - fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_update_event, true, update_activity_cb, &fd_context); - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack); - view->run_loop_src_update = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_update, kCFRunLoopDefaultMode); - } - - return 0; -} - -/** ********************************************************************* - * setup callbacks for data availability on input message queue - ***********************************************************************/ - -int register_input_fds(freerdp* instance) -{ - int fd_input_event; - HANDLE input_event; - CFFileDescriptorRef fdref; - CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL }; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - if (instance->settings->AsyncInput) - { - input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); - fd_input_event = GetEventFileDescriptor(input_event); - - fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_input_event, true, input_activity_cb, &fd_context); - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack); - view->run_loop_src_input = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_input, kCFRunLoopDefaultMode); - } - - return 0; -} - -/** ********************************************************************* - * setup callbacks for data availability on channels - ***********************************************************************/ - -int register_channels_fds(freerdp* instance) -{ - int fd_channel_event; - HANDLE channel_event; - CFFileDescriptorRef fdref; - CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL }; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - if (instance->settings->AsyncChannels) - { - channel_event = freerdp_channels_get_event_handle(instance); - fd_channel_event = GetEventFileDescriptor(channel_event); - - fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_channel_event, true, channel_activity_cb, &fd_context); - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack); - view->run_loop_src_channels = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_channels, kCFRunLoopDefaultMode); - } - - return 0; } /** ********************************************************************* diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 900c488ed..f4e68a0f6 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -88,6 +88,8 @@ int mfreerdp_client_stop(rdpContext* context) mfc->disconnect = TRUE; } + SetEvent(mfc->stopEvent); + if (mfc->view_ownership) { MRDPView* view = (MRDPView*) mfc->view; @@ -106,6 +108,8 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context) mfc = (mfContext*) instance->context; + mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + context->instance->PreConnect = mac_pre_connect; context->instance->PostConnect = mac_post_connect; context->instance->ReceiveChannelData = mac_receive_channel_data; @@ -115,8 +119,8 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context) settings = instance->settings; - settings->AsyncUpdate = TRUE; - // TODO settings->AsyncInput = TRUE; + settings->AsyncUpdate = TRUE; + settings->AsyncInput = TRUE; settings->AsyncChannels = TRUE; settings->AsyncTransport = TRUE; settings->RedirectClipboard = TRUE; diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h index ff3bd6176..52e7be122 100644 --- a/client/Mac/mfreerdp.h +++ b/client/Mac/mfreerdp.h @@ -44,6 +44,7 @@ struct mf_context int client_height; HANDLE keyboardThread; + HANDLE stopEvent; HGDI_DC hdc; UINT16 srcBpp;