Implemented soft keyboard support, and added a workarond for engines that can't handle mouse-down and mouse-up events coming in two subsequent calls to pollEvent()

svn-id: r29557
This commit is contained in:
Oystein Eftevaag 2007-11-18 17:58:53 +00:00
parent 6471eb84f2
commit 6a4ce78789
8 changed files with 266 additions and 36 deletions

View File

@ -29,7 +29,8 @@ enum InputEvent {
kInputMouseUp,
kInputMouseDragged,
kInputMouseSecondToggled,
kInputOrientationChanged
kInputOrientationChanged,
kInputKeyPressed
};
// We need this to be able to call functions from/in Objective-C.

View File

@ -0,0 +1,51 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#import <UIKit/UIKit.h>
#import <UIKit/UITextView.h>
@protocol KeyboardInputProtocol
- (void)handleKeyPress:(unichar)c;
@end
@interface SoftKeyboard : UIKeyboard<KeyboardInputProtocol> {
id inputDelegate;
UITextView* inputView;
}
- (id)initWithFrame:(CGRect)frame;
- (UITextView*)inputView;
- (void)setInputDelegate:(id)delegate;
- (void)handleKeyPress:(unichar)c;
@end
@interface TextInputHandler : UITextView {
SoftKeyboard* softKeyboard;
}
- (id)initWithKeyboard:(SoftKeyboard*)keyboard;
@end

View File

@ -0,0 +1,88 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#import "iphone_keyboard.h"
// Override settings of the default keyboard implementation
@implementation UIKeyboardImpl (DisableFeatures)
- (BOOL)autoCapitalizationPreference {
return false;
}
- (BOOL)autoCorrectionPreference {
return false;
}
@end
@implementation TextInputHandler
- (id)initWithKeyboard:(SoftKeyboard*)keyboard; {
self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
softKeyboard = keyboard;
return self;
}
- (BOOL)webView:(id)fp8 shouldDeleteDOMRange:(id)fp12 {
[softKeyboard handleKeyPress:0x08];
}
- (BOOL)webView:(id)fp8 shouldInsertText:(id)character
replacingDOMRange:(id)fp16
givenAction:(int)fp20 {
if ([character length] != 1) {
[NSException raise:@"Unsupported" format:@"Unhandled multi-char insert!"];
return false;
}
[softKeyboard handleKeyPress:[character characterAtIndex:0]];
}
@end
@implementation SoftKeyboard
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
inputDelegate = nil;
inputView = [[TextInputHandler alloc] initWithKeyboard:self];
return self;
}
- (UITextView*)inputView {
return inputView;
}
- (void)setInputDelegate:(id)delegate {
inputDelegate = delegate;
}
- (void)handleKeyPress:(unichar)c {
[inputDelegate handleKeyPress:c];
}
@end

View File

