diff src/video/uikit/SDL_uikitview.m @ 2765:f55c87ae336b

Final merge of Google Summer of Code 2008 work... Bring SDL to iPhone and iPod Touch by Holmes Futrell, mentored by Sam Lantinga
author Sam Lantinga <slouken@libsdl.org>
date Sat, 04 Oct 2008 06:46:59 +0000
parents
children 99210400e8b9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/uikit/SDL_uikitview.m	Sat Oct 04 06:46:59 2008 +0000
@@ -0,0 +1,398 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2006 Sam Lantinga
+ 
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ 
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Sam Lantinga
+ slouken@libsdl.org
+ */
+
+#import "SDL_uikitview.h"
+
+#if SDL_IPHONE_KEYBOARD
+#import "SDL_keyboard_c.h"
+#import "keyinfotable.h"
+#import "SDL_uikitappdelegate.h"
+#import "SDL_uikitwindow.h"
+#endif
+
+@implementation SDL_uikitview
+
+- (void)dealloc {
+#if SDL_IPHONE_KEYBOARD
+	SDL_DelKeyboard(0);
+	[textField release];
+#endif
+	[super dealloc];
+}
+
+- (id)initWithFrame:(CGRect)frame {
+
+	self = [super initWithFrame: frame];
+	
+#if SDL_IPHONE_KEYBOARD
+	[self initializeKeyboard];
+#endif	
+
+	int i;
+	for (i=0; i<MAX_SIMULTANEOUS_TOUCHES; i++) {
+		mice[i].driverdata = NULL;
+		SDL_AddMouse(&mice[i], i, "Mouse", 0, 0, 1);
+	}
+	self.multipleTouchEnabled = YES;
+			
+	return self;
+
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+
+	NSEnumerator *enumerator = [touches objectEnumerator];
+	UITouch *touch =(UITouch*)[enumerator nextObject];
+	
+	/* associate touches with mice, so long as we have slots */
+	int i;
+	int found = 0;
+	for(i=0; touch && i < MAX_SIMULTANEOUS_TOUCHES; i++) {
+	
+		/* check if this mouse is already tracking a touch */
+		if (mice[i].driverdata != NULL) {
+			continue;
+		}
+		/*	
+			mouse not associated with anything right now,
+			associate the touch with this mouse
+		*/
+		found = 1;
+		
+		/* save old mouse so we can switch back */
+		int oldMouse = SDL_SelectMouse(-1);
+		
+		/* select this slot's mouse */
+		SDL_SelectMouse(i);
+		CGPoint locationInView = [touch locationInView: self];
+		
+		/* set driver data to touch object, we'll use touch object later */
+		mice[i].driverdata = [touch retain];
+		
+		/* send moved event */
+		SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
+		
+		/* send mouse down event */
+		SDL_SendMouseButton(i, SDL_PRESSED, SDL_BUTTON_LEFT);
+		
+		/* re-calibrate relative mouse motion */
+		SDL_GetRelativeMouseState(i, NULL, NULL);
+		
+		/* grab next touch */
+		touch = (UITouch*)[enumerator nextObject]; 
+		
+		/* switch back to our old mouse */
+		SDL_SelectMouse(oldMouse);
+		
+	}	
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+	NSEnumerator *enumerator = [touches objectEnumerator];
+	UITouch *touch=nil;
+	
+	while(touch = (UITouch *)[enumerator nextObject]) {
+		/* search for the mouse slot associated with this touch */
+		int i, found = NO;
+		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
+			if (mice[i].driverdata == touch) {
+				/* found the mouse associate with the touch */
+				[(UITouch*)(mice[i].driverdata) release];
+				mice[i].driverdata = NULL;
+				/* send mouse up */
+				SDL_SendMouseButton(i, SDL_RELEASED, SDL_BUTTON_LEFT);
+				/* discontinue search for this touch */
+				found = YES;
+			}
+		}
+	}
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+	/*
+		this can happen if the user puts more than 5 touches on the screen
+		at once, or perhaps in other circumstances.  Usually (it seems)
+		all active touches are canceled.
+	*/
+	[self touchesEnded: touches withEvent: event];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+	NSEnumerator *enumerator = [touches objectEnumerator];
+	UITouch *touch=nil;
+	
+	while(touch = (UITouch *)[enumerator nextObject]) {
+		/* try to find the mouse associated with this touch */
+		int i, found = NO;
+		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
+			if (mice[i].driverdata == touch) {
+				/* found proper mouse */
+				CGPoint locationInView = [touch locationInView: self];
+				/* send moved event */
+				SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
+				/* discontinue search */
+				found = YES;
+			}
+		}
+	}
+}
+
+/*
+	---- Keyboard related functionality below this line ----
+*/
+#if SDL_IPHONE_KEYBOARD
+
+/* Is the iPhone virtual keyboard visible onscreen? */
+- (BOOL)keyboardVisible {
+	return keyboardVisible;
+}
+
+/* Set ourselves up as a UITextFieldDelegate */
+- (void)initializeKeyboard {
+		
+	textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease];
+	textField.delegate = self;
+	/* placeholder so there is something to delete! */
+	textField.text = @" ";	
+	
+	/* set UITextInputTrait properties, mostly to defaults */
+	textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
+	textField.autocorrectionType = UITextAutocorrectionTypeNo;
+	textField.enablesReturnKeyAutomatically = NO;
+	textField.keyboardAppearance = UIKeyboardAppearanceDefault;
+	textField.keyboardType = UIKeyboardTypeDefault;
+	textField.returnKeyType = UIReturnKeyDefault;
+	textField.secureTextEntry = NO;	
+	
+	textField.hidden = YES;
+	keyboardVisible = NO;
+	/* add the UITextField (hidden) to our view */
+	[self addSubview: textField];
+	
+	/* create our SDL_Keyboard */
+	SDL_Keyboard keyboard;
+	SDL_zero(keyboard);
+	SDL_AddKeyboard(&keyboard, 0);
+	SDLKey keymap[SDL_NUM_SCANCODES];
+	SDL_GetDefaultKeymap(keymap);
+	SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
+	
+}
+
+/* reveal onscreen virtual keyboard */
+- (void)showKeyboard {
+	keyboardVisible = YES;
+	[textField becomeFirstResponder];
+}
+
+/* hide onscreen virtual keyboard */
+- (void)hideKeyboard {
+	keyboardVisible = NO;
+	[textField resignFirstResponder];
+}
+
+/* UITextFieldDelegate method.  Invoked when user types something. */
+- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
+	
+	if ([string length] == 0) {
+		/* it wants to replace text with nothing, ie a delete */
+		SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DELETE);
+		SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DELETE);
+	}
+	else {
+		/* go through all the characters in the string we've been sent
+		   and convert them to key presses */
+		int i;
+		for (i=0; i<[string length]; i++) {
+			
+			unichar c = [string characterAtIndex: i];
+			
+			Uint16 mod = 0;
+			SDL_scancode code;
+			
+			if (c < 127) {
+				/* figure out the SDL_scancode and SDL_keymod for this unichar */
+				code = unicharToUIKeyInfoTable[c].code;
+				mod  = unicharToUIKeyInfoTable[c].mod;
+			}
+			else {
+				/* we only deal with ASCII right now */
+				code = SDL_SCANCODE_UNKNOWN;
+				mod = 0;
+			}
+			
+			if (mod & KMOD_SHIFT) {
+				/* If character uses shift, press shift down */
+				SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT);
+			}
+			/* send a keydown and keyup even for the character */
+			SDL_SendKeyboardKey( 0, SDL_PRESSED, code);
+			SDL_SendKeyboardKey( 0, SDL_RELEASED, code);
+			if (mod & KMOD_SHIFT) {
+				/* If character uses shift, press shift back up */
+				SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT);
+			}			
+		}
+	}
+	return NO; /* don't allow the edit! (keep placeholder text there) */
+}
+
+/* Terminates the editing session */
+- (BOOL)textFieldShouldReturn:(UITextField*)_textField {
+	[self hideKeyboard];
+	return YES;
+}
+
+#endif
+
+@end
+
+/* iPhone keyboard addition functions */
+#if SDL_IPHONE_KEYBOARD
+
+int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
+	
+	SDL_Window *window = SDL_GetWindowFromID(windowID);
+	SDL_WindowData *data;
+	SDL_uikitview *view;
+	
+	if (NULL == window) {
+		SDL_SetError("Window does not exist");
+		return -1;
+	}
+	
+	data = (SDL_WindowData *)window->driverdata;
+	view = data->view;
+	
+	if (nil == view) {
+		SDL_SetError("Window has no view");
+		return -1;
+	}
+	else {
+		[view showKeyboard];
+		return 0;
+	}
+}
+
+int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
+	
+	SDL_Window *window = SDL_GetWindowFromID(windowID);
+	SDL_WindowData *data;
+	SDL_uikitview *view;
+	
+	if (NULL == window) {
+		SDL_SetError("Window does not exist");
+		return -1;
+	}	
+	
+	data = (SDL_WindowData *)window->driverdata;
+	view = data->view;
+	
+	if (NULL == view) {
+		SDL_SetError("Window has no view");
+		return -1;
+	}
+	else {
+		[view hideKeyboard];
+		return 0;
+	}
+}
+
+SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
+	
+	SDL_Window *window = SDL_GetWindowFromID(windowID);
+	SDL_WindowData *data;
+	SDL_uikitview *view;
+	
+	if (NULL == window) {
+		SDL_SetError("Window does not exist");
+		return -1;
+	}	
+	
+	data = (SDL_WindowData *)window->driverdata;
+	view = data->view;
+	
+	if (NULL == view) {
+		SDL_SetError("Window has no view");
+		return 0;
+	}
+	else {
+		return view.keyboardVisible;
+	}
+}
+
+int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
+	
+	SDL_Window *window = SDL_GetWindowFromID(windowID);
+	SDL_WindowData *data;
+	SDL_uikitview *view;
+	
+	if (NULL == window) {
+		SDL_SetError("Window does not exist");
+		return -1;
+	}	
+	
+	data = (SDL_WindowData *)window->driverdata;
+	view = data->view;
+	
+	if (NULL == view) {
+		SDL_SetError("Window has no view");
+		return -1;
+	}
+	else {
+		if (SDL_iPhoneKeyboardIsShown(windowID)) {
+			SDL_iPhoneKeyboardHide(windowID);
+		}
+		else {
+			SDL_iPhoneKeyboardShow(windowID);
+		}
+		return 0;
+	}
+}
+
+#else
+
+/* stubs, used if compiled without keyboard support */
+
+int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
+	SDL_SetError("Not compiled with keyboard support");
+	return -1;
+}
+
+int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
+	SDL_SetError("Not compiled with keyboard support");
+	return -1;
+}
+
+SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
+	return 0;
+}
+
+int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
+	SDL_SetError("Not compiled with keyboard support");
+	return -1;
+}
+
+
+#endif /* SDL_IPHONE_KEYBOARD */
\ No newline at end of file