11 #import <QuartzCore/QuartzCore.h>
12 #import "RDPSessionViewController.h"
13 #import "RDPKeyboard.h"
15 #import "Toast+UIView.h"
16 #import "ConnectionParams.h"
17 #import "CredentialsInputController.h"
18 #import "VerifyCertificateController.h"
19 #import "BlockAlertView.h"
21 #define TOOLBAR_HEIGHT 30
23 #define AUTOSCROLLDISTANCE 20
24 #define AUTOSCROLLTIMEOUT 0.05
26 @interface RDPSessionViewController (Private)
27 - (void)showSessionToolbar:(BOOL)show;
28 - (UIToolbar *)keyboardToolbar;
29 - (void)initGestureRecognizers;
30 - (void)suspendSession;
31 - (NSDictionary *)eventDescriptorForMouseEvent:(
int)event position:(CGPoint)position;
32 - (void)handleMouseMoveForPosition:(CGPoint)position;
37 #pragma mark class methods
39 - (id)initWithNibName:(NSString *)nibNameOrNil
40 bundle:(NSBundle *)nibBundleOrNil
43 self = [
super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
46 _session = [session retain];
47 [_session setDelegate:self];
48 _session_initilized = NO;
50 _mouse_move_events_skipped = 0;
51 _mouse_move_event_timer = nil;
53 _advanced_keyboard_view = nil;
54 _advanced_keyboard_visible = NO;
55 _requesting_advanced_keyboard = NO;
56 _keyboard_last_height = 0;
58 _session_toolbar_visible = NO;
60 _toggle_mouse_button = NO;
62 _autoscroll_with_touchpointer =
63 [[NSUserDefaults standardUserDefaults] boolForKey:@"ui.auto_scroll_touchpointer"];
64 _is_autoscrolling = NO;
66 [UIView setAnimationDelegate:self];
67 [UIView setAnimationDidStopSelector:@selector(animationStopped:finished:context:)];
80 _keyboard_visible = NO;
83 _keyboard_toolbar = [[
self keyboardToolbar] retain];
84 [_dummy_textfield setInputAccessoryView:_keyboard_toolbar];
87 [
self initGestureRecognizers];
91 setFrame:CGRectMake(0.0, -TOOLBAR_HEIGHT, [[
self view] bounds].size.width, TOOLBAR_HEIGHT)];
100 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
105 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
107 if (![_touchpointer_view isHidden])
108 [_touchpointer_view ensurePointerIsVisible];
111 - (void)didReceiveMemoryWarning
114 [
super didReceiveMemoryWarning];
119 - (void)viewDidUnload
121 [
super viewDidUnload];
126 - (void)viewWillAppear:(BOOL)animated
128 [
super viewWillAppear:animated];
131 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"ui.hide_status_bar"])
134 [[UIApplication sharedApplication] setStatusBarHidden:YES
135 withAnimation:UIStatusBarAnimationSlide];
137 [[UIApplication sharedApplication] setStatusBarHidden:YES
138 withAnimation:UIStatusBarAnimationNone];
140 [[
self navigationController] setNavigationBarHidden:YES animated:animated];
143 if ([_session isSuspended])
144 [
self sessionBitmapContextWillChange:_session];
147 [[
RDPKeyboard getSharedRDPKeyboard] initWithSession:_session delegate:self];
150 - (void)viewDidAppear:(BOOL)animated
152 [
super viewDidAppear:animated];
154 if (!_session_initilized)
156 if ([_session isSuspended])
159 [
self sessionBitmapContextDidChange:_session];
160 [_session_view setNeedsDisplay];
165 _session_initilized = YES;
169 - (void)viewWillDisappear:(BOOL)animated
171 [
super viewWillDisappear:animated];
175 [[UIApplication sharedApplication] setStatusBarHidden:NO
176 withAnimation:UIStatusBarAnimationSlide];
178 [[UIApplication sharedApplication] setStatusBarHidden:NO
179 withAnimation:UIStatusBarAnimationNone];
180 [[
self navigationController] setNavigationBarHidden:NO animated:animated];
186 [
self showSessionToolbar:NO];
187 [_dummy_textfield resignFirstResponder];
193 [[NSNotificationCenter defaultCenter] removeObserver:self];
196 [_session setDelegate:nil];
198 [_advanced_keyboard_view release];
199 [_keyboard_toolbar release];
205 #pragma mark ScrollView delegate methods
207 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
209 return _session_view;
212 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
213 withView:(UIView *)view
216 NSLog(
@"New zoom scale: %f", scale);
217 [_session_view setNeedsDisplay];
221 #pragma mark TextField delegate methods
222 - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
224 _keyboard_visible = YES;
225 _advanced_keyboard_visible = NO;
229 - (BOOL)textFieldShouldEndEditing:(UITextField *)textField
231 _keyboard_visible = NO;
232 _advanced_keyboard_visible = NO;
236 - (BOOL)textField:(UITextField *)textField
237 shouldChangeCharactersInRange:(NSRange)range
238 replacementString:(NSString *)string
240 if ([
string length] > 0)
242 for (
int i = 0; i < [string length]; i++)
244 unichar curChar = [string characterAtIndex:i];
248 [[
RDPKeyboard getSharedRDPKeyboard] sendEnterKeyStroke];
250 [[
RDPKeyboard getSharedRDPKeyboard] sendUnicode:curChar];
255 [[
RDPKeyboard getSharedRDPKeyboard] sendBackspaceKeyStroke];
262 #pragma mark AdvancedKeyboardDelegate functions
263 - (void)advancedKeyPressedVKey:(
int)key
265 [[
RDPKeyboard getSharedRDPKeyboard] sendVirtualKeyCode:key];
268 - (void)advancedKeyPressedUnicode:(
int)key
270 [[
RDPKeyboard getSharedRDPKeyboard] sendUnicode:key];
273 #pragma mark - RDP keyboard handler
275 - (void)modifiersChangedForKeyboard:(
RDPKeyboard *)keyboard
277 UIBarButtonItem *curItem;
284 curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
285 [curItem setStyle:[keyboard shiftPressed] ? UIBarButtonItemStyleDone
286 : UIBarButtonItemStyleBordered];
291 curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
293 setStyle:[keyboard ctrlPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
297 curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
299 setStyle:[keyboard winPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
303 curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
305 setStyle:[keyboard altPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
309 #pragma mark RDPSessionDelegate functions
311 - (void)session:(
RDPSession *)session didFailToConnect:(
int)reason
314 [_connecting_indicator_view stopAnimating];
315 [_connecting_view removeFromSuperview];
316 [_connecting_view autorelease];
319 [[
self navigationController] popViewControllerAnimated:YES];
322 - (void)sessionWillConnect:(
RDPSession *)session
325 [[NSBundle mainBundle] loadNibNamed:@"RDPConnectingView" owner:self options:nil];
328 [_lbl_connecting setText:NSLocalizedString(@"Connecting", @"Connecting progress view - label")];
329 [_cancel_connect_button setTitle:NSLocalizedString(@"Cancel", @"Cancel Button")
330 forState:UIControlStateNormal];
333 [_connecting_view setCenter:[[
self view] center]];
334 [[_connecting_view layer] setCornerRadius:10];
337 [[
self view] addSubview:_connecting_view];
338 [_connecting_indicator_view startAnimating];
341 - (void)sessionDidConnect:(
RDPSession *)session
344 [[NSNotificationCenter defaultCenter] addObserver:self
345 selector:@selector(keyboardWillShow:)
346 name:UIKeyboardWillShowNotification
348 [[NSNotificationCenter defaultCenter] addObserver:self
349 selector:@selector(keyboardDidShow:)
350 name:UIKeyboardDidShowNotification
352 [[NSNotificationCenter defaultCenter] addObserver:self
353 selector:@selector(keyboardWillHide:)
354 name:UIKeyboardWillHideNotification
356 [[NSNotificationCenter defaultCenter] addObserver:self
357 selector:@selector(keyboardDidHide:)
358 name:UIKeyboardDidHideNotification
362 [_connecting_indicator_view stopAnimating];
363 [_connecting_view removeFromSuperview];
364 [_connecting_view autorelease];
370 rdpSettings *sess_params = [session getSessionParams];
371 if (([orig_params intForKey:
@"width"] != sess_params->DesktopWidth &&
372 [orig_params intForKey:
@"width"] != (sess_params->DesktopWidth + 1)) ||
373 [orig_params intForKey:
@"height"] != sess_params->DesktopHeight ||
374 [orig_params intForKey:
@"colors"] != sess_params->ColorDepth)
378 [NSString stringWithFormat:NSLocalizedString(
379 @"The server changed the screen settings to %dx%dx%d",
380 @"Screen settings not supported message with width, "
381 @"height and colors parameter"),
382 sess_params->DesktopWidth, sess_params->DesktopHeight,
383 sess_params->ColorDepth];
384 [[
self view] makeToast:message duration:ToastDurationNormal position:@"bottom"];
388 - (void)sessionWillDisconnect:(
RDPSession *)session
392 - (void)sessionDidDisconnect:(
RDPSession *)session
395 [[
self navigationController] popViewControllerAnimated:YES];
398 - (void)sessionBitmapContextWillChange:(
RDPSession *)session
401 rdpSettings *sess_params = [session getSessionParams];
402 CGRect view_rect = CGRectMake(0, 0, sess_params->DesktopWidth, sess_params->DesktopHeight);
405 [_session_scrollview setZoomScale:1.0];
406 [_session_scrollview setContentSize:view_rect.size];
409 [_session_view setFrame:view_rect];
413 setToolbarVisible:![[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_tool_bar"]];
414 [
self showSessionToolbar:[_session toolbarVisible]];
417 - (void)sessionBitmapContextDidChange:(
RDPSession *)session
420 [_session_view setSession:session];
423 [_session_view setNeedsDisplay];
426 - (void)session:(
RDPSession *)session needsRedrawInRect:(CGRect)rect
428 [_session_view setNeedsDisplayInRect:rect];
431 - (void)session:(
RDPSession *)session requestsAuthenticationWithParams:(NSMutableDictionary *)params
437 params:params] autorelease];
438 [
self presentModalViewController:view_controller animated:YES];
441 - (void)session:(
RDPSession *)session verifyCertificateWithParams:(NSMutableDictionary *)params
447 params:params] autorelease];
448 [
self presentModalViewController:view_controller animated:YES];
451 - (CGSize)sizeForFitScreenForSession:(
RDPSession *)session
454 return [
self view].bounds.size;
458 CGSize size = [
self view].bounds.size;
459 CGFloat maxSize = (size.width > size.height) ? size.width : size.height;
460 return CGSizeMake(maxSize * 1.6f, maxSize);
464 #pragma mark - Keyboard Toolbar Handlers
466 - (void)showAdvancedKeyboardAnimated
469 CGRect rect = [[_keyboard_toolbar superview] bounds];
470 rect.origin.y = [_keyboard_toolbar bounds].size.height;
471 rect.size.height -= rect.origin.y;
475 initWithFrame:CGRectMake(rect.origin.x, [[_keyboard_toolbar superview] bounds].size.height,
476 rect.size.width, rect.size.height)
478 [[_keyboard_toolbar superview] addSubview:_advanced_keyboard_view];
481 [[_keyboard_toolbar superview] setAutoresizesSubviews:YES];
484 [UIView beginAnimations:nil context:NULL];
485 [_advanced_keyboard_view setFrame:rect];
486 [UIView commitAnimations];
489 - (IBAction)toggleKeyboardWhenOtherVisible:(
id)sender
491 if (_advanced_keyboard_visible == NO)
493 [
self showAdvancedKeyboardAnimated];
498 [UIView beginAnimations:@"hide_advanced_keyboard_view" context:NULL];
499 CGRect rect = [_advanced_keyboard_view frame];
500 rect.origin.y = [[_keyboard_toolbar superview] bounds].size.height;
501 [_advanced_keyboard_view setFrame:rect];
502 [UIView commitAnimations];
508 _advanced_keyboard_visible = !_advanced_keyboard_visible;
511 - (IBAction)toggleWinKey:(
id)sender
516 - (IBAction)toggleShiftKey:(
id)sender
518 [[
RDPKeyboard getSharedRDPKeyboard] toggleShiftKey];
521 - (IBAction)toggleCtrlKey:(
id)sender
523 [[
RDPKeyboard getSharedRDPKeyboard] toggleCtrlKey];
526 - (IBAction)toggleAltKey:(
id)sender
531 - (IBAction)pressEscKey:(
id)sender
533 [[
RDPKeyboard getSharedRDPKeyboard] sendEscapeKeyStroke];
537 #pragma mark event handlers
539 - (void)animationStopped:(NSString *)animationID
540 finished:(NSNumber *)finished
541 context:(
void *)context
543 if ([animationID isEqualToString:
@"hide_advanced_keyboard_view"])
546 [_advanced_keyboard_view removeFromSuperview];
547 [_advanced_keyboard_view autorelease];
548 _advanced_keyboard_view = nil;
552 - (IBAction)switchSession:(
id)sender
554 [
self suspendSession];
557 - (IBAction)toggleKeyboard:(
id)sender
559 if (!_keyboard_visible)
560 [_dummy_textfield becomeFirstResponder];
562 [_dummy_textfield resignFirstResponder];
565 - (IBAction)toggleExtKeyboard:(
id)sender
568 if (_keyboard_visible && !_advanced_keyboard_visible)
569 [
self toggleKeyboardWhenOtherVisible:nil];
573 if (_advanced_keyboard_visible == NO)
574 _requesting_advanced_keyboard = YES;
575 [
self toggleKeyboard:nil];
579 - (IBAction)toggleTouchPointer:(
id)sender
581 BOOL toggle_visibilty = ![_touchpointer_view isHidden];
582 [_touchpointer_view setHidden:toggle_visibilty];
583 if (toggle_visibilty)
584 [_session_scrollview setContentInset:UIEdgeInsetsZero];
586 [_session_scrollview setContentInset:[_touchpointer_view getEdgeInsets]];
589 - (IBAction)disconnectSession:(
id)sender
591 [_session disconnect];
594 - (IBAction)cancelButtonPressed:(
id)sender
596 [_session disconnect];
600 #pragma mark iOS Keyboard Notification Handlers
606 UIInterfaceOrientation ori = [[UIApplication sharedApplication] statusBarOrientation];
607 return (ori == UIInterfaceOrientationLandscapeLeft ||
608 ori == UIInterfaceOrientationLandscapeRight);
611 - (void)shiftKeyboard:(NSNotification *)notification
614 CGRect keyboardEndFrame =
615 [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
617 CGFloat previousHeight = _keyboard_last_height;
619 if ([
self isLandscape])
622 _keyboard_last_height = keyboardEndFrame.size.width + keyboardEndFrame.origin.x;
627 CGFloat height = [[UIScreen mainScreen] bounds].size.height;
628 _keyboard_last_height = height - keyboardEndFrame.origin.y;
631 CGFloat shiftHeight = _keyboard_last_height - previousHeight;
633 [UIView beginAnimations:nil context:NULL];
634 [UIView setAnimationCurve:[[[notification userInfo]
635 objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
637 setAnimationDuration:[[[notification userInfo]
638 objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
639 CGRect frame = [_session_scrollview frame];
640 frame.size.height -= shiftHeight;
641 [_session_scrollview setFrame:frame];
642 [_touchpointer_view setFrame:frame];
643 [UIView commitAnimations];
646 - (void)keyboardWillShow:(NSNotification *)notification
648 [
self shiftKeyboard:notification];
650 [_touchpointer_view ensurePointerIsVisible];
653 - (void)keyboardDidShow:(NSNotification *)notification
655 if (_requesting_advanced_keyboard)
657 [
self showAdvancedKeyboardAnimated];
658 _advanced_keyboard_visible = YES;
659 _requesting_advanced_keyboard = NO;
663 - (void)keyboardWillHide:(NSNotification *)notification
666 [
self shiftKeyboard:notification];
669 - (void)keyboardDidHide:(NSNotification *)notification
672 if (_advanced_keyboard_visible == YES)
674 _advanced_keyboard_visible = NO;
675 [_advanced_keyboard_view removeFromSuperview];
676 [_advanced_keyboard_view autorelease];
677 _advanced_keyboard_view = nil;
682 #pragma mark Gesture handlers
684 - (void)handleSingleTap:(UITapGestureRecognizer *)gesture
686 CGPoint pos = [gesture locationInView:_session_view];
687 if (_toggle_mouse_button)
690 sendInputEvent:[
self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(YES)
693 sendInputEvent:[
self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(NO)
699 sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
701 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
705 _toggle_mouse_button = NO;
708 - (void)handleDoubleTap:(UITapGestureRecognizer *)gesture
710 CGPoint pos = [gesture locationInView:_session_view];
711 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
713 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
715 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
717 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
719 _toggle_mouse_button = NO;
722 - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
724 CGPoint pos = [gesture locationInView:_session_view];
726 if ([gesture state] == UIGestureRecognizerStateBegan)
728 sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
730 else if ([gesture state] == UIGestureRecognizerStateChanged)
731 [
self handleMouseMoveForPosition:pos];
732 else if ([gesture state] == UIGestureRecognizerStateEnded)
733 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
737 - (void)handleDoubleLongPress:(UILongPressGestureRecognizer *)gesture
741 CGPoint pos = [gesture locationInView:_session_scrollview];
743 if ([gesture state] == UIGestureRecognizerStateBegan)
744 _prev_long_press_position = pos;
745 else if ([gesture state] == UIGestureRecognizerStateChanged)
747 int delta = _prev_long_press_position.y - pos.y;
749 if (delta > GetScrollGestureDelta())
751 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetMouseWheelEvent(YES)
753 _prev_long_press_position = pos;
755 else if (delta < -GetScrollGestureDelta())
757 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetMouseWheelEvent(NO)
759 _prev_long_press_position = pos;
764 - (void)handleSingle2FingersTap:(UITapGestureRecognizer *)gesture
766 _toggle_mouse_button = !_toggle_mouse_button;
769 - (void)handleSingle3FingersTap:(UITapGestureRecognizer *)gesture
771 [_session setToolbarVisible:![_session toolbarVisible]];
772 [
self showSessionToolbar:[_session toolbarVisible]];
776 #pragma mark Touch Pointer delegates
778 - (void)touchPointerClose
780 [
self toggleTouchPointer:nil];
784 - (void)touchPointerLeftClick:(CGPoint)pos down:(BOOL)down
786 CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
787 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(down)
788 position:session_view_pos]];
792 - (void)touchPointerRightClick:(CGPoint)pos down:(BOOL)down
794 CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
795 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(down)
796 position:session_view_pos]];
799 - (void)doAutoScrolling
803 CGPoint curPointerPos = [_touchpointer_view getPointerPosition];
804 CGRect viewBounds = [_touchpointer_view bounds];
805 CGRect scrollBounds = [_session_view bounds];
808 scrollBounds.size.width += [_session_scrollview contentInset].right;
809 scrollBounds.size.height += [_session_scrollview contentInset].bottom;
812 scrollBounds.size.width *= [_session_scrollview zoomScale];
813 scrollBounds.size.height *= [_session_scrollview zoomScale];
815 if (curPointerPos.x > (viewBounds.size.width - [_touchpointer_view getPointerWidth]))
816 scrollX = AUTOSCROLLDISTANCE;
817 else if (curPointerPos.x < 0)
818 scrollX = -AUTOSCROLLDISTANCE;
820 if (curPointerPos.y > (viewBounds.size.height - [_touchpointer_view getPointerHeight]))
821 scrollY = AUTOSCROLLDISTANCE;
822 else if (curPointerPos.y < (_session_toolbar_visible ? TOOLBAR_HEIGHT : 0))
823 scrollY = -AUTOSCROLLDISTANCE;
825 CGPoint newOffset = [_session_scrollview contentOffset];
826 newOffset.x += scrollX;
827 newOffset.y += scrollY;
835 else if (newOffset.x > (scrollBounds.size.width - viewBounds.size.width))
838 newOffset.x = MAX(scrollBounds.size.width - viewBounds.size.width, 0);
845 else if (newOffset.y > (scrollBounds.size.height - viewBounds.size.height))
848 newOffset.y = MAX(scrollBounds.size.height - viewBounds.size.height, 0);
852 [_session_scrollview setContentOffset:newOffset];
855 if (scrollX != 0 || scrollY != 0)
856 [
self performSelector:@selector(doAutoScrolling)
858 afterDelay:AUTOSCROLLTIMEOUT];
860 _is_autoscrolling = NO;
864 - (void)touchPointerMove:(CGPoint)pos
866 CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
867 [
self handleMouseMoveForPosition:session_view_pos];
869 if (_autoscroll_with_touchpointer && !_is_autoscrolling)
871 _is_autoscrolling = YES;
872 [
self performSelector:@selector(doAutoScrolling)
874 afterDelay:AUTOSCROLLTIMEOUT];
879 - (void)touchPointerScrollDown:(BOOL)down
881 [_session sendInputEvent:[
self eventDescriptorForMouseEvent:GetMouseWheelEvent(down)
882 position:CGPointZero]];
886 - (void)touchPointerToggleKeyboard
888 if (_advanced_keyboard_visible)
889 [
self toggleKeyboardWhenOtherVisible:nil];
891 [
self toggleKeyboard:nil];
895 - (void)touchPointerToggleExtendedKeyboard
897 [
self toggleExtKeyboard:nil];
901 - (void)touchPointerResetSessionView
903 [_session_scrollview setZoomScale:1.0 animated:YES];
908 @implementation RDPSessionViewController (Private)
911 #pragma mark Helper functions
913 - (void)showSessionToolbar:(BOOL)show
916 if (_session_toolbar_visible == show)
921 [UIView beginAnimations:@"showToolbar" context:nil];
922 [UIView setAnimationDuration:.4];
923 [UIView setAnimationCurve:UIViewAnimationCurveLinear];
925 setFrame:CGRectMake(0.0, 0.0, [[
self view] bounds].size.width, TOOLBAR_HEIGHT)];
926 [UIView commitAnimations];
927 _session_toolbar_visible = YES;
931 [UIView beginAnimations:@"hideToolbar" context:nil];
932 [UIView setAnimationDuration:.4];
933 [UIView setAnimationCurve:UIViewAnimationCurveLinear];
934 [_session_toolbar setFrame:CGRectMake(0.0, -TOOLBAR_HEIGHT, [[
self view] bounds].size.width,
936 [UIView commitAnimations];
937 _session_toolbar_visible = NO;
941 - (UIToolbar *)keyboardToolbar
943 UIToolbar *keyboard_toolbar = [[[UIToolbar alloc] initWithFrame:CGRectNull] autorelease];
944 [keyboard_toolbar setBarStyle:UIBarStyleBlackOpaque];
946 UIBarButtonItem *esc_btn =
947 [[[UIBarButtonItem alloc] initWithTitle:@"Esc"
948 style:UIBarButtonItemStyleBordered
950 action:@selector(pressEscKey:)] autorelease];
952 [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"toolbar_icon_win"
954 UIBarButtonItem *win_btn =
955 [[[UIBarButtonItem alloc] initWithImage:win_icon
956 style:UIBarButtonItemStyleBordered
958 action:@selector(toggleWinKey:)] autorelease];
959 UIBarButtonItem *ctrl_btn =
960 [[[UIBarButtonItem alloc] initWithTitle:@"Ctrl"
961 style:UIBarButtonItemStyleBordered
963 action:@selector(toggleCtrlKey:)] autorelease];
964 UIBarButtonItem *alt_btn =
965 [[[UIBarButtonItem alloc] initWithTitle:@"Alt"
966 style:UIBarButtonItemStyleBordered
968 action:@selector(toggleAltKey:)] autorelease];
969 UIBarButtonItem *ext_btn = [[[UIBarButtonItem alloc]
971 style:UIBarButtonItemStyleBordered
973 action:@selector(toggleKeyboardWhenOtherVisible:)] autorelease];
974 UIBarButtonItem *done_btn = [[[UIBarButtonItem alloc]
975 initWithBarButtonSystemItem:UIBarButtonSystemItemDone
977 action:@selector(toggleKeyboard:)] autorelease];
978 UIBarButtonItem *flex_spacer =
979 [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
981 action:nil] autorelease];
987 UIBarButtonItem *shift_btn =
988 [[[UIBarButtonItem alloc] initWithTitle:@"Shift"
989 style:UIBarButtonItemStyleBordered
991 action:@selector(toggleShiftKey:)] autorelease];
992 items = [NSArray arrayWithObjects:esc_btn, flex_spacer, shift_btn, flex_spacer, ctrl_btn,
993 flex_spacer, win_btn, flex_spacer, alt_btn, flex_spacer,
994 ext_btn, flex_spacer, done_btn, nil];
998 items = [NSArray arrayWithObjects:esc_btn, flex_spacer, ctrl_btn, flex_spacer, win_btn,
999 flex_spacer, alt_btn, flex_spacer, ext_btn, flex_spacer,
1003 [keyboard_toolbar setItems:items];
1004 [keyboard_toolbar sizeToFit];
1005 return keyboard_toolbar;
1008 - (void)initGestureRecognizers
1011 UITapGestureRecognizer *doubleTapRecognizer =
1012 [[[UITapGestureRecognizer alloc] initWithTarget:self
1013 action:@selector(handleDoubleTap:)] autorelease];
1014 [doubleTapRecognizer setNumberOfTouchesRequired:1];
1015 [doubleTapRecognizer setNumberOfTapsRequired:2];
1017 UITapGestureRecognizer *singleTapRecognizer =
1018 [[[UITapGestureRecognizer alloc] initWithTarget:self
1019 action:@selector(handleSingleTap:)] autorelease];
1020 [singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
1021 [singleTapRecognizer setNumberOfTouchesRequired:1];
1022 [singleTapRecognizer setNumberOfTapsRequired:1];
1025 UITapGestureRecognizer *single2FingersTapRecognizer = [[[UITapGestureRecognizer alloc]
1027 action:@selector(handleSingle2FingersTap:)] autorelease];
1028 [single2FingersTapRecognizer setNumberOfTouchesRequired:2];
1029 [single2FingersTapRecognizer setNumberOfTapsRequired:1];
1032 UILongPressGestureRecognizer *longPressRecognizer = [[[UILongPressGestureRecognizer alloc]
1034 action:@selector(handleLongPress:)] autorelease];
1035 [longPressRecognizer setMinimumPressDuration:0.5];
1038 UILongPressGestureRecognizer *doubleLongPressRecognizer = [[[UILongPressGestureRecognizer alloc]
1040 action:@selector(handleDoubleLongPress:)] autorelease];
1041 [doubleLongPressRecognizer setNumberOfTouchesRequired:2];
1042 [doubleLongPressRecognizer setMinimumPressDuration:0.5];
1045 UITapGestureRecognizer *single3FingersTapRecognizer = [[[UITapGestureRecognizer alloc]
1047 action:@selector(handleSingle3FingersTap:)] autorelease];
1048 [single3FingersTapRecognizer setNumberOfTapsRequired:1];
1049 [single3FingersTapRecognizer setNumberOfTouchesRequired:3];
1052 [_session_scrollview addGestureRecognizer:singleTapRecognizer];
1053 [_session_scrollview addGestureRecognizer:doubleTapRecognizer];
1054 [_session_scrollview addGestureRecognizer:single2FingersTapRecognizer];
1055 [_session_scrollview addGestureRecognizer:longPressRecognizer];
1056 [_session_scrollview addGestureRecognizer:doubleLongPressRecognizer];
1057 [_session_scrollview addGestureRecognizer:single3FingersTapRecognizer];
1060 - (void)suspendSession
1066 [[
self navigationController] popViewControllerAnimated:YES];
1069 - (NSDictionary *)eventDescriptorForMouseEvent:(
int)event position:(CGPoint)position
1071 return [NSDictionary
1072 dictionaryWithObjectsAndKeys:@"mouse", @"type", [NSNumber numberWithUnsignedShort:event],
1074 [NSNumber numberWithUnsignedShort:lrintf(position.x)],
1076 [NSNumber numberWithUnsignedShort:lrintf(position.y)],
1080 - (void)sendDelayedMouseEventWithTimer:(NSTimer *)timer
1082 _mouse_move_event_timer = nil;
1083 NSDictionary *
event = [timer userInfo];
1084 [_session sendInputEvent:event];
1085 [timer autorelease];
1088 - (void)handleMouseMoveForPosition:(CGPoint)position
1090 NSDictionary *
event = [
self eventDescriptorForMouseEvent:PTR_FLAGS_MOVE position:position];
1093 [_mouse_move_event_timer invalidate];
1094 _mouse_move_events_skipped++;
1096 if (_mouse_move_events_skipped >= 5)
1098 [_session sendInputEvent:event];
1099 _mouse_move_events_skipped = 0;
1103 [_mouse_move_event_timer autorelease];
1104 _mouse_move_event_timer =
1105 [[NSTimer scheduledTimerWithTimeInterval:0.05
1107 selector:@selector(sendDelayedMouseEventWithTimer:)
1109 repeats:NO] retain];