src/video/uikit/SDL_uikitview.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 May 2010 20:47:22 -0700
changeset 4465 3e69e077cb95
parent 3685 64ce267332c6
child 4488 6dc6a2bdd55e
permissions -rw-r--r--
Removed multi-mouse / multi-keyboard support in anticipation of a real multi-mouse and multi-touch API.

Plus, this lets me start implementing cursor support.
     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 #if SDL_IPHONE_KEYBOARD
    26 #import "SDL_keyboard_c.h"
    27 #import "keyinfotable.h"
    28 #import "SDL_uikitappdelegate.h"
    29 #import "SDL_uikitwindow.h"
    30 #endif
    31 
    32 @implementation SDL_uikitview
    33 
    34 - (void)dealloc {
    35 #if SDL_IPHONE_KEYBOARD
    36 	SDL_DelKeyboard(0);
    37 	[textField release];
    38 #endif
    39 	[super dealloc];
    40 }
    41 
    42 - (id)initWithFrame:(CGRect)frame {
    43 
    44 	self = [super initWithFrame: frame];
    45 	
    46 #if SDL_IPHONE_KEYBOARD
    47 	[self initializeKeyboard];
    48 #endif	
    49 
    50 #if FIXME_MULTITOUCH
    51 	int i;
    52 	for (i=0; i<MAX_SIMULTANEOUS_TOUCHES; i++) {
    53         mice[i].id = i;
    54 		mice[i].driverdata = NULL;
    55 		SDL_AddMouse(&mice[i], "Mouse", 0, 0, 1);
    56 	}
    57 	self.multipleTouchEnabled = YES;
    58 #endif
    59 			
    60 	return self;
    61 
    62 }
    63 
    64 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    65 
    66 	NSEnumerator *enumerator = [touches objectEnumerator];
    67 	UITouch *touch =(UITouch*)[enumerator nextObject];
    68 	
    69 #if FIXME_MULTITOUCH
    70 	/* associate touches with mice, so long as we have slots */
    71 	int i;
    72 	int found = 0;
    73 	for(i=0; touch && i < MAX_SIMULTANEOUS_TOUCHES; i++) {
    74 	
    75 		/* check if this mouse is already tracking a touch */
    76 		if (mice[i].driverdata != NULL) {
    77 			continue;
    78 		}
    79 		/*	
    80 			mouse not associated with anything right now,
    81 			associate the touch with this mouse
    82 		*/
    83 		found = 1;
    84 		
    85 		/* save old mouse so we can switch back */
    86 		int oldMouse = SDL_SelectMouse(-1);
    87 		
    88 		/* select this slot's mouse */
    89 		SDL_SelectMouse(i);
    90 		CGPoint locationInView = [touch locationInView: self];
    91 		
    92 		/* set driver data to touch object, we'll use touch object later */
    93 		mice[i].driverdata = [touch retain];
    94 		
    95 		/* send moved event */
    96 		SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
    97 		
    98 		/* send mouse down event */
    99 		SDL_SendMouseButton(i, SDL_PRESSED, SDL_BUTTON_LEFT);
   100 		
   101 		/* re-calibrate relative mouse motion */
   102 		SDL_GetRelativeMouseState(i, NULL, NULL);
   103 		
   104 		/* grab next touch */
   105 		touch = (UITouch*)[enumerator nextObject]; 
   106 		
   107 		/* switch back to our old mouse */
   108 		SDL_SelectMouse(oldMouse);
   109 		
   110 	}
   111 #endif
   112 }
   113 
   114 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
   115 	
   116 	NSEnumerator *enumerator = [touches objectEnumerator];
   117 	UITouch *touch=nil;
   118 	
   119 #if FIXME_MULTITOUCH
   120 	while(touch = (UITouch *)[enumerator nextObject]) {
   121 		/* search for the mouse slot associated with this touch */
   122 		int i, found = NO;
   123 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
   124 			if (mice[i].driverdata == touch) {
   125 				/* found the mouse associate with the touch */
   126 				[(UITouch*)(mice[i].driverdata) release];
   127 				mice[i].driverdata = NULL;
   128 				/* send mouse up */
   129 				SDL_SendMouseButton(i, SDL_RELEASED, SDL_BUTTON_LEFT);
   130 				/* discontinue search for this touch */
   131 				found = YES;
   132 			}
   133 		}
   134 	}
   135 #endif
   136 }
   137 
   138 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
   139 	/*
   140 		this can happen if the user puts more than 5 touches on the screen
   141 		at once, or perhaps in other circumstances.  Usually (it seems)
   142 		all active touches are canceled.
   143 	*/
   144 	[self touchesEnded: touches withEvent: event];
   145 }
   146 
   147 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
   148 	
   149 	NSEnumerator *enumerator = [touches objectEnumerator];
   150 	UITouch *touch=nil;
   151 	
   152 #if FIXME_MULTITOUCH
   153 	while(touch = (UITouch *)[enumerator nextObject]) {
   154 		/* try to find the mouse associated with this touch */
   155 		int i, found = NO;
   156 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
   157 			if (mice[i].driverdata == touch) {
   158 				/* found proper mouse */
   159 				CGPoint locationInView = [touch locationInView: self];
   160 				/* send moved event */
   161 				SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
   162 				/* discontinue search */
   163 				found = YES;
   164 			}
   165 		}
   166 	}
   167 #endif
   168 }
   169 
   170 /*
   171 	---- Keyboard related functionality below this line ----
   172 */
   173 #if SDL_IPHONE_KEYBOARD
   174 
   175 /* Is the iPhone virtual keyboard visible onscreen? */
   176 - (BOOL)keyboardVisible {
   177 	return keyboardVisible;
   178 }
   179 
   180 /* Set ourselves up as a UITextFieldDelegate */
   181 - (void)initializeKeyboard {
   182 		
   183 	textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease];
   184 	textField.delegate = self;
   185 	/* placeholder so there is something to delete! */
   186 	textField.text = @" ";	
   187 	
   188 	/* set UITextInputTrait properties, mostly to defaults */
   189 	textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
   190 	textField.autocorrectionType = UITextAutocorrectionTypeNo;
   191 	textField.enablesReturnKeyAutomatically = NO;
   192 	textField.keyboardAppearance = UIKeyboardAppearanceDefault;
   193 	textField.keyboardType = UIKeyboardTypeDefault;
   194 	textField.returnKeyType = UIReturnKeyDefault;
   195 	textField.secureTextEntry = NO;	
   196 	
   197 	textField.hidden = YES;
   198 	keyboardVisible = NO;
   199 	/* add the UITextField (hidden) to our view */
   200 	[self addSubview: textField];
   201 	
   202 	/* create our SDL_Keyboard */
   203 	SDL_Keyboard keyboard;
   204 	SDL_zero(keyboard);
   205 	SDL_AddKeyboard(&keyboard, 0);
   206 	SDLKey keymap[SDL_NUM_SCANCODES];
   207 	SDL_GetDefaultKeymap(keymap);
   208 	SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
   209 	
   210 }
   211 
   212 /* reveal onscreen virtual keyboard */
   213 - (void)showKeyboard {
   214 	keyboardVisible = YES;
   215 	[textField becomeFirstResponder];
   216 }
   217 
   218 /* hide onscreen virtual keyboard */
   219 - (void)hideKeyboard {
   220 	keyboardVisible = NO;
   221 	[textField resignFirstResponder];
   222 }
   223 
   224 /* UITextFieldDelegate method.  Invoked when user types something. */
   225 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
   226 	
   227 	if ([string length] == 0) {
   228 		/* it wants to replace text with nothing, ie a delete */
   229 		SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DELETE);
   230 		SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DELETE);
   231 	}
   232 	else {
   233 		/* go through all the characters in the string we've been sent
   234 		   and convert them to key presses */
   235 		int i;
   236 		for (i=0; i<[string length]; i++) {
   237 			
   238 			unichar c = [string characterAtIndex: i];
   239 			
   240 			Uint16 mod = 0;
   241 			SDL_scancode code;
   242 			
   243 			if (c < 127) {
   244 				/* figure out the SDL_scancode and SDL_keymod for this unichar */
   245 				code = unicharToUIKeyInfoTable[c].code;
   246 				mod  = unicharToUIKeyInfoTable[c].mod;
   247 			}
   248 			else {
   249 				/* we only deal with ASCII right now */
   250 				code = SDL_SCANCODE_UNKNOWN;
   251 				mod = 0;
   252 			}
   253 			
   254 			if (mod & KMOD_SHIFT) {
   255 				/* If character uses shift, press shift down */
   256 				SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT);
   257 			}
   258 			/* send a keydown and keyup even for the character */
   259 			SDL_SendKeyboardKey( 0, SDL_PRESSED, code);
   260 			SDL_SendKeyboardKey( 0, SDL_RELEASED, code);
   261 			if (mod & KMOD_SHIFT) {
   262 				/* If character uses shift, press shift back up */
   263 				SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT);
   264 			}			
   265 		}
   266 	}
   267 	return NO; /* don't allow the edit! (keep placeholder text there) */
   268 }
   269 
   270 /* Terminates the editing session */
   271 - (BOOL)textFieldShouldReturn:(UITextField*)_textField {
   272 	[self hideKeyboard];
   273 	return YES;
   274 }
   275 
   276 #endif
   277 
   278 @end
   279 
   280 /* iPhone keyboard addition functions */
   281 #if SDL_IPHONE_KEYBOARD
   282 
   283 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   284 	
   285 	SDL_WindowData *data;
   286 	SDL_uikitview *view;
   287 	
   288 	if (NULL == window) {
   289 		SDL_SetError("Window does not exist");
   290 		return -1;
   291 	}
   292 	
   293 	data = (SDL_WindowData *)window->driverdata;
   294 	view = data->view;
   295 	
   296 	if (nil == view) {
   297 		SDL_SetError("Window has no view");
   298 		return -1;
   299 	}
   300 	else {
   301 		[view showKeyboard];
   302 		return 0;
   303 	}
   304 }
   305 
   306 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   307 	
   308 	SDL_WindowData *data;
   309 	SDL_uikitview *view;
   310 	
   311 	if (NULL == window) {
   312 		SDL_SetError("Window does not exist");
   313 		return -1;
   314 	}	
   315 	
   316 	data = (SDL_WindowData *)window->driverdata;
   317 	view = data->view;
   318 	
   319 	if (NULL == view) {
   320 		SDL_SetError("Window has no view");
   321 		return -1;
   322 	}
   323 	else {
   324 		[view hideKeyboard];
   325 		return 0;
   326 	}
   327 }
   328 
   329 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   330 	
   331 	SDL_WindowData *data;
   332 	SDL_uikitview *view;
   333 	
   334 	if (NULL == window) {
   335 		SDL_SetError("Window does not exist");
   336 		return -1;
   337 	}	
   338 	
   339 	data = (SDL_WindowData *)window->driverdata;
   340 	view = data->view;
   341 	
   342 	if (NULL == view) {
   343 		SDL_SetError("Window has no view");
   344 		return 0;
   345 	}
   346 	else {
   347 		return view.keyboardVisible;
   348 	}
   349 }
   350 
   351 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   352 	
   353 	SDL_WindowData *data;
   354 	SDL_uikitview *view;
   355 	
   356 	if (NULL == window) {
   357 		SDL_SetError("Window does not exist");
   358 		return -1;
   359 	}	
   360 	
   361 	data = (SDL_WindowData *)window->driverdata;
   362 	view = data->view;
   363 	
   364 	if (NULL == view) {
   365 		SDL_SetError("Window has no view");
   366 		return -1;
   367 	}
   368 	else {
   369 		if (SDL_iPhoneKeyboardIsShown(window)) {
   370 			SDL_iPhoneKeyboardHide(window);
   371 		}
   372 		else {
   373 			SDL_iPhoneKeyboardShow(window);
   374 		}
   375 		return 0;
   376 	}
   377 }
   378 
   379 #else
   380 
   381 /* stubs, used if compiled without keyboard support */
   382 
   383 int SDL_iPhoneKeyboardShow(SDL_Window * window) {
   384 	SDL_SetError("Not compiled with keyboard support");
   385 	return -1;
   386 }
   387 
   388 int SDL_iPhoneKeyboardHide(SDL_Window * window) {
   389 	SDL_SetError("Not compiled with keyboard support");
   390 	return -1;
   391 }
   392 
   393 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window) {
   394 	return 0;
   395 }
   396 
   397 int SDL_iPhoneKeyboardToggle(SDL_Window * window) {
   398 	SDL_SetError("Not compiled with keyboard support");
   399 	return -1;
   400 }
   401 
   402 
   403 #endif /* SDL_IPHONE_KEYBOARD */