mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 12:14:41 +02:00
Updated SDL2 to the latest Mercurial revision.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,438 +24,164 @@
|
||||
|
||||
#include "SDL_uikitview.h"
|
||||
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
#include "keyinfotable.h"
|
||||
#endif
|
||||
#include "SDL_uikitappdelegate.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#import "SDL_uikitappdelegate.h"
|
||||
#import "SDL_uikitmodes.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
|
||||
void _uikit_keyboard_init() ;
|
||||
@implementation SDL_uikitview {
|
||||
SDL_Window *sdlwindow;
|
||||
|
||||
@implementation SDL_uikitview
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
SDL_TouchID touchId;
|
||||
UITouch * __weak firstFingerDown;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame: frame];
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.autoresizesSubviews = YES;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
[self initializeKeyboard];
|
||||
#endif
|
||||
self.multipleTouchEnabled = YES;
|
||||
|
||||
self.multipleTouchEnabled = YES;
|
||||
|
||||
touchId = 1;
|
||||
SDL_AddTouch(touchId, "");
|
||||
touchId = 1;
|
||||
SDL_AddTouch(touchId, "");
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSDLWindow:(SDL_Window *)window
|
||||
{
|
||||
SDL_WindowData *data = nil;
|
||||
|
||||
if (window == sdlwindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove ourself from the old window. */
|
||||
if (sdlwindow) {
|
||||
SDL_uikitview *view = nil;
|
||||
data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
|
||||
|
||||
[data.views removeObject:self];
|
||||
|
||||
[self removeFromSuperview];
|
||||
|
||||
/* Restore the next-oldest view in the old window. */
|
||||
view = data.views.lastObject;
|
||||
|
||||
data.viewcontroller.view = view;
|
||||
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.rootViewController = data.viewcontroller;
|
||||
|
||||
[data.uiwindow layoutIfNeeded];
|
||||
}
|
||||
|
||||
/* Add ourself to the new window. */
|
||||
if (window) {
|
||||
data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
|
||||
/* Make sure the SDL window has a strong reference to this view. */
|
||||
[data.views addObject:self];
|
||||
|
||||
/* Replace the view controller's old view with this one. */
|
||||
[data.viewcontroller.view removeFromSuperview];
|
||||
data.viewcontroller.view = self;
|
||||
|
||||
/* The root view controller handles rotation and the status bar.
|
||||
* Assigning it also adds the controller's view to the window. We
|
||||
* explicitly re-set it to make sure the view is properly attached to
|
||||
* the window. Just adding the sub-view if the root view controller is
|
||||
* already correct causes orientation issues on iOS 7 and below. */
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.rootViewController = data.viewcontroller;
|
||||
|
||||
/* The view's bounds may not be correct until the next event cycle. That
|
||||
* might happen after the current dimensions are queried, so we force a
|
||||
* layout now to immediately update the bounds. */
|
||||
[data.uiwindow layoutIfNeeded];
|
||||
}
|
||||
|
||||
sdlwindow = window;
|
||||
}
|
||||
|
||||
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
|
||||
{
|
||||
CGPoint point = [touch locationInView: self];
|
||||
|
||||
/* Get the display scale and apply that to the input coordinates */
|
||||
SDL_Window *window = self->viewcontroller.window;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
CGPoint point = [touch locationInView:self];
|
||||
|
||||
if (normalize) {
|
||||
CGRect bounds = [self bounds];
|
||||
CGRect bounds = self.bounds;
|
||||
point.x /= bounds.size.width;
|
||||
point.y /= bounds.size.height;
|
||||
} else {
|
||||
point.x *= displaymodedata->scale;
|
||||
point.y *= displaymodedata->scale;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while (touch) {
|
||||
if (!leftFingerDown) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (!firstFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
/* send moved event */
|
||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
/* send mouse moved event */
|
||||
SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
|
||||
/* send mouse down event */
|
||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||
SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||
|
||||
leftFingerDown = touch;
|
||||
firstFingerDown = touch;
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
/* FIXME: TODO: Using touch as the fingerId is potentially dangerous
|
||||
* It is also much more efficient than storing the UITouch pointer
|
||||
* and comparing it to the incoming event.
|
||||
*/
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == NULL) {
|
||||
finger[i] = touch;
|
||||
SDL_SendTouch(touchId, i,
|
||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while(touch) {
|
||||
if (touch == leftFingerDown) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch == firstFingerDown) {
|
||||
/* send mouse up */
|
||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
leftFingerDown = nil;
|
||||
SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
firstFingerDown = nil;
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
SDL_SendTouch(touchId, (long)touch,
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == touch) {
|
||||
SDL_SendTouch(touchId, i,
|
||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
||||
finger[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
/*
|
||||
this can happen if the user puts more than 5 touches on the screen
|
||||
at once, or perhaps in other circumstances. Usually (it seems)
|
||||
all active touches are canceled.
|
||||
*/
|
||||
[self touchesEnded: touches withEvent: event];
|
||||
[self touchesEnded:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while (touch) {
|
||||
if (touch == leftFingerDown) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch == firstFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
/* send moved event */
|
||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
SDL_SendTouchMotion(touchId, (long)touch,
|
||||
SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
|
||||
locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == touch) {
|
||||
SDL_SendTouchMotion(touchId, i,
|
||||
locationInView.x, locationInView.y, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
---- Keyboard related functionality below this line ----
|
||||
*/
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
|
||||
@synthesize textInputRect = textInputRect;
|
||||
@synthesize keyboardHeight = keyboardHeight;
|
||||
|
||||
/* Is the iPhone virtual keyboard visible onscreen? */
|
||||
- (BOOL)keyboardVisible
|
||||
{
|
||||
return keyboardVisible;
|
||||
}
|
||||
|
||||
/* Set ourselves up as a UITextFieldDelegate */
|
||||
- (void)initializeKeyboard
|
||||
{
|
||||
textField = [[UITextField alloc] initWithFrame: CGRectZero];
|
||||
textField.delegate = self;
|
||||
/* placeholder so there is something to delete! */
|
||||
textField.text = @" ";
|
||||
|
||||
/* set UITextInputTrait properties, mostly to defaults */
|
||||
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
textField.enablesReturnKeyAutomatically = NO;
|
||||
textField.keyboardAppearance = UIKeyboardAppearanceDefault;
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
textField.returnKeyType = UIReturnKeyDefault;
|
||||
textField.secureTextEntry = NO;
|
||||
|
||||
textField.hidden = YES;
|
||||
keyboardVisible = NO;
|
||||
/* add the UITextField (hidden) to our view */
|
||||
[self addSubview: textField];
|
||||
[textField release];
|
||||
|
||||
_uikit_keyboard_init();
|
||||
}
|
||||
|
||||
/* reveal onscreen virtual keyboard */
|
||||
- (void)showKeyboard
|
||||
{
|
||||
keyboardVisible = YES;
|
||||
[textField becomeFirstResponder];
|
||||
}
|
||||
|
||||
/* hide onscreen virtual keyboard */
|
||||
- (void)hideKeyboard
|
||||
{
|
||||
keyboardVisible = NO;
|
||||
[textField resignFirstResponder];
|
||||
}
|
||||
|
||||
/* UITextFieldDelegate method. Invoked when user types something. */
|
||||
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
if ([string length] == 0) {
|
||||
/* it wants to replace text with nothing, ie a delete */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE);
|
||||
}
|
||||
else {
|
||||
/* go through all the characters in the string we've been sent
|
||||
and convert them to key presses */
|
||||
int i;
|
||||
for (i = 0; i < [string length]; i++) {
|
||||
|
||||
unichar c = [string characterAtIndex: i];
|
||||
|
||||
Uint16 mod = 0;
|
||||
SDL_Scancode code;
|
||||
|
||||
if (c < 127) {
|
||||
/* figure out the SDL_Scancode and SDL_keymod for this unichar */
|
||||
code = unicharToUIKeyInfoTable[c].code;
|
||||
mod = unicharToUIKeyInfoTable[c].mod;
|
||||
}
|
||||
else {
|
||||
/* we only deal with ASCII right now */
|
||||
code = SDL_SCANCODE_UNKNOWN;
|
||||
mod = 0;
|
||||
}
|
||||
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift down */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
/* send a keydown and keyup even for the character */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, code);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, code);
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift back up */
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
}
|
||||
SDL_SendKeyboardText([string UTF8String]);
|
||||
}
|
||||
return NO; /* don't allow the edit! (keep placeholder text there) */
|
||||
}
|
||||
|
||||
/* Terminates the editing session */
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
|
||||
{
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
|
||||
SDL_StopTextInput();
|
||||
return YES;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
/* iPhone keyboard addition functions */
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
|
||||
static SDL_uikitview * getWindowView(SDL_Window * window)
|
||||
{
|
||||
if (window == NULL) {
|
||||
SDL_SetError("Window does not exist");
|
||||
return nil;
|
||||
}
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = data != NULL ? data->view : nil;
|
||||
|
||||
if (view == nil) {
|
||||
SDL_SetError("Window has no view");
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
SDL_bool UIKit_HasScreenKeyboardSupport(_THIS)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view != nil) {
|
||||
[view showKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view != nil) {
|
||||
[view hideKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view == nil) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view.keyboardVisible;
|
||||
}
|
||||
|
||||
|
||||
void _uikit_keyboard_update() {
|
||||
SDL_Window *window = SDL_GetFocusWindow();
|
||||
if (!window) { return; }
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
if (!data) { return; }
|
||||
SDL_uikitview *view = data->view;
|
||||
if (!view) { return; }
|
||||
|
||||
SDL_Rect r = view.textInputRect;
|
||||
int height = view.keyboardHeight;
|
||||
int offsetx = 0;
|
||||
int offsety = 0;
|
||||
float scale = [UIScreen mainScreen].scale;
|
||||
if (height) {
|
||||
int sw,sh;
|
||||
SDL_GetWindowSize(window,&sw,&sh);
|
||||
int bottom = (r.y + r.h);
|
||||
int kbottom = sh - height;
|
||||
if (kbottom < bottom) {
|
||||
offsety = kbottom-bottom;
|
||||
}
|
||||
}
|
||||
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (ui_orient == UIInterfaceOrientationLandscapeLeft) {
|
||||
int tmp = offsetx; offsetx = offsety; offsety = tmp;
|
||||
}
|
||||
if (ui_orient == UIInterfaceOrientationLandscapeRight) {
|
||||
offsety = -offsety;
|
||||
int tmp = offsetx; offsetx = offsety; offsety = tmp;
|
||||
}
|
||||
if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) {
|
||||
offsety = -offsety;
|
||||
}
|
||||
|
||||
offsetx /= scale;
|
||||
offsety /= scale;
|
||||
|
||||
view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
|
||||
}
|
||||
|
||||
void _uikit_keyboard_set_height(int height) {
|
||||
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
|
||||
if (view == nil) {
|
||||
return ;
|
||||
}
|
||||
|
||||
view.keyboardHeight = height;
|
||||
_uikit_keyboard_update();
|
||||
}
|
||||
|
||||
void _uikit_keyboard_init() {
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
NSOperationQueue *queue = [NSOperationQueue mainQueue];
|
||||
[center addObserverForName:UIKeyboardWillShowNotification
|
||||
object:nil
|
||||
queue:queue
|
||||
usingBlock:^(NSNotification *notification) {
|
||||
int height = 0;
|
||||
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
|
||||
height = keyboardSize.height;
|
||||
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
|
||||
height = keyboardSize.width;
|
||||
}
|
||||
height *= [UIScreen mainScreen].scale;
|
||||
_uikit_keyboard_set_height(height);
|
||||
}
|
||||
];
|
||||
[center addObserverForName:UIKeyboardDidHideNotification
|
||||
object:nil
|
||||
queue:queue
|
||||
usingBlock:^(NSNotification *notification) {
|
||||
_uikit_keyboard_set_height(0);
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
|
||||
{
|
||||
if (!rect) {
|
||||
SDL_InvalidParamError("rect");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
|
||||
if (view == nil) {
|
||||
return ;
|
||||
}
|
||||
|
||||
view.textInputRect = *rect;
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_IPHONE_KEYBOARD */
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
Reference in New Issue
Block a user