src/video/uikit/SDL_uikitview.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 07 Nov 2011 02:24:52 -0500
changeset 6054 effedf4d675c
parent 6044 35448a5ea044
child 6079 d7135957b216
permissions -rw-r--r--
Need to send a key up, silly.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #import "SDL_uikitview.h"
    26 
    27 #include "../../events/SDL_keyboard_c.h"
    28 #include "../../events/SDL_mouse_c.h"
    29 #include "../../events/SDL_touch_c.h"
    30 
    31 #if SDL_IPHONE_KEYBOARD
    32 #import "keyinfotable.h"
    33 #import "SDL_uikitappdelegate.h"
    34 #import "SDL_uikitkeyboard.h"
    35 #import "SDL_uikitwindow.h"
    36 #endif
    37 
    38 @implementation SDL_uikitview
    39 
    40 - (void)dealloc
    41 {
    42     [super dealloc];
    43 }
    44 
    45 - (id)initWithFrame:(CGRect)frame
    46 {
    47     self = [super initWithFrame: frame];
    48 
    49 #if SDL_IPHONE_KEYBOARD
    50     [self initializeKeyboard];
    51 #endif
    52 
    53 #ifdef FIXED_MULTITOUCH
    54     self.multipleTouchEnabled = YES;
    55 
    56     SDL_Touch touch;
    57     touch.id = 0; //TODO: Should be -1?
    58 
    59     //touch.driverdata = SDL_malloc(sizeof(EventTouchData));
    60     //EventTouchData* data = (EventTouchData*)(touch.driverdata);
    61 
    62     touch.x_min = 0;
    63     touch.x_max = frame.size.width;
    64     touch.native_xres = touch.x_max - touch.x_min;
    65     touch.y_min = 0;
    66     touch.y_max = frame.size.height;
    67     touch.native_yres = touch.y_max - touch.y_min;
    68     touch.pressure_min = 0;
    69     touch.pressure_max = 1;
    70     touch.native_pressureres = touch.pressure_max - touch.pressure_min;
    71 
    72 
    73     touchId = SDL_AddTouch(&touch, "IPHONE SCREEN");
    74 #endif
    75 
    76     return self;
    77 
    78 }
    79 
    80 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    81 {
    82     NSEnumerator *enumerator = [touches objectEnumerator];
    83     UITouch *touch = (UITouch*)[enumerator nextObject];
    84 
    85     if (touch) {
    86         CGPoint locationInView = [touch locationInView: self];
    87 
    88         /* send moved event */
    89         SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
    90 
    91         /* send mouse down event */
    92         SDL_SendMouseButton(NULL, SDL_PRESSED, SDL_BUTTON_LEFT);
    93     }
    94 
    95 #ifdef FIXED_MULTITOUCH
    96     while(touch) {
    97         CGPoint locationInView = [touch locationInView: self];
    98 
    99 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   100         //FIXME: TODO: Using touch as the fingerId is potentially dangerous
   101         //It is also much more efficient than storing the UITouch pointer
   102         //and comparing it to the incoming event.
   103         SDL_SendFingerDown(touchId, (long)touch,
   104                            SDL_TRUE, locationInView.x, locationInView.y,
   105                            1);
   106 #else
   107         int i;
   108         for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
   109             if (finger[i] == NULL) {
   110                 finger[i] = touch;
   111                 SDL_SendFingerDown(touchId, i,
   112                                    SDL_TRUE, locationInView.x, locationInView.y,
   113                                    1);
   114                 break;
   115             }
   116         }
   117 #endif
   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 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   139         SDL_SendFingerDown(touchId, (long)touch,
   140                            SDL_FALSE, locationInView.x, locationInView.y,
   141                            1);
   142 #else
   143         int i;
   144         for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
   145             if (finger[i] == touch) {
   146                 SDL_SendFingerDown(touchId, i,
   147                                    SDL_FALSE, locationInView.x, locationInView.y,
   148                                    1);
   149                 finger[i] = NULL;
   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     /*
   163         this can happen if the user puts more than 5 touches on the screen
   164         at once, or perhaps in other circumstances.  Usually (it seems)
   165         all active touches are canceled.
   166     */
   167     [self touchesEnded: touches withEvent: event];
   168 }
   169 
   170 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
   171 {
   172     NSEnumerator *enumerator = [touches objectEnumerator];
   173     UITouch *touch = (UITouch*)[enumerator nextObject];
   174 
   175     if (touch) {
   176         CGPoint locationInView = [touch locationInView: self];
   177 
   178         /* send moved event */
   179         SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
   180     }
   181 
   182 #ifdef FIXED_MULTITOUCH
   183     while(touch) {
   184         CGPoint locationInView = [touch locationInView: self];
   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 {
   215     return keyboardVisible;
   216 }
   217 
   218 /* Set ourselves up as a UITextFieldDelegate */
   219 - (void)initializeKeyboard
   220 {
   221     textField = [[UITextField alloc] initWithFrame: CGRectZero];
   222     textField.delegate = self;
   223     /* placeholder so there is something to delete! */
   224     textField.text = @" ";
   225 
   226     /* set UITextInputTrait properties, mostly to defaults */
   227     textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
   228     textField.autocorrectionType = UITextAutocorrectionTypeNo;
   229     textField.enablesReturnKeyAutomatically = NO;
   230     textField.keyboardAppearance = UIKeyboardAppearanceDefault;
   231     textField.keyboardType = UIKeyboardTypeDefault;
   232     textField.returnKeyType = UIReturnKeyDefault;
   233     textField.secureTextEntry = NO;
   234 
   235     textField.hidden = YES;
   236     keyboardVisible = NO;
   237     /* add the UITextField (hidden) to our view */
   238     [self addSubview: textField];
   239     [textField release];
   240 }
   241 
   242 /* reveal onscreen virtual keyboard */
   243 - (void)showKeyboard
   244 {
   245     keyboardVisible = YES;
   246     [textField becomeFirstResponder];
   247 }
   248 
   249 /* hide onscreen virtual keyboard */
   250 - (void)hideKeyboard
   251 {
   252     keyboardVisible = NO;
   253     [textField resignFirstResponder];
   254 }
   255 
   256 /* UITextFieldDelegate method.  Invoked when user types something. */
   257 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
   258 {
   259     if ([string length] == 0) {
   260         /* it wants to replace text with nothing, ie a delete */
   261         SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
   262         SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
   263     }
   264     else {
   265         /* go through all the characters in the string we've been sent
   266            and convert them to key presses */
   267         int i;
   268         for (i = 0; i < [string length]; i++) {
   269 
   270             unichar c = [string characterAtIndex: i];
   271 
   272             Uint16 mod = 0;
   273             SDL_Scancode code;
   274 
   275             if (c < 127) {
   276                 /* figure out the SDL_Scancode and SDL_keymod for this unichar */
   277                 code = unicharToUIKeyInfoTable[c].code;
   278                 mod  = unicharToUIKeyInfoTable[c].mod;
   279             }
   280             else {
   281                 /* we only deal with ASCII right now */
   282                 code = SDL_SCANCODE_UNKNOWN;
   283                 mod = 0;
   284             }
   285 
   286             if (mod & KMOD_SHIFT) {
   287                 /* If character uses shift, press shift down */
   288                 SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
   289             }
   290             /* send a keydown and keyup even for the character */
   291             SDL_SendKeyboardKey(SDL_PRESSED, code);
   292             SDL_SendKeyboardKey(SDL_RELEASED, code);
   293             if (mod & KMOD_SHIFT) {
   294                 /* If character uses shift, press shift back up */
   295                 SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
   296             }
   297         }
   298         SDL_SendKeyboardText([string UTF8String]);
   299     }
   300     return NO; /* don't allow the edit! (keep placeholder text there) */
   301 }
   302 
   303 /* Terminates the editing session */
   304 - (BOOL)textFieldShouldReturn:(UITextField*)_textField
   305 {
   306     SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
   307     SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
   308     [self hideKeyboard];
   309     return YES;
   310 }
   311 
   312 #endif
   313 
   314 @end
   315 
   316 /* iPhone keyboard addition functions */
   317 #if SDL_IPHONE_KEYBOARD
   318 
   319 static SDL_uikitview * getWindowView(SDL_Window * window)
   320 {
   321     if (window == NULL) {
   322         SDL_SetError("Window does not exist");
   323         return nil;
   324     }
   325 
   326     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
   327     SDL_uikitview *view = data != NULL ? data->view : nil;
   328 
   329     if (view == nil) {
   330         SDL_SetError("Window has no view");
   331     }
   332 
   333     return view;
   334 }
   335 
   336 int SDL_iPhoneKeyboardShow(SDL_Window * window)
   337 {
   338     SDL_uikitview *view = getWindowView(window);
   339     if (view == nil) {
   340         return -1;
   341     }
   342 
   343     [view showKeyboard];
   344     return 0;
   345 }
   346 
   347 int SDL_iPhoneKeyboardHide(SDL_Window * window)
   348 {
   349     SDL_uikitview *view = getWindowView(window);
   350     if (view == nil) {
   351         return -1;
   352     }
   353 
   354     [view hideKeyboard];
   355     return 0;
   356 }
   357 
   358 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window)
   359 {
   360     SDL_uikitview *view = getWindowView(window);
   361     if (view == nil) {
   362         return 0;
   363     }
   364 
   365     return view.keyboardVisible;
   366 }
   367 
   368 int SDL_iPhoneKeyboardToggle(SDL_Window * window)
   369 {
   370     SDL_uikitview *view = getWindowView(window);
   371     if (view == nil) {
   372         return -1;
   373     }
   374 
   375     if (SDL_iPhoneKeyboardIsShown(window)) {
   376         SDL_iPhoneKeyboardHide(window);
   377     }
   378     else {
   379         SDL_iPhoneKeyboardShow(window);
   380     }
   381     return 0;
   382 }
   383 
   384 #else
   385 
   386 /* stubs, used if compiled without keyboard support */
   387 
   388 int SDL_iPhoneKeyboardShow(SDL_Window * window)
   389 {
   390     SDL_SetError("Not compiled with keyboard support");
   391     return -1;
   392 }
   393 
   394 int SDL_iPhoneKeyboardHide(SDL_Window * window)
   395 {
   396     SDL_SetError("Not compiled with keyboard support");
   397     return -1;
   398 }
   399 
   400 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window)
   401 {
   402     return 0;
   403 }
   404 
   405 int SDL_iPhoneKeyboardToggle(SDL_Window * window)
   406 {
   407     SDL_SetError("Not compiled with keyboard support");
   408     return -1;
   409 }
   410 
   411 #endif /* SDL_IPHONE_KEYBOARD */
   412 
   413 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   414 
   415 /* vi: set ts=4 sw=4 expandtab: */