FreeRDP
Loading...
Searching...
No Matches
Mac/cli/AppDelegate.m
1//
2// AppDelegate.m
3// MacClient2
4//
5// Created by BenoƮt et Kathy on 2013-05-08.
6//
7//
8
9#import "AppDelegate.h"
10#import <mfreerdp.h>
11#import <mf_client.h>
12#import <MRDPView.h>
13
14#import <winpr/assert.h>
15#import <freerdp/client/cmdline.h>
16
17static AppDelegate *_singleDelegate = nil;
18void AppDelegate_ConnectionResultEventHandler(void *context, const ConnectionResultEventArgs *e);
19void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e);
20void AppDelegate_EmbedWindowEventHandler(void *context, const EmbedWindowEventArgs *e);
21void AppDelegate_ResizeWindowEventHandler(void *context, const ResizeWindowEventArgs *e);
22void mac_set_view_size(rdpContext *context, MRDPView *view);
23
24@implementation AppDelegate
25
26- (void)dealloc
27{
28 [super dealloc];
29}
30
31@synthesize window = window;
32
33@synthesize context = context;
34
35- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
36{
37 int status;
38 mfContext *mfc;
39 _singleDelegate = self;
40 [self CreateContext];
41 status = [self ParseCommandLineArguments];
42 mfc = (mfContext *)context;
43 WINPR_ASSERT(mfc);
44
45 mfc->view = (void *)mrdpView;
46
47 if (status == 0)
48 {
49 NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
50 NSRect screenFrame = [screen frame];
51 rdpSettings *settings = context->settings;
52
53 WINPR_ASSERT(settings);
54
55 if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
56 {
57 (void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
58 screenFrame.size.width);
59 (void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
60 screenFrame.size.height);
61 }
62
63 PubSub_SubscribeConnectionResult(context->pubSub, AppDelegate_ConnectionResultEventHandler);
64 PubSub_SubscribeErrorInfo(context->pubSub, AppDelegate_ErrorInfoEventHandler);
65 PubSub_SubscribeEmbedWindow(context->pubSub, AppDelegate_EmbedWindowEventHandler);
66 PubSub_SubscribeResizeWindow(context->pubSub, AppDelegate_ResizeWindowEventHandler);
67 freerdp_client_start(context);
68 NSString *winTitle;
69 const char *WindowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
70
71 if (WindowTitle && WindowTitle[0])
72 {
73 winTitle = [[NSString alloc]
74 initWithFormat:@"%@", [NSString stringWithCString:WindowTitle
75 encoding:NSUTF8StringEncoding]];
76 }
77 else
78 {
79 const char *name = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
80 const UINT32 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
81 winTitle = [[NSString alloc]
82 initWithFormat:@"%@:%u",
83 [NSString stringWithCString:name encoding:NSUTF8StringEncoding],
84 port];
85 }
86
87 [window setTitle:winTitle];
88 }
89 else
90 {
91 [NSApp terminate:self];
92 }
93}
94
95- (void)applicationWillBecomeActive:(NSNotification *)notification
96{
97 [mrdpView resume];
98}
99
100- (void)applicationWillResignActive:(NSNotification *)notification
101{
102 [mrdpView pause];
103}
104
105- (void)applicationWillTerminate:(NSNotification *)notification
106{
107 NSLog(@"Stopping...\n");
108 freerdp_client_stop(context);
109 [mrdpView releaseResources];
110 _singleDelegate = nil;
111 NSLog(@"Stopped.\n");
112 [NSApp terminate:self];
113}
114
115- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
116{
117 return YES;
118}
119
120- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app
121{
122 return YES;
123}
124
125- (int)ParseCommandLineArguments
126{
127 int i = 0;
128 NSArray *args = [[NSProcessInfo processInfo] arguments];
129 WINPR_ASSERT(args);
130
131 context->argc = WINPR_ASSERTING_INT_CAST(int, [args count]);
132 context->argv = calloc(sizeof(char *), context->argc);
133
134 for (NSString *str in args)
135 {
136 /* filter out some arguments added by XCode */
137 if ([str isEqualToString:@"YES"])
138 continue;
139
140 if ([str isEqualToString:@"-NSDocumentRevisionsDebugMode"])
141 continue;
142
143 const size_t length = ([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
144 if (length == 0)
145 continue;
146 char *cptr = (char *)malloc(length);
147 if (!cptr)
148 continue;
149 (void)sprintf_s(cptr, length, "%s", [str UTF8String]);
150 context->argv[i++] = cptr;
151 }
152
153 context->argc = i;
154 const int status = freerdp_client_settings_parse_command_line(context->settings, context->argc,
155 context->argv, FALSE);
156 freerdp_client_settings_command_line_status_print(context->settings, status, context->argc,
157 context->argv);
158 return status;
159}
160
161- (void)CreateContext
162{
163 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
164
165 clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
166 clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
167 RdpClientEntry(&clientEntryPoints);
168 context = freerdp_client_context_new(&clientEntryPoints);
169}
170
171- (void)ReleaseContext
172{
173 mfContext *mfc;
174 MRDPView *view;
175 mfc = (mfContext *)context;
176 view = (MRDPView *)mfc->view;
177 [view exitFullScreenModeWithOptions:nil];
178 [view releaseResources];
179 [view release];
180 mfc->view = nil;
181 freerdp_client_context_free(context);
182 context = nil;
183}
184
189- (void)rdpConnectError:(NSString *)withMessage
190{
191 mfContext *mfc;
192 MRDPView *view;
193 mfc = (mfContext *)context;
194 view = (MRDPView *)mfc->view;
195 [view exitFullScreenModeWithOptions:nil];
196 NSString *message = withMessage ? withMessage : @"Error connecting to server";
197 NSAlert *alert = [[NSAlert alloc] init];
198 [alert setMessageText:message];
199 [alert beginSheetModalForWindow:[self window]
200 modalDelegate:self
201 didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
202 contextInfo:nil];
203}
204
209- (void)alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci
210{
211 [NSApp terminate:nil];
212}
213
214@end
215
220void AppDelegate_ConnectionResultEventHandler(void *ctx, const ConnectionResultEventArgs *e)
221{
222 rdpContext *context = (rdpContext *)ctx;
223 NSLog(@"ConnectionResult event result:%d\n", e->result);
224
225 if (_singleDelegate)
226 {
227 if (e->result != 0)
228 {
229 NSString *message = nil;
230 DWORD code = freerdp_get_last_error(context);
231 switch (code)
232 {
233 case FREERDP_ERROR_AUTHENTICATION_FAILED:
234 message = [NSString
235 stringWithFormat:@"%@", @"Authentication failure, check credentials."];
236 break;
237 default:
238 break;
239 }
240
241 // Making sure this should be invoked on the main UI thread.
242 [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
243 withObject:message
244 waitUntilDone:FALSE];
245 }
246 }
247}
248
249void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e)
250{
251 NSLog(@"ErrorInfo event code:%d\n", e->code);
252
253 if (_singleDelegate)
254 {
255 // Retrieve error message associated with error code
256 NSString *message = nil;
257
258 if (e->code != ERRINFO_NONE)
259 {
260 const char *errorMessage = freerdp_get_error_info_string(e->code);
261 message = [[NSString alloc] initWithUTF8String:errorMessage];
262 }
263
264 // Making sure this should be invoked on the main UI thread.
265 [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
266 withObject:message
267 waitUntilDone:TRUE];
268 [message release];
269 }
270}
271
272void AppDelegate_EmbedWindowEventHandler(void *ctx, const EmbedWindowEventArgs *e)
273{
274 rdpContext *context = (rdpContext *)ctx;
275
276 if (_singleDelegate)
277 {
278 mfContext *mfc = (mfContext *)context;
279 _singleDelegate->mrdpView = mfc->view;
280
281 if (_singleDelegate->window)
282 {
283 [[_singleDelegate->window contentView] addSubview:mfc->view];
284 }
285
286 dispatch_async(dispatch_get_main_queue(), ^{
287 mac_set_view_size(context, mfc->view);
288 });
289 }
290}
291
292void AppDelegate_ResizeWindowEventHandler(void *ctx, const ResizeWindowEventArgs *e)
293{
294 rdpContext *context = (rdpContext *)ctx;
295 (void)fprintf(stderr, "ResizeWindowEventHandler: %d %d\n", e->width, e->height);
296
297 if (_singleDelegate)
298 {
299 mfContext *mfc = (mfContext *)context;
300 dispatch_async(dispatch_get_main_queue(), ^{
301 mac_set_view_size(context, mfc->view);
302 });
303 }
304}
305
306void mac_set_view_size(rdpContext *context, MRDPView *view)
307{
308 // set client area to specified dimensions
309 NSRect innerRect;
310 innerRect.origin.x = 0;
311 innerRect.origin.y = 0;
312 innerRect.size.width = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
313 innerRect.size.height = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopHeight);
314 [view setFrame:innerRect];
315 // calculate window of same size, but keep position
316 NSRect outerRect = [[view window] frame];
317 outerRect.size = [[view window] frameRectForContentRect:innerRect].size;
318 // we are not in RemoteApp mode, disable larger than resolution
319 [[view window] setContentMaxSize:innerRect.size];
320 // set window to given area
321 [[view window] setFrame:outerRect display:YES];
322 // set window to front
323 [NSApp activateIgnoringOtherApps:YES];
324
325 if (freerdp_settings_get_bool(context->settings, FreeRDP_Fullscreen))
326 [[view window] toggleFullScreen:nil];
327}
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 BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 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.