2 * Copyright (C) 2012-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 //hack around problem with xbmc's typedef int BOOL
22 // and obj-c's typedef unsigned char BOOL
23 #define BOOL XBMC_BOOL
24 #include "MouseStat.h"
25 #include "WindowingFactory.h"
26 #include "filesystem/SpecialProtocol.h"
27 #include "guilib/LocalizeStrings.h"
30 #import "IOSExternalTouchController.h"
31 #import "XBMCController.h"
33 //dim the touchscreen after 15 secs without touch event
34 const CGFloat touchScreenDimTimeoutSecs = 15.0;
35 const CGFloat timeFadeSecs = 2.0;
37 @implementation IOSExternalTouchController
38 //--------------------------------------------------------------
41 CGRect frame = [[UIScreen mainScreen] bounds];
47 UIImageView *xbmcLogoView;
48 UILabel *descriptionLabel;
50 _internalWindow = [[UIWindow alloc] initWithFrame:frame];
51 _touchView = [[UIView alloc] initWithFrame:frame];
52 /* Turn on autoresizing for the whole hirarchy*/
53 [_touchView setAutoresizesSubviews:YES];
54 [_touchView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
55 [_touchView setAlpha:0.0];//start with alpha 0 and fade in with animation below
56 [_touchView setMultipleTouchEnabled:YES];
57 [_touchView setContentMode:UIViewContentModeCenter];
60 CGRect labelRect = frame;
61 labelRect.size.height/=2;
62 //uilabel with the description
63 descriptionLabel = [[UILabel alloc] initWithFrame:labelRect];
64 //gray textcolor on transparent background
65 [descriptionLabel setTextColor:[UIColor grayColor]];
66 [descriptionLabel setBackgroundColor:[UIColor clearColor]];
67 //text is aligned left in its frame
68 [descriptionLabel setTextAlignment:UITextAlignmentCenter];
69 [descriptionLabel setContentMode:UIViewContentModeCenter];
70 //setup multiline behaviour
71 [descriptionLabel setLineBreakMode:UILineBreakModeTailTruncation];
73 [descriptionLabel setNumberOfLines:5];
74 CStdString descText = g_localizeStrings.Get(34404) + "\n";
75 descText += g_localizeStrings.Get(34405) + "\n";
76 descText += g_localizeStrings.Get(34406) + "\n";
77 descText += g_localizeStrings.Get(34407) + "\n";
78 descText += g_localizeStrings.Get(34408) + "\n";
80 NSString *stringFromUTFString = [[NSString alloc] initWithUTF8String:descText];
82 [descriptionLabel setText:stringFromUTFString];
83 [stringFromUTFString release];
85 //resize it to full view
86 [descriptionLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
87 [descriptionLabel setAutoresizesSubviews:YES];
88 [_touchView addSubview:descriptionLabel];
89 [descriptionLabel release];
91 //load the splash image
92 CStdString strUserSplash = CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png");
93 xbmcLogo = [UIImage imageWithContentsOfFile:[NSString stringWithUTF8String:strUserSplash.c_str()]];
95 //make a view with the image
96 xbmcLogoView = [[UIImageView alloc] initWithImage:xbmcLogo];
97 //center the image and add it to the view
98 [xbmcLogoView setFrame:frame];
99 [xbmcLogoView setContentMode:UIViewContentModeCenter];
100 //autoresize the image frame
101 [xbmcLogoView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
102 [xbmcLogoView setAutoresizesSubviews:YES];
103 [_touchView addSubview:xbmcLogoView];
104 //send the image to the background
105 [_touchView sendSubviewToBack:xbmcLogoView];
106 [xbmcLogoView release];
108 [[self view] addSubview: _touchView];
110 [self createGestureRecognizers];
112 [_internalWindow addSubview:[self view]];
113 [_internalWindow setBackgroundColor:[UIColor blackColor]];
114 [_internalWindow setScreen:[UIScreen mainScreen]];
115 [_internalWindow makeKeyAndVisible];
116 [_internalWindow setRootViewController:self];
118 [self setWantsFullScreenLayout:YES];
120 [self startSleepTimer];//will fade from black too
124 //--------------------------------------------------------------
125 - (void)startSleepTimer
127 NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:touchScreenDimTimeoutSecs];
129 //schedule sleep timer to fire once in touchScreenDimTimeoutSecs if not reset
130 _sleepTimer = [[NSTimer alloc] initWithFireDate:fireDate
133 selector:@selector(sleepTimerCallback:)
136 //schedule the timer to the runloop
137 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
138 [self fadeFromBlack];
139 [runLoop addTimer:_sleepTimer forMode:NSDefaultRunLoopMode];
141 //--------------------------------------------------------------
142 - (void)stopSleepTimer
144 if(_sleepTimer != nil)
146 [_sleepTimer invalidate];
147 [_sleepTimer release];
151 //--------------------------------------------------------------
152 - (void)sleepTimerCallback:(NSTimer*)theTimer
155 [self stopSleepTimer];
157 //--------------------------------------------------------------
158 - (bool)wakeUpFromSleep//returns false if we where dimmed, true if not
160 if(_sleepTimer == nil)
162 [self startSleepTimer];
167 NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:touchScreenDimTimeoutSecs];
168 [_sleepTimer setFireDate:fireDate];
172 //--------------------------------------------------------------
175 [UIView animateWithDuration:timeFadeSecs delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
176 [_touchView setAlpha:0.01];//fade to black (don't fade to 0.0 else we don't get gesture callbacks)
178 completion:^(BOOL finished){}];
180 //--------------------------------------------------------------
181 - (void)fadeFromBlack
183 [UIView animateWithDuration:timeFadeSecs delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
184 [_touchView setAlpha:1.0];//fade in to full alpha
186 completion:^(BOOL finished){}];
188 //--------------------------------------------------------------
189 - (void)createGestureRecognizers
191 //2 finger single tab - right mouse
192 //single finger double tab delays single finger single tab - so we
193 //go for 2 fingers here - so single finger single tap is instant
194 UITapGestureRecognizer *doubleFingerSingleTap = [[UITapGestureRecognizer alloc]
195 initWithTarget:self action:@selector(handleDoubleFingerSingleTap:)];
196 [doubleFingerSingleTap setNumberOfTapsRequired:1];
197 [doubleFingerSingleTap setNumberOfTouchesRequired:2];
198 [[self view] addGestureRecognizer:doubleFingerSingleTap];
199 [doubleFingerSingleTap release];
201 //1 finger single long tab - right mouse - alernative
202 UITapGestureRecognizer *singleFingerSingleLongTap = (UITapGestureRecognizer*)[[UILongPressGestureRecognizer alloc]
203 initWithTarget:self action:@selector(handleSingleFingerSingleLongTap:)];
204 singleFingerSingleLongTap.delaysTouchesBegan = YES;
205 singleFingerSingleLongTap.delaysTouchesEnded = YES;
206 singleFingerSingleLongTap.numberOfTouchesRequired = 1;
207 [self.view addGestureRecognizer:singleFingerSingleLongTap];
208 [singleFingerSingleLongTap release];
210 //1 finger single tab - left mouse
211 UITapGestureRecognizer *singleFingerSingleTap = [[UITapGestureRecognizer alloc]
212 initWithTarget:self action:@selector(handleSingleFingerSingleTap:)];
213 [singleFingerSingleTap setDelaysTouchesBegan:NO];
214 [[self view] addGestureRecognizer:singleFingerSingleTap];
215 [singleFingerSingleTap release];
217 //double finger swipe left for backspace ... i like this fast backspace feature ;)
218 UISwipeGestureRecognizer *swipeDoubleLeft = [[UISwipeGestureRecognizer alloc]
219 initWithTarget:self action:@selector(handleDoubleSwipeLeft:)];
220 [swipeDoubleLeft setNumberOfTouchesRequired:2];
221 [swipeDoubleLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
222 [[self view] addGestureRecognizer:swipeDoubleLeft];
223 [swipeDoubleLeft release];
225 //single finger swipe left for left
226 UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
227 initWithTarget:self action:@selector(handleSwipeLeft:)];
228 [swipeLeft setNumberOfTouchesRequired:1];
229 [swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
230 [[self view] addGestureRecognizer:swipeLeft];
233 //single finger swipe right for right
234 UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
235 initWithTarget:self action:@selector(handleSwipeRight:)];
236 [swipeRight setNumberOfTouchesRequired:1];
237 [swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
238 [[self view] addGestureRecognizer:swipeRight];
239 [swipeRight release];
241 //single finger swipe up for up
242 UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc]
243 initWithTarget:self action:@selector(handleSwipeUp:)];
244 [swipeUp setNumberOfTouchesRequired:1];
245 [swipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
246 [[self view] addGestureRecognizer:swipeUp];
249 //single finger swipe down for down
250 UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc]
251 initWithTarget:self action:@selector(handleSwipeDown:)];
252 [swipeDown setNumberOfTouchesRequired:1];
253 [swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
254 [[self view] addGestureRecognizer:swipeDown];
258 //--------------------------------------------------------------
259 - (IBAction)handleDoubleSwipeLeft:(UISwipeGestureRecognizer *)sender
261 if([self wakeUpFromSleep])
263 [g_xbmcController sendKey:XBMCK_BACKSPACE];
266 //--------------------------------------------------------------
267 - (IBAction)handleSwipeLeft:(UISwipeGestureRecognizer *)sender
269 if([self wakeUpFromSleep])
271 [g_xbmcController sendKey:XBMCK_LEFT];
274 //--------------------------------------------------------------
275 - (IBAction)handleSwipeRight:(UISwipeGestureRecognizer *)sender
277 if([self wakeUpFromSleep])
279 [g_xbmcController sendKey:XBMCK_RIGHT];
282 //--------------------------------------------------------------
283 - (IBAction)handleSwipeUp:(UISwipeGestureRecognizer *)sender
285 if([self wakeUpFromSleep])
287 [g_xbmcController sendKey:XBMCK_UP];
290 //--------------------------------------------------------------
291 - (IBAction)handleSwipeDown:(UISwipeGestureRecognizer *)sender
293 if([self wakeUpFromSleep])
295 [g_xbmcController sendKey:XBMCK_DOWN];
298 //--------------------------------------------------------------
299 - (IBAction)handleDoubleFingerSingleTap:(UIGestureRecognizer *)sender
301 if([self wakeUpFromSleep])
303 [g_xbmcController sendKey:XBMCK_c];
306 //--------------------------------------------------------------
307 - (IBAction)handleSingleFingerSingleLongTap:(UIGestureRecognizer *)sender
309 if([self wakeUpFromSleep])
311 if (sender.state == UIGestureRecognizerStateEnded)
313 [self handleDoubleFingerSingleTap:sender];
317 //--------------------------------------------------------------
318 - (IBAction)handleSingleFingerSingleTap:(UIGestureRecognizer *)sender
320 if([self wakeUpFromSleep])
322 [g_xbmcController sendKey:XBMCK_RETURN];
325 //--------------------------------------------------------------
326 - (void)viewWillAppear:(BOOL)animated
329 [super viewWillAppear:animated];
331 //--------------------------------------------------------------
334 [self stopSleepTimer];
335 [_touchView release];
336 [_internalWindow release];
339 //--------------------------------------------------------------
340 // - iOS6 rotation API - will be called on iOS7 runtime!--------
341 - (NSUInteger)supportedInterfaceOrientations
343 // mask defines available as of ios6 sdk
344 //return UIInterfaceOrientationMaskAll;
345 return (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight) |
346 (1 << UIInterfaceOrientationPortraitUpsideDown) | (1 << UIInterfaceOrientationPortrait);
348 - (BOOL)shouldAutorotate
351 return [self shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)[[UIDevice currentDevice] orientation]];
353 // - old rotation API will be called on iOS6 and lower - removed in iOS7
354 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
358 //start with landscape
359 switch(interfaceOrientation)
361 case UIInterfaceOrientationLandscapeLeft:
362 case UIInterfaceOrientationLandscapeRight:
370 return YES;//we allow all rotations after startup...
373 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
377 //start with landscape
378 switch(toInterfaceOrientation)
380 case UIInterfaceOrientationLandscapeLeft:
381 case UIInterfaceOrientationLandscapeRight:
382 _startup = false;//allow all orientations after initial landscape rotation
389 //--------------------------------------------------------------