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