@ -33,13 +33,14 @@
#import <CoreSurface/CoreSurface.h>
#import <LayerKit/LKLayer.h>
#import "iphone_keyboard.h"
@interface iPhoneView : UIView
{
CoreSurfaceBufferRef _screenSurface;
NSMutableArray* _events;
NSLock* _lock;
UIKeyboardImpl* _keyboard;
SoftKeyboard* _keyboardView;
LKLayer* _screenLayer;
int _fullWidth;
@ -64,4 +65,6 @@
@end
#endif /* _IPHONE_VIDEO__H */

View File

@ -32,6 +32,7 @@
#import <Foundation/Foundation.h>
#import <CoreSurface/CoreSurface.h>
#import <LayerKit/LKLayer.h>
#import <UIKit/UIKeyboardLayoutQWERTY.h>
static iPhoneView *sharedInstance = nil;
static int _width = 0;
@ -108,15 +109,17 @@ bool getLocalMouseCoords(CGPoint *point) {
_screenLayer = nil;
sharedInstance = self;
_keyboard = [UIKeyboardImpl sharedInstance];
//[self addSubview:_keyboard];
_keyboardView = nil;
return self;
}
-(void) dealloc {
[super dealloc];
if (_keyboardView != nil) {
[_keyboardView dealloc];
}
}
- (CoreSurfaceBufferRef)getSurface {
@ -169,6 +172,11 @@ bool getLocalMouseCoords(CGPoint *point) {
LKLayer* screenLayer = [[LKLayer layer] retain];
if (_keyboardView != nil) {
[_keyboardView removeFromSuperview];
[[_keyboardView inputView] removeFromSuperview];
}
if (_landscape) {
float ratioDifference = ((float)_width / (float)_height) / ((float)_fullWidth / (float)_fullHeight);
int rectWidth, rectHeight;
@ -187,10 +195,20 @@ bool getLocalMouseCoords(CGPoint *point) {
//printf("Rect: %i, %i, %i, %i\n", _widthOffset, _heightOffset, rectWidth + _widthOffset, rectHeight + _heightOffset);
_screenRect = CGRectMake(_widthOffset, _heightOffset, rectWidth + _widthOffset, rectHeight + _heightOffset);
[screenLayer setFrame: _screenRect];
} else {
} else {
float ratio = (float)_height / (float)_width;
_screenRect = CGRectMake(0, 0, _fullWidth, _fullWidth * ratio);
[screenLayer setFrame: _screenRect];
[screenLayer setFrame: _screenRect];
CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight);
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
[_keyboardView setInputDelegate:self];
}
[self addSubview:[_keyboardView inputView]];
[self addSubview: _keyboardView];
[[_keyboardView inputView] becomeFirstResponder];
}
[screenLayer setContents: _screenSurface];
@ -306,20 +324,24 @@ bool getLocalMouseCoords(CGPoint *point) {
}
- (void)mouseEntered:(GSEvent*)event {
//printf("mouseEntered()\n");
printf("mouseEntered()\n");
// struct CGPoint point = GSEventGetLocationInWindow(event);
//
// if (!getLocalMouseCoords(&point))
// return;
//
// [self addEvent:
// [[NSDictionary alloc] initWithObjectsAndKeys:
// [NSNumber numberWithInt:kInputMouseSecondStartDrag], @"type",
// [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x",
// [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y",
// [NSNumber numberWithInt:kInputMouseSecondToggled], @"type",
// [NSNumber numberWithFloat:point.x], @"x",
// [NSNumber numberWithFloat:point.y], @"y",
// nil
// ]
// ];
}
- (void)mouseExited:(GSEvent*)event {
//printf("mouseExited().\n");
printf("mouseExited().\n");
// [self addEvent:
// [[NSDictionary alloc] initWithObjectsAndKeys:
// @"mouseExited", @"type",
@ -330,12 +352,12 @@ bool getLocalMouseCoords(CGPoint *point) {
- (void)mouseMoved:(GSEvent*)event
{
//printf("mouseMoved()\n");
printf("mouseMoved()\n");
struct CGPoint point = GSEventGetLocationInWindow(event);
if (!getLocalMouseCoords(&point))
return;
[self addEvent:
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:kInputMouseSecondToggled], @"type",
@ -346,23 +368,12 @@ bool getLocalMouseCoords(CGPoint *point) {
];
}
- (void)keyDown:(GSEvent*)event
{
printf("keyDown()\n");
- (void)handleKeyPress:(unichar)c {
[self addEvent:
[[NSDictionary alloc] initWithObjectsAndKeys:
@"keyDown", @"type",
nil
]
];
}
- (void)keyUp:(GSEvent*)event
{
printf("keyUp()\n");
[self addEvent:
[[NSDictionary alloc] initWithObjectsAndKeys:
@"keyUp", @"type",
[NSNumber numberWithInt:kInputKeyPressed], @"type",
[NSNumber numberWithFloat:(float)c], @"x",
[NSNumber numberWithFloat:0], @"y",
nil
]
];

View File

@ -3,7 +3,8 @@ MODULE := backends/platform/iphone
MODULE_OBJS := \
osys_iphone.o \
iphone_main.o \
iphone_video.o
iphone_video.o \
iphone_keyboard.o
MODULE_DIRS += \
backends/platform/iphone/

View File

@ -59,7 +59,8 @@ OSystem_IPHONE::OSystem_IPHONE() :
_savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL),
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
_secondaryTapped(false), _lastSecondaryTap(0), _landscapeMode(true)
_secondaryTapped(false), _lastSecondaryTap(0), _landscapeMode(true),
_needEventRestPeriod(false)
{
_queuedInputEvent.type = (Common::EventType)0;
}
@ -495,6 +496,13 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
_timerCallbackNext = curTime + _timerCallbackTimer;
}
if (_needEventRestPeriod) {
// Workaround: Some engines can't handle mouse-down and mouse-up events
// appearing right after each other, without a call returning no input in between.
_needEventRestPeriod = false;
return false;
}
if (_queuedInputEvent.type != (Common::EventType)0) {
event = _queuedInputEvent;
_queuedInputEvent.type = (Common::EventType)0;
@ -535,7 +543,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastMouseTap = curTime;
_needEventRestPeriod = true;
// if (curTime - _lastMouseTap < 250 && !_overlayVisible) {
// event.type = Common::EVENT_KEYDOWN;
// _queuedInputEvent.type = Common::EVENT_KEYUP;
@ -578,7 +587,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = 27;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
_needEventRestPeriod = true;
} else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
// Swipe up
event.type = Common::EVENT_KEYDOWN;
@ -587,6 +597,7 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_1;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = '1';
_needEventRestPeriod = true;
} else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
// Swipe right
return false;
@ -620,8 +631,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = 27;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
_needEventRestPeriod = true;
_lastSecondaryTap = 0;
} else {
event.type = Common::EVENT_RBUTTONDOWN;
@ -631,6 +642,7 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastSecondaryTap = curTime;
_needEventRestPeriod = true;
}
} else {
return false;
@ -649,6 +661,68 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
_dirtyRects.push_back(Common::Rect(0, 0, _screenWidth, _screenHeight));
}
break;
case kInputKeyPressed:
int keyPressed = (int)xUnit;
int ascii = keyPressed;
//printf("key: %i\n", keyPressed);
// We remap some of the iPhone keyboard keys.
// The first ten here are the row of symbols below the numeric keys.
switch (keyPressed) {
case 45:
keyPressed = Common::KEYCODE_F1;
ascii = Common::ASCII_F1;
break;
case 47:
keyPressed = Common::KEYCODE_F2;
ascii = Common::ASCII_F2;
break;
case 58:
keyPressed = Common::KEYCODE_F3;
ascii = Common::ASCII_F3;
break;
case 59:
keyPressed = Common::KEYCODE_F4;
ascii = Common::ASCII_F4;
break;
case 40:
keyPressed = Common::KEYCODE_F5;
ascii = Common::ASCII_F5;
break;
case 41:
keyPressed = Common::KEYCODE_F6;
ascii = Common::ASCII_F6;
break;
case 36:
keyPressed = Common::KEYCODE_F7;
ascii = Common::ASCII_F7;
break;
case 38:
keyPressed = Common::KEYCODE_F8;
ascii = Common::ASCII_F8;
break;
case 64:
keyPressed = Common::KEYCODE_F9;
ascii = Common::ASCII_F9;
break;
case 34:
keyPressed = Common::KEYCODE_F10;
ascii = Common::ASCII_F10;
break;
case 10:
keyPressed = Common::KEYCODE_RETURN;
ascii = Common::ASCII_RETURN;
break;
}
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
_needEventRestPeriod = true;
break;
default:
break;
}

View File

@ -28,7 +28,7 @@
#include "graphics/surface.h"
#define AUDIO_BUFFERS 3
#define WAVE_BUFFER_SIZE 2048
#define WAVE_BUFFER_SIZE 4096
#define AUDIO_SAMPLE_RATE 44100
typedef void (*SoundProc)(void *param, byte *buf, int len);
@ -74,6 +74,7 @@ protected:
long _lastMouseDown;
long _lastMouseTap;
Common::Event _queuedInputEvent;
bool _needEventRestPeriod;
bool _secondaryTapped;
long _lastSecondaryDown;
long _lastSecondaryTap;