From 3872b27569a28d96cb1ea99b66bace92ffb6191f Mon Sep 17 00:00:00 2001
From: Laurent Gomila <laurent.gom@gmail.com>
Date: Fri, 6 Sep 2013 14:50:15 +0200
Subject: [PATCH] Reworked the sfml-main module, added Main.hpp, moved the
 main() internal entry point for iOS from sfml-window to sfml-main

---
 cmake/Macros.cmake                            | 14 ++-
 examples/opengl/OpenGL.cpp                    |  1 +
 examples/shader/Shader.cpp                    |  1 +
 examples/window/Window.cpp                    |  1 +
 include/SFML/{Window => }/Main.hpp            |  6 +-
 include/SFML/Window.hpp                       |  1 -
 src/SFML/CMakeLists.txt                       |  6 +-
 src/SFML/Main/CMakeLists.txt                  | 15 ++-
 .../Main/{SFML_Main.cpp => MainAndroid.cpp}   | 45 +--------
 .../iOS/Main.mm => Main/MainWin32.cpp}        | 92 +++++++++++--------
 src/SFML/Main/MainiOS.mm                      | 63 +++++++++++++
 src/SFML/Window/CMakeLists.txt                |  2 -
 src/SFML/Window/iOS/SFAppDelegate.hpp         |  6 --
 src/SFML/Window/iOS/SFAppDelegate.mm          | 16 +---
 src/SFML/Window/iOS/SFMain.mm                 | 21 +++--
 15 files changed, 170 insertions(+), 120 deletions(-)
 rename include/SFML/{Window => }/Main.hpp (92%)
 rename src/SFML/Main/{SFML_Main.cpp => MainAndroid.cpp} (92%)
 rename src/SFML/{Window/iOS/Main.mm => Main/MainWin32.cpp} (65%)
 create mode 100644 src/SFML/Main/MainiOS.mm

diff --git a/cmake/Macros.cmake b/cmake/Macros.cmake
index de294d40..ec80cda4 100644
--- a/cmake/Macros.cmake
+++ b/cmake/Macros.cmake
@@ -212,12 +212,15 @@ macro(sfml_add_example target)
     # set a source group for the source files
     source_group("" FILES ${THIS_SOURCES})
 
-    # create the target
-    if(THIS_GUI_APP AND SFML_OS_WINDOWS)
+    # create the target
+    if(THIS_GUI_APP AND SFML_OS_WINDOWS)
         add_executable(${target} WIN32 ${THIS_SOURCES})
         target_link_libraries(${target} sfml-main)
     elseif(IOS)
         add_executable(${target} MACOSX_BUNDLE ${THIS_SOURCES})
+        if(THIS_GUI_APP)
+            target_link_libraries(${target} sfml-main)
+        endif()
     else()
         add_executable(${target} ${THIS_SOURCES})
     endif()
@@ -261,6 +264,13 @@ macro(sfml_add_example target)
             RUNTIME DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples
             BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples)
 
