From ca16f9160e1ecbaa2a43c69758856b83d25fb818 Mon Sep 17 00:00:00 2001 From: Chaoji Li Date: Sat, 17 Oct 2020 21:45:30 +0800 Subject: [PATCH] Add bluetooth keyboard support for appstore By using private APIs, we have a perfect keyboard support (see DosPadUIApplication). However, that's not allowed in appstore. By using an invisible text input, we can capture external keyboard events and translate to emulator key events. However, it's only good for text input, not game control. We also support arrows, ctrl-?, alt-?, pageup/down, ... --- SDL/src/video/uikit/keyinfotable.h | 4 +- dospad.xcodeproj/project.pbxproj | 19 +- dospad/Shared/DOSPadBaseViewController.h | 5 +- dospad/Shared/DOSPadBaseViewController.m | 91 +-- dospad/Shared/DOSPadEmulator.h | 2 + dospad/Shared/DOSPadEmulator.m | 15 +- dospad/Shared/KeyboardSpy.h | 16 + dospad/Shared/KeyboardSpy.m | 296 ++++++++ dospad/Shared/UIExtendedTextField.h | 13 - dospad/Shared/UIExtendedTextField.m | 72 -- dospad/Shared/VKView.h | 62 -- dospad/Shared/VKView.m | 728 -------------------- dospad/iPad/DosPadViewController.h | 1 - dospad/iPad/DosPadViewController.m | 1 - dospad/iPhone/DosPadViewController_iPhone.h | 1 - 15 files changed, 351 insertions(+), 975 deletions(-) create mode 100644 dospad/Shared/KeyboardSpy.h create mode 100644 dospad/Shared/KeyboardSpy.m delete mode 100644 dospad/Shared/UIExtendedTextField.h delete mode 100644 dospad/Shared/UIExtendedTextField.m delete mode 100755 dospad/Shared/VKView.h delete mode 100755 dospad/Shared/VKView.m diff --git a/SDL/src/video/uikit/keyinfotable.h b/SDL/src/video/uikit/keyinfotable.h index 3bece3e5..269b8117 100755 --- a/SDL/src/video/uikit/keyinfotable.h +++ b/SDL/src/video/uikit/keyinfotable.h @@ -50,8 +50,8 @@ static UIKitKeyInfo unicharToUIKeyInfoTable[] = { /* 6 */ { SDL_SCANCODE_UNKNOWN, 0 }, /* 7 */ { SDL_SCANCODE_UNKNOWN, 0 }, /* 8 */ { SDL_SCANCODE_UNKNOWN, 0 }, -/* 9 */ { SDL_SCANCODE_UNKNOWN, 0 }, -/* 10 */ { SDL_SCANCODE_UNKNOWN, 0 }, +/* 9 */ { SDL_SCANCODE_TAB, 0 }, +/* 10 */ { SDL_SCANCODE_RETURN, 0 }, /* 11 */ { SDL_SCANCODE_UNKNOWN, 0 }, /* 12 */ { SDL_SCANCODE_UNKNOWN, 0 }, /* 13 */ { SDL_SCANCODE_UNKNOWN, 0 }, diff --git a/dospad.xcodeproj/project.pbxproj b/dospad.xcodeproj/project.pbxproj index 20658450..723677a4 100755 --- a/dospad.xcodeproj/project.pbxproj +++ b/dospad.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 2A4546F917D2809F00D18563 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F2A9CD12CD99EC0091B859 /* CoreMIDI.framework */; }; 2A4546FA17D2812100D18563 /* PianoKeyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = E794F3FE12DB4F0E00427836 /* PianoKeyboard.m */; }; 9222DD561CC44A9F00B321B9 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9222DD551CC44A9F00B321B9 /* GameController.framework */; }; + E70836B92539EEB200B9321F /* KeyboardSpy.m in Sources */ = {isa = PBXBuildFile; fileRef = E70836B82539EEB200B9321F /* KeyboardSpy.m */; }; E70C044112A4B43F00AC178F /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E70C044012A4B43F00AC178F /* AVFoundation.framework */; }; E7107154129A8E5A00B21291 /* cpuwindow.png in Resources */ = {isa = PBXBuildFile; fileRef = E7107147129A8E5A00B21291 /* cpuwindow.png */; }; E7107155129A8E5A00B21291 /* exitfull.png in Resources */ = {isa = PBXBuildFile; fileRef = E7107148129A8E5A00B21291 /* exitfull.png */; }; @@ -384,7 +385,6 @@ E778B2CB123919ED008AF49A /* SDLnetsys.h in Headers */ = {isa = PBXBuildFile; fileRef = E778B2C5123919ED008AF49A /* SDLnetsys.h */; }; E778B2CC123919ED008AF49A /* SDLnetTCP.c in Sources */ = {isa = PBXBuildFile; fileRef = E778B2C6123919ED008AF49A /* SDLnetTCP.c */; }; E778B2CD123919ED008AF49A /* SDLnetUDP.c in Sources */ = {isa = PBXBuildFile; fileRef = E778B2C7123919ED008AF49A /* SDLnetUDP.c */; }; - E7A01EE51CC927760036A4CF /* UIExtendedTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = E7A01EE11CC927370036A4CF /* UIExtendedTextField.m */; }; E7A01EE71CC9277E0036A4CF /* ColorTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = E7A01EDD1CC927370036A4CF /* ColorTheme.m */; }; E7A01EF41CC9A5480036A4CF /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDB9E40C0DEB81970027A75A /* CoreAudio.framework */; }; E7A01EF71CC9C1AB0036A4CF /* gift.png in Resources */ = {isa = PBXBuildFile; fileRef = E7A01EE81CC92F0C0036A4CF /* gift.png */; }; @@ -447,7 +447,6 @@ E7BE12FC128BF31A0046990B /* FloatingView.m in Sources */ = {isa = PBXBuildFile; fileRef = E799706312422D6800502015 /* FloatingView.m */; }; E7BE12FD128BF31A0046990B /* SliderView.m in Sources */ = {isa = PBXBuildFile; fileRef = E70EA4111242F83200528C9D /* SliderView.m */; }; E7BE12FF128BF31A0046990B /* GamePadView.m in Sources */ = {isa = PBXBuildFile; fileRef = E7A94CDC127D68B7006509E1 /* GamePadView.m */; }; - E7BE1301128BF31A0046990B /* VKView.m in Sources */ = {isa = PBXBuildFile; fileRef = E723F0C51286A1680009E3DA /* VKView.m */; }; E7BE1305128BF31A0046990B /* libSDLiPhoneOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD6526630DE8FCCB002AD96B /* libSDLiPhoneOS.a */; }; E7BE1306128BF31A0046990B /* libdosbox.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E71E60EB11B5506800EC5A05 /* libdosbox.a */; }; E7BE1307128BF31A0046990B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; }; @@ -711,6 +710,8 @@ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 9222DD551CC44A9F00B321B9 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; + E70836B72539EEB200B9321F /* KeyboardSpy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyboardSpy.h; sourceTree = ""; }; + E70836B82539EEB200B9321F /* KeyboardSpy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyboardSpy.m; sourceTree = ""; }; E70C044012A4B43F00AC178F /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; E70EA4101242F83200528C9D /* SliderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SliderView.h; path = ../iPad/SliderView.h; sourceTree = ""; }; E70EA4111242F83200528C9D /* SliderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SliderView.m; path = ../iPad/SliderView.m; sourceTree = ""; }; @@ -982,8 +983,6 @@ E71E61F511B550FD00EC5A05 /* shell_batch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shell_batch.cpp; sourceTree = ""; }; E71E61F611B550FD00EC5A05 /* shell_cmds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shell_cmds.cpp; sourceTree = ""; }; E71E61F711B550FD00EC5A05 /* shell_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shell_misc.cpp; sourceTree = ""; }; - E723F0C41286A1680009E3DA /* VKView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VKView.h; sourceTree = ""; }; - E723F0C51286A1680009E3DA /* VKView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VKView.m; sourceTree = ""; }; E729BDF0129B506E002B05B2 /* cpuwindow~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cpuwindow~ipad.png"; sourceTree = ""; }; E729BDF1129B506E002B05B2 /* exitfull~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "exitfull~ipad.png"; sourceTree = ""; }; E729BDF2129B506E002B05B2 /* modejoy~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "modejoy~ipad.png"; sourceTree = ""; }; @@ -1115,8 +1114,6 @@ E79E4A0011EC6BF400DEAA7B /* libc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libc.dylib; path = usr/lib/libc.dylib; sourceTree = SDKROOT; }; E7A01EDC1CC927370036A4CF /* ColorTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColorTheme.h; path = Shared/ColorTheme.h; sourceTree = ""; }; E7A01EDD1CC927370036A4CF /* ColorTheme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ColorTheme.m; path = Shared/ColorTheme.m; sourceTree = ""; }; - E7A01EE01CC927370036A4CF /* UIExtendedTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIExtendedTextField.h; sourceTree = ""; }; - E7A01EE11CC927370036A4CF /* UIExtendedTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExtendedTextField.m; sourceTree = ""; }; E7A01EE81CC92F0C0036A4CF /* gift.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gift.png; path = "misc-res/gift.png"; sourceTree = ""; }; E7A01EE91CC92F0C0036A4CF /* kbd.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = kbd.png; path = "misc-res/kbd.png"; sourceTree = ""; }; E7A01EF01CC92F450036A4CF /* button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = button.png; path = "gamepad-res/button.png"; sourceTree = ""; }; @@ -2061,8 +2058,6 @@ E7D214C511E45BD000D9654E /* keys.h */, E7D214C711E45BDE00D9654E /* keys.m */, E77DAFC411B5D83600B78E69 /* main.m */, - E7A01EE01CC927370036A4CF /* UIExtendedTextField.h */, - E7A01EE11CC927370036A4CF /* UIExtendedTextField.m */, E73A56692534979900E3B3FB /* MfiGamepadConfiguration.h */, E73A566A2534979900E3B3FB /* MfiGamepadConfiguration.m */, E73A566C2534A49000E3B3FB /* MfiGamepadManager.h */, @@ -2196,8 +2191,8 @@ E70EA4111242F83200528C9D /* SliderView.m */, E7996FAB1241C0A800502015 /* TipView.h */, E7996FAC1241C0A800502015 /* TipView.m */, - E723F0C41286A1680009E3DA /* VKView.h */, - E723F0C51286A1680009E3DA /* VKView.m */, + E70836B72539EEB200B9321F /* KeyboardSpy.h */, + E70836B82539EEB200B9321F /* KeyboardSpy.m */, ); name = Views; path = Shared; @@ -3308,7 +3303,6 @@ E7BE12EA128BF31A0046990B /* DosPadViewController.m in Sources */, E7BE12EB128BF31A0046990B /* main.m in Sources */, E7BE12F3128BF31A0046990B /* keys.m in Sources */, - E7A01EE51CC927760036A4CF /* UIExtendedTextField.m in Sources */, E7BE12F6128BF31A0046990B /* HoldIndicator.m in Sources */, E73A566B2534979900E3B3FB /* MfiGamepadConfiguration.m in Sources */, E7BE12F7128BF31A0046990B /* FrameskipIndicator.m in Sources */, @@ -3319,7 +3313,6 @@ E7BE12FC128BF31A0046990B /* FloatingView.m in Sources */, E7BE12FD128BF31A0046990B /* SliderView.m in Sources */, E7BE12FF128BF31A0046990B /* GamePadView.m in Sources */, - E7BE1301128BF31A0046990B /* VKView.m in Sources */, E7EF4372128FCE470014D060 /* AlertPrompt.m in Sources */, E72BE69712911096009DC46A /* DosPadViewController_iPhone.m in Sources */, E7A01EE71CC9277E0036A4CF /* ColorTheme.m in Sources */, @@ -3333,6 +3326,7 @@ E72BE6EF12911B5C009DC46A /* ZipArchive.m in Sources */, E715B35B1293B7750098D437 /* DOSPadBaseViewController.m in Sources */, E76C49381299490200901B69 /* FloatPanel.m in Sources */, + E70836B92539EEB200B9321F /* KeyboardSpy.m in Sources */, E74BB2B715C93DBC005EC552 /* DosPadUIApplication.m in Sources */, 2A4546FA17D2812100D18563 /* PianoKeyboard.m in Sources */, ); @@ -3808,6 +3802,7 @@ DEBUG, IDOS, IPHONEOS, + APPSTORE, ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; INFOPLIST_FILE = "Resources/iDOS-Info.plist"; diff --git a/dospad/Shared/DOSPadBaseViewController.h b/dospad/Shared/DOSPadBaseViewController.h index 89b630e1..262da29a 100755 --- a/dospad/Shared/DOSPadBaseViewController.h +++ b/dospad/Shared/DOSPadBaseViewController.h @@ -25,11 +25,11 @@ #import "GamePadView.h" #import "PianoKeyboard.h" #import "DOSPadEmulator.h" +#import "KeyboardSpy.h" typedef enum { InputSource_PCKeyboard = 0, InputSource_MouseButtons, - InputSource_iOSKeyboard, InputSource_NumPad, InputSource_GamePad, InputSource_Joystick, @@ -51,8 +51,6 @@ typedef enum { SDL_uikitopenglview *screenView; HoldIndicator *holdIndicator; - // Input Devices - //VKView *vk; // Background, conflicts with iOS keyboard GamePadView *gamepad; GamePadView *joystick; KeyboardView *kbd; @@ -64,6 +62,7 @@ typedef enum { @property (nonatomic, assign) BOOL autoExit; @property (nonatomic, strong) SDL_uikitopenglview *screenView; +@property (nonatomic, strong) KeyboardSpy *kbdspy; + (DOSPadBaseViewController*)dospadController; diff --git a/dospad/Shared/DOSPadBaseViewController.m b/dospad/Shared/DOSPadBaseViewController.m index 8c4e326e..ca32ba8b 100755 --- a/dospad/Shared/DOSPadBaseViewController.m +++ b/dospad/Shared/DOSPadBaseViewController.m @@ -145,6 +145,12 @@ - (void)viewWillAppear:(BOOL)animated screenView.alpha = 1; // Try to fix reboot problem on iPad 3.2.x dospad_resume(); [self.navigationController setNavigationBarHidden:YES animated:NO]; + + if (self.kbdspy) + { + [self.kbdspy becomeFirstResponder]; + [self.view bringSubviewToFront:self.kbdspy]; + } } - (void)viewWillDisappear:(BOOL)animated @@ -171,54 +177,13 @@ - (void)viewDidLoad //holdIndicator.transform = CGAffineTransformMakeScale(1.5, 1.5); // [self.view addSubview:holdIndicator]; - /* TODO: LITCHIE commented out by TVD - vk = [[VKView alloc] initWithFrame:CGRectMake(0,0,1,1)]; - vk.alpha = 0; - [self.view addSubview:vk]; - */ - - //--------------------------------------------------- - // Remap controls - //--------------------------------------------------- - #if 0 - remappingOnLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - remappingOnLabel.text = @"Remapping Controls ON"; - remappingOnLabel.textColor = [UIColor redColor]; - remappingOnLabel.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:remappingOnLabel]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:remappingOnLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f]]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:remappingOnLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:0.5f constant:0.0f]]; - remappingOnLabel.backgroundColor = [UIColor blackColor]; - remappingOnLabel.alpha = 0.6f; - remappingOnLabel.hidden = YES; - - resetMappingsButton = [[UIButton alloc] initWithFrame:CGRectZero]; - [resetMappingsButton setTitle:@"Reset Mappings" forState:UIControlStateNormal]; - [resetMappingsButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; - [resetMappingsButton setTintColor:[UIColor redColor]]; - resetMappingsButton.translatesAutoresizingMaskIntoConstraints = NO; - [resetMappingsButton addTarget:self action:@selector(resetMappingsButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:resetMappingsButton]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:resetMappingsButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f]]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:resetMappingsButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:0.75f constant:0.0f]]; - resetMappingsButton.contentEdgeInsets = UIEdgeInsetsMake(4.0f, 10.0f, 4.0f, 10.0f); - resetMappingsButton.backgroundColor = [UIColor blackColor]; - resetMappingsButton.alpha = 0.6f; - resetMappingsButton.layer.borderWidth = 1.0f; - resetMappingsButton.layer.borderColor = [[UIColor redColor] CGColor]; - resetMappingsButton.hidden = YES; +#ifdef APPSTORE + // For non appstore builds, we should use private API to support + // external keyboard. + self.kbdspy = [[KeyboardSpy alloc] initWithFrame:CGRectMake(0,0,60,40)]; + [self.view addSubview:self.kbdspy]; +#endif - self.keyMapper = [[KeyMapper alloc] init]; - [self.keyMapper loadFromDefaults]; - self.mfiHandler = [[MfiGameControllerHandler alloc] init]; - self.mfiInputHandler = [[MfiControllerInputHandler alloc] init]; - self.mfiInputHandler.keyMapper = self.keyMapper; - [self.mfiHandler discoverController:^(GCController *gameController) { - [self.mfiInputHandler setupControllerInputsForController:gameController]; - } disconnectedCallback:^{ - - }]; - #endif } @@ -250,9 +215,6 @@ - (NSUInteger)supportedInterfaceOrientations - (void)dealloc { [self removeAllInputSources]; - - //TODO LITCHIE commented out by TVD - //[vk release]; } - (void)onLaunchExit @@ -411,30 +373,6 @@ - (BOOL)prefersStatusBarHidden { return YES; } -- (void)removeiOSKeyboard -{ - //TODO: Litchie commented out by tvd - /* - if (vk.useNativeKeyboard != YES) - return; - // Hide the virtual native keyboard - // However, we are still listening to external keyboard input - vk.active = NO; - vk.useNativeKeyboard=NO; - vk.active = YES; - */ -} - -- (void)createiOSKeyboard -{ - //TODO: Litchie commented out by tvd - /* - if (vk.active) - vk.active = NO; - vk.useNativeKeyboard = YES; - vk.active = YES;*/ -} - - (void)NOT_IMPLEMENTED(createPCKeyboard); - (void)NOT_IMPLEMENTED(createNumpad); - (void)NOT_IMPLEMENTED(createGamepad); @@ -531,11 +469,6 @@ - (void)removeInputSource:(InputSourceType)type } break; } - case InputSource_iOSKeyboard: - { - [self removeiOSKeyboard]; - break; - } case InputSource_GamePad: { if (gamepad) diff --git a/dospad/Shared/DOSPadEmulator.h b/dospad/Shared/DOSPadEmulator.h index 50fcb330..986b0741 100755 --- a/dospad/Shared/DOSPadEmulator.h +++ b/dospad/Shared/DOSPadEmulator.h @@ -43,5 +43,7 @@ - (void)sendCommand:(NSString *)cmd; - (void)updateJoystick:(NSInteger)index x:(float)x y:(float)y; - (void)joystickButton:(NSInteger)buttonIndex pressed:(BOOL)pressed joystickIndex:(NSInteger)index; +- (void)sendKey:(int)scancode pressed:(BOOL)pressed; +- (void)sendKey:(int)scancode; @end diff --git a/dospad/Shared/DOSPadEmulator.m b/dospad/Shared/DOSPadEmulator.m index 7bfa59f2..66638696 100755 --- a/dospad/Shared/DOSPadEmulator.m +++ b/dospad/Shared/DOSPadEmulator.m @@ -50,10 +50,11 @@ extern int SDL_main(int argc, char *argv[]); static DOSPadEmulator* _sharedInstance; +#define MAX_PENDING_KEY_EVENTS 1000 + @interface DOSPadEmulator () { SDL_Joystick *_joystick[4]; - } @end @@ -216,6 +217,18 @@ - (void)sendCommand:(NSString *)cmd } +- (void)sendKey:(int)scancode pressed:(BOOL)pressed +{ + SDL_SendKeyboardKey( 0, pressed?SDL_PRESSED:SDL_RELEASED, scancode); +} + +- (void)sendKey:(int)scancode +{ + SDL_SendKeyboardKey( 0, SDL_PRESSED, scancode); + [NSThread sleepForTimeInterval:0.05]; // Very very important + SDL_SendKeyboardKey( 0, SDL_RELEASED, scancode); +} + - (BOOL)ensureJoystick:(NSInteger)index { if (!_joystick[index]) diff --git a/dospad/Shared/KeyboardSpy.h b/dospad/Shared/KeyboardSpy.h new file mode 100644 index 00000000..72a62c8e --- /dev/null +++ b/dospad/Shared/KeyboardSpy.h @@ -0,0 +1,16 @@ +// +// KeyboardSpy.h +// +// Listening on external keyboard input. +// SDL has an implementation but that's tightly coupled with the +// screen view, and it's not a great solution for iDOS. +// +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KeyboardSpy : UIView +@property (nonatomic, assign) BOOL active; +@end + +NS_ASSUME_NONNULL_END diff --git a/dospad/Shared/KeyboardSpy.m b/dospad/Shared/KeyboardSpy.m new file mode 100644 index 00000000..f415a0b8 --- /dev/null +++ b/dospad/Shared/KeyboardSpy.m @@ -0,0 +1,296 @@ +// +// KeyboardSpy.m +// iDOS +// +// Created by Chaoji Li on 2020/10/16. +// +#import "KeyboardSpy.h" +#import "DOSPadEmulator.h" +#include "SDL.h" +#import "SDL_keyboard_c.h" +#import "keyinfotable.h" + +#define COMBO(mod,k) [NSString stringWithFormat:@"%@-%@", mod, k] + +@interface KeyboardSpy() + +{ + NSMutableArray *_keyCommands; + NSMutableDictionary *_keyMap; +} +@end + +@implementation KeyboardSpy +@synthesize hasText; +@synthesize autocorrectionType; +@synthesize enablesReturnKeyAutomatically; +@synthesize autocapitalizationType; +@synthesize keyboardAppearance; +@synthesize keyboardType; +@synthesize spellCheckingType; +@synthesize smartDashesType; +@synthesize smartQuotesType; +@synthesize smartInsertDeleteType; +@synthesize returnKeyType; +@synthesize secureTextEntry; + +- (void)setActive:(BOOL)active +{ + [self becomeFirstResponder]; +} + +- (BOOL)active +{ + return [self isFirstResponder]; +} + +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (UIView*)inputAccessoryView { + return nil; +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + //self.backgroundColor = [UIColor redColor]; + self.hidden = YES; + + /* set UITextInputTrait properties, mostly to defaults */ + self.autocapitalizationType = UITextAutocapitalizationTypeNone; + self.autocorrectionType = UITextAutocorrectionTypeNo; + self.enablesReturnKeyAutomatically = NO; + self.keyboardAppearance = UIKeyboardAppearanceDefault; + self.keyboardType = UIKeyboardTypeASCIICapable; + self.returnKeyType = UIReturnKeyDefault; + self.secureTextEntry = NO; + self.inputAssistantItem.leadingBarButtonGroups = @[]; + self.inputAssistantItem.trailingBarButtonGroups = @[]; + self.spellCheckingType = UITextSpellCheckingTypeNo; + if (@available(iOS 11.0, *)) { + self.smartDashesType = UITextSmartDashesTypeNo; + self.smartQuotesType = UITextSmartQuotesTypeNo; + self.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; + } else { + // Fallback on earlier versions + } + + _keyCommands = [NSMutableArray array]; + _keyMap = [NSMutableDictionary dictionaryWithDictionary:@{ + @"F1": @(SDL_SCANCODE_F1), + @"F2": @(SDL_SCANCODE_F2), + @"F3": @(SDL_SCANCODE_F3), + @"F4": @(SDL_SCANCODE_F4), + @"F5": @(SDL_SCANCODE_F5), + @"F6": @(SDL_SCANCODE_F6), + @"F7": @(SDL_SCANCODE_F7), + @"F8": @(SDL_SCANCODE_F8), + @"F9": @(SDL_SCANCODE_F9), + @"F10": @(SDL_SCANCODE_F10), + @"F11": @(SDL_SCANCODE_F11), + @"F12": @(SDL_SCANCODE_F12), + @"ALT": @(SDL_SCANCODE_LALT), + @"CTRL": @(SDL_SCANCODE_LCTRL), + }]; + + // For text selection in dos programs + [self registerKeyCommand:COMBO(@"shift", UIKeyInputLeftArrow)]; + [self registerKeyCommand:COMBO(@"shift", UIKeyInputRightArrow)]; + [self registerKeyCommand:COMBO(@"shift", UIKeyInputUpArrow)]; + [self registerKeyCommand:COMBO(@"shift", UIKeyInputDownArrow)]; + + // For alt- and ctrl- shortcut keys in dos programs + for (int i = 'a'; i <= 'z'; i++) + { + NSString *x = [NSString stringWithFormat:@"%c",i]; + [self registerKeyCommand:COMBO(@"alt", x) code:SDL_SCANCODE_A + i - 'a']; + [self registerKeyCommand:COMBO(@"ctrl", x)]; + } + + + [self registerKeyCommand:UIKeyInputEscape code:SDL_SCANCODE_ESCAPE]; + [self registerKeyCommand:UIKeyInputLeftArrow code:SDL_SCANCODE_LEFT]; + [self registerKeyCommand:UIKeyInputRightArrow code:SDL_SCANCODE_RIGHT]; + [self registerKeyCommand:UIKeyInputUpArrow code:SDL_SCANCODE_UP]; + [self registerKeyCommand:UIKeyInputDownArrow code:SDL_SCANCODE_DOWN]; + [self registerKeyCommand:UIKeyInputPageUp code:SDL_SCANCODE_PAGEUP]; + [self registerKeyCommand:UIKeyInputPageDown code:SDL_SCANCODE_PAGEDOWN]; + + if (@available(iOS 13.4, *)) { + [self registerKeyCommand:UIKeyInputHome code:SDL_SCANCODE_HOME]; + [self registerKeyCommand:UIKeyInputEnd code:SDL_SCANCODE_END]; + [self registerKeyCommand:UIKeyInputF1 code:SDL_SCANCODE_F1]; + [self registerKeyCommand:UIKeyInputF2 code:SDL_SCANCODE_F2]; + [self registerKeyCommand:UIKeyInputF3 code:SDL_SCANCODE_F3]; + [self registerKeyCommand:UIKeyInputF4 code:SDL_SCANCODE_F4]; + [self registerKeyCommand:UIKeyInputF5 code:SDL_SCANCODE_F5]; + [self registerKeyCommand:UIKeyInputF6 code:SDL_SCANCODE_F6]; + [self registerKeyCommand:UIKeyInputF7 code:SDL_SCANCODE_F7]; + [self registerKeyCommand:UIKeyInputF8 code:SDL_SCANCODE_F8]; + [self registerKeyCommand:UIKeyInputF9 code:SDL_SCANCODE_F9]; + [self registerKeyCommand:UIKeyInputF10 code:SDL_SCANCODE_F10]; + [self registerKeyCommand:UIKeyInputF11 code:SDL_SCANCODE_F11]; + [self registerKeyCommand:UIKeyInputF12 code:SDL_SCANCODE_F12]; + } + + // Unfortunately, only F5&F6 works in above code. + // For example, F1/F2 are used by system to control brightness, + // and we won't get those key commands. + // Therefore we provide an alternative way to generate function + // keys. + [self registerCommandPrefix:@"1" title:@"F1"]; + [self registerCommandPrefix:@"2" title:@"F2"]; + [self registerCommandPrefix:@"3" title:@"F3"]; + [self registerCommandPrefix:@"4" title:@"F4"]; + [self registerCommandPrefix:@"5" title:@"F5"]; + [self registerCommandPrefix:@"6" title:@"F6"]; + [self registerCommandPrefix:@"7" title:@"F7"]; + [self registerCommandPrefix:@"8" title:@"F8"]; + [self registerCommandPrefix:@"9" title:@"F9"]; + [self registerCommandPrefix:@"0" title:@"F10"]; + [self registerCommandPrefix:@"c" title:@"CTRL"]; + [self registerCommandPrefix:@"x" title:@"ALT"]; + return self; +} + +- (void)registerCommandPrefix:(NSString*)keyInput title:(NSString*)title +{ + UIKeyCommand *cmd = [UIKeyCommand keyCommandWithInput:keyInput modifierFlags:UIKeyModifierCommand action:@selector(onCommandPrefix:) discoverabilityTitle:title]; + [_keyCommands addObject:cmd]; +} + +- (void)onCommandPrefix:(UIKeyCommand *)keyCommand +{ + NSLog(@"command prefix: %@ %@", keyCommand.input, keyCommand.discoverabilityTitle); + NSNumber *code = (NSNumber*)_keyMap[keyCommand.discoverabilityTitle]; + if (code) { + [[DOSPadEmulator sharedInstance] sendKey:code.intValue]; + } +} + +// The keyInput is already registered in _keyMap +- (void)registerKeyCommand:(NSString*)keyInput +{ + [self registerKeyCommand:keyInput code:0]; +} + +- (void)registerKeyCommand:(NSString*)keyInput code:(int)code +{ + NSInteger flags = 0; + if ([keyInput hasPrefix:@"shift-"]) { + flags |= UIKeyModifierShift; + } else if ([keyInput hasPrefix:@"ctrl-"]) { + flags |= UIKeyModifierControl; + } else if ([keyInput hasPrefix:@"alt-"]) { + flags |= UIKeyModifierAlternate; + } + NSUInteger i = [keyInput rangeOfString:@"-"].location; + if (i != NSNotFound) { + keyInput = [keyInput substringFromIndex:i+1]; + } + UIKeyCommand *cmd = [UIKeyCommand keyCommandWithInput:keyInput + modifierFlags:flags action:@selector(onKeyCommand:)]; + [_keyCommands addObject:cmd]; + if (code > 0) + { + _keyMap[keyInput] = @(code); + } +} + +- (void)onKeyCommand:(UIKeyCommand *)keyCommand +{ + NSLog(@"onkeycommand: %@ %c%c%c", keyCommand.input, + (int)keyCommand.modifierFlags & UIKeyModifierShift ? 'S':'-', + (int)keyCommand.modifierFlags & UIKeyModifierAlternate ? 'A':'-', + (int)keyCommand.modifierFlags & UIKeyModifierControl ? 'C':'-' + ); + NSNumber *code = _keyMap[keyCommand.input]; + if (code) { + if (keyCommand.modifierFlags & UIKeyModifierShift) { + SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT); + } else if (keyCommand.modifierFlags & UIKeyModifierAlternate) { + SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LALT); + } else if (keyCommand.modifierFlags & UIKeyModifierControl) { + SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LCTRL); + } + [[DOSPadEmulator sharedInstance] sendKey:code.intValue]; + if (keyCommand.modifierFlags) + [NSThread sleepForTimeInterval:1]; + if (keyCommand.modifierFlags & UIKeyModifierShift) { + SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT); + } else if (keyCommand.modifierFlags & UIKeyModifierAlternate) { + SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LALT); + } else if (keyCommand.modifierFlags & UIKeyModifierControl) { + SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LCTRL); + } + } +} + +- (UIView*)inputView +{ + UIView *inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; + inputView.backgroundColor=[UIColor clearColor]; + inputView.alpha=0; + return inputView; +} + + +- (NSArray *)keyCommands { + return _keyCommands; +} + +- (void)sendChar:(unichar)c +{ + 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( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT); + } + /* send a keydown and keyup even for the character */ + [[DOSPadEmulator sharedInstance] sendKey:code]; + if (mod & KMOD_SHIFT) { + /* If character uses shift, press shift back up */ + SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT); + } +} + + + +- (BOOL)hasText +{ + return YES; +} + +- (void)deleteBackward +{ + [[DOSPadEmulator sharedInstance] sendKey:SDL_SCANCODE_BACKSPACE]; +} + +- (void)insertText:(nonnull NSString *)text { + int i; + for (i=0; i<[text length]; i++) { + + unichar c = [text characterAtIndex: i]; + [self sendChar:c]; + } +} + + + +@end diff --git a/dospad/Shared/UIExtendedTextField.h b/dospad/Shared/UIExtendedTextField.h deleted file mode 100644 index 79786f69..00000000 --- a/dospad/Shared/UIExtendedTextField.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// UIExtendedTextView.h -// dospad -// -// Created by Will Powers on 4/27/14. -// -// - -#import - -@interface UIExtendedTextField : UITextField - -@end diff --git a/dospad/Shared/UIExtendedTextField.m b/dospad/Shared/UIExtendedTextField.m deleted file mode 100644 index 45b199dd..00000000 --- a/dospad/Shared/UIExtendedTextField.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// UIExtendedTextView.m -// dospad -// -// Created by Will Powers on 4/27/14. -// Add additional external keyboard functionality. (ESC, Arrow keys). -// -// - -#import "UIExtendedTextField.h" -#import "SDL_keyboard_c.h" - -@implementation UIExtendedTextField - -- (id)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - // Initialization code - } - return self; -} - -- (NSArray *)keyCommands { - UIKeyCommand *esc = [UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(esc:)]; - UIKeyCommand *leftArrow = [UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:0 action:@selector(leftArrow:)]; - UIKeyCommand *rightArrow = [UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:0 action:@selector(rightArrow:)]; - UIKeyCommand *upArrow = [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:0 action:@selector(upArrow:)]; - UIKeyCommand *downArrow = [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:0 action:@selector(downArrow:)]; - return [[NSArray alloc] initWithObjects:esc, leftArrow, rightArrow, upArrow, downArrow, nil]; -} - -- (void)esc:(UIKeyCommand *)keyCommand -{ - SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_ESCAPE); - SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_ESCAPE); -} - -- (void)leftArrow:(UIKeyCommand *)keyCommand -{ - SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LEFT); - SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LEFT); -} - -- (void)rightArrow:(UIKeyCommand *)keyCommand -{ - SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_RIGHT); - SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_RIGHT); -} - -- (void)upArrow:(UIKeyCommand *)keyCommand -{ - SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_UP); - SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_UP); -} - -- (void)downArrow:(UIKeyCommand *)keyCommand -{ - SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DOWN); - SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DOWN); -} - -/* -// Only override drawRect: if you perform custom drawing. -// An empty implementation adversely affects performance during animation. -- (void)drawRect:(CGRect)rect -{ - // Drawing code -} -*/ - -@end diff --git a/dospad/Shared/VKView.h b/dospad/Shared/VKView.h deleted file mode 100755 index bcdc6c8f..00000000 --- a/dospad/Shared/VKView.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2010 Chaoji Li - * - * DOSPAD 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#import - - -@interface TPos : UITextPosition -{ - int line; - int column; -} - -@property (nonatomic, assign) int line; // line number of the text position. 0-based -@property (nonatomic, assign) int column; // first char is 0, the end of line column. - // a chinese char is counted as one column - // although it is twice as wide -@property (weak, nonatomic, readonly) NSString *description; - -- (NSComparisonResult)compareTo:(TPos *)another; -+ (TPos*)positionWithLine:(int)line column:(int)column; - -@end - -@interface TRange : UITextRange -{ - TPos* __weak start; - TPos* __weak end; -} -@property (weak, nonatomic, readonly) TPos* start; -@property (weak, nonatomic, readonly) TPos* end; -@property (nonatomic, readonly, getter=isEmpty) BOOL empty; // Whether the range is zero-length. -@property (weak, nonatomic, readonly) NSString *description; - -+ (TRange*)rangeWithStart:(TPos*)start end:(TPos*)end; -@end - - -@interface VKView : UIView { - NSString *text; - TRange *selectedTextRange; - BOOL useNativeKeyboard; -} - -@property (nonatomic, assign) BOOL useNativeKeyboard; -@property (nonatomic, assign) BOOL active; - -@end diff --git a/dospad/Shared/VKView.m b/dospad/Shared/VKView.m deleted file mode 100755 index dfaee1e8..00000000 --- a/dospad/Shared/VKView.m +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (C) 2010 Chaoji Li - * - * DOSPAD 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#import "VKView.h" -#include "keys.h" -#import "Common.h" - -extern int SDL_SendKeyboardKey(int index, Uint8 state, SDL_scancode scancode); - - -@implementation TPos -@synthesize line; -@synthesize column; - -- (id)initWithLine:(int)ln Column:(int)col -{ - line = ln; - column = col; - return self; -} - -+ (TPos*)positionWithLine:(int)line column:(int)column -{ - TPos *tp = [[TPos alloc] initWithLine:line Column:column]; - return tp; -} - -- (NSString*)description -{ - return [NSString stringWithFormat:@"(%d,%d)", line, column]; -} - -- (NSComparisonResult)compareTo:(TPos *)another -{ - TPos *tp = another; - if (another == nil) - { - return NSOrderedAscending; - } - if (line < tp.line || (line == tp.line && column < tp.column)) - return NSOrderedAscending; - else if (line == tp.line && column == tp.column) - return NSOrderedSame; - else - return NSOrderedDescending; -} - -@end - -@implementation TRange -@synthesize start; -@synthesize end; -@synthesize empty; - -- (id)initWithPos:(TPos*)beg end:(TPos*)endPos -{ - if (start!=nil) ; - if (end !=nil) ; - start = beg; - end = endPos; - return self; -} - -+ (TRange*)rangeWithStart:(TPos *)start end:(TPos *)end -{ - TRange *range = [[TRange alloc] initWithPos:start end:end]; - return range; -} - -- (NSString*)description -{ - return [NSString stringWithFormat:@"(start=%@, end=%@)", - start.description, end.description]; -} - -- (BOOL)isEmpty -{ - if (start == nil || end == nil) return YES; - return start.line==end.line && start.column == end.column; -} - - -@end - - -@implementation VKView - -@synthesize useNativeKeyboard; -@synthesize active; - -- (void)setActive:(BOOL)b -{ - if (b == [self isFirstResponder]) return; - DEBUGLOG(@"active %d", b); - if (b) - { - [self becomeFirstResponder]; - } - else - { - [self resignFirstResponder]; - } -} - -- (BOOL)active -{ - return [self isFirstResponder]; -} - - -- (void)setUseNativeKeyboard:(BOOL)b -{ - if (useNativeKeyboard == b) - { - return; - } - - useNativeKeyboard = b; - if ([self isFirstResponder]) { - [self resignFirstResponder]; - [self becomeFirstResponder]; - } -} - - -- (UIView*)inputView -{ - if (useNativeKeyboard) return nil; - UIView *inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; - inputView.backgroundColor=[UIColor clearColor]; - inputView.alpha=0; - return inputView; -} - -- (id)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - // Initialization code - self.backgroundColor=[UIColor blueColor]; - selectedTextRange = [TRange rangeWithStart:[TPos positionWithLine:0 column:0] - end:[TPos positionWithLine:0 column:0]]; - } - return self; -} - -/* -- (void)drawRect:(CGRect)rect { - // Drawing code - if (text != nil) - { - [text drawInRect:rect withFont:[UIFont systemFontOfSize:20]]; - } -} - */ - - -- (void)sendKeyEvent:(int)keyCode -{ - SDL_SendKeyboardKey(0, SDL_PRESSED, keyCode); - [NSThread sleepForTimeInterval:0.05]; // Very very important - SDL_SendKeyboardKey(0, SDL_RELEASED, keyCode); -} - -// We need to declare this for it to work -- (BOOL)canBecomeFirstResponder -{ - return YES; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - if ([self isFirstResponder] == NO) - { - UITouch *touch = [touches anyObject]; - CGPoint location = [touch locationInView:self]; - //DEBUGLOG(@"tap at %f %f ", location.x, location.y); - [self becomeFirstResponder]; - } - else - { - [super touchesBegan:touches withEvent:event]; - } -} - -- (void)deleteBackward -{ - [self sendKeyEvent:SDL_SCANCODE_BACKSPACE]; -} - -- (BOOL)hasText -{ - return [text length]>0; -} -- (void)insertText:(NSString *)_text -{ - text = _text; - unichar c = [_text characterAtIndex:0]; - - if ([_text isEqualToString:@"\n"]) [self sendKeyEvent:SDL_SCANCODE_RETURN]; - - if (c < 128) - { - int shift=0; - int code=get_scancode_for_char(c, &shift); - if (shift) - { - SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LSHIFT); - } - if (code > 0) [self sendKeyEvent:code]; - if (shift) - { - SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LSHIFT); - } - } - [self setNeedsDisplay]; -} - - -//============================================================================== -// UITextInput Protocol -//============================================================================== -#pragma mark UITextInput implementation - -//@synthesize inputDelegate; -@synthesize selectionAffinity; - -//------------------------------------------------------------------------------ -// An affiliated view that provides a coordinate system for all geometric values -// in this protocol. (read-only) -// -// Discussion -// The view that both draws the text and provides a coordinate system for all -// geometric values in this protocol. (This is typically an instance of the -// UITextInput-adopting class.) If this property is unimplemented, -// the first view in the responder chain is selected. -- (UIView*)textInputView -{ - //DEBUGLOG(@"returning textInputView"); - return self; -} - -//------------------------------------------------------------------------------ -// An input tokenizer that provides information about the granularity of text -// units. (readonly) -// -// Discussion -// Standard units of granularity include characters, words, lines, and -// paragraphs. In most cases, you may lazily create and assign an instance of -// a subclass of UITextInputStringTokenizer for this purpose. If you require -// different behavior than this system-provided tokenizer, you can create a -// custom tokenizer that adopts the UITextInputTokenizer protocol. -//------------------------------------------------------------------------------ -- (id)tokenizer -{ - return nil; -} - -//------------------------------------------------------------------------------ -// A dictionary of attributes that describes how marked text should be drawn. -// (copy) -// -// Discussion -// Marked text requires a unique visual treatment when displayed to users. -// See “Style Dictionary Keys” for descriptions of the valid keys and values -// for this dictionary. -//------------------------------------------------------------------------------ -- (NSDictionary *)markedTextStyle -{ - DEBUGLOG(@"markedTextStyle not implemented"); - return nil; -} - -- (void)setMarkedTextStyle:(NSDictionary *)style -{ - DEBUGLOG(@"setMarkedTextStyle not implemented"); -} - -//------------------------------------------------------------------------------ -// The range of text that is currently marked in a document. (readonly) -// -// Discussion -// If there is no marked text, the value of the property is nil. Marked text is -// provisionally inserted text that requires user confirmation; it occurs in -// multistage text input. The current selection, which can be a caret or an -// extended range, always occurs within the marked text. -//------------------------------------------------------------------------------ -- (UITextRange*)markedTextRange -{ - //DEBUGLOG(@"markedTextRange"); - return nil; -} - -//------------------------------------------------------------------------------ -// Insert the provided text and marks it to indicate that it is part of an -// active input session. -// -// Parameters -// markedText - The text to be marked. -// selectedRange - A range within markedText that indicates the current -// selection. This range is always relative to markedText. -// Discussion -// Setting marked text either replaces the existing marked text or, if none is -// present, inserts it in place of the current selection. -//------------------------------------------------------------------------------ -- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange -{ - //DEBUGLOG(@"setMarkedText"); -} - - -- (UITextRange*)selectedTextRange -{ - //DEBUGLOG(@"selectedTextRange"); - return selectedTextRange; -} - -- (void)setSelectedTextRange:(UITextRange *)range -{ - // DEBUGLOG(@"setSelectedTextRange:%@=>%@", - // [selectedTextRange description], - // [(TRange*)range description]); - TRange *trNew = (TRange*)range; - if (trNew.start.line < selectedTextRange.start.line) - { - [self sendKeyEvent:SDL_SCANCODE_UP]; - } - else if (trNew.start.line > selectedTextRange.start.line) - { - [self sendKeyEvent:SDL_SCANCODE_DOWN]; - } - else if (trNew.start.column > selectedTextRange.start.column) - { - [self sendKeyEvent:SDL_SCANCODE_RIGHT]; - } - else - { - [self sendKeyEvent:SDL_SCANCODE_LEFT]; - } - - selectedTextRange = (TRange*)range; -} - -- (UITextPosition*)beginningOfDocument -{ - //DEBUGLOG(@"beginningOfDocument"); - return [TPos positionWithLine:INT_MIN column:0]; -} - - -- (UITextPosition*)endOfDocument -{ - //DEBUGLOG(@"endOfDocument"); - // FIXME: perhaps we need to use the end of last line - return [TPos positionWithLine:INT_MAX column:0]; -} - - - - -- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction -{ - DEBUGLOG(@"baseWritingDirectionForPosition"); - return UITextWritingDirectionLeftToRight; -} - -- (CGRect)caretRectForPosition:(UITextPosition *)position -{ - DEBUGLOG(@"caretRectForPosition"); - return CGRectZero; -} - - -//------------------------------------------------------------------------------ -// Return the character offset of a position in a document’s text that falls -// within a given range. -// -// This method is used when there is no one-to-one correspondence between -// UITextPosition objects and characters. For example, one chinese character -// occupies two position. -// -// Parameters -// position - An object that identifies a location in a document’s text. -// range - An object that specifies a range of text in a document. -// -// Return Value -// The number of characters in a document's text that occur between position -// and the beginning of range. -//------------------------------------------------------------------------------ -- (NSInteger)characterOffsetOfPosition:(UITextPosition *)position - withinRange:(UITextRange *)range -{ - DEBUGLOG(@"characterOffsetOfPosition"); - return 0; -} - - -//------------------------------------------------------------------------------ -// Return the character or range of characters that is at a given point in a document. -// -// Parameters -// point - A point in the view that is drawing a document’s text. -// Return Value -// An object representing a range that encloses a character (or characters) at point. -//------------------------------------------------------------------------------ -- (UITextRange *)characterRangeAtPoint:(CGPoint)point -{ - DEBUGLOG(@"characterRangeAtPoint:(%f,%f)",point.x, point.y); - return nil; -} - -//------------------------------------------------------------------------------ -// Return a text range from a given text position to its farthest extent in a -// certain direction of layout. -// -// Parameters -// position - A text-position object that identifies a location in a document. -// direction - A constant that indicates a direction of layout (right, left, -// up, down). -// Return Value -// A text-range object that represents the distance from position to the -// farthest extent in direction. -//------------------------------------------------------------------------------ -- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position - inDirection:(UITextLayoutDirection)direction -{ - DEBUGLOG(@"characterRangeByExtendingPosition"); - return nil; -} - -//------------------------------------------------------------------------------ -// Return the position in a document that is closest to a specified point. -// -// Parameters -// point - A point in the view that is drawing a document’s text. -// Return Value -// An object locating a position in a document that is closest to point. -//------------------------------------------------------------------------------ -- (UITextPosition *)closestPositionToPoint:(CGPoint)point -{ - DEBUGLOG(@"closestPositionToPoint:(%f,%f)", point.x, point.y); - return nil; -} - -//------------------------------------------------------------------------------ -// Return the position in a document that is closest to a specified point in a -// given range. -// -// Parameters -// point - A point in the view that is drawing a document’s text. -// range - An object representing a range in a document’s text. -// Return Value -// An object representing the character position in range that is closest to -// point. -//------------------------------------------------------------------------------ -- (UITextPosition *)closestPositionToPoint:(CGPoint)point - withinRange:(UITextRange *)range -{ - DEBUGLOG(@"closestPositionToPoint"); - return nil; -} - -//------------------------------------------------------------------------------ -// Return how one text position compares to another text position. (required) -// -// Parameters -// position - A custom object that represents a location within a document. -// other - A custom object that represents another location within a document. -// Return Value -// A value that indicates whether the two text positions are identical or -// whether one is before the other. -//------------------------------------------------------------------------------ -- (NSComparisonResult)comparePosition:(UITextPosition *)position - toPosition:(UITextPosition *)other -{ -// DEBUGLOG(@"comparePosition:%@ toPosition:%@", -// [(TPos*)position description], [(TPos*)other description]); - return [(TPos*)position compareTo:(TPos*)other]; -} - -//------------------------------------------------------------------------------ -// Return the first rectangle that encloses a range of text in a document. -// -// Parameters -// range - An object that represents a range of text in a document. -// Return Value -// The first rectangle in a range of text. You might use this rectangle to -// draw a correction rectangle. The “first” in the name refers the rectangle -// enclosing the first line when the range encompasses multiple lines of text. -//------------------------------------------------------------------------------ -- (CGRect)firstRectForRange:(UITextRange *)range -{ - DEBUGLOG(@"firstRectForRange"); - return CGRectZero; -} - -//------------------------------------------------------------------------------ -// Return the number of visible characters between one text position and another -// text position. -// -// Parameters -// fromPosition - A custom object that represents a location within a -// document. -// toPosition - A custom object that represents another location within -// document. -// Return Value -// The number of visible characters between fromPosition and toPosition. -//------------------------------------------------------------------------------ -- (NSInteger)offsetFromPosition:(UITextPosition *)fromPosition - toPosition:(UITextPosition *)toPosition -{ - DEBUGLOG(@"offsetFromPosition"); - return 0; -} - -//------------------------------------------------------------------------------ -// Returns the text position at a given offset in a specified direction from -// another text position. -// -// Parameters -// position - A custom UITextPosition object that represents a location in a document. -// direction - A UITextLayoutDirection constant that represents the direction of the offset from position. -// offset - A character offset from position. -// Return nil if the computed text position is less than 0 or greater than the length of the backing string. -//------------------------------------------------------------------------------ -- (UITextPosition *)positionFromPosition:(UITextPosition *)position - inDirection:(UITextLayoutDirection)direction - offset:(NSInteger)offset -{ -// DEBUGLOG(@"positionFromPosition %@ inDirection %d offset %d", -// [(TPos*)position description], direction, offset); - TPos *tp = (TPos*)position; - switch (direction) - { - case UITextLayoutDirectionUp: - return [TPos positionWithLine:tp.line-offset column:tp.column]; - case UITextLayoutDirectionDown: - return [TPos positionWithLine:tp.line+offset column:tp.column]; - case UITextLayoutDirectionLeft: - return [TPos positionWithLine:tp.line column:tp.column-offset]; - case UITextLayoutDirectionRight: - return [TPos positionWithLine:tp.line column:tp.column+offset]; - } - return nil; -} - -//------------------------------------------------------------------------------ -// Returns the text position at a given offset from another text position. -// -// Parameters -// position - A custom UITextPosition object that represents a location in a -// document. -// offset - A character offset from position. It can be a positive or negative -// value. -// Return Value -// A custom UITextPosition object that represents the location in a document -// that is at the specified offset from position. -// Return nil if the computed text position is less than 0 or greater than the -// length of the backing string. -//------------------------------------------------------------------------------ -- (UITextPosition *)positionFromPosition:(UITextPosition *)position - offset:(NSInteger)offset -{ - //DEBUGLOG(@"positionFromPosition offset"); - return nil; -} - -//------------------------------------------------------------------------------ -// Return the position within a range of a document’s text that corresponds to -// the character offset from the start of that range. -// -// Parameters -// range - An object that specifies a range of text in a document. -// offset - A character offset from the start of range. -// Return Value -// An object that represents a position in a document’s visible text. -//------------------------------------------------------------------------------ -- (UITextPosition *)positionWithinRange:(UITextRange *)range atCharacterOffset:(NSInteger)offset -{ - DEBUGLOG(@"positionWithinRange atCharacterOffset"); - return nil; -} - -//------------------------------------------------------------------------------ -// Return the text position that is at the farthest extent in a given layout -// direction within a range of text. -// -// Parameters -// range - A text-range object that demarcates a range of text in a document. -// direction - A constant that indicates a direction of layout (right, left, -// up, down). -// Return Value -// A text-position object that identifies a location in the visible text. -//------------------------------------------------------------------------------ -- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction -{ - DEBUGLOG(@"positionWithinRange:farthestInDirection not implemented"); - return nil; -} - -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -- (void)replaceRange:(UITextRange *)range withText:(NSString *)text -{ - DEBUGLOG(@"replaceRange not implemented"); -} - -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range -{ - DEBUGLOG(@"setBaseWritingDirection not implemented"); - -} - -//------------------------------------------------------------------------------ -// textInRange: -// -// Return the text in the specified range. (required) -// -// Parameters -// range - A range of text in a document. -// -// Return Value -// A substring of a document that falls within the specified range. -//------------------------------------------------------------------------------ -- (NSString *)textInRange:(UITextRange *)range -{ - DEBUGLOG(@"textInRange"); - return nil; -} - -//------------------------------------------------------------------------------ -// Return the range between two text positions. -// -// Parameters -// fromPosition - An object that represents a location in a document. -// toPosition - An object that represents another location in a document. -// Return Value -// An object that represents the range between fromPosition and toPosition. -//------------------------------------------------------------------------------ -- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition - toPosition:(UITextPosition *)toPosition -{ - //DEBUGLOG(@"textRangeFromPosition:%@ toPosition:%@", -// [(TPos*)fromPosition description], -// [(TPos*)toPosition description]); - return [TRange rangeWithStart:(TPos*)fromPosition end:(TPos*)toPosition]; -} - -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -- (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction -{ - DEBUGLOG(@"textStylingAtPosition not implemented"); - return nil; -} - -//------------------------------------------------------------------------------ -// Unmark the currently marked text. (required) -// -// Discussion -// After this method is called, the value of markedTextRange is nil. -//------------------------------------------------------------------------------ -- (void)unmarkText -{ - DEBUGLOG(@"unmarkText"); -} - -//============================================================================== -// UITextInputTraits Protocol -//============================================================================== -#pragma mark UITextInputTraits Protocol - -- ( UITextAutocorrectionType)autocorrectionType -{ - return UITextAutocorrectionTypeDefault; -} - -- (UIKeyboardAppearance)keyboardAppearance -{ - return UIKeyboardAppearanceAlert; -} - -- (UIReturnKeyType)returnKeyType; -{ - return UIReturnKeyDefault; -} - -- (UITextAutocapitalizationType)autocapitalizationType -{ - return UITextAutocapitalizationTypeNone; -} - -- (UIKeyboardType)keyboardType -{ - return UIKeyboardTypeASCIICapable; -} - -- (BOOL)enablesReturnKeyAutomatically; -{ - return NO; -} - -- (BOOL)isSecureTextEntry -{ - return NO; -} - - -@end diff --git a/dospad/iPad/DosPadViewController.h b/dospad/iPad/DosPadViewController.h index b390adb2..0483f174 100755 --- a/dospad/iPad/DosPadViewController.h +++ b/dospad/iPad/DosPadViewController.h @@ -25,7 +25,6 @@ #import "CommandListView.h" #import "SliderView.h" #import "GamePadView.h" -//#import "VKView.h" #import "DOSPadBaseViewController.h" #import "FloatPanel.h" diff --git a/dospad/iPad/DosPadViewController.m b/dospad/iPad/DosPadViewController.m index 83dc1580..f737ee1d 100755 --- a/dospad/iPad/DosPadViewController.m +++ b/dospad/iPad/DosPadViewController.m @@ -533,7 +533,6 @@ -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self updateUI]; - //[vk becomeFirstResponder]; TODO Litchie commented out by tvd } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. diff --git a/dospad/iPhone/DosPadViewController_iPhone.h b/dospad/iPhone/DosPadViewController_iPhone.h index 29b73cdf..096a87f1 100755 --- a/dospad/iPhone/DosPadViewController_iPhone.h +++ b/dospad/iPhone/DosPadViewController_iPhone.h @@ -24,7 +24,6 @@ #import "HoldIndicator.h" #import "FrameskipIndicator.h" #import "GamePadView.h" -#import "VKView.h" #import "SliderView.h" #import "DOSPadBaseViewController.h" #import "FloatPanel.h"