src/video/uikit/SDL_uikitview.m
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 6079 d7135957b216
child 6342 ac83b73f0edd
permissions -rwxr-xr-x
Happy New Year!
     1  /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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 = 1;
    64     touch.native_xres = touch.x_max - touch.x_min;
    65     touch.y_min = 0;
    66     touch.y_max = 1;
    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 - (CGPoint)touchLocation:(UITouch *)touch
    81 {
    82     CGPoint point = [touch locationInView: self];
    83     CGRect frame = [self frame];
    84 
    85     frame = CGRectApplyAffineTransform(frame, [self transform]);
    86     point.x /= frame.size.width;
    87     point.y /= frame.size.height;
    88     return point;
    89 }
    90 
    91 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    92 {
    93     NSEnumerator *enumerator = [touches objectEnumerator];
    94     UITouch *touch = (UITouch*)[enumerator nextObject];
    95 
    96     if (touch) {
    97         CGPoint locationInView = [touch locationInView: self];
    98 
    99         /* send moved event */
   100         SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
   101 
   102         /* send mouse down event */
   103         SDL_SendMouseButton(NULL, SDL_PRESSED, SDL_BUTTON_LEFT);
   104     }
   105 
   106 #ifdef FIXED_MULTITOUCH
   107     while(touch) {
   108         CGPoint locationInView = [self touchLocation:touch];
   109 
   110 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   111         //FIXME: TODO: Using touch as the fingerId is potentially dangerous
   112         //It is also much more efficient than storing the UITouch pointer
   113         //and comparing it to the incoming event.
   114         SDL_SendFingerDown(touchId, (long)touch,
   115                            SDL_TRUE, locationInView.x, locationInView.y,
   116                            1);
   117 #else
   118         int i;
   119         for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
   120             if (finger[i] == NULL) {
   121                 finger[i] = touch;
   122                 SDL_SendFingerDown(touchId, i,
   123                                    SDL_TRUE, locationInView.x, locationInView.y,
   124                                    1);
   125                 break;
   126             }
   127         }
   128 #endif
   129 
   130         touch = (UITouch*)[enumerator nextObject];
   131     }
   132 #endif
   133 }
   134 
   135 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
   136 {
   137     NSEnumerator *enumerator = [touches objectEnumerator];
   138     UITouch *touch = (UITouch*)[enumerator nextObject];
   139 
   140     if (touch) {
   141         /* send mouse up */
   142         SDL_SendMouseButton(NULL, SDL_RELEASED, SDL_BUTTON_LEFT);
   143     }
   144 
   145 #ifdef FIXED_MULTITOUCH
   146     while(touch) {
   147         CGPoint locationInView = [self touchLocation:touch];
   148 
   149 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   150         SDL_SendFingerDown(touchId, (long)touch,
   151                            SDL_FALSE, locationInView.x, locationInView.y,
   152                            1);
   153 #else
   154         int i;
   155         for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
   156             if (finger[i] == touch) {
   157                 SDL_SendFingerDown(touchId, i,
   158                                    SDL_FALSE, locationInView.x, locationInView.y,
   159                                    1);
   160                 finger[i] = NULL;
   161                 break;
   162             }
   163         }
   164 #endif
   165 
   166         touch = (UITouch*)[enumerator nextObject];
   167     }
   168 #endif
   169 }
   170 
   171 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
   172 {
   173     /*
   174         this can happen if the user puts more than 5 touches on the screen
   175         at once, or perhaps in other circumstances.  Usually (it seems)
   176         all active touches are canceled.
   177     */
   178     [self touchesEnded: touches withEvent: event];
   179 }
   180 
   181 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
   182 {
   183     NSEnumerator *enumerator = [touches objectEnumerator];
   184     UITouch *touch = (UITouch*)[enumerator nextObject];
   185 
   186     if (touch) {
   187         CGPoint locationInView = [touch locationInView: self];
   188 
   189         /* send moved event */
   190         SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y);
   191     }
   192 
   193 #ifdef FIXED_MULTITOUCH
   194     while(touch) {
   195         CGPoint locationInView = [self touchLocation:touch];
   196 
   197 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
   198         SDL_SendTouchMotion(touchId, (long)touch,
   199                             SDL_FALSE, locationInView.x, locationInView.y,
   200                             1);
   201 #else
   202         int i;
   203         for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
   204             if (finger[i] == touch) {
   205                 SDL_SendTouchMotion(touchId, i,
   206                                     SDL_FALSE, locationInView.x, locationInView.y,
   207                                     1);
   208                 break;
   209             }
   210         }
   211 #endif
   212 
   213         touch = (UITouch*)[enumerator nextObject];
   214     }
   215 #endif
   216 }
   217 
   218 /*
   219     ---- Keyboard related functionality below this line ----
   220 */
   221 #if SDL_IPHONE_KEYBOARD
   222 
   223 /* Is the iPhone virtual keyboard visible onscreen? */
   224 - (BOOL)keyboardVisible
   225 {
   226     return keyboardVisible;
   227 }
   228 
   229 /* Set ourselves up as a UITextFieldDelegate */
   230 - (void)initializeKeyboard
   231 {
   232     textField = [[UITextField alloc] initWithFrame: CGRectZero];
   233     textField.delegate = self;
   234     /* placeholder so there is something to delete! */
   235     textField.text = @" ";
   236 
   237     /* set UITextInputTrait properties, mostly to defaults */
   238     textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
   239     textField.autocorrectionType = UITextAutocorrectionTypeNo;
   240     textField.enablesReturnKeyAutomatically = NO;
   241     textField.keyboardAppearance = UIKeyboardAppearanceDefault;
   242     textField.keyboardType = UIKeyboardTypeDefault;
   243     textField.returnKeyType = UIReturnKeyDefault;
   244     textField.secureTextEntry = NO;
   245 
   246     textField.hidden = YES;
   247     keyboardVisible = NO;
   248     /* add the UITextField (hidden) to our view */
   249     [self addSubview: textField];
   250     [textField release];
   251 }
   252 
   253 /* reveal onscreen virtual keyboard */
   254 - (void)showKeyboard
   255 {
   256     keyboardVisible = YES;
   257     [textField becomeFirstResponder];
   258 }
   259 
   260 /* hide onscreen virtual keyboard */
   261 - (void)hideKeyboard
   262 {
   263     keyboardVisible = NO;
   264     [textField resignFirstResponder];
   265 }
   266 
   267 /* UITextFieldDelegate method.  Invoked when user types something. */
   268 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
   269 {
   270     if ([string length] == 0) {
   271         /* it wants to replace text with nothing, ie a delete */
   272         SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
   273         SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
   274     }
   275     else {
   276         /* go through all the characters in the string we've been sent
   277            and convert them to key presses */
   278         int i;
   279         for (i = 0; i < [string length]; i++) {
   280 
   281             unichar c = [string characterAtIndex: i];
   282 
   283             Uint16 mod = 0;
   284             SDL_Scancode code;
   285 
   286             if (c < 127) {
   287                 /* figure out the SDL_Scancode and SDL_keymod for this unichar */
   288                 code = unicharToUIKeyInfoTable[c].code;
   289                 mod  = unicharToUIKeyInfoTable[c].mod;
   290             }
   291             else {
   292                 /* we only deal with ASCII right now */
   293                 code = SDL_SCANCODE_UNKNOWN;
   294                 mod = 0;
   295             }
   296 
   297             if (mod & KMOD_SHIFT) {
   298                 /* If character uses shift, press shift down */
   299                 SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
   300             }
   301             /* send a keydown and keyup even for the character */
   302             SDL_SendKeyboardKey(SDL_PRESSED, code);
   303             SDL_SendKeyboardKey(SDL_RELEASED, code);
   304             if (mod & KMOD_SHIFT) {
   305                 /* If character uses shift, press shift back up */
   306                 SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
   307             }
   308         }
   309         SDL_SendKeyboardText([string UTF8String]);
   310     }
   311     return NO; /* don't allow the edit! (keep placeholder text there) */
   312 }
   313 
   314 /* Terminates the editing session */
   315 - (BOOL)textFieldShouldReturn:(UITextField*)_textField
   316 {
   317     SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
   318     SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
   319     [self hideKeyboard];
   320     return YES;
   321 }
   322 
   323 #endif
   324 
   325 @end
   326 
   327 /* iPhone keyboard addition functions */
   328 #if SDL_IPHONE_KEYBOARD
   329 
   330 static SDL_uikitview * getWindowView(SDL_Window * window)
   331 {
   332     if (window == NULL) {
   333         SDL_SetError("Window does not exist");
   334         return nil;
   335     }
   336 
   337     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
   338     SDL_uikitview *view = data != NULL ? data->view : nil;
   339 
   340     if (view == nil) {
   341         SDL_SetError("Window has no view");
   342     }
   343 
   344     return view;
   345 }
   346 
   347 int SDL_iPhoneKeyboardShow(SDL_Window * window)
   348 {
   349     SDL_uikitview *view = getWindowView(window);
   350     if (view == nil) {
   351         return -1;
   352     }
   353 
   354     [view showKeyboard];
   355     return 0;
   356 }
   357 
   358 int SDL_iPhoneKeyboardHide(SDL_Window * window)
   359 {
   360     SDL_uikitview *view = getWindowView(window);
   361     if (view == nil) {
   362         return -1;
   363     }
   364 
   365     [view hideKeyboard];
   366     return 0;
   367 }
   368 
   369 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window)
   370 {
   371     SDL_uikitview *view = getWindowView(window);
   372     if (view == nil) {
   373         return 0;
   374     }
   375 
   376     return view.keyboardVisible;
   377 }
   378 
   379 int SDL_iPhoneKeyboardToggle(SDL_Window * window)
   380 {
   381     SDL_uikitview *view = getWindowView(window);
   382     if (view == nil) {
   383         return -1;
   384     }
   385 
   386     if (SDL_iPhoneKeyboardIsShown(window)) {
   387         SDL_iPhoneKeyboardHide(window);
   388     }
   389     else {
   390         SDL_iPhoneKeyboardShow(window);
   391     }
   392     return 0;
   393 }
   394 
   395 #else
   396 
   397 /* stubs, used if compiled without keyboard support */
   398 
   399 int SDL_iPhoneKeyboardShow(SDL_Window * window)
   400 {
   401     SDL_SetError("Not compiled with keyboard support");
   402     return -1;
   403 }
   404 
   405 int SDL_iPhoneKeyboardHide(SDL_Window * window)
   406 {
   407     SDL_SetError("Not compiled with keyboard support");
   408     return -1;
   409 }
   410 
   411 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window)
   412 {
   413     return 0;
   414 }
   415 
   416 int SDL_iPhoneKeyboardToggle(SDL_Window * window)
   417 {
   418     SDL_SetError("Not compiled with keyboard support");
   419     return -1;
   420 }
   421 
   422 #endif /* SDL_IPHONE_KEYBOARD */
   423 
   424 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   425 
   426 /* vi: set ts=4 sw=4 expandtab: */