Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #4558 from nyalldawson/native-lib-mac
Add OS native interface lib, with objective-c++ interface to Mac Cocoa libraries, v3
  • Loading branch information
nyalldawson committed May 15, 2017
2 parents ae97c33 + 8f44a29 commit 87052a7
Show file tree
Hide file tree
Showing 22 changed files with 570 additions and 15 deletions.
2 changes: 0 additions & 2 deletions CMakeLists.txt
Expand Up @@ -494,8 +494,6 @@ ELSE (WIN32)
ELSE ()
SET (OSX_HAVE_LOADERPATH 0)
ENDIF ()
#this will define ${APP_SERVICES_LIBRARY}
FIND_LIBRARY(APP_SERVICES_LIBRARY ApplicationServices )

SET (DEFAULT_BIN_SUBDIR bin)
SET (QGIS_BIN_SUBDIR_REV ..)
Expand Down
1 change: 1 addition & 0 deletions python/gui/qgsgui.sip
Expand Up @@ -31,6 +31,7 @@ class QgsGui
:rtype: QgsGui
%End


static QgsEditorWidgetRegistry *editorWidgetRegistry();
%Docstring
Returns the global editor widget registry, used for managing all known edit widget factories.
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
@@ -1,3 +1,5 @@
ADD_SUBDIRECTORY(native)

ADD_SUBDIRECTORY(core)
ADD_SUBDIRECTORY(analysis)
ADD_SUBDIRECTORY(ui)
Expand Down
14 changes: 11 additions & 3 deletions src/app/CMakeLists.txt
Expand Up @@ -519,6 +519,8 @@ INCLUDE_DIRECTORIES(
openstreetmap
dwg
dwg/libdxfrw
${CMAKE_SOURCE_DIR}/src/native
${CMAKE_BINARY_DIR}/src/native
)
INCLUDE_DIRECTORIES(SYSTEM
${SPATIALITE_INCLUDE_DIR}
Expand All @@ -529,7 +531,7 @@ INCLUDE_DIRECTORIES(SYSTEM
${QWTPOLAR_INCLUDE_DIR}
${QCA_INCLUDE_DIR}
${QTKEYCHAIN_INCLUDE_DIR}
)
)

IF(ENABLE_MODELTEST)
INCLUDE_DIRECTORIES(../../tests/qt_modeltest)
Expand All @@ -539,6 +541,10 @@ IF (ANDROID)
INCLUDE_DIRECTORIES(SYSTEM ${ANDROID_NDK_TOOLCHAIN_ROOT}/sysroot/usr/include)
ENDIF (ANDROID)

IF (APPLE)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/native/mac)
ENDIF (APPLE)

IF (POSTGRES_FOUND)
INCLUDE_DIRECTORIES(SYSTEM ${POSTGRES_INCLUDE_DIR})
ENDIF (POSTGRES_FOUND)
Expand Down Expand Up @@ -566,6 +572,7 @@ TARGET_LINK_LIBRARIES(qgis_app
qgis_core
qgis_gui
qgis_analysis
qgis_native
libdxfrw
)

Expand All @@ -586,6 +593,7 @@ IF (APPLE)
TARGET_LINK_LIBRARIES(qgis_app ${APP_SERVICES_LIBRARY})
ENDIF(APPLE)


