src/video/uikit/SDL_uikitview.m
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9861 2117766ff8d2
child 10340 5724f5087acd
permissions -rw-r--r--
Updated copyright to 2016
     1  /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 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_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #include "SDL_uikitview.h"
    26 
    27 #include "../../events/SDL_mouse_c.h"
    28 #include "../../events/SDL_touch_c.h"
    29 #include "../../events/SDL_events_c.h"
    30 
    31 #import "SDL_uikitappdelegate.h"
    32 #import "SDL_uikitmodes.h"
    33 #import "SDL_uikitwindow.h"
    34 
    35 @implementation SDL_uikitview {
    36     SDL_Window *sdlwindow;
    37 
    38     SDL_TouchID touchId;
    39     UITouch * __weak firstFingerDown;
    40 }
    41 
    42 - (instancetype)initWithFrame:(CGRect)frame
    43 {
    44     if ((self = [super initWithFrame:frame])) {
    45         self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    46         self.autoresizesSubviews = YES;
    47 
    48         self.multipleTouchEnabled = YES;
    49 
    50         touchId = 1;
    51         SDL_AddTouch(touchId, "");
    52     }
    53 
    54     return self;
    55 }
    56 
    57 - (void)setSDLWindow:(SDL_Window *)window
    58 {
    59     SDL_WindowData *data = nil;
    60 
    61     if (window == sdlwindow) {
    62         return;
    63     }
    64 
    65     /* Remove ourself from the old window. */
    66     if (sdlwindow) {
    67         SDL_uikitview *view = nil;
    68         data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
    69 
    70         [data.views removeObject:self];
    71 
    72         [self removeFromSuperview];
    73 
    74         /* Restore the next-oldest view in the old window. */
    75         view = data.views.lastObject;
    76 
    77         data.viewcontroller.view = view;
    78 
    79         data.uiwindow.rootViewController = nil;
    80         data.uiwindow.rootViewController = data.viewcontroller;
    81 
    82         [data.uiwindow layoutIfNeeded];
    83     }
    84 
    85     /* Add ourself to the new window. */
    86     if (window) {
    87         data = (__bridge SDL_WindowData *) window->driverdata;
    88 
    89         /* Make sure the SDL window has a strong reference to this view. */
    90         [data.views addObject:self];
    91 
    92         /* Replace the view controller's old view with this one. */
    93         [data.viewcontroller.view removeFromSuperview];
    94         data.viewcontroller.view = self;
    95 
    96         /* The root view controller handles rotation and the status bar.
    97          * Assigning it also adds the controller's view to the window. We
    98          * explicitly re-set it to make sure the view is properly attached to
    99          * the window. Just adding the sub-view if the root view controller is
   100          * already correct causes orientation issues on iOS 7 and below. */
   101         data.uiwindow.rootViewController = nil;
   102         data.uiwindow.rootViewController = data.viewcontroller;
   103 
   104         /* The view's bounds may not be correct until the next event cycle. That
   105          * might happen after the current dimensions are queried, so we force a
   106          * layout now to immediately update the bounds. */
   107         [data.uiwindow layoutIfNeeded];
   108     }
   109 
   110     sdlwindow = window;
   111 }
   112 
   113 - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
   114 {
   115     CGPoint point = [touch locationInView:self];
   116 
   117     if (normalize) {
   118         CGRect bounds = self.bounds;
   119         point.x /= bounds.size.width;
   120         point.y /= bounds.size.height;
   121     }
   122 
   123     return point;
   124 }
   125 
   126 - (float)pressureForTouch:(UITouch *)touch
   127 {
   128 #ifdef __IPHONE_9_0
   129     if ([touch respondsToSelector:@selector(force)]) {
   130         return (float) touch.force;
   131     }
   132 #endif
   133 
   134     return 1.0f;
   135 }
   136 
   137 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
   138 {
   139     for (UITouch *touch in touches) {
   140         float pressure = [self pressureForTouch:touch];
   141 
   142         if (!firstFingerDown) {
   143             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
   144 
   145             /* send mouse moved event */
   146             SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
   147 
   148             /* send mouse down event */
   149             SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
   150 
   151             firstFingerDown = touch;
   152         }
   153 
   154         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
   155         SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
   156                       SDL_TRUE, locationInView.x, locationInView.y, pressure);
   157     }
   158 }
   159 
   160 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
   161 {
   162     for (UITouch *touch in touches) {
   163         float pressure = [self pressureForTouch:touch];
   164 
   165         if (touch == firstFingerDown) {
   166             /* send mouse up */
   167             SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
   168             firstFingerDown = nil;
   169         }
   170 
   171         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
   172         SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
   173                       SDL_FALSE, locationInView.x, locationInView.y, pressure);
   174     }
   175 }
   176 
   177 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
   178 {
   179     [self touchesEnded:touches withEvent:event];
   180 }
   181 
   182 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
   183 {
   184     for (UITouch *touch in touches) {
   185         float pressure = [self pressureForTouch:touch];
   186 
   187         if (touch == firstFingerDown) {
   188             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
   189 
   190             /* send moved event */
   191             SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
   192         }
   193 
   194         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
   195         SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
   196                             locationInView.x, locationInView.y, pressure);
   197     }
   198 }
   199 
   200 @end
   201 
   202 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   203 
   204 /* vi: set ts=4 sw=4 expandtab: */