From 1648ca2917baaf893a4e05210dab89af68f26d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benoi=CC=82t=20LeBlanc?= Date: Thu, 20 Jun 2013 20:55:49 -0400 Subject: [PATCH] AsyncInput implementation. WARNING: settings->AsyncInput intentionnally left at FALSE, because the input callback function does not seem to be triggered after a certain point. Possibility of a deadlock? --- client/Mac/MRDPView.h | 3 +- client/Mac/MRDPView.m | 85 ++++++++++++++++++++++++++++++++++++------ client/Mac/mf_client.m | 7 ++++ 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 18f51b56d..e12ad75b3 100755 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -43,7 +43,8 @@ { CFRunLoopSourceRef run_loop_src_channels; CFRunLoopSourceRef run_loop_src_update; - + CFRunLoopSourceRef run_loop_src_input; + NSBitmapImageRep* bmiRep; NSMutableArray* cursors; NSMutableArray* windows; diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 29c5dfd34..c4e170b97 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -83,8 +83,11 @@ 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); -void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info); +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); 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); @@ -152,7 +155,10 @@ struct rgba_data /* 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); @@ -605,6 +611,9 @@ struct rgba_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); @@ -784,13 +793,6 @@ struct rgba_data * * ***********************************************************************/ -/** ********************************************************************* - * connect to RDP server - * - * @return 0 on success, -1 on failure - ***********************************************************************/ - - /** ********************************************************************* * a callback given to freerdp_connect() to process the pre-connect operations. * @@ -812,6 +814,7 @@ BOOL mac_pre_connect(freerdp* instance) //instance->update->BitmapUpdate = mac_bitmap_update; mfContext *mfc = (mfContext*) instance->context; + MRDPView* view = (MRDPView*) mfc->view; settings = instance->settings; if (!settings->ServerHostname) @@ -861,7 +864,7 @@ BOOL mac_pre_connect(freerdp* instance) settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; - [((MRDPView*)mfc->view) setViewSize:instance->settings->DesktopWidth :instance->settings->DesktopHeight]; + [view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight]; freerdp_channels_pre_connect(instance->context->channels, instance); @@ -1158,7 +1161,7 @@ void mac_end_paint(rdpContext* context) /** ********************************************************************* - * called when data is available on a socket + * called when update data is available ***********************************************************************/ static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) @@ -1186,11 +1189,42 @@ static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBack register_update_fds(instance); } +/** ********************************************************************* + * called when input data is available + ***********************************************************************/ + +static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) +{ + int status; + wMessage message; + wMessageQueue* queue; + freerdp* instance = (freerdp*) info; + + status = 1; + queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); + + if (queue) + { + 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); +} + /** ********************************************************************* * called when data is available on a virtual channel ***********************************************************************/ -void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) +static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) { wMessage* event; freerdp* instance = (freerdp*) info; @@ -1240,6 +1274,33 @@ int register_update_fds(freerdp* instance) 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 ***********************************************************************/ diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 7d9ca4d1f..061b9d981 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -67,6 +67,13 @@ int mfreerdp_client_stop(rdpContext* context) { mfContext* mfc = (mfContext*) context; + if (context->settings->AsyncUpdate) + { + wMessageQueue* queue; + queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE); + MessageQueue_PostQuit(queue, 0); + } + if (context->settings->AsyncInput) { wMessageQueue* queue;