2 Simple DirectMedia Layer
3 Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_UIKIT
25 #include "SDL_uikitview.h"
27 #include "../../events/SDL_mouse_c.h"
28 #include "../../events/SDL_touch_c.h"
29 #include "../../events/SDL_events_c.h"
31 #import "SDL_uikitappdelegate.h"
32 #import "SDL_uikitmodes.h"
33 #import "SDL_uikitwindow.h"
35 @implementation SDL_uikitview {
36 SDL_Window *sdlwindow;
39 UITouch * __weak firstFingerDown;
42 - (instancetype)initWithFrame:(CGRect)frame
44 if ((self = [super initWithFrame:frame])) {
45 self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
46 self.autoresizesSubviews = YES;
48 self.multipleTouchEnabled = YES;
51 SDL_AddTouch(touchId, "");
57 - (void)setSDLWindow:(SDL_Window *)window
59 SDL_WindowData *data = nil;
61 if (window == sdlwindow) {
66 SDL_uikitview *view = nil;
67 data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
69 [data.views removeObject:self];
71 [self removeFromSuperview];
73 /* Restore the next-oldest view in the old window. */
74 if (data.views.count > 0) {
75 view = data.views[data.views.count - 1];
78 data.viewcontroller.view = view;
80 data.uiwindow.rootViewController = nil;
81 data.uiwindow.rootViewController = data.viewcontroller;
83 [data.uiwindow layoutIfNeeded];
87 data = (__bridge SDL_WindowData *) window->driverdata;
89 /* Make sure the SDL window has a strong reference to this view. */
90 [data.views addObject:self];
92 /* Replace the view controller's old view with this one. */
93 [data.viewcontroller.view removeFromSuperview];
94 data.viewcontroller.view = self;
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;
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];
113 - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
115 CGPoint point = [touch locationInView:self];
118 CGRect bounds = self.bounds;
119 point.x /= bounds.size.width;
120 point.y /= bounds.size.height;
126 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
128 for (UITouch *touch in touches) {
129 if (!firstFingerDown) {
130 CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
132 /* send mouse moved event */
133 SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
135 /* send mouse down event */
136 SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
138 firstFingerDown = touch;
141 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
142 SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
143 SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
147 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
149 for (UITouch *touch in touches) {
150 if (touch == firstFingerDown) {
152 SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
153 firstFingerDown = nil;
156 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
157 SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
158 SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
162 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
164 [self touchesEnded:touches withEvent:event];
167 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
169 for (UITouch *touch in touches) {
170 if (touch == firstFingerDown) {
171 CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
173 /* send moved event */
174 SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
177 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
178 SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
179 locationInView.x, locationInView.y, 1.0f);
185 #endif /* SDL_VIDEO_DRIVER_UIKIT */
187 /* vi: set ts=4 sw=4 expandtab: */