FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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;
128 int length;
129 int status;
130 char *cptr;
131 NSArray *args = [[NSProcessInfo processInfo] arguments];
132 context->argc = (int)[args count];
133 context->argv = malloc(sizeof(char *) * context->argc);
134 i = 0;
135
136 for (NSString *str in args)
137 {
138 /* filter out some arguments added by XCode */
139 if ([str isEqualToString:@"YES"])
140 continue;
141
142 if ([str isEqualToString:@"-NSDocumentRevisionsDebugMode"])
143 continue;
144
145 length = (int)([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
146 cptr = (char *)malloc(length);
147 sprintf_s(cptr, length, "%s", [str UTF8String]);
148 context->argv[i++] = cptr;
149 }
150
151 context->argc = i;
152 status = freerdp_client_settings_parse_command_line(context->settings, context->argc,
153 context->argv, FALSE);
154 freerdp_client_settings_command_line_status_print(context->settings, status, context->argc,
155 context->argv);
156 return status;
157}
158
159- (void)CreateContext
160{
161 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = { 0 };
162
163 clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
164 clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
165 RdpClientEntry(&clientEntryPoints);
166 context = freerdp_client_context_new(&clientEntryPoints);
167}
168
169- (void)ReleaseContext
170{
171 mfContext *mfc;
172 MRDPView *view;
173 mfc = (mfContext *)context;
174 view = (MRDPView *)mfc->view;
175 [view exitFullScreenModeWithOptions:nil];
176 [view releaseResources];
177 [view release];
178 mfc->view = nil;
179 freerdp_client_context_free(context);
180 context = nil;
181}
182
187- (void)rdpConnectError:(NSString *)withMessage
188{
189 mfContext *mfc;
190 MRDPView *view;
191 mfc = (mfContext *)context;
192 view = (MRDPView *)mfc->view;
193 [view exitFullScreenModeWithOptions:nil];
194 NSString *message = withMessage ? withMessage : @"Error connecting to server";
195 NSAlert *alert = [[NSAlert alloc] init];
196 [alert setMessageText:message];
197 [alert beginSheetModalForWindow:[self window]
198 modalDelegate:self
199 didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
200 contextInfo:nil];
201}
202
207- (void)alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci
208{
209 [NSApp terminate:nil];
210}
211
212@end
213
218void AppDelegate_ConnectionResultEventHandler(void *ctx, const ConnectionResultEventArgs *e)
219{
220 rdpContext *context = (rdpContext *)ctx;
221 NSLog(@"ConnectionResult event result:%d\n", e->result);
222
223 if (_singleDelegate)
224 {
225 if (e->result != 0)
226 {
227 NSString *message = nil;
228 DWORD code = freerdp_get_last_error(context);
229 switch (code)
230 {
231 case FREERDP_ERROR_AUTHENTICATION_FAILED:
232 message = [NSString
233 stringWithFormat:@"%@", @"Authentication failure, check credentials."];
234 break;
235 default:
236 break;
237 }
238
239 // Making sure this should be invoked on the main UI thread.
240 [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
241 withObject:message
242 waitUntilDone:FALSE];
243 }
244 }
245}
246
247void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e)
248{
249 NSLog(@"ErrorInfo event code:%d\n", e->code);
250
251 if (_singleDelegate)
252 {
253 // Retrieve error message associated with error code
254 NSString *message = nil;
255
256 if (e->code != ERRINFO_NONE)
257 {
258 const char *errorMessage = freerdp_get_error_info_string(e->code);
259 message = [[NSString alloc] initWithUTF8String:errorMessage];
260 }
261
262 // Making sure this should be invoked on the main UI thread.
263 [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
264 withObject:message
265 waitUntilDone:TRUE];
266 [message release];
267 }
268}
269
270void AppDelegate_EmbedWindowEventHandler(void *ctx, const EmbedWindowEventArgs *e)
271{
272 rdpContext *context = (rdpContext *)ctx;
273
274 if (_singleDelegate)
275 {
276 mfContext *mfc = (mfContext *)context;
277 _singleDelegate->mrdpView = mfc->view;
278
279 if (_singleDelegate->window)
280 {
281 [[_singleDelegate->window contentView] addSubview:mfc->view];
282 }
283
284 dispatch_async(dispatch_get_main_queue(), ^{
285 mac_set_view_size(context, mfc->view);
286 });
287 }
288}
289
290void AppDelegate_ResizeWindowEventHandler(void *ctx, const ResizeWindowEventArgs *e)
291{
292 rdpContext *context = (rdpContext *)ctx;
293 (void)fprintf(stderr, "ResizeWindowEventHandler: %d %d\n", e->width, e->height);
294
295 if (_singleDelegate)
296 {
297 mfContext *mfc = (mfContext *)context;
298 dispatch_async(dispatch_get_main_queue(), ^{
299 mac_set_view_size(context, mfc->view);
300 });
301 }
302}
303
304void mac_set_view_size(rdpContext *context, MRDPView *view)
305{
306 // set client area to specified dimensions
307 NSRect innerRect;
308 innerRect.origin.x = 0;
309 innerRect.origin.y = 0;
310 innerRect.size.width = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
311 innerRect.size.height = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopHeight);
312 [view setFrame:innerRect];
313 // calculate window of same size, but keep position
314 NSRect outerRect = [[view window] frame];
315 outerRect.size = [[view window] frameRectForContentRect:innerRect].size;
316 // we are not in RemoteApp mode, disable larger than resolution
317 [[view window] setContentMaxSize:innerRect.size];
318 // set window to given area
319 [[view window] setFrame:outerRect display:YES];
320 // set window to front
321 [NSApp activateIgnoringOtherApps:YES];
322
323 if (freerdp_settings_get_bool(context->settings, FreeRDP_Fullscreen))
324 [[view window] toggleFullScreen:nil];
325}
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.