diff --git a/Makefile.common b/Makefile.common index b759018a44..9272a1738f 100644 --- a/Makefile.common +++ b/Makefile.common @@ -777,8 +777,7 @@ ifeq ($(HAVE_COMPRESSION), 1) endif ifeq ($(HAVE_COCOA),1) - OBJ += apple/OSX/platform.o \ - apple/OSX/settings.o \ + OBJ += apple/OSX/settings.o \ input/drivers/cocoa_input.o \ input/drivers_keyboard/keyboard_event_apple.o \ ui/drivers/ui_cocoa.o \ diff --git a/apple/OSX/platform.m b/apple/OSX/platform.m deleted file mode 100644 index 179bdf4aca..0000000000 --- a/apple/OSX/platform.m +++ /dev/null @@ -1,406 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2013-2014 - Jason Fetters - * Copyright (C) 2011-2015 - Daniel De Matteis - * - * RetroArch 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 Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch 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 RetroArch. - * If not, see . - */ - -#include -#include - -#include "../../ui/drivers/cocoa/cocoa_common.h" -#include "../../input/drivers/cocoa_input.h" -#include "../../frontend/frontend.h" -#include "../../retroarch.h" - -id apple_platform; - -void apple_rarch_exited(void) -{ - [apple_platform unloadingCore]; -} - -@interface RApplication : NSApplication -@end - -@implementation RApplication - -- (void)sendEvent:(NSEvent *)event -{ - NSEventType event_type; - cocoa_input_data_t *apple = NULL; - driver_t *driver = driver_get_ptr(); - [super sendEvent:event]; - - apple = (cocoa_input_data_t*)driver->input_data; - event_type = event.type; - - if (!apple) - return; - - switch ((int32_t)event_type) - { - case NSKeyDown: - case NSKeyUp: - { - NSString* ch = (NSString*)event.characters; - uint32_t character = 0; - uint32_t mod = 0; - - if (ch && ch.length != 0) - { - uint32_t i; - character = [ch characterAtIndex:0]; - - if (event.modifierFlags & NSAlphaShiftKeyMask) - mod |= RETROKMOD_CAPSLOCK; - if (event.modifierFlags & NSShiftKeyMask) - mod |= RETROKMOD_SHIFT; - if (event.modifierFlags & NSControlKeyMask) - mod |= RETROKMOD_CTRL; - if (event.modifierFlags & NSAlternateKeyMask) - mod |= RETROKMOD_ALT; - if (event.modifierFlags & NSCommandKeyMask) - mod |= RETROKMOD_META; - if (event.modifierFlags & NSNumericPadKeyMask) - mod |= RETROKMOD_NUMLOCK; - - for (i = 1; i < ch.length; i++) - cocoa_input_keyboard_event(event_type == NSKeyDown, - 0, [ch characterAtIndex:i], mod, RETRO_DEVICE_KEYBOARD); - } - - cocoa_input_keyboard_event(event_type == NSKeyDown, - event.keyCode, character, mod, RETRO_DEVICE_KEYBOARD); - } - break; - case NSFlagsChanged: - { - static uint32_t old_flags = 0; - uint32_t new_flags = event.modifierFlags; - bool down = (new_flags & old_flags) == old_flags; - old_flags = new_flags; - - cocoa_input_keyboard_event(down, event.keyCode, - 0, event.modifierFlags, RETRO_DEVICE_KEYBOARD); - } - break; - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - { - NSPoint pos; - /* Relative */ - apple->mouse_x = event.deltaX; - apple->mouse_y = event.deltaY; - - /* Absolute */ - pos = [[RAGameView get] convertPoint:[event locationInWindow] fromView:nil]; - apple->touches[0].screen_x = pos.x; - apple->touches[0].screen_y = pos.y; - } - break; - case NSScrollWheel: - /* TODO/FIXME - properly implement. */ - break; - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - apple->mouse_buttons |= 1 << event.buttonNumber; - apple->touch_count = 1; - break; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - apple->mouse_buttons &= ~(1 << event.buttonNumber); - apple->touch_count = 0; - break; - } -} - -@end - -static int waiting_argc; -static char** waiting_argv; - -@interface RetroArch_OSX() -@property (nonatomic, retain) NSWindowController* settingsWindow; -@end - -@implementation RetroArch_OSX - -@synthesize window = _window; -@synthesize settingsWindow = _settingsWindow; - -- (void)dealloc -{ - [_window release]; - [_settingsWindow release]; - [super dealloc]; -} - -+ (RetroArch_OSX*)get -{ - return (RetroArch_OSX*)[[NSApplication sharedApplication] delegate]; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - apple_platform = self; - - -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - [self.window setCollectionBehavior:[self.window collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; -#endif - - [self.window setAcceptsMouseMovedEvents: YES]; - - [[RAGameView get] setFrame: [[self.window contentView] bounds]]; - [[self.window contentView] setAutoresizesSubviews:YES]; - [[self.window contentView] addSubview:[RAGameView get]]; - [self.window makeFirstResponder:[RAGameView get]]; - - self.settingsWindow = [[[NSWindowController alloc] initWithWindowNibName:BOXSTRING("Settings")] autorelease]; - - [apple_platform loadingCore:nil withFile:nil]; - - if (rarch_main(waiting_argc, waiting_argv)) - apple_rarch_exited(); - - waiting_argc = 0; -} - -static void poll_iteration(void) -{ - NSEvent *event = NULL; - driver_t *driver = driver_get_ptr(); - cocoa_input_data_t *apple = (cocoa_input_data_t*)driver->input_data; - - if (!apple) - return; - - apple->mouse_x = 0; - apple->mouse_y = 0; - - do - { - event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; - - [NSApp sendEvent: event]; - }while(event != nil); -} - -- (void) rarch_main -{ - int ret = 0; - while (ret != -1) - { - poll_iteration(); - ret = rarch_main_iterate(); - while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, FALSE) == kCFRunLoopRunHandledSource); - } - - main_exit(NULL); -} - -- (void) apple_start_iteration -{ - [self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO]; -} - -- (void) apple_stop_iteration -{ -} - -- (void)applicationDidBecomeActive:(NSNotification *)notification -{ - [self apple_start_iteration]; -} - -- (void)applicationWillResignActive:(NSNotification *)notification -{ - [self apple_stop_iteration]; -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication -{ - return YES; -} - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - NSApplicationTerminateReply reply = NSTerminateNow; - global_t *global = global_get_ptr(); - - if (global && global->main_is_init) - reply = NSTerminateCancel; - - event_command(EVENT_CMD_QUIT); - - return reply; -} - - -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames -{ - if (filenames.count == 1 && [filenames objectAtIndex:0]) - { - global_t *global = global_get_ptr(); - NSString *__core = [filenames objectAtIndex:0]; - const char *core_name = global ? global->menu.info.library_name : NULL; - - if (global) - strlcpy(global->fullpath, __core.UTF8String, sizeof(global->fullpath)); - - if (core_name) - event_command(EVENT_CMD_LOAD_CONTENT); - - [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; - } - else - { - apple_display_alert("Cannot open multiple files", "RetroArch"); - [sender replyToOpenOrPrint:NSApplicationDelegateReplyFailure]; - } -} - -- (void)openDocument:(id)sender -{ - NSOpenPanel* panel = (NSOpenPanel*)[NSOpenPanel openPanel]; -#if defined(MAC_OS_X_VERSION_10_6) - [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) - { - [[NSApplication sharedApplication] stopModal]; - - if (result == NSOKButton && panel.URL) - { - global_t *global = global_get_ptr(); - NSURL *url = (NSURL*)panel.URL; - NSString *__core = url.path; - const char *core_name = global ? global->menu.info.library_name : NULL; - - if (global) - strlcpy(global->fullpath, __core.UTF8String, sizeof(global->fullpath)); - - if (core_name) - event_command(EVENT_CMD_LOAD_CONTENT); - else - [self performSelector:@selector(chooseCore) withObject:nil afterDelay:.5f]; - } - }]; -#else - [panel beginSheetForDirectory:nil file:nil modalForWindopw:[self window] modalDelegate:self didEndSelector:@selector(didEndSaveSheet:returnCode:contextInfo:) contextInfo:NULL]; -#endif - [[NSApplication sharedApplication] runModalForWindow:panel]; -} - -- (void)loadingCore:(const NSString*)core withFile:(const char*)file -{ - if (file) - [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:BOXSTRING(file)]]; -} - -- (void)unloadingCore -{ - [[NSApplication sharedApplication] terminate:nil]; -} - -- (IBAction)showCoresDirectory:(id)sender -{ - settings_t *settings = config_get_ptr(); - [[NSWorkspace sharedWorkspace] openFile:BOXSTRING(settings->libretro_directory)]; -} - -- (IBAction)showPreferences:(id)sender -{ - [NSApp runModalForWindow:[self.settingsWindow window]]; -} - -- (IBAction)basicEvent:(id)sender -{ - unsigned cmd; - unsigned sender_tag = (unsigned)[sender tag]; - global_t *global = global_get_ptr(); - - RARCH_LOG("Gets here, sender tag is: %d\n", sender_tag); - - switch (sender_tag) - { - case 1: - cmd = EVENT_CMD_RESET; - break; - case 2: - cmd = EVENT_CMD_LOAD_STATE; - break; - case 3: - cmd = EVENT_CMD_SAVE_STATE; - break; - case 4: - cmd = EVENT_CMD_DISK_EJECT_TOGGLE; - break; - case 5: - cmd = EVENT_CMD_DISK_PREV; - break; - case 6: - cmd = EVENT_CMD_DISK_NEXT; - break; - case 7: - cmd = EVENT_CMD_GRAB_MOUSE_TOGGLE; - break; - case 8: - cmd = EVENT_CMD_MENU_TOGGLE; - break; - case 9: - cmd = EVENT_CMD_PAUSE_TOGGLE; - break; - case 20: - cmd = EVENT_CMD_FULLSCREEN_TOGGLE; - break; - default: - cmd = EVENT_CMD_NONE; - break; - } - - if (sender_tag >= 10 && sender_tag <= 19) - { - unsigned idx = (sender_tag - (10-1)); - global->pending.windowed_scale = idx; - cmd = EVENT_CMD_RESIZE_WINDOWED_SCALE; - } - - event_command(cmd); -} - -- (void)alertDidEnd:(NSAlert *)alert returnCode:(int32_t)returnCode contextInfo:(void *)contextInfo -{ - [[NSApplication sharedApplication] stopModal]; -} - -@end - -int main(int argc, char *argv[]) -{ - int i; - for (i = 0; i < argc; i ++) - { - if (strcmp(argv[i], "--") == 0) - { - waiting_argc = argc - i; - waiting_argv = argv + i; - break; - } - } - - return NSApplicationMain(argc, (const char **) argv); -} - diff --git a/apple/iOS/platform.m b/apple/iOS/platform.m deleted file mode 100644 index a7b00c30f1..0000000000 --- a/apple/iOS/platform.m +++ /dev/null @@ -1,454 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2013-2014 - Jason Fetters - * Copyright (C) 2011-2015 - Daniel De Matteis - * - * RetroArch 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 Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch 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 RetroArch. - * If not, see . - */ - -#include - -#include "../../ui/drivers/cocoa/cocoa_common.h" -#include "../../input/drivers/cocoa_input.h" -#include "../../settings.h" -#ifdef HAVE_MFI -#include "../../input/drivers_hid/mfi_hid.h" -#endif - -#include "../../input/drivers_hid/btstack_hid.h" -#include "../../frontend/frontend.h" - -id apple_platform; -static CFRunLoopObserverRef iterate_observer; - -void main_exit_save_config(void); - -static void rarch_draw(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) -{ - runloop_t *runloop = rarch_main_get_ptr(); - int ret = 0; - bool iterate = iterate_observer && !runloop->is_paused; - - if (!iterate) - return; - - ret = rarch_main_iterate(); - - if (ret == -1) - { - main_exit_save_config(); - main_exit(NULL); - return; - } - - if (runloop->is_idle) - return; - CFRunLoopWakeUp(CFRunLoopGetMain()); -} - -void apple_rarch_exited(void) -{ - [apple_platform unloadingCore]; -} - -apple_frontend_settings_t apple_frontend_settings; - -enum frontend_powerstate ios_get_powerstate(int *seconds, int *percent) -{ - float level; - enum frontend_powerstate ret = FRONTEND_POWERSTATE_NONE; - UIDevice *uidev = [UIDevice currentDevice]; - - if (!uidev) - return ret; - - [uidev setBatteryMonitoringEnabled:true]; - - switch (uidev.batteryState) - { - case UIDeviceBatteryStateCharging: - ret = FRONTEND_POWERSTATE_CHARGING; - break; - case UIDeviceBatteryStateFull: - ret = FRONTEND_POWERSTATE_CHARGED; - break; - case UIDeviceBatteryStateUnplugged: - ret = FRONTEND_POWERSTATE_ON_POWER_SOURCE; - break; - case UIDeviceBatteryStateUnknown: - break; - } - - level = uidev.batteryLevel; - - *percent = ((level < 0.0f) ? -1 : ((int)((level * 100) + 0.5f))); - - [uidev setBatteryMonitoringEnabled:false]; - - return ret; -} - -void get_ios_version(int *major, int *minor) -{ - NSArray *decomposed_os_version = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; - - if (major && decomposed_os_version.count > 0) - *major = [decomposed_os_version[0] integerValue]; - if (minor && decomposed_os_version.count > 1) - *minor = [decomposed_os_version[1] integerValue]; -} - -extern float cocoagl_gfx_ctx_get_native_scale(void); - -/* Input helpers: This is kept here because it needs ObjC */ -static void handle_touch_event(NSArray* touches) -{ - unsigned i; - driver_t *driver = driver_get_ptr(); - cocoa_input_data_t *apple = (cocoa_input_data_t*)driver->input_data; - float scale = cocoagl_gfx_ctx_get_native_scale(); - - if (!apple) - return; - - apple->touch_count = 0; - - for (i = 0; i < touches.count && (apple->touch_count < MAX_TOUCHES); i++) - { - CGPoint coord; - UITouch *touch = [touches objectAtIndex:i]; - - if (touch.view != [RAGameView get].view) - continue; - - coord = [touch locationInView:[touch view]]; - - if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) - { - apple->touches[apple->touch_count ].screen_x = coord.x * scale; - apple->touches[apple->touch_count ++].screen_y = coord.y * scale; - } - } -} - -// iO7 Keyboard support -@interface UIEvent(iOS7Keyboard) -@property(readonly, nonatomic) long long _keyCode; -@property(readonly, nonatomic) _Bool _isKeyDown; -@property(retain, nonatomic) NSString *_privateInput; -@property(nonatomic) long long _modifierFlags; -- (struct __IOHIDEvent { }*)_hidEvent; -@end - -@interface UIApplication(iOS7Keyboard) -- (id)_keyCommandForEvent:(UIEvent*)event; -@end - -@interface RApplication : UIApplication -@end - -@implementation RApplication - -/* Keyboard handler for iOS 7. */ - -/* This is copied here as it isn't - * defined in any standard iOS header */ -enum -{ - NSAlphaShiftKeyMask = 1 << 16, - NSShiftKeyMask = 1 << 17, - NSControlKeyMask = 1 << 18, - NSAlternateKeyMask = 1 << 19, - NSCommandKeyMask = 1 << 20, - NSNumericPadKeyMask = 1 << 21, - NSHelpKeyMask = 1 << 22, - NSFunctionKeyMask = 1 << 23, - NSDeviceIndependentModifierFlagsMask = 0xffff0000U -}; - -- (id)_keyCommandForEvent:(UIEvent*)event -{ - /* This gets called twice with the same timestamp - * for each keypress, that's fine for polling - * but is bad for business with events. */ - static double last_time_stamp; - - if (last_time_stamp == event.timestamp) - return [super _keyCommandForEvent:event]; - last_time_stamp = event.timestamp; - - /* If the _hidEvent is null, [event _keyCode] will crash. - * (This happens with the on screen keyboard). */ - if (event._hidEvent) - { - NSString *ch = (NSString*)event._privateInput; - uint32_t character = 0; - uint32_t mod = 0; - - mod |= (event._modifierFlags & NSAlphaShiftKeyMask) ? RETROKMOD_CAPSLOCK : 0; - mod |= (event._modifierFlags & NSShiftKeyMask ) ? RETROKMOD_SHIFT : 0; - mod |= (event._modifierFlags & NSControlKeyMask ) ? RETROKMOD_CTRL : 0; - mod |= (event._modifierFlags & NSAlternateKeyMask ) ? RETROKMOD_ALT : 0; - mod |= (event._modifierFlags & NSCommandKeyMask ) ? RETROKMOD_META : 0; - mod |= (event._modifierFlags & NSNumericPadKeyMask) ? RETROKMOD_NUMLOCK : 0; - - if (ch && ch.length != 0) - { - unsigned i; - character = [ch characterAtIndex:0]; - - cocoa_input_keyboard_event(event._isKeyDown, - (uint32_t)event._keyCode, 0, mod, - RETRO_DEVICE_KEYBOARD); - - for (i = 1; i < ch.length; i++) - cocoa_input_keyboard_event(event._isKeyDown, - 0, [ch characterAtIndex:i], mod, - RETRO_DEVICE_KEYBOARD); - } - - cocoa_input_keyboard_event(event._isKeyDown, - (uint32_t)event._keyCode, character, mod, - RETRO_DEVICE_KEYBOARD); - } - - return [super _keyCommandForEvent:event]; -} - -#define GSEVENT_TYPE_KEYDOWN 10 -#define GSEVENT_TYPE_KEYUP 11 - -- (void)sendEvent:(UIEvent *)event -{ - int major, minor; - [super sendEvent:event]; - - if (event.allTouches.count) - handle_touch_event(event.allTouches.allObjects); - - get_ios_version(&major, &minor); - - if ((major < 7) && [event respondsToSelector:@selector(_gsEvent)]) - { - /* Keyboard event hack for iOS versions prior to iOS 7. - * - * Derived from: - * http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html - */ - const uint8_t *eventMem = objc_unretainedPointer([event performSelector:@selector(_gsEvent)]); - int eventType = eventMem ? *(int*)&eventMem[8] : 0; - - switch (eventType) - { - case GSEVENT_TYPE_KEYDOWN: - case GSEVENT_TYPE_KEYUP: - cocoa_input_keyboard_event(eventType == GSEVENT_TYPE_KEYDOWN, - *(uint16_t*)&eventMem[0x3C], 0, 0, RETRO_DEVICE_KEYBOARD); - break; - } - } -} - -@end - -@implementation RetroArch_iOS - -+ (RetroArch_iOS*)get -{ - return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate]; -} - -- (void)applicationDidFinishLaunching:(UIApplication *)application -{ - apple_platform = self; - - [self setDelegate:self]; - - if (rarch_main(0, NULL)) - apple_rarch_exited(); - - /* Setup window */ - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - [self.window makeKeyAndVisible]; - - [self pushViewController:[RAMainMenu new] animated:YES]; - - [apple_platform loadingCore:nil withFile:nil]; - - if (rarch_main(0, NULL)) - apple_rarch_exited(); - -#ifdef HAVE_MFI - apple_gamecontroller_init(); -#endif - - [self apple_start_iteration]; -} - -- (void) apple_start_iteration -{ - if (iterate_observer) - return; - - iterate_observer = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting, - true, 0, rarch_draw, 0); - CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); -} - -- (void) apple_stop_iteration -{ - if (!iterate_observer) - return; - - CFRunLoopObserverInvalidate(iterate_observer); - CFRelease(iterate_observer); - iterate_observer = NULL; -} - -- (void)applicationDidEnterBackground:(UIApplication *)application -{ - -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - [self apple_stop_iteration]; -} - -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - settings_t *settings = config_get_ptr(); - - if (settings->ui.companion_start_on_boot) - return; - - [self showGameView]; -} - -- (void)applicationWillResignActive:(UIApplication *)application -{ - dispatch_async(dispatch_get_main_queue(), - ^{ - main_exit_save_config(); - }); - [self showPauseMenu: self]; -} - --(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation -{ - NSString *filename = (NSString*)url.path.lastPathComponent; - NSError *error = nil; - - [[NSFileManager defaultManager] moveItemAtPath:[url path] toPath:[self.documentsDirectory stringByAppendingPathComponent:filename] error:&error]; - - if (error) - printf("%s\n", [[error description] UTF8String]); - - return true; -} - -- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated -{ - cocoa_input_reset_icade_buttons(); - [self setToolbarHidden:![[viewController toolbarItems] count] animated:YES]; - - [self refreshSystemConfig]; -} - -- (void)showGameView -{ - runloop_t *runloop = rarch_main_get_ptr(); - - [self popToRootViewControllerAnimated:NO]; - [self setToolbarHidden:true animated:NO]; - [[UIApplication sharedApplication] setStatusBarHidden:true withAnimation:UIStatusBarAnimationNone]; - [[UIApplication sharedApplication] setIdleTimerDisabled:true]; - [self.window setRootViewController:[RAGameView get]]; - - runloop->is_paused = false; - runloop->is_idle = false; - runloop->ui_companion_is_on_foreground = false; -} - -- (IBAction)showPauseMenu:(id)sender -{ - runloop_t *runloop = rarch_main_get_ptr(); - - if (runloop) - { - runloop->is_paused = true; - runloop->is_idle = true; - runloop->ui_companion_is_on_foreground = true; - } - - [[UIApplication sharedApplication] setStatusBarHidden:false withAnimation:UIStatusBarAnimationNone]; - [[UIApplication sharedApplication] setIdleTimerDisabled:false]; - [self.window setRootViewController:self]; -} - -- (void)loadingCore:(NSString*)core withFile:(const char*)file -{ - btpad_set_inquiry_state(false); - - [self refreshSystemConfig]; - [self showGameView]; -} - -- (void)toggleUI -{ - runloop_t *runloop = rarch_main_get_ptr(); - - if (runloop->ui_companion_is_on_foreground) - { - [self showGameView]; - } - else - { - [self showPauseMenu:self]; - } -} - -- (void)unloadingCore -{ - [self showPauseMenu:self]; - btpad_set_inquiry_state(true); -} - -- (void)refreshSystemConfig -{ - bool small_keyboard, is_icade, is_btstack; - - /* Get enabled orientations */ - apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskAll; - - if (!strcmp(apple_frontend_settings.orientations, "landscape")) - apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskLandscape; - else if (!strcmp(apple_frontend_settings.orientations, "portrait")) - apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; - - /* Set bluetooth mode */ - small_keyboard = !(strcmp(apple_frontend_settings.bluetooth_mode, "small_keyboard")); - is_icade = !(strcmp(apple_frontend_settings.bluetooth_mode, "icade")); - is_btstack = !(strcmp(apple_frontend_settings.bluetooth_mode, "btstack")); - - cocoa_input_enable_small_keyboard(small_keyboard); - cocoa_input_enable_icade(is_icade); - btstack_set_poweron(is_btstack); -} - -@end - -int main(int argc, char *argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class])); - } -} diff --git a/griffin/griffin_objc.m b/griffin/griffin_objc.m index b58f6b43b7..e628fbe1b4 100644 --- a/griffin/griffin_objc.m +++ b/griffin/griffin_objc.m @@ -34,7 +34,6 @@ #if defined(HAVE_COCOATOUCH) #if TARGET_OS_IPHONE -#include "../apple/iOS/platform.m" #include "../apple/iOS/menu.m" #include "../apple/iOS/browser.m" @@ -42,7 +41,6 @@ #endif #elif defined(HAVE_COCOA) -#include "../apple/OSX/platform.m" #include "../apple/OSX/settings.m" #include "../ui/drivers/ui_cocoa.m" diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index bc57686e56..2fbb7b58a8 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -1,4 +1,5 @@ /* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters * Copyright (C) 2011-2015 - Daniel De Matteis * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -13,15 +14,402 @@ * If not, see . */ -#include "cocoa/cocoa_common.h" +#include #include -#include #include #include #include +#include #include + +#include "cocoa/cocoa_common.h" #include "../ui_companion_driver.h" +#include "../input/drivers/cocoa_input.h" +#include "../frontend/frontend.h" +#include "../retroarch.h" + +id apple_platform; + +void apple_rarch_exited(void) +{ + [apple_platform unloadingCore]; +} + +@interface RApplication : NSApplication +@end + +@implementation RApplication + +- (void)sendEvent:(NSEvent *)event +{ + NSEventType event_type; + cocoa_input_data_t *apple = NULL; + driver_t *driver = driver_get_ptr(); + [super sendEvent:event]; + + apple = (cocoa_input_data_t*)driver->input_data; + event_type = event.type; + + if (!apple) + return; + + switch ((int32_t)event_type) + { + case NSKeyDown: + case NSKeyUp: + { + NSString* ch = (NSString*)event.characters; + uint32_t character = 0; + uint32_t mod = 0; + + if (ch && ch.length != 0) + { + uint32_t i; + character = [ch characterAtIndex:0]; + + if (event.modifierFlags & NSAlphaShiftKeyMask) + mod |= RETROKMOD_CAPSLOCK; + if (event.modifierFlags & NSShiftKeyMask) + mod |= RETROKMOD_SHIFT; + if (event.modifierFlags & NSControlKeyMask) + mod |= RETROKMOD_CTRL; + if (event.modifierFlags & NSAlternateKeyMask) + mod |= RETROKMOD_ALT; + if (event.modifierFlags & NSCommandKeyMask) + mod |= RETROKMOD_META; + if (event.modifierFlags & NSNumericPadKeyMask) + mod |= RETROKMOD_NUMLOCK; + + for (i = 1; i < ch.length; i++) + cocoa_input_keyboard_event(event_type == NSKeyDown, + 0, [ch characterAtIndex:i], mod, RETRO_DEVICE_KEYBOARD); + } + + cocoa_input_keyboard_event(event_type == NSKeyDown, + event.keyCode, character, mod, RETRO_DEVICE_KEYBOARD); + } + break; + case NSFlagsChanged: + { + static uint32_t old_flags = 0; + uint32_t new_flags = event.modifierFlags; + bool down = (new_flags & old_flags) == old_flags; + old_flags = new_flags; + + cocoa_input_keyboard_event(down, event.keyCode, + 0, event.modifierFlags, RETRO_DEVICE_KEYBOARD); + } + break; + case NSMouseMoved: + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + { + NSPoint pos; + /* Relative */ + apple->mouse_x = event.deltaX; + apple->mouse_y = event.deltaY; + + /* Absolute */ + pos = [[RAGameView get] convertPoint:[event locationInWindow] fromView:nil]; + apple->touches[0].screen_x = pos.x; + apple->touches[0].screen_y = pos.y; + } + break; + case NSScrollWheel: + /* TODO/FIXME - properly implement. */ + break; + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + apple->mouse_buttons |= 1 << event.buttonNumber; + apple->touch_count = 1; + break; + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + apple->mouse_buttons &= ~(1 << event.buttonNumber); + apple->touch_count = 0; + break; + } +} + +@end + +static int waiting_argc; +static char** waiting_argv; + +@interface RetroArch_OSX() +@property (nonatomic, retain) NSWindowController* settingsWindow; +@end + +@implementation RetroArch_OSX + +@synthesize window = _window; +@synthesize settingsWindow = _settingsWindow; + +- (void)dealloc +{ + [_window release]; + [_settingsWindow release]; + [super dealloc]; +} + ++ (RetroArch_OSX*)get +{ + return (RetroArch_OSX*)[[NSApplication sharedApplication] delegate]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + apple_platform = self; + + +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + [self.window setCollectionBehavior:[self.window collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; +#endif + + [self.window setAcceptsMouseMovedEvents: YES]; + + [[RAGameView get] setFrame: [[self.window contentView] bounds]]; + [[self.window contentView] setAutoresizesSubviews:YES]; + [[self.window contentView] addSubview:[RAGameView get]]; + [self.window makeFirstResponder:[RAGameView get]]; + + self.settingsWindow = [[[NSWindowController alloc] initWithWindowNibName:BOXSTRING("Settings")] autorelease]; + + [apple_platform loadingCore:nil withFile:nil]; + + if (rarch_main(waiting_argc, waiting_argv)) + apple_rarch_exited(); + + waiting_argc = 0; +} + +static void poll_iteration(void) +{ + NSEvent *event = NULL; + driver_t *driver = driver_get_ptr(); + cocoa_input_data_t *apple = (cocoa_input_data_t*)driver->input_data; + + if (!apple) + return; + + apple->mouse_x = 0; + apple->mouse_y = 0; + + do + { + event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + + [NSApp sendEvent: event]; + }while(event != nil); +} + +- (void) rarch_main +{ + int ret = 0; + while (ret != -1) + { + poll_iteration(); + ret = rarch_main_iterate(); + while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, FALSE) == kCFRunLoopRunHandledSource); + } + + main_exit(NULL); +} + +- (void) apple_start_iteration +{ + [self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO]; +} + +- (void) apple_stop_iteration +{ +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification +{ + [self apple_start_iteration]; +} + +- (void)applicationWillResignActive:(NSNotification *)notification +{ + [self apple_stop_iteration]; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication +{ + return YES; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + NSApplicationTerminateReply reply = NSTerminateNow; + global_t *global = global_get_ptr(); + + if (global && global->main_is_init) + reply = NSTerminateCancel; + + event_command(EVENT_CMD_QUIT); + + return reply; +} + + +- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames +{ + if (filenames.count == 1 && [filenames objectAtIndex:0]) + { + global_t *global = global_get_ptr(); + NSString *__core = [filenames objectAtIndex:0]; + const char *core_name = global ? global->menu.info.library_name : NULL; + + if (global) + strlcpy(global->fullpath, __core.UTF8String, sizeof(global->fullpath)); + + if (core_name) + event_command(EVENT_CMD_LOAD_CONTENT); + + [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; + } + else + { + apple_display_alert("Cannot open multiple files", "RetroArch"); + [sender replyToOpenOrPrint:NSApplicationDelegateReplyFailure]; + } +} + +- (void)openDocument:(id)sender +{ + NSOpenPanel* panel = (NSOpenPanel*)[NSOpenPanel openPanel]; +#if defined(MAC_OS_X_VERSION_10_6) + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) + { + [[NSApplication sharedApplication] stopModal]; + + if (result == NSOKButton && panel.URL) + { + global_t *global = global_get_ptr(); + NSURL *url = (NSURL*)panel.URL; + NSString *__core = url.path; + const char *core_name = global ? global->menu.info.library_name : NULL; + + if (global) + strlcpy(global->fullpath, __core.UTF8String, sizeof(global->fullpath)); + + if (core_name) + event_command(EVENT_CMD_LOAD_CONTENT); + else + [self performSelector:@selector(chooseCore) withObject:nil afterDelay:.5f]; + } + }]; +#else + [panel beginSheetForDirectory:nil file:nil modalForWindopw:[self window] modalDelegate:self didEndSelector:@selector(didEndSaveSheet:returnCode:contextInfo:) contextInfo:NULL]; +#endif + [[NSApplication sharedApplication] runModalForWindow:panel]; +} + +- (void)loadingCore:(const NSString*)core withFile:(const char*)file +{ + if (file) + [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:BOXSTRING(file)]]; +} + +- (void)unloadingCore +{ + [[NSApplication sharedApplication] terminate:nil]; +} + +- (IBAction)showCoresDirectory:(id)sender +{ + settings_t *settings = config_get_ptr(); + [[NSWorkspace sharedWorkspace] openFile:BOXSTRING(settings->libretro_directory)]; +} + +- (IBAction)showPreferences:(id)sender +{ + [NSApp runModalForWindow:[self.settingsWindow window]]; +} + +- (IBAction)basicEvent:(id)sender +{ + unsigned cmd; + unsigned sender_tag = (unsigned)[sender tag]; + global_t *global = global_get_ptr(); + + RARCH_LOG("Gets here, sender tag is: %d\n", sender_tag); + + switch (sender_tag) + { + case 1: + cmd = EVENT_CMD_RESET; + break; + case 2: + cmd = EVENT_CMD_LOAD_STATE; + break; + case 3: + cmd = EVENT_CMD_SAVE_STATE; + break; + case 4: + cmd = EVENT_CMD_DISK_EJECT_TOGGLE; + break; + case 5: + cmd = EVENT_CMD_DISK_PREV; + break; + case 6: + cmd = EVENT_CMD_DISK_NEXT; + break; + case 7: + cmd = EVENT_CMD_GRAB_MOUSE_TOGGLE; + break; + case 8: + cmd = EVENT_CMD_MENU_TOGGLE; + break; + case 9: + cmd = EVENT_CMD_PAUSE_TOGGLE; + break; + case 20: + cmd = EVENT_CMD_FULLSCREEN_TOGGLE; + break; + default: + cmd = EVENT_CMD_NONE; + break; + } + + if (sender_tag >= 10 && sender_tag <= 19) + { + unsigned idx = (sender_tag - (10-1)); + global->pending.windowed_scale = idx; + cmd = EVENT_CMD_RESIZE_WINDOWED_SCALE; + } + + event_command(cmd); +} + +- (void)alertDidEnd:(NSAlert *)alert returnCode:(int32_t)returnCode contextInfo:(void *)contextInfo +{ + [[NSApplication sharedApplication] stopModal]; +} + +@end + +int main(int argc, char *argv[]) +{ + int i; + for (i = 0; i < argc; i ++) + { + if (strcmp(argv[i], "--") == 0) + { + waiting_argc = argc - i; + waiting_argv = argv + i; + break; + } + } + + return NSApplicationMain(argc, (const char **) argv); +} typedef struct ui_companion_cocoa { diff --git a/ui/drivers/ui_cocoatouch.m b/ui/drivers/ui_cocoatouch.m index b5ac68ac5b..1ed008e303 100644 --- a/ui/drivers/ui_cocoatouch.m +++ b/ui/drivers/ui_cocoatouch.m @@ -13,15 +13,453 @@ * If not, see . */ -#include "cocoa/cocoa_common.h" #include -#include #include #include #include +#include + #include + +#include "cocoa/cocoa_common.h" #include "../ui_companion_driver.h" +#include "../../input/drivers/cocoa_input.h" +#include "../../settings.h" + +#ifdef HAVE_MFI +#include "../../input/drivers_hid/mfi_hid.h" +#endif + +#include "../../input/drivers_hid/btstack_hid.h" +#include "../../frontend/frontend.h" + +id apple_platform; +static CFRunLoopObserverRef iterate_observer; + +void main_exit_save_config(void); + +static void rarch_draw(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) +{ + runloop_t *runloop = rarch_main_get_ptr(); + int ret = 0; + bool iterate = iterate_observer && !runloop->is_paused; + + if (!iterate) + return; + + ret = rarch_main_iterate(); + + if (ret == -1) + { + main_exit_save_config(); + main_exit(NULL); + return; + } + + if (runloop->is_idle) + return; + CFRunLoopWakeUp(CFRunLoopGetMain()); +} + +void apple_rarch_exited(void) +{ + [apple_platform unloadingCore]; +} + +apple_frontend_settings_t apple_frontend_settings; + +enum frontend_powerstate ios_get_powerstate(int *seconds, int *percent) +{ + float level; + enum frontend_powerstate ret = FRONTEND_POWERSTATE_NONE; + UIDevice *uidev = [UIDevice currentDevice]; + + if (!uidev) + return ret; + + [uidev setBatteryMonitoringEnabled:true]; + + switch (uidev.batteryState) + { + case UIDeviceBatteryStateCharging: + ret = FRONTEND_POWERSTATE_CHARGING; + break; + case UIDeviceBatteryStateFull: + ret = FRONTEND_POWERSTATE_CHARGED; + break; + case UIDeviceBatteryStateUnplugged: + ret = FRONTEND_POWERSTATE_ON_POWER_SOURCE; + break; + case UIDeviceBatteryStateUnknown: + break; + } + + level = uidev.batteryLevel; + + *percent = ((level < 0.0f) ? -1 : ((int)((level * 100) + 0.5f))); + + [uidev setBatteryMonitoringEnabled:false]; + + return ret; +} + +void get_ios_version(int *major, int *minor) +{ + NSArray *decomposed_os_version = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; + + if (major && decomposed_os_version.count > 0) + *major = [decomposed_os_version[0] integerValue]; + if (minor && decomposed_os_version.count > 1) + *minor = [decomposed_os_version[1] integerValue]; +} + +extern float cocoagl_gfx_ctx_get_native_scale(void); + +/* Input helpers: This is kept here because it needs ObjC */ +static void handle_touch_event(NSArray* touches) +{ + unsigned i; + driver_t *driver = driver_get_ptr(); + cocoa_input_data_t *apple = (cocoa_input_data_t*)driver->input_data; + float scale = cocoagl_gfx_ctx_get_native_scale(); + + if (!apple) + return; + + apple->touch_count = 0; + + for (i = 0; i < touches.count && (apple->touch_count < MAX_TOUCHES); i++) + { + CGPoint coord; + UITouch *touch = [touches objectAtIndex:i]; + + if (touch.view != [RAGameView get].view) + continue; + + coord = [touch locationInView:[touch view]]; + + if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) + { + apple->touches[apple->touch_count ].screen_x = coord.x * scale; + apple->touches[apple->touch_count ++].screen_y = coord.y * scale; + } + } +} + +// iO7 Keyboard support +@interface UIEvent(iOS7Keyboard) +@property(readonly, nonatomic) long long _keyCode; +@property(readonly, nonatomic) _Bool _isKeyDown; +@property(retain, nonatomic) NSString *_privateInput; +@property(nonatomic) long long _modifierFlags; +- (struct __IOHIDEvent { }*)_hidEvent; +@end + +@interface UIApplication(iOS7Keyboard) +- (id)_keyCommandForEvent:(UIEvent*)event; +@end + +@interface RApplication : UIApplication +@end + +@implementation RApplication + +/* Keyboard handler for iOS 7. */ + +/* This is copied here as it isn't + * defined in any standard iOS header */ +enum +{ + NSAlphaShiftKeyMask = 1 << 16, + NSShiftKeyMask = 1 << 17, + NSControlKeyMask = 1 << 18, + NSAlternateKeyMask = 1 << 19, + NSCommandKeyMask = 1 << 20, + NSNumericPadKeyMask = 1 << 21, + NSHelpKeyMask = 1 << 22, + NSFunctionKeyMask = 1 << 23, + NSDeviceIndependentModifierFlagsMask = 0xffff0000U +}; + +- (id)_keyCommandForEvent:(UIEvent*)event +{ + /* This gets called twice with the same timestamp + * for each keypress, that's fine for polling + * but is bad for business with events. */ + static double last_time_stamp; + + if (last_time_stamp == event.timestamp) + return [super _keyCommandForEvent:event]; + last_time_stamp = event.timestamp; + + /* If the _hidEvent is null, [event _keyCode] will crash. + * (This happens with the on screen keyboard). */ + if (event._hidEvent) + { + NSString *ch = (NSString*)event._privateInput; + uint32_t character = 0; + uint32_t mod = 0; + + mod |= (event._modifierFlags & NSAlphaShiftKeyMask) ? RETROKMOD_CAPSLOCK : 0; + mod |= (event._modifierFlags & NSShiftKeyMask ) ? RETROKMOD_SHIFT : 0; + mod |= (event._modifierFlags & NSControlKeyMask ) ? RETROKMOD_CTRL : 0; + mod |= (event._modifierFlags & NSAlternateKeyMask ) ? RETROKMOD_ALT : 0; + mod |= (event._modifierFlags & NSCommandKeyMask ) ? RETROKMOD_META : 0; + mod |= (event._modifierFlags & NSNumericPadKeyMask) ? RETROKMOD_NUMLOCK : 0; + + if (ch && ch.length != 0) + { + unsigned i; + character = [ch characterAtIndex:0]; + + cocoa_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, 0, mod, + RETRO_DEVICE_KEYBOARD); + + for (i = 1; i < ch.length; i++) + cocoa_input_keyboard_event(event._isKeyDown, + 0, [ch characterAtIndex:i], mod, + RETRO_DEVICE_KEYBOARD); + } + + cocoa_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, character, mod, + RETRO_DEVICE_KEYBOARD); + } + + return [super _keyCommandForEvent:event]; +} + +#define GSEVENT_TYPE_KEYDOWN 10 +#define GSEVENT_TYPE_KEYUP 11 + +- (void)sendEvent:(UIEvent *)event +{ + int major, minor; + [super sendEvent:event]; + + if (event.allTouches.count) + handle_touch_event(event.allTouches.allObjects); + + get_ios_version(&major, &minor); + + if ((major < 7) && [event respondsToSelector:@selector(_gsEvent)]) + { + /* Keyboard event hack for iOS versions prior to iOS 7. + * + * Derived from: + * http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html + */ + const uint8_t *eventMem = objc_unretainedPointer([event performSelector:@selector(_gsEvent)]); + int eventType = eventMem ? *(int*)&eventMem[8] : 0; + + switch (eventType) + { + case GSEVENT_TYPE_KEYDOWN: + case GSEVENT_TYPE_KEYUP: + cocoa_input_keyboard_event(eventType == GSEVENT_TYPE_KEYDOWN, + *(uint16_t*)&eventMem[0x3C], 0, 0, RETRO_DEVICE_KEYBOARD); + break; + } + } +} + +@end + +@implementation RetroArch_iOS + ++ (RetroArch_iOS*)get +{ + return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate]; +} + +- (void)applicationDidFinishLaunching:(UIApplication *)application +{ + apple_platform = self; + + [self setDelegate:self]; + + if (rarch_main(0, NULL)) + apple_rarch_exited(); + + /* Setup window */ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [self.window makeKeyAndVisible]; + + [self pushViewController:[RAMainMenu new] animated:YES]; + + [apple_platform loadingCore:nil withFile:nil]; + + if (rarch_main(0, NULL)) + apple_rarch_exited(); + +#ifdef HAVE_MFI + apple_gamecontroller_init(); +#endif + + [self apple_start_iteration]; +} + +- (void) apple_start_iteration +{ + if (iterate_observer) + return; + + iterate_observer = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting, + true, 0, rarch_draw, 0); + CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); +} + +- (void) apple_stop_iteration +{ + if (!iterate_observer) + return; + + CFRunLoopObserverInvalidate(iterate_observer); + CFRelease(iterate_observer); + iterate_observer = NULL; +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + [self apple_stop_iteration]; +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + settings_t *settings = config_get_ptr(); + + if (settings->ui.companion_start_on_boot) + return; + + [self showGameView]; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + dispatch_async(dispatch_get_main_queue(), + ^{ + main_exit_save_config(); + }); + [self showPauseMenu: self]; +} + +-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation +{ + NSString *filename = (NSString*)url.path.lastPathComponent; + NSError *error = nil; + + [[NSFileManager defaultManager] moveItemAtPath:[url path] toPath:[self.documentsDirectory stringByAppendingPathComponent:filename] error:&error]; + + if (error) + printf("%s\n", [[error description] UTF8String]); + + return true; +} + +- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated +{ + cocoa_input_reset_icade_buttons(); + [self setToolbarHidden:![[viewController toolbarItems] count] animated:YES]; + + [self refreshSystemConfig]; +} + +- (void)showGameView +{ + runloop_t *runloop = rarch_main_get_ptr(); + + [self popToRootViewControllerAnimated:NO]; + [self setToolbarHidden:true animated:NO]; + [[UIApplication sharedApplication] setStatusBarHidden:true withAnimation:UIStatusBarAnimationNone]; + [[UIApplication sharedApplication] setIdleTimerDisabled:true]; + [self.window setRootViewController:[RAGameView get]]; + + runloop->is_paused = false; + runloop->is_idle = false; + runloop->ui_companion_is_on_foreground = false; +} + +- (IBAction)showPauseMenu:(id)sender +{ + runloop_t *runloop = rarch_main_get_ptr(); + + if (runloop) + { + runloop->is_paused = true; + runloop->is_idle = true; + runloop->ui_companion_is_on_foreground = true; + } + + [[UIApplication sharedApplication] setStatusBarHidden:false withAnimation:UIStatusBarAnimationNone]; + [[UIApplication sharedApplication] setIdleTimerDisabled:false]; + [self.window setRootViewController:self]; +} + +- (void)loadingCore:(NSString*)core withFile:(const char*)file +{ + btpad_set_inquiry_state(false); + + [self refreshSystemConfig]; + [self showGameView]; +} + +- (void)toggleUI +{ + runloop_t *runloop = rarch_main_get_ptr(); + + if (runloop->ui_companion_is_on_foreground) + { + [self showGameView]; + } + else + { + [self showPauseMenu:self]; + } +} + +- (void)unloadingCore +{ + [self showPauseMenu:self]; + btpad_set_inquiry_state(true); +} + +- (void)refreshSystemConfig +{ + bool small_keyboard, is_icade, is_btstack; + + /* Get enabled orientations */ + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskAll; + + if (!strcmp(apple_frontend_settings.orientations, "landscape")) + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskLandscape; + else if (!strcmp(apple_frontend_settings.orientations, "portrait")) + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; + + /* Set bluetooth mode */ + small_keyboard = !(strcmp(apple_frontend_settings.bluetooth_mode, "small_keyboard")); + is_icade = !(strcmp(apple_frontend_settings.bluetooth_mode, "icade")); + is_btstack = !(strcmp(apple_frontend_settings.bluetooth_mode, "btstack")); + + cocoa_input_enable_small_keyboard(small_keyboard); + cocoa_input_enable_icade(is_icade); + btstack_set_poweron(is_btstack); +} + +@end + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class])); + } +} typedef struct ui_companion_cocoatouch {