20 #include <winpr/windows.h>
22 #include "mf_client.h"
25 #import "MRDPCursor.h"
27 #import "PasswordDialog.h"
28 #import "CertificateDialog.h"
30 #include <winpr/crt.h>
31 #include <winpr/assert.h>
32 #include <winpr/input.h>
33 #include <winpr/synch.h>
34 #include <winpr/sysinfo.h>
36 #include <freerdp/constants.h>
38 #import "freerdp/freerdp.h"
39 #import "freerdp/types.h"
40 #import "freerdp/config.h"
41 #import "freerdp/channels/channels.h"
42 #import "freerdp/gdi/gdi.h"
43 #import "freerdp/gdi/dc.h"
44 #import "freerdp/gdi/region.h"
45 #import "freerdp/graphics.h"
46 #import "freerdp/client/file.h"
47 #import "freerdp/client/cmdline.h"
48 #import "freerdp/log.h"
50 #import <CoreGraphics/CoreGraphics.h>
52 #define TAG CLIENT_TAG("mac")
54 static BOOL mf_Pointer_New(rdpContext *context, rdpPointer *pointer);
55 static void mf_Pointer_Free(rdpContext *context, rdpPointer *pointer);
56 static BOOL mf_Pointer_Set(rdpContext *context, rdpPointer *pointer);
57 static BOOL mf_Pointer_SetNull(rdpContext *context);
58 static BOOL mf_Pointer_SetDefault(rdpContext *context);
59 static BOOL mf_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y);
61 static BOOL mac_begin_paint(rdpContext *context);
62 static BOOL mac_end_paint(rdpContext *context);
63 static BOOL mac_desktop_resize(rdpContext *context);
65 static void input_activity_cb(freerdp *instance);
67 static DWORD WINAPI mac_client_thread(
void *param);
68 static void windows_to_apple_cords(
MRDPView *view, NSRect *r);
69 static CGContextRef mac_create_bitmap_context(rdpContext *context);
73 @synthesize is_connected;
75 - (int)rdpStart:(rdpContext *)rdp_context
77 rdpSettings *settings;
78 EmbedWindowEventArgs e;
79 [
self initializeView];
85 instance = context->instance;
86 WINPR_ASSERT(instance);
88 settings = context->settings;
89 WINPR_ASSERT(settings);
91 EventArgsInit(&e,
"mfreerdp");
93 e.handle = (
void *)
self;
94 PubSub_OnEmbedWindow(context->pubSub, context, &e);
95 NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
96 NSRect screenFrame = [screen frame];
104 [
self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
108 [
self exitFullScreenModeWithOptions:nil];
114 if (!(mfc->common.thread =
115 CreateThread(NULL, 0, mac_client_thread, (
void *)context, 0, &mfc->mainThreadId)))
117 WLog_ERR(TAG,
"failed to create client thread");
124 DWORD WINAPI mac_client_thread(
void *param)
130 HANDLE events[16] = { 0 };
135 rdpContext *context = (rdpContext *)param;
137 freerdp *instance = context->instance;
139 rdpSettings *settings = context->settings;
140 status = freerdp_connect(context->instance);
144 [view setIs_connected:0];
148 [view setIs_connected:1];
150 events[nCount++] = mfc->stopEvent;
153 freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE)))
155 WLog_ERR(TAG,
"failed to get input event handle");
159 events[nCount++] = inputEvent;
163 while (!freerdp_shall_disconnect_context(instance->context))
167 if (!(nCountTmp = freerdp_get_event_handles(context, &events[nCount], 16 - nCount)))
169 WLog_ERR(TAG,
"freerdp_get_event_handles failed");
175 rc = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
177 if (rc >= (WAIT_OBJECT_0 + nCount))
179 WLog_ERR(TAG,
"WaitForMultipleObjects failed (0x%08X)", rc);
183 if (rc == WAIT_OBJECT_0)
189 if (WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0)
191 input_activity_cb(instance);
195 if (!freerdp_check_event_handles(context))
197 WLog_ERR(TAG,
"freerdp_check_event_handles failed");
204 [view setIs_connected:0];
205 freerdp_disconnect(instance);
212 - (id)initWithFrame:(NSRect)frame
214 self = [
super initWithFrame:frame];
226 [
self initializeView];
229 - (void)initializeView
233 cursors = [[NSMutableArray alloc] initWithCapacity:10];
235 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
236 initWithRect:[
self visibleRect]
237 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
238 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
239 NSTrackingActiveWhenFirstResponder
242 [
self addTrackingArea:trackingArea];
244 currentCursor = [NSCursor arrowCursor];
249 - (void)setCursor:(NSCursor *)cursor
251 self->currentCursor = cursor;
252 dispatch_async(dispatch_get_main_queue(), ^{
253 [[
self window] invalidateCursorRectsForView:self];
257 - (void)resetCursorRects
259 [
self addCursorRect:[
self visibleRect] cursor:currentCursor];
262 - (BOOL)acceptsFirstResponder
267 - (void)mouseMoved:(NSEvent *)event
269 [
super mouseMoved:event];
271 if (!
self.is_connected)
274 NSPoint loc = [event locationInWindow];
277 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
280 - (void)mouseDown:(NSEvent *)event
282 [
super mouseDown:event];
284 if (!
self.is_connected)
287 NSPoint loc = [event locationInWindow];
290 mf_press_mouse_button(context, 0, x, y, TRUE);
293 - (void)mouseUp:(NSEvent *)event
295 [
super mouseUp:event];
297 if (!
self.is_connected)
300 NSPoint loc = [event locationInWindow];
303 mf_press_mouse_button(context, 0, x, y, FALSE);
306 - (void)rightMouseDown:(NSEvent *)event
308 [
super rightMouseDown:event];
310 if (!
self.is_connected)
313 NSPoint loc = [event locationInWindow];
316 mf_press_mouse_button(context, 1, x, y, TRUE);
319 - (void)rightMouseUp:(NSEvent *)event
321 [
super rightMouseUp:event];
323 if (!
self.is_connected)
326 NSPoint loc = [event locationInWindow];
329 mf_press_mouse_button(context, 1, x, y, FALSE);
332 - (void)otherMouseDown:(NSEvent *)event
334 [
super otherMouseDown:event];
336 if (!
self.is_connected)
339 NSPoint loc = [event locationInWindow];
342 int pressed = [event buttonNumber];
343 mf_press_mouse_button(context, pressed, x, y, TRUE);
346 - (void)otherMouseUp:(NSEvent *)event
348 [
super otherMouseUp:event];
350 if (!
self.is_connected)
353 NSPoint loc = [event locationInWindow];
356 int pressed = [event buttonNumber];
357 mf_press_mouse_button(context, pressed, x, y, FALSE);
360 - (void)scrollWheel:(NSEvent *)event
363 [
super scrollWheel:event];
365 if (!
self.is_connected)
368 float dx = [event deltaX];
369 float dy = [event deltaY];
373 if (fabsf(dy) > FLT_EPSILON)
375 flags = PTR_FLAGS_WHEEL;
376 units = fabsf(dy) * 120;
379 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
381 else if (fabsf(dx) > FLT_EPSILON)
383 flags = PTR_FLAGS_HWHEEL;
384 units = fabsf(dx) * 120;
387 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
403 if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
406 mf_scale_mouse_event(context, flags | step, 0, 0);
409 - (void)mouseDragged:(NSEvent *)event
411 [
super mouseDragged:event];
413 if (!
self.is_connected)
416 NSPoint loc = [event locationInWindow];
420 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
423 static DWORD fixKeyCode(DWORD keyCode, unichar keyChar,
enum APPLE_KEYBOARD_TYPE type)
451 if (keyCode == APPLE_VK_ISO_Section)
452 keyCode = APPLE_VK_ANSI_Grave;
458 if (keyCode == APPLE_VK_ANSI_Grave)
459 keyCode = APPLE_VK_ISO_Section;
468 if (type == APPLE_KEYBOARD_TYPE_ISO)
470 if (keyCode == APPLE_VK_ANSI_Grave)
471 keyCode = APPLE_VK_ISO_Section;
472 else if (keyCode == APPLE_VK_ISO_Section)
473 keyCode = APPLE_VK_ANSI_Grave;
479 - (void)flagsChanged:(NSEvent *)event
484 DWORD modFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
486 WINPR_ASSERT(instance);
487 WINPR_ASSERT(instance->context);
489 rdpInput *input = instance->context->input;
491 #if defined(WITH_DEBUG_KBD)
492 WLog_DBG(TAG,
"flagsChanged: modFlags: 0x%04X kbdModFlags: 0x%04X", modFlags, kbdModFlags);
495 updateFlagStates(input, modFlags, kbdModFlags);
496 kbdModFlags = modFlags;
499 - (void)keyDown:(NSEvent *)event
506 NSString *characters;
511 [
self flagsChanged:event];
513 keyFlags = KBD_FLAGS_DOWN;
514 keyCode = [event keyCode];
515 characters = [event charactersIgnoringModifiers];
517 if ([characters length] > 0)
519 keyChar = [characters characterAtIndex:0];
520 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
523 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
524 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
525 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
529 #if defined(WITH_DEBUG_KBD)
530 WLog_DBG(TAG,
"keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
531 keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
534 WINPR_ASSERT(instance->context);
535 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
538 - (void)keyUp:(NSEvent *)event
545 NSString *characters;
550 [
self flagsChanged:event];
552 keyFlags = KBD_FLAGS_RELEASE;
553 keyCode = [event keyCode];
554 characters = [event charactersIgnoringModifiers];
556 if ([characters length] > 0)
558 keyChar = [characters characterAtIndex:0];
559 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
562 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
563 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
564 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
567 #if defined(WITH_DEBUG_KBD)
568 WLog_DBG(TAG,
"keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
569 keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
571 WINPR_ASSERT(instance->context);
572 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
575 static BOOL updateFlagState(rdpInput *input, DWORD modFlags, DWORD aKbdModFlags, DWORD flag)
577 BOOL press = ((modFlags & flag) != 0) && ((aKbdModFlags & flag) == 0);
578 BOOL release = ((modFlags & flag) == 0) && ((aKbdModFlags & flag) != 0);
580 const char *name = NULL;
583 if ((modFlags & flag) == (aKbdModFlags & flag))
588 case NSEventModifierFlagCapsLock:
589 name =
"NSEventModifierFlagCapsLock";
590 scancode = RDP_SCANCODE_CAPSLOCK;
591 release = press = TRUE;
593 case NSEventModifierFlagShift:
594 name =
"NSEventModifierFlagShift";
595 scancode = RDP_SCANCODE_LSHIFT;
598 case NSEventModifierFlagControl:
599 name =
"NSEventModifierFlagControl";
600 scancode = RDP_SCANCODE_LCONTROL;
603 case NSEventModifierFlagOption:
604 name =
"NSEventModifierFlagOption";
605 scancode = RDP_SCANCODE_LMENU;
608 case NSEventModifierFlagCommand:
609 name =
"NSEventModifierFlagCommand";
610 scancode = RDP_SCANCODE_LWIN;
613 case NSEventModifierFlagNumericPad:
614 name =
"NSEventModifierFlagNumericPad";
615 scancode = RDP_SCANCODE_NUMLOCK;
616 release = press = TRUE;
619 case NSEventModifierFlagHelp:
620 name =
"NSEventModifierFlagHelp";
621 scancode = RDP_SCANCODE_HELP;
624 case NSEventModifierFlagFunction:
625 name =
"NSEventModifierFlagFunction";
626 scancode = RDP_SCANCODE_HELP;
630 WLog_ERR(TAG,
"Invalid flag: 0x%08" PRIx32
", not supported", flag);
634 keyFlags = (scancode & KBDEXT);
637 #if defined(WITH_DEBUG_KBD)
638 if (press || release)
639 WLog_DBG(TAG,
"changing flag %s[0x%08" PRIx32
"] to %s", name, flag,
640 press ?
"DOWN" :
"RELEASE");
645 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode))
651 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode))
658 static BOOL updateFlagStates(rdpInput *input, UINT32 modFlags, UINT32 aKbdModFlags)
660 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagCapsLock);
661 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagShift);
662 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagControl);
663 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagOption);
664 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagCommand);
665 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagNumericPad);
669 static BOOL releaseFlagStates(rdpInput *input, UINT32 aKbdModFlags)
671 return updateFlagStates(input, 0, aKbdModFlags);
674 - (void)releaseResources
676 for (
int i = 0; i < argc; i++)
685 - (void)drawRect:(NSRect)rect
690 if (self->bitmap_context)
692 CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
693 CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context);
694 CGContextSaveGState(cgContext);
696 cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
697 CGContextDrawImage(cgContext,
698 CGRectMake(0, 0, [
self bounds].size.width, [
self bounds].size.height),
700 CGContextRestoreGState(cgContext);
701 CGImageRelease(cgImage);
706 [[NSColor blackColor] set];
707 NSRectFill([
self bounds]);
711 - (void)onPasteboardTimerFired:(NSTimer *)timer
717 NSString *formatString;
718 const char *formatType;
719 NSPasteboardItem *item;
720 changeCount = (int)[pasteboard_rd changeCount];
722 if (changeCount == pasteboard_changecount)
725 pasteboard_changecount = changeCount;
726 NSArray *items = [pasteboard_rd pasteboardItems];
728 if ([items count] < 1)
731 item = [items objectAtIndex:0];
738 for (NSString *type in [item types])
740 formatType = [type UTF8String];
742 if (strcmp(formatType,
"public.utf8-plain-text") == 0)
744 formatData = [item dataForType:type];
746 if (formatData == nil)
751 formatString = [[NSString alloc] initWithData:formatData encoding:NSUTF8StringEncoding];
753 const char *data = [formatString cStringUsingEncoding:NSUTF8StringEncoding];
754 const size_t dataLen = [formatString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
755 formatId = ClipboardRegisterFormat(mfc->clipboard,
"text/plain");
756 ClipboardSetData(mfc->clipboard, formatId, data, dataLen + 1);
757 [formatString release];
766 ClipboardEmpty(mfc->clipboard);
768 if (mfc->clipboardSync)
769 mac_cliprdr_send_client_format_list(mfc->cliprdr);
774 dispatch_async(dispatch_get_main_queue(), ^{
775 [
self->pasteboard_timer invalidate];
777 NSArray *trackingAreas =
self.trackingAreas;
779 for (NSTrackingArea *ta in trackingAreas)
781 [
self removeTrackingArea:ta];
783 releaseFlagStates(instance->context->input, kbdModFlags);
789 if (!
self.is_connected)
792 releaseFlagStates(instance->context->input, kbdModFlags);
794 freerdp_input_send_focus_in_event(instance->context->input, 0);
796 dispatch_async(dispatch_get_main_queue(), ^{
797 self->pasteboard_timer =
798 [NSTimer scheduledTimerWithTimeInterval:0.5
800 selector:@selector(onPasteboardTimerFired:)
804 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
805 initWithRect:[
self visibleRect]
806 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
807 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
808 NSTrackingActiveWhenFirstResponder
811 [
self addTrackingArea:trackingArea];
812 [trackingArea release];
816 - (void)setScrollOffset:(
int)xOffset y:(
int)yOffset w:(
int)width h:(
int)height
820 mfc->yCurrentScroll = yOffset;
821 mfc->xCurrentScroll = xOffset;
822 mfc->client_height = height;
823 mfc->client_width = width;
826 static void mac_OnChannelConnectedEventHandler(
void *context,
const ChannelConnectedEventArgs *e)
828 rdpSettings *settings;
834 settings = mfc->common.context.settings;
835 WINPR_ASSERT(settings);
837 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
839 mac_cliprdr_init(mfc, (CliprdrClientContext *)e->pInterface);
841 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
845 freerdp_client_OnChannelConnectedEventHandler(context, e);
848 static void mac_OnChannelDisconnectedEventHandler(
void *context,
849 const ChannelDisconnectedEventArgs *e)
851 rdpSettings *settings;
857 settings = mfc->common.context.settings;
858 WINPR_ASSERT(settings);
860 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
862 mac_cliprdr_uninit(mfc, (CliprdrClientContext *)e->pInterface);
864 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
868 freerdp_client_OnChannelDisconnectedEventHandler(context, e);
871 BOOL mac_pre_connect(freerdp *instance)
873 rdpSettings *settings;
876 WINPR_ASSERT(instance);
877 WINPR_ASSERT(instance->context);
879 update = instance->context->update;
880 WINPR_ASSERT(update);
882 update->BeginPaint = mac_begin_paint;
883 update->EndPaint = mac_end_paint;
884 update->DesktopResize = mac_desktop_resize;
886 settings = instance->context->settings;
887 WINPR_ASSERT(settings);
891 WLog_ERR(TAG,
"error: server hostname was not specified with /v:<server>[:port]");
899 PubSub_SubscribeChannelConnected(instance->context->pubSub, mac_OnChannelConnectedEventHandler);
900 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
901 mac_OnChannelDisconnectedEventHandler);
906 BOOL mac_post_connect(freerdp *instance)
913 WINPR_ASSERT(instance);
929 if (!gdi_init(instance, PIXEL_FORMAT_BGRX32))
932 gdi = instance->context->gdi;
933 view->bitmap_context = mac_create_bitmap_context(instance->context);
934 graphics_register_pointer(instance->context->graphics, &
rdp_pointer);
936 view->pasteboard_wr = [NSPasteboard generalPasteboard];
938 dispatch_async(dispatch_get_main_queue(), ^{
939 view->pasteboard_rd = [NSPasteboard generalPasteboard];
940 view->pasteboard_changecount = -1;
943 mfc->appleKeyboardType = mac_detect_keyboard_type();
947 void mac_post_disconnect(freerdp *instance)
951 if (!instance || !instance->context)
959 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
960 mac_OnChannelConnectedEventHandler);
961 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
962 mac_OnChannelDisconnectedEventHandler);
966 static BOOL mac_show_auth_dialog(
MRDPView *view, NSString *title,
char **username,
char **password,
971 WINPR_ASSERT(username);
972 WINPR_ASSERT(password);
973 WINPR_ASSERT(domain);
977 dialog.serverHostname = title;
980 dialog.username = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding];
983 dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding];
986 dialog.domain = [NSString stringWithCString:*domain encoding:NSUTF8StringEncoding];
995 dispatch_sync(dispatch_get_main_queue(), ^{
996 [dialog performSelectorOnMainThread:@selector(runModal:)
997 withObject:[view window]
1000 BOOL ok = dialog.modalCode;
1004 const char *submittedUsername = [dialog.username cStringUsingEncoding:NSUTF8StringEncoding];
1005 const size_t submittedUsernameLen =
1006 [dialog.username lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1007 if (submittedUsername && (submittedUsernameLen > 0))
1008 *username = strndup(submittedUsername, submittedUsernameLen);
1013 const char *submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding];
1014 const size_t submittedPasswordLen =
1015 [dialog.password lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1016 if (submittedPassword && (submittedPasswordLen > 0))
1017 *password = strndup(submittedPassword, submittedPasswordLen);
1022 const char *submittedDomain = [dialog.domain cStringUsingEncoding:NSUTF8StringEncoding];
1023 const size_t submittedDomainLen =
1024 [dialog.domain lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1025 if (submittedDomain && (submittedDomainLen > 0))
1027 *domain = strndup(submittedDomain, submittedDomainLen);
1036 static BOOL mac_authenticate_raw(freerdp *instance,
char **username,
char **password,
char **domain,
1037 rdp_auth_reason reason)
1039 BOOL pinOnly = FALSE;
1041 WINPR_ASSERT(instance);
1042 WINPR_ASSERT(instance->context);
1043 WINPR_ASSERT(instance->context->settings);
1045 const rdpSettings *settings = instance->context->settings;
1048 NSString *title = NULL;
1052 case AUTH_SMARTCARD_PIN:
1055 stringWithFormat:@"%@:%u",
1056 [NSString stringWithCString:freerdp_settings_get_string(
1057 settings, FreeRDP_ServerHostname)
1058 encoding:NSUTF8StringEncoding],
1059 freerdp_settings_get_uint32(settings, FreeRDP_ServerPort)];
1065 stringWithFormat:@"%@:%u",
1066 [NSString stringWithCString:freerdp_settings_get_string(
1067 settings, FreeRDP_ServerHostname)
1068 encoding:NSUTF8StringEncoding],
1069 freerdp_settings_get_uint32(settings, FreeRDP_ServerPort)];
1075 stringWithFormat:@"%@:%u",
1076 [NSString stringWithCString:freerdp_settings_get_string(
1077 settings, FreeRDP_GatewayHostname)
1078 encoding:NSUTF8StringEncoding],
1079 freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort)];
1085 if (!username || !password || !domain)
1088 if (!*username && !pinOnly)
1090 if (!mac_show_auth_dialog(view, title, username, password, domain))
1093 else if (!*domain && !pinOnly)
1095 if (!mac_show_auth_dialog(view, title, username, password, domain))
1098 else if (!*password)
1100 if (!mac_show_auth_dialog(view, title, username, password, domain))
1115 BOOL mac_authenticate_ex(freerdp *instance,
char **username,
char **password,
char **domain,
1116 rdp_auth_reason reason)
1118 WINPR_ASSERT(instance);
1119 WINPR_ASSERT(username);
1120 WINPR_ASSERT(password);
1121 WINPR_ASSERT(domain);
1131 case AUTH_SMARTCARD_PIN:
1132 if ((*username) && (*password))
1143 return mac_authenticate_raw(instance, username, password, domain, reason);
1146 DWORD mac_verify_certificate_ex(freerdp *instance,
const char *host, UINT16 port,
1147 const char *common_name,
const char *subject,
const char *issuer,
1148 const char *fingerprint, DWORD flags)
1153 const char *type =
"RDP-Server";
1154 char hostname[8192] = { 0 };
1156 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1157 type =
"RDP-Gateway";
1159 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1160 type =
"RDP-Redirect";
1162 sprintf_s(hostname,
sizeof(hostname),
"%s %s:%" PRIu16, type, host, port);
1163 dialog.serverHostname = [NSString stringWithCString:hostname encoding:NSUTF8StringEncoding];
1164 dialog.commonName = [NSString stringWithCString:common_name encoding:NSUTF8StringEncoding];
1165 dialog.subject = [NSString stringWithCString:subject encoding:NSUTF8StringEncoding];
1166 dialog.issuer = [NSString stringWithCString:issuer encoding:NSUTF8StringEncoding];
1167 dialog.fingerprint = [NSString stringWithCString:fingerprint encoding:NSUTF8StringEncoding];
1169 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1170 dialog.hostMismatch = TRUE;
1172 if (flags & VERIFY_CERT_FLAG_CHANGED)
1173 dialog.changed = TRUE;
1175 [dialog performSelectorOnMainThread:@selector(runModal:)
1176 withObject:[view window]
1177 waitUntilDone:TRUE];
1178 return dialog.result;
1181 DWORD mac_verify_changed_certificate_ex(freerdp *instance,
const char *host, UINT16 port,
1182 const char *common_name,
const char *subject,
1183 const char *issuer,
const char *fingerprint,
1184 const char *old_subject,
const char *old_issuer,
1185 const char *old_fingerprint, DWORD flags)
1190 const char *type =
"RDP-Server";
1191 char hostname[8192];
1193 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1194 type =
"RDP-Gateway";
1196 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1197 type =
"RDP-Redirect";
1199 sprintf_s(hostname,
sizeof(hostname),
"%s %s:%" PRIu16, type, host, port);
1200 dialog.serverHostname = [NSString stringWithCString:hostname encoding:NSUTF8StringEncoding];
1201 dialog.commonName = [NSString stringWithCString:common_name encoding:NSUTF8StringEncoding];
1202 dialog.subject = [NSString stringWithCString:subject encoding:NSUTF8StringEncoding];
1203 dialog.issuer = [NSString stringWithCString:issuer encoding:NSUTF8StringEncoding];
1204 dialog.fingerprint = [NSString stringWithCString:fingerprint encoding:NSUTF8StringEncoding];
1206 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1207 dialog.hostMismatch = TRUE;
1209 if (flags & VERIFY_CERT_FLAG_CHANGED)
1210 dialog.changed = TRUE;
1212 [dialog performSelectorOnMainThread:@selector(runModal:)
1213 withObject:[view window]
1214 waitUntilDone:TRUE];
1215 return dialog.result;
1218 int mac_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
1220 const char *str_data = freerdp_get_logon_error_info_data(data);
1221 const char *str_type = freerdp_get_logon_error_info_type(type);
1223 WLog_INFO(TAG,
"Logon Error Info %s [%s]", str_data, str_type);
1227 BOOL mf_Pointer_New(rdpContext *context, rdpPointer *pointer)
1236 NSBitmapImageRep *bmiRep;
1242 if (!mfc || !context || !pointer)
1251 rect.size.width = pointer->width;
1252 rect.size.height = pointer->height;
1253 rect.origin.x = pointer->xPos;
1254 rect.origin.y = pointer->yPos;
1255 cursor_data = (BYTE *)malloc(rect.size.width * rect.size.height * 4);
1260 mrdpCursor->cursor_data = cursor_data;
1261 format = PIXEL_FORMAT_RGBA32;
1263 if (!freerdp_image_copy_from_pointer_data(cursor_data, format, 0, 0, 0, pointer->width,
1264 pointer->height, pointer->xorMaskData,
1265 pointer->lengthXorMask, pointer->andMaskData,
1266 pointer->lengthAndMask, pointer->xorBpp, NULL))
1269 mrdpCursor->cursor_data = NULL;
1274 bmiRep = [[NSBitmapImageRep alloc]
1275 initWithBitmapDataPlanes:(unsigned char **)&cursor_data
1276 pixelsWide:rect.size.width
1277 pixelsHigh:rect.size.height
1282 colorSpaceName:NSDeviceRGBColorSpace
1284 bytesPerRow:rect.size.width * FreeRDPGetBytesPerPixel(format)
1286 mrdpCursor->bmiRep = bmiRep;
1288 image = [[NSImage alloc] initWithSize:[bmiRep size]];
1289 [image addRepresentation:bmiRep];
1290 mrdpCursor->nsImage = image;
1292 hotSpot.x = pointer->xPos;
1293 hotSpot.y = pointer->yPos;
1294 cursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot];
1295 mrdpCursor->nsCursor = cursor;
1296 mrdpCursor->pointer = pointer;
1299 [ma addObject:mrdpCursor];
1303 void mf_Pointer_Free(rdpContext *context, rdpPointer *pointer)
1307 NSMutableArray *ma = view->cursors;
1311 if (cursor->pointer == pointer)
1313 cursor->nsImage = nil;
1314 cursor->nsCursor = nil;
1315 cursor->bmiRep = nil;
1316 free(cursor->cursor_data);
1317 [ma removeObject:cursor];
1323 BOOL mf_Pointer_Set(rdpContext *context, rdpPointer *pointer)
1327 NSMutableArray *ma = view->cursors;
1331 if (cursor->pointer == pointer)
1333 [view setCursor:cursor->nsCursor];
1338 NSLog(
@"Cursor not found");
1342 BOOL mf_Pointer_SetNull(rdpContext *context)
1347 BOOL mf_Pointer_SetDefault(rdpContext *context)
1351 [view setCursor:[NSCursor arrowCursor]];
1355 static BOOL mf_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y)
1366 CGContextRef mac_create_bitmap_context(rdpContext *context)
1368 CGContextRef bitmap_context;
1369 rdpGdi *gdi = context->gdi;
1370 UINT32 bpp = FreeRDPGetBytesPerPixel(gdi->dstFormat);
1371 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1375 bitmap_context = CGBitmapContextCreate(
1376 gdi->primary_buffer, gdi->width, gdi->height, 5, gdi->stride, colorSpace,
1377 kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
1381 bitmap_context = CGBitmapContextCreate(
1382 gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->stride, colorSpace,
1383 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
1386 CGColorSpaceRelease(colorSpace);
1387 return bitmap_context;
1390 BOOL mac_begin_paint(rdpContext *context)
1392 rdpGdi *gdi = context->gdi;
1397 gdi->primary->hdc->hwnd->invalid->null = TRUE;
1401 BOOL mac_end_paint(rdpContext *context)
1414 ww = mfc->client_width;
1415 wh = mfc->client_height;
1419 if ((!context) || (!context->gdi))
1422 if (context->gdi->primary->hdc->hwnd->invalid->null)
1425 invalid = gdi->primary->hdc->hwnd->invalid;
1426 newDrawRect.origin.x = invalid->x;
1427 newDrawRect.origin.y = invalid->y;
1428 newDrawRect.size.width = invalid->w;
1429 newDrawRect.size.height = invalid->h;
1432 (ww != dw || wh != dh))
1434 newDrawRect.origin.y = newDrawRect.origin.y * wh / dh - 1;
1435 newDrawRect.size.height = newDrawRect.size.height * wh / dh + 1;
1436 newDrawRect.origin.x = newDrawRect.origin.x * ww / dw - 1;
1437 newDrawRect.size.width = newDrawRect.size.width * ww / dw + 1;
1441 newDrawRect.origin.y = newDrawRect.origin.y - 1;
1442 newDrawRect.size.height = newDrawRect.size.height + 1;
1443 newDrawRect.origin.x = newDrawRect.origin.x - 1;
1444 newDrawRect.size.width = newDrawRect.size.width + 1;
1447 windows_to_apple_cords(mfc->view, &newDrawRect);
1448 dispatch_sync(dispatch_get_main_queue(), ^{
1449 [view setNeedsDisplayInRect:newDrawRect];
1451 gdi->primary->hdc->hwnd->ninvalid = 0;
1455 BOOL mac_desktop_resize(rdpContext *context)
1457 ResizeWindowEventArgs e;
1460 rdpSettings *settings = context->settings;
1470 CGContextRef old_context = view->bitmap_context;
1471 view->bitmap_context = NULL;
1472 CGContextRelease(old_context);
1476 if (!gdi_resize(context->gdi, mfc->width, mfc->height))
1479 view->bitmap_context = mac_create_bitmap_context(context);
1481 if (!view->bitmap_context)
1484 mfc->client_width = mfc->width;
1485 mfc->client_height = mfc->height;
1486 [view setFrameSize:NSMakeSize(mfc->width, mfc->height)];
1487 EventArgsInit(&e,
"mfreerdp");
1490 PubSub_OnResizeWindow(context->pubSub, context, &e);
1494 void input_activity_cb(freerdp *instance)
1498 wMessageQueue *queue;
1500 queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
1504 while (MessageQueue_Peek(queue, &message, TRUE))
1506 status = freerdp_message_queue_process_message(instance, FREERDP_INPUT_MESSAGE_QUEUE,
1515 WLog_ERR(TAG,
"input_activity_cb: No queue!");
1527 void windows_to_apple_cords(
MRDPView *view, NSRect *r)
1529 dispatch_sync(dispatch_get_main_queue(), ^{
1530 r->origin.y = [view frame].size.height - (r->origin.y + r->size.height);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.