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