FreeRDP
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 
17 static AppDelegate *_singleDelegate = nil;
18 void AppDelegate_ConnectionResultEventHandler(void *context, const ConnectionResultEventArgs *e);
19 void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e);
20 void AppDelegate_EmbedWindowEventHandler(void *context, const EmbedWindowEventArgs *e);
21 void AppDelegate_ResizeWindowEventHandler(void *context, const ResizeWindowEventArgs *e);
22 void 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 
218 void 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 
247 void 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 
270 void 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 
290 void 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 
304 void 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 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.