+   # fix install rules broken in CMake (see http://public.kitware.com/Bug/view.php?id=12506)
+   if(IOS)
+        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}\$ENV{EFFECTIVE_PLATFORM_NAME}/${target}.app
+                DESTINATION ${INSTALL_MISC_DIR}/examples/${target}
+                COMPONENT examples)
+    endif()
+
     # install the example's source code
     install(FILES ${THIS_SOURCES}
             DESTINATION ${INSTALL_MISC_DIR}/examples/${target}
diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp
index bdb3a58e..d655e7c0 100644
--- a/examples/opengl/OpenGL.cpp
+++ b/examples/opengl/OpenGL.cpp
@@ -4,6 +4,7 @@
 ////////////////////////////////////////////////////////////
 #include <SFML/Graphics.hpp>
 #include <SFML/OpenGL.hpp>
+#include <SFML/Main.hpp>
 
 
 // Some platform-specific stuff
diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp
index 2b0d8a58..3421df8c 100644
--- a/examples/shader/Shader.cpp
+++ b/examples/shader/Shader.cpp
@@ -4,6 +4,7 @@
 ////////////////////////////////////////////////////////////
 #include "Effect.hpp"
 #include <SFML/Graphics.hpp>
+#include <SFML/Main.hpp>
 #include <vector>
 #include <cmath>
 
diff --git a/examples/window/Window.cpp b/examples/window/Window.cpp
index bd8f4ffd..10c3ca2f 100644
--- a/examples/window/Window.cpp
+++ b/examples/window/Window.cpp
@@ -3,6 +3,7 @@
 ////////////////////////////////////////////////////////////
 #include <SFML/Window.hpp>
 #include <SFML/OpenGL.hpp>
+#include <SFML/Main.hpp>
 
 
 // Some platform-specific stuff
diff --git a/include/SFML/Window/Main.hpp b/include/SFML/Main.hpp
similarity index 92%
rename from include/SFML/Window/Main.hpp
rename to include/SFML/Main.hpp
index 9f6114b4..254ad7dd 100644
--- a/include/SFML/Window/Main.hpp
+++ b/include/SFML/Main.hpp
@@ -31,10 +31,12 @@
 #include <SFML/Config.hpp>
 
 
-// On iOS, we have no choice but to have our own main,
-// so we need to rename the user one and call it later
 #if defined(SFML_SYSTEM_IOS)
+
+    // On iOS, we have no choice but to have our own main,
+    // so we need to rename the user one and call it later
     #define main sfmlMain
+
 #endif
 
 
diff --git a/include/SFML/Window.hpp b/include/SFML/Window.hpp
index 3671344a..d7894e38 100644
--- a/include/SFML/Window.hpp
+++ b/include/SFML/Window.hpp
@@ -35,7 +35,6 @@
 #include <SFML/Window/Event.hpp>
 #include <SFML/Window/Joystick.hpp>
 #include <SFML/Window/Keyboard.hpp>
-#include <SFML/Window/Main.hpp>
 #include <SFML/Window/Mouse.hpp>
 #include <SFML/Window/VideoMode.hpp>
 #include <SFML/Window/Window.hpp>
diff --git a/src/SFML/CMakeLists.txt b/src/SFML/CMakeLists.txt
index 27a7d1ae..0f76a3d1 100644
--- a/src/SFML/CMakeLists.txt
+++ b/src/SFML/CMakeLists.txt
@@ -43,8 +43,6 @@ add_subdirectory(Window)
 add_subdirectory(Network)
 add_subdirectory(Graphics)
 if(NOT SFML_OS_IOS)
-    add_subdirectory(Audio)
-endif()
-if(SFML_OS_WINDOWS OR SFML_OS_ANDROID)
-    add_subdirectory(Main)
+    add_subdirectory(Audio)
 endif()
+add_subdirectory(Main)
diff --git a/src/SFML/Main/CMakeLists.txt b/src/SFML/Main/CMakeLists.txt
index 1f6f2c5b..6bbbc266 100644
--- a/src/SFML/Main/CMakeLists.txt
+++ b/src/SFML/Main/CMakeLists.txt
@@ -1,8 +1,17 @@
 
+set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main)
+set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main)
+
 # sources
-set(SRC
-    ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFML_Main.cpp
-)
+if(WINDOWS)
+    set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp)
+elseif(IOS)
+    set(SRC ${SRC} ${SRCROOT}/MainiOS.mm)
+elseif(ANDROID)
+    set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp)
+else()
+    return()
+endif()
 source_group("" FILES ${SRC})
 
 if(NOT ANDROID)
diff --git a/src/SFML/Main/SFML_Main.cpp b/src/SFML/Main/MainAndroid.cpp
similarity index 92%
rename from src/SFML/Main/SFML_Main.cpp
rename to src/SFML/Main/MainAndroid.cpp
index 0787c4f3..97f02e8a 100644
--- a/src/SFML/Main/SFML_Main.cpp
+++ b/src/SFML/Main/MainAndroid.cpp
@@ -23,48 +23,9 @@
 ////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////
-// Windows specific : defines the WinMain entry function,
-// so that developers can use the standard main function
-// even in a Win32 Application project, and keep a portable code
-////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
 
