Mercurial > sdl-ios-xcode
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 */ |