src/video/uikit/SDL_uikitview.m
author krogoway
Mon, 24 Jan 2011 13:47:35 -0600
changeset 5081 25d4feb7c127
parent 5051 a69e36365766
child 5131 7b7da52e8775
permissions -rw-r--r--
Renamed SDL_keysym to SDL_KeySym
Renamed SDL_scancode to SDL_ScanCode
Added #defines to SDL_compat.h
     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 #include "../../events/SDL_touch_c.h"
    28 
    29 #if SDL_IPHONE_KEYBOARD
    30 #import "keyinfotable.h"
    31 #import "SDL_uikitappdelegate.h"
    32 #import "SDL_uikitwindow.h"
    33 #endif
    34 
    35 @implementation SDL_uikitview
    36 
    37 - (void)dealloc {
    38 	[super dealloc];
    39 }
    40 
    41 - (id)initWithFrame:(CGRect)frame {
    42 
    43 	self = [super initWithFrame: frame];
    44 	
    45 #if SDL_IPHONE_KEYBOARD
    46 	[self initializeKeyboard];
    47 #endif	
    48 
    49 #ifdef FIXED_MULTITOUCH
    50 	SDL_Touch touch;
    51 	touch.id = 0; //TODO: Should be -1?
    52 
    53 	//touch.driverdata = SDL_malloc(sizeof(EventTouchData));
    54 	//EventTouchData* data = (EventTouchData*)(touch.driverdata);
    55 	
    56 	touch.x_min = 0;
    57 	touch.x_max = frame.size.width;
    58 	touch.native_xres = touch.x_max - touch.x_min;
    59 	touch.y_min = 0;
    60 	touch.y_max = frame.size.height;
    61 	touch.native_yres = touch.y_max - touch.y_min;
    62 	touch.pressure_min = 0;
    63 	touch.pressure_max = 1;
    64 	touch.native_pressureres = touch.pressure_max - touch.pressure_min;
    65 
    66 
    67 	touchId = SDL_AddTouch(&touch, "IPHONE SCREEN");
    68 #endif
    69 
    70 	return self;
    71 
    72 }
    73 
    74 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    75 
    76 	NSEnumerator *enumerator = [touches objectEnumerator];
    77 	UITouch *touch = (UITouch*)[enumerator nextObject];
    78 	
    79 	//NSLog("Click");
    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 #ifdef 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 #ifdef 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 #ifdef 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];
   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 	[textField release];
   239 }
   240 
   241 /* reveal onscreen virtual keyboard */
   242 - (void)showKeyboard {
   243 	keyboardVisible = YES;
   244 	[textField becomeFirstResponder];
   245 }
   246 
   247 /* hide onscreen virtual keyboard */
   248 - (void)hideKeyboard {
   249 	keyboardVisible = NO;
   250 	[textField resignFirstResponder];
   251 }
   252 
   253 /* UITextFieldDelegate method.  Invoked when user types something. */
   254 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
   255 	
   256 	if ([string length] == 0) {
   257 		/* it wants to replace text with nothing, ie a delete */
   258 		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
   259 		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
   260 	}
   261 	else {
   262 		/* go through all the characters in the string we've been sent
   263 		   and convert them to key presses */
   264 		int i;
   265 		for (i=0; i<[string length]; i++) {
   266 			
   267 			unichar c = [string characterAtIndex: i];
   268 			
   269 			Uint16 mod = 0;
   270 			SDL_ScanCode code;
   271 			
   272 			if (c < 127) {
   273 				/* figure out the SDL_ScanCode and SDL_keymod for this unichar */
   274 				code = unicharToUIKeyInfoTable[c].code;
   275 				mod  = unicharToUIKeyInfoTable[c].mod;
   276 			}
   277 			else {
   278 				/* we only deal with ASCII right now */
   279 				code = SDL_SCANCODE_UNKNOWN;
   280 				mod = 0;
   281 			}
   282 			
   283 			if (mod & KMOD_SHIFT) {
   284 				/* If character uses shift, press shift down */
   285 				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
   286 			}
   287 			/* send a keydown and keyup even for the character */
   288 			SDL_SendKeyboardKey(SDL_PRESSED, code);
   289 			SDL_SendKeyboardKey(SDL_RELEASED, code);
   290 			if (mod & KMOD_SHIFT) {
   291 				/* If character uses shift, press shift back up */
   292 				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
   293 			}			
   294 		}
   295 	}
   296 	return NO; /* don't allow the edit! (keep placeholder text there) */
   297 }
   298 
   299 /* Terminates the editing session */
   300 - (BOOL)textFieldShouldReturn:(UITextField*)_textField {
   301 	[self hideKeyboard];
   302 	return YES;
   303 }
   304 
   305 #endif
   306 
   307 @end
   308 
   309 /* iPhone keyboard addition functions */
   310 #if SDL_IPHONE_KEYBOARD
   311 
   312 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   313 	
   314 	SDL_WindowData *data;
   315 	SDL_uikitview *view;
   316 	
   317 	if (NULL == window) {
   318 		SDL_SetError("Window does not exist");
   319 		return -1;
   320 	}
   321 	
   322 	data = (SDL_WindowData *)window->driverdata;
   323 	view = data->view;
   324 	
   325 	if (nil == view) {
   326 		SDL_SetError("Window has no view");
   327 		return -1;
   328 	}
   329 	else {
   330 		[view showKeyboard];
   331 		return 0;
   332 	}
   333 }
   334 
   335 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   336 	
   337 	SDL_WindowData *data;
   338 	SDL_uikitview *view;
   339 	
   340 	if (NULL == window) {
   341 		SDL_SetError("Window does not exist");
   342 		return -1;
   343 	}	
   344 	
   345 	data = (SDL_WindowData *)window->driverdata;
   346 	view = data->view;
   347 	
   348 	if (NULL == view) {
   349 		SDL_SetError("Window has no view");
   350 		return -1;
   351 	}
   352 	else {
   353 		[view hideKeyboard];
   354 		return 0;
   355 	}
   356 }
   357 
   358 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   359 	
   360 	SDL_WindowData *data;
   361 	SDL_uikitview *view;
   362 	
   363 	if (NULL == window) {
   364 		SDL_SetError("Window does not exist");
   365 		return -1;
   366 	}	
   367 	
   368 	data = (SDL_WindowData *)window->driverdata;
   369 	view = data->view;
   370 	
   371 	if (NULL == view) {
   372 		SDL_SetError("Window has no view");
   373 		return 0;
   374 	}
   375 	else {
   376 		return view.keyboardVisible;
   377 	}
   378 }
   379 
   380 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   381 	
   382 	SDL_WindowData *data;
   383 	SDL_uikitview *view;
   384 	
   385 	if (NULL == window) {
   386 		SDL_SetError("Window does not exist");
   387 		return -1;
   388 	}	
   389 	
   390 	data = (SDL_WindowData *)window->driverdata;
   391 	view = data->view;
   392 	
   393 	if (NULL == view) {
   394 		SDL_SetError("Window has no view");
   395 		return -1;
   396 	}
   397 	else {
   398 		if (SDL_iPhoneKeyboardIsShown(window)) {
   399 			SDL_iPhoneKeyboardHide(window);
   400 		}
   401 		else {
   402 			SDL_iPhoneKeyboardShow(window);
   403 		}
   404 		return 0;
   405 	}
   406 }
   407 
   408 #else
   409 
   410 /* stubs, used if compiled without keyboard support */
   411 
   412 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   413 	SDL_SetError("Not compiled with keyboard support");
   414 	return -1;
   415 }
   416 
   417 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   418 	SDL_SetError("Not compiled with keyboard support");
   419 	return -1;
   420 }
   421 
   422 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   423 	return 0;
   424 }
   425 
   426 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   427 	SDL_SetError("Not compiled with keyboard support");
   428 	return -1;
   429 }
   430 
   431 
   432 #endif /* SDL_IPHONE_KEYBOARD */