diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4535bb6..8ae7cad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,7 +72,10 @@ if(WIN32)
"${CMAKE_SOURCE_DIR}/extlib/si")
set(SPACEWARE_LIBRARIES
"${CMAKE_SOURCE_DIR}/extlib/si/siapp.lib")
-else()
+elseif(APPLE)
+ find_package(PNG REQUIRED)
+ find_library(APPKIT_LIBRARY AppKit REQUIRED)
+else() # Linux and compatible systems
find_package(PNG REQUIRED)
find_package(SpaceWare)
diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in
new file mode 100644
index 0000000..c215c44
--- /dev/null
+++ b/cmake/MacOSXBundleInfo.plist.in
@@ -0,0 +1,47 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ solvespace
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ SolveSpace
+ CFBundlePackageType
+ APPL
+ CFBundleVersion
+ ${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}
+ CFBundleShortVersionString
+ ${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}
+ NSHumanReadableCopyright
+ © 2008-2015 Jonathan Westhues and other authors
+ NSPrincipalClass
+ NSApplication
+ NSMainNibFile
+ MainMenu
+ CFBundleIconFile
+ AppIcon
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ slvs
+
+ CFBundleTypeIconFile
+ AppIcon.icns
+ CFBundleTypeName
+ SolveSpace sketch
+ CFBundleTypeOSTypes
+
+ slvs
+
+ CFBundleTypeRole
+ Editor
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9f9f535..a118df8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -129,6 +129,27 @@ if(WIN32)
win32/freeze.cpp
win32/w32main.cpp
win32/resource.rc)
+elseif(APPLE)
+ add_definitions(
+ -mmacosx-version-min=10.6
+ -fobjc-arc)
+
+ set(platform_SOURCES
+ cocoa/cocoamain.mm
+ unix/gloffscreen.cpp)
+
+ set(platform_XIBS
+ cocoa/MainMenu.xib
+ cocoa/SaveFormatAccessory.xib)
+
+ set(platform_ICONS
+ cocoa/AppIcon.iconset)
+
+ set(platform_RESOURCES
+ unix/solvespace-48x48.png)
+
+ set(platform_LIBRARIES
+ ${APPKIT_LIBRARY})
elseif(HAVE_FLTK)
include_directories(${FLTK_INCLUDE_DIR})
@@ -168,6 +189,52 @@ elseif(HAVE_GTK)
${GLEW_LIBRARIES})
endif()
+set(platform_BUNDLED_RESOURCES)
+
+foreach(xib ${platform_XIBS})
+ get_filename_component(nib ${xib} NAME_WE)
+ set(source ${CMAKE_CURRENT_SOURCE_DIR}/${xib})
+ set(target ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources/${nib}.nib)
+ list(APPEND platform_BUNDLED_RESOURCES ${target})
+
+ add_custom_command(
+ OUTPUT ${target}
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources
+ COMMAND ibtool --errors --warnings --notices
+ --output-format human-readable-text --compile
+ ${target} ${source}
+ COMMENT "Building Interface Builder file ${xib}"
+ DEPENDS ${xib})
+endforeach()
+
+foreach(icon ${platform_ICONS})
+ get_filename_component(name ${icon} NAME_WE)
+ set(source ${CMAKE_CURRENT_SOURCE_DIR}/${icon})
+ set(target ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources/${name}.icns)
+ list(APPEND platform_BUNDLED_RESOURCES ${target})
+
+ add_custom_command(
+ OUTPUT ${target}
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources
+ COMMAND iconutil -c icns -o ${target} ${source}
+ COMMENT "Building icon set ${icon}"
+ DEPENDS ${source})
+endforeach()
+
+foreach(res ${platform_RESOURCES})
+ get_filename_component(name ${res} NAME)
+ set(source ${CMAKE_CURRENT_SOURCE_DIR}/${res})
+ set(target ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources/${name})
+ list(APPEND platform_BUNDLED_RESOURCES ${target})
+
+ add_custom_command(
+ OUTPUT ${target}
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/solvespace.app/Contents/Resources
+ COMMAND ${CMAKE_COMMAND} -E copy ${source} ${target}
+ COMMENT "Copying resource file ${res}"
+ DEPENDS ${res})
+endforeach()
+
# solvespace executable
set(solvespace_HEADERS
@@ -226,12 +293,13 @@ set(solvespace_SOURCES
srf/surfinter.cpp
srf/triangulate.cpp)
-add_executable(solvespace WIN32
+add_executable(solvespace WIN32 MACOSX_BUNDLE
${libslvs_HEADERS}
${libslvs_SOURCES}
${util_SOURCES}
${platform_HEADERS}
${platform_SOURCES}
+ ${platform_BUNDLED_RESOURCES}
${generated_HEADERS}
${solvespace_HEADERS}
${solvespace_SOURCES})
@@ -252,7 +320,8 @@ if(SPACEWARE_FOUND)
endif()
install(TARGETS solvespace
- RUNTIME DESTINATION bin)
+ RUNTIME DESTINATION bin
+ BUNDLE DESTINATION .)
install(FILES unix/solvespace.desktop
DESTINATION share/applications)
diff --git a/src/cocoa/AppIcon.iconset/icon_16x16.png b/src/cocoa/AppIcon.iconset/icon_16x16.png
new file mode 120000
index 0000000..d618a4c
--- /dev/null
+++ b/src/cocoa/AppIcon.iconset/icon_16x16.png
@@ -0,0 +1 @@
+../../unix/solvespace-16x16.png
\ No newline at end of file
diff --git a/src/cocoa/AppIcon.iconset/icon_32x32.png b/src/cocoa/AppIcon.iconset/icon_32x32.png
new file mode 120000
index 0000000..c205b7d
--- /dev/null
+++ b/src/cocoa/AppIcon.iconset/icon_32x32.png
@@ -0,0 +1 @@
+../../unix/solvespace-32x32.png
\ No newline at end of file
diff --git a/src/cocoa/MainMenu.xib b/src/cocoa/MainMenu.xib
new file mode 100644
index 0000000..b1951c4
--- /dev/null
+++ b/src/cocoa/MainMenu.xib
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cocoa/SaveFormatAccessory.xib b/src/cocoa/SaveFormatAccessory.xib
new file mode 100644
index 0000000..3962b6a
--- /dev/null
+++ b/src/cocoa/SaveFormatAccessory.xib
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cocoa/cocoamain.mm b/src/cocoa/cocoamain.mm
new file mode 100644
index 0000000..8858c6c
--- /dev/null
+++ b/src/cocoa/cocoamain.mm
@@ -0,0 +1,1103 @@
+//-----------------------------------------------------------------------------
+// Our main() function, and Cocoa-specific stuff to set up our windows and
+// otherwise handle our interface to the operating system. Everything
+// outside gtk/... should be standard C++ and OpenGL.
+//
+// Copyright 2015
+//-----------------------------------------------------------------------------
+#include
+#include
+
+#import
+
+#include
+#include