if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
SET_TARGET_PROPERTIES(qgis_app PROPERTIES STATIC_LIBRARY_FLAGS "/machine:x64")
ENDIF(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
Expand All @@ -605,9 +613,9 @@ IF(WIN32)
TARGET_LINK_LIBRARIES(qgis_app DbgHelp Qt5::WinExtras)
ENDIF(WIN32)

IF (APPLE)
TARGET_LINK_LIBRARIES(${QGIS_APP_NAME} ${APP_SERVICES_LIBRARY})
TARGET_LINK_LIBRARIES(${QGIS_APP_NAME} qgis_native)

IF (APPLE)
SET_TARGET_PROPERTIES(${QGIS_APP_NAME} PROPERTIES
INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${QGIS_LIB_DIR}
INSTALL_RPATH_USE_LINK_PATH true
Expand Down
11 changes: 4 additions & 7 deletions src/app/qgisapp.cpp
Expand Up @@ -100,6 +100,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
//
#ifdef Q_OS_MACX
#include <ApplicationServices/ApplicationServices.h>
#include "qgsmacnative.h"

// check macro breaks QItemDelegate
#ifdef check
Expand Down Expand Up @@ -205,6 +206,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmimedatautils.h"
#include "qgsmessagelog.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsnative.h"
#include "qgsnewvectorlayerdialog.h"
#include "qgsnewmemorylayerdialog.h"
#include "qgsoptions.h"
Expand Down Expand Up @@ -1210,7 +1212,7 @@ QgisApp::QgisApp()
, mMapToolGroup( nullptr )
, mPreviewGroup( nullptr )
#ifdef Q_OS_MAC
, mWindowMenu( 0 )
, mWindowMenu( nullptr )
#endif
, mPanelMenu( nullptr )
, mToolbarMenu( nullptr )
Expand Down Expand Up @@ -6119,12 +6121,7 @@ void QgisApp::activate()

void QgisApp::bringAllToFront()
{
#ifdef Q_OS_MAC
// Bring forward all open windows while maintaining layering order
ProcessSerialNumber psn;
GetCurrentProcess( &psn );
SetFrontProcess( &psn );
#endif
QgsGui::nativePlatformInterface()->currentAppActivateIgnoringOtherApps();
}

void QgisApp::addWindow( QAction *action )
Expand Down
5 changes: 2 additions & 3 deletions src/core/CMakeLists.txt
Expand Up @@ -1044,6 +1044,7 @@ INCLUDE_DIRECTORIES(SYSTEM
${QTKEYCHAIN_INCLUDE_DIR}
)


#for PAL classes
IF (WIN32)
ADD_DEFINITIONS("-D_HAVE_WINDOWS_H_")
Expand Down Expand Up @@ -1112,9 +1113,7 @@ IF (WIN32)
TARGET_LINK_LIBRARIES(qgis_core wsock32 ${SETUPAPI_LIBRARY} DbgHelp)
ENDIF (WIN32)

IF(APPLE)
TARGET_LINK_LIBRARIES(qgis_core "-framework CoreFoundation -framework IOKit")
ENDIF(APPLE)
TARGET_LINK_LIBRARIES(qgis_core qgis_native)

IF (NOT WITH_INTERNAL_QEXTSERIALPORT)
TARGET_LINK_LIBRARIES(qgis_core ${QEXTSERIALPORT_LIBRARY})
Expand Down
4 changes: 4 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -744,6 +744,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/effects
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/gui
${CMAKE_BINARY_DIR}/src/native
../core
../core/annotations
../core/auth
Expand All @@ -758,6 +759,7 @@ INCLUDE_DIRECTORIES(
../core/symbology-ng
../core/effects
../core/metadata
../native
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/../ui
)
Expand Down Expand Up @@ -804,6 +806,7 @@ SET(QGIS_GUI_HDRS ${QGIS_GUI_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_gui.h)
IF(NOT APPLE)
INSTALL(FILES ${QGIS_GUI_HDRS} ${QGIS_GUI_MOC_HDRS} DESTINATION ${QGIS_INCLUDE_DIR})
ELSE(NOT APPLE)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/native/mac)
SET_TARGET_PROPERTIES(qgis_gui PROPERTIES
CLEAN_DIRECT_OUTPUT 1
FRAMEWORK 1
Expand Down Expand Up @@ -838,6 +841,7 @@ ADD_DEPENDENCIES(qgis_gui ui)

TARGET_LINK_LIBRARIES(qgis_gui
qgis_core
qgis_native
${QT_QTUITOOLS_LIBRARY}
${QWT_LIBRARY}
${QSCINTILLA_LIBRARY}
Expand Down
17 changes: 17 additions & 0 deletions src/gui/qgsgui.cpp
Expand Up @@ -19,6 +19,11 @@
#include "qgseditorwidgetregistry.h"
#include "qgslayertreeembeddedwidgetregistry.h"
#include "qgsmaplayeractionregistry.h"
#ifdef Q_OS_MACX
#include "qgsmacnative.h"
#else
#include "qgsnative.h"
#endif
#include "qgsshortcutsmanager.h"

QgsGui *QgsGui::instance()
Expand All @@ -27,6 +32,11 @@ QgsGui *QgsGui::instance()
return sInstance;
}

QgsNative *QgsGui::nativePlatformInterface()
{
return instance()->mNative;
}

QgsEditorWidgetRegistry *QgsGui::editorWidgetRegistry()
{
return instance()->mEditorWidgetRegistry;
Expand All @@ -53,10 +63,17 @@ QgsGui::~QgsGui()
delete mEditorWidgetRegistry;
delete mMapLayerActionRegistry;
delete mShortcutsManager;
delete mNative;
}

QgsGui::QgsGui()
{
#ifdef Q_OS_MAC
mNative = new QgsMacNative();
#else
mNative = new QgsNative();
#endif

mEditorWidgetRegistry = new QgsEditorWidgetRegistry();
mShortcutsManager = new QgsShortcutsManager();
mLayerTreeEmbeddedWidgetRegistry = new QgsLayerTreeEmbeddedWidgetRegistry();
Expand Down
10 changes: 10 additions & 0 deletions src/gui/qgsgui.h
Expand Up @@ -19,11 +19,13 @@
#define QGSGUI_H

#include "qgis_gui.h"
#include "qgis_sip.h"

class QgsEditorWidgetRegistry;
class QgsShortcutsManager;
class QgsLayerTreeEmbeddedWidgetRegistry;
class QgsMapLayerActionRegistry;
class QgsNative;

/**
* \ingroup gui
Expand All @@ -46,6 +48,13 @@ class GUI_EXPORT QgsGui
*/
static QgsGui *instance();

/**
* Returns the global native interface, which offers abstraction to the host OS's underlying public
* interfaces.
* \note Not available in Python bindings
*/
SIP_SKIP static QgsNative *nativePlatformInterface();

/**
* Returns the global editor widget registry, used for managing all known edit widget factories.
*/
Expand All @@ -72,6 +81,7 @@ class GUI_EXPORT QgsGui

QgsGui();

QgsNative *mNative = nullptr;
QgsEditorWidgetRegistry *mEditorWidgetRegistry = nullptr;
QgsShortcutsManager *mShortcutsManager = nullptr;
QgsLayerTreeEmbeddedWidgetRegistry *mLayerTreeEmbeddedWidgetRegistry = nullptr;
Expand Down
120 changes: 120 additions & 0 deletions src/native/CMakeLists.txt
@@ -0,0 +1,120 @@
#############################################################
# locate native libs

SET(NATIVE_LINK_LIBS)

IF(APPLE)
SET(APPLE_LIB_LIST ApplicationServices CoreFoundation IOKit AppKit)
FOREACH(_lib ${APPLE_LIB_LIST})
STRING(TOUPPER ${_lib} _lib_var)
# prefer /System/Library/Frameworks, in case CMAKE_FIND_FRAMEWORK=LAST, etc.
FIND_LIBRARY(APPLE_${_lib_var}_LIBRARY
NAMES ${_lib}
PATHS /System/Library/Frameworks
NO_DEFAULT_PATH
)
# if not found, drop back to standard find paths
FIND_LIBRARY(APPLE_${_lib_var}_LIBRARY ${_lib})

IF(NOT APPLE_${_lib_var}_LIBRARY)
MESSAGE(FATAL_ERROR "Couldn't find Apple's '${_lib}' framework or library")
ENDIF(NOT APPLE_${_lib_var}_LIBRARY)

LIST(APPEND NATIVE_LINK_LIBS "-framework ${_lib}")
ENDFOREACH(_lib ${APPLE_LIB_LIST})
ENDIF(APPLE)

#############################################################
# sources

SET(QGIS_NATIVE_SRCS
qgsnative.cpp
)

IF(APPLE)
SET(QGIS_APP_OBJC_SRCS
mac/cocoainitializer.mm
mac/qgsmacnative.mm
)

SET_SOURCE_FILES_PROPERTIES(${QGIS_APP_OBJC_SRCS} PROPERTIES COMPILE_FLAGS "-x objective-c++")

SET(QGIS_NATIVE_SRCS ${QGIS_NATIVE_SRCS}
${QGIS_APP_OBJC_SRCS}
)
ENDIF(APPLE)

SET(QGIS_NATIVE_HDRS
qgsnative.h
)

# install headers

IF(APPLE)
SET (QGIS_NATIVE_HDRS ${QGIS_NATIVE_HDRS}
mac/qgsmacnative.h
mac/cocoainitializer.h
)
ENDIF(APPLE)

INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)

#############################################################
# qgis_native library

ADD_LIBRARY(qgis_native SHARED ${QGIS_NATIVE_SRCS} ${QGIS_NATIVE_HDRS})
SET_PROPERTY(TARGET qgis_native PROPERTY POSITION_INDEPENDENT_CODE ON)

GENERATE_EXPORT_HEADER(
qgis_native
BASE_NAME NATIVE
EXPORT_FILE_NAME qgis_native.h
)

SET(QGIS_NATIVE_HDRS ${QGIS_NATIVE_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_native.h)

IF(NOT APPLE)
INSTALL(FILES ${QGIS_NATIVE_HDRS} DESTINATION ${QGIS_INCLUDE_DIR})
ELSE(NOT APPLE)
SET_TARGET_PROPERTIES(qgis_native PROPERTIES
CLEAN_DIRECT_OUTPUT 1
FRAMEWORK 1
FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}"
MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in"
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION}
MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis2_native
BUILD_WITH_INSTALL_RPATH TRUE
PUBLIC_HEADER "${QGIS_NATIVE_HDRS}"
LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}"
)
ENDIF(NOT APPLE)

#generate unversioned libs for android
IF(NOT ANDROID)
SET_TARGET_PROPERTIES(qgis_native PROPERTIES
VERSION ${COMPLETE_VERSION}
SOVERSION ${COMPLETE_VERSION}
)
ENDIF(NOT ANDROID)

TARGET_LINK_LIBRARIES(qgis_native "${NATIVE_LINK_LIBS}")

# install

INSTALL(TARGETS qgis_native
RUNTIME DESTINATION ${QGIS_BIN_DIR}
LIBRARY DESTINATION ${QGIS_LIB_DIR}
ARCHIVE DESTINATION ${QGIS_LIB_DIR}
FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR}
PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}
)

