diff --git a/CMakeLists.txt b/CMakeLists.txt index 61f5ffa9ce..2ddad0dac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -955,9 +955,6 @@ elseif(IOS AND NOT LIBRETRO) ios/CameraHelper.h ios/LocationHelper.mm ios/LocationHelper.h - ios/iCade/iCadeReaderView.h - ios/iCade/iCadeReaderView.m - ios/iCade/iCadeState.h Common/Battery/AppleBatteryClient.m ) @@ -987,7 +984,6 @@ elseif(IOS AND NOT LIBRETRO) ios/ViewControllerMetal.mm ios/iOSCoreAudio.mm ios/IAPManager.mm - ios/iCade/iCadeReaderView.m ios/main.mm ios/CameraHelper.mm ios/LocationHelper.mm diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index f62c374f30..62d2ac3cf0 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -731,22 +731,6 @@ true true - - true - true - true - true - true - true - - - true - true - true - true - true - true - true true @@ -1143,14 +1127,6 @@ true true - - true - true - true - true - true - true - true true diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index f3fbd990a7..1c942c989d 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -50,9 +50,6 @@ {14abd855-ec8b-47a5-8b4c-eadcff122dc8} - - {ce617e38-1bc8-4eab-a3cb-d3d664116c91} - {8f39c005-9738-41c5-a8d8-cfc05bf178e8} @@ -487,12 +484,6 @@ Other Platforms\libretro - - Other Platforms\iOS\iCade - - - Other Platforms\iOS\iCade - Windows\W32Util @@ -698,9 +689,6 @@ Other Platforms\iOS - - Other Platforms\iOS\iCade - Build\CMake diff --git a/ios/Controls.h b/ios/Controls.h index dc3aef7448..49ec243056 100644 --- a/ios/Controls.h +++ b/ios/Controls.h @@ -1,12 +1,10 @@ #pragma once -#include #include #import #import -#include "iCade/iCadeState.h" #include "Common/Input/InputState.h" // Code extracted from ViewController.mm, in order to modularize @@ -27,22 +25,6 @@ private: UITouch *touches_[10]{}; }; -// Can probably get rid of this, but let's keep it for now. -struct ICadeTracker { -public: - void ButtonDown(iCadeState button); - void ButtonUp(iCadeState button); - void InitKeyMap(); -private: - bool simulateAnalog = false; - bool iCadeConnectNotified = false; - - std::map iCadeToKeyMap; - - double lastSelectPress = 0.0f; - double lastStartPress = 0.0f; -}; - void ProcessAccelerometerData(CMAccelerometerData *accData); InputKeyCode HIDUsageToInputKeyCode(UIKeyboardHIDUsage usage); diff --git a/ios/Controls.mm b/ios/Controls.mm index 711a81a6e5..78f0da8d29 100644 --- a/ios/Controls.mm +++ b/ios/Controls.mm @@ -287,131 +287,6 @@ void TouchTracker::Cancelled(NSSet *touches, UIView *view) { } } -void ICadeTracker::InitKeyMap() { - iCadeToKeyMap[iCadeJoystickUp] = NKCODE_DPAD_UP; - iCadeToKeyMap[iCadeJoystickRight] = NKCODE_DPAD_RIGHT; - iCadeToKeyMap[iCadeJoystickDown] = NKCODE_DPAD_DOWN; - iCadeToKeyMap[iCadeJoystickLeft] = NKCODE_DPAD_LEFT; - iCadeToKeyMap[iCadeButtonA] = NKCODE_BUTTON_9; // Select - iCadeToKeyMap[iCadeButtonB] = NKCODE_BUTTON_7; // LTrigger - iCadeToKeyMap[iCadeButtonC] = NKCODE_BUTTON_10; // Start - iCadeToKeyMap[iCadeButtonD] = NKCODE_BUTTON_8; // RTrigger - iCadeToKeyMap[iCadeButtonE] = NKCODE_BUTTON_4; // Square - iCadeToKeyMap[iCadeButtonF] = NKCODE_BUTTON_2; // Cross - iCadeToKeyMap[iCadeButtonG] = NKCODE_BUTTON_1; // Triangle - iCadeToKeyMap[iCadeButtonH] = NKCODE_BUTTON_3; // Circle -} - -void ICadeTracker::ButtonDown(iCadeState button) { - if (simulateAnalog && - ((button == iCadeJoystickUp) || - (button == iCadeJoystickDown) || - (button == iCadeJoystickLeft) || - (button == iCadeJoystickRight))) { - AxisInput axis; - switch (button) { - case iCadeJoystickUp : - axis.axisId = JOYSTICK_AXIS_Y; - axis.value = -1.0f; - break; - - case iCadeJoystickDown : - axis.axisId = JOYSTICK_AXIS_Y; - axis.value = 1.0f; - break; - - case iCadeJoystickLeft : - axis.axisId = JOYSTICK_AXIS_X; - axis.value = -1.0f; - break; - - case iCadeJoystickRight : - axis.axisId = JOYSTICK_AXIS_X; - axis.value = 1.0f; - break; - - default: - break; - } - axis.deviceId = DEVICE_ID_PAD_0; - NativeAxis(&axis, 1); - } else { - KeyInput key; - key.flags = KeyInputFlags::DOWN; - key.keyCode = iCadeToKeyMap[button]; - key.deviceId = DEVICE_ID_PAD_0; - NativeKey(key); - } -} - -void ICadeTracker::ButtonUp(iCadeState button) { - if (!iCadeConnectNotified) { - iCadeConnectNotified = true; - KeyMap::NotifyPadConnected(DEVICE_ID_PAD_0, "iCade"); - } - - if (button == iCadeButtonA) { - // Pressing Select twice within 1 second toggles the DPad between - // normal operation and simulating the Analog stick. - if ((lastSelectPress + 1.0f) > time_now_d()) - simulateAnalog = !simulateAnalog; - lastSelectPress = time_now_d(); - } - - if (button == iCadeButtonC) { - // Pressing Start twice within 1 second will take to the Emu menu - if ((lastStartPress + 1.0f) > time_now_d()) { - KeyInput key; - key.flags = KeyInputFlags::DOWN; - key.keyCode = NKCODE_ESCAPE; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - return; - } - lastStartPress = time_now_d(); - } - - if (simulateAnalog && - ((button == iCadeJoystickUp) || - (button == iCadeJoystickDown) || - (button == iCadeJoystickLeft) || - (button == iCadeJoystickRight))) { - AxisInput axis; - switch (button) { - case iCadeJoystickUp : - axis.axisId = JOYSTICK_AXIS_Y; - axis.value = 0.0f; - break; - - case iCadeJoystickDown : - axis.axisId = JOYSTICK_AXIS_Y; - axis.value = 0.0f; - break; - - case iCadeJoystickLeft : - axis.axisId = JOYSTICK_AXIS_X; - axis.value = 0.0f; - break; - - case iCadeJoystickRight : - axis.axisId = JOYSTICK_AXIS_X; - axis.value = 0.0f; - break; - - default: - break; - } - axis.deviceId = DEVICE_ID_PAD_0; - NativeAxis(&axis, 1); - } else { - KeyInput key; - key.flags = KeyInputFlags::UP; - key.keyCode = iCadeToKeyMap[button]; - key.deviceId = DEVICE_ID_PAD_0; - NativeKey(key); - } -} - void ProcessAccelerometerData(CMAccelerometerData *accData) { CMAcceleration acc = accData.acceleration; // INFO_LOG(SYSTEM, "%f %f %f", acc.x, acc.y, acc.z); diff --git a/ios/IAPManager.mm b/ios/IAPManager.mm index c0f44dbc6f..5f6faf7d50 100644 --- a/ios/IAPManager.mm +++ b/ios/IAPManager.mm @@ -199,12 +199,9 @@ static bool SafeStringEqual(NSString *a, NSString *b) { completionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"[IAPManager] Failed to set Gold icon to %@: %@", desiredIcon, error.localizedDescription); - [sharedViewController hideKeyboard]; } else { NSLog(@"Icon update succeeded."); NSLog(@"Current icon name: %@", [[UIApplication sharedApplication] alternateIconName]); - // Here we need to call hideKeyboard. - [sharedViewController hideKeyboard]; } }]; NSLog(@"Icon update to %@ dispatched, waiting for response.", desiredIcon); diff --git a/ios/SceneDelegate.mm b/ios/SceneDelegate.mm index 50246e1c20..87378db36f 100644 --- a/ios/SceneDelegate.mm +++ b/ios/SceneDelegate.mm @@ -171,7 +171,9 @@ static NSString *ExtractGameInfoScheme(NSURL *url) { NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/assets/"]; - NativeInit(argc, argv.data(), cmdLineOptions, documentsPath.UTF8String, bundlePath.UTF8String, NULL); + // Caches the system may clear when space runs low, and the zips ShareFilesAsZip hands to other apps. + NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NativeInit(argc, argv.data(), cmdLineOptions, documentsPath.UTF8String, bundlePath.UTF8String, cachesPath.UTF8String); // If we were cold-started by a library export request, serve it now that // the config (and recent games list) has been loaded by NativeInit. diff --git a/ios/ViewController.h b/ios/ViewController.h index 911c011b31..17a336d222 100644 --- a/ios/ViewController.h +++ b/ios/ViewController.h @@ -3,7 +3,6 @@ #import #import -#import "iCade/iCadeReaderView.h" #import "LocationHelper.h" #import "ViewControllerCommon.h" diff --git a/ios/ViewController.mm b/ios/ViewController.mm index a2a2b85e3b..8db77ce43e 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -138,17 +138,10 @@ PPSSPPBaseViewController *sharedViewController; ERROR_LOG(Log::G3D, "InitSurface failed: %s", errorMessage.c_str()); } - /*self.iCadeView = [[iCadeReaderView alloc] init]; - [self.view addSubview:self.iCadeView]; - self.iCadeView.delegate = self; - self.iCadeView.active = YES;*/ - if ([[GCController controllers] count] > 0) { [self setupController:[[GCController controllers] firstObject]]; } - [self hideKeyboard]; - INFO_LOG(Log::G3D, "Done with viewDidLoad."); } diff --git a/ios/ViewControllerCommon.h b/ios/ViewControllerCommon.h index c42e735271..11f299ee87 100644 --- a/ios/ViewControllerCommon.h +++ b/ios/ViewControllerCommon.h @@ -7,17 +7,17 @@ #import "CameraHelper.h" #import "LocationHelper.h" -#import "iCade/iCadeReaderView.h" @interface PPSSPPBaseViewController : UIViewController< UIImagePickerControllerDelegate, UINavigationControllerDelegate, PHPickerViewControllerDelegate, - CameraFrameDelegate, LocationHandlerDelegate, UIKeyInput, - UIGestureRecognizerDelegate, iCadeEventDelegate> + CameraFrameDelegate, LocationHandlerDelegate, + UIGestureRecognizerDelegate> - (void)hideKeyboard; - (void)showKeyboard; - (void)shareText:(NSString *)text; +- (void)shareFile:(NSURL *)url; - (void)shutdown; - (void)bindDefaultFBO; - (void)startLocation; diff --git a/ios/ViewControllerCommon.mm b/ios/ViewControllerCommon.mm index ce3c1a8bbd..c56b5ca5ae 100644 --- a/ios/ViewControllerCommon.mm +++ b/ios/ViewControllerCommon.mm @@ -14,10 +14,40 @@ #include "Core/System.h" #include "Core/Config.h" +// The target of the soft keyboard. It's a view of its own so the keyboard only comes up when we ask +// for it: UIKit hands first responder back to the view controller whenever something it presented +// (a share sheet, a picker, an alert) goes away, and if that were the text input, up it would come. +@interface KeyboardInputView : UIView +@end + +@implementation KeyboardInputView + +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (BOOL)hasText { + // Otherwise the keyboard wouldn't send backspaces. + return YES; +} + +- (void)insertText:(NSString *)text { + SendKeyboardChars([text UTF8String]); +} + +- (void)deleteBackward { + KeyInput input{}; + input.deviceId = DEVICE_ID_KEYBOARD; + input.flags = KeyInputFlags::DOWN | KeyInputFlags::UP; + input.keyCode = NKCODE_DEL; + NativeKey(input); +} + +@end + @interface PPSSPPBaseViewController () { CameraHelper *cameraHelper; LocationHelper *locationHelper; - ICadeTracker g_iCadeTracker; TouchTracker g_touchTracker; } @@ -30,6 +60,7 @@ @implementation PPSSPPBaseViewController { UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer; CGSize lastLayoutSize_; + KeyboardInputView *keyboardInputView_; } // Strange idiom for generating unique IDs (within the process, at least). @@ -66,8 +97,6 @@ static int GetPickerRequestId(id picker) { if (self) { sharedViewController = self; - g_iCadeTracker.InitKeyMap(); - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidConnect:) name:GCControllerDidConnectNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidDisconnect:) name:GCControllerDidDisconnectNotification object:nil]; @@ -137,7 +166,8 @@ static int GetPickerRequestId(id picker) { - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; INFO_LOG(Log::G3D, "viewDidAppear"); - [self hideKeyboard]; + // For hardware keyboard presses. + [self becomeFirstResponder]; [self updateGesture]; // This needs to be called really late during startup, unfortunately. @@ -146,7 +176,6 @@ static int GetPickerRequestId(id picker) { NSLog(@"viewDidAppear. updating icon"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[IAPManager sharedIAPManager] updateIcon:false]; - [self hideKeyboard]; }); #endif // IOS_APP_STORE } @@ -248,7 +277,6 @@ static int GetPickerRequestId(id picker) { if (results.count == 0) { NSLog(@"User cancelled photo picker"); g_requestManager.PostSystemFailure(requestId); - [self hideKeyboard]; return; } @@ -256,7 +284,6 @@ static int GetPickerRequestId(id picker) { if (![itemProvider canLoadObjectOfClass:[UIImage class]]) { NSLog(@"Photo picker result does not provide UIImage"); g_requestManager.PostSystemFailure(requestId); - [self hideKeyboard]; return; } @@ -268,7 +295,6 @@ static int GetPickerRequestId(id picker) { } else { [self savePickedImage:image toFilename:targetFilename requestId:requestId]; } - [self hideKeyboard]; }); }]; } @@ -282,8 +308,6 @@ static int GetPickerRequestId(id picker) { [self savePickedImage:image toFilename:targetFilename requestId:requestId]; [picker dismissViewControllerAnimated:YES completion:nil]; - - [self hideKeyboard]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { @@ -292,9 +316,7 @@ static int GetPickerRequestId(id picker) { [picker dismissViewControllerAnimated:YES completion:nil]; - // You can also call your custom callback or use the requestId here g_requestManager.PostSystemFailure(requestId); - [self hideKeyboard]; } - (void)handleSwipeFrom:(UIScreenEdgePanGestureRecognizer *)recognizer { @@ -370,6 +392,9 @@ static int GetPickerRequestId(id picker) { [locationHelper setDelegate:self]; self.motionManager = [[CMMotionManager alloc] init]; + + keyboardInputView_ = [[KeyboardInputView alloc] initWithFrame:CGRectZero]; + [self.view addSubview:keyboardInputView_]; } extern float g_safeInsetLeft; @@ -406,7 +431,15 @@ extern float g_safeInsetBottom; } - (void)shareText:(NSString *)text { - NSArray *items = @[text]; + [self shareItems:@[text]]; +} + +- (void)shareFile:(NSURL *)url { + // The share sheet works out the type from the extension. + [self shareItems:@[url]]; +} + +- (void)shareItems:(NSArray *)items { UIActivityViewController *viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; // On iPad, the share sheet is a popover and needs an anchor. viewController.popoverPresentationController.sourceView = self.view; @@ -419,56 +452,25 @@ extern float g_safeInsetBottom; [self setNeedsUpdateOfHomeIndicatorAutoHidden]; } -// The below is inspired by https://stackoverflow.com/questions/7253477/how-to-display-the-iphone-ipad-keyboard-over-a-full-screen-opengl-es-app -// It's a bit limited but good enough. - -- (void)deleteBackward { - KeyInput input{}; - input.deviceId = DEVICE_ID_KEYBOARD; - input.flags = KeyInputFlags::DOWN | KeyInputFlags::UP; - input.keyCode = NKCODE_DEL; - NativeKey(input); - INFO_LOG(Log::System, "Backspace"); -} - -- (void)insertText:(NSString *)text { - std::string str([text UTF8String]); - INFO_LOG(Log::System, "Chars: %s", str.c_str()); - SendKeyboardChars(str); -} - -- (BOOL)hasText { - return true; -} - +// Main thread, like the rest of these. - (void)showKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - INFO_LOG(Log::System, "becomeFirstResponder"); - [self becomeFirstResponder]; - }); + INFO_LOG(Log::System, "showKeyboard"); + [keyboardInputView_ becomeFirstResponder]; } - (void)hideKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - INFO_LOG(Log::System, "resignFirstResponder"); - [self resignFirstResponder]; - }); + if (keyboardInputView_.isFirstResponder) { + INFO_LOG(Log::System, "hideKeyboard"); + [keyboardInputView_ resignFirstResponder]; + // Back to us, for hardware keyboard presses. We don't take text, so no keyboard comes with it. + [self becomeFirstResponder]; + } } - (BOOL)canBecomeFirstResponder { return YES; } -- (void)buttonDown:(iCadeState)button -{ - g_iCadeTracker.ButtonDown(button); -} - -- (void)buttonUp:(iCadeState)button -{ - g_iCadeTracker.ButtonUp(button); -} - - (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event { KeyboardPressesBegan(presses, event); } @@ -520,8 +522,6 @@ extern float g_safeInsetBottom; [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; // The immersive mode setting is per-orientation, so the status bar may need to change along with the rotation. [self setNeedsStatusBarAppearanceUpdate]; - - [self.view endEditing:YES]; // clears any input focus } // Rotations and window resizes land here. UIKit lays out at the final size at the start of a diff --git a/ios/ViewControllerMetal.h b/ios/ViewControllerMetal.h index 33bc1d757a..b554ad954f 100644 --- a/ios/ViewControllerMetal.h +++ b/ios/ViewControllerMetal.h @@ -4,7 +4,6 @@ #pragma once #import "ViewControllerCommon.h" -#import "iCade/iCadeReaderView.h" @interface PPSSPPViewControllerMetal : PPSSPPBaseViewController @end diff --git a/ios/ViewControllerMetal.mm b/ios/ViewControllerMetal.mm index ec759ec740..25ac77825a 100644 --- a/ios/ViewControllerMetal.mm +++ b/ios/ViewControllerMetal.mm @@ -168,7 +168,6 @@ static void VulkanRenderLoop(GraphicsContext *graphicsContext, CAMetalLayer *met - (void)viewDidLoad { [super viewDidLoad]; - [self hideKeyboard]; INFO_LOG(Log::System, "Metal viewDidLoad"); diff --git a/ios/iCade/iCadeReaderView.h b/ios/iCade/iCadeReaderView.h deleted file mode 100755 index 8a6bb586f9..0000000000 --- a/ios/iCade/iCadeReaderView.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (C) 2011 by Stuart Carnie - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -#import -#import "iCadeState.h" - -/* - UP ON,OFF = w,e - RT ON,OFF = d,c - DN ON,OFF = x,z - LT ON,OFF = a,q - A ON,OFF = y,t - B ON,OFF = h,r - C ON,OFF = u,f - D ON,OFF = j,n - E ON,OFF = i,m - F ON,OFF = k,p - G ON,OFF = o,g - H ON,OFF = l,v -*/ - -@protocol iCadeEventDelegate - -@optional -- (void)stateChanged:(iCadeState)state; -- (void)buttonDown:(iCadeState)button; -- (void)buttonUp:(iCadeState)button; - -@end - -@interface iCadeReaderView : UIView { - UIView *inputView; - iCadeState _iCadeState; - id __weak _delegate; - - struct { - bool stateChanged:1; - bool buttonDown:1; - bool buttonUp:1; - } _delegateFlags; -} - -@property (nonatomic, assign) iCadeState iCadeState; -@property (nonatomic, weak) id delegate; -@property (nonatomic, assign) BOOL active; - -@end diff --git a/ios/iCade/iCadeReaderView.m b/ios/iCade/iCadeReaderView.m deleted file mode 100755 index f4cd28bbed..0000000000 --- a/ios/iCade/iCadeReaderView.m +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright (C) 2011 by Stuart Carnie - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -#import "iCadeReaderView.h" - -static const char * const ON_STATES = "wdxayhujikol"; -static const char * const OFF_STATES = "eczqtrfnmpgv"; - -@interface iCadeReaderView() - -- (void)didEnterBackground; -- (void)didBecomeActive; - -@end - -@implementation iCadeReaderView - -@synthesize iCadeState=_iCadeState, delegate=_delegate, active; - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - inputView = [[UIView alloc] initWithFrame:CGRectZero]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; - - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; -} - -- (void)didEnterBackground { - if (self.active) - [self resignFirstResponder]; -} - -- (void)didBecomeActive { - if (self.active) - [self becomeFirstResponder]; -} - -- (BOOL)canBecomeFirstResponder { - return YES; -} - -- (void)setActive:(BOOL)value { - if (active == value) return; - - active = value; - if (active) { - [self becomeFirstResponder]; - } else { - [self resignFirstResponder]; - } -} - -- (UIView*) inputView { - return inputView; -} - -- (void)setDelegate:(id)delegate { - _delegate = delegate; - if (!_delegate) return; - - /*_delegateFlags.stateChanged = [_delegate respondsToSelector:@selector(stateChanged:)]; - _delegateFlags.buttonDown = [_delegate respondsToSelector:@selector(buttonDown:)]; - _delegateFlags.buttonUp = [_delegate respondsToSelector:@selector(buttonUp:)];*/ -} - -/*#pragma mark - -#pragma mark UIKeyInput Protocol Methods - -- (BOOL)hasText { - return NO; -} - -- (void)insertText:(NSString *)text { - - char ch = [text characterAtIndex:0]; - char *p = strchr(ON_STATES, ch); - bool stateChanged = false; - if (p) { - int index = p-ON_STATES; - _iCadeState |= (1 << index); - stateChanged = true; - if (_delegateFlags.buttonDown) { - [_delegate buttonDown:(1 << index)]; - } - } else { - p = strchr(OFF_STATES, ch); - if (p) { - int index = p-OFF_STATES; - _iCadeState &= ~(1 << index); - stateChanged = true; - if (_delegateFlags.buttonUp) { - [_delegate buttonUp:(1 << index)]; - } - } - } - - if (stateChanged && _delegateFlags.stateChanged) { - [_delegate stateChanged:_iCadeState]; - } - - static int cycleResponder = 0; - if (++cycleResponder > 20) { - // necessary to clear a buffer that accumulates internally - cycleResponder = 0; - [self resignFirstResponder]; - [self becomeFirstResponder]; - } -} - -- (void)deleteBackward { - // This space intentionally left blank to complete protocol -}*/ - -@end diff --git a/ios/iCade/iCadeState.h b/ios/iCade/iCadeState.h deleted file mode 100755 index 0355ee917f..0000000000 --- a/ios/iCade/iCadeState.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2011 by Stuart Carnie - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -typedef enum iCadeState { - iCadeJoystickNone = 0x000, - iCadeJoystickUp = 0x001, - iCadeJoystickRight = 0x002, - iCadeJoystickDown = 0x004, - iCadeJoystickLeft = 0x008, - - iCadeJoystickUpRight = iCadeJoystickUp | iCadeJoystickRight, - iCadeJoystickDownRight = iCadeJoystickDown | iCadeJoystickRight, - iCadeJoystickUpLeft = iCadeJoystickUp | iCadeJoystickLeft, - iCadeJoystickDownLeft = iCadeJoystickDown | iCadeJoystickLeft, - - iCadeButtonA = 0x010, - iCadeButtonB = 0x020, - iCadeButtonC = 0x040, - iCadeButtonD = 0x080, - iCadeButtonE = 0x100, - iCadeButtonF = 0x200, - iCadeButtonG = 0x400, - iCadeButtonH = 0x800, - -} iCadeState; diff --git a/ios/main.mm b/ios/main.mm index 1b14d1ac27..f3039a726b 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -377,6 +377,7 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_HAS_KEYBOARD: return true; case SYSPROP_SUPPORTS_SHARE_TEXT: + case SYSPROP_SUPPORTS_SHARE_FILE: return true; case SYSPROP_KEYBOARD_IS_SOFT: // If a hardware keyboard is connected, and we add support, we could return false here. @@ -586,6 +587,20 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string }); return true; } + case SystemRequestType::SHARE_FILE: + { + // param2, the MIME type, isn't needed. The share sheet goes by the extension. + NSString *path = [NSString stringWithUTF8String:param1.c_str()]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + ERROR_LOG(Log::System, "SHARE_FILE: '%s' doesn't exist", param1.c_str()); + return false; + } + NSURL *url = [NSURL fileURLWithPath:path]; + dispatch_async(dispatch_get_main_queue(), ^{ + [sharedViewController shareFile:url]; + }); + return true; + } case SystemRequestType::NOTIFY_UI_EVENT: { const UIEventNotification event = (UIEventNotification)param3;