-
-#if defined(_WIN32)
-
-    #include <windows.h>
-
-    extern int main(int argc, char* argv[]);
-
-    int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
-    {
-        return main(__argc, __argv);
-    }
-
-#endif // _WIN32
-
-
-
-
-
-#if defined(_WIN32)
-////////////////////////////////////////////////////////////////////////////////
-// Windows specific : defines the WinMain entry function,
-// so that developers can use the standard main function
-// even in a Win32 Application project, and keep a portable code
-////////////////////////////////////////////////////////////////////////////////
-
-#include <windows.h>
-
-extern int main(int argc, char* argv[]);
-
-int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
-{
-    return main(__argc, __argv);
-}
-
-
-#elif defined(__ANDROID__)
+#ifdef SFML_SYSTEM_ANDROID
 
 #include <SFML/Window/Keyboard.hpp>
 #include <SFML/System/Sleep.hpp>
@@ -700,4 +661,4 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
     activity->instance = states;
 }
 
-#endif
+#endif // SFML_SYSTEM_ANDROID
diff --git a/src/SFML/Window/iOS/Main.mm b/src/SFML/Main/MainWin32.cpp
similarity index 65%
rename from src/SFML/Window/iOS/Main.mm
rename to src/SFML/Main/MainWin32.cpp
index a220eb83..33374e55 100644
--- a/src/SFML/Window/iOS/Main.mm
+++ b/src/SFML/Main/MainWin32.cpp
@@ -1,38 +1,54 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// This software is provided 'as-is', without any express or implied warranty.
-// In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-//    you must not claim that you wrote the original software.
-//    If you use this software in a product, an acknowledgment
-//    in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-//    and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/iOS/SFAppDelegate.hpp>
-
-
-////////////////////////////////////////////////////////////
-int main(int argc, char** argv)
-{
-    @autoreleasepool
-    {
-        [SFAppDelegate main:argc argv:argv];
-    }
-}
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+//    you must not claim that you wrote the original software.
+//    If you use this software in a product, an acknowledgment
+//    in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+//    and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// Windows specific: we define the WinMain entry point,
+// so that developers can use the standard main function
+// even in a Win32 Application project, and thus keep a
+// portable code
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+
+#ifdef SFML_SYSTEM_WINDOWS
+
+#include <windows.h>
+
+
+extern int main(int argc, char* argv[]);
+
+////////////////////////////////////////////////////////////
+int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
+{
+    return main(__argc, __argv);
+}
+
+#endif // SFML_SYSTEM_WINDOWS
+
diff --git a/src/SFML/Main/MainiOS.mm b/src/SFML/Main/MainiOS.mm
new file mode 100644
index 00000000..5a362c3d
--- /dev/null
+++ b/src/SFML/Main/MainiOS.mm
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+//    you must not claim that you wrote the original software.
+//    If you use this software in a product, an acknowledgment
+//    in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+//    and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// iOS specific: SFML needs to hook the main function, to
+// launch the iOS application (event loop), and then call the
+// user main from inside it.
+//
+// Our strategy is to rename the user main to 'sfmlMain' with
+// a macro (see Main.hpp), and call this modified main ourselves.
+//
+// Note that half of this trick (the sfmlMain placeholders and
+// the application delegate) is defined sfml-window; see there
+// for the full implementation.
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+
+#ifdef SFML_SYSTEM_IOS
+
+#include <UIKit/UIKit.h>
+
+
+////////////////////////////////////////////////////////////
+int main(int argc, char** argv)
+{
+    // Note: we intentionally drop command line arguments,
+    // there's no such thing as a command line on an iOS device :)
+
+    // Important: "SFAppDelegate" must always match the name of the
+    // application delegate class defined in sfml-window
+
+    return UIApplicationMain(argc, argv, nil, @"SFAppDelegate");
+}
+
+#endif // SFML_SYSTEM_IOS
diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt
index 65d2e1ef..2464333e 100644
--- a/src/SFML/Window/CMakeLists.txt
+++ b/src/SFML/Window/CMakeLists.txt
@@ -21,7 +21,6 @@ set(SRC
     ${SRCROOT}/JoystickManager.hpp
     ${INCROOT}/Keyboard.hpp
     ${SRCROOT}/Keyboard.cpp
-    ${INCROOT}/Main.hpp
     ${INCROOT}/Mouse.hpp
     ${SRCROOT}/Mouse.cpp
     ${SRCROOT}/VideoMode.cpp
@@ -127,7 +126,6 @@ elseif(IOS)
         ${SRCROOT}/iOS/VideoModeImpl.mm
         ${SRCROOT}/iOS/WindowImplUIKit.hpp
         ${SRCROOT}/iOS/WindowImplUIKit.mm
-        ${SRCROOT}/iOS/Main.mm
         ${SRCROOT}/iOS/ObjCType.hpp
         ${SRCROOT}/iOS/SFAppDelegate.hpp
         ${SRCROOT}/iOS/SFAppDelegate.mm
diff --git a/src/SFML/Window/iOS/SFAppDelegate.hpp b/src/SFML/Window/iOS/SFAppDelegate.hpp
index 7cac7695..db61bc36 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.hpp
+++ b/src/SFML/Window/iOS/SFAppDelegate.hpp
@@ -41,12 +41,6 @@
 ////////////////////////////////////////////////////////////
 @interface SFAppDelegate : NSObject<UIApplicationDelegate>
 
-////////////////////////////////////////////////////////////
-/// \brief Run the application
-///
-////////////////////////////////////////////////////////////
-+(int)main:(int)argc argv:(char**)argv;
-
 ////////////////////////////////////////////////////////////
 /// \brief Return the instance of the application delegate
 ///
diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm
index 370d1aae..3b0bdd82 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.mm
+++ b/src/SFML/Window/iOS/SFAppDelegate.mm
@@ -31,10 +31,6 @@
 
 namespace
 {
-    // Save the main's arguments, to pass them back to the user's main
-    int mainArgc;
-    char** mainArgv;
-
     // Save the global instance of the delegate
     SFAppDelegate* delegateInstance = NULL;
 }
@@ -53,15 +49,6 @@ namespace
 @synthesize sfWindow;
 
 
-////////////////////////////////////////////////////////////
-+(int)main:(int)argc argv:(char**)argv
-{
-    mainArgc = argc;
-    mainArgv = argv;
-    return UIApplicationMain(argc, argv, nil, NSStringFromClass([SFAppDelegate class]));
-}
-
-
 ////////////////////////////////////////////////////////////
 +(SFAppDelegate*)getInstance
 {
@@ -72,7 +59,8 @@ namespace
 ////////////////////////////////////////////////////////////
 -(void)runUserMain
 {
-    sfmlMain(mainArgc, mainArgv);
+    // Arguments intentionally dropped, see comments in main in sfml-main
+    sfmlMain(0, NULL);
 }
 
 
diff --git a/src/SFML/Window/iOS/SFMain.mm b/src/SFML/Window/iOS/SFMain.mm
index b6060dfa..7d793a3f 100644
--- a/src/SFML/Window/iOS/SFMain.mm
+++ b/src/SFML/Window/iOS/SFMain.mm
@@ -28,14 +28,23 @@
 #include <SFML/Window/iOS/SFMain.hpp>
 
 
-// We declare both versions of sfmlMain, but with the 'weak' attribute (GCC extension)
-// so that the user-declared one will replace SFML's one at linking stage.
+// sfmlMain is called by the application delegate (SFAppDelegate).
 //
-// If user defines main(argc, argv) then it will be called directly,
-// if he defines main() then it will be called by our placeholder.
+// Since we don't know which prototype of main the user
+// defines, we declare both versions of sfmlMain, but with
+// the 'weak' attribute (GCC extension) so that the
+// user-declared one will replace SFML's one at linking stage.
 //
-// The sfmlMain() version is never called, it is just defined to avoid a
-// linker error if the user directly defines the version with arguments.
+// If user defines main(argc, argv) then it will be called
+// directly, if he defines main() then it will be called by
+// our placeholder.
+//
+// The sfmlMain() version is never called, it is just defined
+// to avoid a linker error if the user directly defines the
+// version with arguments.
+//
+// See the sfml-main module for the other half of this
+// initialization trick.
 
 
 ////////////////////////////////////////////////////////////