Blame client/iOS/Controllers/RDPSessionViewController.m

Packit 1fb8d4
/*
Packit 1fb8d4
 RDP Session View Controller
Packit Service 5a9772
Packit 1fb8d4
 Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
Packit Service 5a9772
Packit Service 5a9772
 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
Packit Service 5a9772
 If a copy of the MPL was not distributed with this file, You can obtain one at
Packit Service 5a9772
 http://mozilla.org/MPL/2.0/.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#import <QuartzCore/QuartzCore.h>
Packit 1fb8d4
#import "RDPSessionViewController.h"
Packit 1fb8d4
#import "RDPKeyboard.h"
Packit 1fb8d4
#import "Utils.h"
Packit 1fb8d4
#import "Toast+UIView.h"
Packit 1fb8d4
#import "ConnectionParams.h"
Packit 1fb8d4
#import "CredentialsInputController.h"
Packit 1fb8d4
#import "VerifyCertificateController.h"
Packit 1fb8d4
#import "BlockAlertView.h"
Packit 1fb8d4
Packit 1fb8d4
#define TOOLBAR_HEIGHT 30
Packit 1fb8d4
Packit 1fb8d4
#define AUTOSCROLLDISTANCE 20
Packit 1fb8d4
#define AUTOSCROLLTIMEOUT 0.05
Packit 1fb8d4
Packit 1fb8d4
@interface RDPSessionViewController (Private)
Packit Service 5a9772
- (void)showSessionToolbar:(BOOL)show;
Packit Service 5a9772
- (UIToolbar *)keyboardToolbar;
Packit Service 5a9772
- (void)initGestureRecognizers;
Packit 1fb8d4
- (void)suspendSession;
Packit Service 5a9772
- (NSDictionary *)eventDescriptorForMouseEvent:(int)event position:(CGPoint)position;
Packit 1fb8d4
- (void)handleMouseMoveForPosition:(CGPoint)position;
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
@implementation RDPSessionViewController
Packit 1fb8d4
Packit 1fb8d4
#pragma mark class methods
Packit 1fb8d4
Packit Service 5a9772
- (id)initWithNibName:(NSString *)nibNameOrNil
Packit Service 5a9772
               bundle:(NSBundle *)nibBundleOrNil
Packit Service 5a9772
              session:(RDPSession *)session
Packit Service 5a9772
{
Packit Service 5a9772
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
Packit Service 5a9772
	if (self)
Packit Service 5a9772
	{
Packit Service 5a9772
		_session = [session retain];
Packit Service 5a9772
		[_session setDelegate:self];
Packit Service 5a9772
		_session_initilized = NO;
Packit Service 5a9772
Packit Service 5a9772
		_mouse_move_events_skipped = 0;
Packit Service 5a9772
		_mouse_move_event_timer = nil;
Packit Service 5a9772
Packit Service 5a9772
		_advanced_keyboard_view = nil;
Packit Service 5a9772
		_advanced_keyboard_visible = NO;
Packit Service 5a9772
		_requesting_advanced_keyboard = NO;
Packit 1fb8d4
		_keyboard_last_height = 0;
Packit 1fb8d4
Packit Service 5a9772
		_session_toolbar_visible = NO;
Packit Service 5a9772
Packit Service 5a9772
		_toggle_mouse_button = NO;
Packit Service 5a9772
Packit Service 5a9772
		_autoscroll_with_touchpointer =
Packit Service 5a9772
		    [[NSUserDefaults standardUserDefaults] boolForKey:@"ui.auto_scroll_touchpointer"];
Packit Service 5a9772
		_is_autoscrolling = NO;
Packit Service 5a9772
Packit Service 5a9772
		[UIView setAnimationDelegate:self];
Packit Service 5a9772
		[UIView setAnimationDidStopSelector:@selector(animationStopped:finished:context:)];
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	return self;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// Implement loadView to create a view hierarchy programmatically, without using a nib.
Packit Service 5a9772
- (void)loadView
Packit 1fb8d4
{
Packit 1fb8d4
	// load default view and set background color and resizing mask
Packit 1fb8d4
	[super loadView];
Packit 1fb8d4
Packit Service 5a9772
	// init keyboard handling vars
Packit Service 5a9772
	_keyboard_visible = NO;
Packit 1fb8d4
Packit Service 5a9772
	// init keyboard toolbar
Packit Service 5a9772
	_keyboard_toolbar = [[self keyboardToolbar] retain];
Packit Service 5a9772
	[_dummy_textfield setInputAccessoryView:_keyboard_toolbar];
Packit Service 5a9772
Packit Service 5a9772
	// init gesture recognizers
Packit Service 5a9772
	[self initGestureRecognizers];
Packit 1fb8d4
Packit Service 5a9772
	// hide session toolbar
Packit Service 5a9772
	[_session_toolbar
Packit Service 5a9772
	    setFrame:CGRectMake(0.0, -TOOLBAR_HEIGHT, [[self view] bounds].size.width, TOOLBAR_HEIGHT)];
Packit Service 5a9772
}
Packit 1fb8d4
Packit 1fb8d4
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
Packit Service 5a9772
- (void)viewDidLoad
Packit 1fb8d4
{
Packit Service 5a9772
	[super viewDidLoad];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
Packit Service 5a9772
{
Packit Service 5a9772
	return YES;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
Packit 1fb8d4
{
Packit Service 5a9772
	if (![_touchpointer_view isHidden])
Packit Service 5a9772
		[_touchpointer_view ensurePointerIsVisible];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)didReceiveMemoryWarning
Packit Service 5a9772
{
Packit Service 5a9772
	// Releases the view if it doesn't have a superview.
Packit Service 5a9772
	[super didReceiveMemoryWarning];
Packit Service 5a9772
Packit Service 5a9772
	// Release any cached data, images, etc. that aren't in use.
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)viewDidUnload
Packit Service 5a9772
{
Packit Service 5a9772
	[super viewDidUnload];
Packit Service 5a9772
	// Release any retained subviews of the main view.
Packit Service 5a9772
	// e.g. self.myOutlet = nil;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)viewWillAppear:(BOOL)animated
Packit 1fb8d4
{
Packit 1fb8d4
	[super viewWillAppear:animated];
Packit 1fb8d4
Packit Service 5a9772
	// hide navigation bar and (if enabled) the status bar
Packit Service 5a9772
	if ([[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_status_bar"])
Packit Service 5a9772
	{
Packit Service 5a9772
		if (animated == YES)
Packit Service 5a9772
			[[UIApplication sharedApplication] setStatusBarHidden:YES
Packit Service 5a9772
			                                        withAnimation:UIStatusBarAnimationSlide];
Packit Service 5a9772
		else
Packit Service 5a9772
			[[UIApplication sharedApplication] setStatusBarHidden:YES
Packit Service 5a9772
			                                        withAnimation:UIStatusBarAnimationNone];
Packit Service 5a9772
	}
Packit Service 5a9772
	[[self navigationController] setNavigationBarHidden:YES animated:animated];
Packit Service 5a9772
Packit Service 5a9772
	// if sesssion is suspended - notify that we got a new bitmap context
Packit Service 5a9772
	if ([_session isSuspended])
Packit Service 5a9772
		[self sessionBitmapContextWillChange:_session];
Packit 1fb8d4
Packit Service 5a9772
	// init keyboard
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] initWithSession:_session delegate:self];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)viewDidAppear:(BOOL)animated
Packit 1fb8d4
{
Packit 1fb8d4
	[super viewDidAppear:animated];
Packit Service 5a9772
Packit Service 5a9772
	if (!_session_initilized)
Packit Service 5a9772
	{
Packit Service 5a9772
		if ([_session isSuspended])
Packit Service 5a9772
		{
Packit Service 5a9772
			[_session resume];
Packit Service 5a9772
			[self sessionBitmapContextDidChange:_session];
Packit Service 5a9772
			[_session_view setNeedsDisplay];
Packit Service 5a9772
		}
Packit Service 5a9772
		else
Packit Service 5a9772
			[_session connect];
Packit Service 5a9772
Packit Service 5a9772
		_session_initilized = YES;
Packit Service 5a9772
	}
Packit Service 5a9772
}
Packit Service 5a9772
Packit Service 5a9772
- (void)viewWillDisappear:(BOOL)animated
Packit Service 5a9772
{
Packit Service 5a9772
	[super viewWillDisappear:animated];
Packit Service 5a9772
Packit Service 5a9772
	// show navigation and status bar again
Packit Service 5a9772
	if (animated == YES)
Packit Service 5a9772
		[[UIApplication sharedApplication] setStatusBarHidden:NO
Packit Service 5a9772
		                                        withAnimation:UIStatusBarAnimationSlide];
Packit 1fb8d4
	else
Packit Service 5a9772
		[[UIApplication sharedApplication] setStatusBarHidden:NO
Packit Service 5a9772
		                                        withAnimation:UIStatusBarAnimationNone];
Packit 1fb8d4
	[[self navigationController] setNavigationBarHidden:NO animated:animated];
Packit Service 5a9772
Packit Service 5a9772
	// reset all modifier keys on rdp keyboard
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] reset];
Packit Service 5a9772
Packit 1fb8d4
	// hide toolbar and keyboard
Packit Service 5a9772
	[self showSessionToolbar:NO];
Packit 1fb8d4
	[_dummy_textfield resignFirstResponder];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)dealloc
Packit Service 5a9772
{
Packit Service 5a9772
	// remove any observers
Packit Service 5a9772
	[[NSNotificationCenter defaultCenter] removeObserver:self];
Packit 1fb8d4
Packit Service 5a9772
	// the session lives on longer so set the delegate to nil
Packit Service 5a9772
	[_session setDelegate:nil];
Packit 1fb8d4
Packit Service 5a9772
	[_advanced_keyboard_view release];
Packit Service 5a9772
	[_keyboard_toolbar release];
Packit Service 5a9772
	[_session release];
Packit Service 5a9772
	[super dealloc];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark ScrollView delegate methods
Packit 1fb8d4
Packit 1fb8d4
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
Packit Service 5a9772
{
Packit Service 5a9772
	return _session_view;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
Packit Service 5a9772
                       withView:(UIView *)view
Packit Service 5a9772
                        atScale:(float)scale
Packit 1fb8d4
{
Packit Service 5a9772
	NSLog(@"New zoom scale: %f", scale);
Packit 1fb8d4
	[_session_view setNeedsDisplay];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark TextField delegate methods
Packit Service 5a9772
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
Packit 1fb8d4
{
Packit 1fb8d4
	_keyboard_visible = YES;
Packit Service 5a9772
	_advanced_keyboard_visible = NO;
Packit 1fb8d4
	return YES;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
Packit 1fb8d4
{
Packit 1fb8d4
	_keyboard_visible = NO;
Packit Service 5a9772
	_advanced_keyboard_visible = NO;
Packit 1fb8d4
	return YES;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (BOOL)textField:(UITextField *)textField
Packit Service 5a9772
    shouldChangeCharactersInRange:(NSRange)range
Packit Service 5a9772
                replacementString:(NSString *)string
Packit Service 5a9772
{
Packit Service 5a9772
	if ([string length] > 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		for (int i = 0; i < [string length]; i++)
Packit 1fb8d4
		{
Packit Service 5a9772
			unichar curChar = [string characterAtIndex:i];
Packit 1fb8d4
Packit Service 5a9772
			// special handling for return/enter key
Packit Service 5a9772
			if (curChar == '\n')
Packit Service 5a9772
				[[RDPKeyboard getSharedRDPKeyboard] sendEnterKeyStroke];
Packit Service 5a9772
			else
Packit Service 5a9772
				[[RDPKeyboard getSharedRDPKeyboard] sendUnicode:curChar];
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		[[RDPKeyboard getSharedRDPKeyboard] sendBackspaceKeyStroke];
Packit Service 5a9772
	}
Packit Service 5a9772
Packit 1fb8d4
	return NO;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark AdvancedKeyboardDelegate functions
Packit Service 5a9772
- (void)advancedKeyPressedVKey:(int)key
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] sendVirtualKeyCode:key];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)advancedKeyPressedUnicode:(int)key
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] sendUnicode:key];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark - RDP keyboard handler
Packit 1fb8d4
Packit 1fb8d4
- (void)modifiersChangedForKeyboard:(RDPKeyboard *)keyboard
Packit 1fb8d4
{
Packit Service 5a9772
	UIBarButtonItem *curItem;
Packit Service 5a9772
Packit Service 5a9772
	// shift button (only on iPad)
Packit Service 5a9772
	int objectIdx = 0;
Packit Service 5a9772
	if (IsPad())
Packit Service 5a9772
	{
Packit Service 5a9772
		objectIdx = 2;
Packit Service 5a9772
		curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
Packit Service 5a9772
		[curItem setStyle:[keyboard shiftPressed] ? UIBarButtonItemStyleDone
Packit Service 5a9772
		                                          : UIBarButtonItemStyleBordered];
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	// ctrl button
Packit Service 5a9772
	objectIdx += 2;
Packit Service 5a9772
	curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
Packit Service 5a9772
	[curItem
Packit Service 5a9772
	    setStyle:[keyboard ctrlPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
Packit Service 5a9772
Packit Service 5a9772
	// win button
Packit Service 5a9772
	objectIdx += 2;
Packit Service 5a9772
	curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
Packit Service 5a9772
	[curItem
Packit Service 5a9772
	    setStyle:[keyboard winPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
Packit Service 5a9772
Packit Service 5a9772
	// alt button
Packit Service 5a9772
	objectIdx += 2;
Packit Service 5a9772
	curItem = (UIBarButtonItem *)[[_keyboard_toolbar items] objectAtIndex:objectIdx];
Packit Service 5a9772
	[curItem
Packit Service 5a9772
	    setStyle:[keyboard altPressed] ? UIBarButtonItemStyleDone : UIBarButtonItemStyleBordered];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark RDPSessionDelegate functions
Packit 1fb8d4
Packit Service 5a9772
- (void)session:(RDPSession *)session didFailToConnect:(int)reason
Packit 1fb8d4
{
Packit Service 5a9772
	// remove and release connecting view
Packit Service 5a9772
	[_connecting_indicator_view stopAnimating];
Packit Service 5a9772
	[_connecting_view removeFromSuperview];
Packit Service 5a9772
	[_connecting_view autorelease];
Packit 1fb8d4
Packit Service 5a9772
	// return to bookmark list
Packit Service 5a9772
	[[self navigationController] popViewControllerAnimated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionWillConnect:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	// load connecting view
Packit Service 5a9772
	[[NSBundle mainBundle] loadNibNamed:@"RDPConnectingView" owner:self options:nil];
Packit 1fb8d4
Packit Service 5a9772
	// set strings
Packit Service 5a9772
	[_lbl_connecting setText:NSLocalizedString(@"Connecting", @"Connecting progress view - label")];
Packit Service 5a9772
	[_cancel_connect_button setTitle:NSLocalizedString(@"Cancel", @"Cancel Button")
Packit Service 5a9772
	                        forState:UIControlStateNormal];
Packit 1fb8d4
Packit Service 5a9772
	// center view and give it round corners
Packit Service 5a9772
	[_connecting_view setCenter:[[self view] center]];
Packit Service 5a9772
	[[_connecting_view layer] setCornerRadius:10];
Packit 1fb8d4
Packit Service 5a9772
	// display connecting view and start indicator
Packit Service 5a9772
	[[self view] addSubview:_connecting_view];
Packit Service 5a9772
	[_connecting_indicator_view startAnimating];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionDidConnect:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	// register keyboard notification handlers
Packit Service 5a9772
	[[NSNotificationCenter defaultCenter] addObserver:self
Packit Service 5a9772
	                                         selector:@selector(keyboardWillShow:)
Packit Service 5a9772
	                                             name:UIKeyboardWillShowNotification
Packit Service 5a9772
	                                           object:nil];
Packit Service 5a9772
	[[NSNotificationCenter defaultCenter] addObserver:self
Packit Service 5a9772
	                                         selector:@selector(keyboardDidShow:)
Packit Service 5a9772
	                                             name:UIKeyboardDidShowNotification
Packit Service 5a9772
	                                           object:nil];
Packit Service 5a9772
	[[NSNotificationCenter defaultCenter] addObserver:self
Packit Service 5a9772
	                                         selector:@selector(keyboardWillHide:)
Packit Service 5a9772
	                                             name:UIKeyboardWillHideNotification
Packit Service 5a9772
	                                           object:nil];
Packit Service 5a9772
	[[NSNotificationCenter defaultCenter] addObserver:self
Packit Service 5a9772
	                                         selector:@selector(keyboardDidHide:)
Packit Service 5a9772
	                                             name:UIKeyboardDidHideNotification
Packit Service 5a9772
	                                           object:nil];
Packit Service 5a9772
Packit Service 5a9772
	// remove and release connecting view
Packit Service 5a9772
	[_connecting_indicator_view stopAnimating];
Packit Service 5a9772
	[_connecting_view removeFromSuperview];
Packit Service 5a9772
	[_connecting_view autorelease];
Packit Service 5a9772
Packit Service 5a9772
	// check if session settings changed ...
Packit Service 5a9772
	// The 2nd width check is to ignore changes in resolution settings due to the RDVH display bug
Packit Service 5a9772
	// (refer to RDPSEssion.m for more details)
Packit Service 5a9772
	ConnectionParams *orig_params = [session params];
Packit Service 5a9772
	rdpSettings *sess_params = [session getSessionParams];
Packit Service 5a9772
	if (([orig_params intForKey:@"width"] != sess_params->DesktopWidth &&
Packit Service 5a9772
	     [orig_params intForKey:@"width"] != (sess_params->DesktopWidth + 1)) ||
Packit Service 5a9772
	    [orig_params intForKey:@"height"] != sess_params->DesktopHeight ||
Packit Service 5a9772
	    [orig_params intForKey:@"colors"] != sess_params->ColorDepth)
Packit Service 5a9772
	{
Packit Service 5a9772
		// display notification that the session params have been changed by the server
Packit Service 5a9772
		NSString *message =
Packit Service 5a9772
		    [NSString stringWithFormat:NSLocalizedString(
Packit Service 5a9772
		                                   @"The server changed the screen settings to %dx%dx%d",
Packit Service 5a9772
		                                   @"Screen settings not supported message with width, "
Packit Service 5a9772
		                                   @"height and colors parameter"),
Packit Service 5a9772
		                               sess_params->DesktopWidth, sess_params->DesktopHeight,
Packit Service 5a9772
		                               sess_params->ColorDepth];
Packit Service 5a9772
		[[self view] makeToast:message duration:ToastDurationNormal position:@"bottom"];
Packit Service 5a9772
	}
Packit Service 5a9772
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionWillDisconnect:(RDPSession *)session
Packit Service 5a9772
{
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionDidDisconnect:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	// return to bookmark list
Packit Service 5a9772
	[[self navigationController] popViewControllerAnimated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionBitmapContextWillChange:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	// calc new view frame
Packit Service 5a9772
	rdpSettings *sess_params = [session getSessionParams];
Packit Service 5a9772
	CGRect view_rect = CGRectMake(0, 0, sess_params->DesktopWidth, sess_params->DesktopHeight);
Packit Service 5a9772
Packit Service 5a9772
	// reset  zoom level and update content size
Packit Service 5a9772
	[_session_scrollview setZoomScale:1.0];
Packit Service 5a9772
	[_session_scrollview setContentSize:view_rect.size];
Packit 1fb8d4
Packit Service 5a9772
	// set session view size
Packit Service 5a9772
	[_session_view setFrame:view_rect];
Packit 1fb8d4
Packit Service 5a9772
	// show/hide toolbar
Packit Service 5a9772
	[_session
Packit Service 5a9772
	    setToolbarVisible:![[NSUserDefaults standardUserDefaults] boolForKey:@"ui.hide_tool_bar"]];
Packit Service 5a9772
	[self showSessionToolbar:[_session toolbarVisible]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sessionBitmapContextDidChange:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	// associate view with session
Packit Service 5a9772
	[_session_view setSession:session];
Packit 1fb8d4
Packit Service 5a9772
	// issue an update (this might be needed in case we had a resize for instance)
Packit Service 5a9772
	[_session_view setNeedsDisplay];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)session:(RDPSession *)session needsRedrawInRect:(CGRect)rect
Packit 1fb8d4
{
Packit Service 5a9772
	[_session_view setNeedsDisplayInRect:rect];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)session:(RDPSession *)session requestsAuthenticationWithParams:(NSMutableDictionary *)params
Packit 1fb8d4
{
Packit Service 5a9772
	CredentialsInputController *view_controller =
Packit Service 5a9772
	    [[[CredentialsInputController alloc] initWithNibName:@"CredentialsInputView"
Packit Service 5a9772
	                                                  bundle:nil
Packit Service 5a9772
	                                                 session:_session
Packit Service 5a9772
	                                                  params:params] autorelease];
Packit Service 5a9772
	[self presentModalViewController:view_controller animated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)session:(RDPSession *)session verifyCertificateWithParams:(NSMutableDictionary *)params
Packit 1fb8d4
{
Packit Service 5a9772
	VerifyCertificateController *view_controller =
Packit Service 5a9772
	    [[[VerifyCertificateController alloc] initWithNibName:@"VerifyCertificateView"
Packit Service 5a9772
	                                                   bundle:nil
Packit Service 5a9772
	                                                  session:_session
Packit Service 5a9772
	                                                   params:params] autorelease];
Packit Service 5a9772
	[self presentModalViewController:view_controller animated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (CGSize)sizeForFitScreenForSession:(RDPSession *)session
Packit 1fb8d4
{
Packit Service 5a9772
	if (IsPad())
Packit Service 5a9772
		return [self view].bounds.size;
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		// on phones make a resolution that has a 16:10 ratio with the phone's height
Packit Service 5a9772
		CGSize size = [self view].bounds.size;
Packit Service 5a9772
		CGFloat maxSize = (size.width > size.height) ? size.width : size.height;
Packit Service 5a9772
		return CGSizeMake(maxSize * 1.6f, maxSize);
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark - Keyboard Toolbar Handlers
Packit 1fb8d4
Packit Service 5a9772
- (void)showAdvancedKeyboardAnimated
Packit 1fb8d4
{
Packit Service 5a9772
	// calc initial and final rect of the advanced keyboard view
Packit Service 5a9772
	CGRect rect = [[_keyboard_toolbar superview] bounds];
Packit Service 5a9772
	rect.origin.y = [_keyboard_toolbar bounds].size.height;
Packit Service 5a9772
	rect.size.height -= rect.origin.y;
Packit Service 5a9772
Packit Service 5a9772
	// create new view (hidden) and add to host-view of keyboard toolbar
Packit Service 5a9772
	_advanced_keyboard_view = [[AdvancedKeyboardView alloc]
Packit Service 5a9772
	    initWithFrame:CGRectMake(rect.origin.x, [[_keyboard_toolbar superview] bounds].size.height,
Packit Service 5a9772
	                             rect.size.width, rect.size.height)
Packit Service 5a9772
	         delegate:self];
Packit Service 5a9772
	[[_keyboard_toolbar superview] addSubview:_advanced_keyboard_view];
Packit Service 5a9772
	// we set autoresize to YES for the keyboard toolbar's superview so that our adv. keyboard view
Packit Service 5a9772
	// gets properly resized
Packit Service 5a9772
	[[_keyboard_toolbar superview] setAutoresizesSubviews:YES];
Packit Service 5a9772
Packit Service 5a9772
	// show view with animation
Packit Service 5a9772
	[UIView beginAnimations:nil context:NULL];
Packit Service 5a9772
	[_advanced_keyboard_view setFrame:rect];
Packit Service 5a9772
	[UIView commitAnimations];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)toggleKeyboardWhenOtherVisible:(id)sender
Packit Service 5a9772
{
Packit Service 5a9772
	if (_advanced_keyboard_visible == NO)
Packit Service 5a9772
	{
Packit Service 5a9772
		[self showAdvancedKeyboardAnimated];
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		// hide existing view
Packit Service 5a9772
		[UIView beginAnimations:@"hide_advanced_keyboard_view" context:NULL];
Packit Service 5a9772
		CGRect rect = [_advanced_keyboard_view frame];
Packit Service 5a9772
		rect.origin.y = [[_keyboard_toolbar superview] bounds].size.height;
Packit Service 5a9772
		[_advanced_keyboard_view setFrame:rect];
Packit Service 5a9772
		[UIView commitAnimations];
Packit Service 5a9772
Packit Service 5a9772
		// the view is released in the animationDidStop selector registered in init
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	// toggle flag
Packit Service 5a9772
	_advanced_keyboard_visible = !_advanced_keyboard_visible;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)toggleWinKey:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] toggleWinKey];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)toggleShiftKey:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] toggleShiftKey];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)toggleCtrlKey:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] toggleCtrlKey];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)toggleAltKey:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] toggleAltKey];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)pressEscKey:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[[RDPKeyboard getSharedRDPKeyboard] sendEscapeKeyStroke];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark event handlers
Packit 1fb8d4
Packit Service 5a9772
- (void)animationStopped:(NSString *)animationID
Packit Service 5a9772
                finished:(NSNumber *)finished
Packit Service 5a9772
                 context:(void *)context
Packit 1fb8d4
{
Packit Service 5a9772
	if ([animationID isEqualToString:@"hide_advanced_keyboard_view"])
Packit Service 5a9772
	{
Packit Service 5a9772
		// cleanup advanced keyboard view
Packit Service 5a9772
		[_advanced_keyboard_view removeFromSuperview];
Packit Service 5a9772
		[_advanced_keyboard_view autorelease];
Packit Service 5a9772
		_advanced_keyboard_view = nil;
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (IBAction)switchSession:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[self suspendSession];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (IBAction)toggleKeyboard:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	if (!_keyboard_visible)
Packit 1fb8d4
		[_dummy_textfield becomeFirstResponder];
Packit 1fb8d4
	else
Packit 1fb8d4
		[_dummy_textfield resignFirstResponder];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (IBAction)toggleExtKeyboard:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	// if the sys kb is shown but not the advanced kb then toggle the advanced kb
Packit Service 5a9772
	if (_keyboard_visible && !_advanced_keyboard_visible)
Packit Service 5a9772
		[self toggleKeyboardWhenOtherVisible:nil];
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		// if not visible request the advanced keyboard view
Packit Service 5a9772
		if (_advanced_keyboard_visible == NO)
Packit Service 5a9772
			_requesting_advanced_keyboard = YES;
Packit Service 5a9772
		[self toggleKeyboard:nil];
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (IBAction)toggleTouchPointer:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	BOOL toggle_visibilty = ![_touchpointer_view isHidden];
Packit Service 5a9772
	[_touchpointer_view setHidden:toggle_visibilty];
Packit Service 5a9772
	if (toggle_visibilty)
Packit Service 5a9772
		[_session_scrollview setContentInset:UIEdgeInsetsZero];
Packit Service 5a9772
	else
Packit Service 5a9772
		[_session_scrollview setContentInset:[_touchpointer_view getEdgeInsets]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (IBAction)disconnectSession:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[_session disconnect];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (IBAction)cancelButtonPressed:(id)sender
Packit 1fb8d4
{
Packit Service 5a9772
	[_session disconnect];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark iOS Keyboard Notification Handlers
Packit 1fb8d4
Packit 1fb8d4
// the keyboard is given in a portrait frame of reference
Packit Service 5a9772
- (BOOL)isLandscape
Packit Service 5a9772
{
Packit Service 5a9772
Packit 1fb8d4
	UIInterfaceOrientation ori = [[UIApplication sharedApplication] statusBarOrientation];
Packit Service 5a9772
	return (ori == UIInterfaceOrientationLandscapeLeft ||
Packit Service 5a9772
	        ori == UIInterfaceOrientationLandscapeRight);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)shiftKeyboard:(NSNotification *)notification
Packit Service 5a9772
{
Packit Service 5a9772
Packit Service 5a9772
	CGRect keyboardEndFrame =
Packit Service 5a9772
	    [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
Packit Service 5a9772
Packit 1fb8d4
	CGFloat previousHeight = _keyboard_last_height;
Packit Service 5a9772
Packit Service 5a9772
	if ([self isLandscape])
Packit Service 5a9772
	{
Packit 1fb8d4
		// landscape has the keyboard based on x, so x can go negative
Packit 1fb8d4
		_keyboard_last_height = keyboardEndFrame.size.width + keyboardEndFrame.origin.x;
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit 1fb8d4
		// portrait has the keyboard based on the difference of the height and the frames y.
Packit 1fb8d4
		CGFloat height = [[UIScreen mainScreen] bounds].size.height;
Packit 1fb8d4
		_keyboard_last_height = height - keyboardEndFrame.origin.y;
Packit 1fb8d4
	}
Packit Service 5a9772
Packit 1fb8d4
	CGFloat shiftHeight = _keyboard_last_height - previousHeight;
Packit Service 5a9772
Packit 1fb8d4
	[UIView beginAnimations:nil context:NULL];
Packit Service 5a9772
	[UIView setAnimationCurve:[[[notification userInfo]
Packit Service 5a9772
	                              objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
Packit Service 5a9772
	[UIView
Packit Service 5a9772
	    setAnimationDuration:[[[notification userInfo]
Packit Service 5a9772
	                             objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
Packit 1fb8d4
	CGRect frame = [_session_scrollview frame];
Packit 1fb8d4
	frame.size.height -= shiftHeight;
Packit 1fb8d4
	[_session_scrollview setFrame:frame];
Packit Service 5a9772
	[_touchpointer_view setFrame:frame];
Packit 1fb8d4
	[UIView commitAnimations];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)keyboardWillShow:(NSNotification *)notification
Packit 1fb8d4
{
Packit Service 5a9772
	[self shiftKeyboard:notification];
Packit Service 5a9772
Packit Service 5a9772
	[_touchpointer_view ensurePointerIsVisible];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)keyboardDidShow:(NSNotification *)notification
Packit 1fb8d4
{
Packit Service 5a9772
	if (_requesting_advanced_keyboard)
Packit Service 5a9772
	{
Packit Service 5a9772
		[self showAdvancedKeyboardAnimated];
Packit Service 5a9772
		_advanced_keyboard_visible = YES;
Packit Service 5a9772
		_requesting_advanced_keyboard = NO;
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)keyboardWillHide:(NSNotification *)notification
Packit 1fb8d4
{
Packit Service 5a9772
Packit Service 5a9772
	[self shiftKeyboard:notification];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)keyboardDidHide:(NSNotification *)notification
Packit 1fb8d4
{
Packit Service 5a9772
	// release adanced keyboard view
Packit Service 5a9772
	if (_advanced_keyboard_visible == YES)
Packit Service 5a9772
	{
Packit Service 5a9772
		_advanced_keyboard_visible = NO;
Packit Service 5a9772
		[_advanced_keyboard_view removeFromSuperview];
Packit Service 5a9772
		[_advanced_keyboard_view autorelease];
Packit Service 5a9772
		_advanced_keyboard_view = nil;
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Gesture handlers
Packit 1fb8d4
Packit Service 5a9772
- (void)handleSingleTap:(UITapGestureRecognizer *)gesture
Packit 1fb8d4
{
Packit 1fb8d4
	CGPoint pos = [gesture locationInView:_session_view];
Packit Service 5a9772
	if (_toggle_mouse_button)
Packit Service 5a9772
	{
Packit Service 5a9772
		[_session
Packit Service 5a9772
		    sendInputEvent:[self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(YES)
Packit Service 5a9772
		                                             position:pos]];
Packit Service 5a9772
		[_session
Packit Service 5a9772
		    sendInputEvent:[self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(NO)
Packit Service 5a9772
		                                             position:pos]];
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		[_session
Packit Service 5a9772
		    sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
Packit Service 5a9772
		                                             position:pos]];
Packit Service 5a9772
		[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
Packit Service 5a9772
		                                                   position:pos]];
Packit Service 5a9772
	}
Packit 1fb8d4
Packit Service 5a9772
	_toggle_mouse_button = NO;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)handleDoubleTap:(UITapGestureRecognizer *)gesture
Packit Service 5a9772
{
Packit Service 5a9772
	CGPoint pos = [gesture locationInView:_session_view];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
Packit Service 5a9772
	                                                   position:pos]];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
Packit Service 5a9772
	                                                   position:pos]];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
Packit Service 5a9772
	                                                   position:pos]];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
Packit Service 5a9772
	                                                   position:pos]];
Packit Service 5a9772
	_toggle_mouse_button = NO;
Packit Service 5a9772
}
Packit Service 5a9772
Packit Service 5a9772
- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
Packit 1fb8d4
{
Packit 1fb8d4
	CGPoint pos = [gesture locationInView:_session_view];
Packit 1fb8d4
Packit Service 5a9772
	if ([gesture state] == UIGestureRecognizerStateBegan)
Packit Service 5a9772
		[_session
Packit Service 5a9772
		    sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(YES)
Packit Service 5a9772
		                                             position:pos]];
Packit Service 5a9772
	else if ([gesture state] == UIGestureRecognizerStateChanged)
Packit Service 5a9772
		[self handleMouseMoveForPosition:pos];
Packit Service 5a9772
	else if ([gesture state] == UIGestureRecognizerStateEnded)
Packit Service 5a9772
		[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(NO)
Packit Service 5a9772
		                                                   position:pos]];
Packit Service 5a9772
}
Packit 1fb8d4
Packit Service 5a9772
- (void)handleDoubleLongPress:(UILongPressGestureRecognizer *)gesture
Packit 1fb8d4
{
Packit Service 5a9772
	// this point is mapped against the scroll view because we want to have relative movement to the
Packit Service 5a9772
	// screen/scrollview
Packit 1fb8d4
	CGPoint pos = [gesture locationInView:_session_scrollview];
Packit Service 5a9772
Packit Service 5a9772
	if ([gesture state] == UIGestureRecognizerStateBegan)
Packit Service 5a9772
		_prev_long_press_position = pos;
Packit Service 5a9772
	else if ([gesture state] == UIGestureRecognizerStateChanged)
Packit Service 5a9772
	{
Packit Service 5a9772
		int delta = _prev_long_press_position.y - pos.y;
Packit Service 5a9772
Packit Service 5a9772
		if (delta > GetScrollGestureDelta())
Packit Service 5a9772
		{
Packit Service 5a9772
			[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetMouseWheelEvent(YES)
Packit Service 5a9772
			                                                   position:pos]];
Packit Service 5a9772
			_prev_long_press_position = pos;
Packit Service 5a9772
		}
Packit Service 5a9772
		else if (delta < -GetScrollGestureDelta())
Packit Service 5a9772
		{
Packit Service 5a9772
			[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetMouseWheelEvent(NO)
Packit Service 5a9772
			                                                   position:pos]];
Packit Service 5a9772
			_prev_long_press_position = pos;
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)handleSingle2FingersTap:(UITapGestureRecognizer *)gesture
Packit 1fb8d4
{
Packit Service 5a9772
	_toggle_mouse_button = !_toggle_mouse_button;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)handleSingle3FingersTap:(UITapGestureRecognizer *)gesture
Packit 1fb8d4
{
Packit Service 5a9772
	[_session setToolbarVisible:![_session toolbarVisible]];
Packit Service 5a9772
	[self showSessionToolbar:[_session toolbarVisible]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Touch Pointer delegates
Packit 1fb8d4
// callback if touch pointer should be closed
Packit Service 5a9772
- (void)touchPointerClose
Packit 1fb8d4
{
Packit Service 5a9772
	[self toggleTouchPointer:nil];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for a left click action
Packit Service 5a9772
- (void)touchPointerLeftClick:(CGPoint)pos down:(BOOL)down
Packit 1fb8d4
{
Packit Service 5a9772
	CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetLeftMouseButtonClickEvent(down)
Packit Service 5a9772
	                                                   position:session_view_pos]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for a right click action
Packit Service 5a9772
- (void)touchPointerRightClick:(CGPoint)pos down:(BOOL)down
Packit 1fb8d4
{
Packit Service 5a9772
	CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetRightMouseButtonClickEvent(down)
Packit Service 5a9772
	                                                   position:session_view_pos]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)doAutoScrolling
Packit 1fb8d4
{
Packit Service 5a9772
	int scrollX = 0;
Packit Service 5a9772
	int scrollY = 0;
Packit Service 5a9772
	CGPoint curPointerPos = [_touchpointer_view getPointerPosition];
Packit Service 5a9772
	CGRect viewBounds = [_touchpointer_view bounds];
Packit Service 5a9772
	CGRect scrollBounds = [_session_view bounds];
Packit Service 5a9772
Packit Service 5a9772
	// add content insets to scroll bounds
Packit Service 5a9772
	scrollBounds.size.width += [_session_scrollview contentInset].right;
Packit Service 5a9772
	scrollBounds.size.height += [_session_scrollview contentInset].bottom;
Packit Service 5a9772
Packit Service 5a9772
	// add zoom factor
Packit Service 5a9772
	scrollBounds.size.width *= [_session_scrollview zoomScale];
Packit Service 5a9772
	scrollBounds.size.height *= [_session_scrollview zoomScale];
Packit Service 5a9772
Packit Service 5a9772
	if (curPointerPos.x > (viewBounds.size.width - [_touchpointer_view getPointerWidth]))
Packit Service 5a9772
		scrollX = AUTOSCROLLDISTANCE;
Packit Service 5a9772
	else if (curPointerPos.x < 0)
Packit Service 5a9772
		scrollX = -AUTOSCROLLDISTANCE;
Packit Service 5a9772
Packit Service 5a9772
	if (curPointerPos.y > (viewBounds.size.height - [_touchpointer_view getPointerHeight]))
Packit Service 5a9772
		scrollY = AUTOSCROLLDISTANCE;
Packit Service 5a9772
	else if (curPointerPos.y < (_session_toolbar_visible ? TOOLBAR_HEIGHT : 0))
Packit Service 5a9772
		scrollY = -AUTOSCROLLDISTANCE;
Packit Service 5a9772
Packit Service 5a9772
	CGPoint newOffset = [_session_scrollview contentOffset];
Packit Service 5a9772
	newOffset.x += scrollX;
Packit Service 5a9772
	newOffset.y += scrollY;
Packit Service 5a9772
Packit Service 5a9772
	// if offset is going off screen - stop scrolling in that direction
Packit Service 5a9772
	if (newOffset.x < 0)
Packit Service 5a9772
	{
Packit Service 5a9772
		scrollX = 0;
Packit Service 5a9772
		newOffset.x = 0;
Packit Service 5a9772
	}
Packit Service 5a9772
	else if (newOffset.x > (scrollBounds.size.width - viewBounds.size.width))
Packit Service 5a9772
	{
Packit Service 5a9772
		scrollX = 0;
Packit Service 5a9772
		newOffset.x = MAX(scrollBounds.size.width - viewBounds.size.width, 0);
Packit Service 5a9772
	}
Packit Service 5a9772
	if (newOffset.y < 0)
Packit Service 5a9772
	{
Packit Service 5a9772
		scrollY = 0;
Packit Service 5a9772
		newOffset.y = 0;
Packit Service 5a9772
	}
Packit Service 5a9772
	else if (newOffset.y > (scrollBounds.size.height - viewBounds.size.height))
Packit Service 5a9772
	{
Packit Service 5a9772
		scrollY = 0;
Packit Service 5a9772
		newOffset.y = MAX(scrollBounds.size.height - viewBounds.size.height, 0);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	// perform scrolling
Packit Service 5a9772
	[_session_scrollview setContentOffset:newOffset];
Packit Service 5a9772
Packit Service 5a9772
	// continue scrolling?
Packit Service 5a9772
	if (scrollX != 0 || scrollY != 0)
Packit Service 5a9772
		[self performSelector:@selector(doAutoScrolling)
Packit Service 5a9772
		           withObject:nil
Packit Service 5a9772
		           afterDelay:AUTOSCROLLTIMEOUT];
Packit Service 5a9772
	else
Packit Service 5a9772
		_is_autoscrolling = NO;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for a right click action
Packit Service 5a9772
- (void)touchPointerMove:(CGPoint)pos
Packit 1fb8d4
{
Packit Service 5a9772
	CGPoint session_view_pos = [_touchpointer_view convertPoint:pos toView:_session_view];
Packit Service 5a9772
	[self handleMouseMoveForPosition:session_view_pos];
Packit Service 5a9772
Packit Service 5a9772
	if (_autoscroll_with_touchpointer && !_is_autoscrolling)
Packit Service 5a9772
	{
Packit Service 5a9772
		_is_autoscrolling = YES;
Packit Service 5a9772
		[self performSelector:@selector(doAutoScrolling)
Packit Service 5a9772
		           withObject:nil
Packit Service 5a9772
		           afterDelay:AUTOSCROLLTIMEOUT];
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback if scrolling is performed
Packit Service 5a9772
- (void)touchPointerScrollDown:(BOOL)down
Packit Service 5a9772
{
Packit Service 5a9772
	[_session sendInputEvent:[self eventDescriptorForMouseEvent:GetMouseWheelEvent(down)
Packit Service 5a9772
	                                                   position:CGPointZero]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for toggling the standard keyboard
Packit Service 5a9772
- (void)touchPointerToggleKeyboard
Packit 1fb8d4
{
Packit Service 5a9772
	if (_advanced_keyboard_visible)
Packit Service 5a9772
		[self toggleKeyboardWhenOtherVisible:nil];
Packit Service 5a9772
	else
Packit Service 5a9772
		[self toggleKeyboard:nil];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for toggling the extended keyboard
Packit Service 5a9772
- (void)touchPointerToggleExtendedKeyboard
Packit 1fb8d4
{
Packit Service 5a9772
	[self toggleExtKeyboard:nil];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// callback for reset view
Packit Service 5a9772
- (void)touchPointerResetSessionView
Packit 1fb8d4
{
Packit Service 5a9772
	[_session_scrollview setZoomScale:1.0 animated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
@implementation RDPSessionViewController (Private)
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Helper functions
Packit 1fb8d4
Packit Service 5a9772
- (void)showSessionToolbar:(BOOL)show
Packit Service 5a9772
{
Packit Service 5a9772
	// already shown or hidden?
Packit Service 5a9772
	if (_session_toolbar_visible == show)
Packit Service 5a9772
		return;
Packit Service 5a9772
Packit Service 5a9772
	if (show)
Packit Service 5a9772
	{
Packit Service 5a9772
		[UIView beginAnimations:@"showToolbar" context:nil];
Packit Service 5a9772
		[UIView setAnimationDuration:.4];
Packit Service 5a9772
		[UIView setAnimationCurve:UIViewAnimationCurveLinear];
Packit Service 5a9772
		[_session_toolbar
Packit Service 5a9772
		    setFrame:CGRectMake(0.0, 0.0, [[self view] bounds].size.width, TOOLBAR_HEIGHT)];
Packit Service 5a9772
		[UIView commitAnimations];
Packit Service 5a9772
		_session_toolbar_visible = YES;
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		[UIView beginAnimations:@"hideToolbar" context:nil];
Packit Service 5a9772
		[UIView setAnimationDuration:.4];
Packit Service 5a9772
		[UIView setAnimationCurve:UIViewAnimationCurveLinear];
Packit Service 5a9772
		[_session_toolbar setFrame:CGRectMake(0.0, -TOOLBAR_HEIGHT, [[self view] bounds].size.width,
Packit Service 5a9772
		                                      TOOLBAR_HEIGHT)];
Packit Service 5a9772
		[UIView commitAnimations];
Packit Service 5a9772
		_session_toolbar_visible = NO;
Packit Service 5a9772
	}
Packit Service 5a9772
}
Packit Service 5a9772
Packit Service 5a9772
- (UIToolbar *)keyboardToolbar
Packit Service 5a9772
{
Packit Service 5a9772
	UIToolbar *keyboard_toolbar = [[[UIToolbar alloc] initWithFrame:CGRectNull] autorelease];
Packit 1fb8d4
	[keyboard_toolbar setBarStyle:UIBarStyleBlackOpaque];
Packit Service 5a9772
Packit Service 5a9772
	UIBarButtonItem *esc_btn =
Packit Service 5a9772
	    [[[UIBarButtonItem alloc] initWithTitle:@"Esc"
Packit Service 5a9772
	                                      style:UIBarButtonItemStyleBordered
Packit Service 5a9772
	                                     target:self
Packit Service 5a9772
	                                     action:@selector(pressEscKey:)] autorelease];
Packit Service 5a9772
	UIImage *win_icon =
Packit Service 5a9772
	    [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"toolbar_icon_win"
Packit Service 5a9772
	                                                                     ofType:@"png"]];
Packit Service 5a9772
	UIBarButtonItem *win_btn =
Packit Service 5a9772
	    [[[UIBarButtonItem alloc] initWithImage:win_icon
Packit Service 5a9772
	                                      style:UIBarButtonItemStyleBordered
Packit Service 5a9772
	                                     target:self
Packit Service 5a9772
	                                     action:@selector(toggleWinKey:)] autorelease];
Packit Service 5a9772
	UIBarButtonItem *ctrl_btn =
Packit Service 5a9772
	    [[[UIBarButtonItem alloc] initWithTitle:@"Ctrl"
Packit Service 5a9772
	                                      style:UIBarButtonItemStyleBordered
Packit Service 5a9772
	                                     target:self
Packit Service 5a9772
	                                     action:@selector(toggleCtrlKey:)] autorelease];
Packit Service 5a9772
	UIBarButtonItem *alt_btn =
Packit Service 5a9772
	    [[[UIBarButtonItem alloc] initWithTitle:@"Alt"
Packit Service 5a9772
	                                      style:UIBarButtonItemStyleBordered
Packit Service 5a9772
	                                     target:self
Packit Service 5a9772
	                                     action:@selector(toggleAltKey:)] autorelease];
Packit Service 5a9772
	UIBarButtonItem *ext_btn = [[[UIBarButtonItem alloc]
Packit Service 5a9772
	    initWithTitle:@"Ext"
Packit Service 5a9772
	            style:UIBarButtonItemStyleBordered
Packit Service 5a9772
	           target:self
Packit Service 5a9772
	           action:@selector(toggleKeyboardWhenOtherVisible:)] autorelease];
Packit Service 5a9772
	UIBarButtonItem *done_btn = [[[UIBarButtonItem alloc]
Packit Service 5a9772
	    initWithBarButtonSystemItem:UIBarButtonSystemItemDone
Packit Service 5a9772
	                         target:self
Packit Service 5a9772
	                         action:@selector(toggleKeyboard:)] autorelease];
Packit Service 5a9772
	UIBarButtonItem *flex_spacer =
Packit Service 5a9772
	    [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
Packit Service 5a9772
	                                                   target:nil
Packit Service 5a9772
	                                                   action:nil] autorelease];
Packit Service 5a9772
Packit Service 5a9772
	// iPad gets a shift button, iphone doesn't (there's just not enough space ...)
Packit Service 5a9772
	NSArray *items;
Packit Service 5a9772
	if (IsPad())
Packit Service 5a9772
	{
Packit Service 5a9772
		UIBarButtonItem *shift_btn =
Packit Service 5a9772
		    [[[UIBarButtonItem alloc] initWithTitle:@"Shift"
Packit Service 5a9772
		                                      style:UIBarButtonItemStyleBordered
Packit Service 5a9772
		                                     target:self
Packit Service 5a9772
		                                     action:@selector(toggleShiftKey:)] autorelease];
Packit Service 5a9772
		items = [NSArray arrayWithObjects:esc_btn, flex_spacer, shift_btn, flex_spacer, ctrl_btn,
Packit Service 5a9772
		                                  flex_spacer, win_btn, flex_spacer, alt_btn, flex_spacer,
Packit Service 5a9772
		                                  ext_btn, flex_spacer, done_btn, nil];
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		items = [NSArray arrayWithObjects:esc_btn, flex_spacer, ctrl_btn, flex_spacer, win_btn,
Packit Service 5a9772
		                                  flex_spacer, alt_btn, flex_spacer, ext_btn, flex_spacer,
Packit Service 5a9772
		                                  done_btn, nil];
Packit Service 5a9772
	}
Packit Service 5a9772
Packit 1fb8d4
	[keyboard_toolbar setItems:items];
Packit Service 5a9772
	[keyboard_toolbar sizeToFit];
Packit Service 5a9772
	return keyboard_toolbar;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)initGestureRecognizers
Packit Service 5a9772
{
Packit Service 5a9772
	// single and double tap recognizer
Packit Service 5a9772
	UITapGestureRecognizer *doubleTapRecognizer =
Packit Service 5a9772
	    [[[UITapGestureRecognizer alloc] initWithTarget:self
Packit Service 5a9772
	                                             action:@selector(handleDoubleTap:)] autorelease];
Packit Service 5a9772
	[doubleTapRecognizer setNumberOfTouchesRequired:1];
Packit Service 5a9772
	[doubleTapRecognizer setNumberOfTapsRequired:2];
Packit Service 5a9772
Packit Service 5a9772
	UITapGestureRecognizer *singleTapRecognizer =
Packit Service 5a9772
	    [[[UITapGestureRecognizer alloc] initWithTarget:self
Packit Service 5a9772
	                                             action:@selector(handleSingleTap:)] autorelease];
Packit Service 5a9772
	[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
Packit Service 5a9772
	[singleTapRecognizer setNumberOfTouchesRequired:1];
Packit 1fb8d4
	[singleTapRecognizer setNumberOfTapsRequired:1];
Packit Service 5a9772
Packit Service 5a9772
	// 2 fingers - tap recognizer
Packit Service 5a9772
	UITapGestureRecognizer *single2FingersTapRecognizer = [[[UITapGestureRecognizer alloc]
Packit Service 5a9772
	    initWithTarget:self
Packit Service 5a9772
	            action:@selector(handleSingle2FingersTap:)] autorelease];
Packit Service 5a9772
	[single2FingersTapRecognizer setNumberOfTouchesRequired:2];
Packit 1fb8d4
	[single2FingersTapRecognizer setNumberOfTapsRequired:1];
Packit Service 5a9772
Packit 1fb8d4
	// long press gesture recognizer
Packit Service 5a9772
	UILongPressGestureRecognizer *longPressRecognizer = [[[UILongPressGestureRecognizer alloc]
Packit Service 5a9772
	    initWithTarget:self
Packit Service 5a9772
	            action:@selector(handleLongPress:)] autorelease];
Packit 1fb8d4
	[longPressRecognizer setMinimumPressDuration:0.5];
Packit Service 5a9772
Packit Service 5a9772
	// double long press gesture recognizer
Packit Service 5a9772
	UILongPressGestureRecognizer *doubleLongPressRecognizer = [[[UILongPressGestureRecognizer alloc]
Packit Service 5a9772
	    initWithTarget:self
Packit Service 5a9772
	            action:@selector(handleDoubleLongPress:)] autorelease];
Packit Service 5a9772
	[doubleLongPressRecognizer setNumberOfTouchesRequired:2];
Packit 1fb8d4
	[doubleLongPressRecognizer setMinimumPressDuration:0.5];
Packit Service 5a9772
Packit Service 5a9772
	// 3 finger, single tap gesture for showing/hiding the toolbar
Packit Service 5a9772
	UITapGestureRecognizer *single3FingersTapRecognizer = [[[UITapGestureRecognizer alloc]
Packit Service 5a9772
	    initWithTarget:self
Packit Service 5a9772
	            action:@selector(handleSingle3FingersTap:)] autorelease];
Packit Service 5a9772
	[single3FingersTapRecognizer setNumberOfTapsRequired:1];
Packit Service 5a9772
	[single3FingersTapRecognizer setNumberOfTouchesRequired:3];
Packit Service 5a9772
Packit Service 5a9772
	// add gestures to scroll view
Packit 1fb8d4
	[_session_scrollview addGestureRecognizer:singleTapRecognizer];
Packit 1fb8d4
	[_session_scrollview addGestureRecognizer:doubleTapRecognizer];
Packit 1fb8d4
	[_session_scrollview addGestureRecognizer:single2FingersTapRecognizer];
Packit 1fb8d4
	[_session_scrollview addGestureRecognizer:longPressRecognizer];
Packit 1fb8d4
	[_session_scrollview addGestureRecognizer:doubleLongPressRecognizer];
Packit Service 5a9772
	[_session_scrollview addGestureRecognizer:single3FingersTapRecognizer];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)suspendSession
Packit 1fb8d4
{
Packit 1fb8d4
	// suspend session and pop navigation controller
Packit Service 5a9772
	[_session suspend];
Packit Service 5a9772
Packit Service 5a9772
	// pop current view controller
Packit Service 5a9772
	[[self navigationController] popViewControllerAnimated:YES];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (NSDictionary *)eventDescriptorForMouseEvent:(int)event position:(CGPoint)position
Packit 1fb8d4
{
Packit Service 5a9772
	return [NSDictionary
Packit Service 5a9772
	    dictionaryWithObjectsAndKeys:@"mouse", @"type", [NSNumber numberWithUnsignedShort:event],
Packit Service 5a9772
	                                 @"flags",
Packit Service 5a9772
	                                 [NSNumber numberWithUnsignedShort:lrintf(position.x)],
Packit Service 5a9772
	                                 @"coord_x",
Packit Service 5a9772
	                                 [NSNumber numberWithUnsignedShort:lrintf(position.y)],
Packit Service 5a9772
	                                 @"coord_y", nil];
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
- (void)sendDelayedMouseEventWithTimer:(NSTimer *)timer
Packit 1fb8d4
{
Packit Service 5a9772
	_mouse_move_event_timer = nil;
Packit Service 5a9772
	NSDictionary *event = [timer userInfo];
Packit Service 5a9772
	[_session sendInputEvent:event];
Packit Service 5a9772
	[timer autorelease];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)handleMouseMoveForPosition:(CGPoint)position
Packit 1fb8d4
{
Packit Service 5a9772
	NSDictionary *event = [self eventDescriptorForMouseEvent:PTR_FLAGS_MOVE position:position];
Packit Service 5a9772
Packit Service 5a9772
	// cancel pending mouse move events
Packit Service 5a9772
	[_mouse_move_event_timer invalidate];
Packit Service 5a9772
	_mouse_move_events_skipped++;
Packit Service 5a9772
Packit Service 5a9772
	if (_mouse_move_events_skipped >= 5)
Packit Service 5a9772
	{
Packit Service 5a9772
		[_session sendInputEvent:event];
Packit Service 5a9772
		_mouse_move_events_skipped = 0;
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		[_mouse_move_event_timer autorelease];
Packit Service 5a9772
		_mouse_move_event_timer =
Packit Service 5a9772
		    [[NSTimer scheduledTimerWithTimeInterval:0.05
Packit Service 5a9772
		                                      target:self
Packit Service 5a9772
		                                    selector:@selector(sendDelayedMouseEventWithTimer:)
Packit Service 5a9772
		                                    userInfo:event
Packit Service 5a9772
		                                     repeats:NO] retain];
Packit Service 5a9772
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
@end