From 6a4ce78789a4297a46e3528eaaf48601c1461549 Mon Sep 17 00:00:00 2001 From: Oystein Eftevaag Date: Sun, 18 Nov 2007 17:58:53 +0000 Subject: 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 --- backends/platform/iphone/iphone_common.h | 3 +- backends/platform/iphone/iphone_keyboard.h | 51 +++++++++++++++++ backends/platform/iphone/iphone_keyboard.m | 88 ++++++++++++++++++++++++++++++ backends/platform/iphone/iphone_video.h | 5 +- backends/platform/iphone/iphone_video.m | 65 +++++++++++++--------- backends/platform/iphone/module.mk | 3 +- backends/platform/iphone/osys_iphone.cpp | 84 ++++++++++++++++++++++++++-- backends/platform/iphone/osys_iphone.h | 3 +- 8 files changed, 266 insertions(+), 36 deletions(-) create mode 100644 backends/platform/iphone/iphone_keyboard.h create mode 100644 backends/platform/iphone/iphone_keyboard.m (limited to 'backends/platform') diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h index 287f797472..567f54800e 100644 --- a/backends/platform/iphone/iphone_common.h +++ b/backends/platform/iphone/iphone_common.h @@ -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. diff --git a/backends/platform/iphone/iphone_keyboard.h b/backends/platform/iphone/iphone_keyboard.h new file mode 100644 index 0000000000..17a3836efd --- /dev/null +++ b/backends/platform/iphone/iphone_keyboard.h @@ -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 +#import + +@protocol KeyboardInputProtocol +- (void)handleKeyPress:(unichar)c; +@end + +@interface SoftKeyboard : UIKeyboard { + 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 diff --git a/backends/platform/iphone/iphone_keyboard.m b/backends/platform/iphone/iphone_keyboard.m new file mode 100644 index 0000000000..923b7be46d --- /dev/null +++ b/backends/platform/iphone/iphone_keyboard.m @@ -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 \ No newline at end of file diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h index 167b74705b..9a0492bad3 100644 --- a/backends/platform/iphone/iphone_video.h +++ b/backends/platform/iphone/iphone_video.h @@ -33,13 +33,14 @@ #import #import +#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 */ diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m index d3989e3838..df15f61a6b 100644 --- a/backends/platform/iphone/iphone_video.m +++ b/backends/platform/iphone/iphone_video.m @@ -32,6 +32,7 @@ #import #import #import +#import 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 ] ]; diff --git a/backends/platform/iphone/module.mk b/backends/platform/iphone/module.mk index 2d26c26e59..47461ad2b2 100644 --- a/backends/platform/iphone/module.mk +++ b/backends/platform/iphone/module.mk @@ -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/ diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp index 6f1d82fb2c..8c029d10b5 100644 --- a/backends/platform/iphone/osys_iphone.cpp +++ b/backends/platform/iphone/osys_iphone.cpp @@ -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; } diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h index 9abd8657e7..65d4b9744e 100644 --- a/backends/platform/iphone/osys_iphone.h +++ b/backends/platform/iphone/osys_iphone.h @@ -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; -- cgit v1.2.3