# Mac dev frameworks

IF (APPLE AND QGIS_MACAPP_INSTALL_DEV)
INSTALL(TARGETS qgis_native FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX})
INSTALL(CODE "EXECUTE_PROCESS(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_native.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_native\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_native.framework/qgis_native\")")
ENDIF (APPLE AND QGIS_MACAPP_INSTALL_DEV)
23 changes: 23 additions & 0 deletions src/native/README.md
@@ -0,0 +1,23 @@
README for qgis_native lib
==========================

This library is intended to offer abstraction to the host OS's underlying public
interfaces. This is useful for OSes that provide interfaces in languages other
than C/C++, or for grouping calls to OS-specific code so that it only needs to
be updated in one place in the source tree. It is advisable to leverage existing
functions provided by Qt, rather than rely upon OS-specific code, unless such
code extends the application to provide a better OS-specific user experience or
solve a problem.

Example
-------

As of Mac OS X 10.9 (Mavericks) many system public API calls to Carbon libraries
(based upon C) have been deprecated in favor of modern Cocoa libraries (written
in Objective-C), which can no longer be directly called from C++. Coalescing
and mixing these new calls in a library, using Objective-C++ allows not only
access to the Apple system Objective-C libraries and frameworks, but also those
from third-parties, like the auto-updating Sparkle.framework.

See also: http://el-tramo.be/blog/mixing-cocoa-and-qt/
http://sparkle.andymatuschak.org/

0 comments on commit 87052a7

Please sign in to comment.