From 81a041e3dd7a8a06ef85db7897572b816bbaba2a Mon Sep 17 00:00:00 2001 From: "tommy.li" Date: Sat, 16 Nov 2019 00:31:47 -0600 Subject: [PATCH 1/5] "Fixed" some Objective-C API issues blocking the game from launching --- .../LowLevelWindow/LowLevelWindow_MacOSX.mm | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm b/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm index d3675cf92f..eabbc3a95c 100644 --- a/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm +++ b/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm @@ -301,7 +301,9 @@ LowLevelWindow_MacOSX::LowLevelWindow_MacOSX() : m_Context(nil), m_BGContext(nil m_CurrentParams.windowed = true; // We are essentially windowed to begin with. SetActualParamsFromMode( CGDisplayCurrentMode(kCGDirectMainDisplay) ); - HOOKS->SetHasFocus( [NSApp isActive] ); + dispatch_sync(dispatch_get_main_queue(), ^{ + HOOKS->SetHasFocus( [NSApp isActive] );; + }); } LowLevelWindow_MacOSX::~LowLevelWindow_MacOSX() @@ -382,9 +384,11 @@ RString LowLevelWindow_MacOSX::TryVideoMode( const VideoModeParams& p, bool& new } [m_WindowDelegate performSelectorOnMainThread:@selector(setParams:) withObject:[NSValue valueWithPointer:&p] waitUntilDone:YES]; - [m_Context setView:[((SMWindowDelegate *)m_WindowDelegate)->m_Window contentView]]; - [m_Context update]; - [m_Context makeCurrentContext]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [m_Context setView:[((SMWindowDelegate *)m_WindowDelegate)->m_Window contentView]]; + [m_Context update]; + }); + [m_Context makeCurrentContext]; m_CurrentParams.windowed = true; SetActualParamsFromMode( CGDisplayCurrentMode(kCGDirectMainDisplay) ); m_CurrentParams.vsync = p.vsync; // hack @@ -544,8 +548,11 @@ void LowLevelWindow_MacOSX::SetActualParamsFromMode( CFDictionaryRef mode ) } else { - NSSize size = [[((SMWindowDelegate *)m_WindowDelegate)->m_Window contentView] frame].size; - + __block NSSize size; + dispatch_sync(dispatch_get_main_queue(), ^{ + size = [[((SMWindowDelegate *)m_WindowDelegate)->m_Window contentView] frame].size; + }); + m_CurrentParams.width = int(size.width); m_CurrentParams.height = int(size.height); } From bfc3feb6df9165ffe13069e13a3429546a9dc47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=AA=E7=AB=9C=20=28Tommy=20Li=29?= Date: Sun, 24 Nov 2019 00:04:59 -0600 Subject: [PATCH 2/5] Specify no high res window in Info.plist template --- Xcode/Info.plist.in.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Xcode/Info.plist.in.xml b/Xcode/Info.plist.in.xml index 34d6ffee4d..4b911aa973 100644 --- a/Xcode/Info.plist.in.xml +++ b/Xcode/Info.plist.in.xml @@ -55,6 +55,8 @@ Copyright 2001-2015 NSPrincipalClass SMApplication + NSHighResolutionCapable + From d8acd46319038c1a892d68a5f2b4b464c252396e Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Sun, 22 Dec 2019 12:56:39 -0600 Subject: [PATCH 3/5] More synchronous call to the main thread to avoid crashes --- src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm b/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm index eabbc3a95c..e871612d0b 100644 --- a/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm +++ b/src/arch/LowLevelWindow/LowLevelWindow_MacOSX.mm @@ -425,9 +425,10 @@ RString LowLevelWindow_MacOSX::TryVideoMode( const VideoModeParams& p, bool& new m_BGContext = nil; } } - - [m_Context setFullScreen]; - [m_Context update]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [m_Context setFullScreen]; + [m_Context update]; + }); [m_Context makeCurrentContext]; if( bChangeVsync ) @@ -639,7 +640,10 @@ void LowLevelWindow_MacOSX::Update() m_CurrentParams.width = g_iWidth; m_CurrentParams.height = g_iHeight; lock.Unlock(); // Unlock before calling ResolutionChanged(). - [m_Context update]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [m_Context update]; + }); + DISPLAY->ResolutionChanged(); } From 6b524a6c1fd8867eaf2bc6fb12bffae816376e86 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Sun, 22 Dec 2019 21:20:57 -0600 Subject: [PATCH 4/5] Add CMake instructions to copy default resources to app bundle, and add mounting points for those resources. --- Xcode/StepMania.entitlements | 14 ++++++++++++++ src/CMakeLists.txt | 19 +++++++++++++++++++ src/arch/ArchHooks/ArchHooks_MacOSX.mm | 19 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 Xcode/StepMania.entitlements diff --git a/Xcode/StepMania.entitlements b/Xcode/StepMania.entitlements new file mode 100644 index 0000000000..a98af77462 --- /dev/null +++ b/Xcode/StepMania.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.device.usb + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aadde32fd7..9d4a374112 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -251,6 +251,25 @@ elseif(APPLE) "NO" XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "${SM_XCODE_DIR}/Libraries") + # XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS + # "${SM_XCODE_DIR}/StepMania.entitlements") + + set(APPLE_BUNDLE_RESOURCES + "${SM_ROOT_DIR}/Announcers" + "${SM_ROOT_DIR}/BackgroundEffects" + "${SM_ROOT_DIR}/BackgroundTransitions" + "${SM_ROOT_DIR}/BGAnimations" + "${SM_ROOT_DIR}/Characters" + "${SM_ROOT_DIR}/Courses" + "${SM_ROOT_DIR}/Data" + "${SM_ROOT_DIR}/NoteSkins" + "${SM_ROOT_DIR}/Scripts" + "${SM_ROOT_DIR}/Songs" + "${SM_ROOT_DIR}/Themes" + ) + + target_sources("${SM_EXE_NAME}" PUBLIC ${APPLE_BUNDLE_RESOURCES}) + set_source_files_properties(${APPLE_BUNDLE_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) sm_add_compile_definition("${SM_EXE_NAME}" _XOPEN_SOURCE) diff --git a/src/arch/ArchHooks/ArchHooks_MacOSX.mm b/src/arch/ArchHooks/ArchHooks_MacOSX.mm index def9a1b7a5..f5c546b1d9 100644 --- a/src/arch/ArchHooks/ArchHooks_MacOSX.mm +++ b/src/arch/ArchHooks/ArchHooks_MacOSX.mm @@ -360,6 +360,25 @@ void ArchHooks::MountUserFilesystems( const RString &sDirOfExecutable ) // /Logs -> ~/Library/Logs/PRODUCT_ID PathForFolderType( dir, kDomainLibraryFolderType ); FILEMAN->Mount( "dir", ssprintf("%s/Logs/" PRODUCT_ID, dir), "/Logs" ); + + NSString* resourcePath = [[NSBundle mainBundle] resourcePath]; + if( resourcePath ) + { + const char* resourcePathUTF8String = [resourcePath UTF8String]; + FILEMAN->Mount( "dir", ssprintf("%s/Announcers", resourcePathUTF8String), "/Announcers" ); + FILEMAN->Mount( "dir", ssprintf("%s/BGAnimations", resourcePathUTF8String), "/BGAnimations" ); + FILEMAN->Mount( "dir", ssprintf("%s/BackgroundEffects", resourcePathUTF8String), "/BackgroundEffects" ); + FILEMAN->Mount( "dir", ssprintf("%s/BackgroundTransitions", resourcePathUTF8String), "/BackgroundTransitions" ); + FILEMAN->Mount( "dir", ssprintf("%s/CDTitles", resourcePathUTF8String), "/CDTitles" ); + FILEMAN->Mount( "dir", ssprintf("%s/Characters", resourcePathUTF8String), "/Characters" ); + FILEMAN->Mount( "dir", ssprintf("%s/Courses", resourcePathUTF8String), "/Courses" ); + FILEMAN->Mount( "dir", ssprintf("%s/NoteSkins", resourcePathUTF8String), "/NoteSkins" ); + FILEMAN->Mount( "dir", ssprintf("%s/Packages", resourcePathUTF8String), "/" + SpecialFiles::USER_PACKAGES_DIR ); + FILEMAN->Mount( "dir", ssprintf("%s/Songs", resourcePathUTF8String), "/Songs" ); + FILEMAN->Mount( "dir", ssprintf("%s/RandomMovies", resourcePathUTF8String), "/RandomMovies" ); + FILEMAN->Mount( "dir", ssprintf("%s/Themes", resourcePathUTF8String), "/Themes" ); + FILEMAN->Mount( "dir", ssprintf("%s/Data", resourcePathUTF8String), "/Data" ); + } // /Desktop -> /Users//Desktop/PRODUCT_ID // PathForFolderType( dir, kDesktopFolderType ); From aae68b4b7203f393129d6c7e8db55b72c9955432 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Sun, 22 Dec 2019 21:21:18 -0600 Subject: [PATCH 5/5] Add a draft for NSEvent based keyboard input. --- src/arch/InputHandler/InputHandler.cpp | 2 + .../InputHandler/InputHandler_NSEvent.hpp | 24 +++ src/arch/InputHandler/InputHandler_NSEvent.mm | 199 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 src/arch/InputHandler/InputHandler_NSEvent.hpp create mode 100644 src/arch/InputHandler/InputHandler_NSEvent.mm diff --git a/src/arch/InputHandler/InputHandler.cpp b/src/arch/InputHandler/InputHandler.cpp index 6e8a445281..bfd575560d 100644 --- a/src/arch/InputHandler/InputHandler.cpp +++ b/src/arch/InputHandler/InputHandler.cpp @@ -6,6 +6,7 @@ #include "LocalizedString.h" #include "arch/arch_default.h" #include "InputHandler_MonkeyKeyboard.h" +//#include "InputHandler_NSEvent.hpp" void InputHandler::UpdateTimer() @@ -192,6 +193,7 @@ void InputHandler::Create( const RString &drivers_, vector &Add // Always add Add.push_back( new InputHandler_MonkeyKeyboard ); +// Add.push_back( new InputHandler_NSEvent ); } diff --git a/src/arch/InputHandler/InputHandler_NSEvent.hpp b/src/arch/InputHandler/InputHandler_NSEvent.hpp new file mode 100644 index 0000000000..98db29e04a --- /dev/null +++ b/src/arch/InputHandler/InputHandler_NSEvent.hpp @@ -0,0 +1,24 @@ +// +// InputHandler_NSEvent.hpp +// StepMania +// +// Created by heshuimu on 12/22/19. +// + +#ifndef InputHandler_NSEvent_hpp +#define InputHandler_NSEvent_hpp + +#include "InputHandler.h" + +#include + +class InputHandler_NSEvent : public InputHandler +{ +public: + InputHandler_NSEvent(); + ~InputHandler_NSEvent(); + + void GetDevicesAndDescriptions( vector& vDevicesOut ); +}; + +#endif /* InputHandler_NSEvent_hpp */ diff --git a/src/arch/InputHandler/InputHandler_NSEvent.mm b/src/arch/InputHandler/InputHandler_NSEvent.mm new file mode 100644 index 0000000000..1560d22fb7 --- /dev/null +++ b/src/arch/InputHandler/InputHandler_NSEvent.mm @@ -0,0 +1,199 @@ +// +// InputHandler_NSEvent.cpp +// StepMania +// +// Created by heshuimu on 12/22/19. +// + +#include "InputHandler_NSEvent.hpp" + +#import +#import + +DeviceButton NSKeyCodeMap[0x100]; + +float DownOrUp(bool down) +{ + return down ? 1 : 0; +} + +void InitKeyCodeMap() +{ + NSKeyCodeMap[kVK_ANSI_A] = KEY_Ca; + NSKeyCodeMap[kVK_ANSI_B] = KEY_Cb; + NSKeyCodeMap[kVK_ANSI_C] = KEY_Cc; + NSKeyCodeMap[kVK_ANSI_D] = KEY_Cd; + NSKeyCodeMap[kVK_ANSI_E] = KEY_Ce; + NSKeyCodeMap[kVK_ANSI_F] = KEY_Cf; + NSKeyCodeMap[kVK_ANSI_G] = KEY_Cg; + NSKeyCodeMap[kVK_ANSI_H] = KEY_Ch; + NSKeyCodeMap[kVK_ANSI_I] = KEY_Ci; + NSKeyCodeMap[kVK_ANSI_J] = KEY_Cj; + NSKeyCodeMap[kVK_ANSI_K] = KEY_Ck; + NSKeyCodeMap[kVK_ANSI_L] = KEY_Cl; + NSKeyCodeMap[kVK_ANSI_M] = KEY_Cm; + NSKeyCodeMap[kVK_ANSI_N] = KEY_Cn; + NSKeyCodeMap[kVK_ANSI_O] = KEY_Co; + NSKeyCodeMap[kVK_ANSI_P] = KEY_Cp; + NSKeyCodeMap[kVK_ANSI_Q] = KEY_Cq; + NSKeyCodeMap[kVK_ANSI_R] = KEY_Cr; + NSKeyCodeMap[kVK_ANSI_S] = KEY_Cs; + NSKeyCodeMap[kVK_ANSI_T] = KEY_Ct; + NSKeyCodeMap[kVK_ANSI_U] = KEY_Cu; + NSKeyCodeMap[kVK_ANSI_V] = KEY_Cv; + NSKeyCodeMap[kVK_ANSI_W] = KEY_Cw; + NSKeyCodeMap[kVK_ANSI_X] = KEY_Cx; + NSKeyCodeMap[kVK_ANSI_Y] = KEY_Cy; + NSKeyCodeMap[kVK_ANSI_Z] = KEY_Cz; + + NSKeyCodeMap[kVK_ANSI_0] = KEY_C0; + NSKeyCodeMap[kVK_ANSI_1] = KEY_C1; + NSKeyCodeMap[kVK_ANSI_2] = KEY_C2; + NSKeyCodeMap[kVK_ANSI_3] = KEY_C3; + NSKeyCodeMap[kVK_ANSI_4] = KEY_C4; + NSKeyCodeMap[kVK_ANSI_5] = KEY_C5; + NSKeyCodeMap[kVK_ANSI_6] = KEY_C6; + NSKeyCodeMap[kVK_ANSI_7] = KEY_C7; + NSKeyCodeMap[kVK_ANSI_8] = KEY_C8; + NSKeyCodeMap[kVK_ANSI_9] = KEY_C9; + + NSKeyCodeMap[kVK_ANSI_Keypad0] = KEY_KP_C0; + NSKeyCodeMap[kVK_ANSI_Keypad1] = KEY_KP_C1; + NSKeyCodeMap[kVK_ANSI_Keypad2] = KEY_KP_C2; + NSKeyCodeMap[kVK_ANSI_Keypad3] = KEY_KP_C3; + NSKeyCodeMap[kVK_ANSI_Keypad4] = KEY_KP_C4; + NSKeyCodeMap[kVK_ANSI_Keypad5] = KEY_KP_C5; + NSKeyCodeMap[kVK_ANSI_Keypad6] = KEY_KP_C6; + NSKeyCodeMap[kVK_ANSI_Keypad7] = KEY_KP_C7; + NSKeyCodeMap[kVK_ANSI_Keypad8] = KEY_KP_C8; + NSKeyCodeMap[kVK_ANSI_Keypad9] = KEY_KP_C9; + + NSKeyCodeMap[kVK_ANSI_KeypadDivide] = KEY_KP_SLASH; + NSKeyCodeMap[kVK_ANSI_KeypadMultiply] = KEY_KP_ASTERISK; + NSKeyCodeMap[kVK_ANSI_KeypadEnter] = KEY_KP_ENTER; + NSKeyCodeMap[kVK_ANSI_KeypadEquals] = KEY_KP_EQUAL; + NSKeyCodeMap[kVK_ANSI_KeypadMinus] = KEY_KP_HYPHEN; + NSKeyCodeMap[kVK_ANSI_KeypadPlus] = KEY_KP_PLUS; + NSKeyCodeMap[kVK_ANSI_KeypadDecimal] = KEY_KP_PERIOD; + + NSKeyCodeMap[kVK_Home] = KEY_HOME; + NSKeyCodeMap[kVK_End] = KEY_END; + NSKeyCodeMap[kVK_PageDown] = KEY_PGDN; + NSKeyCodeMap[kVK_PageUp] = KEY_PGUP; + + NSKeyCodeMap[kVK_F1] = KEY_F1; + NSKeyCodeMap[kVK_F2] = KEY_F2; + NSKeyCodeMap[kVK_F3] = KEY_F3; + NSKeyCodeMap[kVK_F4] = KEY_F4; + NSKeyCodeMap[kVK_F5] = KEY_F5; + NSKeyCodeMap[kVK_F6] = KEY_F6; + NSKeyCodeMap[kVK_F7] = KEY_F7; + NSKeyCodeMap[kVK_F8] = KEY_F8; + NSKeyCodeMap[kVK_F9] = KEY_F9; + NSKeyCodeMap[kVK_F10] = KEY_F10; + NSKeyCodeMap[kVK_F11] = KEY_F11; + NSKeyCodeMap[kVK_F12] = KEY_F12; + NSKeyCodeMap[kVK_F13] = KEY_F13; + NSKeyCodeMap[kVK_F14] = KEY_F14; + NSKeyCodeMap[kVK_F15] = KEY_F15; + NSKeyCodeMap[kVK_F16] = KEY_F16; + + NSKeyCodeMap[kVK_ANSI_Quote] = KEY_QUOTE; + NSKeyCodeMap[kVK_ANSI_Backslash] = KEY_BACKSLASH; + NSKeyCodeMap[kVK_CapsLock] = KEY_CAPSLOCK; + NSKeyCodeMap[kVK_ANSI_Comma] = KEY_COMMA; + NSKeyCodeMap[kVK_ForwardDelete] = KEY_DEL; + NSKeyCodeMap[kVK_Delete] = KEY_BACK; + NSKeyCodeMap[kVK_ANSI_Equal] = KEY_EQUAL; + + NSKeyCodeMap[kVK_Escape] = KEY_ESC; + NSKeyCodeMap[kVK_ANSI_LeftBracket] = KEY_LBRACKET; + NSKeyCodeMap[kVK_ANSI_Minus] = KEY_HYPHEN; + NSKeyCodeMap[kVK_ANSI_Period] = KEY_PERIOD; + NSKeyCodeMap[kVK_Return] = KEY_ENTER; + NSKeyCodeMap[kVK_ANSI_RightBracket] = KEY_RBRACKET; + NSKeyCodeMap[kVK_ANSI_Semicolon] = KEY_SEMICOLON; + NSKeyCodeMap[kVK_Space] = KEY_SPACE; + NSKeyCodeMap[kVK_Tab] = KEY_TAB; + + NSKeyCodeMap[kVK_Command] = KEY_LMETA; + NSKeyCodeMap[kVK_RightCommand] = KEY_RMETA; + NSKeyCodeMap[kVK_Control] = KEY_LCTRL; + NSKeyCodeMap[kVK_RightControl] = KEY_RCTRL; + NSKeyCodeMap[kVK_Function] = KEY_FN; + NSKeyCodeMap[kVK_Option] = KEY_LALT; + NSKeyCodeMap[kVK_RightOption] = KEY_RALT; + NSKeyCodeMap[kVK_Shift] = KEY_LSHIFT; + NSKeyCodeMap[kVK_RightShift] = KEY_RSHIFT; + + NSKeyCodeMap[kVK_DownArrow] = KEY_DOWN; + NSKeyCodeMap[kVK_LeftArrow] = KEY_LEFT; + NSKeyCodeMap[kVK_RightArrow] = KEY_RIGHT; + NSKeyCodeMap[kVK_UpArrow] = KEY_UP; +} + +//static let backApostrophe = UInt16(kVK_ANSI_Grave) +//static let keypadClear = UInt16(kVK_ANSI_KeypadClear) +//static let mute = UInt16(kVK_Mute) +//static let volumeDown = UInt16(kVK_VolumeDown) +//static let volumeUp = UInt16(kVK_VolumeUp) +// +//static let downArrow = UInt16(kVK_DownArrow) +//static let leftArrow = UInt16(kVK_LeftArrow) +//static let rightArrow = UInt16(kVK_RightArrow) +//static let upArrow = UInt16(kVK_UpArrow) + +InputHandler_NSEvent::InputHandler_NSEvent() +{ + InitKeyCodeMap(); + + [NSEvent addLocalMonitorForEventsMatchingMask:(NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged) handler:^(NSEvent* e) { + unsigned short keyCode = [e keyCode]; + + if([e type] == NSEventTypeKeyUp) + { + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], 1)); + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], 0)); + } + else if([e type] == NSEventTypeFlagsChanged) + { + NSEventModifierFlags flags = [e modifierFlags]; + switch(keyCode) + { + case kVK_CapsLock: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagCapsLock))); + break; + case kVK_Shift: + case kVK_RightShift: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagShift))); + break; + case kVK_Control: + case kVK_RightControl: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagControl))); + break; + case kVK_Option: + case kVK_RightOption: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagOption))); + break; + case kVK_Command: + case kVK_RightCommand: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagCommand))); + break; + case kVK_Function: + ButtonPressed(DeviceInput(DEVICE_KEYBOARD, NSKeyCodeMap[keyCode], DownOrUp(flags & NSEventModifierFlagFunction))); + break; + } + } + + return e; + }]; +} + +InputHandler_NSEvent::~InputHandler_NSEvent() +{ +} + +void InputHandler_NSEvent::GetDevicesAndDescriptions( vector& vDevicesOut ) +{ + vDevicesOut.push_back(InputDeviceInfo(DEVICE_KEYBOARD, "NSEventKeyboard")); +}