20#include <winpr/windows.h>
27#import "PasswordDialog.h"
28#import "CertificateDialog.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")
54static BOOL mf_Pointer_New(rdpContext *context, rdpPointer *pointer);
55static void mf_Pointer_Free(rdpContext *context, rdpPointer *pointer);
56static BOOL mf_Pointer_Set(rdpContext *context, rdpPointer *pointer);
57static BOOL mf_Pointer_SetNull(rdpContext *context);
58static BOOL mf_Pointer_SetDefault(rdpContext *context);
59static BOOL mf_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y);
61static BOOL mac_begin_paint(rdpContext *context);
62static BOOL mac_end_paint(rdpContext *context);
63static BOOL mac_desktop_resize(rdpContext *context);
65static void input_activity_cb(freerdp *instance);
67static DWORD WINAPI mac_client_thread(
void *param);
68static void windows_to_apple_cords(
MRDPView *view, NSRect *r);
69static 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 if (PubSub_OnEmbedWindow(context->pubSub, context, &e) < 0)
97 NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
98 NSRect screenFrame = [screen frame];
106 [
self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
110 [
self exitFullScreenModeWithOptions:nil];
116 if (!(mfc->common.thread =
117 CreateThread(
nullptr, 0, mac_client_thread, (
void *)context, 0, &mfc->mainThreadId)))
119 WLog_ERR(TAG,
"failed to create client thread");
126DWORD WINAPI mac_client_thread(
void *param)
132 HANDLE events[16] = WINPR_C_ARRAY_INIT;
137 rdpContext *context = (rdpContext *)param;
139 freerdp *instance = context->instance;
141 rdpSettings *settings = context->settings;
142 status = freerdp_connect(context->instance);
146 [view setIs_connected:0];
150 [view setIs_connected:1];
152 events[nCount++] = mfc->stopEvent;
155 freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE)))
157 WLog_ERR(TAG,
"failed to get input event handle");
161 events[nCount++] = inputEvent;
165 while (!freerdp_shall_disconnect_context(instance->context))
169 if (!(nCountTmp = freerdp_get_event_handles(context, &events[nCount], 16 - nCount)))
171 WLog_ERR(TAG,
"freerdp_get_event_handles failed");
177 rc = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
179 if (rc >= (WAIT_OBJECT_0 + nCount))
181 WLog_ERR(TAG,
"WaitForMultipleObjects failed (0x%08X)", rc);
185 if (rc == WAIT_OBJECT_0)
191 if (WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0)
193 input_activity_cb(instance);
197 if (!freerdp_check_event_handles(context))
199 WLog_ERR(TAG,
"freerdp_check_event_handles failed");
206 [view setIs_connected:0];
207 freerdp_disconnect(instance);
214- (id)initWithFrame:(NSRect)frame
216 self = [
super initWithFrame:frame];
228 [
self initializeView];
231- (void)initializeView
235 cursors = [[NSMutableArray alloc] initWithCapacity:10];
237 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
238 initWithRect:[
self visibleRect]
239 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
240 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
241 NSTrackingActiveWhenFirstResponder
244 [
self addTrackingArea:trackingArea];
246 currentCursor = [NSCursor arrowCursor];
251- (void)setCursor:(NSCursor *)cursor
253 self->currentCursor = cursor;
254 dispatch_async(dispatch_get_main_queue(), ^{
255 [[
self window] invalidateCursorRectsForView:self];
259- (void)resetCursorRects
261 [
self addCursorRect:[
self visibleRect] cursor:currentCursor];
264- (BOOL)acceptsFirstResponder
269- (void)mouseMoved:(NSEvent *)event
271 [
super mouseMoved:event];
273 if (!
self.is_connected)
276 NSPoint loc = [event locationInWindow];
279 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
282- (void)mouseDown:(NSEvent *)event
284 [
super mouseDown:event];
286 if (!
self.is_connected)
289 NSPoint loc = [event locationInWindow];
292 mf_press_mouse_button(context, 0, x, y, TRUE);
295- (void)mouseUp:(NSEvent *)event
297 [
super mouseUp:event];
299 if (!
self.is_connected)
302 NSPoint loc = [event locationInWindow];
305 mf_press_mouse_button(context, 0, x, y, FALSE);
308- (void)rightMouseDown:(NSEvent *)event
310 [
super rightMouseDown:event];
312 if (!
self.is_connected)
315 NSPoint loc = [event locationInWindow];
318 mf_press_mouse_button(context, 1, x, y, TRUE);
321- (void)rightMouseUp:(NSEvent *)event
323 [
super rightMouseUp:event];
325 if (!
self.is_connected)
328 NSPoint loc = [event locationInWindow];
331 mf_press_mouse_button(context, 1, x, y, FALSE);
334- (void)otherMouseDown:(NSEvent *)event
336 [
super otherMouseDown:event];
338 if (!
self.is_connected)
341 NSPoint loc = [event locationInWindow];
344 int pressed = [event buttonNumber];
345 mf_press_mouse_button(context, pressed, x, y, TRUE);
348- (void)otherMouseUp:(NSEvent *)event
350 [
super otherMouseUp:event];
352 if (!
self.is_connected)
355 NSPoint loc = [event locationInWindow];
358 int pressed = [event buttonNumber];
359 mf_press_mouse_button(context, pressed, x, y, FALSE);
362- (void)scrollWheel:(NSEvent *)event
365 [
super scrollWheel:event];
367 if (!
self.is_connected)
370 float dx = [event deltaX];
371 float dy = [event deltaY];
375 if (fabsf(dy) > FLT_EPSILON)
377 flags = PTR_FLAGS_WHEEL;
378 units = fabsf(dy) * 120;
381 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
383 else if (fabsf(dx) > FLT_EPSILON)
385 flags = PTR_FLAGS_HWHEEL;
386 units = fabsf(dx) * 120;
389 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
405 if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
408 mf_scale_mouse_event(context, flags | step, 0, 0);
411- (void)mouseDragged:(NSEvent *)event
413 [
super mouseDragged:event];
415 if (!
self.is_connected)
418 NSPoint loc = [event locationInWindow];
422 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
425static DWORD fixKeyCode(DWORD keyCode, unichar keyChar,
enum APPLE_KEYBOARD_TYPE type)
453 if (keyCode == APPLE_VK_ISO_Section)
454 keyCode = APPLE_VK_ANSI_Grave;
460 if (keyCode == APPLE_VK_ANSI_Grave)
461 keyCode = APPLE_VK_ISO_Section;
470 if (type == APPLE_KEYBOARD_TYPE_ISO)
472 if (keyCode == APPLE_VK_ANSI_Grave)
473 keyCode = APPLE_VK_ISO_Section;
474 else if (keyCode == APPLE_VK_ISO_Section)
475 keyCode = APPLE_VK_ANSI_Grave;
481- (void)flagsChanged:(NSEvent *)event
486 DWORD modFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
488 WINPR_ASSERT(instance);
489 WINPR_ASSERT(instance->context);
491 rdpInput *input = instance->context->input;
493#if defined(WITH_DEBUG_KBD)
494 WLog_DBG(TAG,
"flagsChanged: modFlags: 0x%04X kbdModFlags: 0x%04X", modFlags, kbdModFlags);
497 updateFlagStates(input, modFlags, kbdModFlags);
498 kbdModFlags = modFlags;
501- (void)keyDown:(NSEvent *)event
508 NSString *characters;
513 [
self flagsChanged:event];
515 keyFlags = KBD_FLAGS_DOWN;
516 keyCode = [event keyCode];
517 characters = [event charactersIgnoringModifiers];
519 if ([characters length] > 0)
521 keyChar = [characters characterAtIndex:0];
522 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
525 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
526 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
527 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
531#if defined(WITH_DEBUG_KBD)
532 WLog_DBG(TAG,
"keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
533 keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
536 WINPR_ASSERT(instance->context);
537 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
540- (void)keyUp:(NSEvent *)event
547 NSString *characters;
552 [
self flagsChanged:event];
554 keyFlags = KBD_FLAGS_RELEASE;
555 keyCode = [event keyCode];
556 characters = [event charactersIgnoringModifiers];
558 if ([characters length] > 0)
560 keyChar = [characters characterAtIndex:0];
561 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
564 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
565 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
566 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
569#if defined(WITH_DEBUG_KBD)
570 WLog_DBG(TAG,
"keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
571 keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
573 WINPR_ASSERT(instance->context);
574 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
577static BOOL updateFlagState(rdpInput *input, DWORD modFlags, DWORD aKbdModFlags, DWORD flag)
579 BOOL press = ((modFlags & flag) != 0) && ((aKbdModFlags & flag) == 0);
580 BOOL release = ((modFlags & flag) == 0) && ((aKbdModFlags & flag) != 0);
582 const char *name =
nullptr;
585 if ((modFlags & flag) == (aKbdModFlags & flag))
590 case NSEventModifierFlagCapsLock:
591 name =
"NSEventModifierFlagCapsLock";
592 scancode = RDP_SCANCODE_CAPSLOCK;
593 release = press = TRUE;
595 case NSEventModifierFlagShift:
596 name =
"NSEventModifierFlagShift";
597 scancode = RDP_SCANCODE_LSHIFT;
600 case NSEventModifierFlagControl:
601 name =
"NSEventModifierFlagControl";
602 scancode = RDP_SCANCODE_LCONTROL;
605 case NSEventModifierFlagOption:
606 name =
"NSEventModifierFlagOption";
607 scancode = RDP_SCANCODE_LMENU;
610 case NSEventModifierFlagCommand:
611 name =
"NSEventModifierFlagCommand";
612 scancode = RDP_SCANCODE_LWIN;
615 case NSEventModifierFlagNumericPad:
616 name =
"NSEventModifierFlagNumericPad";
617 scancode = RDP_SCANCODE_NUMLOCK;
618 release = press = TRUE;
621 case NSEventModifierFlagHelp:
622 name =
"NSEventModifierFlagHelp";
623 scancode = RDP_SCANCODE_HELP;
626 case NSEventModifierFlagFunction:
627 name =
"NSEventModifierFlagFunction";
628 scancode = RDP_SCANCODE_HELP;
632 WLog_ERR(TAG,
"Invalid flag: 0x%08" PRIx32
", not supported", flag);
636 keyFlags = (scancode & KBDEXT);
639#if defined(WITH_DEBUG_KBD)
640 if (press || release)
641 WLog_DBG(TAG,
"changing flag %s[0x%08" PRIx32
"] to %s", name, flag,
642 press ?
"DOWN" :
"RELEASE");
647 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode))
653 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode))
660static BOOL updateFlagStates(rdpInput *input, UINT32 modFlags, UINT32 aKbdModFlags)
662 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagCapsLock);
663 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagShift);
664 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagControl);
665 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagOption);
666 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagCommand);
667 updateFlagState(input, modFlags, aKbdModFlags, NSEventModifierFlagNumericPad);
671static BOOL releaseFlagStates(rdpInput *input, UINT32 aKbdModFlags)
673 return updateFlagStates(input, 0, aKbdModFlags);
676- (void)releaseResources
678 for (
int i = 0; i < argc; i++)
687- (void)drawRect:(NSRect)rect
692 if (self->bitmap_context)
694 CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
695 CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context);
696 CGContextSaveGState(cgContext);
698 cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
699 CGContextDrawImage(cgContext,
700 CGRectMake(0, 0, [
self bounds].size.width, [
self bounds].size.height),
702 CGContextRestoreGState(cgContext);
703 CGImageRelease(cgImage);
708 [[NSColor blackColor] set];
709 NSRectFill([
self bounds]);
713- (void)onPasteboardTimerFired:(NSTimer *)timer
719 NSString *formatString;
720 const char *formatType;
721 NSPasteboardItem *item;
722 changeCount = (int)[pasteboard_rd changeCount];
724 if (changeCount == pasteboard_changecount)
727 pasteboard_changecount = changeCount;
728 NSArray *items = [pasteboard_rd pasteboardItems];
730 if ([items count] < 1)
733 item = [items objectAtIndex:0];
740 for (NSString *type in [item types])
742 formatType = [type UTF8String];
744 if (strcmp(formatType,
"public.utf8-plain-text") == 0)
746 formatData = [item dataForType:type];
748 if (formatData == nil)
753 formatString = [[NSString alloc] initWithData:formatData encoding:NSUTF8StringEncoding];
755 const char *data = [formatString cStringUsingEncoding:NSUTF8StringEncoding];
756 const size_t dataLen = [formatString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
757 formatId = ClipboardRegisterFormat(mfc->clipboard,
"text/plain");
758 ClipboardSetData(mfc->clipboard, formatId, data, dataLen + 1);
759 [formatString release];
768 ClipboardEmpty(mfc->clipboard);
770 if (mfc->clipboardSync)
771 mac_cliprdr_send_client_format_list(mfc->cliprdr);
776 dispatch_async(dispatch_get_main_queue(), ^{
777 [
self->pasteboard_timer invalidate];
779 NSArray *trackingAreas =
self.trackingAreas;
781 for (NSTrackingArea *ta in trackingAreas)
783 [
self removeTrackingArea:ta];
785 releaseFlagStates(instance->context->input, kbdModFlags);
791 if (!
self.is_connected)
794 releaseFlagStates(instance->context->input, kbdModFlags);
796 freerdp_input_send_focus_in_event(instance->context->input, 0);
798 dispatch_async(dispatch_get_main_queue(), ^{
799 self->pasteboard_timer =
800 [NSTimer scheduledTimerWithTimeInterval:0.5
802 selector:@selector(onPasteboardTimerFired:)
806 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
807 initWithRect:[
self visibleRect]
808 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
809 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
810 NSTrackingActiveWhenFirstResponder
813 [
self addTrackingArea:trackingArea];
814 [trackingArea release];
818- (void)setScrollOffset:(
int)xOffset y:(
int)yOffset w:(
int)width h:(
int)height
822 mfc->yCurrentScroll = yOffset;
823 mfc->xCurrentScroll = xOffset;
824 mfc->client_height = height;
825 mfc->client_width = width;
828static void mac_OnChannelConnectedEventHandler(
void *context,
const ChannelConnectedEventArgs *e)
830 rdpSettings *settings;
836 settings = mfc->common.context.settings;
837 WINPR_ASSERT(settings);
839 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
841 mac_cliprdr_init(mfc, (CliprdrClientContext *)e->pInterface);
843 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
847 freerdp_client_OnChannelConnectedEventHandler(context, e);
850static void mac_OnChannelDisconnectedEventHandler(
void *context,
851 const ChannelDisconnectedEventArgs *e)
853 rdpSettings *settings;
859 settings = mfc->common.context.settings;
860 WINPR_ASSERT(settings);
862 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
864 mac_cliprdr_uninit(mfc, (CliprdrClientContext *)e->pInterface);
866 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
870 freerdp_client_OnChannelDisconnectedEventHandler(context, e);
873BOOL mac_pre_connect(freerdp *instance)
875 rdpSettings *settings;
878 WINPR_ASSERT(instance);
879 WINPR_ASSERT(instance->context);
881 update = instance->context->update;
882 WINPR_ASSERT(update);
884 update->BeginPaint = mac_begin_paint;
885 update->EndPaint = mac_end_paint;
886 update->DesktopResize = mac_desktop_resize;
888 settings = instance->context->settings;
889 WINPR_ASSERT(settings);
893 WLog_ERR(TAG,
"error: server hostname was not specified with /v:<server>[:port]");
901 PubSub_SubscribeChannelConnected(instance->context->pubSub, mac_OnChannelConnectedEventHandler);
902 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
903 mac_OnChannelDisconnectedEventHandler);
908BOOL mac_post_connect(freerdp *instance)
915 WINPR_ASSERT(instance);
931 if (!gdi_init(instance, PIXEL_FORMAT_BGRX32))
934 gdi = instance->context->gdi;
935 view->bitmap_context = mac_create_bitmap_context(instance->context);
936 graphics_register_pointer(instance->context->graphics, &
rdp_pointer);
938 view->pasteboard_wr = [NSPasteboard generalPasteboard];
940 dispatch_async(dispatch_get_main_queue(), ^{
941 view->pasteboard_rd = [NSPasteboard generalPasteboard];
942 view->pasteboard_changecount = -1;
945 mfc->appleKeyboardType = mac_detect_keyboard_type();
949void mac_post_disconnect(freerdp *instance)
953 if (!instance || !instance->context)
961 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
962 mac_OnChannelConnectedEventHandler);
963 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
964 mac_OnChannelDisconnectedEventHandler);
968static BOOL mac_show_auth_dialog(
MRDPView *view, NSString *title,
char **username,
char **password,
973 WINPR_ASSERT(username);
974 WINPR_ASSERT(password);
975 WINPR_ASSERT(domain);
979 dialog.serverHostname = title;
982 dialog.username = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding];
985 dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding];
988 dialog.domain = [NSString stringWithCString:*domain encoding:NSUTF8StringEncoding];
997 dispatch_sync(dispatch_get_main_queue(), ^{
998 [dialog performSelectorOnMainThread:@selector(runModal:)
999 withObject:[view window]
1000 waitUntilDone:TRUE];
1002 BOOL ok = dialog.modalCode;
1006 const char *submittedUsername = [dialog.username cStringUsingEncoding:NSUTF8StringEncoding];
1007 const size_t submittedUsernameLen =
1008 [dialog.username lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1009 if (submittedUsername && (submittedUsernameLen > 0))
1010 *username = strndup(submittedUsername, submittedUsernameLen);
1015 const char *submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding];
1016 const size_t submittedPasswordLen =
1017 [dialog.password lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1018 if (submittedPassword && (submittedPasswordLen > 0))
1019 *password = strndup(submittedPassword, submittedPasswordLen);
1024 const char *submittedDomain = [dialog.domain cStringUsingEncoding:NSUTF8StringEncoding];
1025 const size_t submittedDomainLen =
1026 [dialog.domain lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1027 if (submittedDomain && (submittedDomainLen > 0))
1029 *domain = strndup(submittedDomain, submittedDomainLen);
1038static BOOL mac_authenticate_raw(freerdp *instance,
char **username,
char **password,
char **domain,
1039 rdp_auth_reason reason)
1041 BOOL pinOnly = FALSE;
1043 WINPR_ASSERT(instance);
1044 WINPR_ASSERT(instance->context);
1045 WINPR_ASSERT(instance->context->settings);
1047 const rdpSettings *settings = instance->context->settings;
1050 NSString *title =
nullptr;
1054 case AUTH_SMARTCARD_PIN:
1057 stringWithFormat:@"%@:%u",
1058 [NSString stringWithCString:freerdp_settings_get_string(
1059 settings, FreeRDP_ServerHostname)
1060 encoding:NSUTF8StringEncoding],
1061 freerdp_settings_get_uint32(settings, FreeRDP_ServerPort)];
1067 stringWithFormat:@"%@:%u",
1068 [NSString stringWithCString:freerdp_settings_get_string(
1069 settings, FreeRDP_ServerHostname)
1070 encoding:NSUTF8StringEncoding],
1071 freerdp_settings_get_uint32(settings, FreeRDP_ServerPort)];
1077 stringWithFormat:@"%@:%u",
1078 [NSString stringWithCString:freerdp_settings_get_string(
1079 settings, FreeRDP_GatewayHostname)
1080 encoding:NSUTF8StringEncoding],
1081 freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort)];
1087 if (!username || !password || !domain)
1090 if (!*username && !pinOnly)
1092 if (!mac_show_auth_dialog(view, title, username, password, domain))
1095 else if (!*domain && !pinOnly)
1097 if (!mac_show_auth_dialog(view, title, username, password, domain))
1100 else if (!*password)
1102 if (!mac_show_auth_dialog(view, title, username, password, domain))
1111 *username =
nullptr;
1113 *password =
nullptr;
1117BOOL mac_authenticate_ex(freerdp *instance,
char **username,
char **password,
char **domain,
1118 rdp_auth_reason reason)
1120 WINPR_ASSERT(instance);
1121 WINPR_ASSERT(username);
1122 WINPR_ASSERT(password);
1123 WINPR_ASSERT(domain);
1133 case AUTH_SMARTCARD_PIN:
1134 if ((*username) && (*password))
1145 return mac_authenticate_raw(instance, username, password, domain, reason);
1148DWORD mac_verify_certificate_ex(freerdp *instance,
const char *host, UINT16 port,
1149 const char *common_name,
const char *subject,
const char *issuer,
1150 const char *fingerprint, DWORD flags)
1155 const char *type =
"RDP-Server";
1156 char hostname[8192] = WINPR_C_ARRAY_INIT;
1158 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1159 type =
"RDP-Gateway";
1161 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1162 type =
"RDP-Redirect";
1164 sprintf_s(hostname,
sizeof(hostname),
"%s %s:%" PRIu16, type, host, port);
1165 dialog.serverHostname = [NSString stringWithCString:hostname encoding:NSUTF8StringEncoding];
1166 dialog.commonName = [NSString stringWithCString:common_name encoding:NSUTF8StringEncoding];
1167 dialog.subject = [NSString stringWithCString:subject encoding:NSUTF8StringEncoding];
1168 dialog.issuer = [NSString stringWithCString:issuer encoding:NSUTF8StringEncoding];
1169 dialog.fingerprint = [NSString stringWithCString:fingerprint encoding:NSUTF8StringEncoding];
1171 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1172 dialog.hostMismatch = TRUE;
1174 if (flags & VERIFY_CERT_FLAG_CHANGED)
1175 dialog.changed = TRUE;
1177 [dialog performSelectorOnMainThread:@selector(runModal:)
1178 withObject:[view window]
1179 waitUntilDone:TRUE];
1180 return dialog.result;
1183DWORD mac_verify_changed_certificate_ex(freerdp *instance,
const char *host, UINT16 port,
1184 const char *common_name,
const char *subject,
1185 const char *issuer,
const char *fingerprint,
1186 const char *old_subject,
const char *old_issuer,
1187 const char *old_fingerprint, DWORD flags)
1192 const char *type =
"RDP-Server";
1193 char hostname[8192];
1195 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1196 type =
"RDP-Gateway";
1198 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1199 type =
"RDP-Redirect";
1201 sprintf_s(hostname,
sizeof(hostname),
"%s %s:%" PRIu16, type, host, port);
1202 dialog.serverHostname = [NSString stringWithCString:hostname encoding:NSUTF8StringEncoding];
1203 dialog.commonName = [NSString stringWithCString:common_name encoding:NSUTF8StringEncoding];
1204 dialog.subject = [NSString stringWithCString:subject encoding:NSUTF8StringEncoding];
1205 dialog.issuer = [NSString stringWithCString:issuer encoding:NSUTF8StringEncoding];
1206 dialog.fingerprint = [NSString stringWithCString:fingerprint encoding:NSUTF8StringEncoding];
1208 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1209 dialog.hostMismatch = TRUE;
1211 if (flags & VERIFY_CERT_FLAG_CHANGED)
1212 dialog.changed = TRUE;
1214 [dialog performSelectorOnMainThread:@selector(runModal:)
1215 withObject:[view window]
1216 waitUntilDone:TRUE];
1217 return dialog.result;
1220int mac_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
1222 const char *str_data = freerdp_get_logon_error_info_data(data);
1223 const char *str_type = freerdp_get_logon_error_info_type(type);
1225 WLog_INFO(TAG,
"Logon Error Info %s [%s]", str_data, str_type);
1229BOOL mf_Pointer_New(rdpContext *context, rdpPointer *pointer)
1238 NSBitmapImageRep *bmiRep;
1244 if (!mfc || !context || !pointer)
1253 rect.size.width = pointer->width;
1254 rect.size.height = pointer->height;
1255 rect.origin.x = pointer->xPos;
1256 rect.origin.y = pointer->yPos;
1257 cursor_data = (BYTE *)malloc(rect.size.width * rect.size.height * 4);
1262 mrdpCursor->cursor_data = cursor_data;
1263 format = PIXEL_FORMAT_RGBA32;
1265 if (!freerdp_image_copy_from_pointer_data(cursor_data, format, 0, 0, 0, pointer->width,
1266 pointer->height, pointer->xorMaskData,
1267 pointer->lengthXorMask, pointer->andMaskData,
1268 pointer->lengthAndMask, pointer->xorBpp,
nullptr))
1271 mrdpCursor->cursor_data =
nullptr;
1276 bmiRep = [[NSBitmapImageRep alloc]
1277 initWithBitmapDataPlanes:(unsigned char **)&cursor_data
1278 pixelsWide:rect.size.width
1279 pixelsHigh:rect.size.height
1284 colorSpaceName:NSDeviceRGBColorSpace
1286 bytesPerRow:rect.size.width * FreeRDPGetBytesPerPixel(format)
1288 mrdpCursor->bmiRep = bmiRep;
1290 image = [[NSImage alloc] initWithSize:[bmiRep size]];
1291 [image addRepresentation:bmiRep];
1292 mrdpCursor->nsImage = image;
1294 hotSpot.x = pointer->xPos;
1295 hotSpot.y = pointer->yPos;
1296 cursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot];
1297 mrdpCursor->nsCursor = cursor;
1298 mrdpCursor->pointer = pointer;
1301 [ma addObject:mrdpCursor];
1305void mf_Pointer_Free(rdpContext *context, rdpPointer *pointer)
1309 NSMutableArray *ma = view->cursors;
1313 if (cursor->pointer == pointer)
1315 cursor->nsImage = nil;
1316 cursor->nsCursor = nil;
1317 cursor->bmiRep = nil;
1318 free(cursor->cursor_data);
1319 [ma removeObject:cursor];
1325BOOL mf_Pointer_Set(rdpContext *context, rdpPointer *pointer)
1329 NSMutableArray *ma = view->cursors;
1333 if (cursor->pointer == pointer)
1335 [view setCursor:cursor->nsCursor];
1340 NSLog(
@"Cursor not found");
1344BOOL mf_Pointer_SetNull(rdpContext *context)
1349BOOL mf_Pointer_SetDefault(rdpContext *context)
1353 [view setCursor:[NSCursor arrowCursor]];
1357static BOOL mf_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y)
1368CGContextRef mac_create_bitmap_context(rdpContext *context)
1370 CGContextRef bitmap_context;
1371 rdpGdi *gdi = context->gdi;
1372 UINT32 bpp = FreeRDPGetBytesPerPixel(gdi->dstFormat);
1373 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1377 bitmap_context = CGBitmapContextCreate(
1378 gdi->primary_buffer, gdi->width, gdi->height, 5, gdi->stride, colorSpace,
1379 kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
1383 bitmap_context = CGBitmapContextCreate(
1384 gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->stride, colorSpace,
1385 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
1388 CGColorSpaceRelease(colorSpace);
1389 return bitmap_context;
1392BOOL mac_begin_paint(rdpContext *context)
1394 rdpGdi *gdi = context->gdi;
1399 gdi->primary->hdc->hwnd->invalid->null = TRUE;
1403BOOL mac_end_paint(rdpContext *context)
1407 if ((!context) || (!context->gdi))
1414 rdpGdi *gdi = context->gdi;
1419 const int ww = mfc->client_width;
1420 const int wh = mfc->client_height;
1424 HGDI_DC hdc = gdi->primary->hdc;
1430 WINPR_ASSERT(hwnd->invalid || (hwnd->ninvalid == 0));
1432 if (hwnd->invalid->null)
1435 HGDI_RGN invalid = gdi->primary->hdc->hwnd->invalid;
1436 newDrawRect.origin.x = invalid->x;
1437 newDrawRect.origin.y = invalid->y;
1438 newDrawRect.size.width = invalid->w;
1439 newDrawRect.size.height = invalid->h;
1442 (ww != dw || wh != dh))
1444 newDrawRect.origin.y = newDrawRect.origin.y * wh / dh - 1;
1445 newDrawRect.size.height = newDrawRect.size.height * wh / dh + 1;
1446 newDrawRect.origin.x = newDrawRect.origin.x * ww / dw - 1;
1447 newDrawRect.size.width = newDrawRect.size.width * ww / dw + 1;
1451 newDrawRect.origin.y = newDrawRect.origin.y - 1;
1452 newDrawRect.size.height = newDrawRect.size.height + 1;
1453 newDrawRect.origin.x = newDrawRect.origin.x - 1;
1454 newDrawRect.size.width = newDrawRect.size.width + 1;
1457 windows_to_apple_cords(mfc->view, &newDrawRect);
1458 dispatch_sync(dispatch_get_main_queue(), ^{
1459 [view setNeedsDisplayInRect:newDrawRect];
1461 gdi->primary->hdc->hwnd->ninvalid = 0;
1465BOOL mac_desktop_resize(rdpContext *context)
1467 ResizeWindowEventArgs e;
1470 rdpSettings *settings = context->settings;
1480 CGContextRef old_context = view->bitmap_context;
1481 view->bitmap_context =
nullptr;
1482 CGContextRelease(old_context);
1486 if (!gdi_resize(context->gdi, mfc->width, mfc->height))
1489 view->bitmap_context = mac_create_bitmap_context(context);
1491 if (!view->bitmap_context)
1494 mfc->client_width = mfc->width;
1495 mfc->client_height = mfc->height;
1496 [view setFrameSize:NSMakeSize(mfc->width, mfc->height)];
1497 EventArgsInit(&e,
"mfreerdp");
1500 if (PubSub_OnResizeWindow(context->pubSub, context, &e) < 0)
1505void input_activity_cb(freerdp *instance)
1509 wMessageQueue *queue;
1511 queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
1515 while (MessageQueue_Peek(queue, &message, TRUE))
1517 status = freerdp_message_queue_process_message(instance, FREERDP_INPUT_MESSAGE_QUEUE,
1526 WLog_ERR(TAG,
"input_activity_cb: No queue!");
1538void windows_to_apple_cords(
MRDPView *view, NSRect *r)
1540 dispatch_sync(dispatch_get_main_queue(), ^{
1541 r->origin.y = [view frame].size.height - (r->origin.y + r->size.height);
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.