FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
MRDPView.m
1
20#include <winpr/windows.h>
21
22#include "mf_client.h"
23#import "mfreerdp.h"
24#import "MRDPView.h"
25#import "MRDPCursor.h"
26#import "Clipboard.h"
27#import "PasswordDialog.h"
28#import "CertificateDialog.h"
29
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>
35
36#include <freerdp/constants.h>
37
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"
49
50#import <CoreGraphics/CoreGraphics.h>
51
52#define TAG CLIENT_TAG("mac")
53
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);
60
61static BOOL mac_begin_paint(rdpContext *context);
62static BOOL mac_end_paint(rdpContext *context);
63static BOOL mac_desktop_resize(rdpContext *context);
64
65static void input_activity_cb(freerdp *instance);
66
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);
70
71@implementation MRDPView
72
73@synthesize is_connected;
74
75- (int)rdpStart:(rdpContext *)rdp_context
76{
77 rdpSettings *settings;
78 EmbedWindowEventArgs e;
79 [self initializeView];
80
81 WINPR_ASSERT(rdp_context);
82 context = rdp_context;
83 mfc = (mfContext *)rdp_context;
84
85 instance = context->instance;
86 WINPR_ASSERT(instance);
87
88 settings = context->settings;
89 WINPR_ASSERT(settings);
90
91 EventArgsInit(&e, "mfreerdp");
92 e.embed = TRUE;
93 e.handle = (void *)self;
94 PubSub_OnEmbedWindow(context->pubSub, context, &e);
95 NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
96 NSRect screenFrame = [screen frame];
97
98 if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
99 {
100 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, screenFrame.size.width))
101 return -1;
102 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, screenFrame.size.height))
103 return -1;
104 [self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
105 }
106 else
107 {
108 [self exitFullScreenModeWithOptions:nil];
109 }
110
111 mfc->client_height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
112 mfc->client_width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
113
114 if (!(mfc->common.thread =
115 CreateThread(NULL, 0, mac_client_thread, (void *)context, 0, &mfc->mainThreadId)))
116 {
117 WLog_ERR(TAG, "failed to create client thread");
118 return -1;
119 }
120
121 return 0;
122}
123
124DWORD WINAPI mac_client_thread(void *param)
125{
126 @autoreleasepool
127 {
128 int status;
129 DWORD rc;
130 HANDLE events[16] = { 0 };
131 HANDLE inputEvent;
132 DWORD nCount;
133 DWORD nCountTmp;
134 DWORD nCountBase;
135 rdpContext *context = (rdpContext *)param;
136 mfContext *mfc = (mfContext *)context;
137 freerdp *instance = context->instance;
138 MRDPView *view = mfc->view;
139 rdpSettings *settings = context->settings;
140 status = freerdp_connect(context->instance);
141
142 if (!status)
143 {
144 [view setIs_connected:0];
145 return 0;
146 }
147
148 [view setIs_connected:1];
149 nCount = 0;
150 events[nCount++] = mfc->stopEvent;
151
152 if (!(inputEvent =
153 freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE)))
154 {
155 WLog_ERR(TAG, "failed to get input event handle");
156 goto disconnect;
157 }
158
159 events[nCount++] = inputEvent;
160
161 nCountBase = nCount;
162
163 while (!freerdp_shall_disconnect_context(instance->context))
164 {
165 nCount = nCountBase;
166 {
167 if (!(nCountTmp = freerdp_get_event_handles(context, &events[nCount], 16 - nCount)))
168 {
169 WLog_ERR(TAG, "freerdp_get_event_handles failed");
170 break;
171 }
172
173 nCount += nCountTmp;
174 }
175 rc = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
176
177 if (rc >= (WAIT_OBJECT_0 + nCount))
178 {
179 WLog_ERR(TAG, "WaitForMultipleObjects failed (0x%08X)", rc);
180 break;
181 }
182
183 if (rc == WAIT_OBJECT_0)
184 {
185 /* stop event triggered */
186 break;
187 }
188
189 if (WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0)
190 {
191 input_activity_cb(instance);
192 }
193
194 {
195 if (!freerdp_check_event_handles(context))
196 {
197 WLog_ERR(TAG, "freerdp_check_event_handles failed");
198 break;
199 }
200 }
201 }
202
203 disconnect:
204 [view setIs_connected:0];
205 freerdp_disconnect(instance);
206
207 ExitThread(0);
208 return 0;
209 }
210}
211
212- (id)initWithFrame:(NSRect)frame
213{
214 self = [super initWithFrame:frame];
215
216 if (self)
217 {
218 // Initialization code here.
219 }
220
221 return self;
222}
223
224- (void)viewDidLoad
225{
226 [self initializeView];
227}
228
229- (void)initializeView
230{
231 if (!initialized)
232 {
233 cursors = [[NSMutableArray alloc] initWithCapacity:10];
234 // setup a mouse tracking area
235 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
236 initWithRect:[self visibleRect]
237 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
238 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
239 NSTrackingActiveWhenFirstResponder
240 owner:self
241 userInfo:nil];
242 [self addTrackingArea:trackingArea];
243 // Set the default cursor
244 currentCursor = [NSCursor arrowCursor];
245 initialized = YES;
246 }
247}
248
249- (void)setCursor:(NSCursor *)cursor
250{
251 self->currentCursor = cursor;
252 dispatch_async(dispatch_get_main_queue(), ^{
253 [[self window] invalidateCursorRectsForView:self];
254 });
255}
256
257- (void)resetCursorRects
258{
259 [self addCursorRect:[self visibleRect] cursor:currentCursor];
260}
261
262- (BOOL)acceptsFirstResponder
263{
264 return YES;
265}
266
267- (void)mouseMoved:(NSEvent *)event
268{
269 [super mouseMoved:event];
270
271 if (!self.is_connected)
272 return;
273
274 NSPoint loc = [event locationInWindow];
275 int x = (int)loc.x;
276 int y = (int)loc.y;
277 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
278}
279
280- (void)mouseDown:(NSEvent *)event
281{
282 [super mouseDown:event];
283
284 if (!self.is_connected)
285 return;
286
287 NSPoint loc = [event locationInWindow];
288 int x = (int)loc.x;
289 int y = (int)loc.y;
290 mf_press_mouse_button(context, 0, x, y, TRUE);
291}
292
293- (void)mouseUp:(NSEvent *)event
294{
295 [super mouseUp:event];
296
297 if (!self.is_connected)
298 return;
299
300 NSPoint loc = [event locationInWindow];
301 int x = (int)loc.x;
302 int y = (int)loc.y;
303 mf_press_mouse_button(context, 0, x, y, FALSE);
304}
305
306- (void)rightMouseDown:(NSEvent *)event
307{
308 [super rightMouseDown:event];
309
310 if (!self.is_connected)
311 return;
312
313 NSPoint loc = [event locationInWindow];
314 int x = (int)loc.x;
315 int y = (int)loc.y;
316 mf_press_mouse_button(context, 1, x, y, TRUE);
317}
318
319- (void)rightMouseUp:(NSEvent *)event
320{
321 [super rightMouseUp:event];
322
323 if (!self.is_connected)
324 return;
325
326 NSPoint loc = [event locationInWindow];
327 int x = (int)loc.x;
328 int y = (int)loc.y;
329 mf_press_mouse_button(context, 1, x, y, FALSE);
330}
331
332- (void)otherMouseDown:(NSEvent *)event
333{
334 [super otherMouseDown:event];
335
336 if (!self.is_connected)
337 return;
338
339 NSPoint loc = [event locationInWindow];
340 int x = (int)loc.x;
341 int y = (int)loc.y;
342 int pressed = [event buttonNumber];
343 mf_press_mouse_button(context, pressed, x, y, TRUE);
344}
345
346- (void)otherMouseUp:(NSEvent *)event
347{
348 [super otherMouseUp:event];
349
350 if (!self.is_connected)
351 return;
352
353 NSPoint loc = [event locationInWindow];
354 int x = (int)loc.x;
355 int y = (int)loc.y;
356 int pressed = [event buttonNumber];
357 mf_press_mouse_button(context, pressed, x, y, FALSE);
358}
359
360- (void)scrollWheel:(NSEvent *)event
361{
362 UINT16 flags;
363 [super scrollWheel:event];
364
365 if (!self.is_connected)
366 return;
367
368 float dx = [event deltaX];
369 float dy = [event deltaY];
370 /* 1 event = 120 units */
371 UINT16 units = 0;
372
373 if (fabsf(dy) > FLT_EPSILON)
374 {
375 flags = PTR_FLAGS_WHEEL;
376 units = fabsf(dy) * 120;
377
378 if (dy < 0)
379 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
380 }
381 else if (fabsf(dx) > FLT_EPSILON)
382 {
383 flags = PTR_FLAGS_HWHEEL;
384 units = fabsf(dx) * 120;
385
386 if (dx > 0)
387 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
388 }
389 else
390 return;
391
392 /* Wheel rotation steps:
393 *
394 * positive: 0 ... 0xFF -> slow ... fast
395 * negative: 0 ... 0xFF -> fast ... slow
396 */
397 UINT16 step = units;
398 if (step > 0xFF)
399 step = 0xFF;
400
401 /* Negative rotation, so count down steps from top
402 * 9bit twos complement */
403 if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
404 step = 0x100 - step;
405
406 mf_scale_mouse_event(context, flags | step, 0, 0);
407}
408
409- (void)mouseDragged:(NSEvent *)event
410{
411 [super mouseDragged:event];
412
413 if (!self.is_connected)
414 return;
415
416 NSPoint loc = [event locationInWindow];
417 int x = (int)loc.x;
418 int y = (int)loc.y;
419 // send mouse motion event to RDP server
420 mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
421}
422
423static DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
424{
446#if 0
447 switch (keyChar)
448 {
449 case '0':
450 case 0x00A7: /* section sign */
451 if (keyCode == APPLE_VK_ISO_Section)
452 keyCode = APPLE_VK_ANSI_Grave;
453
454 break;
455
456 case 0x00ED: /* latin small letter i with acute */
457 case 0x00CD: /* latin capital letter i with acute */
458 if (keyCode == APPLE_VK_ANSI_Grave)
459 keyCode = APPLE_VK_ISO_Section;
460
461 break;
462 }
463
464#endif
465
466 /* Perform keycode correction for all ISO keyboards */
467
468 if (type == APPLE_KEYBOARD_TYPE_ISO)
469 {
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;
474 }
475
476 return keyCode;
477}
478
479- (void)flagsChanged:(NSEvent *)event
480{
481 if (!is_connected)
482 return;
483
484 DWORD modFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
485
486 WINPR_ASSERT(instance);
487 WINPR_ASSERT(instance->context);
488
489 rdpInput *input = instance->context->input;
490
491#if defined(WITH_DEBUG_KBD)
492 WLog_DBG(TAG, "flagsChanged: modFlags: 0x%04X kbdModFlags: 0x%04X", modFlags, kbdModFlags);
493#endif
494
495 updateFlagStates(input, modFlags, kbdModFlags);
496 kbdModFlags = modFlags;
497}
498
499- (void)keyDown:(NSEvent *)event
500{
501 DWORD keyCode;
502 DWORD keyFlags;
503 DWORD vkcode;
504 DWORD scancode;
505 unichar keyChar;
506 NSString *characters;
507
508 if (!is_connected)
509 return;
510
511 [self flagsChanged:event];
512
513 keyFlags = KBD_FLAGS_DOWN;
514 keyCode = [event keyCode];
515 characters = [event charactersIgnoringModifiers];
516
517 if ([characters length] > 0)
518 {
519 keyChar = [characters characterAtIndex:0];
520 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
521 }
522
523 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
524 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
525 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
526 scancode &= 0xFF;
527 vkcode &= 0xFF;
528
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));
532#endif
533
534 WINPR_ASSERT(instance->context);
535 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
536}
537
538- (void)keyUp:(NSEvent *)event
539{
540 DWORD keyCode;
541 DWORD keyFlags;
542 DWORD vkcode;
543 DWORD scancode;
544 unichar keyChar;
545 NSString *characters;
546
547 if (!is_connected)
548 return;
549
550 [self flagsChanged:event];
551
552 keyFlags = KBD_FLAGS_RELEASE;
553 keyCode = [event keyCode];
554 characters = [event charactersIgnoringModifiers];
555
556 if ([characters length] > 0)
557 {
558 keyChar = [characters characterAtIndex:0];
559 keyCode = fixKeyCode(keyCode, keyChar, mfc->appleKeyboardType);
560 }
561
562 vkcode = GetVirtualKeyCodeFromKeycode(keyCode, WINPR_KEYCODE_TYPE_APPLE);
563 scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
564 keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
565 scancode &= 0xFF;
566 vkcode &= 0xFF;
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));
570#endif
571 WINPR_ASSERT(instance->context);
572 freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
573}
574
575static BOOL updateFlagState(rdpInput *input, DWORD modFlags, DWORD aKbdModFlags, DWORD flag)
576{
577 BOOL press = ((modFlags & flag) != 0) && ((aKbdModFlags & flag) == 0);
578 BOOL release = ((modFlags & flag) == 0) && ((aKbdModFlags & flag) != 0);
579 DWORD keyFlags = 0;
580 const char *name = NULL;
581 DWORD scancode = 0;
582
583 if ((modFlags & flag) == (aKbdModFlags & flag))
584 return TRUE;
585
586 switch (flag)
587 {
588 case NSEventModifierFlagCapsLock:
589 name = "NSEventModifierFlagCapsLock";
590 scancode = RDP_SCANCODE_CAPSLOCK;
591 release = press = TRUE;
592 break;
593 case NSEventModifierFlagShift:
594 name = "NSEventModifierFlagShift";
595 scancode = RDP_SCANCODE_LSHIFT;
596 break;
597
598 case NSEventModifierFlagControl:
599 name = "NSEventModifierFlagControl";
600 scancode = RDP_SCANCODE_LCONTROL;
601 break;
602
603 case NSEventModifierFlagOption:
604 name = "NSEventModifierFlagOption";
605 scancode = RDP_SCANCODE_LMENU;
606 break;
607
608 case NSEventModifierFlagCommand:
609 name = "NSEventModifierFlagCommand";
610 scancode = RDP_SCANCODE_LWIN;
611 break;
612
613 case NSEventModifierFlagNumericPad:
614 name = "NSEventModifierFlagNumericPad";
615 scancode = RDP_SCANCODE_NUMLOCK;
616 release = press = TRUE;
617 break;
618
619 case NSEventModifierFlagHelp:
620 name = "NSEventModifierFlagHelp";
621 scancode = RDP_SCANCODE_HELP;
622 break;
623
624 case NSEventModifierFlagFunction:
625 name = "NSEventModifierFlagFunction";
626 scancode = RDP_SCANCODE_HELP;
627 break;
628
629 default:
630 WLog_ERR(TAG, "Invalid flag: 0x%08" PRIx32 ", not supported", flag);
631 return FALSE;
632 }
633
634 keyFlags = (scancode & KBDEXT);
635 scancode &= 0xFF;
636
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");
641#endif
642
643 if (press)
644 {
645 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode))
646 return FALSE;
647 }
648
649 if (release)
650 {
651 if (!freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode))
652 return FALSE;
653 }
654
655 return TRUE;
656}
657
658static BOOL updateFlagStates(rdpInput *input, UINT32 modFlags, UINT32 aKbdModFlags)
659{
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);
666 return TRUE;
667}
668
669static BOOL releaseFlagStates(rdpInput *input, UINT32 aKbdModFlags)
670{
671 return updateFlagStates(input, 0, aKbdModFlags);
672}
673
674- (void)releaseResources
675{
676 for (int i = 0; i < argc; i++)
677 free(argv[i]);
678
679 if (!is_connected)
680 return;
681
682 free(pixel_data);
683}
684
685- (void)drawRect:(NSRect)rect
686{
687 if (!context)
688 return;
689
690 if (self->bitmap_context)
691 {
692 CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
693 CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context);
694 CGContextSaveGState(cgContext);
695 CGContextClipToRect(
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),
699 cgImage);
700 CGContextRestoreGState(cgContext);
701 CGImageRelease(cgImage);
702 }
703 else
704 {
705 /* Fill the screen with black */
706 [[NSColor blackColor] set];
707 NSRectFill([self bounds]);
708 }
709}
710
711- (void)onPasteboardTimerFired:(NSTimer *)timer
712{
713 UINT32 formatId;
714 BOOL formatMatch;
715 int changeCount;
716 NSData *formatData;
717 NSString *formatString;
718 const char *formatType;
719 NSPasteboardItem *item;
720 changeCount = (int)[pasteboard_rd changeCount];
721
722 if (changeCount == pasteboard_changecount)
723 return;
724
725 pasteboard_changecount = changeCount;
726 NSArray *items = [pasteboard_rd pasteboardItems];
727
728 if ([items count] < 1)
729 return;
730
731 item = [items objectAtIndex:0];
736 formatMatch = FALSE;
737
738 for (NSString *type in [item types])
739 {
740 formatType = [type UTF8String];
741
742 if (strcmp(formatType, "public.utf8-plain-text") == 0)
743 {
744 formatData = [item dataForType:type];
745
746 if (formatData == nil)
747 {
748 break;
749 }
750
751 formatString = [[NSString alloc] initWithData:formatData encoding:NSUTF8StringEncoding];
752
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];
758
759 formatMatch = TRUE;
760
761 break;
762 }
763 }
764
765 if (!formatMatch)
766 ClipboardEmpty(mfc->clipboard);
767
768 if (mfc->clipboardSync)
769 mac_cliprdr_send_client_format_list(mfc->cliprdr);
770}
771
772- (void)pause
773{
774 dispatch_async(dispatch_get_main_queue(), ^{
775 [self->pasteboard_timer invalidate];
776 });
777 NSArray *trackingAreas = self.trackingAreas;
778
779 for (NSTrackingArea *ta in trackingAreas)
780 {
781 [self removeTrackingArea:ta];
782 }
783 releaseFlagStates(instance->context->input, kbdModFlags);
784 kbdModFlags = 0;
785}
786
787- (void)resume
788{
789 if (!self.is_connected)
790 return;
791
792 releaseFlagStates(instance->context->input, kbdModFlags);
793 kbdModFlags = 0;
794 freerdp_input_send_focus_in_event(instance->context->input, 0);
795
796 dispatch_async(dispatch_get_main_queue(), ^{
797 self->pasteboard_timer =
798 [NSTimer scheduledTimerWithTimeInterval:0.5
799 target:self
800 selector:@selector(onPasteboardTimerFired:)
801 userInfo:nil
802 repeats:YES];
803
804 NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
805 initWithRect:[self visibleRect]
806 options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
807 NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag |
808 NSTrackingActiveWhenFirstResponder
809 owner:self
810 userInfo:nil];
811 [self addTrackingArea:trackingArea];
812 [trackingArea release];
813 });
814}
815
816- (void)setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height
817{
818 WINPR_ASSERT(mfc);
819
820 mfc->yCurrentScroll = yOffset;
821 mfc->xCurrentScroll = xOffset;
822 mfc->client_height = height;
823 mfc->client_width = width;
824}
825
826static void mac_OnChannelConnectedEventHandler(void *context, const ChannelConnectedEventArgs *e)
827{
828 rdpSettings *settings;
829 mfContext *mfc = (mfContext *)context;
830
831 WINPR_ASSERT(mfc);
832 WINPR_ASSERT(e);
833
834 settings = mfc->common.context.settings;
835 WINPR_ASSERT(settings);
836
837 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
838 {
839 mac_cliprdr_init(mfc, (CliprdrClientContext *)e->pInterface);
840 }
841 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
842 {
843 }
844 else
845 freerdp_client_OnChannelConnectedEventHandler(context, e);
846}
847
848static void mac_OnChannelDisconnectedEventHandler(void *context,
849 const ChannelDisconnectedEventArgs *e)
850{
851 rdpSettings *settings;
852 mfContext *mfc = (mfContext *)context;
853
854 WINPR_ASSERT(mfc);
855 WINPR_ASSERT(e);
856
857 settings = mfc->common.context.settings;
858 WINPR_ASSERT(settings);
859
860 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
861 {
862 mac_cliprdr_uninit(mfc, (CliprdrClientContext *)e->pInterface);
863 }
864 else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
865 {
866 }
867 else
868 freerdp_client_OnChannelDisconnectedEventHandler(context, e);
869}
870
871BOOL mac_pre_connect(freerdp *instance)
872{
873 rdpSettings *settings;
874 rdpUpdate *update;
875
876 WINPR_ASSERT(instance);
877 WINPR_ASSERT(instance->context);
878
879 update = instance->context->update;
880 WINPR_ASSERT(update);
881
882 update->BeginPaint = mac_begin_paint;
883 update->EndPaint = mac_end_paint;
884 update->DesktopResize = mac_desktop_resize;
885
886 settings = instance->context->settings;
887 WINPR_ASSERT(settings);
888
889 if (!freerdp_settings_get_string(settings, FreeRDP_ServerHostname))
890 {
891 WLog_ERR(TAG, "error: server hostname was not specified with /v:<server>[:port]");
892 return FALSE;
893 }
894
895 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_MACINTOSH))
896 return FALSE;
897 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_MACINTOSH))
898 return FALSE;
899 PubSub_SubscribeChannelConnected(instance->context->pubSub, mac_OnChannelConnectedEventHandler);
900 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
901 mac_OnChannelDisconnectedEventHandler);
902
903 return TRUE;
904}
905
906BOOL mac_post_connect(freerdp *instance)
907{
908 rdpGdi *gdi;
909 rdpPointer rdp_pointer = { 0 };
910 mfContext *mfc;
911 MRDPView *view;
912
913 WINPR_ASSERT(instance);
914
915 mfc = (mfContext *)instance->context;
916 WINPR_ASSERT(mfc);
917
918 view = (MRDPView *)mfc->view;
919 WINPR_ASSERT(view);
920
921 rdp_pointer.size = sizeof(rdpPointer);
922 rdp_pointer.New = mf_Pointer_New;
923 rdp_pointer.Free = mf_Pointer_Free;
924 rdp_pointer.Set = mf_Pointer_Set;
925 rdp_pointer.SetNull = mf_Pointer_SetNull;
926 rdp_pointer.SetDefault = mf_Pointer_SetDefault;
927 rdp_pointer.SetPosition = mf_Pointer_SetPosition;
928
929 if (!gdi_init(instance, PIXEL_FORMAT_BGRX32))
930 return FALSE;
931
932 gdi = instance->context->gdi;
933 view->bitmap_context = mac_create_bitmap_context(instance->context);
934 graphics_register_pointer(instance->context->graphics, &rdp_pointer);
935 /* setup pasteboard (aka clipboard) for copy operations (write only) */
936 view->pasteboard_wr = [NSPasteboard generalPasteboard];
937 /* setup pasteboard for read operations */
938 dispatch_async(dispatch_get_main_queue(), ^{
939 view->pasteboard_rd = [NSPasteboard generalPasteboard];
940 view->pasteboard_changecount = -1;
941 });
942 [view resume];
943 mfc->appleKeyboardType = mac_detect_keyboard_type();
944 return TRUE;
945}
946
947void mac_post_disconnect(freerdp *instance)
948{
949 mfContext *mfc;
950 MRDPView *view;
951 if (!instance || !instance->context)
952 return;
953
954 mfc = (mfContext *)instance->context;
955 view = (MRDPView *)mfc->view;
956
957 [view pause];
958
959 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
960 mac_OnChannelConnectedEventHandler);
961 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
962 mac_OnChannelDisconnectedEventHandler);
963 gdi_free(instance);
964}
965
966static BOOL mac_show_auth_dialog(MRDPView *view, NSString *title, char **username, char **password,
967 char **domain)
968{
969 WINPR_ASSERT(view);
970 WINPR_ASSERT(title);
971 WINPR_ASSERT(username);
972 WINPR_ASSERT(password);
973 WINPR_ASSERT(domain);
974
975 PasswordDialog *dialog = [PasswordDialog new];
976
977 dialog.serverHostname = title;
978
979 if (*username)
980 dialog.username = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding];
981
982 if (*password)
983 dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding];
984
985 if (*domain)
986 dialog.domain = [NSString stringWithCString:*domain encoding:NSUTF8StringEncoding];
987
988 free(*username);
989 free(*password);
990 free(*domain);
991 *username = NULL;
992 *password = NULL;
993 *domain = NULL;
994
995 dispatch_sync(dispatch_get_main_queue(), ^{
996 [dialog performSelectorOnMainThread:@selector(runModal:)
997 withObject:[view window]
998 waitUntilDone:TRUE];
999 });
1000 BOOL ok = dialog.modalCode;
1001
1002 if (ok)
1003 {
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);
1009
1010 if (!(*username))
1011 return FALSE;
1012
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);
1018
1019 if (!(*password))
1020 return FALSE;
1021
1022 const char *submittedDomain = [dialog.domain cStringUsingEncoding:NSUTF8StringEncoding];
1023 const size_t submittedDomainLen =
1024 [dialog.domain lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1025 if (submittedDomain && (submittedDomainLen > 0))
1026 {
1027 *domain = strndup(submittedDomain, submittedDomainLen);
1028 if (!(*domain))
1029 return FALSE;
1030 }
1031 }
1032
1033 return ok;
1034}
1035
1036static BOOL mac_authenticate_raw(freerdp *instance, char **username, char **password, char **domain,
1037 rdp_auth_reason reason)
1038{
1039 BOOL pinOnly = FALSE;
1040
1041 WINPR_ASSERT(instance);
1042 WINPR_ASSERT(instance->context);
1043 WINPR_ASSERT(instance->context->settings);
1044
1045 const rdpSettings *settings = instance->context->settings;
1046 mfContext *mfc = (mfContext *)instance->context;
1047 MRDPView *view = (MRDPView *)mfc->view;
1048 NSString *title = NULL;
1049
1050 switch (reason)
1051 {
1052 case AUTH_SMARTCARD_PIN:
1053 pinOnly = TRUE;
1054 title = [NSString
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)];
1060 break;
1061 case AUTH_TLS:
1062 case AUTH_RDP:
1063 case AUTH_NLA:
1064 title = [NSString
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)];
1070 break;
1071 case GW_AUTH_HTTP:
1072 case GW_AUTH_RDG:
1073 case GW_AUTH_RPC:
1074 title = [NSString
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)];
1080 break;
1081 default:
1082 return FALSE;
1083 }
1084
1085 if (!username || !password || !domain)
1086 return FALSE;
1087
1088 if (!*username && !pinOnly)
1089 {
1090 if (!mac_show_auth_dialog(view, title, username, password, domain))
1091 goto fail;
1092 }
1093 else if (!*domain && !pinOnly)
1094 {
1095 if (!mac_show_auth_dialog(view, title, username, password, domain))
1096 goto fail;
1097 }
1098 else if (!*password)
1099 {
1100 if (!mac_show_auth_dialog(view, title, username, password, domain))
1101 goto fail;
1102 }
1103
1104 return TRUE;
1105fail:
1106 free(*username);
1107 free(*domain);
1108 free(*password);
1109 *username = NULL;
1110 *domain = NULL;
1111 *password = NULL;
1112 return FALSE;
1113}
1114
1115BOOL mac_authenticate_ex(freerdp *instance, char **username, char **password, char **domain,
1116 rdp_auth_reason reason)
1117{
1118 WINPR_ASSERT(instance);
1119 WINPR_ASSERT(username);
1120 WINPR_ASSERT(password);
1121 WINPR_ASSERT(domain);
1122
1123 NSString *title;
1124 switch (reason)
1125 {
1126 case AUTH_NLA:
1127 break;
1128
1129 case AUTH_TLS:
1130 case AUTH_RDP:
1131 case AUTH_SMARTCARD_PIN: /* in this case password is pin code */
1132 if ((*username) && (*password))
1133 return TRUE;
1134 break;
1135 case GW_AUTH_HTTP:
1136 case GW_AUTH_RDG:
1137 case GW_AUTH_RPC:
1138 break;
1139 default:
1140 return FALSE;
1141 }
1142
1143 return mac_authenticate_raw(instance, username, password, domain, reason);
1144}
1145
1146DWORD 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)
1149{
1150 mfContext *mfc = (mfContext *)instance->context;
1151 MRDPView *view = (MRDPView *)mfc->view;
1152 CertificateDialog *dialog = [CertificateDialog new];
1153 const char *type = "RDP-Server";
1154 char hostname[8192] = { 0 };
1155
1156 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1157 type = "RDP-Gateway";
1158
1159 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1160 type = "RDP-Redirect";
1161
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];
1168
1169 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1170 dialog.hostMismatch = TRUE;
1171
1172 if (flags & VERIFY_CERT_FLAG_CHANGED)
1173 dialog.changed = TRUE;
1174
1175 [dialog performSelectorOnMainThread:@selector(runModal:)
1176 withObject:[view window]
1177 waitUntilDone:TRUE];
1178 return dialog.result;
1179}
1180
1181DWORD 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)
1186{
1187 mfContext *mfc = (mfContext *)instance->context;
1188 MRDPView *view = (MRDPView *)mfc->view;
1189 CertificateDialog *dialog = [CertificateDialog new];
1190 const char *type = "RDP-Server";
1191 char hostname[8192];
1192
1193 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1194 type = "RDP-Gateway";
1195
1196 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1197 type = "RDP-Redirect";
1198
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];
1205
1206 if (flags & VERIFY_CERT_FLAG_MISMATCH)
1207 dialog.hostMismatch = TRUE;
1208
1209 if (flags & VERIFY_CERT_FLAG_CHANGED)
1210 dialog.changed = TRUE;
1211
1212 [dialog performSelectorOnMainThread:@selector(runModal:)
1213 withObject:[view window]
1214 waitUntilDone:TRUE];
1215 return dialog.result;
1216}
1217
1218int mac_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
1219{
1220 const char *str_data = freerdp_get_logon_error_info_data(data);
1221 const char *str_type = freerdp_get_logon_error_info_type(type);
1222 // TODO: Error message dialog
1223 WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type);
1224 return 1;
1225}
1226
1227BOOL mf_Pointer_New(rdpContext *context, rdpPointer *pointer)
1228{
1229 rdpGdi *gdi;
1230 NSRect rect;
1231 NSImage *image;
1232 NSPoint hotSpot;
1233 NSCursor *cursor;
1234 BYTE *cursor_data;
1235 NSMutableArray *ma;
1236 NSBitmapImageRep *bmiRep;
1237 MRDPCursor *mrdpCursor = [[MRDPCursor alloc] init];
1238 mfContext *mfc = (mfContext *)context;
1239 MRDPView *view;
1240 UINT32 format;
1241
1242 if (!mfc || !context || !pointer)
1243 return FALSE;
1244
1245 view = (MRDPView *)mfc->view;
1246 gdi = context->gdi;
1247
1248 if (!gdi || !view)
1249 return FALSE;
1250
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);
1256
1257 if (!cursor_data)
1258 return FALSE;
1259
1260 mrdpCursor->cursor_data = cursor_data;
1261 format = PIXEL_FORMAT_RGBA32;
1262
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))
1267 {
1268 free(cursor_data);
1269 mrdpCursor->cursor_data = NULL;
1270 return FALSE;
1271 }
1272
1273 /* store cursor bitmap image in representation - required by NSImage */
1274 bmiRep = [[NSBitmapImageRep alloc]
1275 initWithBitmapDataPlanes:(unsigned char **)&cursor_data
1276 pixelsWide:rect.size.width
1277 pixelsHigh:rect.size.height
1278 bitsPerSample:8
1279 samplesPerPixel:4
1280 hasAlpha:YES
1281 isPlanar:NO
1282 colorSpaceName:NSDeviceRGBColorSpace
1283 bitmapFormat:0
1284 bytesPerRow:rect.size.width * FreeRDPGetBytesPerPixel(format)
1285 bitsPerPixel:0];
1286 mrdpCursor->bmiRep = bmiRep;
1287 /* create an image using above representation */
1288 image = [[NSImage alloc] initWithSize:[bmiRep size]];
1289 [image addRepresentation:bmiRep];
1290 mrdpCursor->nsImage = image;
1291 /* need hotspot to create cursor */
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;
1297 /* save cursor for later use in mf_Pointer_Set() */
1298 ma = view->cursors;
1299 [ma addObject:mrdpCursor];
1300 return TRUE;
1301}
1302
1303void mf_Pointer_Free(rdpContext *context, rdpPointer *pointer)
1304{
1305 mfContext *mfc = (mfContext *)context;
1306 MRDPView *view = (MRDPView *)mfc->view;
1307 NSMutableArray *ma = view->cursors;
1308
1309 for (MRDPCursor *cursor in ma)
1310 {
1311 if (cursor->pointer == pointer)
1312 {
1313 cursor->nsImage = nil;
1314 cursor->nsCursor = nil;
1315 cursor->bmiRep = nil;
1316 free(cursor->cursor_data);
1317 [ma removeObject:cursor];
1318 return;
1319 }
1320 }
1321}
1322
1323BOOL mf_Pointer_Set(rdpContext *context, rdpPointer *pointer)
1324{
1325 mfContext *mfc = (mfContext *)context;
1326 MRDPView *view = (MRDPView *)mfc->view;
1327 NSMutableArray *ma = view->cursors;
1328
1329 for (MRDPCursor *cursor in ma)
1330 {
1331 if (cursor->pointer == pointer)
1332 {
1333 [view setCursor:cursor->nsCursor];
1334 return TRUE;
1335 }
1336 }
1337
1338 NSLog(@"Cursor not found");
1339 return TRUE;
1340}
1341
1342BOOL mf_Pointer_SetNull(rdpContext *context)
1343{
1344 return TRUE;
1345}
1346
1347BOOL mf_Pointer_SetDefault(rdpContext *context)
1348{
1349 mfContext *mfc = (mfContext *)context;
1350 MRDPView *view = (MRDPView *)mfc->view;
1351 [view setCursor:[NSCursor arrowCursor]];
1352 return TRUE;
1353}
1354
1355static BOOL mf_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y)
1356{
1357 mfContext *mfc = (mfContext *)context;
1358
1359 if (!mfc)
1360 return FALSE;
1361
1362 /* TODO: Set pointer position */
1363 return TRUE;
1364}
1365
1366CGContextRef mac_create_bitmap_context(rdpContext *context)
1367{
1368 CGContextRef bitmap_context;
1369 rdpGdi *gdi = context->gdi;
1370 UINT32 bpp = FreeRDPGetBytesPerPixel(gdi->dstFormat);
1371 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1372
1373 if (bpp == 2)
1374 {
1375 bitmap_context = CGBitmapContextCreate(
1376 gdi->primary_buffer, gdi->width, gdi->height, 5, gdi->stride, colorSpace,
1377 kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
1378 }
1379 else
1380 {
1381 bitmap_context = CGBitmapContextCreate(
1382 gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->stride, colorSpace,
1383 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
1384 }
1385
1386 CGColorSpaceRelease(colorSpace);
1387 return bitmap_context;
1388}
1389
1390BOOL mac_begin_paint(rdpContext *context)
1391{
1392 rdpGdi *gdi = context->gdi;
1393
1394 if (!gdi)
1395 return FALSE;
1396
1397 gdi->primary->hdc->hwnd->invalid->null = TRUE;
1398 return TRUE;
1399}
1400
1401BOOL mac_end_paint(rdpContext *context)
1402{
1403 rdpGdi *gdi;
1404 HGDI_RGN invalid;
1405 NSRect newDrawRect;
1406 int ww, wh, dw, dh;
1407 mfContext *mfc = (mfContext *)context;
1408 MRDPView *view = (MRDPView *)mfc->view;
1409 gdi = context->gdi;
1410
1411 if (!gdi)
1412 return FALSE;
1413
1414 ww = mfc->client_width;
1415 wh = mfc->client_height;
1416 dw = freerdp_settings_get_uint32(mfc->common.context.settings, FreeRDP_DesktopWidth);
1417 dh = freerdp_settings_get_uint32(mfc->common.context.settings, FreeRDP_DesktopHeight);
1418
1419 if ((!context) || (!context->gdi))
1420 return FALSE;
1421
1422 if (context->gdi->primary->hdc->hwnd->invalid->null)
1423 return TRUE;
1424
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;
1430
1431 if (freerdp_settings_get_bool(mfc->common.context.settings, FreeRDP_SmartSizing) &&
1432 (ww != dw || wh != dh))
1433 {
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;
1438 }
1439 else
1440 {
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;
1445 }
1446
1447 windows_to_apple_cords(mfc->view, &newDrawRect);
1448 dispatch_sync(dispatch_get_main_queue(), ^{
1449 [view setNeedsDisplayInRect:newDrawRect];
1450 });
1451 gdi->primary->hdc->hwnd->ninvalid = 0;
1452 return TRUE;
1453}
1454
1455BOOL mac_desktop_resize(rdpContext *context)
1456{
1457 ResizeWindowEventArgs e;
1458 mfContext *mfc = (mfContext *)context;
1459 MRDPView *view = (MRDPView *)mfc->view;
1460 rdpSettings *settings = context->settings;
1461
1462 if (!context->gdi)
1463 return TRUE;
1464
1470 CGContextRef old_context = view->bitmap_context;
1471 view->bitmap_context = NULL;
1472 CGContextRelease(old_context);
1473 mfc->width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1474 mfc->height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1475
1476 if (!gdi_resize(context->gdi, mfc->width, mfc->height))
1477 return FALSE;
1478
1479 view->bitmap_context = mac_create_bitmap_context(context);
1480
1481 if (!view->bitmap_context)
1482 return FALSE;
1483
1484 mfc->client_width = mfc->width;
1485 mfc->client_height = mfc->height;
1486 [view setFrameSize:NSMakeSize(mfc->width, mfc->height)];
1487 EventArgsInit(&e, "mfreerdp");
1488 e.width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1489 e.height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1490 PubSub_OnResizeWindow(context->pubSub, context, &e);
1491 return TRUE;
1492}
1493
1494void input_activity_cb(freerdp *instance)
1495{
1496 int status;
1497 wMessage message;
1498 wMessageQueue *queue;
1499 status = 1;
1500 queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
1501
1502 if (queue)
1503 {
1504 while (MessageQueue_Peek(queue, &message, TRUE))
1505 {
1506 status = freerdp_message_queue_process_message(instance, FREERDP_INPUT_MESSAGE_QUEUE,
1507 &message);
1508
1509 if (!status)
1510 break;
1511 }
1512 }
1513 else
1514 {
1515 WLog_ERR(TAG, "input_activity_cb: No queue!");
1516 }
1517}
1518
1527void windows_to_apple_cords(MRDPView *view, NSRect *r)
1528{
1529 dispatch_sync(dispatch_get_main_queue(), ^{
1530 r->origin.y = [view frame].size.height - (r->origin.y + r->size.height);
1531 });
1532}
1533
1534@end
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 BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.