diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index a2c0c4ec2..5010c8401 100755 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -22,23 +22,6 @@ #import -/* - #import "freerdp/freerdp.h" -#import "freerdp/types.h" -#import "freerdp/channels/channels.h" -#import "freerdp/gdi/gdi.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/rail/rail.h" -#import "freerdp/rail.h" -#import "freerdp/utils/rail.h" - -#import "mf_interface.h" -*/ - #import "mfreerdp.h" #import "mf_client.h" diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index cdb42ea7d..dba022192 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -17,31 +17,6 @@ * limitations under the License. */ -/* - * TODO - * + provide a UI for configuring optional parameters, but keep cmd line args - * + audio redirection is delayed considerably - * + caps lock key needs to be sent in func flagsChanged() - * + libfreerdp-utils.1.0.dylib needs to be installed to /usr/local/lib - * - * - MRDPView implementation is incomplete - * - all variables should have consistent nameing scheme - camel case - * - all funcs same as above - * - PolygonSc seems to create a transparent rect - * - ensure mouse cursor changes are working ok after moving to NSTracking area - * - RAIL: - * - - * - - * - tool tips to be correctly positioned - * - dragging is slightly of - * - resize after dragging not working - * - dragging app from macbook to monitor gives exec/access err - * - unable to drag rect out of monitor boundaries - * - - * - - * - - */ - #include #include "mf_client.h" @@ -52,6 +27,8 @@ #include #include +#include +#include #include @@ -67,26 +44,20 @@ #import "freerdp/client/file.h" #import "freerdp/client/cmdline.h" -/****************************************** - Forward declarations - ******************************************/ - - void mf_Pointer_New(rdpContext* context, rdpPointer* pointer); void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer); void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer); void mf_Pointer_SetNull(rdpContext* context); void mf_Pointer_SetDefault(rdpContext* context); -// int rdp_connect(void); -void mac_set_bounds(rdpContext* context, rdpBounds* bounds); -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 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 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); @@ -99,7 +70,6 @@ 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 @@ -140,10 +110,10 @@ struct rgba_data e.handle = (void*) self; PubSub_OnEmbedWindow(context->pubSub, context, &e); - NSScreen *screen = [[NSScreen screens] objectAtIndex:0]; + NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; NSRect screenFrame = [screen frame]; - if(instance->settings->Fullscreen) + if (instance->settings->Fullscreen) { instance->settings->DesktopWidth = screenFrame.size.width; instance->settings->DesktopHeight = screenFrame.size.height; @@ -157,15 +127,108 @@ struct rgba_data return 0; } +DWORD mac_client_update_thread(void* param) +{ + int status; + wMessage message; + wMessageQueue* queue; + rdpContext* context = (rdpContext*) param; + + status = 1; + queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE); + + while (MessageQueue_Wait(queue)) + { + while (MessageQueue_Peek(queue, &message, TRUE)) + { + status = freerdp_message_queue_process_message(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message); + + if (!status) + break; + } + + if (!status) + break; + } + + ExitThread(0); + return NULL; +} + +DWORD mac_client_input_thread(void* param) +{ + int status; + wMessage message; + wMessageQueue* queue; + rdpContext* context = (rdpContext*) param; + + status = 1; + queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE); + + while (MessageQueue_Wait(queue)) + { + while (MessageQueue_Peek(queue, &message, TRUE)) + { + status = freerdp_message_queue_process_message(context->instance, FREERDP_INPUT_MESSAGE_QUEUE, &message); + + if (!status) + break; + } + } + + ExitThread(0); + return NULL; +} + +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 NULL; +} + DWORD mac_client_thread(void* param) { @autoreleasepool { int status; HANDLE events[4]; - HANDLE input_event; - HANDLE update_event; - HANDLE channels_event; + HANDLE inputEvent; + HANDLE inputThread; + HANDLE updateEvent; + HANDLE updateThread; + HANDLE channelsEvent; + HANDLE channelsThread; DWORD nCount; rdpContext* context = (rdpContext*) param; @@ -190,17 +253,29 @@ DWORD mac_client_thread(void* param) if (settings->AsyncUpdate) { - events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); + updateThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_update_thread, context, 0, NULL); + } + else + { + events[nCount++] = updateEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE); } if (settings->AsyncInput) { - events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); + inputThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_input_thread, context, 0, NULL); + } + else + { + events[nCount++] = inputEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); } if (settings->AsyncChannels) { - events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance); + channelsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_channels_thread, context, 0, NULL); + } + else + { + events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance); } while (1) @@ -213,44 +288,58 @@ DWORD mac_client_thread(void* param) break; } - if (settings->AsyncUpdate) + if (!settings->AsyncUpdate) { - if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(updateEvent, 0) == WAIT_OBJECT_0) { update_activity_cb(instance); } } - if (settings->AsyncInput) + if (!settings->AsyncInput) { - if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0) { input_activity_cb(instance); } } - if (settings->AsyncChannels) + if (!settings->AsyncChannels) { - if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0) { channel_activity_cb(instance); } } } + if (settings->AsyncUpdate) + { + wMessageQueue* updateQueue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE); + MessageQueue_PostQuit(updateQueue, 0); + WaitForSingleObject(updateThread, INFINITE); + CloseHandle(updateThread); + } + + if (settings->AsyncInput) + { + wMessageQueue* inputQueue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); + MessageQueue_PostQuit(inputQueue, 0); + WaitForSingleObject(inputThread, INFINITE); + CloseHandle(inputThread); + } + + if (settings->AsyncChannels) + { + WaitForSingleObject(channelsThread, INFINITE); + CloseHandle(channelsThread); + } + ExitThread(0); return 0; } } -/************************************************************************ - methods we override - ************************************************************************/ - -/** ********************************************************************* - * create MRDPView with specified rectangle - ***********************************************************************/ - - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; @@ -263,12 +352,6 @@ DWORD mac_client_thread(void* param) return self; } -/** ********************************************************************* - * called when MRDPView has been successfully created from the NIB - ***********************************************************************/ - -//TODO - Expose this code as a public method, because awakeFromNib -// won't be called if the view is created dynamically - (void) viewDidLoad { [self initializeView]; @@ -298,35 +381,16 @@ DWORD mac_client_thread(void* param) [[self window] invalidateCursorRectsForView:self]; } - -// Set the current cursor - (void) resetCursorRects { [self addCursorRect:[self visibleRect] cursor:currentCursor]; } -/** ********************************************************************* - * become first responder so we can get keyboard and mouse events - ***********************************************************************/ - - (BOOL)acceptsFirstResponder { return YES; } -/** ********************************************************************* - * called when a mouse move event occurrs - * - * ideally we want to be called when the mouse moves over NSView client area, - * but in reality we get called any time the mouse moves anywhere on the screen; - * we could use NSTrackingArea class to handle this but this class is available - * on Mac OS X v10.5 and higher; since we want to be compatible with older - * versions, we do this manually. - * - * TODO: here is how it can be done using legacy methods - * http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/MouseTrackingEvents/MouseTrackingEvents.html#//apple_ref/doc/uid/10000060i-CH11-SW1 - ***********************************************************************/ - - (void) mouseMoved:(NSEvent *)event { [super mouseMoved:event]; @@ -341,10 +405,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y); } -/** ********************************************************************* - * called when left mouse button is pressed down - ***********************************************************************/ - - (void)mouseDown:(NSEvent *) event { [super mouseDown:event]; @@ -359,10 +419,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); } -/** ********************************************************************* - * called when left mouse button is released - ***********************************************************************/ - - (void) mouseUp:(NSEvent *) event { [super mouseUp:event]; @@ -377,10 +433,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON1, x, y); } -/** ********************************************************************* - * called when right mouse button is pressed down - ***********************************************************************/ - - (void) rightMouseDown:(NSEvent *)event { [super rightMouseDown:event]; @@ -395,10 +447,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); } -/** ********************************************************************* - * called when right mouse button is released - ***********************************************************************/ - - (void) rightMouseUp:(NSEvent *)event { [super rightMouseUp:event]; @@ -413,10 +461,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON2, x, y); } -/** ********************************************************************* - * called when middle mouse button is pressed - ***********************************************************************/ - - (void) otherMouseDown:(NSEvent *)event { [super otherMouseDown:event]; @@ -431,10 +475,6 @@ DWORD mac_client_thread(void* param) mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); } -/** ********************************************************************* - * called when middle mouse button is released - ***********************************************************************/ - - (void) otherMouseUp:(NSEvent *)event { [super otherMouseUp:event]; @@ -478,11 +518,6 @@ DWORD mac_client_thread(void* param) } } -/** ********************************************************************* - * called when mouse is moved with left button pressed - * note: invocation order is: mouseDown, mouseDragged, mouseUp - ***********************************************************************/ - - (void) mouseDragged:(NSEvent *)event { [super mouseDragged:event]; @@ -540,10 +575,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar) return keyCode; } -/** ********************************************************************* - * called when a key is pressed - ***********************************************************************/ - - (void) keyDown:(NSEvent *) event { DWORD keyCode; @@ -581,10 +612,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar) freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode); } -/** ********************************************************************* - * called when a key is released - ***********************************************************************/ - - (void) keyUp:(NSEvent *) event { DWORD keyCode; @@ -622,10 +649,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar) freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode); } -/** ********************************************************************* - * called when shift, control, alt and meta keys are pressed/released - ***********************************************************************/ - - (void) flagsChanged:(NSEvent*) event { int key; @@ -732,38 +755,34 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar) free(pixel_data); } -/** ********************************************************************* - * called when our view needs refreshing - ***********************************************************************/ - - (void) drawRect:(NSRect)rect { if (!context) return; - + if (self->bitmap_context) { CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context); - + + CGContextSaveGState(cgContext); + CGContextClipToRect(cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); - CGContextDrawImage(cgContext, CGRectMake(0, - 0, [self bounds].size.width, [self bounds].size.height), cgImage); + CGContextDrawImage(cgContext, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage); + + CGContextRestoreGState(cgContext); + CGImageRelease(cgImage); } else { - // just clear the screen with black + /* Fill the screen with black */ [[NSColor blackColor] set]; NSRectFill([self bounds]); } } -/************************************************************************ - instance methods - ************************************************************************/ - - (void) onPasteboardTimerFired :(NSTimer*) timer { int i; @@ -791,30 +810,13 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar) mfc->client_width = width; } -/************************************************************************ - * * - * C functions * - * * - ***********************************************************************/ - -/** ********************************************************************* - * a callback given to freerdp_connect() to process the pre-connect operations. - * - * @param inst - pointer to a rdp_freerdp struct that contains the connection's parameters, and - * will be filled with the appropriate informations. - * - * @return true if successful. false otherwise. - ************************************************************************/ - BOOL mac_pre_connect(freerdp* instance) { rdpSettings* settings; - // setup callbacks instance->update->BeginPaint = mac_begin_paint; instance->update->EndPaint = mac_end_paint; - instance->update->SetBounds = mac_set_bounds; - //instance->update->BitmapUpdate = mac_bitmap_update; + instance->update->DesktopResize = mac_desktop_resize; settings = instance->settings; @@ -825,7 +827,6 @@ BOOL mac_pre_connect(freerdp* instance) return -1; } - settings->ColorDepth = 32; settings->SoftwareGdi = TRUE; settings->OsMajorType = OSMAJORTYPE_MACINTOSH; @@ -852,8 +853,8 @@ BOOL mac_pre_connect(freerdp* instance) settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; - settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; - settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; + settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; @@ -864,22 +865,13 @@ BOOL mac_pre_connect(freerdp* instance) return TRUE; } -/** ********************************************************************* - * a callback registered with freerdp_connect() to perform post-connection operations. - * we get called only if the connection was initialized properly, and will continue - * the initialization based on the newly created connection. - * - * @param inst - pointer to a rdp_freerdp struct - * - * @return true on success, false on failure - * - ************************************************************************/ - BOOL mac_post_connect(freerdp* instance) { + rdpGdi* gdi; UINT32 flags; + rdpSettings* settings; rdpPointer rdp_pointer; - mfContext *mfc = (mfContext*) instance->context; + mfContext* mfc = (mfContext*) instance->context; MRDPView* view = (MRDPView*) mfc->view; @@ -891,13 +883,20 @@ BOOL mac_post_connect(freerdp* instance) rdp_pointer.SetNull = mf_Pointer_SetNull; rdp_pointer.SetDefault = mf_Pointer_SetDefault; - flags = CLRBUF_32BPP | CLRCONV_ALPHA; + settings = instance->settings; + + flags = CLRCONV_ALPHA | CLRCONV_RGB555; + + if (settings->ColorDepth > 16) + flags |= CLRBUF_32BPP; + else + flags |= CLRBUF_16BPP; + gdi_init(instance, flags, NULL); - - rdpGdi* gdi = instance->context->gdi; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - view->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); - + gdi = instance->context->gdi; + + view->bitmap_context = mac_create_bitmap_context(instance->context); + pointer_cache_register_callbacks(instance->update); graphics_register_pointer(instance->context->graphics, &rdp_pointer); @@ -942,14 +941,6 @@ BOOL mac_authenticate(freerdp* instance, char** username, char** password, char* return ok; } -/** ********************************************************************* - * create a new mouse cursor - * - * @param context our context state - * @param pointer information about the cursor to create - * - ************************************************************************/ - void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) { NSRect rect; @@ -978,7 +969,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData, pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv); - + /* store cursor bitmap image in representation - required by NSImage */ bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data pixelsWide:rect.size.width @@ -1012,10 +1003,6 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) [ma addObject:mrdpCursor]; } -/** ********************************************************************* - * release resources on specified cursor - ************************************************************************/ - void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer) { mfContext* mfc = (mfContext*) context; @@ -1036,10 +1023,6 @@ void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer) } } -/** ********************************************************************* - * set specified cursor as the current cursor - ************************************************************************/ - void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer) { mfContext* mfc = (mfContext*) context; @@ -1059,19 +1042,11 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer) NSLog(@"Cursor not found"); } -/** ********************************************************************* - * do not display any mouse cursor - ***********************************************************************/ - void mf_Pointer_SetNull(rdpContext* context) { } -/** ********************************************************************* - * display default mouse cursor - ***********************************************************************/ - void mf_Pointer_SetDefault(rdpContext* context) { mfContext* mfc = (mfContext*) context; @@ -1079,28 +1054,31 @@ void mf_Pointer_SetDefault(rdpContext* context) [view setCursor:[NSCursor arrowCursor]]; } -/** ********************************************************************* - * clip drawing surface so nothing is drawn outside specified bounds - ***********************************************************************/ - -void mac_set_bounds(rdpContext* context, rdpBounds* bounds) +CGContextRef mac_create_bitmap_context(rdpContext* context) { + CGContextRef bitmap_context; + rdpGdi* gdi = context->gdi; -} - -/** ********************************************************************* - * we don't do much over here - ***********************************************************************/ - -void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) -{ + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (gdi->dstBpp == 16) + { + bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, + gdi->width, gdi->height, 5, gdi->width * 2, colorSpace, + kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst); + } + else + { + bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, + gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, + kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); + } + + CGColorSpaceRelease(colorSpace); + + return bitmap_context; } -/** ********************************************************************* - * we don't do much over here - ***********************************************************************/ - void mac_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; @@ -1111,10 +1089,6 @@ void mac_begin_paint(rdpContext* context) gdi->primary->hdc->hwnd->invalid->null = 1; } -/** ********************************************************************* - * RDP server wants us to draw new data in the view - ***********************************************************************/ - void mac_end_paint(rdpContext* context) { rdpGdi* gdi; @@ -1139,9 +1113,6 @@ void mac_end_paint(rdpContext* context) if (context->gdi->primary->hdc->hwnd->invalid->null) return; - - if (context->gdi->drawing != context->gdi->primary) - return; invalid = gdi->primary->hdc->hwnd->invalid; @@ -1172,17 +1143,36 @@ void mac_end_paint(rdpContext* context) gdi->primary->hdc->hwnd->ninvalid = 0; } - -/** ********************************************************************* - * called when update data is available - ***********************************************************************/ +void mac_desktop_resize(rdpContext* context) +{ + mfContext* mfc = (mfContext*) context; + MRDPView* view = (MRDPView*) mfc->view; + rdpSettings* settings = context->settings; + + /** + * TODO: Fix resizing race condition. We should probably implement a message to be + * put on the update message queue to be able to properly flush pending updates, + * resize, and then continue with post-resizing graphical updates. + */ + + CGContextRef old_context = view->bitmap_context; + view->bitmap_context = NULL; + CGContextRelease(old_context); + + mfc->width = settings->DesktopWidth; + mfc->height = settings->DesktopHeight; + + gdi_resize(context->gdi, mfc->width, mfc->height); + + view->bitmap_context = mac_create_bitmap_context(context); +} static void update_activity_cb(freerdp* instance) { int status; wMessage message; wMessageQueue* queue; - + status = 1; queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE); @@ -1191,7 +1181,7 @@ static void update_activity_cb(freerdp* instance) while (MessageQueue_Peek(queue, &message, TRUE)) { status = freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message); - + if (!status) break; } @@ -1202,10 +1192,6 @@ static void update_activity_cb(freerdp* instance) } } -/** ********************************************************************* - * called when input data is available - ***********************************************************************/ - static void input_activity_cb(freerdp* instance) { int status; @@ -1231,10 +1217,6 @@ static void input_activity_cb(freerdp* instance) } } -/** ********************************************************************* - * called when data is available on a virtual channel - ***********************************************************************/ - static void channel_activity_cb(freerdp* instance) { wMessage* event; @@ -1257,20 +1239,6 @@ static void channel_activity_cb(freerdp* instance) } } -/** - * Used to load plugins based on the commandline parameters. - * This function is provided as a parameter to freerdp_parse_args(), that will call it - * each time a plugin name is found on the command line. - * This function just calls freerdp_channels_load_plugin() for the given plugin, and always returns 1. - * - * @param settings - * @param name - * @param plugin_data - * @param user_data - * - * @return 1 - */ - int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { rdpChannels* channels = (rdpChannels*) user_data; @@ -1284,10 +1252,6 @@ int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA * stuff related to clipboard redirection */ -/** - * remote system has requested clipboard data from local system - */ - void cliprdr_process_cb_data_request_event(freerdp* instance) { int len; diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m index 351111b97..218f28178 100644 --- a/client/Mac/cli/AppDelegate.m +++ b/client/Mac/cli/AppDelegate.m @@ -71,35 +71,38 @@ void mac_set_view_size(rdpContext* context, MRDPView* view); - (int) ParseCommandLineArguments { int i; - int len; + int length; int status; char* cptr; - int argc; - char** argv = nil; NSArray* args = [[NSProcessInfo processInfo] arguments]; - argc = (int) [args count]; - argv = malloc(sizeof(char*) * argc); + context->argc = (int) [args count]; + context->argv = malloc(sizeof(char*) * context->argc); i = 0; for (NSString* str in args) { - len = (int) ([str length] + 1); - cptr = (char*) malloc(len); + /* filter out some arguments added by XCode */ + + if ([str isEqualToString:@"YES"]) + continue; + + if ([str isEqualToString:@"-NSDocumentRevisionsDebugMode"]) + continue; + + length = (int) ([str length] + 1); + cptr = (char*) malloc(length); strcpy(cptr, [str UTF8String]); - argv[i++] = cptr; + context->argv[i++] = cptr; } - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv); - - if (context->argc && context->argv) - status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv); - else - { - freerdp_client_print_command_line_help(argc, argv); - } + context->argc = i; + + status = freerdp_client_settings_parse_command_line(context->settings, context->argc, context->argv); + + status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv); return status; } diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 9b01de2c3..b9b16171f 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -99,10 +99,11 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context) settings = instance->settings; + settings->AsyncTransport = TRUE; + settings->AsyncUpdate = TRUE; settings->AsyncInput = TRUE; settings->AsyncChannels = TRUE; - settings->AsyncTransport = TRUE; return 0; } @@ -135,7 +136,6 @@ void freerdp_client_mouse_event(rdpContext* cfc, DWORD flags, int x, int y) input->MouseEvent(input, flags, x, y); } - void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { mfContext* mfc = (mfContext*) context; diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h index 52e7be122..35efb27d4 100644 --- a/client/Mac/mfreerdp.h +++ b/client/Mac/mfreerdp.h @@ -28,7 +28,7 @@ struct mf_context DEFINE_RDP_CLIENT_COMMON(); void* view; - BOOL view_ownership; // TRUE indicates that the window was created and should be freed by the API. + BOOL view_ownership; int width; int height; @@ -44,8 +44,8 @@ struct mf_context int client_height; HANDLE keyboardThread; - HANDLE stopEvent; - + HANDLE stopEvent; + HGDI_DC hdc; UINT16 srcBpp; UINT16 dstBpp; diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index fa72fbb40..8a4d20631 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -335,6 +335,14 @@ static void timespec_add_ms(struct timespec* tspec, UINT32 ms) tspec->tv_nsec = (ns % 1000000000); } +static UINT64 timespec_to_ms(struct timespec* tspec) +{ + UINT64 ms; + ms = tspec->tv_sec * 1000; + ms += tspec->tv_nsec / 1000000; + return ms; +} + static void timespec_gettimeofday(struct timespec* tspec) { struct timeval tval; @@ -345,13 +353,10 @@ static void timespec_gettimeofday(struct timespec* tspec) static int timespec_compare(const struct timespec* tspec1, const struct timespec* tspec2) { - if (tspec1->tv_sec < tspec2->tv_sec) - return -1; - - if (tspec1->tv_sec > tspec2->tv_sec) - return 1; - - return tspec1->tv_nsec - tspec2->tv_nsec; + if (tspec1->tv_sec == tspec2->tv_sec) + return (tspec1->tv_nsec - tspec2->tv_nsec); + else + return (tspec1->tv_sec - tspec2->tv_sec); } static void timespec_copy(struct timespec* dst, struct timespec* src) @@ -363,37 +368,49 @@ static void timespec_copy(struct timespec* dst, struct timespec* src) void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { WINPR_TIMER_QUEUE_TIMER* node; - + if (!(*pHead)) { *pHead = timer; + timer->next = NULL; return; } node = *pHead; - + while (node->next) { - if (timespec_compare(&(timer->ExpirationTime), &(node->ExpirationTime)) < 0) - break; + if (timespec_compare(&(timer->ExpirationTime), &(node->ExpirationTime)) > 0) + { + if (timespec_compare(&(timer->ExpirationTime), &(node->next->ExpirationTime)) < 0) + break; + } node = node->next; } if (node->next) + { timer->next = node->next->next; - - node->next = timer; + node->next = timer; + } + else + { + node->next = timer; + timer->next = NULL; + } } void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { + BOOL found = FALSE; WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* prevNode; if (timer == *pHead) { *pHead = timer->next; + timer->next = NULL; return; } @@ -403,14 +420,24 @@ void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI while (node) { if (node == timer) + { + found = TRUE; break; + } prevNode = node; node = node->next; } - - prevNode->next = timer->next; - timer->next = NULL; + + if (found) + { + if (prevNode) + { + prevNode->next = timer->next; + } + + timer->next = NULL; + } } int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) @@ -438,14 +465,14 @@ int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) if (node->Period) { timespec_add_ms(&(node->ExpirationTime), node->Period); - InsertTimerQueueTimer(&(timerQueue->activeHead), node); - node = timerQueue->activeHead; } else { InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); } + + node = timerQueue->activeHead; } else { @@ -470,7 +497,7 @@ static void* TimerQueueThread(void* arg) if (!timerQueue->activeHead) { - timespec_add_ms(&timeout, 100); + timespec_add_ms(&timeout, 50); } else { @@ -518,12 +545,15 @@ HANDLE CreateTimerQueue(void) if (timerQueue) { + ZeroMemory(timerQueue, sizeof(WINPR_TIMER_QUEUE)); + WINPR_HANDLE_SET_TYPE(timerQueue, HANDLE_TYPE_TIMER_QUEUE); handle = (HANDLE) timerQueue; timerQueue->activeHead = NULL; + timerQueue->inactiveHead = NULL; timerQueue->bCancelled = FALSE; - + StartTimerQueueThread(timerQueue); } @@ -642,6 +672,7 @@ BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, timer->timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer->FireCount = 0; + timer->next = NULL; pthread_mutex_lock(&(timerQueue->cond_mutex)); @@ -670,9 +701,11 @@ BOOL ChangeTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG pthread_mutex_lock(&(timerQueue->cond_mutex)); RemoveTimerQueueTimer(&(timerQueue->activeHead), timer); + RemoveTimerQueueTimer(&(timerQueue->inactiveHead), timer); timer->DueTime = DueTime; timer->Period = Period; + timer->next = NULL; timespec_copy(&(timer->StartTime), &CurrentTime); timespec_add_ms(&(timer->StartTime), DueTime);