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