diff --git a/config.features.h b/config.features.h index 93062366f4..f3e0d85b50 100644 --- a/config.features.h +++ b/config.features.h @@ -308,7 +308,7 @@ static const bool _python_supp = true; static const bool _python_supp = false; #endif -#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) +#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) static const bool _cocoa_supp = true; #else static const bool _cocoa_supp = false; diff --git a/configuration.c b/configuration.c index a9b64bc8cc..0329a77778 100644 --- a/configuration.c +++ b/configuration.c @@ -451,7 +451,7 @@ static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UDEV; static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_LINUXRAW; #elif defined(HAVE_WAYLAND) static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WAYLAND; -#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) +#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_COCOA; #elif defined(__QNX__) static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_QNX; @@ -511,7 +511,7 @@ static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_V4L2; static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_RWEBCAM; #elif defined(ANDROID) static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_ANDROID; -#elif defined(HAVE_AVFOUNDATION) && (defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH)) +#elif defined(HAVE_AVFOUNDATION) && (defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)) static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_AVFOUNDATION; #else static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_NULL; @@ -525,7 +525,7 @@ static enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_NULL; #if defined(ANDROID) static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROID; -#elif defined(HAVE_CORELOCATION) && (defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH)) +#elif defined(HAVE_CORELOCATION) && (defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)) static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_CORELOCATION; #else static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL; diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index 3358883392..2c2129d911 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -7,7 +7,7 @@ #import #import "metal_common.h" -#import "../../ui/drivers/cocoa/cocoa_common.h" +#import "../../ui/drivers/cocoa/cocoa_common_metal.h" #import #import #import diff --git a/gfx/drivers_context/macos_ctx.m b/gfx/drivers_context/cocoa_gl_ctx_metal.m similarity index 97% rename from gfx/drivers_context/macos_ctx.m rename to gfx/drivers_context/cocoa_gl_ctx_metal.m index 329fc062cf..d554ab8385 100644 --- a/gfx/drivers_context/macos_ctx.m +++ b/gfx/drivers_context/cocoa_gl_ctx_metal.m @@ -22,7 +22,7 @@ #else #include #endif -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) #include #include #include @@ -37,7 +37,7 @@ #include #include -#import "../../ui/drivers/cocoa/cocoa_common.h" +#import "../../ui/drivers/cocoa/cocoa_common_metal.h" #include "../video_driver.h" #include "../../configuration.h" #include "../../verbosity.h" @@ -107,8 +107,8 @@ static int g_fast_forward_skips; static bool g_is_syncing = true; static bool g_use_hw_ctx = false; -#if defined(HAVE_COCOA) -#include "../../ui/drivers/ui_cocoa.h" +#if defined(HAVE_COCOA_METAL) +#include "../../ui/drivers/ui_cocoa_metal.h" static NSOpenGLPixelFormat* g_format; void *glcontext_get_ptr(void) @@ -203,7 +203,7 @@ float get_backing_scale_factor(void) return backing_scale_def; backing_scale_def = 1.0f; -#ifdef HAVE_COCOA +#ifdef HAVE_COCOA_METAL screen = (BRIDGE RAScreen*)get_chosen_screen(); if (screen) @@ -228,7 +228,7 @@ void cocoagl_gfx_ctx_update(void) switch (cocoagl_api) { case GFX_CTX_OPENGL_API: -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) #if MAC_OS_X_VERSION_10_7 CGLUpdateContext(g_hw_ctx.CGLContextObj); CGLUpdateContext(g_context.CGLContextObj); @@ -256,7 +256,7 @@ static void cocoagl_gfx_ctx_destroy(void *data) case GFX_CTX_OPENGL_ES_API: [GLContextClass clearCurrentContext]; -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) [g_context clearDrawable]; RELEASE(g_context); RELEASE(g_format); @@ -302,7 +302,7 @@ static void *cocoagl_gfx_ctx_init(video_frame_info_t *video_info, void *video_dr // setViewType is not (yet?) defined for iOS // [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL_ES]; break; -#elif defined(HAVE_COCOA) +#elif defined(HAVE_COCOA_METAL) case GFX_CTX_OPENGL_API: [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL]; break; @@ -341,7 +341,7 @@ static bool cocoagl_gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned #if defined(HAVE_COCOATOUCH) case GFX_CTX_OPENGL_ES_API: break; -#elif defined(HAVE_COCOA) +#elif defined(HAVE_COCOA_METAL) case GFX_CTX_OPENGL_API: break; #ifdef HAVE_VULKAN @@ -376,7 +376,7 @@ static void cocoagl_gfx_ctx_swap_interval(void *data, int interval) // Just skip presents so fast forward still works. g_is_syncing = interval ? true : false; g_fast_forward_skips = interval ? 0 : 3; -#elif defined(HAVE_COCOA) +#elif defined(HAVE_COCOA_METAL) GLint value = interval ? 1 : 0; [g_context setValues:&value forParameter:NSOpenGLCPSwapInterval]; #endif @@ -405,7 +405,7 @@ static void cocoagl_gfx_ctx_show_mouse(void *data, bool state) { (void)data; -#ifdef HAVE_COCOA +#ifdef HAVE_COCOA_METAL if (state) [NSCursor unhide]; else @@ -421,7 +421,7 @@ static bool cocoagl_gfx_ctx_set_video_mode(void *data, cocoa_ctx->width = width; cocoa_ctx->height = height; -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) //CocoaView *g_view = (BRIDGE CocoaView *)nsview_get_ptr(); NSView *g_view = apple_platform.renderView; #endif @@ -431,7 +431,7 @@ static bool cocoagl_gfx_ctx_set_video_mode(void *data, case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: { -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) if ([g_view respondsToSelector: @selector(setWantsBestResolutionOpenGLSurface:)]) [g_view setWantsBestResolutionOpenGLSurface:YES]; @@ -507,7 +507,7 @@ static bool cocoagl_gfx_ctx_set_video_mode(void *data, break; } -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) static bool has_went_fullscreen = false; /* TODO: Screen mode support. */ @@ -563,7 +563,7 @@ float cocoagl_gfx_ctx_get_native_scale(void) static void cocoagl_gfx_ctx_get_video_size(void *data, unsigned* width, unsigned* height) { float screenscale = cocoagl_gfx_ctx_get_native_scale(); -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) CGRect size; GLsizei backingPixelWidth, backingPixelHeight; NSView *g_view = apple_platform.renderView; @@ -584,7 +584,7 @@ static void cocoagl_gfx_ctx_get_video_size(void *data, unsigned* width, unsigned *height = CGRectGetHeight(size) * screenscale; } -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) static void cocoagl_gfx_ctx_update_title(void *data, void *data2) { ui_window_cocoa_t view; @@ -611,7 +611,7 @@ static bool cocoagl_gfx_ctx_get_metrics(void *data, enum display_metric_types ty float *value) { RAScreen *screen = (BRIDGE RAScreen*)get_chosen_screen(); -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) NSDictionary *description = [screen deviceDescription]; NSSize display_pixel_size = [[description objectForKey:NSDeviceSize] sizeValue]; CGSize display_physical_size = CGDisplayScreenSize( @@ -719,7 +719,7 @@ static void cocoagl_gfx_ctx_swap_buffers(void *data, void *data2) if (!(--g_fast_forward_skips < 0)) return; -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) [g_context flushBuffer]; [g_hw_ctx flushBuffer]; #elif defined(HAVE_COCOATOUCH) @@ -892,7 +892,7 @@ const gfx_ctx_driver_t gfx_ctx_cocoagl = { .set_video_mode = cocoagl_gfx_ctx_set_video_mode, .get_video_size = cocoagl_gfx_ctx_get_video_size, .get_metrics = cocoagl_gfx_ctx_get_metrics, -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA_METAL) .update_window_title = cocoagl_gfx_ctx_update_title, #endif .check_window = cocoagl_gfx_ctx_check_window, diff --git a/griffin/griffin.c b/griffin/griffin.c index e063951f5c..f84450d833 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -567,7 +567,7 @@ INPUT #elif defined(SN_TARGET_PSP2) || defined(PSP) || defined(VITA) #include "../input/drivers/psp_input.c" #include "../input/drivers_joypad/psp_joypad.c" -#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) +#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) #include "../input/drivers/cocoa_input.c" #elif defined(_3DS) #include "../input/drivers/ctr_input.c" diff --git a/griffin/griffin_objc.m b/griffin/griffin_objc.m index 1393d61bf1..f11512e7a4 100644 --- a/griffin/griffin_objc.m +++ b/griffin/griffin_objc.m @@ -27,9 +27,14 @@ #include "../frontend/drivers/platform_darwin.m" #endif +#if defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) #if defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA) -#include "../gfx/drivers_context/macos_ctx.m" +#include "../gfx/drivers_context/cocoa_gl_ctx.m" #include "../ui/drivers/cocoa/cocoa_common.m" +#else +#include "../gfx/drivers_context/cocoa_gl_ctx_metal.m" +#include "../ui/drivers/cocoa/cocoa_common_metal.m" +#endif #if defined(HAVE_COCOATOUCH) @@ -45,6 +50,12 @@ #include "../ui/drivers/cocoa/ui_cocoa_window.m" #include "../ui/drivers/cocoa/ui_cocoa_msg_window.m" #include "../ui/drivers/cocoa/ui_cocoa_application.m" +#elif defined(HAVE_COCOA_METAL) +#include "../ui/drivers/ui_cocoa_metal.m" +#include "../ui/drivers/cocoa/ui_cocoa_browser_window_metal.m" +#include "../ui/drivers/cocoa/ui_cocoa_window_metal.m" +#include "../ui/drivers/cocoa/ui_cocoa_msg_window_metal.m" +#include "../ui/drivers/cocoa/ui_cocoa_application_metal.m" #endif #endif diff --git a/input/drivers_hid/btstack_hid.c b/input/drivers_hid/btstack_hid.c index fb701e7505..cf7e1cf6c9 100644 --- a/input/drivers_hid/btstack_hid.c +++ b/input/drivers_hid/btstack_hid.c @@ -1284,7 +1284,7 @@ static bool btstack_try_load(void) } #endif -#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) +#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) run_loop_init_ptr(RUN_LOOP_COCOA); #else run_loop_init_ptr(RUN_LOOP_POSIX); diff --git a/input/input_driver.c b/input/input_driver.c index f49fd829fe..4a6a6fb8b5 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -122,7 +122,7 @@ static const input_driver_t *input_drivers[] = { #if defined(__linux__) && !defined(ANDROID) &input_linuxraw, #endif -#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) +#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) &input_cocoa, #endif #ifdef __QNX__ diff --git a/pkg/apple/BaseConfig.xcconfig b/pkg/apple/BaseConfig.xcconfig index 0ff10b6737..70ab0271c1 100644 --- a/pkg/apple/BaseConfig.xcconfig +++ b/pkg/apple/BaseConfig.xcconfig @@ -4,8 +4,7 @@ // // Created by Stuart Carnie on 5/10/18. // - -OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_OPENGL -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_COCOA -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG +OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DRC_DISABLE_LUA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DHAVE_NETPLAYDISCOVERY -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG -DHAVE_OPENGL SRCBASE = $(SRCROOT)/../.. DEPS_DIR = $(SRCBASE)/deps diff --git a/pkg/apple/Metal.xcconfig b/pkg/apple/Metal.xcconfig index 27d22dd265..1168500099 100644 --- a/pkg/apple/Metal.xcconfig +++ b/pkg/apple/Metal.xcconfig @@ -5,5 +5,5 @@ // Created by Stuart Carnie on 5/10/18. // -OTHER_CFLAGS = $(inherited) -DHAVE_MAIN +OTHER_CFLAGS = $(inherited) -DHAVE_MAIN -DHAVE_COCOA_METAL diff --git a/pkg/apple/OSX/en.lproj/MainMenu.xib b/pkg/apple/OSX/en.lproj/MainMenu.xib index b9d83c4861..111ef503b3 100644 --- a/pkg/apple/OSX/en.lproj/MainMenu.xib +++ b/pkg/apple/OSX/en.lproj/MainMenu.xib @@ -1,1809 +1,342 @@ - - - 1050 - 12F45 - 3084 - 1187.40 - 626.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 3084 - - - YES - NSCustomObject - NSMenu - NSMenuItem - NSView - NSWindowTemplate - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - NSApplication - - - FirstResponder - - - NSApplication - - - AMainMenu - - YES - - - RetroArch - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - submenuAction: - - - RetroArch - - YES - - - About RetroArch - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Services - - 1048576 - 2147483647 - - - submenuAction: - - - Services - - YES - - _NSServicesMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Hide RetroArch - h - 1048576 - 2147483647 - - - - - - Hide Others - h - 1572864 - 2147483647 - - - - - - Show All - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Quit RetroArch - q - 1048576 - 2147483647 - - - - - _NSAppleMenu - - - - - File - - 1048576 - 2147483647 - - - submenuAction: - - - File - - YES - - - Load Core... - - 2147483647 - - - - - - Load Content... - o - 1048576 - 2147483647 - - - - - - Open Recent - - 1048576 - 2147483647 - - - submenuAction: - - - Open Recent - - YES - - - Clear Menu - - 1048576 - 2147483647 - - - - - _NSRecentDocumentsMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Close - w - 1048576 - 2147483647 - - - - - - - - - Command - - 2147483647 - - - submenuAction: - - - Command - - YES - - - Audio Options - - 2147483647 - - - submenuAction: - - Audio Options - - YES - - - Mute Toggle - - 2147483647 - - - 11 - - - - - - - Disk Options - - 1048576 - 2147483647 - - - submenuAction: - - Disk Options - - YES - - - Cycle Tray - - 2147483647 - - - 4 - - - - Next Disk - - 2147483647 - - - 6 - - - - Previous Disk - - 2147483647 - - - 5 - - - - - - - Mouse Options - - 1048576 - 2147483647 - - - submenuAction: - - Mouse Options - - YES - - - Mouse Grab Toggle - - 2147483647 - - - 7 - - - - - - - Save State Options - - 1048576 - 2147483647 - - - submenuAction: - - Save State Options - - YES - - - Load State - - 2147483647 - - - 2 - - - - Save State - - 2147483647 - - - 3 - - - - - - - Reset - - 2147483647 - - - 1 - - - - Menu Toggle - - 2147483647 - - - 8 - - - - Pause Toggle - - 2147483647 - - - 9 - - - - Take Screenshot - - 2147483647 - - - 10 - - - - - - - Paths - - 2147483647 - - - submenuAction: - - - Paths - - YES - - - Core Directory - - 2147483647 - - - - - - - - - Window - - 1048576 - 2147483647 - - - submenuAction: - - - Window - - YES - - - Minimize - m - 1048576 - 2147483647 - - - - - - Zoom - - 1048576 - 2147483647 - - - - - - Windowed Scale - - 1048576 - 2147483647 - - - submenuAction: - - - - YES - - - 1x - - 2147483647 - - - 10 - - - - 2x - - 2147483647 - - - 11 - - - - 3x - - 2147483647 - - - 12 - - - - 4x - - 2147483647 - - - 13 - - - - 5x - - 2147483647 - - - 14 - - - - 6x - - 2147483647 - - - 15 - - - - 7x - - 2147483647 - - - 16 - - - - 8x - - 2147483647 - - - 17 - - - - 9x - - 2147483647 - - - 18 - - - - 10x - - 2147483647 - - - 19 - - - - - - - Enter Full Screen - f - 1310720 - 2147483647 - - - - - - Toggle Exclusive Full Screen - - 2147483647 - - - 20 - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Bring All to Front - - 1048576 - 2147483647 - - - - - _NSWindowsMenu - - - - - Help - - 2147483647 - - - submenuAction: - - - Help - - YES - - - RetroArch Help - ? - 1048576 - 2147483647 - - - - - _NSHelpMenu - - - - _NSMainMenu - - - 15 - 2 - {{335, 390}, {480, 360}} - 1954021376 - RetroArch_OSX - NSWindow - - - - - 256 - {480, 360} - - - - {{0, 0}, {2560, 1418}} - {10000000000000, 10000000000000} - YES - - - RetroArch_OSX - - - - - YES - - - terminate: - - - - 449 - - - - orderFrontStandardAboutPanel: - - - - 142 - - - - delegate - - - - 495 - - - - performMiniaturize: - - - - 37 - - - - arrangeInFront: - - - - 39 - - - - clearRecentDocuments: - - - - 127 - - - - performClose: - - - - 193 - - - - performZoom: - - - - 240 - - - - hide: - - - - 367 - - - - hideOtherApplications: - - - - 368 - - - - unhideAllApplications: - - - - 370 - - - - showHelp: - - - - 493 - - - - toggleFullScreen: - - - - 593 - - - - openDocument: - - - - 657 - - - - basicEvent: - - - - 550 - - - - basicEvent: - - - - 552 - - - - showCoresDirectory: - - - - 588 - - - - window - - - - 591 - - - - basicEvent: - - - - 615 - - - - basicEvent: - - - - 617 - - - - basicEvent: - - - - 619 - - - - basicEvent: - - - - 621 - - - - basicEvent: - - - - 623 - - - - basicEvent: - - - - 625 - - - - basicEvent: - - - - 627 - - - - basicEvent: - - - - 634 - - - - basicEvent: - - - - 636 - - - - basicEvent: - - - - 638 - - - - basicEvent: - - - - 640 - - - - basicEvent: - - - - 642 - - - - basicEvent: - - - - 644 - - - - basicEvent: - - - - 646 - - - - basicEvent: - - - - 648 - - - - basicEvent: - - - - 650 - - - - basicEvent: - - - - 652 - - - - basicEvent: - - - - 655 - - - - basicEvent: - - - - 659 - - - - basicEvent: - - - - 664 - - - - openCore: - - - - 665 - - - - - YES - - 0 - - YES - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 29 - - - YES - - - - - - - - - - - 19 - - - YES - - - - - - 56 - - - YES - - - - - - 83 - - - YES - - - - - - 81 - - - YES - - - - - - - - - - 72 - - - - - 124 - - - YES - - - - - - 73 - - - - - 79 - - - - - 125 - - - YES - - - - - - 126 - - - - - 57 - - - YES - - - - - - - - - - - - - - 58 - - - - - 134 - - - - - 150 - - - - - 136 - - - - - 144 - - - - - 236 - - - - - 131 - - - YES - - - - - - 149 - - - - - 145 - - - - - 130 - - - - - 371 - - - YES - - - - - - 372 - - - - - 490 - - - YES - - - - - - 491 - - - YES - - - - - - 492 - - - - - 494 - - - - - 545 - - - YES - - - - - - 546 - - - YES - - - - - - - - - - - - - 585 - - - YES - - - - - - 586 - - - YES - - - - - - 587 - - - - - 597 - - - YES - - - - - - 598 - - - YES - - - - - - - - 602 - - - YES - - - - - - 603 - - - YES - - - - - - 24 - - - YES - - - - - - - - - - - - 592 - - - - - 23 - - - - - 239 - - - - - 5 - - - - - 92 - - - - - 612 - - - YES - - - - - - 613 - - - YES - - - - - - - 549 - - - - - 551 - - - - - 614 - - - - - 616 - - - - - 618 - - - - - 620 - - - - - 629 - - - YES - - - - - - 630 - - - YES - - - - - - - - - - - - - - - 633 - - - - - 635 - - - - - 637 - - - - - 639 - - - - - 641 - - - - - 643 - - - - - 645 - - - - - 647 - - - - - 649 - - - - - 651 - - - - - 654 - - - - - 622 - - - - - 624 - - - - - 626 - - - - - 656 - - - - - 658 - - - - - 660 - - - YES - - - - - - 661 - - - YES - - - - - - 663 - - - - - - - YES - - YES - -1.IBPluginDependency - -2.IBPluginDependency - -3.IBPluginDependency - 124.IBPluginDependency - 125.IBPluginDependency - 126.IBPluginDependency - 130.IBPluginDependency - 131.IBPluginDependency - 134.IBPluginDependency - 136.IBPluginDependency - 144.IBPluginDependency - 145.IBPluginDependency - 149.IBPluginDependency - 150.IBPluginDependency - 19.IBPluginDependency - 23.IBPluginDependency - 236.IBPluginDependency - 239.IBPluginDependency - 24.IBPluginDependency - 29.IBPluginDependency - 371.IBPluginDependency - 371.IBWindowTemplateEditedContentRect - 371.NSWindowTemplate.visibleAtLaunch - 372.IBPluginDependency - 490.IBPluginDependency - 491.IBPluginDependency - 492.IBPluginDependency - 494.IBPluginDependency - 5.IBPluginDependency - 545.IBPluginDependency - 546.IBPluginDependency - 549.IBPluginDependency - 551.IBPluginDependency - 56.IBPluginDependency - 57.IBPluginDependency - 58.IBPluginDependency - 585.IBPluginDependency - 586.IBPluginDependency - 587.IBPluginDependency - 592.IBPluginDependency - 597.IBPluginDependency - 598.IBPluginDependency - 602.IBPluginDependency - 603.IBPluginDependency - 612.IBPluginDependency - 613.IBPluginDependency - 614.IBPluginDependency - 616.IBPluginDependency - 618.IBPluginDependency - 620.IBPluginDependency - 622.IBPluginDependency - 624.IBPluginDependency - 626.IBPluginDependency - 629.IBPluginDependency - 630.IBPluginDependency - 633.IBPluginDependency - 635.IBPluginDependency - 637.IBPluginDependency - 639.IBPluginDependency - 641.IBPluginDependency - 643.IBPluginDependency - 645.IBPluginDependency - 647.IBPluginDependency - 649.IBPluginDependency - 651.IBPluginDependency - 654.IBPluginDependency - 656.IBPluginDependency - 658.IBPluginDependency - 660.IBPluginDependency - 661.IBPluginDependency - 663.IBPluginDependency - 72.IBPluginDependency - 73.IBPluginDependency - 79.IBPluginDependency - 81.IBPluginDependency - 83.IBPluginDependency - 92.IBPluginDependency - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{438, 199}, {480, 360}} - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - YES - - - - - - YES - - - - - 665 - - - - YES - - RetroArch_OSX - NSObject - - YES - - YES - basicEvent: - openCore: - showCoresDirectory: - showPreferences: - - - YES - id - id - id - id - - - - YES - - YES - basicEvent: - openCore: - showCoresDirectory: - showPreferences: - - - YES - - basicEvent: - id - - - openCore: - id - - - showCoresDirectory: - id - - - showPreferences: - id - - - - - window - NSWindow - - - window - - window - NSWindow - - - - IBProjectSource - ./Classes/RetroArch.h - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES - 3 - - YES - - YES - NSMenuCheckmark - NSMenuMixedState - - - YES - {11, 11} - {10, 3} - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/apple/OSX/en.lproj/MainMenu_Metal.xib b/pkg/apple/OSX/en.lproj/MainMenu_Metal.xib index 934ee76845..ecf5bbe58b 100644 --- a/pkg/apple/OSX/en.lproj/MainMenu_Metal.xib +++ b/pkg/apple/OSX/en.lproj/MainMenu_Metal.xib @@ -1,8 +1,8 @@ - + - - + + diff --git a/pkg/apple/OSX/en.lproj/MainMenu_PPC.xib b/pkg/apple/OSX/en.lproj/MainMenu_PPC.xib new file mode 100644 index 0000000000..b9d83c4861 --- /dev/null +++ b/pkg/apple/OSX/en.lproj/MainMenu_PPC.xib @@ -0,0 +1,1809 @@ + + + + 1050 + 12F45 + 3084 + 1187.40 + 626.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + YES + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + RetroArch + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + + RetroArch + + YES + + + About RetroArch + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide RetroArch + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit RetroArch + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + YES + + + Load Core... + + 2147483647 + + + + + + Load Content... + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + + + + Command + + 2147483647 + + + submenuAction: + + + Command + + YES + + + Audio Options + + 2147483647 + + + submenuAction: + + Audio Options + + YES + + + Mute Toggle + + 2147483647 + + + 11 + + + + + + + Disk Options + + 1048576 + 2147483647 + + + submenuAction: + + Disk Options + + YES + + + Cycle Tray + + 2147483647 + + + 4 + + + + Next Disk + + 2147483647 + + + 6 + + + + Previous Disk + + 2147483647 + + + 5 + + + + + + + Mouse Options + + 1048576 + 2147483647 + + + submenuAction: + + Mouse Options + + YES + + + Mouse Grab Toggle + + 2147483647 + + + 7 + + + + + + + Save State Options + + 1048576 + 2147483647 + + + submenuAction: + + Save State Options + + YES + + + Load State + + 2147483647 + + + 2 + + + + Save State + + 2147483647 + + + 3 + + + + + + + Reset + + 2147483647 + + + 1 + + + + Menu Toggle + + 2147483647 + + + 8 + + + + Pause Toggle + + 2147483647 + + + 9 + + + + Take Screenshot + + 2147483647 + + + 10 + + + + + + + Paths + + 2147483647 + + + submenuAction: + + + Paths + + YES + + + Core Directory + + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + Windowed Scale + + 1048576 + 2147483647 + + + submenuAction: + + + + YES + + + 1x + + 2147483647 + + + 10 + + + + 2x + + 2147483647 + + + 11 + + + + 3x + + 2147483647 + + + 12 + + + + 4x + + 2147483647 + + + 13 + + + + 5x + + 2147483647 + + + 14 + + + + 6x + + 2147483647 + + + 15 + + + + 7x + + 2147483647 + + + 16 + + + + 8x + + 2147483647 + + + 17 + + + + 9x + + 2147483647 + + + 18 + + + + 10x + + 2147483647 + + + 19 + + + + + + + Enter Full Screen + f + 1310720 + 2147483647 + + + + + + Toggle Exclusive Full Screen + + 2147483647 + + + 20 + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + + Help + + YES + + + RetroArch Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 360}} + 1954021376 + RetroArch_OSX + NSWindow + + + + + 256 + {480, 360} + + + + {{0, 0}, {2560, 1418}} + {10000000000000, 10000000000000} + YES + + + RetroArch_OSX + + + + + YES + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + performZoom: + + + + 240 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + showHelp: + + + + 493 + + + + toggleFullScreen: + + + + 593 + + + + openDocument: + + + + 657 + + + + basicEvent: + + + + 550 + + + + basicEvent: + + + + 552 + + + + showCoresDirectory: + + + + 588 + + + + window + + + + 591 + + + + basicEvent: + + + + 615 + + + + basicEvent: + + + + 617 + + + + basicEvent: + + + + 619 + + + + basicEvent: + + + + 621 + + + + basicEvent: + + + + 623 + + + + basicEvent: + + + + 625 + + + + basicEvent: + + + + 627 + + + + basicEvent: + + + + 634 + + + + basicEvent: + + + + 636 + + + + basicEvent: + + + + 638 + + + + basicEvent: + + + + 640 + + + + basicEvent: + + + + 642 + + + + basicEvent: + + + + 644 + + + + basicEvent: + + + + 646 + + + + basicEvent: + + + + 648 + + + + basicEvent: + + + + 650 + + + + basicEvent: + + + + 652 + + + + basicEvent: + + + + 655 + + + + basicEvent: + + + + 659 + + + + basicEvent: + + + + 664 + + + + openCore: + + + + 665 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + 72 + + + + + 124 + + + YES + + + + + + 73 + + + + + 79 + + + + + 125 + + + YES + + + + + + 126 + + + + + 57 + + + YES + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 371 + + + YES + + + + + + 372 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 494 + + + + + 545 + + + YES + + + + + + 546 + + + YES + + + + + + + + + + + + + 585 + + + YES + + + + + + 586 + + + YES + + + + + + 587 + + + + + 597 + + + YES + + + + + + 598 + + + YES + + + + + + + + 602 + + + YES + + + + + + 603 + + + YES + + + + + + 24 + + + YES + + + + + + + + + + + + 592 + + + + + 23 + + + + + 239 + + + + + 5 + + + + + 92 + + + + + 612 + + + YES + + + + + + 613 + + + YES + + + + + + + 549 + + + + + 551 + + + + + 614 + + + + + 616 + + + + + 618 + + + + + 620 + + + + + 629 + + + YES + + + + + + 630 + + + YES + + + + + + + + + + + + + + + 633 + + + + + 635 + + + + + 637 + + + + + 639 + + + + + 641 + + + + + 643 + + + + + 645 + + + + + 647 + + + + + 649 + + + + + 651 + + + + + 654 + + + + + 622 + + + + + 624 + + + + + 626 + + + + + 656 + + + + + 658 + + + + + 660 + + + YES + + + + + + 661 + + + YES + + + + + + 663 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 124.IBPluginDependency + 125.IBPluginDependency + 126.IBPluginDependency + 130.IBPluginDependency + 131.IBPluginDependency + 134.IBPluginDependency + 136.IBPluginDependency + 144.IBPluginDependency + 145.IBPluginDependency + 149.IBPluginDependency + 150.IBPluginDependency + 19.IBPluginDependency + 23.IBPluginDependency + 236.IBPluginDependency + 239.IBPluginDependency + 24.IBPluginDependency + 29.IBPluginDependency + 371.IBPluginDependency + 371.IBWindowTemplateEditedContentRect + 371.NSWindowTemplate.visibleAtLaunch + 372.IBPluginDependency + 490.IBPluginDependency + 491.IBPluginDependency + 492.IBPluginDependency + 494.IBPluginDependency + 5.IBPluginDependency + 545.IBPluginDependency + 546.IBPluginDependency + 549.IBPluginDependency + 551.IBPluginDependency + 56.IBPluginDependency + 57.IBPluginDependency + 58.IBPluginDependency + 585.IBPluginDependency + 586.IBPluginDependency + 587.IBPluginDependency + 592.IBPluginDependency + 597.IBPluginDependency + 598.IBPluginDependency + 602.IBPluginDependency + 603.IBPluginDependency + 612.IBPluginDependency + 613.IBPluginDependency + 614.IBPluginDependency + 616.IBPluginDependency + 618.IBPluginDependency + 620.IBPluginDependency + 622.IBPluginDependency + 624.IBPluginDependency + 626.IBPluginDependency + 629.IBPluginDependency + 630.IBPluginDependency + 633.IBPluginDependency + 635.IBPluginDependency + 637.IBPluginDependency + 639.IBPluginDependency + 641.IBPluginDependency + 643.IBPluginDependency + 645.IBPluginDependency + 647.IBPluginDependency + 649.IBPluginDependency + 651.IBPluginDependency + 654.IBPluginDependency + 656.IBPluginDependency + 658.IBPluginDependency + 660.IBPluginDependency + 661.IBPluginDependency + 663.IBPluginDependency + 72.IBPluginDependency + 73.IBPluginDependency + 79.IBPluginDependency + 81.IBPluginDependency + 83.IBPluginDependency + 92.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{438, 199}, {480, 360}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 665 + + + + YES + + RetroArch_OSX + NSObject + + YES + + YES + basicEvent: + openCore: + showCoresDirectory: + showPreferences: + + + YES + id + id + id + id + + + + YES + + YES + basicEvent: + openCore: + showCoresDirectory: + showPreferences: + + + YES + + basicEvent: + id + + + openCore: + id + + + showCoresDirectory: + id + + + showPreferences: + id + + + + + window + NSWindow + + + window + + window + NSWindow + + + + IBProjectSource + ./Classes/RetroArch.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {11, 11} + {10, 3} + + + + diff --git a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj index 471b781c50..bf606084c4 100644 --- a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj @@ -291,7 +291,6 @@ 05A8C5D220DB72F000FF7857 /* ui_companion_driver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui_companion_driver.h; sourceTree = ""; }; 05A8C5D320DB72F000FF7857 /* ui_companion_driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui_companion_driver.c; sourceTree = ""; }; 05A8C5D520DB72F000FF7857 /* video_display_server.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = video_display_server.c; sourceTree = ""; }; - 05A8C5DD20DB72F000FF7857 /* macos_ctx.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = macos_ctx.m; sourceTree = ""; }; 05A8C5E720DB72F000FF7857 /* cocoa_gl_ctx.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = cocoa_gl_ctx.m; sourceTree = ""; }; 05A8C5F020DB72F000FF7857 /* gl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = gl.c; sourceTree = ""; }; 05A8C5F720DB72F000FF7857 /* metal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = metal.m; sourceTree = ""; }; @@ -548,10 +547,20 @@ 84DD5EB71A89F1C7007336C1 /* retroarch.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = retroarch.icns; path = ../../media/retroarch.icns; sourceTree = ""; }; 8D1107320486CEB800E47090 /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; }; A902040DE66D42F9EE47BFE3 /* MenuDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuDisplay.h; sourceTree = ""; }; + A90205DCA5102DF8D80D3F68 /* ui_cocoa_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_cocoa_metal.h; sourceTree = ""; }; A90205FD4D5979BD8B7E4DD6 /* Info_Metal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.info; name = Info_Metal.plist; path = OSX/Info_Metal.plist; sourceTree = ""; }; A902065A41AEBECE594908C7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = OSX/en.lproj/MainMenu_Metal.xib; sourceTree = ""; }; A902070F2C43F222FD56A95A /* MenuDisplay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenuDisplay.m; sourceTree = ""; }; A90207489289602F593626D5 /* QTConfig.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = QTConfig.xcconfig; sourceTree = ""; }; + A90208A05A895029CEC32C14 /* ui_cocoa_msg_window_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_msg_window_metal.m; sourceTree = ""; }; + A9020AF14B9A73364C6CDDA5 /* cocoa_common_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cocoa_common_metal.m; sourceTree = ""; }; + A9020BD6594399DDAB0E2563 /* ui_cocoatouch_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoatouch_metal.m; sourceTree = ""; }; + A9020C55D864F0E0C6E7DFF9 /* ui_cocoa_window_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_window_metal.m; sourceTree = ""; }; + A9020E880B5DBFD909921A8F /* cocoa_common_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_common_metal.h; sourceTree = ""; }; + A9020EE4BE2C6A15024A32E0 /* ui_cocoa_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_metal.m; sourceTree = ""; }; + A9020F2EEF870903107B0EA7 /* ui_cocoa_application_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_application_metal.m; sourceTree = ""; }; + A9020F48BA562B13D4789292 /* ui_cocoa_browser_window_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa_browser_window_metal.m; sourceTree = ""; }; + A9020FA64527ED74C836B41D /* cocoa_gl_ctx_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cocoa_gl_ctx_metal.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -932,6 +941,9 @@ 05366511213F8BE5007E7EA0 /* qt */, 05A8C5CE20DB72F000FF7857 /* ui_cocoa.h */, 05A8C5BA20DB72F000FF7857 /* ui_cocoa.m */, + A90205DCA5102DF8D80D3F68 /* ui_cocoa_metal.h */, + A9020EE4BE2C6A15024A32E0 /* ui_cocoa_metal.m */, + A9020BD6594399DDAB0E2563 /* ui_cocoatouch_metal.m */, 05A8C5CF20DB72F000FF7857 /* ui_cocoatouch.m */, 05A8C5B920DB72F000FF7857 /* ui_null.c */, 05A8C5D020DB72F000FF7857 /* ui_qt.cpp */, @@ -946,12 +958,18 @@ 05A8C5BB20DB72F000FF7857 /* cocoa */ = { isa = PBXGroup; children = ( + A9020E880B5DBFD909921A8F /* cocoa_common_metal.h */, + A9020AF14B9A73364C6CDDA5 /* cocoa_common_metal.m */, 05A8C5C220DB72F000FF7857 /* cocoa_common.h */, 05A8C5BD20DB72F000FF7857 /* cocoa_common.m */, 05A8C5BE20DB72F000FF7857 /* cocoatouch_menu.m */, + A9020F2EEF870903107B0EA7 /* ui_cocoa_application_metal.m */, 05A8C5C120DB72F000FF7857 /* ui_cocoa_application.m */, + A9020F48BA562B13D4789292 /* ui_cocoa_browser_window_metal.m */, 05A8C5BF20DB72F000FF7857 /* ui_cocoa_browser_window.m */, + A90208A05A895029CEC32C14 /* ui_cocoa_msg_window_metal.m */, 05A8C5BC20DB72F000FF7857 /* ui_cocoa_msg_window.m */, + A9020C55D864F0E0C6E7DFF9 /* ui_cocoa_window_metal.m */, 05A8C5C020DB72F000FF7857 /* ui_cocoa_window.m */, ); path = cocoa; @@ -995,7 +1013,7 @@ isa = PBXGroup; children = ( 05A8C5E720DB72F000FF7857 /* cocoa_gl_ctx.m */, - 05A8C5DD20DB72F000FF7857 /* macos_ctx.m */, + A9020FA64527ED74C836B41D /* cocoa_gl_ctx_metal.m */, ); path = drivers_context; sourceTree = ""; @@ -1790,67 +1808,6 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "$(inherited)", - "-DHAVE_RUNAHEAD", - "-DHAVE_GRIFFIN", - "-DHAVE_FLAC", - "-DHAVE_DR_FLAC", - "-DHAVE_DR_MP3", - "-DHAVE_LROUND", - "-DFLAC__HAS_OGG=0", - "-DHAVE_CHD", - "-DHAVE_STB_VORBIS", - "-DHAVE_MINIUPNPC", - "-DHAVE_BUILTINMINIUPNPC", - "-DHAVE_UPDATE_ASSETS", - "-DHAVE_LANGEXTRA", - "-DRC_DISABLE_LUA", - "-DHAVE_CHEEVOS", - "-DHAVE_IMAGEVIEWER", - "-DHAVE_IOHIDMANAGER", - "-DHAVE_CORETEXT", - "-DHAVE_RGUI", - "-DHAVE_MENU", - "-DOSX", - "-DHAVE_OPENGL", - "-DHAVE_CC_RESAMPLER", - "-DHAVE_GLSL", - "-DINLINE=inline", - "-D__LIBRETRO__", - "-DHAVE_COREAUDIO", - "-DHAVE_DYNAMIC", - "-DHAVE_OVERLAY", - "-DHAVE_ZLIB", - "-DHAVE_RPNG", - "-DHAVE_RJPEG", - "-DHAVE_RBMP", - "-DHAVE_RTGA", - "-DHAVE_COCOA", - "-DHAVE_NETWORKGAMEPAD", - "-DHAVE_NETWORKING", - "-DHAVE_NETPLAYDISCOVERY", - "-DRARCH_INTERNAL", - "-DHAVE_THREADS", - "-DHAVE_DYLIB", - "-DHAVE_7ZIP", - "-DHAVE_MATERIALUI", - "-DHAVE_HID", - "-DHAVE_XMB", - "-DHAVE_SEGA", - "-DHAVE_SHADERPIPELINE", - "-DHAVE_MMAP", - "-DHAVE_LIBRETRODB", - "-DHAVE_GETOPT_LONG", - "-DHAVE_METAL", - "-DHAVE_SLANG", - "-DHAVE_GLSLANG", - "-DHAVE_SPIRV_CROSS", - "-DWANT_GLSLANG", - "-DENABLE_HLSL", - "-DGLSLANG_OSINCLUDE_UNIX", - "-DMETAL_DEBUG", - ); PREBINDING = NO; SDKROOT = macosx; }; @@ -1905,67 +1862,6 @@ "$(DEPS_DIR)/glslang/glslang/glslang/OSDependent/Unix", ); MACOSX_DEPLOYMENT_TARGET = 10.13; - OTHER_CFLAGS = ( - "$(inherited)", - "-DHAVE_RUNAHEAD", - "-DHAVE_GRIFFIN", - "-DHAVE_FLAC", - "-DHAVE_DR_FLAC", - "-DHAVE_DR_MP3", - "-DHAVE_LROUND", - "-DFLAC__HAS_OGG=0", - "-DHAVE_CHD", - "-DHAVE_STB_VORBIS", - "-DHAVE_MINIUPNPC", - "-DHAVE_BUILTINMINIUPNPC", - "-DHAVE_UPDATE_ASSETS", - "-DHAVE_LANGEXTRA", - "-DRC_DISABLE_LUA", - "-DHAVE_CHEEVOS", - "-DHAVE_IMAGEVIEWER", - "-DHAVE_IOHIDMANAGER", - "-DHAVE_CORETEXT", - "-DHAVE_RGUI", - "-DHAVE_MENU", - "-DOSX", - "-DHAVE_OPENGL", - "-DHAVE_CC_RESAMPLER", - "-DHAVE_GLSL", - "-DINLINE=inline", - "-D__LIBRETRO__", - "-DHAVE_COREAUDIO", - "-DHAVE_DYNAMIC", - "-DHAVE_OVERLAY", - "-DHAVE_ZLIB", - "-DHAVE_RPNG", - "-DHAVE_RJPEG", - "-DHAVE_RBMP", - "-DHAVE_RTGA", - "-DHAVE_COCOA", - "-DHAVE_NETWORKGAMEPAD", - "-DHAVE_NETWORKING", - "-DHAVE_NETPLAYDISCOVERY", - "-DRARCH_INTERNAL", - "-DHAVE_THREADS", - "-DHAVE_DYLIB", - "-DHAVE_7ZIP", - "-DHAVE_MATERIALUI", - "-DHAVE_HID", - "-DHAVE_XMB", - "-DHAVE_SEGA", - "-DHAVE_SHADERPIPELINE", - "-DHAVE_MMAP", - "-DHAVE_LIBRETRODB", - "-DHAVE_GETOPT_LONG", - "-DHAVE_METAL", - "-DHAVE_SLANG", - "-DHAVE_GLSLANG", - "-DHAVE_SPIRV_CROSS", - "-DWANT_GLSLANG", - "-DENABLE_HLSL", - "-DGLSLANG_OSINCLUDE_UNIX", - "-DMETAL_DEBUG", - ); PREBINDING = NO; SDKROOT = macosx; }; diff --git a/ui/drivers/cocoa/cocoa_common.h b/ui/drivers/cocoa/cocoa_common.h index a291b769b3..be2aee7595 100644 --- a/ui/drivers/cocoa/cocoa_common.h +++ b/ui/drivers/cocoa/cocoa_common.h @@ -14,8 +14,8 @@ * If not, see . */ -#ifndef __COCOA_COMMON_H -#define __COCOA_COMMON_H +#ifndef __COCOA_COMMON_METAL_H +#define __COCOA_COMMON_METAL_H #include @@ -28,46 +28,6 @@ #include #endif -typedef enum apple_view_type { - APPLE_VIEW_TYPE_NONE, - APPLE_VIEW_TYPE_OPENGL_ES, - APPLE_VIEW_TYPE_OPENGL, - APPLE_VIEW_TYPE_VULKAN, - APPLE_VIEW_TYPE_METAL, -} apple_view_type_t; - -#ifdef HAVE_METAL -#import - -@interface MetalView : MTKView -@end - -#endif - -@protocol ApplePlatform - -/*! @brief renderView returns the current render view based on the viewType */ -@property (readonly) id renderView; - -/*! @brief isActive returns true if the application has focus */ -@property (readonly) bool hasFocus; - -@property (readwrite) apple_view_type_t viewType; - -/*! @brief setVideoMode adjusts the video display to the specified mode */ -- (void)setVideoMode:(gfx_ctx_mode_t)mode; - -/*! @brief setCursorVisible specifies whether the cursor is visible */ -- (void)setCursorVisible:(bool)v; - -/*! @brief controls whether the screen saver should be disabled and - * the displays should not sleep. - */ -- (bool)setDisableDisplaySleep:(bool)disable; -@end - -extern id apple_platform; - #if defined(HAVE_COCOATOUCH) #include @@ -106,7 +66,7 @@ AVCaptureAudioDataOutputSampleBufferDelegate> @end @interface RetroArch_iOS : UINavigationController +UINavigationControllerDelegate> @property (nonatomic) UIWindow* window; @property (nonatomic) NSString* documentsDirectory; @@ -148,15 +108,4 @@ void get_ios_version(int *major, int *minor); #define BOXUINT(x) [NSNumber numberWithUnsignedInt:x] #define BOXFLOAT(x) [NSNumber numberWithDouble:x] -#if __has_feature(objc_arc) -#define RELEASE(x) x = nil -#define BRIDGE __bridge -#define UNSAFE_UNRETAINED __unsafe_unretained -#else -#define RELEASE(x) [x release]; \ - x = nil -#define BRIDGE -#define UNSAFE_UNRETAINED -#endif - #endif diff --git a/ui/drivers/cocoa/cocoa_common.m b/ui/drivers/cocoa/cocoa_common.m index 09163291c8..b356ffed58 100644 --- a/ui/drivers/cocoa/cocoa_common.m +++ b/ui/drivers/cocoa/cocoa_common.m @@ -43,32 +43,12 @@ #include "../../../location/location_driver.h" #include "../../../camera/camera_driver.h" -#ifdef HAVE_METAL -@implementation MetalView - -- (void)keyDown:(NSEvent*)theEvent -{ -} - -/* Stop the annoying sound when pressing a key. */ -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -- (BOOL)isFlipped -{ - return YES; -} -@end -#endif - static CocoaView* g_instance; #if defined(HAVE_COCOA) void *nsview_get_ptr(void) { - return (BRIDGE void *)g_instance; + return g_instance; } #endif @@ -85,7 +65,6 @@ void *glkitview_init(void); cocoa_input_data_t *apple = (cocoa_input_data_t*)input_driver_get_data(); (void)apple; } - #endif + (CocoaView*)get @@ -102,6 +81,9 @@ void *glkitview_init(void); #if defined(HAVE_COCOA) [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + ui_window_cocoa_t cocoa_view; + cocoa_view.data = (CocoaView*)self; + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSColorPboardType, NSFilenamesPboardType, nil]]; #elif defined(HAVE_COCOATOUCH) self.view = (__bridge GLKView*)glkitview_init(); @@ -113,13 +95,10 @@ void *glkitview_init(void); } #if defined(HAVE_COCOA) -- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window { - return YES; -} - - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; + cocoagl_gfx_ctx_update(); } @@ -191,7 +170,7 @@ void *glkitview_init(void); { float width = 0.0f, height = 0.0f, tenpctw, tenpcth; RAScreen *screen = (__bridge RAScreen*)get_chosen_screen(); - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + UIInterfaceOrientation orientation = self.interfaceOrientation; CGRect screenSize = [screen bounds]; SEL selector = NSSelectorFromString(BOXSTRING("coordinateSpace")); @@ -212,40 +191,8 @@ void *glkitview_init(void); g_pause_indicator_view.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth); [g_pause_indicator_view viewWithTag:1].frame = CGRectMake(0, 0, tenpctw * 2.0f, tenpcth); - - [self adjustViewFrameForSafeArea]; } --(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; - if (@available(iOS 11, *)) { - [coordinator animateAlongsideTransition:^(id _Nonnull context) { - [self adjustViewFrameForSafeArea]; - } completion:^(id _Nonnull context) { - }]; - } -} - --(void)adjustViewFrameForSafeArea { - // This is for adjusting the view frame to account for the notch in iPhone X phones - if (@available(iOS 11, *)) { - RAScreen *screen = (__bridge RAScreen*)get_chosen_screen(); - CGRect screenSize = [screen bounds]; - UIEdgeInsets inset = [[UIApplication sharedApplication] delegate].window.safeAreaInsets; - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; - CGRect newFrame = screenSize; - if ( orientation == UIInterfaceOrientationPortrait ) { - newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y + inset.top, screenSize.size.width, screenSize.size.height - inset.top); - } else if ( orientation == UIInterfaceOrientationLandscapeLeft ) { - newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y, screenSize.size.width - inset.right, screenSize.size.height); - } else if ( orientation == UIInterfaceOrientationLandscapeRight ) { - newFrame = CGRectMake(screenSize.origin.x + inset.left, screenSize.origin.y, screenSize.size.width - inset.left, screenSize.size.height); - } - self.view.frame = newFrame; - } -} - - #define ALMOST_INVISIBLE (.021f) - (void)hidePauseButton diff --git a/ui/drivers/cocoa/cocoa_common_metal.h b/ui/drivers/cocoa/cocoa_common_metal.h new file mode 100644 index 0000000000..377e3a2732 --- /dev/null +++ b/ui/drivers/cocoa/cocoa_common_metal.h @@ -0,0 +1,162 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - 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 . + */ + +#ifndef __COCOA_COMMON_H +#define __COCOA_COMMON_H + +#include + +#ifdef HAVE_MENU +#include "../../menu/menu_setting.h" +#include "../../menu/menu_driver.h" +#endif + +#ifdef HAVE_CORELOCATION +#include +#endif + +typedef enum apple_view_type { + APPLE_VIEW_TYPE_NONE, + APPLE_VIEW_TYPE_OPENGL_ES, + APPLE_VIEW_TYPE_OPENGL, + APPLE_VIEW_TYPE_VULKAN, + APPLE_VIEW_TYPE_METAL, +} apple_view_type_t; + +#ifdef HAVE_METAL +#import + +@interface MetalView : MTKView +@end + +#endif + +@protocol ApplePlatform + +/*! @brief renderView returns the current render view based on the viewType */ +@property (readonly) id renderView; + +/*! @brief isActive returns true if the application has focus */ +@property (readonly) bool hasFocus; + +@property (readwrite) apple_view_type_t viewType; + +/*! @brief setVideoMode adjusts the video display to the specified mode */ +- (void)setVideoMode:(gfx_ctx_mode_t)mode; + +/*! @brief setCursorVisible specifies whether the cursor is visible */ +- (void)setCursorVisible:(bool)v; + +/*! @brief controls whether the screen saver should be disabled and + * the displays should not sleep. + */ +- (bool)setDisableDisplaySleep:(bool)disable; +@end + +extern id apple_platform; + +#if defined(HAVE_COCOATOUCH) +#include + +#ifdef HAVE_AVFOUNDATION +#import +#endif + + +/*********************************************/ +/* RAMenuBase */ +/* A menu class that displays RAMenuItemBase */ +/* objects. */ +/*********************************************/ +@interface RAMenuBase : UITableViewController +@property (nonatomic) NSMutableArray* sections; +@property (nonatomic) BOOL hidesHeaders; +@property (nonatomic) RAMenuBase* last_menu; +@property (nonatomic) UILabel *osdmessage; + +- (id)initWithStyle:(UITableViewStyle)style; +- (id)itemForIndexPath:(NSIndexPath*)indexPath; + +@end + +typedef struct +{ + char orientations[32]; + unsigned orientation_flags; + char bluetooth_mode[64]; +} apple_frontend_settings_t; +extern apple_frontend_settings_t apple_frontend_settings; + +@interface CocoaView : UIViewController ++ (CocoaView*)get; +@end + +@interface RetroArch_iOS : UINavigationController + +@property (nonatomic) UIWindow* window; +@property (nonatomic) NSString* documentsDirectory; +@property (nonatomic) RAMenuBase* mainmenu; +@property (nonatomic) int menu_count; + ++ (RetroArch_iOS*)get; + +- (void)showGameView; +- (void)toggleUI; +- (void)supportOtherAudioSessions; + +- (void)refreshSystemConfig; +- (void)mainMenuPushPop: (bool)pushp; +- (void)mainMenuRefresh; +@end + +void get_ios_version(int *major, int *minor); + +#elif defined(HAVE_COCOA_METAL) +#include + +@interface CocoaView : NSView +#ifdef HAVE_CORELOCATION + +#endif + ++ (CocoaView*)get; +#if !defined(HAVE_COCOA_METAL) +- (void)display; +#endif + +@end + +#endif + +#define BOXSTRING(x) [NSString stringWithUTF8String:x] +#define BOXINT(x) [NSNumber numberWithInt:x] +#define BOXUINT(x) [NSNumber numberWithUnsignedInt:x] +#define BOXFLOAT(x) [NSNumber numberWithDouble:x] + +#if __has_feature(objc_arc) +#define RELEASE(x) x = nil +#define BRIDGE __bridge +#define UNSAFE_UNRETAINED __unsafe_unretained +#else +#define RELEASE(x) [x release]; \ + x = nil +#define BRIDGE +#define UNSAFE_UNRETAINED +#endif + +#endif diff --git a/ui/drivers/cocoa/cocoa_common_metal.m b/ui/drivers/cocoa/cocoa_common_metal.m new file mode 100644 index 0000000000..928a06cc6c --- /dev/null +++ b/ui/drivers/cocoa/cocoa_common_metal.m @@ -0,0 +1,694 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - 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 . + */ + +#import +#include +#include "cocoa_common_metal.h" +#ifdef HAVE_COCOA_METAL +#include "../ui_cocoa_metal.h" +#endif + +#include + +#include "../../../verbosity.h" + +/* Define compatibility symbols and categories. */ + +#ifdef HAVE_AVFOUNDATION +#include +#include +#include +#include +#include +#ifdef HAVE_OPENGLES +#include +#else +#include +#endif +#endif + +#include "../../../location/location_driver.h" +#include "../../../camera/camera_driver.h" + +#ifdef HAVE_METAL +@implementation MetalView + +- (void)keyDown:(NSEvent*)theEvent +{ +} + +/* Stop the annoying sound when pressing a key. */ +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)isFlipped +{ + return YES; +} +@end +#endif + +static CocoaView* g_instance; + +#if defined(HAVE_COCOA_METAL) +void *nsview_get_ptr(void) +{ + return (BRIDGE void *)g_instance; +} +#endif + +/* forward declarations */ +void cocoagl_gfx_ctx_update(void); +void *glkitview_init(void); + +@implementation CocoaView + +#if defined(HAVE_COCOA_METAL) +#include "../../../input/drivers/cocoa_input.h" + +- (void)scrollWheel:(NSEvent *)theEvent { + cocoa_input_data_t *apple = (cocoa_input_data_t*)input_driver_get_data(); + (void)apple; +} + +#endif + ++ (CocoaView*)get +{ + if (!g_instance) + g_instance = [CocoaView new]; + + return g_instance; +} + +- (id)init +{ + self = [super init]; + +#if defined(HAVE_COCOA_METAL) + [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSColorPboardType, NSFilenamesPboardType, nil]]; +#elif defined(HAVE_COCOATOUCH) + self.view = (__bridge GLKView*)glkitview_init(); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showPauseIndicator) name:UIApplicationWillEnterForegroundNotification object:nil]; +#endif + + return self; +} + +#if defined(HAVE_COCOA_METAL) +- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window { + return YES; +} + +- (void)setFrame:(NSRect)frameRect +{ + [super setFrame:frameRect]; + cocoagl_gfx_ctx_update(); +} + +/* Stop the annoying sound when pressing a key. */ +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)isFlipped +{ + return YES; +} + +- (void)keyDown:(NSEvent*)theEvent +{ +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + NSDragOperation sourceDragMask = [sender draggingSourceOperationMask]; + NSPasteboard *pboard = [sender draggingPasteboard]; + + if ( [[pboard types] containsObject:NSFilenamesPboardType] ) + { + if (sourceDragMask & NSDragOperationCopy) + return NSDragOperationCopy; + } + + return NSDragOperationNone; +} + +- (BOOL)performDragOperation:(id)sender +{ + NSPasteboard *pboard = [sender draggingPasteboard]; + + if ( [[pboard types] containsObject:NSURLPboardType]) + { + NSURL *fileURL = [NSURL URLFromPasteboard:pboard]; + NSString *s = [fileURL path]; + if (s != nil) + { + RARCH_LOG("Drop name is: %s\n", [s UTF8String]); + } + } + return YES; +} + +- (void)draggingExited:(id )sender +{ + [self setNeedsDisplay: YES]; +} + +#elif defined(HAVE_COCOATOUCH) +- (void)viewDidAppear:(BOOL)animated +{ + /* Pause Menus. */ + [self showPauseIndicator]; +} + +- (void)showPauseIndicator +{ + g_pause_indicator_view.alpha = 1.0f; + [NSObject cancelPreviousPerformRequestsWithTarget:g_instance]; + [g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f]; +} + +- (void)viewWillLayoutSubviews +{ + float width = 0.0f, height = 0.0f, tenpctw, tenpcth; + RAScreen *screen = (__bridge RAScreen*)get_chosen_screen(); + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + CGRect screenSize = [screen bounds]; + SEL selector = NSSelectorFromString(BOXSTRING("coordinateSpace")); + + if ([screen respondsToSelector:selector]) + { + screenSize = [[screen coordinateSpace] bounds]; + width = CGRectGetWidth(screenSize); + height = CGRectGetHeight(screenSize); + } + else + { + width = ((int)orientation < 3) ? CGRectGetWidth(screenSize) : CGRectGetHeight(screenSize); + height = ((int)orientation < 3) ? CGRectGetHeight(screenSize) : CGRectGetWidth(screenSize); + } + + tenpctw = width / 10.0f; + tenpcth = height / 10.0f; + + g_pause_indicator_view.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth); + [g_pause_indicator_view viewWithTag:1].frame = CGRectMake(0, 0, tenpctw * 2.0f, tenpcth); + + [self adjustViewFrameForSafeArea]; +} + +-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + if (@available(iOS 11, *)) { + [coordinator animateAlongsideTransition:^(id _Nonnull context) { + [self adjustViewFrameForSafeArea]; + } completion:^(id _Nonnull context) { + }]; + } +} + +-(void)adjustViewFrameForSafeArea { + // This is for adjusting the view frame to account for the notch in iPhone X phones + if (@available(iOS 11, *)) { + RAScreen *screen = (__bridge RAScreen*)get_chosen_screen(); + CGRect screenSize = [screen bounds]; + UIEdgeInsets inset = [[UIApplication sharedApplication] delegate].window.safeAreaInsets; + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + CGRect newFrame = screenSize; + if ( orientation == UIInterfaceOrientationPortrait ) { + newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y + inset.top, screenSize.size.width, screenSize.size.height - inset.top); + } else if ( orientation == UIInterfaceOrientationLandscapeLeft ) { + newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y, screenSize.size.width - inset.right, screenSize.size.height); + } else if ( orientation == UIInterfaceOrientationLandscapeRight ) { + newFrame = CGRectMake(screenSize.origin.x + inset.left, screenSize.origin.y, screenSize.size.width - inset.left, screenSize.size.height); + } + self.view.frame = newFrame; + } +} + + +#define ALMOST_INVISIBLE (.021f) + +- (void)hidePauseButton +{ + [UIView animateWithDuration:0.2 + animations:^{ g_pause_indicator_view.alpha = ALMOST_INVISIBLE; } + completion:^(BOOL finished) { } + ]; +} + +/* NOTE: This version runs on iOS6+. */ +- (NSUInteger)supportedInterfaceOrientations +{ + return (NSUInteger)apple_frontend_settings.orientation_flags; +} + +/* NOTE: This version runs on iOS2-iOS5, but not iOS6+. */ +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + switch (interfaceOrientation) + { + case UIInterfaceOrientationPortrait: + return (apple_frontend_settings.orientation_flags & UIInterfaceOrientationMaskPortrait); + case UIInterfaceOrientationPortraitUpsideDown: + return (apple_frontend_settings.orientation_flags & UIInterfaceOrientationMaskPortraitUpsideDown); + case UIInterfaceOrientationLandscapeLeft: + return (apple_frontend_settings.orientation_flags & UIInterfaceOrientationMaskLandscapeLeft); + case UIInterfaceOrientationLandscapeRight: + return (apple_frontend_settings.orientation_flags & UIInterfaceOrientationMaskLandscapeRight); + + default: + return (apple_frontend_settings.orientation_flags & UIInterfaceOrientationMaskAll); + } + + return YES; +} +#endif + +#ifdef HAVE_AVFOUNDATION +#include "../../gfx/common/gl_common.h" + +#ifndef GL_BGRA +#define GL_BGRA 0x80E1 +#endif + +#ifdef HAVE_OPENGLES +#define RCVOpenGLTextureCacheCreateTextureFromImage CVOpenGLESTextureCacheCreateTextureFromImage +#define RCVOpenGLTextureGetName CVOpenGLESTextureGetName +#define RCVOpenGLTextureCacheFlush CVOpenGLESTextureCacheFlush +#define RCVOpenGLTextureCacheCreate CVOpenGLESTextureCacheCreate +#define RCVOpenGLTextureRef CVOpenGLESTextureRef +#define RCVOpenGLTextureCacheRef CVOpenGLESTextureCacheRef +#if COREVIDEO_USE_EAGLCONTEXT_CLASS_IN_API +#define RCVOpenGLGetCurrentContext() (CVEAGLContext)(g_context) +#else +#define RCVOpenGLGetCurrentContext() (__bridge void *)(g_context) +#endif +#else +#define RCVOpenGLTextureCacheCreateTextureFromImage CVOpenGLTextureCacheCreateTextureFromImage +#define RCVOpenGLTextureGetName CVOpenGLTextureGetName +#define RCVOpenGLTextureCacheFlush CVOpenGLTextureCacheFlush +#define RCVOpenGLTextureCacheCreate CVOpenGLTextureCacheCreate +#define RCVOpenGLTextureRef CVOpenGLTextureRef +#define RCVOpenGLTextureCacheRef CVOpenGLTextureCacheRef +#define RCVOpenGLGetCurrentContext() CGLGetCurrentContext(), CGLGetPixelFormat(CGLGetCurrentContext()) +#endif + +static AVCaptureSession *_session; +static NSString *_sessionPreset; +RCVOpenGLTextureCacheRef textureCache; +GLuint outputTexture; +static bool newFrame = false; + +static void event_process_camera_frame(void *pbuf_ptr) +{ + CVReturn ret; + RCVOpenGLTextureRef renderTexture; + CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)pbuf_ptr; + size_t width = CVPixelBufferGetWidth(pixelBuffer); + size_t height = CVPixelBufferGetHeight(pixelBuffer); + + CVPixelBufferLockBaseAddress(pixelBuffer, 0); + + (void)width; + (void)height; + + /*TODO - rewrite all this. + * + * create a texture from our render target. + * textureCache will be what you previously + * made with RCVOpenGLTextureCacheCreate. + */ +#ifdef HAVE_OPENGLES + ret = RCVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, + GL_RGBA, (GLsizei)width, (GLsizei)height, + GL_BGRA, GL_UNSIGNED_BYTE, 0, &renderTexture); +#else + ret = RCVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + textureCache, pixelBuffer, 0, &renderTexture); +#endif + + if (!renderTexture || ret) + { + RARCH_ERR("[apple_camera]: RCVOpenGLTextureCacheCreateTextureFromImage failed.\n"); + return; + } + + outputTexture = RCVOpenGLTextureGetName(renderTexture); + + gl_bind_texture(outputTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR); + + CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); + [[NSNotificationCenter defaultCenter] postNotificationName:@"NewCameraTextureReady" object:nil]; + newFrame = true; + + glBindTexture(GL_TEXTURE_2D, 0); + + RCVOpenGLTextureCacheFlush(textureCache, 0); + + CFRelease(renderTexture); + CFRelease(pixelBuffer); + + pixelBuffer = 0; +} + +- (void)captureOutput:(AVCaptureOutput *)captureOutput +didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection +{ + /* TODO: Don't post if event queue is full */ + CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CVPixelBufferRetain(CMSampleBufferGetImageBuffer(sampleBuffer)); + event_process_camera_frame(pixelBuffer); +} + +/* TODO - add void param to onCameraInit so we can pass g_context. */ +- (void) onCameraInit +{ + NSError *error; + AVCaptureVideoDataOutput * dataOutput; + AVCaptureDeviceInput *input; + AVCaptureDevice *videoDevice; + + CVReturn ret = RCVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, + RCVOpenGLGetCurrentContext(), NULL, &textureCache); + (void)ret; + + /* Setup Capture Session. */ + _session = [[AVCaptureSession alloc] init]; + [_session beginConfiguration]; + + /* TODO: dehardcode this based on device capabilities */ + _sessionPreset = AVCaptureSessionPreset640x480; + + /* Set preset session size. */ + [_session setSessionPreset:_sessionPreset]; + + /* Creata a video device and input from that Device. Add the input to the capture session. */ + videoDevice = (AVCaptureDevice*)[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (videoDevice == nil) + retro_assert(0); + + /* Add the device to the session. */ + input = (AVCaptureDeviceInput*)[AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; + + if (error) + { + RARCH_ERR("video device input %s\n", error.localizedDescription.UTF8String); + retro_assert(0); + } + + [_session addInput:input]; + + /* Create the output for the capture session. */ + dataOutput = (AVCaptureVideoDataOutput*)[[AVCaptureVideoDataOutput alloc] init]; + [dataOutput setAlwaysDiscardsLateVideoFrames:NO]; /* Probably want to set this to NO when recording. */ + + [dataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; + + /* Set dispatch to be on the main thread so OpenGL can do things with the data. */ + [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; + + [_session addOutput:dataOutput]; + [_session commitConfiguration]; +} + +- (void) onCameraStart +{ + [_session startRunning]; +} + +- (void) onCameraStop +{ + [_session stopRunning]; +} + +- (void) onCameraFree +{ + RCVOpenGLTextureCacheFlush(textureCache, 0); + CFRelease(textureCache); +} +#endif + +#ifdef HAVE_CORELOCATION +#include + +static CLLocationManager *locationManager; +static bool locationChanged; +static CLLocationDegrees currentLatitude; +static CLLocationDegrees currentLongitude; +static CLLocationAccuracy currentHorizontalAccuracy; +static CLLocationAccuracy currentVerticalAccuracy; + +- (bool)onLocationHasChanged +{ + bool hasChanged = locationChanged; + + if (hasChanged) + locationChanged = false; + + return hasChanged; +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation +{ + locationChanged = true; + currentLatitude = newLocation.coordinate.latitude; + currentLongitude = newLocation.coordinate.longitude; + currentHorizontalAccuracy = newLocation.horizontalAccuracy; + currentVerticalAccuracy = newLocation.verticalAccuracy; + RARCH_LOG("didUpdateToLocation - latitude %f, longitude %f\n", (float)currentLatitude, (float)currentLongitude); +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations +{ + CLLocation *location = (CLLocation*)[locations objectAtIndex:([locations count] - 1)]; + + locationChanged = true; + currentLatitude = [location coordinate].latitude; + currentLongitude = [location coordinate].longitude; + currentHorizontalAccuracy = location.horizontalAccuracy; + currentVerticalAccuracy = location.verticalAccuracy; + RARCH_LOG("didUpdateLocations - latitude %f, longitude %f\n", (float)currentLatitude, (float)currentLongitude); +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error +{ + RARCH_LOG("didFailWithError - %s\n", [[error localizedDescription] UTF8String]); +} + +- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager +{ + RARCH_LOG("didPauseLocationUpdates\n"); +} + +- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager +{ + RARCH_LOG("didResumeLocationUpdates\n"); +} + +- (void)onLocationInit +{ + /* Create the location manager + * if this object does not already have one. + */ + + if (locationManager == nil) + locationManager = [[CLLocationManager alloc] init]; + locationManager.delegate = self; + locationManager.desiredAccuracy = kCLLocationAccuracyBest; + locationManager.distanceFilter = kCLDistanceFilterNone; + [locationManager startUpdatingLocation]; +} +#endif + +@end + +#ifdef HAVE_AVFOUNDATION +typedef struct apple_camera +{ + void *empty; +} applecamera_t; + +static void *apple_camera_init(const char *device, uint64_t caps, unsigned width, unsigned height) +{ + applecamera_t *applecamera; + + if ((caps & (UINT64_C(1) << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE)) == 0) + { + RARCH_ERR("applecamera returns OpenGL texture.\n"); + return NULL; + } + + applecamera = (applecamera_t*)calloc(1, sizeof(applecamera_t)); + if (!applecamera) + return NULL; + + [[CocoaView get] onCameraInit]; + + return applecamera; +} + +static void apple_camera_free(void *data) +{ + applecamera_t *applecamera = (applecamera_t*)data; + + [[CocoaView get] onCameraFree]; + + if (applecamera) + free(applecamera); + applecamera = NULL; +} + +static bool apple_camera_start(void *data) +{ + (void)data; + + [[CocoaView get] onCameraStart]; + + return true; +} + +static void apple_camera_stop(void *data) +{ + [[CocoaView get] onCameraStop]; +} + +static bool apple_camera_poll(void *data, retro_camera_frame_raw_framebuffer_t frame_raw_cb, + retro_camera_frame_opengl_texture_t frame_gl_cb) +{ + + (void)data; + (void)frame_raw_cb; + + if (frame_gl_cb && newFrame) + { + /* FIXME: Identity for now. + * Use proper texture matrix as returned by iOS Camera (if at all?). */ + static const float affine[] = { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + + frame_gl_cb(outputTexture, GL_TEXTURE_2D, affine); + newFrame = false; + } + + return true; +} + +camera_driver_t camera_avfoundation = { + apple_camera_init, + apple_camera_free, + apple_camera_start, + apple_camera_stop, + apple_camera_poll, + "avfoundation", +}; +#endif + +#ifdef HAVE_CORELOCATION +typedef struct apple_location +{ + void *empty; +} applelocation_t; + +static void *apple_location_init(void) +{ + applelocation_t *applelocation = (applelocation_t*)calloc(1, sizeof(applelocation_t)); + if (!applelocation) + return NULL; + + [[CocoaView get] onLocationInit]; + + return applelocation; +} + +static void apple_location_set_interval(void *data, unsigned interval_update_ms, unsigned interval_distance) +{ + (void)data; + + locationManager.distanceFilter = interval_distance ? interval_distance : kCLDistanceFilterNone; +} + +static void apple_location_free(void *data) +{ + applelocation_t *applelocation = (applelocation_t*)data; + + /* TODO - free location manager? */ + + if (applelocation) + free(applelocation); + applelocation = NULL; +} + +static bool apple_location_start(void *data) +{ + (void)data; + + [locationManager startUpdatingLocation]; + return true; +} + +static void apple_location_stop(void *data) +{ + (void)data; + + [locationManager stopUpdatingLocation]; +} + +static bool apple_location_get_position(void *data, double *lat, double *lon, double *horiz_accuracy, + double *vert_accuracy) +{ + (void)data; + + bool ret = [[CocoaView get] onLocationHasChanged]; + + if (!ret) + goto fail; + + *lat = currentLatitude; + *lon = currentLongitude; + *horiz_accuracy = currentHorizontalAccuracy; + *vert_accuracy = currentVerticalAccuracy; + return true; + +fail: + *lat = 0.0; + *lon = 0.0; + *horiz_accuracy = 0.0; + *vert_accuracy = 0.0; + return false; +} + +location_driver_t location_corelocation = { + apple_location_init, + apple_location_free, + apple_location_start, + apple_location_stop, + apple_location_get_position, + apple_location_set_interval, + "corelocation", +}; +#endif + diff --git a/ui/drivers/cocoa/ui_cocoa_application.m b/ui/drivers/cocoa/ui_cocoa_application.m index afb6740d43..14975b3c10 100644 --- a/ui/drivers/cocoa/ui_cocoa_application.m +++ b/ui/drivers/cocoa/ui_cocoa_application.m @@ -23,10 +23,6 @@ #include "cocoa_common.h" #include "../../ui_companion_driver.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 -#define NSEventMaskAny NSAnyEventMask -#endif - static void* ui_application_cocoa_initialize(void) { return NULL; @@ -34,7 +30,7 @@ static void* ui_application_cocoa_initialize(void) static bool ui_application_cocoa_pending_events(void) { - NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; if (!event) return false; return true; @@ -44,17 +40,12 @@ static void ui_application_cocoa_process_events(void) { while (1) { - NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; if (!event) break; -#if __has_feature(objc_arc) - [NSApp sendEvent: event]; - -#else [event retain]; [NSApp sendEvent: event]; [event release]; -#endif } } diff --git a/ui/drivers/cocoa/ui_cocoa_application_metal.m b/ui/drivers/cocoa/ui_cocoa_application_metal.m new file mode 100644 index 0000000000..b5cc8f46ea --- /dev/null +++ b/ui/drivers/cocoa/ui_cocoa_application_metal.m @@ -0,0 +1,73 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - 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 +#include +#include + +#include +#include "cocoa_common_metal.h" +#include "../../ui_companion_driver.h" + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 +#define NSEventMaskAny NSAnyEventMask +#endif + +static void* ui_application_cocoa_initialize(void) +{ + return NULL; +} + +static bool ui_application_cocoa_pending_events(void) +{ + NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + if (!event) + return false; + return true; +} + +static void ui_application_cocoa_process_events(void) +{ + while (1) + { + NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + if (!event) + break; +#if __has_feature(objc_arc) + [NSApp sendEvent: event]; + +#else + [event retain]; + [NSApp sendEvent: event]; + [event release]; +#endif + } +} + +static void ui_application_cocoa_run(void *args) +{ + (void)args; +} + +ui_application_t ui_application_cocoa = { + ui_application_cocoa_initialize, + ui_application_cocoa_pending_events, + ui_application_cocoa_process_events, + ui_application_cocoa_run, + NULL, + "cocoa" +}; diff --git a/ui/drivers/cocoa/ui_cocoa_browser_window_metal.m b/ui/drivers/cocoa/ui_cocoa_browser_window_metal.m new file mode 100644 index 0000000000..27b1474409 --- /dev/null +++ b/ui/drivers/cocoa/ui_cocoa_browser_window_metal.m @@ -0,0 +1,67 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - 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 +#include +#include + +#include + +#include "cocoa_common_metal.h" + +#include "../../ui_companion_driver.h" + +static bool ui_browser_window_cocoa_open(ui_browser_window_state_t *state) +{ + NSOpenPanel* panel = (NSOpenPanel*)[NSOpenPanel openPanel]; + NSArray *filetypes = NULL; + + if (!string_is_empty(state->filters)) + filetypes = [[NSArray alloc] initWithObjects:BOXSTRING(state->filters), BOXSTRING(state->filters_title), nil]; + [panel setAllowedFileTypes:filetypes]; +#if defined(MAC_OS_X_VERSION_10_6) + [panel setMessage:BOXSTRING(state->title)]; + if ([panel runModalForDirectory:BOXSTRING(state->startdir) file:nil] != 1) + return false; +#else + [panel setTitle:NSLocalizedString(BOXSTRING(state->title), BOXSTRING("open panel"))]; + [panel setDirectory:BOXSTRING(state->startdir)]; + [panel setCanChooseDirectories:NO]; + [panel setCanChooseFiles:YES]; + [panel setAllowsMultipleSelection:NO]; + [panel setTreatsFilePackagesAsDirectories:NO]; + NSInteger result = [panel runModal]; + if (result != 1) + return false; +#endif + NSURL *url = (NSURL*)panel.URL; + const char *res_path = [url.path UTF8String]; + state->result = strdup(res_path); + + return true; +} + +static bool ui_browser_window_cocoa_save(ui_browser_window_state_t *state) +{ + return false; +} + +ui_browser_window_t ui_browser_window_cocoa = { + ui_browser_window_cocoa_open, + ui_browser_window_cocoa_save, + "cocoa" +}; diff --git a/ui/drivers/cocoa/ui_cocoa_msg_window.m b/ui/drivers/cocoa/ui_cocoa_msg_window.m index 71c83393c6..d5e4ec9713 100644 --- a/ui/drivers/cocoa/ui_cocoa_msg_window.m +++ b/ui/drivers/cocoa/ui_cocoa_msg_window.m @@ -25,104 +25,88 @@ #include "../../ui_companion_driver.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 -#define NSAlertStyleCritical NSCriticalAlertStyle -#define NSAlertStyleWarning NSWarningAlertStyle -#define NSAlertStyleInformational NSInformationalAlertStyle -#endif +extern id apple_platform; static enum ui_msg_window_response ui_msg_window_cocoa_dialog(ui_msg_window_state *state, enum ui_msg_window_type type) { - NSInteger response; -#if __has_feature(objc_arc) - NSAlert *alert = [NSAlert new]; -#else - NSAlert* alert = [[NSAlert new] autorelease]; -#endif - - if (!string_is_empty(state->title)) - [alert setMessageText:BOXSTRING(state->title)]; - [alert setInformativeText:BOXSTRING(state->text)]; - - switch (state->buttons) - { - case UI_MSG_WINDOW_OK: - [alert addButtonWithTitle:BOXSTRING("OK")]; - break; - case UI_MSG_WINDOW_YESNO: - [alert addButtonWithTitle:BOXSTRING("Yes")]; - [alert addButtonWithTitle:BOXSTRING("No")]; - break; - case UI_MSG_WINDOW_OKCANCEL: - [alert addButtonWithTitle:BOXSTRING("OK")]; - [alert addButtonWithTitle:BOXSTRING("Cancel")]; - break; - case UI_MSG_WINDOW_YESNOCANCEL: - [alert addButtonWithTitle:BOXSTRING("Yes")]; - [alert addButtonWithTitle:BOXSTRING("No")]; - [alert addButtonWithTitle:BOXSTRING("Cancel")]; - break; - } - - switch (type) - { - case UI_MSG_WINDOW_TYPE_ERROR: - [alert setAlertStyle:NSAlertStyleCritical]; - break; - case UI_MSG_WINDOW_TYPE_WARNING: - [alert setAlertStyle:NSAlertStyleWarning]; - break; - case UI_MSG_WINDOW_TYPE_QUESTION: - [alert setAlertStyle:NSAlertStyleInformational]; - break; - case UI_MSG_WINDOW_TYPE_INFORMATION: - [alert setAlertStyle:NSAlertStyleInformational]; - break; - } - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 - [alert beginSheetModalForWindow:(BRIDGE NSWindow *)ui_companion_driver_get_main_window() - completionHandler:^(NSModalResponse returnCode) { - [[NSApplication sharedApplication] stopModalWithCode:returnCode]; - }]; - response = [alert runModal]; -#else - [alert beginSheetModalForWindow:(BRIDGE NSWindow *)ui_companion_driver_get_main_window() - modalDelegate:apple_platform - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:nil]; - response = [[NSApplication sharedApplication] runModalForWindow:[alert window]]; -#endif - - switch (state->buttons) - { - case UI_MSG_WINDOW_OK: - if (response == NSAlertFirstButtonReturn) - return UI_MSG_RESPONSE_OK; - break; - case UI_MSG_WINDOW_OKCANCEL: - if (response == NSAlertFirstButtonReturn) - return UI_MSG_RESPONSE_OK; - if (response == NSAlertSecondButtonReturn) - return UI_MSG_RESPONSE_CANCEL; - break; - case UI_MSG_WINDOW_YESNO: - if (response == NSAlertFirstButtonReturn) - return UI_MSG_RESPONSE_YES; - if (response == NSAlertSecondButtonReturn) - return UI_MSG_RESPONSE_NO; - break; - case UI_MSG_WINDOW_YESNOCANCEL: - if (response == NSAlertFirstButtonReturn) - return UI_MSG_RESPONSE_YES; - if (response == NSAlertSecondButtonReturn) - return UI_MSG_RESPONSE_NO; - if (response == NSAlertThirdButtonReturn) - return UI_MSG_RESPONSE_CANCEL; - break; - } - - return UI_MSG_RESPONSE_NA; + NSInteger response; + NSAlert* alert = [[NSAlert new] autorelease]; + + if (!string_is_empty(state->title)) + [alert setMessageText:BOXSTRING(state->title)]; + [alert setInformativeText:BOXSTRING(state->text)]; + + switch (state->buttons) + { + case UI_MSG_WINDOW_OK: + [alert addButtonWithTitle:BOXSTRING("OK")]; + break; + case UI_MSG_WINDOW_YESNO: + [alert addButtonWithTitle:BOXSTRING("Yes")]; + [alert addButtonWithTitle:BOXSTRING("No")]; + break; + case UI_MSG_WINDOW_OKCANCEL: + [alert addButtonWithTitle:BOXSTRING("OK")]; + [alert addButtonWithTitle:BOXSTRING("Cancel")]; + break; + case UI_MSG_WINDOW_YESNOCANCEL: + [alert addButtonWithTitle:BOXSTRING("Yes")]; + [alert addButtonWithTitle:BOXSTRING("No")]; + [alert addButtonWithTitle:BOXSTRING("Cancel")]; + break; + } + + switch (type) + { + case UI_MSG_WINDOW_TYPE_ERROR: + [alert setAlertStyle:NSCriticalAlertStyle]; + break; + case UI_MSG_WINDOW_TYPE_WARNING: + [alert setAlertStyle:NSWarningAlertStyle]; + break; + case UI_MSG_WINDOW_TYPE_QUESTION: + [alert setAlertStyle:NSInformationalAlertStyle]; + break; + case UI_MSG_WINDOW_TYPE_INFORMATION: + [alert setAlertStyle:NSInformationalAlertStyle]; + break; + } + + [alert beginSheetModalForWindow:ui_companion_driver_get_main_window() + modalDelegate:apple_platform + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:nil]; + response = [[NSApplication sharedApplication] runModalForWindow:[alert window]]; + + switch (state->buttons) + { + case UI_MSG_WINDOW_OK: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_OK; + break; + case UI_MSG_WINDOW_OKCANCEL: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_OK; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_CANCEL; + break; + case UI_MSG_WINDOW_YESNO: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_YES; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_NO; + break; + case UI_MSG_WINDOW_YESNOCANCEL: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_YES; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_NO; + if (response == NSAlertThirdButtonReturn) + return UI_MSG_RESPONSE_CANCEL; + break; + } + + return UI_MSG_RESPONSE_NA; } static enum ui_msg_window_response ui_msg_window_cocoa_error(ui_msg_window_state *state) diff --git a/ui/drivers/cocoa/ui_cocoa_msg_window_metal.m b/ui/drivers/cocoa/ui_cocoa_msg_window_metal.m new file mode 100644 index 0000000000..a209e8dc58 --- /dev/null +++ b/ui/drivers/cocoa/ui_cocoa_msg_window_metal.m @@ -0,0 +1,154 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - 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 +#include +#include + +#include + +#include "cocoa_common_metal.h" + +#include "../../ui_companion_driver.h" + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 +#define NSAlertStyleCritical NSCriticalAlertStyle +#define NSAlertStyleWarning NSWarningAlertStyle +#define NSAlertStyleInformational NSInformationalAlertStyle +#endif + +static enum ui_msg_window_response ui_msg_window_cocoa_dialog(ui_msg_window_state *state, enum ui_msg_window_type type) +{ + NSInteger response; +#if __has_feature(objc_arc) + NSAlert *alert = [NSAlert new]; +#else + NSAlert* alert = [[NSAlert new] autorelease]; +#endif + + if (!string_is_empty(state->title)) + [alert setMessageText:BOXSTRING(state->title)]; + [alert setInformativeText:BOXSTRING(state->text)]; + + switch (state->buttons) + { + case UI_MSG_WINDOW_OK: + [alert addButtonWithTitle:BOXSTRING("OK")]; + break; + case UI_MSG_WINDOW_YESNO: + [alert addButtonWithTitle:BOXSTRING("Yes")]; + [alert addButtonWithTitle:BOXSTRING("No")]; + break; + case UI_MSG_WINDOW_OKCANCEL: + [alert addButtonWithTitle:BOXSTRING("OK")]; + [alert addButtonWithTitle:BOXSTRING("Cancel")]; + break; + case UI_MSG_WINDOW_YESNOCANCEL: + [alert addButtonWithTitle:BOXSTRING("Yes")]; + [alert addButtonWithTitle:BOXSTRING("No")]; + [alert addButtonWithTitle:BOXSTRING("Cancel")]; + break; + } + + switch (type) + { + case UI_MSG_WINDOW_TYPE_ERROR: + [alert setAlertStyle:NSAlertStyleCritical]; + break; + case UI_MSG_WINDOW_TYPE_WARNING: + [alert setAlertStyle:NSAlertStyleWarning]; + break; + case UI_MSG_WINDOW_TYPE_QUESTION: + [alert setAlertStyle:NSAlertStyleInformational]; + break; + case UI_MSG_WINDOW_TYPE_INFORMATION: + [alert setAlertStyle:NSAlertStyleInformational]; + break; + } + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + [alert beginSheetModalForWindow:(BRIDGE NSWindow *)ui_companion_driver_get_main_window() + completionHandler:^(NSModalResponse returnCode) { + [[NSApplication sharedApplication] stopModalWithCode:returnCode]; + }]; + response = [alert runModal]; +#else + [alert beginSheetModalForWindow:(BRIDGE NSWindow *)ui_companion_driver_get_main_window() + modalDelegate:apple_platform + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:nil]; + response = [[NSApplication sharedApplication] runModalForWindow:[alert window]]; +#endif + + switch (state->buttons) + { + case UI_MSG_WINDOW_OK: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_OK; + break; + case UI_MSG_WINDOW_OKCANCEL: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_OK; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_CANCEL; + break; + case UI_MSG_WINDOW_YESNO: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_YES; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_NO; + break; + case UI_MSG_WINDOW_YESNOCANCEL: + if (response == NSAlertFirstButtonReturn) + return UI_MSG_RESPONSE_YES; + if (response == NSAlertSecondButtonReturn) + return UI_MSG_RESPONSE_NO; + if (response == NSAlertThirdButtonReturn) + return UI_MSG_RESPONSE_CANCEL; + break; + } + + return UI_MSG_RESPONSE_NA; +} + +static enum ui_msg_window_response ui_msg_window_cocoa_error(ui_msg_window_state *state) +{ + return ui_msg_window_cocoa_dialog(state, UI_MSG_WINDOW_TYPE_ERROR); +} + +static enum ui_msg_window_response ui_msg_window_cocoa_information(ui_msg_window_state *state) +{ + return ui_msg_window_cocoa_dialog(state, UI_MSG_WINDOW_TYPE_INFORMATION); +} + +static enum ui_msg_window_response ui_msg_window_cocoa_question(ui_msg_window_state *state) +{ + return ui_msg_window_cocoa_dialog(state, UI_MSG_WINDOW_TYPE_QUESTION); +} + +static enum ui_msg_window_response ui_msg_window_cocoa_warning(ui_msg_window_state *state) +{ + return ui_msg_window_cocoa_dialog(state, UI_MSG_WINDOW_TYPE_WARNING); +} + +ui_msg_window_t ui_msg_window_cocoa = { + ui_msg_window_cocoa_error, + ui_msg_window_cocoa_information, + ui_msg_window_cocoa_question, + ui_msg_window_cocoa_warning, + "cocoa" +}; diff --git a/ui/drivers/cocoa/ui_cocoa_window.m b/ui/drivers/cocoa/ui_cocoa_window.m index 94e2a15fcc..3ec869e569 100644 --- a/ui/drivers/cocoa/ui_cocoa_window.m +++ b/ui/drivers/cocoa/ui_cocoa_window.m @@ -32,18 +32,15 @@ static void* ui_window_cocoa_init(void) static void ui_window_cocoa_destroy(void *data) { -#if !__has_feature(objc_arc) ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; CocoaView *cocoa_view = (CocoaView*)cocoa->data; - // TODO(sgc): incorrect behavior [[cocoa_view window] release]; -#endif } static void ui_window_cocoa_set_focused(void *data) { ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; - CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; [[cocoa_view window] makeKeyAndOrderFront:nil]; } @@ -51,7 +48,7 @@ static void ui_window_cocoa_set_visible(void *data, bool set_visible) { ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; - CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; if (set_visible) [[cocoa_view window] makeKeyAndOrderFront:nil]; else @@ -61,7 +58,7 @@ static void ui_window_cocoa_set_visible(void *data, static void ui_window_cocoa_set_title(void *data, char *buf) { ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; - CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; const char* const text = buf; /* < Can't access buffer directly in the block */ [[cocoa_view window] setTitle:[NSString stringWithCString:text encoding:NSUTF8StringEncoding]]; } @@ -69,7 +66,7 @@ static void ui_window_cocoa_set_title(void *data, char *buf) static void ui_window_cocoa_set_droppable(void *data, bool droppable) { ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; - CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; if (droppable) { @@ -84,7 +81,7 @@ static void ui_window_cocoa_set_droppable(void *data, bool droppable) static bool ui_window_cocoa_focused(void *data) { ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; - CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; if ([[cocoa_view window] isMainWindow] == YES) return true; return false; diff --git a/ui/drivers/cocoa/ui_cocoa_window_metal.m b/ui/drivers/cocoa/ui_cocoa_window_metal.m new file mode 100644 index 0000000000..d9f39db124 --- /dev/null +++ b/ui/drivers/cocoa/ui_cocoa_window_metal.m @@ -0,0 +1,102 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2017 - 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 +#include +#include + +#include + +#include "cocoa_common_metal.h" +#include "../ui_cocoa_metal.h" +#include "../../ui_companion_driver.h" + +static void* ui_window_cocoa_init(void) +{ + return NULL; +} + +static void ui_window_cocoa_destroy(void *data) +{ +#if !__has_feature(objc_arc) + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (CocoaView*)cocoa->data; + // TODO(sgc): incorrect behavior + [[cocoa_view window] release]; +#endif +} + +static void ui_window_cocoa_set_focused(void *data) +{ + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + [[cocoa_view window] makeKeyAndOrderFront:nil]; +} + +static void ui_window_cocoa_set_visible(void *data, + bool set_visible) +{ + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + if (set_visible) + [[cocoa_view window] makeKeyAndOrderFront:nil]; + else + [[cocoa_view window] orderOut:nil]; +} + +static void ui_window_cocoa_set_title(void *data, char *buf) +{ + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + const char* const text = buf; /* < Can't access buffer directly in the block */ + [[cocoa_view window] setTitle:[NSString stringWithCString:text encoding:NSUTF8StringEncoding]]; +} + +static void ui_window_cocoa_set_droppable(void *data, bool droppable) +{ + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + + if (droppable) + { + [[cocoa_view window] registerForDraggedTypes:[NSArray arrayWithObjects:NSColorPboardType, NSFilenamesPboardType, nil]]; + } + else + { + [[cocoa_view window] unregisterDraggedTypes]; + } +} + +static bool ui_window_cocoa_focused(void *data) +{ + ui_window_cocoa_t *cocoa = (ui_window_cocoa_t*)data; + CocoaView *cocoa_view = (BRIDGE CocoaView*)cocoa->data; + if ([[cocoa_view window] isMainWindow] == YES) + return true; + return false; +} + +ui_window_t ui_window_cocoa = { + ui_window_cocoa_init, + ui_window_cocoa_destroy, + ui_window_cocoa_set_focused, + ui_window_cocoa_set_visible, + ui_window_cocoa_set_title, + ui_window_cocoa_set_droppable, + ui_window_cocoa_focused, + "cocoa" +}; diff --git a/ui/drivers/ui_cocoa.h b/ui/drivers/ui_cocoa.h index 6b50692cef..11f6f5c5c0 100644 --- a/ui/drivers/ui_cocoa.h +++ b/ui/drivers/ui_cocoa.h @@ -36,7 +36,7 @@ typedef struct ui_application_cocoa typedef struct ui_window_cocoa { - void *data; + CocoaView *data; } ui_window_cocoa_t; RETRO_END_DECLS diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index bf917f53cf..b93d748cf3 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -38,46 +38,15 @@ #include "../../tasks/tasks_internal.h" #include ".././verbosity.h" -#ifdef HAVE_METAL -#import -#import -#endif - -#if !((defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))) -@interface WindowListener : NSResponder -@end - -@implementation WindowListener - -/* Similarly to SDL, we'll respond to key events by doing nothing so we don't beep. - */ -- (void)flagsChanged:(NSEvent *)event -{} - -- (void)keyDown:(NSEvent *)event -{} - -- (void)keyUp:(NSEvent *)event -{} - -@end -#endif - -id apple_platform; +id apple_platform; #if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) -@interface RetroArch_OSX : NSObject +@interface RetroArch_OSX : NSObject #else -@interface RetroArch_OSX : NSObject +@interface RetroArch_OSX : NSObject #endif { - NSWindow* _window; - apple_view_type_t _vt; - NSView* _renderView; - id _sleepActivity; -#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) - WindowListener *_listener; -#endif + NSWindow* _window; } @property (nonatomic, retain) NSWindow IBOutlet* window; @@ -88,55 +57,26 @@ static void app_terminate(void) { [[NSApplication sharedApplication] terminate:nil]; } -#ifdef HAVE_METAL -@interface RAWindow : NSWindow -@end -@implementation RAWindow -#else @interface RApplication : NSApplication @end @implementation RApplication -#endif -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 -#define NSEventTypeKeyDown NSKeyDown -#define NSEventTypeKeyUp NSKeyUp -#define NSEventTypeFlagsChanged NSFlagsChanged -#define NSEventTypeMouseMoved NSMouseMoved -#define NSEventTypeLeftMouseDragged NSLeftMouseDragged -#define NSEventTypeRightMouseDragged NSRightMouseDragged -#define NSEventTypeOtherMouseDragged NSOtherMouseDragged -#define NSEventTypeLeftMouseDown NSLeftMouseDown -#define NSEventTypeRightMouseDown NSRightMouseDown -#define NSEventTypeOtherMouseDown NSOtherMouseDown -#define NSEventTypeLeftMouseUp NSLeftMouseUp -#define NSEventTypeRightMouseUp NSRightMouseUp -#define NSEventTypeOtherMouseUp NSOtherMouseUp -#define NSEventTypeScrollWheel NSScrollWheel - -// modifier flags -#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask -#define NSEventModifierFlagShift NSShiftKeyMask -#define NSEventModifierFlagControl NSControlKeyMask -#define NSEventModifierFlagOption NSAlternateKeyMask -#define NSEventModifierFlagCommand NSCommandKeyMask -#define NSEventModifierFlagNumericPad NSNumericPadKeyMask -#endif - -- (void)sendEvent:(NSEvent *)event { - [super sendEvent:event]; - +- (void)sendEvent:(NSEvent *)event +{ + NSEventType event_type; cocoa_input_data_t *apple = NULL; - NSEventType event_type = event.type; + [super sendEvent:event]; - switch (event_type) + event_type = event.type; + + switch ((int32_t)event_type) { - case NSEventTypeKeyDown: - case NSEventTypeKeyUp: + case NSKeyDown: + case NSKeyUp: { - NSString* ch = event.characters; + NSString* ch = (NSString*)event.characters; uint32_t character = 0; uint32_t mod = 0; @@ -145,29 +85,29 @@ static void app_terminate(void) uint32_t i; character = [ch characterAtIndex:0]; - if (event.modifierFlags & NSEventModifierFlagCapsLock) + if (event.modifierFlags & NSAlphaShiftKeyMask) mod |= RETROKMOD_CAPSLOCK; - if (event.modifierFlags & NSEventModifierFlagShift) + if (event.modifierFlags & NSShiftKeyMask) mod |= RETROKMOD_SHIFT; - if (event.modifierFlags & NSEventModifierFlagControl) + if (event.modifierFlags & NSControlKeyMask) mod |= RETROKMOD_CTRL; - if (event.modifierFlags & NSEventModifierFlagOption) + if (event.modifierFlags & NSAlternateKeyMask) mod |= RETROKMOD_ALT; - if (event.modifierFlags & NSEventModifierFlagCommand) + if (event.modifierFlags & NSCommandKeyMask) mod |= RETROKMOD_META; - if (event.modifierFlags & NSEventModifierFlagNumericPad) + if (event.modifierFlags & NSNumericPadKeyMask) mod |= RETROKMOD_NUMLOCK; for (i = 1; i < ch.length; i++) - apple_input_keyboard_event(event_type == NSEventTypeKeyDown, + apple_input_keyboard_event(event_type == NSKeyDown, 0, [ch characterAtIndex:i], mod, RETRO_DEVICE_KEYBOARD); } - apple_input_keyboard_event(event_type == NSEventTypeKeyDown, + apple_input_keyboard_event(event_type == NSKeyDown, event.keyCode, character, mod, RETRO_DEVICE_KEYBOARD); } break; - case NSEventTypeFlagsChanged: + case NSFlagsChanged: { static uint32_t old_flags = 0; uint32_t new_flags = event.modifierFlags; @@ -179,10 +119,10 @@ static void app_terminate(void) 0, event.modifierFlags, RETRO_DEVICE_KEYBOARD); } break; - case NSEventTypeMouseMoved: - case NSEventTypeLeftMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeOtherMouseDragged: + case NSMouseMoved: + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: { NSPoint pos; NSPoint mouse_pos; @@ -191,27 +131,27 @@ static void app_terminate(void) return; /* Relative */ - apple->mouse_rel_x = (int16_t)event.deltaX; - apple->mouse_rel_y = (int16_t)event.deltaY; + apple->mouse_rel_x = event.deltaX; + apple->mouse_rel_y = event.deltaY; /* Absolute */ - pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; - apple->touches[0].screen_x = (int16_t)pos.x; - apple->touches[0].screen_y = (int16_t)pos.y; + pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil]; + apple->touches[0].screen_x = pos.x; + apple->touches[0].screen_y = pos.y; - mouse_pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + mouse_pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil]; apple->window_pos_x = (int16_t)mouse_pos.x; apple->window_pos_y = (int16_t)mouse_pos.y; } break; - case NSEventTypeScrollWheel: + case NSScrollWheel: /* TODO/FIXME - properly implement. */ break; - case NSEventTypeLeftMouseDown: - case NSEventTypeRightMouseDown: - case NSEventTypeOtherMouseDown: + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: { - NSPoint pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil]; apple = (cocoa_input_data_t*)input_driver_get_data(); if (!apple || pos.y < 0) return; @@ -220,11 +160,11 @@ static void app_terminate(void) apple->touch_count = 1; } break; - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseUp: - case NSEventTypeOtherMouseUp: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: { - NSPoint pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + NSPoint pos = [[CocoaView get] convertPoint:[event locationInWindow] fromView:nil]; apple = (cocoa_input_data_t*)input_driver_get_data(); if (!apple || pos.y < 0) return; @@ -232,8 +172,6 @@ static void app_terminate(void) apple->touch_count = 0; } break; - default: - break; } } @@ -246,41 +184,33 @@ static char** waiting_argv; @synthesize window = _window; -#if !__has_feature(objc_arc) - (void)dealloc { [_window release]; [super dealloc]; } -#endif #define NS_WINDOW_COLLECTION_BEHAVIOR_FULLSCREEN_PRIMARY (1 << 17) - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { unsigned i; - apple_platform = self; - SEL selector = NSSelectorFromString(BOXSTRING("setCollectionBehavior:")); SEL fsselector = NSSelectorFromString(BOXSTRING("toggleFullScreen:")); + apple_platform = self; if ([self.window respondsToSelector:selector]) { if ([self.window respondsToSelector:fsselector]) [self.window setCollectionBehavior:NS_WINDOW_COLLECTION_BEHAVIOR_FULLSCREEN_PRIMARY]; } - -#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) - _listener = [WindowListener new]; -#endif - + [self.window setAcceptsMouseMovedEvents: YES]; -#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) - [self.window setNextResponder:_listener]; - self.window.delegate = _listener; -#endif - + + [[CocoaView get] setFrame: [[self.window contentView] bounds]]; [[self.window contentView] setAutoresizesSubviews:YES]; + [[self.window contentView] addSubview:[CocoaView get]]; + [self.window makeFirstResponder:[CocoaView get]]; for (i = 0; i < waiting_argc; i++) { @@ -295,127 +225,10 @@ static char** waiting_argv; app_terminate(); waiting_argc = 0; - - [self.window makeMainWindow]; - [self.window makeKeyWindow]; - + [self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO]; } -#pragma mark - ApplePlatform - -- (void)setViewType:(apple_view_type_t)vt { - if (vt == _vt) { - return; - } - - RARCH_LOG("[Cocoa]: change view type: %d → %d\n", _vt, vt); - - _vt = vt; - if (_renderView != nil) - { - _renderView.wantsLayer = NO; - _renderView.layer = nil; - [_renderView removeFromSuperview]; - self.window.contentView = nil; - _renderView = nil; - } - - switch (vt) { - case APPLE_VIEW_TYPE_VULKAN: - case APPLE_VIEW_TYPE_METAL: -#if defined(HAVE_METAL) || defined(HAVE_VULKAN) - { - MetalView *v = [MetalView new]; - v.paused = YES; - v.enableSetNeedsDisplay = NO; - _renderView = v; - } -#endif - break; - - case APPLE_VIEW_TYPE_OPENGL: - { - _renderView = [CocoaView get]; - break; - } - - case APPLE_VIEW_TYPE_NONE: - default: - return; - } - - _renderView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - [_renderView setFrame: [[self.window contentView] bounds]]; - - self.window.contentView = _renderView; -#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) - [self.window.contentView setNextResponder:_listener]; -#endif -} - -- (apple_view_type_t)viewType { - return _vt; -} - -- (id)renderView { - return _renderView; -} - -- (bool)hasFocus { - return [NSApp isActive]; -} - -- (void)setVideoMode:(gfx_ctx_mode_t)mode { -#ifdef HAVE_METAL - BOOL isFullScreen = (self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; - if (mode.fullscreen && !isFullScreen) - { - [self.window toggleFullScreen:self]; - return; - } - - if (!mode.fullscreen && isFullScreen) - { - [self.window toggleFullScreen:self]; - } - - if (mode.width > 0) - { - // HACK(sgc): ensure MTKView posts a drawable resize event - [self.window setContentSize:NSMakeSize(mode.width-1, mode.height)]; - } - [self.window setContentSize:NSMakeSize(mode.width, mode.height)]; -#endif -} - -- (void)setCursorVisible:(bool)v { - if (v) - [NSCursor unhide]; - else - [NSCursor hide]; -} - -- (bool)setDisableDisplaySleep:(bool)disable -{ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 - if (disable && _sleepActivity == nil) - { - _sleepActivity = [NSProcessInfo.processInfo beginActivityWithOptions:NSActivityIdleDisplaySleepDisabled reason:@"disable screen saver"]; - } - else if (!disable && _sleepActivity != nil) - { - [NSProcessInfo.processInfo endActivity:_sleepActivity]; - _sleepActivity = nil; - } - return YES; -#else - return NO; -#endif - -} - - - (void) rarch_main { do @@ -470,7 +283,7 @@ static char** waiting_argv; if (rarch_ctl(RARCH_CTL_IS_INITED, NULL)) reply = NSTerminateCancel; - command_event(CMD_EVENT_QUIT, NULL); + ui_companion_event_command(CMD_EVENT_QUIT); return reply; } @@ -749,7 +562,7 @@ static void *ui_companion_cocoa_init(void) static void ui_companion_cocoa_event_command(void *data, enum event_command cmd) { (void)data; - (void)cmd; + command_event(cmd, NULL); } static void ui_companion_cocoa_notify_list_pushed(void *data, @@ -762,7 +575,7 @@ static void ui_companion_cocoa_notify_list_pushed(void *data, static void *ui_companion_cocoa_get_main_window(void *data) { - return (BRIDGE void *)((RetroArch_OSX*)[[NSApplication sharedApplication] delegate]).window; + return ((RetroArch_OSX*)[[NSApplication sharedApplication] delegate]).window; } ui_companion_driver_t ui_companion_cocoa = { diff --git a/ui/drivers/ui_cocoa_metal.h b/ui/drivers/ui_cocoa_metal.h new file mode 100644 index 0000000000..8bbe7cd8c7 --- /dev/null +++ b/ui/drivers/ui_cocoa_metal.h @@ -0,0 +1,44 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - 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 . + */ + +#ifndef _COCOA_METAL_UI +#define _COCOA_METAL_UI + +#include +#include + +#include +#include + +#include "cocoa/cocoa_common_metal.h" + +#include "../ui_companion_driver.h" + +RETRO_BEGIN_DECLS + +typedef struct ui_application_cocoa +{ + void *empty; +} ui_application_cocoa_t; + +typedef struct ui_window_cocoa +{ + void *data; +} ui_window_cocoa_t; + +RETRO_END_DECLS + +#endif diff --git a/ui/drivers/ui_cocoa_metal.m b/ui/drivers/ui_cocoa_metal.m new file mode 100644 index 0000000000..854fac7de5 --- /dev/null +++ b/ui/drivers/ui_cocoa_metal.m @@ -0,0 +1,786 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - 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 +#include +#include + +#include +#include +#include +#include +#include + +#include "cocoa/cocoa_common_metal.h" +#include "../ui_companion_driver.h" +#include "../../input/drivers/cocoa_input.h" +#include "../../input/drivers_keyboard/keyboard_event_apple.h" +#include "../../frontend/frontend.h" +#include "../../configuration.h" +#include "../../paths.h" +#include "../../core.h" +#include "../../retroarch.h" +#include "../../tasks/tasks_internal.h" +#include ".././verbosity.h" + +#ifdef HAVE_METAL +#import +#import +#endif + +#if !((defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))) +@interface WindowListener : NSResponder +@end + +@implementation WindowListener + +/* Similarly to SDL, we'll respond to key events by doing nothing so we don't beep. + */ +- (void)flagsChanged:(NSEvent *)event +{} + +- (void)keyDown:(NSEvent *)event +{} + +- (void)keyUp:(NSEvent *)event +{} + +@end +#endif + +id apple_platform; + +#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) +@interface RetroArch_OSX : NSObject +#else +@interface RetroArch_OSX : NSObject +#endif +{ + NSWindow* _window; + apple_view_type_t _vt; + NSView* _renderView; + id _sleepActivity; +#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) + WindowListener *_listener; +#endif +} + +@property (nonatomic, retain) NSWindow IBOutlet* window; + +@end + +static void app_terminate(void) +{ + [[NSApplication sharedApplication] terminate:nil]; +} +#ifdef HAVE_METAL +@interface RAWindow : NSWindow +@end + +@implementation RAWindow +#else +@interface RApplication : NSApplication +@end + +@implementation RApplication +#endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 +#define NSEventTypeKeyDown NSKeyDown +#define NSEventTypeKeyUp NSKeyUp +#define NSEventTypeFlagsChanged NSFlagsChanged +#define NSEventTypeMouseMoved NSMouseMoved +#define NSEventTypeLeftMouseDragged NSLeftMouseDragged +#define NSEventTypeRightMouseDragged NSRightMouseDragged +#define NSEventTypeOtherMouseDragged NSOtherMouseDragged +#define NSEventTypeLeftMouseDown NSLeftMouseDown +#define NSEventTypeRightMouseDown NSRightMouseDown +#define NSEventTypeOtherMouseDown NSOtherMouseDown +#define NSEventTypeLeftMouseUp NSLeftMouseUp +#define NSEventTypeRightMouseUp NSRightMouseUp +#define NSEventTypeOtherMouseUp NSOtherMouseUp +#define NSEventTypeScrollWheel NSScrollWheel + +// modifier flags +#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask +#define NSEventModifierFlagShift NSShiftKeyMask +#define NSEventModifierFlagControl NSControlKeyMask +#define NSEventModifierFlagOption NSAlternateKeyMask +#define NSEventModifierFlagCommand NSCommandKeyMask +#define NSEventModifierFlagNumericPad NSNumericPadKeyMask +#endif + +- (void)sendEvent:(NSEvent *)event { + [super sendEvent:event]; + + cocoa_input_data_t *apple = NULL; + NSEventType event_type = event.type; + + switch (event_type) + { + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: + { + NSString* ch = 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 & NSEventModifierFlagCapsLock) + mod |= RETROKMOD_CAPSLOCK; + if (event.modifierFlags & NSEventModifierFlagShift) + mod |= RETROKMOD_SHIFT; + if (event.modifierFlags & NSEventModifierFlagControl) + mod |= RETROKMOD_CTRL; + if (event.modifierFlags & NSEventModifierFlagOption) + mod |= RETROKMOD_ALT; + if (event.modifierFlags & NSEventModifierFlagCommand) + mod |= RETROKMOD_META; + if (event.modifierFlags & NSEventModifierFlagNumericPad) + mod |= RETROKMOD_NUMLOCK; + + for (i = 1; i < ch.length; i++) + apple_input_keyboard_event(event_type == NSEventTypeKeyDown, + 0, [ch characterAtIndex:i], mod, RETRO_DEVICE_KEYBOARD); + } + + apple_input_keyboard_event(event_type == NSEventTypeKeyDown, + event.keyCode, character, mod, RETRO_DEVICE_KEYBOARD); + } + break; + case NSEventTypeFlagsChanged: + { + static uint32_t old_flags = 0; + uint32_t new_flags = event.modifierFlags; + bool down = (new_flags & old_flags) == old_flags; + + old_flags = new_flags; + + apple_input_keyboard_event(down, event.keyCode, + 0, event.modifierFlags, RETRO_DEVICE_KEYBOARD); + } + break; + case NSEventTypeMouseMoved: + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeOtherMouseDragged: + { + NSPoint pos; + NSPoint mouse_pos; + apple = (cocoa_input_data_t*)input_driver_get_data(); + if (!apple) + return; + + /* Relative */ + apple->mouse_rel_x = (int16_t)event.deltaX; + apple->mouse_rel_y = (int16_t)event.deltaY; + + /* Absolute */ + pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + apple->touches[0].screen_x = (int16_t)pos.x; + apple->touches[0].screen_y = (int16_t)pos.y; + + mouse_pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + apple->window_pos_x = (int16_t)mouse_pos.x; + apple->window_pos_y = (int16_t)mouse_pos.y; + } + break; + case NSEventTypeScrollWheel: + /* TODO/FIXME - properly implement. */ + break; + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + { + NSPoint pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + apple = (cocoa_input_data_t*)input_driver_get_data(); + if (!apple || pos.y < 0) + return; + apple->mouse_buttons |= 1 << event.buttonNumber; + + apple->touch_count = 1; + } + break; + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseUp: + case NSEventTypeOtherMouseUp: + { + NSPoint pos = [apple_platform.renderView convertPoint:[event locationInWindow] fromView:nil]; + apple = (cocoa_input_data_t*)input_driver_get_data(); + if (!apple || pos.y < 0) + return; + apple->mouse_buttons &= ~(1 << event.buttonNumber); + apple->touch_count = 0; + } + break; + default: + break; + } +} + +@end + +static int waiting_argc; +static char** waiting_argv; + +@implementation RetroArch_OSX + +@synthesize window = _window; + +#if !__has_feature(objc_arc) +- (void)dealloc +{ + [_window release]; + [super dealloc]; +} +#endif + +#define NS_WINDOW_COLLECTION_BEHAVIOR_FULLSCREEN_PRIMARY (1 << 17) + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + unsigned i; + apple_platform = self; + + SEL selector = NSSelectorFromString(BOXSTRING("setCollectionBehavior:")); + SEL fsselector = NSSelectorFromString(BOXSTRING("toggleFullScreen:")); + + if ([self.window respondsToSelector:selector]) + { + if ([self.window respondsToSelector:fsselector]) + [self.window setCollectionBehavior:NS_WINDOW_COLLECTION_BEHAVIOR_FULLSCREEN_PRIMARY]; + } + +#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) + _listener = [WindowListener new]; +#endif + + [self.window setAcceptsMouseMovedEvents: YES]; +#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) + [self.window setNextResponder:_listener]; + self.window.delegate = _listener; +#endif + + [[self.window contentView] setAutoresizesSubviews:YES]; + + for (i = 0; i < waiting_argc; i++) + { + if (string_is_equal(waiting_argv[i], "-NSDocumentRevisionsDebugMode")) + { + waiting_argv[i] = NULL; + waiting_argv[i+1] = NULL; + waiting_argc -= 2; + } + } + if (rarch_main(waiting_argc, waiting_argv, NULL)) + app_terminate(); + + waiting_argc = 0; + + [self.window makeMainWindow]; + [self.window makeKeyWindow]; + + [self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO]; +} + +#pragma mark - ApplePlatform + +- (void)setViewType:(apple_view_type_t)vt { + if (vt == _vt) { + return; + } + + RARCH_LOG("[Cocoa]: change view type: %d → %d\n", _vt, vt); + + _vt = vt; + if (_renderView != nil) + { + _renderView.wantsLayer = NO; + _renderView.layer = nil; + [_renderView removeFromSuperview]; + self.window.contentView = nil; + _renderView = nil; + } + + switch (vt) { + case APPLE_VIEW_TYPE_VULKAN: + case APPLE_VIEW_TYPE_METAL: +#if defined(HAVE_METAL) || defined(HAVE_VULKAN) + { + MetalView *v = [MetalView new]; + v.paused = YES; + v.enableSetNeedsDisplay = NO; + _renderView = v; + } +#endif + break; + + case APPLE_VIEW_TYPE_OPENGL: + { + _renderView = [CocoaView get]; + break; + } + + case APPLE_VIEW_TYPE_NONE: + default: + return; + } + + _renderView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; + [_renderView setFrame: [[self.window contentView] bounds]]; + + self.window.contentView = _renderView; +#if !(defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))) + [self.window.contentView setNextResponder:_listener]; +#endif +} + +- (apple_view_type_t)viewType { + return _vt; +} + +- (id)renderView { + return _renderView; +} + +- (bool)hasFocus { + return [NSApp isActive]; +} + +- (void)setVideoMode:(gfx_ctx_mode_t)mode { +#ifdef HAVE_METAL + BOOL isFullScreen = (self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; + if (mode.fullscreen && !isFullScreen) + { + [self.window toggleFullScreen:self]; + return; + } + + if (!mode.fullscreen && isFullScreen) + { + [self.window toggleFullScreen:self]; + } + + if (mode.width > 0) + { + // HACK(sgc): ensure MTKView posts a drawable resize event + [self.window setContentSize:NSMakeSize(mode.width-1, mode.height)]; + } + [self.window setContentSize:NSMakeSize(mode.width, mode.height)]; +#endif +} + +- (void)setCursorVisible:(bool)v { + if (v) + [NSCursor unhide]; + else + [NSCursor hide]; +} + +- (bool)setDisableDisplaySleep:(bool)disable +{ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + if (disable && _sleepActivity == nil) + { + _sleepActivity = [NSProcessInfo.processInfo beginActivityWithOptions:NSActivityIdleDisplaySleepDisabled reason:@"disable screen saver"]; + } + else if (!disable && _sleepActivity != nil) + { + [NSProcessInfo.processInfo endActivity:_sleepActivity]; + _sleepActivity = nil; + } + return YES; +#else + return NO; +#endif + +} + + +- (void) rarch_main +{ + do + { + int ret; + unsigned sleep_ms = 0; +#ifdef HAVE_QT + const ui_application_t *application = &ui_application_qt; +#else + const ui_application_t *application = ui_companion_driver_get_application_ptr(); +#endif + if (application) + application->process_events(); + + ret = runloop_iterate(&sleep_ms); + + if (ret == 1 && sleep_ms > 0) + retro_sleep(sleep_ms); + + task_queue_check(); + + while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, FALSE) == kCFRunLoopRunHandledSource); + if (ret == -1) + { +#ifdef HAVE_QT + ui_application_qt.quit(); +#endif + break; + } + }while(1); + + main_exit(NULL); +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification +{ +} + +- (void)applicationWillResignActive:(NSNotification *)notification +{ +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication +{ + return YES; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + NSApplicationTerminateReply reply = NSTerminateNow; + + if (rarch_ctl(RARCH_CTL_IS_INITED, NULL)) + reply = NSTerminateCancel; + + command_event(CMD_EVENT_QUIT, NULL); + + return reply; +} + + +- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames +{ + if (filenames.count == 1 && [filenames objectAtIndex:0]) + { + struct retro_system_info *system = runloop_get_libretro_system_info(); + NSString *__core = [filenames objectAtIndex:0]; + const char *core_name = system ? system->library_name : NULL; + + if (core_name) + { + content_ctx_info_t content_info = {0}; + task_push_load_content_with_current_core_from_companion_ui( + __core.UTF8String, + &content_info, + CORE_TYPE_PLAIN, + NULL, NULL); + } + else + path_set(RARCH_PATH_CONTENT, __core.UTF8String); + + [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; + } + else + { + const ui_msg_window_t *msg_window = ui_companion_driver_get_msg_window_ptr(); + if (msg_window) + { + ui_msg_window_state msg_window_state; + msg_window_state.text = strdup("Cannot open multiple files"); + msg_window_state.title = strdup(msg_hash_to_str(MSG_PROGRAM)); + msg_window->information(&msg_window_state); + + free(msg_window_state.text); + free(msg_window_state.title); + } + [sender replyToOpenOrPrint:NSApplicationDelegateReplyFailure]; + } +} + +static void open_core_handler(ui_browser_window_state_t *state, bool result) +{ + rarch_system_info_t *info = runloop_get_system_info(); + if (!state) + return; + if (string_is_empty(state->result)) + return; + if (!result) + return; + + settings_t *settings = config_get_ptr(); + + rarch_ctl(RARCH_CTL_SET_LIBRETRO_PATH, (void*)state->result); + ui_companion_event_command(CMD_EVENT_LOAD_CORE); + + if (info && info->load_no_content + && settings->bools.set_supports_no_game_enable) + { + content_ctx_info_t content_info = {0}; + path_clear(RARCH_PATH_CONTENT); + task_push_load_content_with_current_core_from_companion_ui( + NULL, + &content_info, + CORE_TYPE_PLAIN, + NULL, NULL); + } +} + +static void open_document_handler(ui_browser_window_state_t *state, bool result) +{ + if (!state) + return; + if (string_is_empty(state->result)) + return; + if (!result) + return; + + struct retro_system_info *system = runloop_get_libretro_system_info(); + const char *core_name = system ? system->library_name : NULL; + + path_set(RARCH_PATH_CONTENT, state->result); + + if (core_name) + { + content_ctx_info_t content_info = {0}; + task_push_load_content_with_current_core_from_companion_ui( + NULL, + &content_info, + CORE_TYPE_PLAIN, + NULL, NULL); + } +} + +- (IBAction)openCore:(id)sender { + const ui_browser_window_t *browser = ui_companion_driver_get_browser_window_ptr(); + + if (browser) + { + ui_browser_window_state_t browser_state; + settings_t *settings = config_get_ptr(); + + browser_state.filters = strdup("dylib"); + browser_state.filters_title = strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_SETTINGS)); + browser_state.title = strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_LIST)); + browser_state.startdir = strdup(settings->paths.directory_libretro); + + bool result = browser->open(&browser_state); + open_core_handler(&browser_state, result); + + free(browser_state.filters); + free(browser_state.filters_title); + free(browser_state.title); + free(browser_state.startdir); + } +} + +- (void)openDocument:(id)sender +{ + const ui_browser_window_t *browser = ui_companion_driver_get_browser_window_ptr(); + + if (browser) + { + ui_browser_window_state_t browser_state = {{0}}; + settings_t *settings = config_get_ptr(); + NSString *startdir = BOXSTRING(settings->paths.directory_menu_content); + + if (!startdir.length) + startdir = BOXSTRING("/"); + + browser_state.title = strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST)); + browser_state.startdir = strdup([startdir UTF8String]); + + bool result = browser->open(&browser_state); + open_document_handler(&browser_state, result); + + free(browser_state.startdir); + free(browser_state.title); + } +} + +- (void)unloadingCore +{ +} + +- (IBAction)showCoresDirectory:(id)sender +{ + settings_t *settings = config_get_ptr(); + [[NSWorkspace sharedWorkspace] openFile:BOXSTRING(settings->paths.directory_libretro)]; +} + +- (IBAction)showPreferences:(id)sender +{ +} + +- (IBAction)basicEvent:(id)sender +{ + enum event_command cmd; + unsigned sender_tag = (unsigned)[sender tag]; + + switch (sender_tag) + { + case 1: + cmd = CMD_EVENT_RESET; + break; + case 2: + cmd = CMD_EVENT_LOAD_STATE; + break; + case 3: + cmd = CMD_EVENT_SAVE_STATE; + break; + case 4: + cmd = CMD_EVENT_DISK_EJECT_TOGGLE; + break; + case 5: + cmd = CMD_EVENT_DISK_PREV; + break; + case 6: + cmd = CMD_EVENT_DISK_NEXT; + break; + case 7: + cmd = CMD_EVENT_GRAB_MOUSE_TOGGLE; + break; + case 8: + cmd = CMD_EVENT_MENU_TOGGLE; + break; + case 9: + cmd = CMD_EVENT_PAUSE_TOGGLE; + break; + case 20: + cmd = CMD_EVENT_FULLSCREEN_TOGGLE; + break; + default: + cmd = CMD_EVENT_NONE; + break; + } + + if (sender_tag >= 10 && sender_tag <= 19) + { + unsigned idx = (sender_tag - (10-1)); + rarch_ctl(RARCH_CTL_SET_WINDOWED_SCALE, &idx); + cmd = CMD_EVENT_RESIZE_WINDOWED_SCALE; + } + + ui_companion_event_command(cmd); +} + +- (void)alertDidEnd:(NSAlert *)alert returnCode:(int32_t)returnCode contextInfo:(void *)contextInfo +{ + [[NSApplication sharedApplication] stopModal]; +} + +@end + +int main(int argc, char *argv[]) +{ + if (argc == 2) + { + if (argv[1] != '\0') + if (!strncmp(argv[1], "-psn", 4)) + argc = 1; + } + + waiting_argc = argc; + waiting_argv = argv; + + return NSApplicationMain(argc, (const char **) argv); +} + +typedef struct ui_companion_cocoa +{ + void *empty; +} ui_companion_cocoa_t; + +static void ui_companion_cocoa_notify_content_loaded(void *data) +{ + (void)data; +} + +static void ui_companion_cocoa_toggle(void *data, bool force) +{ + (void)data; + (void)force; +} + +static int ui_companion_cocoa_iterate(void *data, unsigned action) +{ + (void)data; + + return 0; +} + +static void ui_companion_cocoa_deinit(void *data) +{ + ui_companion_cocoa_t *handle = (ui_companion_cocoa_t*)data; + + app_terminate(); + + if (handle) + free(handle); +} + +static void *ui_companion_cocoa_init(void) +{ + ui_companion_cocoa_t *handle = (ui_companion_cocoa_t*)calloc(1, sizeof(*handle)); + + if (!handle) + return NULL; + + return handle; +} + +static void ui_companion_cocoa_event_command(void *data, enum event_command cmd) +{ + (void)data; + (void)cmd; +} + +static void ui_companion_cocoa_notify_list_pushed(void *data, + file_list_t *list, file_list_t *menu_list) +{ + (void)data; + (void)list; + (void)menu_list; +} + +static void *ui_companion_cocoa_get_main_window(void *data) +{ + return (BRIDGE void *)((RetroArch_OSX*)[[NSApplication sharedApplication] delegate]).window; +} + +ui_companion_driver_t ui_companion_cocoa = { + ui_companion_cocoa_init, + ui_companion_cocoa_deinit, + ui_companion_cocoa_iterate, + ui_companion_cocoa_toggle, + ui_companion_cocoa_event_command, + ui_companion_cocoa_notify_content_loaded, + ui_companion_cocoa_notify_list_pushed, + NULL, /* notify_refresh */ + NULL, /* msg_queue_push */ + NULL, /* render_messagebox */ + ui_companion_cocoa_get_main_window, + NULL, /* log_msg */ + &ui_browser_window_cocoa, + &ui_msg_window_cocoa, + &ui_window_cocoa, + &ui_application_cocoa, + "cocoa", +}; diff --git a/ui/drivers/ui_cocoatouch.m b/ui/drivers/ui_cocoatouch.m index 4e637feb21..04fb6d4065 100644 --- a/ui/drivers/ui_cocoatouch.m +++ b/ui/drivers/ui_cocoatouch.m @@ -41,7 +41,7 @@ #endif static char msg_old[PATH_MAX_LENGTH]; -id apple_platform; +static id apple_platform; static CFRunLoopObserverRef iterate_observer; /* forward declaration */ @@ -79,6 +79,7 @@ static void ui_companion_cocoatouch_event_command( void *data, enum event_command cmd) { (void)data; + command_event(cmd, NULL); } static void rarch_draw_observer(CFRunLoopObserverRef observer, @@ -239,7 +240,7 @@ enum // This is for iOS versions < 9.0 - (id)_keyCommandForEvent:(UIEvent*)event { - /* This gets called twice with the same timestamp + /* 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; @@ -248,7 +249,7 @@ enum return [super _keyCommandForEvent:event]; last_time_stamp = event.timestamp; - /* If the _hidEvent is null, [event _keyCode] will crash. + /* If the _hidEvent is null, [event _keyCode] will crash. * (This happens with the on screen keyboard). */ if (event._hidEvent) { @@ -299,13 +300,13 @@ enum handle_touch_event(event.allTouches.allObjects); get_ios_version(&major, &minor); - + #if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000 if ((major < 7) && [event respondsToSelector:@selector(_gsEvent)]) { /* Keyboard event hack for iOS versions prior to iOS 7. * - * Derived from: + * 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)]); @@ -379,7 +380,7 @@ enum iterate_observer = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting, true, 0, rarch_draw_observer, 0); CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); - + #ifdef HAVE_MFI extern bool apple_gamecontroller_joypad_init(void *data); apple_gamecontroller_joypad_init(NULL); @@ -430,7 +431,7 @@ enum { NSString *filename = (NSString*)url.path.lastPathComponent; NSError *error = nil; - + [[NSFileManager defaultManager] moveItemAtPath:[url path] toPath:[self.documentsDirectory stringByAppendingPathComponent:filename] error:&error]; if (error) @@ -497,11 +498,11 @@ enum if (string_is_equal(apple_frontend_settings.orientations, "landscape")) apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskLandscape; else if (string_is_equal(apple_frontend_settings.orientations, "portrait")) - apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskPortrait + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; } -- (void)mainMenuRefresh +- (void)mainMenuRefresh { [self.mainmenu reloadData]; } @@ -525,7 +526,7 @@ enum self.menu_count--; [self popViewControllerAnimated:YES]; - self.mainmenu = self.mainmenu.last_menu; + self.mainmenu = self.mainmenu.last_menu; } } } @@ -593,7 +594,7 @@ static void ui_companion_cocoatouch_notify_content_loaded(void *data) [ap showGameView]; } -static void ui_companion_cocoatouch_toggle(void *data, bool force) +static void ui_companion_cocoatouch_toggle(void *data) { RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; @@ -608,7 +609,7 @@ static int ui_companion_cocoatouch_iterate(void *data, unsigned action) RetroArch_iOS *ap = (RetroArch_iOS*)apple_platform; (void)data; - + if (ap) [ap showPauseMenu:ap]; @@ -662,7 +663,7 @@ static void ui_companion_cocoatouch_notify_list_pushed(void *data, printf( "notify_list_pushed: old size should not be larger\n" ); old_size = new_size; - + if (ap) [ap mainMenuPushPop: pushp]; } @@ -686,9 +687,8 @@ static void ui_companion_cocoatouch_render_messagebox(const char *msg) } } -static void ui_companion_cocoatouch_msg_queue_push(void *data, - const char *msg, - unsigned priority, unsigned duration, bool flush) +static void ui_companion_cocoatouch_msg_queue_push(const char *msg, + unsigned priority, unsigned duration, bool flush) { RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; diff --git a/ui/drivers/ui_cocoatouch_metal.m b/ui/drivers/ui_cocoatouch_metal.m new file mode 100644 index 0000000000..b1c21a624a --- /dev/null +++ b/ui/drivers/ui_cocoatouch_metal.m @@ -0,0 +1,719 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2016 - 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 +#include + +#include + +#include +#include +#include +#include + +#include "cocoa/cocoa_common_metal.h" +#include "../ui_companion_driver.h" +#include "../../configuration.h" +#include "../../frontend/frontend.h" +#include "../../input/drivers/cocoa_input.h" +#include "../../input/drivers_keyboard/keyboard_event_apple.h" +#include "../../retroarch.h" +#ifdef HAVE_AVFOUNDATION +#import +#endif + +#ifdef HAVE_MENU +#include "../../menu/menu_setting.h" +#endif + +static char msg_old[PATH_MAX_LENGTH]; +id apple_platform; +static CFRunLoopObserverRef iterate_observer; + +/* forward declaration */ +static void apple_rarch_exited(void); + +static void rarch_enable_ui(void) +{ + bool boolean = true; +#ifdef HAVE_AVFOUNDATION + [[RetroArch_iOS get] supportOtherAudioSessions]; +#endif + + ui_companion_set_foreground(true); + + rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean); + rarch_ctl(RARCH_CTL_SET_IDLE, &boolean); + rarch_menu_running(); +} + +static void rarch_disable_ui(void) +{ + bool boolean = false; + + ui_companion_set_foreground(false); + + rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean); + rarch_ctl(RARCH_CTL_SET_IDLE, &boolean); + rarch_menu_running_finished(); +#ifdef HAVE_AVFOUNDATION + [[RetroArch_iOS get] supportOtherAudioSessions]; +#endif +} + +static void ui_companion_cocoatouch_event_command( + void *data, enum event_command cmd) +{ + (void)data; +} + +static void rarch_draw_observer(CFRunLoopObserverRef observer, + CFRunLoopActivity activity, void *info) +{ + unsigned sleep_ms = 0; + int ret = runloop_iterate(&sleep_ms); + + if (ret == 1 && !ui_companion_is_on_foreground() && sleep_ms > 0) + retro_sleep(sleep_ms); + task_queue_check(); + + if (ret == -1) + { + ui_companion_cocoatouch_event_command(NULL, CMD_EVENT_MENU_SAVE_CURRENT_CONFIG); + main_exit(NULL); + return; + } + + if (rarch_ctl(RARCH_CTL_IS_IDLE, NULL)) + return; + CFRunLoopWakeUp(CFRunLoopGetMain()); +} + +apple_frontend_settings_t apple_frontend_settings; + +void get_ios_version(int *major, int *minor) +{ + NSArray *decomposed_os_version = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; + + if (major && decomposed_os_version.count > 0) + *major = (int)[decomposed_os_version[0] integerValue]; + if (minor && decomposed_os_version.count > 1) + *minor = (int)[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; + cocoa_input_data_t *apple = (cocoa_input_data_t*)input_driver_get_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 != [CocoaView 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; + } + } +} + +#ifndef HAVE_APPLE_STORE +// 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) +- (void)handleKeyUIEvent:(UIEvent*)event; +- (id)_keyCommandForEvent:(UIEvent*)event; +@end +#endif + +@interface RApplication : UIApplication +@end + +@implementation RApplication + +#ifndef HAVE_APPLE_STORE +/* 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 +}; + +// This is specifically for iOS 9, according to the private headers +-(void)handleKeyUIEvent:(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 handleKeyUIEvent: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]; + + apple_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, 0, mod, + RETRO_DEVICE_KEYBOARD); + + for (i = 1; i < ch.length; i++) + apple_input_keyboard_event(event._isKeyDown, + 0, [ch characterAtIndex:i], mod, + RETRO_DEVICE_KEYBOARD); + } + + apple_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, character, mod, + RETRO_DEVICE_KEYBOARD); + } + + [super handleKeyUIEvent:event]; +} + +// This is for iOS versions < 9.0 +- (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]; + + apple_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, 0, mod, + RETRO_DEVICE_KEYBOARD); + + for (i = 1; i < ch.length; i++) + apple_input_keyboard_event(event._isKeyDown, + 0, [ch characterAtIndex:i], mod, + RETRO_DEVICE_KEYBOARD); + } + + apple_input_keyboard_event(event._isKeyDown, + (uint32_t)event._keyCode, character, mod, + RETRO_DEVICE_KEYBOARD); + } + + return [super _keyCommandForEvent:event]; +} +#endif + +#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 __IPHONE_OS_VERSION_MAX_ALLOWED < 70000 + 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: + apple_input_keyboard_event(eventType == GSEVENT_TYPE_KEYDOWN, + *(uint16_t*)&eventMem[0x3C], 0, 0, RETRO_DEVICE_KEYBOARD); + break; + } + } +#endif +} + +@end + +@implementation RetroArch_iOS + ++ (RetroArch_iOS*)get +{ +#ifdef HAVE_AVFOUNDATION + /* Implicitly initializes your audio session. */ + [(RetroArch_iOS*)[[UIApplication sharedApplication] delegate] supportOtherAudioSessions]; +#endif + return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate]; +} + +-(NSString*)documentsDirectory { + if ( _documentsDirectory == nil ) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + _documentsDirectory = paths.firstObject; + } + return _documentsDirectory; +} + +- (void)applicationDidFinishLaunching:(UIApplication *)application +{ + char arguments[] = "retroarch"; + char *argv[] = {arguments, NULL}; + int argc = 1; + apple_platform = self; + + [self setDelegate:self]; + +#ifdef HAVE_AVFOUNDATION + /* Other background audio check */ + [self supportOtherAudioSessions]; +#endif + + /* Setup window */ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [self.window makeKeyAndVisible]; + + self.mainmenu = [RAMainMenu new]; + self.mainmenu.last_menu = self.mainmenu; + [self pushViewController:self.mainmenu animated:NO]; + + [self refreshSystemConfig]; + [self showGameView]; + +#ifdef HAVE_AVFOUNDATION + [self supportOtherAudioSessions]; +#endif + + if (rarch_main(argc, argv, NULL)) + apple_rarch_exited(); + + iterate_observer = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting, + true, 0, rarch_draw_observer, 0); + CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); + +#ifdef HAVE_MFI + extern bool apple_gamecontroller_joypad_init(void *data); + apple_gamecontroller_joypad_init(NULL); +#endif + +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ +#ifdef HAVE_AVFOUNDATION + [self supportOtherAudioSessions]; +#endif +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + CFRunLoopObserverInvalidate(iterate_observer); + CFRelease(iterate_observer); + iterate_observer = NULL; +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + settings_t *settings = config_get_ptr(); + +#ifdef HAVE_AVFOUNDATION + [self supportOtherAudioSessions]; +#endif + if (settings->bools.ui_companion_start_on_boot) + return; + + [self showGameView]; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ +#ifdef HAVE_AVFOUNDATION + [self supportOtherAudioSessions]; +#endif + dispatch_async(dispatch_get_main_queue(), + ^{ + ui_companion_cocoatouch_event_command(NULL, CMD_EVENT_MENU_SAVE_CURRENT_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 +{ + [self setToolbarHidden:![[viewController toolbarItems] count] animated:YES]; + [self refreshSystemConfig]; +} + +- (void)showGameView +{ +#ifdef HAVE_AVFOUNDATION + /* implicitly initializes your audio session */ + [self supportOtherAudioSessions]; +#endif + [self popToRootViewControllerAnimated:NO]; + [self setToolbarHidden:true animated:NO]; + [[UIApplication sharedApplication] setStatusBarHidden:true withAnimation:UIStatusBarAnimationNone]; + [[UIApplication sharedApplication] setIdleTimerDisabled:true]; + [self.window setRootViewController:[CocoaView get]]; + + ui_companion_cocoatouch_event_command(NULL, CMD_EVENT_AUDIO_START); + rarch_disable_ui(); +} + +- (IBAction)showPauseMenu:(id)sender +{ +#ifndef HAVE_AVFOUNDATION + ui_companion_cocoatouch_event_command(NULL, CMD_EVENT_AUDIO_STOP); +#endif + rarch_enable_ui(); + + [[UIApplication sharedApplication] setStatusBarHidden:false withAnimation:UIStatusBarAnimationNone]; + [[UIApplication sharedApplication] setIdleTimerDisabled:false]; + [self.window setRootViewController:self]; +} + + +- (void)toggleUI +{ + if (ui_companion_is_on_foreground()) + { + [self showGameView]; + } + else + { + [self showPauseMenu:self]; + } +#ifdef HAVE_AVFOUNDATION + [self supportOtherAudioSessions]; +#endif +} + +- (void)refreshSystemConfig +{ + /* Get enabled orientations */ + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskAll; + + if (string_is_equal(apple_frontend_settings.orientations, "landscape")) + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskLandscape; + else if (string_is_equal(apple_frontend_settings.orientations, "portrait")) + apple_frontend_settings.orientation_flags = UIInterfaceOrientationMaskPortrait + | UIInterfaceOrientationMaskPortraitUpsideDown; +} + +- (void)mainMenuRefresh +{ + [self.mainmenu reloadData]; +} + +- (void)mainMenuPushPop: (bool)pushp +{ + if ( pushp ) + { + self.menu_count++; + RAMenuBase* next_menu = [RAMainMenu new]; + next_menu.last_menu = self.mainmenu; + self.mainmenu = next_menu; + [self pushViewController:self.mainmenu animated:YES]; + } + else + { + if ( self.menu_count == 0 ) + [self.mainmenu reloadData]; + else + { + self.menu_count--; + + [self popViewControllerAnimated:YES]; + self.mainmenu = self.mainmenu.last_menu; + } + } +} + +- (void)supportOtherAudioSessions +{ +#ifdef HAVE_AVFOUNDATION + /* implicitly initializes your audio session */ + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + [audioSession setCategory: AVAudioSessionCategoryAmbient error: nil]; + [audioSession setActive:YES error:nil]; +#endif +} + +- (void)mainMenuRenderMessageBox:(NSString *)msg +{ + [self.mainmenu renderMessageBox:msg]; +} + +@end + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class])); + } +} + +#if 0 +static void apple_display_alert(const char *message, const char *title) +{ + UIAlertView* alert = [[UIAlertView alloc] initWithTitle:BOXSTRING(title) + message:BOXSTRING(message) + delegate:nil + cancelButtonTitle:BOXSTRING("OK") + otherButtonTitles:nil]; + [alert show]; +} +#endif + +static void apple_rarch_exited(void) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + if (!ap) + return; +#ifdef HAVE_AVFOUNDATION + [ap supportOtherAudioSessions]; +#endif + [ap showPauseMenu:ap]; +} + +typedef struct ui_companion_cocoatouch +{ + void *empty; +} ui_companion_cocoatouch_t; + +static void ui_companion_cocoatouch_notify_content_loaded(void *data) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + (void)data; + + if (ap) + [ap showGameView]; +} + +static void ui_companion_cocoatouch_toggle(void *data, bool force) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + (void)data; + + if (ap) + [ap toggleUI]; +} + +static int ui_companion_cocoatouch_iterate(void *data, unsigned action) +{ + RetroArch_iOS *ap = (RetroArch_iOS*)apple_platform; + + (void)data; + + if (ap) + [ap showPauseMenu:ap]; + + return 0; +} + +static void ui_companion_cocoatouch_deinit(void *data) +{ + ui_companion_cocoatouch_t *handle = (ui_companion_cocoatouch_t*)data; + + apple_rarch_exited(); + + if (handle) + free(handle); +} + +static void *ui_companion_cocoatouch_init(void) +{ + ui_companion_cocoatouch_t *handle = (ui_companion_cocoatouch_t*) + calloc(1, sizeof(*handle)); + + if (!handle) + return NULL; + + rarch_enable_ui(); + + return handle; +} + +static size_t old_size = 0; + +static void ui_companion_cocoatouch_notify_list_pushed(void *data, + file_list_t *list, file_list_t *menu_list) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + bool pushp = false; + size_t new_size = file_list_get_size( menu_list ); + + /* FIXME workaround for the double call */ + if ( old_size == 0 ) + { + old_size = new_size; + return; + } + + if ( old_size == new_size ) + pushp = false; + else if ( old_size < new_size ) + pushp = true; + else if ( old_size > new_size ) + printf( "notify_list_pushed: old size should not be larger\n" ); + + old_size = new_size; + + if (ap) + [ap mainMenuPushPop: pushp]; +} + +static void ui_companion_cocoatouch_notify_refresh(void *data) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + if (ap) + [ap mainMenuRefresh]; +} + +static void ui_companion_cocoatouch_render_messagebox(const char *msg) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + if (ap && !string_is_equal(msg, msg_old)) + { + [ap mainMenuRenderMessageBox: [NSString stringWithUTF8String:msg]]; + strlcpy(msg_old, msg, sizeof(msg_old)); + } +} + +static void ui_companion_cocoatouch_msg_queue_push(void *data, + const char *msg, + unsigned priority, unsigned duration, bool flush) +{ + RetroArch_iOS *ap = (RetroArch_iOS *)apple_platform; + + if (ap && msg) + { + [ap.mainmenu msgQueuePush: [NSString stringWithUTF8String:msg]]; + } +} + +ui_companion_driver_t ui_companion_cocoatouch = { + ui_companion_cocoatouch_init, + ui_companion_cocoatouch_deinit, + ui_companion_cocoatouch_iterate, + ui_companion_cocoatouch_toggle, + ui_companion_cocoatouch_event_command, + ui_companion_cocoatouch_notify_content_loaded, + ui_companion_cocoatouch_notify_list_pushed, + ui_companion_cocoatouch_notify_refresh, + ui_companion_cocoatouch_msg_queue_push, + ui_companion_cocoatouch_render_messagebox, + NULL, /* get_main_window */ + NULL, /* log_msg */ + &ui_browser_window_null, + &ui_msg_window_null, + &ui_window_null, + &ui_application_null, + "cocoatouch", +}; diff --git a/ui/ui_companion_driver.c b/ui/ui_companion_driver.c index a866b6749b..daeae6e1d3 100644 --- a/ui/ui_companion_driver.c +++ b/ui/ui_companion_driver.c @@ -30,7 +30,7 @@ static const ui_companion_driver_t *ui_companion_drivers[] = { #if defined(_WIN32) && !defined(_XBOX) &ui_companion_win32, #endif -#ifdef HAVE_COCOA +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) &ui_companion_cocoa, #endif #ifdef HAVE_COCOATOUCH