Index: source/lib/sysdep/os/osx/osx_atlas.h =================================================================== --- /dev/null +++ source/lib/sysdep/os/osx/osx_atlas.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2020 Wildfire Games. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef OSX_ATLAS_H +#define OSX_ATLAS_H + + +/** + * Runs a new pyrogenesis process with the -editor argument. + * Necessary because SDL and WxWidgets conflict. + */ +void startNewAtlasProcess(); + +#endif // OSX_ATLAS_H Index: source/lib/sysdep/os/osx/osx_atlas.mm =================================================================== --- /dev/null +++ source/lib/sysdep/os/osx/osx_atlas.mm @@ -0,0 +1,39 @@ +/* Copyright (C) 2020 Wildfire Games. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import // MAC_OS_X_VERSION_MIN_REQUIRED +#include + +#import "osx_atlas.h" + +void startNewAtlasProcess() +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + // TODO: it would be nice to pass mods. + NSArray *args = @[@"--editor"]; + NSDictionary *params = @{ NSWorkspaceLaunchConfigurationArguments: args }; + + [[NSWorkspace sharedWorkspace] launchApplicationAtURL:[[NSRunningApplication currentApplication] executableURL] options:NSWorkspaceLaunchNewInstance configuration:params error:nil]; + + [pool drain]; +} Index: source/main.cpp =================================================================== --- source/main.cpp +++ source/main.cpp @@ -85,6 +85,10 @@ #include // geteuid #endif // OS_UNIX +#if OS_MACOSX +#include "lib/sysdep/os/osx/osx_atlas.h" +#endif + #if MSC_VERSION #include #define getpid _getpid // Use the non-deprecated function name @@ -649,8 +653,13 @@ } while (g_Shutdown == ShutdownType::Restart); +#if OS_MACOSX if (g_Shutdown == ShutdownType::RestartAsAtlas) - ATLAS_RunIfOnCmdLine(args, true); + startNewAtlasProcess(); +#else + if (g_Shutdown == ShutdownType::RestartAsAtlas) + ATLAS_RunIfOnCmdLine(args, true); +#endif CXeromyces::Terminate(); } Index: source/ps/GameSetup/HWDetect.cpp =================================================================== --- source/ps/GameSetup/HWDetect.cpp +++ source/ps/GameSetup/HWDetect.cpp @@ -383,7 +383,8 @@ snprintf(version, ARRAY_SIZE(version), "%d.%d.%d", runtime.major, runtime.minor, runtime.patch); scriptInterface.SetProperty(settings, "sdl_runtime_version", version); - const char* backend = GetSDLSubsystem(g_VideoMode.GetWindow()); + // This is null in atlas (and further the call triggers an assertion). + const char* backend = g_VideoMode.GetWindow() ? GetSDLSubsystem(g_VideoMode.GetWindow()) : "none"; scriptInterface.SetProperty(settings, "sdl_video_backend", backend ? backend : "unknown"); } Index: source/tools/atlas/AtlasUI/Misc/DLLInterface.cpp =================================================================== --- source/tools/atlas/AtlasUI/Misc/DLLInterface.cpp +++ source/tools/atlas/AtlasUI/Misc/DLLInterface.cpp @@ -180,13 +180,6 @@ { public: -#ifdef __WXOSX__ - virtual bool OSXIsGUIApplication() - { - return false; - } -#endif - virtual bool OnInit() { // _CrtSetBreakAlloc(5632); Index: source/tools/atlas/AtlasUI/Misc/KeyMap.cpp =================================================================== --- source/tools/atlas/AtlasUI/Misc/KeyMap.cpp +++ source/tools/atlas/AtlasUI/Misc/KeyMap.cpp @@ -77,6 +77,8 @@ case WXK_F14: return SDLK_F14; case WXK_F15: return SDLK_F15; + case WXK_BACK: return SDLK_BACKSPACE; + case WXK_DELETE: return SDLK_DELETE; case WXK_NUMLOCK: return SDLK_NUMLOCKCLEAR; case WXK_SCROLL: return SDLK_SCROLLLOCK; // case WXK_: return SDLK_CAPSLOCK; Index: source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp @@ -132,9 +132,7 @@ if (KeyScroll(evt, true)) return; - // Slight hack: Only pass 'special' keys; normal keys will generate a translated Char event instead - if (evt.GetKeyCode() >= 256) - POST_MESSAGE(GuiKeyEvent, (GetSDLKeyFromWxKeyCode(evt.GetKeyCode()), evt.GetUnicodeKey(), true)); + POST_MESSAGE(GuiKeyEvent, (GetSDLKeyFromWxKeyCode(evt.GetKeyCode()), evt.GetUnicodeKey(), true)); evt.Skip(); } @@ -147,9 +145,7 @@ if (KeyScroll(evt, false)) return; - // Slight hack: Only pass 'special' keys; normal keys will generate a translated Char event instead - if (evt.GetKeyCode() >= 256) - POST_MESSAGE(GuiKeyEvent, (GetSDLKeyFromWxKeyCode(evt.GetKeyCode()), evt.GetUnicodeKey(), false)); + POST_MESSAGE(GuiKeyEvent, (GetSDLKeyFromWxKeyCode(evt.GetKeyCode()), evt.GetUnicodeKey(), false)); evt.Skip(); } @@ -189,8 +185,8 @@ } else { - // Slight hack: Only pass 'normal' keys; special keys will generate a KeyDown/KeyUp event instead - if (evt.GetKeyCode() < 256) + // Slight hack: Only pass 'alphanumeric' keys; special keys will generate a KeyDown/KeyUp event instead + if (evt.GetKeyCode() >= 33 && evt.GetKeyCode() <= 126) POST_MESSAGE(GuiCharEvent, (GetSDLKeyFromWxKeyCode(evt.GetKeyCode()), evt.GetUnicodeKey())); evt.Skip(); Index: source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp @@ -198,17 +198,21 @@ MESSAGEHANDLER(GuiCharEvent) { - // wxWidgets has special Char events but SDL doesn't, so convert it to - // a keydown+keyup sequence. (We do the conversion here instead of on - // the wx side to avoid nondeterministic behaviour caused by async messaging.) - + // Simulate special 'text input' events in the SDL + // This isn't quite compatible with WXWidget's handling, + // so to avoid trouble we only send 'letter-like' ASCII input. SDL_Event_ ev = { { 0 } }; - ev.ev.type = SDL_KEYDOWN; - ev.ev.key.keysym.sym = (SDL_Keycode)(int)msg->sdlkey; + ev.ev.type = SDL_TEXTEDITING; + ev.ev.text.type = SDL_TEXTEDITING; + ev.ev.text.text[0] = (char)msg->sdlkey; + ev.ev.text.text[1] = (char)0; in_dispatch_event(&ev); - ev.ev.type = SDL_KEYUP; - in_dispatch_event(&ev); + ev.ev.type = SDL_TEXTINPUT; + ev.ev.text.type = SDL_TEXTINPUT; + ev.ev.text.text[0] = (char)msg->sdlkey; + ev.ev.text.text[1] = (char)0; + in_dispatch_event(&ev); } }