src/video/uikit/SDL_uikitview.m
author Jim Grandpre <jim.tla@gmail.com>
Tue, 13 Jul 2010 18:31:09 -0400
changeset 4662 3c4e0130c9b1
parent 4661 03dcb795c583
child 4677 31607094315c
permissions -rw-r--r--
Added alternative finger tracking method. Still prefer IPHONE_TOUCH_EFFICIENT_DANGEROUS.
     1 /*
     2  SDL - Simple DirectMedia Layer
     3  Copyright (C) 1997-2009 Sam Lantinga
     4  
     5  This library is free software; you can redistribute it and/or
     6  modify it under the terms of the GNU Lesser General Public
     7  License as published by the Free Software Foundation; either
     8  version 2.1 of the License, or (at your option) any later version.
     9  
    10  This library 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 GNU
    13  Lesser General Public License for more details.
    14  
    15  You should have received a copy of the GNU Lesser General Public
    16  License along with this library; if not, write to the Free Software
    17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18  
    19  Sam Lantinga
    20  slouken@libsdl.org
    21  */
    22 
    23 #import "SDL_uikitview.h"
    24 
    25 #include "../../events/SDL_keyboard_c.h"
    26 #include "../../events/SDL_mouse_c.h"
    27 
    28 #if SDL_IPHONE_KEYBOARD
    29 #import "keyinfotable.h"
    30 #import "SDL_uikitappdelegate.h"
    31 #import "SDL_uikitwindow.h"
    32 #endif
    33 
    34 @implementation SDL_uikitview
    35 
    36 - (void)dealloc {
    37 #if SDL_IPHONE_KEYBOARD
    38 	[textField release];
    39 #endif
    40 	[super dealloc];
    41 }
    42 
    43 - (id)initWithFrame:(CGRect)frame {
    44 
    45 	self = [super initWithFrame: frame];
    46 	
    47 #if SDL_IPHONE_KEYBOARD
    48 	[self initializeKeyboard];
    49 #endif	
    50 
    51 #if FIXED_MULTITOUCH
    52 	SDL_Touch touch;
    53 	touch.id = 0; //TODO: Should be -1?
    54 
    55 	//touch.driverdata = SDL_malloc(sizeof(EventTouchData));
    56 	//EventTouchData* data = (EventTouchData*)(touch.driverdata);
    57 	
    58 	touch.x_min = 0;
    59 	touch.x_max = frame.size.width;
    60 	touch.xres = touch.x_max - touch.x_min;
    61 	touch.y_min = 0;
    62 	touch.y_max = frame.size.height;
    63 	touch.yres = touch.y_max - touch.y_min;
    64 	touch.pressure_min = 0;
    65 	touch.pressure_max = 1;
    66 	touch.pressureres = touch.pressure_max - touch.pressure_min;
    67 
    68 
    69 	touchId = SDL_AddTouch(&touch, "IPHONE SCREEN");
    70 #endif
    71 
    72 	return self;
    73 
    74 }
    75 
    76 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    77 
    78 	NSEnumerator *enumerator = [touches objectEnumerator];
    79 	UITouch *touch = (UITouch*)[enumerator nextObject];
    80 	
    81 	if (touch) {
    82 		CGPoint locationInView = [touch locationInView: self];
    83 			
    84 		/* send moved event */
    85 		SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
    86 
    87 		/* send mouse down event */
    88 		SDL_SendMouseButton(NULL, SDL_PRESSED, SDL_BUTTON_LEFT);
    89 	}
    90 
    91 #if FIXED_MULTITOUCH
    92 	while(touch) {
    93 	  CGPoint locationInView = [touch locationInView: self];
    94 
    95 
    96 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
    97 	  //FIXME: TODO: Using touch as the fingerId is potentially dangerous
    98 	  //It is also much more efficient than storing the UITouch pointer
    99 	  //and comparing it to the incoming event.
   100 	  SDL_SendFingerDown(touchId,(long)touch,
   101 			     SDL_TRUE,locationInView.x,locationInView.y,
   102 			     1);
   103 #else
   104 	  int i;
   105 	  for(i = 0;i < MAX_SIMULTANEOUS_TOUCHES;i++) {
   106 	    if(finger[i] == NULL) {
   107 	      finger[i] = touch;
   108 	      SDL_SendFingerDown(touchId,i,
   109 				 SDL_TRUE,locationInView.x,locationInView.y,
   110 				 1);
   111 	      break;
   112 	    }
   113 	  }
   114 #endif
   115 	  
   116 
   117 	  
   118 
   119 	  touch = (UITouch*)[enumerator nextObject]; 
   120 	}
   121 #endif
   122 }
   123 
   124 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
   125 	
   126 	NSEnumerator *enumerator = [touches objectEnumerator];
   127 	UITouch *touch = (UITouch*)[enumerator nextObject];
   128 	
   129 	if (touch) {
   130 		/* send mouse up */
   131 		SDL_SendMouseButton(NULL, SDL_RELEASED, SDL_BUTTON_LEFT);
   132 	}
   133 
   134 #if FIXED_MULTITOUCH
   135 	while(touch) {
   136 	  CGPoint locationInView = [touch locationInView: self];
   137 	  
   138 
   139 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   140 	  SDL_SendFingerDown(touchId,(long)touch,
   141 			     SDL_FALSE,locationInView.x,locationInView.y,
   142 			     1);
   143 #else
   144 	  int i;
   145 	  for(i = 0;i < MAX_SIMULTANEOUS_TOUCHES;i++) {
   146 	    if(finger[i] == touch) {
   147 	      SDL_SendFingerDown(touchId,i,
   148 				 SDL_FALSE,locationInView.x,locationInView.y,
   149 				 1);
   150 	      break;
   151 	    }
   152 	  }
   153 #endif
   154 
   155 	  touch = (UITouch*)[enumerator nextObject]; 
   156 	}
   157 #endif
   158 }
   159 
   160 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
   161 	/*
   162 		this can happen if the user puts more than 5 touches on the screen
   163 		at once, or perhaps in other circumstances.  Usually (it seems)
   164 		all active touches are canceled.
   165 	*/
   166 	[self touchesEnded: touches withEvent: event];
   167 }
   168 
   169 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
   170 	
   171 	NSEnumerator *enumerator = [touches objectEnumerator];
   172 	UITouch *touch = (UITouch*)[enumerator nextObject];
   173 	
   174 	if (touch) {
   175 		CGPoint locationInView = [touch locationInView: self];
   176 
   177 		/* send moved event */
   178 		SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
   179 	}
   180 
   181 #if FIXED_MULTITOUCH
   182 	while(touch) {
   183 	  CGPoint locationInView = [touch locationInView: self];
   184 	  
   185 
   186 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   187 	  SDL_SendTouchMotion(touchId,(long)touch,
   188 			      SDL_FALSE,locationInView.x,locationInView.y,
   189 			      1);
   190 #else
   191 	  int i;
   192 	  for(i = 0;i < MAX_SIMULTANEOUS_TOUCHES;i++) {
   193 	    if(finger[i] == touch) {
   194 	      SDL_SendTouchMotion(touchId,i,
   195 				  SDL_FALSE,locationInView.x,locationInView.y,
   196 				  1);
   197 	      break;
   198 	    }
   199 	  }
   200 #endif
   201 
   202 	  touch = (UITouch*)[enumerator nextObject]; 
   203 	}
   204 #endif
   205 }
   206 
   207 /*
   208 	---- Keyboard related functionality below this line ----
   209 */
   210 #if SDL_IPHONE_KEYBOARD
   211 
   212 /* Is the iPhone virtual keyboard visible onscreen? */
   213 - (BOOL)keyboardVisible {
   214 	return keyboardVisible;
   215 }
   216 
   217 /* Set ourselves up as a UITextFieldDelegate */
   218 - (void)initializeKeyboard {
   219 		
   220 	textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease];
   221 	textField.delegate = self;
   222 	/* placeholder so there is something to delete! */
   223 	textField.text = @" ";	
   224 	
   225 	/* set UITextInputTrait properties, mostly to defaults */
   226 	textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
   227 	textField.autocorrectionType = UITextAutocorrectionTypeNo;
   228 	textField.enablesReturnKeyAutomatically = NO;
   229 	textField.keyboardAppearance = UIKeyboardAppearanceDefault;
   230 	textField.keyboardType = UIKeyboardTypeDefault;
   231 	textField.returnKeyType = UIReturnKeyDefault;
   232 	textField.secureTextEntry = NO;	
   233 	
   234 	textField.hidden = YES;
   235 	keyboardVisible = NO;
   236 	/* add the UITextField (hidden) to our view */
   237 	[self addSubview: textField];
   238 }
   239 
   240 /* reveal onscreen virtual keyboard */
   241 - (void)showKeyboard {
   242 	keyboardVisible = YES;
   243 	[textField becomeFirstResponder];
   244 }
   245 
   246 /* hide onscreen virtual keyboard */
   247 - (void)hideKeyboard {
   248 	keyboardVisible = NO;
   249 	[textField resignFirstResponder];
   250 }
   251 
   252 /* UITextFieldDelegate method.  Invoked when user types something. */
   253 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
   254 	
   255 	if ([string length] == 0) {
   256 		/* it wants to replace text with nothing, ie a delete */
   257 		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
   258 		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
   259 	}
   260 	else {
   261 		/* go through all the characters in the string we've been sent
   262 		   and convert them to key presses */
   263 		int i;
   264 		for (i=0; i<[string length]; i++) {
   265 			
   266 			unichar c = [string characterAtIndex: i];
   267 			
   268 			Uint16 mod = 0;
   269 			SDL_scancode code;
   270 			
   271 			if (c < 127) {
   272 				/* figure out the SDL_scancode and SDL_keymod for this unichar */
   273 				code = unicharToUIKeyInfoTable[c].code;
   274 				mod  = unicharToUIKeyInfoTable[c].mod;
   275 			}
   276 			else {
   277 				/* we only deal with ASCII right now */
   278 				code = SDL_SCANCODE_UNKNOWN;
   279 				mod = 0;
   280 			}
   281 			
   282 			if (mod & KMOD_SHIFT) {
   283 				/* If character uses shift, press shift down */
   284 				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
   285 			}
   286 			/* send a keydown and keyup even for the character */
   287 			SDL_SendKeyboardKey(SDL_PRESSED, code);
   288 			SDL_SendKeyboardKey(SDL_RELEASED, code);
   289 			if (mod & KMOD_SHIFT) {
   290 				/* If character uses shift, press shift back up */
   291 				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
   292 			}			
   293 		}
   294 	}
   295 	return NO; /* don't allow the edit! (keep placeholder text there) */
   296 }
   297 
   298 /* Terminates the editing session */
   299 - (BOOL)textFieldShouldReturn:(UITextField*)_textField {
   300 	[self hideKeyboard];
   301 	return YES;
   302 }
   303 
   304 #endif
   305 
   306 @end
   307 
   308 /* iPhone keyboard addition functions */
   309 #if SDL_IPHONE_KEYBOARD
   310 
   311 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   312 	
   313 	SDL_WindowData *data;
   314 	SDL_uikitview *view;
   315 	
   316 	if (NULL == window) {
   317 		SDL_SetError("Window does not exist");
   318 		return -1;
   319 	}
   320 	
   321 	data = (SDL_WindowData *)window->driverdata;
   322 	view = data->view;
   323 	
   324 	if (nil == view) {
   325 		SDL_SetError("Window has no view");
   326 		return -1;
   327 	}
   328 	else {
   329 		[view showKeyboard];
   330 		return 0;
   331 	}
   332 }
   333 
   334 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   335 	
   336 	SDL_WindowData *data;
   337 	SDL_uikitview *view;
   338 	
   339 	if (NULL == window) {
   340 		SDL_SetError("Window does not exist");
   341 		return -1;
   342 	}	
   343 	
   344 	data = (SDL_WindowData *)window->driverdata;
   345 	view = data->view;
   346 	
   347 	if (NULL == view) {
   348 		SDL_SetError("Window has no view");
   349 		return -1;
   350 	}
   351 	else {
   352 		[view hideKeyboard];
   353 		return 0;
   354 	}
   355 }
   356 
   357 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   358 	
   359 	SDL_WindowData *data;
   360 	SDL_uikitview *view;
   361 	
   362 	if (NULL == window) {
   363 		SDL_SetError("Window does not exist");
   364 		return -1;
   365 	}	
   366 	
   367 	data = (SDL_WindowData *)window->driverdata;
   368 	view = data->view;
   369 	
   370 	if (NULL == view) {
   371 		SDL_SetError("Window has no view");
   372 		return 0;
   373 	}
   374 	else {
   375 		return view.keyboardVisible;
   376 	}
   377 }
   378 
   379 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   380 	
   381 	SDL_WindowData *data;
   382 	SDL_uikitview *view;
   383 	
   384 	if (NULL == window) {
   385 		SDL_SetError("Window does not exist");
   386 		return -1;
   387 	}	
   388 	
   389 	data = (SDL_WindowData *)window->driverdata;
   390 	view = data->view;
   391 	
   392 	if (NULL == view) {
   393 		SDL_SetError("Window has no view");
   394 		return -1;
   395 	}
   396 	else {
   397 		if (SDL_iPhoneKeyboardIsShown(window)) {
   398 			SDL_iPhoneKeyboardHide(window);
   399 		}
   400 		else {
   401 			SDL_iPhoneKeyboardShow(window);
   402 		}
   403 		return 0;
   404 	}
   405 }
   406 
   407 #else
   408 
   409 /* stubs, used if compiled without keyboard support */
   410 
   411 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   412 	SDL_SetError("Not compiled with keyboard support");
   413 	return -1;
   414 }
   415 
   416 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   417 	SDL_SetError("Not compiled with keyboard support");
   418 	return -1;
   419 }
   420 
   421 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   422 	return 0;
   423 }
   424 
   425 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   426 	SDL_SetError("Not compiled with keyboard support");
   427 	return -1;
   428 }
   429 
   430 
   431 #endif /* SDL_IPHONE_KEYBOARD */