summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure9
-rw-r--r--mkspecs/common/clang-mac.conf2
-rw-r--r--mkspecs/common/ios.conf14
-rw-r--r--mkspecs/common/ios/arch.conf84
-rw-r--r--mkspecs/common/ios/clang.conf51
-rw-r--r--mkspecs/common/ios/g++.conf21
-rw-r--r--mkspecs/common/ios/llvm.conf31
-rw-r--r--mkspecs/common/ios/qmake.conf60
-rw-r--r--mkspecs/common/ios/versions.conf184
-rw-r--r--mkspecs/common/mac/qplatformdefs.h2
-rw-r--r--mkspecs/common/xcode.conf13
-rw-r--r--mkspecs/features/configure.prf3
-rw-r--r--mkspecs/features/ios.prf25
-rw-r--r--mkspecs/features/ios/default_post.prf43
-rw-r--r--mkspecs/features/ios/default_pre.prf4
-rw-r--r--mkspecs/features/mac/sdk.prf10
-rw-r--r--mkspecs/macx-llvm/qmake.conf2
-rwxr-xr-xmkspecs/unsupported/macx-ios-clang/Info.plist.app20
-rw-r--r--mkspecs/unsupported/macx-ios-clang/Info.plist.lib18
-rw-r--r--mkspecs/unsupported/macx-ios-clang/qmake.conf30
-rw-r--r--mkspecs/unsupported/macx-ios-clang/qplatformdefs.h (renamed from mkspecs/unsupported/macx-iosdevice-clang-legacy/qplatformdefs.h)0
-rw-r--r--mkspecs/unsupported/macx-iosdevice-clang-legacy/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-clang/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-g++-legacy/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-g++/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-g++/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iosdevice-llvm-legacy/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-llvm-legacy/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iosdevice-llvm/qmake.conf35
-rw-r--r--mkspecs/unsupported/macx-iosdevice-llvm/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-clang-legacy/qmake.conf6
-rw-r--r--mkspecs/unsupported/macx-iossimulator-clang-legacy/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-clang/qmake.conf6
-rw-r--r--mkspecs/unsupported/macx-iossimulator-clang/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-g++-legacy/qmake.conf33
-rw-r--r--mkspecs/unsupported/macx-iossimulator-g++-legacy/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-g++/qmake.conf33
-rw-r--r--mkspecs/unsupported/macx-iossimulator-g++/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-llvm-legacy/qmake.conf33
-rw-r--r--mkspecs/unsupported/macx-iossimulator-llvm-legacy/qplatformdefs.h42
-rw-r--r--mkspecs/unsupported/macx-iossimulator-llvm/qmake.conf33
-rw-r--r--mkspecs/unsupported/macx-iossimulator-llvm/qplatformdefs.h42
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp642
-rw-r--r--qmake/generators/unix/unixmake2.cpp2
-rw-r--r--qmake/main.cpp5
-rw-r--r--src/corelib/global/qsystemdetection.h22
-rw-r--r--src/corelib/kernel/qcore_mac_p.h2
-rw-r--r--src/gui/gui.pro4
-rw-r--r--src/gui/opengl/qopenglpaintdevice.cpp14
-rw-r--r--src/gui/opengl/qopenglpaintdevice.h1
-rw-r--r--src/network/kernel/kernel.pri6
-rw-r--r--src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri4
-rw-r--r--src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp255
-rw-r--r--src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h90
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri8
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm2
-rw-r--r--src/platformsupport/platformsupport.pro3
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm193
-rw-r--r--src/plugins/platforms/ios/ios.json3
-rw-r--r--src/plugins/platforms/ios/ios.pro3
-rw-r--r--src/plugins/platforms/ios/plugin.mm69
-rw-r--r--src/plugins/platforms/ios/plugin.pro36
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.h (renamed from mkspecs/unsupported/macx-iosdevice-g++-legacy/qplatformdefs.h)15
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm94
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.h70
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.mm125
-rw-r--r--src/plugins/platforms/ios/qioscontext.h91
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm204
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h133
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm322
-rw-r--r--src/plugins/platforms/ios/qiosglobal.h67
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm144
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h73
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm142
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h88
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm180
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h88
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm238
-rw-r--r--src/plugins/platforms/ios/qiossoftwareinputhandler.h71
-rw-r--r--src/plugins/platforms/ios/qiostheme.h (renamed from mkspecs/unsupported/macx-iosdevice-clang/qplatformdefs.h)26
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm96
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h (renamed from mkspecs/common/ios/GLES/gl.h)9
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm90
-rw-r--r--src/plugins/platforms/ios/qioswindow.h103
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm523
-rw-r--r--src/plugins/platforms/ios/qtmain.mm93
-rw-r--r--src/plugins/platforms/ios/qtmain.pro8
-rw-r--r--src/plugins/platforms/platforms.pro5
-rw-r--r--src/printsupport/dialogs/dialogs.pri2
-rw-r--r--src/testlib/qtestcase.cpp10
-rw-r--r--src/widgets/kernel/mac.pri2
-rw-r--r--src/widgets/styles/qfusionstyle_p_p.h4
-rw-r--r--src/widgets/styles/qstyleoption.cpp2
95 files changed, 4170 insertions, 1684 deletions
diff --git a/configure b/configure
index 16b6a8ed52..dbc82b4e47 100755
--- a/configure
+++ b/configure
@@ -2512,6 +2512,7 @@ fi
case `basename "$XPLATFORM"` in win32-g++*) XPLATFORM_MINGW=yes;; esac
case "$XPLATFORM" in *-maemo*) XPLATFORM_MAEMO=yes;; esac
case "$XPLATFORM" in *qnx-*|*blackberry-*) XPLATFORM_QNX=yes;; esac
+case "$XPLATFORM" in *ios*) XPLATFORM_IOS=yes;; esac
if [ -d "$PLATFORM" ]; then
QMAKESPEC="$PLATFORM"
@@ -2620,6 +2621,11 @@ if [ "$CFG_FORCEDEBUGINFO" = "yes" ]; then
QT_CONFIG="$QT_CONFIG force_debug_info"
fi
+# iOS builds should be static to be able to submit to the App Store
+if [ "$XPLATFORM_IOS" = "yes" ]; then
+ CFG_SHARED="no"
+fi
+
# disable GTK style support auto-detection on Mac
if [ "$BUILD_ON_MAC" = "yes" ] && [ "$CFG_QGTKSTYLE" = "auto" ]; then
CFG_QGTKSTYLE=no
@@ -4026,7 +4032,8 @@ fi
# detect neon support
if [ "$CFG_ARCH" = "arm" ] && [ "${CFG_NEON}" = "auto" ]; then
- if compileTest unix/neon "neon"; then
+ # The iOS toolchain has trouble building the pixman NEON draw-helpers
+ if [ "$XPLATFORM_IOS" != "yes" ] && compileTest unix/neon "neon"; then
CFG_NEON=yes
else
CFG_NEON=no
diff --git a/mkspecs/common/clang-mac.conf b/mkspecs/common/clang-mac.conf
index f7fe50a50b..efe771d24d 100644
--- a/mkspecs/common/clang-mac.conf
+++ b/mkspecs/common/clang-mac.conf
@@ -3,3 +3,5 @@ QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -
QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
+
+QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvm.clang.1_0
diff --git a/mkspecs/common/ios.conf b/mkspecs/common/ios.conf
index 7420b56daf..5ff2f9b416 100644
--- a/mkspecs/common/ios.conf
+++ b/mkspecs/common/ios.conf
@@ -3,17 +3,23 @@
#
MAKEFILE_GENERATOR = UNIX
-CONFIG += ios reduce_exports incremental global_init_link_order lib_version_first plugin_no_soname
+CONFIG += app_bundle reduce_exports incremental global_init_link_order lib_version_first plugin_no_soname sdk
QMAKE_INCREMENTAL_STYLE = sublib
-# Qt can't build iOS app bundle :(
-CONFIG -= app_bundle
+# FIXME: Transform ios.conf to follow the same inheritance pattern as eg mac.conf and unix.conf
+QMAKE_PLATFORM = ios $$QMAKE_PLATFORM
# Not deploying to Mac OSX
QMAKE_MACOSX_DEPLOYMENT_TARGET =
+# But to iOS
+QMAKE_IOS_DEPLOYMENT_TARGET = 4.3
+
# Add iOS common folder to include path
INCLUDEPATH += $$PWD/ios
# iOS defines
-DEFINES += DARWIN_NO_CARBON Q_OS_IOS QT_NO_CORESERVICES QT_NO_PRINTER QT_NO_PRINTDIALOG
+DEFINES += DARWIN_NO_CARBON QT_NO_CORESERVICES QT_NO_PRINTER QT_NO_PRINTDIALOG
+
+# Universal target (iPhone and iPad)
+QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2
diff --git a/mkspecs/common/ios/arch.conf b/mkspecs/common/ios/arch.conf
deleted file mode 100644
index 4ad96874fe..0000000000
--- a/mkspecs/common/ios/arch.conf
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Helper to set CPU architecture flags for iOS configurations
-#
-# Depends on:
-#
-# QMAKE_IPHONEOS_DEPLOYMENT_TARGET - set in mkspecs/common/ios/versions.conf
-#
-# Note:
-#
-# Must be included after load(qt_config) in mkspec for auto-detection based
-# on GL/ES version (GL/ES 2.x implies armv7 on iOS).
-#
-
-# Target architecture for iOS devices (armv6, armv7 or leave blank for default)
-QMAKE_IOS_TARGET_ARCH =
-
-###########################################################################
-
-# Device?
-!*simulator* {
- # Let mkspec specify archictecture
- *armv6*: QMAKE_IOS_TARGET_ARCH = armv6
- else:*armv7*: QMAKE_IOS_TARGET_ARCH = armv7
-
- # ARMv7 architecture device (see below) is required for OpenGL/ES 2.x
- isEmpty(QMAKE_IOS_TARGET_ARCH):contains(QT_CONFIG, opengles2): QMAKE_IOS_TARGET_ARCH = armv7
-
- # No target architecture specified?
- isEmpty(QMAKE_IOS_TARGET_ARCH) {
- # iOS versions < 4.3 can be armv6 or armv7, so need armv6 for max. compatibility,
- # assume that building for OpenGL/ES 1.x is targeting armv6
- lessThan(QMAKE_IPHONEOS_DEPLOYMENT_TARGET, "4.3")|contains(QT_CONFIG, opengles1) {
- QMAKE_IOS_TARGET_ARCH = armv6
- } else: QMAKE_IOS_TARGET_ARCH = armv7
- }
-
- # Samsung S5PC100, Apple A4, A5, A5X
- equals(QMAKE_IOS_TARGET_ARCH, "armv7") {
- # iOS CPU architecture (armv7)
- QMAKE_IOS_ARM_ARCH = __ARM_ARCH_7__
-
- # Thumb2 instructions
- QMAKE_IOS_ARM_FLAGS = -mthumb
- QMAKE_IOS_ARM_ARCH += __MARM_THUMB__
-
- # NEON instructions
- *-g++*: QMAKE_IOS_ARM_FLAGS += -mfloat-abi=softfp -mfpu=neon
- QMAKE_IOS_ARM_ARCH += __ARM_NEON__
- } else {
- # Samsung S5L8900
- if(equals(QMAKE_IOS_TARGET_ARCH, "armv6")) {
- # iOS CPU architecture (armv6)
- QMAKE_IOS_ARM_ARCH = __ARM_ARCH_6__
-
- # ARM instructions
- QMAKE_IOS_ARM_FLAGS = -marm -mcpu=arm1176jzf-s
- !*clang*: QMAKE_IOS_ARM_FLAGS += -march=armv6
- } else {
- # Unsupported architecture
- error("Invalid iOS target $${QMAKE_IOS_TARGET_ARCH}! Edit mkspecs/common/ios/arch.conf to specify target architecture.")
- }
- }
-# Simulator is i386 only
-} else: QMAKE_IOS_TARGET_ARCH = i386
-
-# iOS architecture build flags
-QMAKE_IOS_ARCH_FLAGS = -arch $$QMAKE_IOS_TARGET_ARCH
-QMAKE_CFLAGS += $$QMAKE_IOS_ARCH_FLAGS
-QMAKE_CXXFLAGS += $$QMAKE_IOS_ARCH_FLAGS
-QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_ARCH_FLAGS
-QMAKE_LFLAGS += $$QMAKE_IOS_ARCH_FLAGS
-QMAKE_IOS_TARGET_ARCH =
-QMAKE_IOS_ARCH_FLAGS =
-
-# Architecture specific defines/flags
-!*simulator* {
- DEFINES += $$QMAKE_IOS_ARM_ARCH
- QMAKE_IOS_ARM_ARCH =
-
- QMAKE_CFLAGS += $$QMAKE_IOS_ARM_FLAGS
- QMAKE_CXXFLAGS += $$QMAKE_IOS_ARM_FLAGS
- QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_ARM_FLAGS
- QMAKE_IOS_ARM_FLAGS =
-}
diff --git a/mkspecs/common/ios/clang.conf b/mkspecs/common/ios/clang.conf
index 10d1dbd24e..7513a0a315 100644
--- a/mkspecs/common/ios/clang.conf
+++ b/mkspecs/common/ios/clang.conf
@@ -3,39 +3,32 @@
#
# Depends on:
#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
+# QMAKE_IOS_XCODE_VERSION - set in macx-ios-clang/qmake.conf
#
# iOS build flags
-QMAKE_IOS_CFLAGS = -fvisibility=hidden -fpascal-strings -fmessage-length=0
+QMAKE_IOS_CFLAGS += -fvisibility=hidden -fpascal-strings -fmessage-length=0
QMAKE_IOS_CFLAGS += -Wno-trigraphs -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -Wno-sign-conversion
-QMAKE_IOS_CXXFLAGS = -fvisibility-inlines-hidden
-QMAKE_IOS_OBJ_CFLAGS = -Wno-arc-abi -Wc++0x-extensions
-
-# Device or simulator specific flags
-*simulator* {
- QMAKE_IOS_CFLAGS += -fexceptions -fasm-blocks
- QMAKE_IOS_OBJ_CFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
-}
-
-# Compiler version-specific flags
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- # Clang 3.1 flags (will be used for later versions too)
- QMAKE_IOS_CFLAGS += -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-implicit-atomic-properties -Wformat -Wno-missing-braces -Wno-unused-function -Wno-unused-label -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-sign-compare -Wpointer-sign -Wno-newline-eof -Wdeprecated-declarations -Winvalid-offsetof -Wno-conversion
- QMAKE_IOS_CXXFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wc++11-extensions
- QMAKE_IOS_OBJ_CFLAGS += -Wno-deprecated-implementations -Wprotocol -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector
-
- # Warn about unsupported (later than 4.5) Xcode versions
- !lessThan(QMAKE_IOS_XCODE_VERSION, "4.6"): warning("The version of Xcode installed on this system is not recognised - custom compiler settings may be necessary")
-} else {
- if (!lessThan(QMAKE_IOS_XCODE_VERSION, "4.2")) {
- # Clang 3.0 flags
- QMAKE_IOS_CFLAGS += -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits
- } else {
- # Older Clang versions are not supported
- error("Unsupported Xcode version $${QMAKE_IOS_XCODE_VERSION}")
- }
-}
+QMAKE_IOS_CXXFLAGS += -fvisibility-inlines-hidden
+QMAKE_IOS_OBJ_CFLAGS += -Wno-arc-abi
+
+# Based on the following information, http://clang.llvm.org/doxygen/ObjCRuntime_8h_source.html,
+# we can conclude that it's safe to always pass the following flags
+QMAKE_IOS_OBJ_CFLAGS += -fobjc-nonfragile-abi -fobjc-legacy-dispatch
+
+# But these only apply to non-ARM targets
+!contains(QT_ARCH, arm): QMAKE_IOS_CFLAGS += -fexceptions -fasm-blocks
+
+# Clang 3.1 (and above) flags
+QMAKE_IOS_CFLAGS += -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-implicit-atomic-properties -Wformat -Wno-missing-braces -Wno-unused-function -Wno-unused-label -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-sign-compare -Wpointer-sign -Wno-newline-eof -Wdeprecated-declarations -Winvalid-offsetof -Wno-conversion
+QMAKE_IOS_CXXFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors
+QMAKE_IOS_OBJ_CFLAGS += -Wno-deprecated-implementations -Wprotocol -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector
+
+# We do not yet build with C++11 support, so warn about extensions unless they are used all over Qt
+QMAKE_IOS_CXXFLAGS += -Wc++11-extensions -Wc++0x-extensions -Wno-c++11-long-long
+
+# Warn about unsupported (later than 4.5) Xcode versions
+!lessThan(QMAKE_IOS_XCODE_VERSION, "4.7"): warning("The version of Xcode installed on this system is not recognised - custom compiler settings may be necessary")
# Set build flags
QMAKE_CFLAGS += $$QMAKE_IOS_CFLAGS
diff --git a/mkspecs/common/ios/g++.conf b/mkspecs/common/ios/g++.conf
deleted file mode 100644
index 8a1e0b20c0..0000000000
--- a/mkspecs/common/ios/g++.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# compiler settings for iOS g++ compilers
-#
-
-# iOS build flags
-QMAKE_IOS_CFLAGS = -fvisibility=hidden -fexceptions -fmessage-length=0
-QMAKE_IOS_CFLAGS += -Wno-trigraphs -Wreturn-type -Wunused-variable
-QMAKE_IOS_CXXFLAGS = -fvisibility-inlines-hidden
-
-# Device or simulator specific flags
-!*simulator*: QMAKE_IOS_OBJ_CFLAGS =
-else: QMAKE_IOS_OBJ_CFLAGS = -fobjc-abi-version=2 -fobjc-legacy-dispatch
-
-# Set build flags
-QMAKE_CFLAGS += $$QMAKE_IOS_CFLAGS
-QMAKE_CXXFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS
-QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS $$QMAKE_IOS_OBJ_CFLAGS
-
-QMAKE_IOS_CFLAGS =
-QMAKE_IOS_CXXFLAGS =
-QMAKE_IOS_OBJ_CFLAGS =
diff --git a/mkspecs/common/ios/llvm.conf b/mkspecs/common/ios/llvm.conf
deleted file mode 100644
index fa2e519dd9..0000000000
--- a/mkspecs/common/ios/llvm.conf
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# compiler settings for iOS llvm-g++ compilers
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-# iOS build flags
-QMAKE_IOS_CFLAGS = -fvisibility=hidden -fpascal-strings -fmessage-length=0
-QMAKE_IOS_CFLAGS += -Wno-trigraphs -Wreturn-type -Wunused-variable
-QMAKE_IOS_CXXFLAGS = -fvisibility-inlines-hidden
-
-# Device or simulator specific flags
-!*simulator*: QMAKE_IOS_OBJ_CFLAGS =
-else: QMAKE_IOS_OBJ_CFLAGS = -fobjc-abi-version=2 -fobjc-legacy-dispatch
-
-# Compiler version specific flags
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- # Xcode 4.3+ specific flags
- QMAKE_IOS_CFLAGS += -Wuninitialized
-}
-
-# Set build flags
-QMAKE_CFLAGS += $$QMAKE_IOS_CFLAGS
-QMAKE_CXXFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS
-QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS $$QMAKE_IOS_OBJ_CFLAGS
-
-QMAKE_IOS_CFLAGS =
-QMAKE_IOS_CXXFLAGS =
-QMAKE_IOS_OBJ_CFLAGS =
diff --git a/mkspecs/common/ios/qmake.conf b/mkspecs/common/ios/qmake.conf
index 6d38e16581..5164c48e12 100644
--- a/mkspecs/common/ios/qmake.conf
+++ b/mkspecs/common/ios/qmake.conf
@@ -3,63 +3,39 @@
#
# Depends on:
#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-# QMAKE_IOS_SDK_VERSION - set in mkspecs/common/ios/versions.conf
-# QMAKE_IOSSIMULATOR_SDK_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-# iOS SDK device type
-!*simulator*: QMAKE_IOS_DEVICE_TYPE = iPhoneOS
-else {
- QMAKE_IOS_DEVICE_TYPE = iPhoneSimulator
+# QMAKE_XCODE_DEVELOPER_PATH - set in mkspecs/common/xcode.conf
- # Use simulator SDK version
- QMAKE_IOS_SDK_VERSION = $$QMAKE_IOS_SIMULATOR_SDK_VERSION
- QMAKE_IOS_SIMULATOR_SDK_VERSION =
-}
+QT_QPA_DEFAULT_PLATFORM = ios
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- # Xcode 4.3+ is stored in /Applications
- QMAKE_IOS_XCODE_PATH = /Applications/Xcode.app/Contents
-} else: QMAKE_IOS_XCODE_PATH =
+QMAKE_XCODE_TOOLCHAIN_BIN_PATH = $$QMAKE_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/bin
-# iOS platform /Developer path
-QMAKE_IOS_DEV_PATH = $$QMAKE_IOS_XCODE_PATH/Developer/Platforms/$${QMAKE_IOS_DEVICE_TYPE}.platform/Developer
-QMAKE_IOS_XCODE_PATH =
+QMAKE_XCODE_CODE_SIGN_IDENTITY = "iPhone Developer"
-# iOS platform SDK path
-QMAKE_IOS_SDK = $$QMAKE_IOS_DEV_PATH/SDKs/$${QMAKE_IOS_DEVICE_TYPE}$${QMAKE_IOS_SDK_VERSION}.sdk
-QMAKE_IOS_DEV_PATH =
-QMAKE_IOS_DEVICE_TYPE =
+# iOS build tools
+QMAKE_CC = $$QMAKE_XCODE_TOOLCHAIN_BIN_PATH/clang
+QMAKE_CXX = $$QMAKE_XCODE_TOOLCHAIN_BIN_PATH/clang++
+QMAKE_FIX_RPATH = $$QMAKE_XCODE_TOOLCHAIN_BIN_PATH/install_name_tool -id
+QMAKE_AR = $$QMAKE_XCODE_TOOLCHAIN_BIN_PATH/ar cq
+QMAKE_RANLIB = $$QMAKE_XCODE_TOOLCHAIN_BIN_PATH/ranlib -s
+QMAKE_LINK = $$QMAKE_CXX
+QMAKE_LINK_SHLIB = $$QMAKE_CXX
-QMAKE_CFLAGS += -isysroot $$QMAKE_IOS_SDK
-QMAKE_CXXFLAGS += -isysroot $$QMAKE_IOS_SDK
-QMAKE_OBJECTIVE_CFLAGS += -isysroot $$QMAKE_IOS_SDK
-QMAKE_LFLAGS += -Wl,-syslibroot,$$QMAKE_IOS_SDK
-QMAKE_IOS_SDK =
+# Check that compiler is valid
+!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the clang compiler")
# Basic iOS frameworks needed for any GUI app
QMAKE_LFLAGS += -framework Foundation -framework UIKit -framework QuartzCore -lz
-# OpenGL ES1
-QMAKE_INCDIR_OPENGL_ES1 = $$QMAKE_IOS_SDK/System/Library/Frameworks/OpenGLES.framework/Headers
+# No OpenGL ES1
+QMAKE_INCDIR_OPENGL_ES1 =
QMAKE_LIBDIR_OPENGL_ES1 =
-QMAKE_LIBS_OPENGL_ES1 = -framework OpenGLES
+QMAKE_LIBS_OPENGL_ES1 =
# OpenGL ES2
-QMAKE_INCDIR_OPENGL_ES2 = $$QMAKE_IOS_SDK/System/Library/Frameworks/OpenGLES.framework/Headers
+QMAKE_INCDIR_OPENGL_ES2 =
QMAKE_LIBDIR_OPENGL_ES2 =
QMAKE_LIBS_OPENGL_ES2 = -framework OpenGLES
# No desktop OpenGL
QMAKE_INCDIR_OPENGL =
QMAKE_LIBS_OPENGL =
-
-# Compiler-specific flags
-!*-g++* {
- # Objective-C/C++ precompile flags
- QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
- QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
- QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
- QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
-}
diff --git a/mkspecs/common/ios/versions.conf b/mkspecs/common/ios/versions.conf
deleted file mode 100644
index b755068769..0000000000
--- a/mkspecs/common/ios/versions.conf
+++ /dev/null
@@ -1,184 +0,0 @@
-#
-# Helper to set build tool & SDK versions for iOS configurations
-#
-# This file sets up the following configuration variables:
-#
-# QMAKE_IOS_XCODE_VERSION - version number of Xcode being used
-# QMAKE_IOS_SDK_VERSION - version number of iOS device SDK
-# QMAKE_IOS_SIMULATOR_SDK_VERSION - version number of iOS simulator SDK
-#
-# Used in:
-#
-# mkspecs/common/ios/clang.conf
-# mkspecs/common/ios/llvm.conf
-# mkspecs/common/ios/qmake.conf
-# mkspecs/unsupported/macx-iosdevice-clang-legacy/qmake.conf
-# mkspecs/unsupported/macx-iosdevice-clang/qmake.conf
-# mkspecs/unsupported/macx-iosdevice-llvm-legacy/qmake.conf
-# mkspecs/unsupported/macx-iosdevice-llvm/qmake.conf
-# mkspecs/unsupported/macx-iosdevice-g++-legacy/qmake.conf
-# mkspecs/unsupported/macx-iossimulator-llvm-legacy/qmake.conf
-# mkspecs/unsupported/macx-iossimulator-llvm/qmake.conf
-# mkspecs/unsupported/macx-iossimulator-g++-legacy/qmake.conf
-#
-
-#
-# IMPORTANT:
-#
-# Xcode versions <= 4.2.x must be installed in /Developer.
-# Xcode versions >= 4.3.x must be installed in /Applications
-#
-# Xcode versions >= 4.10 & < 5.0 and versions >= 10.0 are not supported due to
-# the way the version checks are done here. As Apple (so far) has not used
-# minor version numbers greater than 3 for Xcode, and the Xcode major version
-# has only changed three times in the period 2003-2012, this is viewed as an
-# acceptable limitation.
-#
-
-#
-# Edit values below to match iOS build environment, or leave blank for
-# autodetection (slower!)
-#
-
-# Xcode version used for cross-compiling
-QMAKE_IOS_XCODE_VERSION =
-
-# iOS SDK version used for cross-compiling for iOS devices
-QMAKE_IOS_SDK_VERSION =
-
-# iOS SDK version used for cross-compiling for the iOS simulator
-QMAKE_IOS_SIMULATOR_SDK_VERSION =
-
-#
-# Do not edit values below here if using a pre-built SDK
-#
-
-# Minimum iOS version required on deployment target (if not specified, will
-# default to minimum version that guarantees ARMv7 & OpenGL/ES 2.x).
-#
-# No part of Qt or any known plugin uses features that require iOS versions
-# later than 4.0.
-QMAKE_IPHONEOS_DEPLOYMENT_TARGET = 4.0
-
-###########################################################################
-
-# No Xcode version specified?
-isEmpty(QMAKE_IOS_XCODE_VERSION) {
- # Get version string from installed Xcode
- exists(/Applications/Xcode.app/Contents/Developer) {
- QMAKE_IOS_XCODE_INFO = $$system(/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -version)
- } else: QMAKE_IOS_XCODE_INFO = $$system(/Developer/usr/bin/xcodebuild -version)
-
- # Extract Xcode version number from output
- QMAKE_IOS_XCODE_VERSION = $$member(QMAKE_IOS_XCODE_INFO, 1)
- QMAKE_IOS_XCODE_INFO =
-}
-
-# Make sure Xcode version is valid
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- # Xcode 4.3+ is stored in /Applications
- QMAKE_IOS_PLATFORM_PATH = /Applications/Xcode.app/Contents/Developer/Platforms
-
- # Make sure Xcode path is valid
- !exists($$QMAKE_IOS_PLATFORM_PATH): error("Xcode is not installed in /Applications/Xcode.app! Edit mkspecs/common/ios/versions.conf to specify version installed.")
-} else {
- # Older Xcode versions are stored in /Developer
- QMAKE_IOS_PLATFORM_PATH = /Developer/Platforms
-
- # Make sure Xcode path is valid
- !exists($$QMAKE_IOS_PLATFORM_PATH): error("Xcode is not installed in /Developer! Edit mkspecs/common/ios/versions.conf to specify version installed.")
-}
-
-# iOS 4.3 is the preferred version as it is the earliest version that is armv7/gles2 only
-QMAKE_IPHONEOS_PREFERRED_TARGET = 4.3
-
-# Building for iOS device?
-!*simulator* {
- # No iOS SDK version specified?
- isEmpty(QMAKE_IOS_SDK_VERSION) {
- # Get version string from installed Xcode
- !lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- QMAKE_IOS_SDK_INFO = $$system(/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -showsdks)
- } else: QMAKE_IOS_SDK_INFO = $$system(/Developer/usr/bin/xcodebuild -showsdks)
-
- # Get names of installed device SDKs
- QMAKE_IOS_SDK_INFO = $$find(QMAKE_IOS_SDK_INFO, ^iphoneos)
- for(v, QMAKE_IOS_SDK_INFO): {
- # Extract SDK version number from output
- v = $$replace(v,iphoneos,)
-
- # Use latest SDK version
- greaterThan(v, $$QMAKE_IOS_SDK_VERSION): QMAKE_IOS_SDK_VERSION = $$v
- }
- QMAKE_IOS_SDK_INFO =
- }
-
- # Make sure iOS SDK version is valid
- !exists($$QMAKE_IOS_PLATFORM_PATH/iPhoneOS.platform/Developer/SDKs/iPhoneOS$${QMAKE_IOS_SDK_VERSION}.sdk) {
- error("iOS $$QMAKE_IOS_SDK_VERSION SDK not found! Edit mkspecs/common/ios/versions.conf to specify version installed.")
- }
-
- # No deployment target specified?
- isEmpty(QMAKE_IPHONEOS_DEPLOYMENT_TARGET) {
- # Use SDK version for iOS versions < preferred
- lessThan(QMAKE_IOS_SDK_VERSION, $$QMAKE_IPHONEOS_PREFERRED_TARGET) {
- QMAKE_IPHONEOS_DEPLOYMENT_TARGET = $$QMAKE_IOS_SDK_VERSION
- } else: QMAKE_IPHONEOS_DEPLOYMENT_TARGET = $$QMAKE_IPHONEOS_PREFERRED_TARGET
- }
-
- # Make sure iOS SDK version is >= iOS target version
- !lessThan(QMAKE_IPHONEOS_DEPLOYMENT_TARGET, $$QMAKE_IOS_SDK_VERSION) {
- error("Target iOS version is greater that iOS SDK version $$QMAKE_IOS_SDK_VERSION! Edit mkspecs/common/ios/versions.conf to specify target iOS version.")
- }
-# Building for iOS simulator
-} else {
- # No iOS simulator SDK version specified?
- isEmpty(QMAKE_IOS_SIMULATOR_SDK_VERSION) {
- # Get version string from installed Xcode
- !lessThan(QMAKE_IOS_XCODE_VERSION, "4.3") {
- QMAKE_IOS_SDK_INFO = $$system(/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -showsdks)
- } else: QMAKE_IOS_SDK_INFO = $$system(/Developer/usr/bin/xcodebuild -showsdks)
-
- # Get names of installed device SDKs
- QMAKE_IOS_SDK_INFO = $$find(QMAKE_IOS_SDK_INFO, ^iphonesimulator)
- for(v, QMAKE_IOS_SDK_INFO): {
- # Extract SDK version number from output
- v = $$replace(v,iphonesimulator,)
-
- # Use latest SDK version
- greaterThan(v, $$QMAKE_IOS_SIMULATOR_SDK_VERSION): QMAKE_IOS_SIMULATOR_SDK_VERSION = $$v
- }
- QMAKE_IOS_SDK_INFO =
- }
-
- # Make sure iOS simulator SDK version is valid
- !exists($$QMAKE_IOS_PLATFORM_PATH/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$${QMAKE_IOS_SIMULATOR_SDK_VERSION}.sdk) {
- error("iOS $$QMAKE_IOS_SIMULATOR_SDK_VERSION simulator SDK not found! Edit mkspecs/common/ios/versions.conf to specify version installed.")
- }
-
- # No deployment target specified?
- isEmpty(QMAKE_IPHONEOS_DEPLOYMENT_TARGET) {
- # Use SDK version for iOS versions < preferred
- lessThan(QMAKE_IOS_SIMULATOR_SDK_VERSION, $$QMAKE_IPHONEOS_PREFERRED_TARGET) {
- QMAKE_IPHONEOS_DEPLOYMENT_TARGET = $$QMAKE_IOS_SIMULATOR_SDK_VERSION
- } else: QMAKE_IPHONEOS_DEPLOYMENT_TARGET = $$QMAKE_IPHONEOS_PREFERRED_TARGET
- }
-
- # Make sure iOS simulator SDK version is >= iOS target version
- !lessThan(QMAKE_IPHONEOS_DEPLOYMENT_TARGET, $$QMAKE_IOS_SIMULATOR_SDK_VERSION) {
- error("Target iOS version is greater that iOS simulator SDK version $$QMAKE_IOS_SIMULATOR_SDK_VERSION! Edit mkspecs/common/ios/versions.conf to specify target iOS version.")
- }
-}
-
-QMAKE_IPHONEOS_PREFERRED_TARGET =
-QMAKE_IOS_PLATFORM_PATH =
-
-# Set deployment target
-QMAKE_IOS_VERSION_FLAGS = -miphoneos-version-min=$$QMAKE_IPHONEOS_DEPLOYMENT_TARGET
-
-# Set build flags
-QMAKE_CFLAGS += $$QMAKE_IOS_VERSION_FLAGS
-QMAKE_CXXFLAGS += $$QMAKE_IOS_VERSION_FLAGS
-QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_VERSION_FLAGS
-QMAKE_LFLAGS += $$QMAKE_IOS_VERSION_FLAGS
-QMAKE_IOS_VERSION_FLAGS =
diff --git a/mkspecs/common/mac/qplatformdefs.h b/mkspecs/common/mac/qplatformdefs.h
index 7d4b6a2427..7ee337cce4 100644
--- a/mkspecs/common/mac/qplatformdefs.h
+++ b/mkspecs/common/mac/qplatformdefs.h
@@ -42,8 +42,6 @@
#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H
-#define QT_QPA_DEFAULT_PLATFORM_NAME "cocoa"
-
// Get Qt defines/settings
#include "qglobal.h"
diff --git a/mkspecs/common/xcode.conf b/mkspecs/common/xcode.conf
new file mode 100644
index 0000000000..800e2e849c
--- /dev/null
+++ b/mkspecs/common/xcode.conf
@@ -0,0 +1,13 @@
+#
+# qmake configuration for Xcode
+#
+
+# Get path of Xcode's Developer directory
+QMAKE_XCODE_DEVELOPER_PATH = $$system(xcode-select --print-path)
+isEmpty(QMAKE_XCODE_DEVELOPER_PATH): \
+ error("Xcode path is not set. Please use xcode-select to choose Xcode installation path.")
+
+# Make sure Xcode path is valid
+!exists($$QMAKE_XCODE_DEVELOPER_PATH): \
+ error("Xcode is not installed in $${QMAKE_XCODE_DEVELOPER_PATH}. Please use xcode-select to choose Xcode installation path.")
+
diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf
index 39144e7216..b4569df6d5 100644
--- a/mkspecs/features/configure.prf
+++ b/mkspecs/features/configure.prf
@@ -7,6 +7,9 @@ equals(MAKEFILE_GENERATOR, UNIX) {
QMAKE_MAKE = mingw32-make
} else:if(equals(MAKEFILE_GENERATOR, MSVC.NET)|equals(MAKEFILE_GENERATOR, MSBUILD)) {
QMAKE_MAKE = nmake
+} else:ios {
+ # iOS unsets MAKEFILE_GENERATOR in its default_pre.prf
+ QMAKE_MAKE = make
} else {
error("Configure tests are not supported with the $$MAKEFILE_GENERATOR Makefile generator.")
}
diff --git a/mkspecs/features/ios.prf b/mkspecs/features/ios.prf
new file mode 100644
index 0000000000..841378e8dd
--- /dev/null
+++ b/mkspecs/features/ios.prf
@@ -0,0 +1,25 @@
+isEmpty(QT_ARCH) {
+ # The iPhoneOS and iPhoneSimulator targets share the same toolchain,
+ # so when configure runs the arch tests it passes the correct sysroot,
+ # but we fail to pick up the architecture since we're not passing -arch
+ # yet. Xcode does not seem to have a way to run the shared toolchain
+ # in a way that will automatically do this (for example xcrun -sdk).
+ contains(QMAKE_MAC_SDK, iphoneos.*): QT_ARCH = armv7
+ else: QT_ARCH = i386 # Simulator
+} else {
+ # Fix up the QT_ARCH to be more specific
+ equals(QT_ARCH, arm) {
+ # Samsung S5PC100, Apple A4, A5, A5X
+ QT_ARCH = armv7
+
+ # FIXME: How do we support armv7s when Qt can't do universal builds?
+ }
+}
+
+!equals(MAKEFILE_GENERATOR, XCODE) {
+ arch_flag = -arch $$QT_ARCH
+ QMAKE_CFLAGS += $$arch_flag
+ QMAKE_CXXFLAGS += $$arch_flag
+ QMAKE_OBJECTIVE_CFLAGS += $$arch_flag
+ QMAKE_LFLAGS += $$arch_flag
+}
diff --git a/mkspecs/features/ios/default_post.prf b/mkspecs/features/ios/default_post.prf
new file mode 100644
index 0000000000..f5e7b3c02d
--- /dev/null
+++ b/mkspecs/features/ios/default_post.prf
@@ -0,0 +1,43 @@
+
+CONFIG(qt):contains(QT, gui):equals(TEMPLATE, app): CONFIG += gui_app
+
+isEmpty(MAKEFILE_GENERATOR) {
+ gui_app:app_bundle: \
+ # For applications we want Xcode project files
+ MAKEFILE_GENERATOR = XCODE
+ else: \
+ # For libs, etc we still want regular Makefiles
+ MAKEFILE_GENERATOR = UNIX
+}
+
+gui_app {
+ # We have to do the link and dependency resolution for the platform plugin
+ # manually, since QTPLUGIN and the prl lookup logic does not support
+ # the -force_load link style. The -force_load option ensures that all
+ # symbols from the static library are included, not just the ones the
+ # linker have seen a use for so far. We need this because we load the platform
+ # plugin from the platform plugin itself, using Q_IMPORT_PLUGIN.
+ lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/libqios$$qtPlatformTargetSuffix()
+ LIBS += "-force_load $${lib_path_and_base}.$${QMAKE_EXTENSION_STATICLIB}"
+ LIBS += $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+
+ # Which means we don't want the auto-generated import for the platform plugin
+ CONFIG -= import_qpa_plugin
+
+ !no_main_wrapper {
+ # We link the iosmain library manually as well, since it's not really a plugin
+ lib_name = qiosmain
+ lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
+ LIBS += -L$$[QT_INSTALL_PLUGINS/get]/platforms -l$${lib_name}$$qtPlatformTargetSuffix()
+ LIBS += $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+ DEFINES += main=qt_main
+ }
+}
+
+contains(MAKEFILE_GENERATOR, XCODE) {
+ ios_device_family.name = TARGETED_DEVICE_FAMILY
+ ios_device_family.value = $$QMAKE_IOS_TARGETED_DEVICE_FAMILY
+ QMAKE_MAC_XCODE_SETTINGS += ios_device_family
+}
+
+load(default_post)
diff --git a/mkspecs/features/ios/default_pre.prf b/mkspecs/features/ios/default_pre.prf
new file mode 100644
index 0000000000..e2956bd77d
--- /dev/null
+++ b/mkspecs/features/ios/default_pre.prf
@@ -0,0 +1,4 @@
+# Unset makefile generator, so we can auto-detect value in default_post
+unset(MAKEFILE_GENERATOR)
+
+load(default_pre)
diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf
index 320e4e5382..16dd16159c 100644
--- a/mkspecs/features/mac/sdk.prf
+++ b/mkspecs/features/mac/sdk.prf
@@ -37,7 +37,15 @@
}
!equals(MAKEFILE_GENERATOR, XCODE) {
- version_min_flag = -m$${QMAKE_MAC_PLATFORM_NAME}-version-min=$$QMAKE_MACOSX_DEPLOYMENT_TARGET
+ # FIXME: Get the version_min_flag out of the platform's 'Native Build System.xcspec'
+ version_identifier = $$replace(QMAKE_MAC_PLATFORM_NAME, iphonesimulator, ios-simulator)
+
+ ios:!host_build: \
+ deployment_target = $$QMAKE_IOS_DEPLOYMENT_TARGET
+ else: \
+ deployment_target = $$QMAKE_MACOSX_DEPLOYMENT_TARGET
+
+ version_min_flag = -m$${version_identifier}-version-min=$$deployment_target
QMAKE_CFLAGS += $$version_min_flag
QMAKE_CXXFLAGS += $$version_min_flag
QMAKE_OBJECTIVE_CFLAGS += $$version_min_flag
diff --git a/mkspecs/macx-llvm/qmake.conf b/mkspecs/macx-llvm/qmake.conf
index 43db8d850c..96e02dc913 100644
--- a/mkspecs/macx-llvm/qmake.conf
+++ b/mkspecs/macx-llvm/qmake.conf
@@ -16,6 +16,8 @@ include(../common/llvm.conf)
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
+QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvmgcc42
+
QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
diff --git a/mkspecs/unsupported/macx-ios-clang/Info.plist.app b/mkspecs/unsupported/macx-ios-clang/Info.plist.app
new file mode 100755
index 0000000000..bcf7f41f27
--- /dev/null
+++ b/mkspecs/unsupported/macx-ios-clang/Info.plist.app
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.@BUNDLEIDENTIFIER@</string>
+ <key>NOTE</key>
+ <string>This file was generated by Qt/QMake.</string>
+</dict>
+</plist>
diff --git a/mkspecs/unsupported/macx-ios-clang/Info.plist.lib b/mkspecs/unsupported/macx-ios-clang/Info.plist.lib
new file mode 100644
index 0000000000..97609ed0ce
--- /dev/null
+++ b/mkspecs/unsupported/macx-ios-clang/Info.plist.lib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@SHORT_VERSION@</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@LIBRARY@</string>
+ <key>NOTE</key>
+ <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
+</dict>
+</plist>
diff --git a/mkspecs/unsupported/macx-ios-clang/qmake.conf b/mkspecs/unsupported/macx-ios-clang/qmake.conf
new file mode 100644
index 0000000000..8f176f3f83
--- /dev/null
+++ b/mkspecs/unsupported/macx-ios-clang/qmake.conf
@@ -0,0 +1,30 @@
+#
+# qmake configuration for macx-ios-clang
+#
+
+!load(device_config): error("Could not successfully load device configuration.")
+
+isEmpty(QMAKE_MAC_SDK): QMAKE_MAC_SDK = iphoneos
+
+# iOS is considered a variant of MacOS by Apple. We follow this to
+# keep things simple, e.g. by defining Q_OS_MAC _and_ Q_OS_IOS.
+include(../../common/mac.conf)
+
+include(../../common/gcc-base-ios.conf)
+include(../../common/xcode.conf)
+include(../../common/clang.conf)
+include(../../common/clang-mac.conf)
+
+# Extract Xcode version using xcodebuild
+version_info = $$system("$${QMAKE_XCODE_DEVELOPER_PATH}/usr/bin/xcodebuild -version")
+QMAKE_IOS_XCODE_VERSION = $$member(version_info, 1)
+unset(version_info)
+
+# Version check
+lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
+
+include(../../common/ios.conf)
+include(../../common/ios/clang.conf)
+include(../../common/ios/qmake.conf)
+
+load(qt_config)
diff --git a/mkspecs/unsupported/macx-iosdevice-clang-legacy/qplatformdefs.h b/mkspecs/unsupported/macx-ios-clang/qplatformdefs.h
index 5f80a17860..5f80a17860 100644
--- a/mkspecs/unsupported/macx-iosdevice-clang-legacy/qplatformdefs.h
+++ b/mkspecs/unsupported/macx-ios-clang/qplatformdefs.h
diff --git a/mkspecs/unsupported/macx-iosdevice-clang-legacy/qmake.conf b/mkspecs/unsupported/macx-iosdevice-clang-legacy/qmake.conf
deleted file mode 100644
index ff8e0b6aa9..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-clang-legacy/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-clang
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/clang.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/clang.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.2.x or earlier")
-
-# iOS build tools
-QMAKE_CC = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang
-QMAKE_CXX = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang++
-QMAKE_FIX_RPATH = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the clang compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-clang/qmake.conf b/mkspecs/unsupported/macx-iosdevice-clang/qmake.conf
deleted file mode 100644
index 777b5ab6e2..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-clang/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-clang
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/clang.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/clang.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
-
-# iOS build tools
-QMAKE_CC = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-QMAKE_CXX = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-QMAKE_FIX_RPATH = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool -id
-QMAKE_AR = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar cq
-QMAKE_RANLIB = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the clang compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-g++-legacy/qmake.conf b/mkspecs/unsupported/macx-iosdevice-g++-legacy/qmake.conf
deleted file mode 100644
index 5fcfb4a51d..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-g++-legacy/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-g++
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/g++-macx.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/g++.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check (g++ was discontinued at version 4.2, but user may have added it themselves)
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.2.x or earlier")
-
-# iOS build tools
-QMAKE_CC = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2
-QMAKE_CXX = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++-4.2
-QMAKE_FIX_RPATH = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the g++ 4.2 compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-g++/qmake.conf b/mkspecs/unsupported/macx-iosdevice-g++/qmake.conf
deleted file mode 100644
index 2a29335334..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-g++/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-g++
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/g++-macx.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/g++.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check (g++ was discontinued at version 4.2, but user may have added it themselves)
-lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
-
-# iOS build tools
-QMAKE_CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2
-QMAKE_CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++-4.2
-QMAKE_FIX_RPATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the g++ 4.2 compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-g++/qplatformdefs.h b/mkspecs/unsupported/macx-iosdevice-g++/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-g++/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qmake.conf b/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qmake.conf
deleted file mode 100644
index 4554843610..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-llvm
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/llvm.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/llvm.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.2.x or earlier")
-
-# iOS build tools
-QMAKE_CC = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2
-QMAKE_CXX = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-g++-4.2
-QMAKE_FIX_RPATH = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the llvm-g++ 4.2 compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qplatformdefs.h b/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-llvm-legacy/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iosdevice-llvm/qmake.conf b/mkspecs/unsupported/macx-iosdevice-llvm/qmake.conf
deleted file mode 100644
index 335c68fd42..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-llvm/qmake.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# qmake configuration for ios-device-llvm
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/llvm.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/llvm.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
-
-# iOS build tools
-QMAKE_CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2
-QMAKE_CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-g++-4.2
-QMAKE_FIX_RPATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the llvm-g++ 4.2 compiler")
-
-load(qt_config)
-
-# Include after config is loaded to allow autodetection on GL/ES version
-include(../../common/ios/arch.conf)
diff --git a/mkspecs/unsupported/macx-iosdevice-llvm/qplatformdefs.h b/mkspecs/unsupported/macx-iosdevice-llvm/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iosdevice-llvm/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-clang-legacy/qmake.conf b/mkspecs/unsupported/macx-iossimulator-clang-legacy/qmake.conf
deleted file mode 100644
index b042766a39..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-clang-legacy/qmake.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# qmake configuration for ios-simulator-clang
-#
-
-# All differences between device and simulator are handled in iOS include files
-include(../macx-iosdevice-clang-legacy/qmake.conf)
diff --git a/mkspecs/unsupported/macx-iossimulator-clang-legacy/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-clang-legacy/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-clang-legacy/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-clang/qmake.conf b/mkspecs/unsupported/macx-iossimulator-clang/qmake.conf
deleted file mode 100644
index 11301cb72f..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-clang/qmake.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# qmake configuration for ios-simulator-clang
-#
-
-# All differences between device and simulator are handled in iOS include files
-include(../macx-iosdevice-clang/qmake.conf)
diff --git a/mkspecs/unsupported/macx-iossimulator-clang/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-clang/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-clang/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-g++-legacy/qmake.conf b/mkspecs/unsupported/macx-iossimulator-g++-legacy/qmake.conf
deleted file mode 100644
index abc695231e..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-g++-legacy/qmake.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# qmake configuration for ios-simulator-g++
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/g++-macx.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/arch.conf)
-include(../../common/ios/g++.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check (g++ was discontinued at version 4.2)
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.2"): error("This mkspec requires Xcode 4.1.x or earlier")
-
-# iOS build tools
-QMAKE_CC = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2
-QMAKE_CXX = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/g++-4.2
-QMAKE_FIX_RPATH = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the g++ 4.2 compiler")
-
-load(qt_config)
diff --git a/mkspecs/unsupported/macx-iossimulator-g++-legacy/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-g++-legacy/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-g++-legacy/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-g++/qmake.conf b/mkspecs/unsupported/macx-iossimulator-g++/qmake.conf
deleted file mode 100644
index 99848be410..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-g++/qmake.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# qmake configuration for ios-simulator-g++
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/g++-macx.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/arch.conf)
-include(../../common/ios/g++.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check (g++ was discontinued at version 4.2, but user may have added it themselves)
-lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
-
-# iOS build tools
-QMAKE_CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2
-QMAKE_CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/g++-4.2
-QMAKE_FIX_RPATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the g++ 4.2 compiler")
-
-load(qt_config)
diff --git a/mkspecs/unsupported/macx-iossimulator-g++/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-g++/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-g++/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qmake.conf b/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qmake.conf
deleted file mode 100644
index 95d530cc18..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qmake.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# qmake configuration for ios-simulator-llvm
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/llvm.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/arch.conf)
-include(../../common/ios/llvm.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-!lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.2.x or earlier")
-
-# iOS build tools
-QMAKE_CC = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2
-QMAKE_CXX = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-g++-4.2
-QMAKE_FIX_RPATH = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the llvm-g++ 4.2 compiler")
-
-load(qt_config)
diff --git a/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-llvm-legacy/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/mkspecs/unsupported/macx-iossimulator-llvm/qmake.conf b/mkspecs/unsupported/macx-iossimulator-llvm/qmake.conf
deleted file mode 100644
index 7e3d4b5710..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-llvm/qmake.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# qmake configuration for ios-simulator-llvm
-#
-# Depends on:
-#
-# QMAKE_IOS_XCODE_VERSION - set in mkspecs/common/ios/versions.conf
-#
-
-include(../../common/mac.conf)
-include(../../common/gcc-base-ios.conf)
-include(../../common/llvm.conf)
-include(../../common/ios.conf)
-include(../../common/ios/versions.conf)
-include(../../common/ios/arch.conf)
-include(../../common/ios/llvm.conf)
-include(../../common/ios/qmake.conf)
-
-# Version check
-lessThan(QMAKE_IOS_XCODE_VERSION, "4.3"): error("This mkspec requires Xcode 4.3 or later")
-
-# iOS build tools
-QMAKE_CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2
-QMAKE_CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-g++-4.2
-QMAKE_FIX_RPATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/install_name_tool -id
-QMAKE_AR = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ar cq
-QMAKE_RANLIB = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ranlib -s
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
-
-# Check that compiler is valid
-!exists($$QMAKE_CXX): error("The version of Xcode installed on this system does not include the llvm-g++ 4.2 compiler")
-
-load(qt_config)
diff --git a/mkspecs/unsupported/macx-iossimulator-llvm/qplatformdefs.h b/mkspecs/unsupported/macx-iossimulator-llvm/qplatformdefs.h
deleted file mode 100644
index 5f80a17860..0000000000
--- a/mkspecs/unsupported/macx-iossimulator-llvm/qplatformdefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../../common/ios/qplatformdefs.h"
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 9893a7a7a4..923639d89d 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -46,6 +46,7 @@
#include <qregexp.h>
#include <qcryptographichash.h>
#include <qdebug.h>
+#include <qstring.h>
#include <stdlib.h>
#include <time.h>
#ifdef Q_OS_UNIX
@@ -222,7 +223,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
<< "\t\t\t" << writeSettings("lastKnownFileType", "wrapper.pb-project") << ";" << "\n"
<< "\t\t\t" << writeSettings("name", escapeFilePath(tmp_proj.first("TARGET") + projectSuffix())) << ";" << "\n"
<< "\t\t\t" << writeSettings("path", pbxproj) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<absolute>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
//WRAPPER
@@ -235,8 +235,7 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
t << "\t\t\t" << writeSettings("fileType", "compiled.mach-o.dylib") << ";" << "\n"
<< "\t\t\t" << writeSettings("path", tmp_proj.first("TARGET") + ".dylib") << ";" << "\n";
}
- t << "\t\t\t" << writeSettings("refType", "3", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("remoteRef", keyFor(pbxproj + "_WRAPPERREF")) << ";" << "\n"
+ t << "\t\t\t" << writeSettings("remoteRef", keyFor(pbxproj + "_WRAPPERREF")) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
<< "\t\t" << "};" << "\n";
t << "\t\t" << keyFor(pbxproj + "_WRAPPERREF") << " = {" << "\n"
@@ -252,7 +251,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
<< "\t\t\t" << writeSettings("children", project->values(ProKey(pbxproj + "_WRAPPER")), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", "Products") << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
@@ -291,14 +289,13 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("children", grp_it.value(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", escapeFilePath(grp_it.key().section(Option::dir_sep, -1))) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
//DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
- //BUILDSTYLE
- QString active_buildstyle;
+ //BUILDCONFIGURATIONS
+ QString defaultConfig;
for(int as_release = 0; as_release < 2; as_release++)
{
QMap<QString, QString> settings;
@@ -320,6 +317,8 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
}
QString name = (as_release ? "Release" : "Debug");
+ if (project->isActiveConfig("debug") != (bool)as_release)
+ defaultConfig = name;
QString key = keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_" + name);
project->values("QMAKE_SUBDIR_PBX_BUILDCONFIGS").append(key);
t << "\t\t" << key << " = {" << "\n"
@@ -330,26 +329,12 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
t << "\t\t\t" << "};" << "\n"
<< "\t\t\t" << writeSettings("name", name) << ";" << "\n"
<< "\t\t" << "};" << "\n";
-
- key = keyFor("QMAKE_SUBDIR_PBX_BUILDSTYLE_" + name);
- project->values("QMAKE_SUBDIR_PBX_BUILDSTYLES").append(key);
- if (project->isActiveConfig("debug") != (bool)as_release)
- active_buildstyle = name;
- t << "\t\t" << key << " = {" << "\n"
- << "\t\t\t" << writeSettings("buildRules", ProStringList(), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << "buildSettings = {" << "\n";
- for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
- t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n";
- t << "\t\t\t" << "};" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXBuildStyle", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
- << "\t\t" << "};" << "\n";
}
t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_BUILDCONFIG_LIST") << " = {" << "\n"
<< "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("buildConfigurations", project->values("QMAKE_SUBDIR_PBX_BUILDCONFIGS"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n"
+ << "\t\t\t" << writeSettings("defaultConfigurationName", defaultConfig, SettingsNoQuote) << ";" << "\n"
<< "\t\t" << "};" << "\n";
#ifdef GENERATE_AGGREGRATE_SUBDIR
@@ -376,7 +361,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
t << "\t\t" << keyFor("QMAKE_SUBDIR_PBX_ROOT_GROUP") << " = {" << "\n"
<< "\t\t\t" << writeSettings("children", project->values("QMAKE_SUBDIR_PBX_GROUPS"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
@@ -451,18 +435,17 @@ public:
ProjectBuilderSources::ProjectBuilderSources(const QString &k, bool b,
const QString &g, const QString &c, bool o) : buildable(b), object_output(o), key(k), group(g), compiler(c)
{
- if(group.isNull()) {
- if(k == "SOURCES")
- group = "Sources";
- else if(k == "HEADERS")
- group = "Headers";
- else if(k == "QMAKE_INTERNAL_INCLUDED_FILES")
- group = "Sources [qmake]";
- else if(k == "GENERATED_SOURCES" || k == "GENERATED_FILES")
- group = "Temporary Sources";
- else
- fprintf(stderr, "No group available for %s!\n", k.toLatin1().constData());
- }
+ // Override group name for a few common keys
+ if (k == "SOURCES" || k == "OBJECTIVE_SOURCES" || k == "HEADERS")
+ group = "Sources";
+ else if (k == "QMAKE_INTERNAL_INCLUDED_FILES")
+ group = "Supporting Files";
+ else if (k == "GENERATED_SOURCES" || k == "GENERATED_FILES")
+ group = "Generated Sources";
+ else if (k == "RESOURCES")
+ group = "Resources";
+ else if (group.isNull())
+ group = QString("Sources [") + c + "]";
}
QStringList
@@ -470,7 +453,6 @@ ProjectBuilderSources::files(QMakeProject *project) const
{
QStringList ret = project->values(ProKey(key)).toQStringList();
if(key == "QMAKE_INTERNAL_INCLUDED_FILES") {
- ret.prepend(project->projectFile());
for(int i = 0; i < ret.size(); ++i) {
QStringList newret;
if(!ret.at(i).endsWith(Option::prf_ext))
@@ -483,10 +465,48 @@ ProjectBuilderSources::files(QMakeProject *project) const
return ret;
}
+static QString xcodeFiletypeForFilename(const QString &filename)
+{
+ foreach (const QString &ext, Option::cpp_ext) {
+ if (filename.endsWith(ext))
+ return QStringLiteral("sourcecode.cpp.cpp");
+ }
+
+ foreach (const QString &ext, Option::c_ext) {
+ if (filename.endsWith(ext))
+ return QStringLiteral("sourcecode.c.c");
+ }
+
+ foreach (const QString &ext, Option::h_ext) {
+ if (filename.endsWith(ext))
+ return "sourcecode.c.h";
+ }
+
+ if (filename.endsWith(QStringLiteral(".mm")))
+ return QStringLiteral("sourcecode.cpp.objcpp");
+ if (filename.endsWith(QStringLiteral(".m")))
+ return QStringLiteral("sourcecode.c.objc");
+ if (filename.endsWith(QStringLiteral(".framework")))
+ return QStringLiteral("wrapper.framework");
+ if (filename.endsWith(QStringLiteral(".a")))
+ return QStringLiteral("archive.ar");
+ if (filename.endsWith(QStringLiteral(".pro")) || filename.endsWith(QStringLiteral(".qrc")))
+ return QStringLiteral("text");
+
+ return QString();
+}
bool
ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
{
+ // The code in this function assumes that the current directory matches
+ // the output directory, which is not actually the case when we are called
+ // from the generic generator code. Instead of changing every single
+ // assumption and fileFixify we cheat by moving into the output directory
+ // for the duration of this function.
+ QString input_dir = qmake_getpwd();
+ qmake_setpwd(Option::output_dir);
+
ProStringList tmp;
bool did_preprocess = false;
@@ -508,6 +528,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QFile mkf(mkfile);
if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
writingUnixMakefileGenerator = true;
+ qmake_setpwd(input_dir); // Makefile generation assumes input_dir as pwd
debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
QTextStream mkt(&mkf);
writeHeader(mkt);
@@ -516,6 +537,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
mkt.flush();
mkf.close();
writingUnixMakefileGenerator = false;
+ qmake_setpwd(Option::output_dir);
}
QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE");
mkfile = fileFixify(mkfile, qmake_getpwd());
@@ -523,15 +545,18 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t" << phase_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("generatedFileNames", ProStringList(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", "Qt Qmake") << ";" << "\n"
- << "\t\t\t" << writeSettings("neededFileNames", ProStringList(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";" << "\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
+ // FIXME: Move all file resolving logic out of ProjectBuilderSources::files(), as it
+ // doesn't have access to any of the information it needs to resolve relative paths.
+ project->values("QMAKE_INTERNAL_INCLUDED_FILES").prepend(fileFixify(project->projectFile(), qmake_getpwd(), input_dir));
+
//DUMP SOURCES
QMap<QString, ProStringList> groups;
QList<ProjectBuilderSources> sources;
@@ -545,14 +570,13 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
if (project->isEmpty(ProKey(*it + ".output")))
continue;
- ProString name = *it;
- const ProKey nkey(*it + ".name");
- if (!project->isEmpty(nkey))
- name = project->first(nkey);
- const ProStringList &inputs = project->values(ProKey(*it + ".input"));
- for(int input = 0; input < inputs.size(); ++input) {
- if (project->isEmpty(inputs.at(input).toKey()))
+ ProStringList &inputs = project->values(ProKey(*it + ".input"));
+ int input = 0;
+ while (input < inputs.size()) {
+ if (project->isEmpty(inputs.at(input).toKey())) {
+ ++input;
continue;
+ }
bool duplicate = false;
bool isObj = project->values(ProKey(*it + ".CONFIG")).indexOf("no_link") == -1;
if (!isObj) {
@@ -572,8 +596,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
sources.append(ProjectBuilderSources(inputs.at(input).toQString(), true,
- QString("Sources [") + name + "]", (*it).toQString(), isObj));
+ QString(), (*it).toQString(), isObj));
+
+ if (isObj) {
+ inputs.removeAt(input);
+ continue;
+ }
}
+
+ ++input;
}
}
}
@@ -618,30 +649,29 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
last_grp = new_grp;
}
+ if (groups[last_grp].contains(src_key))
+ continue;
groups[last_grp] += src_key;
in_root = false;
}
}
- if(in_root)
+ if (in_root) {
+ if (src_list.contains(src_key))
+ continue;
src_list.append(src_key);
+ }
//source reference
t << "\t\t" << src_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n"
- << "\t\t\t" << writeSettings("path", escapeFilePath(file)) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(file)), SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(file)) << ";" << "\n";
- QString filetype;
- for (QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
- if (file.endsWith((*cppit))) {
- filetype = "sourcecode.cpp.cpp";
- break;
- }
- }
+ << "\t\t\t" << writeSettings("path", escapeFilePath(file)) << ";" << "\n";
+ if (name != file)
+ t << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n";
+ t << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(file)) << ";" << "\n";
+ QString filetype = xcodeFiletypeForFilename(file);
if (!filetype.isNull())
t << "\t\t\t" << writeSettings("lastKnownFileType", filetype) << ";" << "\n";
t << "\t\t" << "};" << "\n";
- if(sources.at(source).isBuildable()) { //build reference
+ if (sources.at(source).isBuildable() && sources.at(source).isObjectOutput(file)) { //build reference
QString build_key = keyFor(file + ".BUILDABLE");
t << "\t\t" << build_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("fileRef", src_key) << ";" << "\n"
@@ -650,8 +680,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t\t" << writeSettings("ATTRIBUTES", ProStringList(), SettingsAsList, 5) << ";" << "\n"
<< "\t\t\t" << "};" << "\n"
<< "\t\t" << "};" << "\n";
- if(sources.at(source).isObjectOutput(file))
- project->values("QMAKE_PBX_OBJ").append(build_key);
+ project->values("QMAKE_PBX_OBJ").append(build_key);
}
}
if(!src_list.isEmpty()) {
@@ -671,7 +700,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("children", grp_it.value(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", escapeFilePath(grp_it.key().section(Option::dir_sep, -1))) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
@@ -775,10 +803,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t" << phase_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("generatedFileNames", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", "Qt Preprocessors") << ";" << "\n"
- << "\t\t\t" << writeSettings("neededFileNames", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";" << "\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";" << "\n"
<< "\t\t" << "};" << "\n";
@@ -786,12 +813,13 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
//SOURCE BUILDPHASE
if(!project->isEmpty("QMAKE_PBX_OBJ")) {
- QString grp = "Build Sources", key = keyFor(grp);
+ QString grp = "Compile Sources", key = keyFor(grp);
project->values("QMAKE_PBX_BUILDPHASES").append(key);
t << "\t\t" << key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("files", fixListForOutput("QMAKE_PBX_OBJ"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXSourcesBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", grp) << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
@@ -899,24 +927,25 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
libdirs += path;
}
library = fileFixify(library);
+ QString filetype = xcodeFiletypeForFilename(library);
QString key = keyFor(library);
- bool is_frmwrk = (library.endsWith(".framework"));
- t << "\t\t" << key << " = {" << "\n"
- << "\t\t\t" << writeSettings("isa", (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference"), SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n"
- << "\t\t\t" << writeSettings("path", escapeFilePath(library)) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(library)), SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(library)) << ";" << "\n"
- << "\t\t" << "};" << "\n";
- project->values("QMAKE_PBX_LIBRARIES").append(key);
- QString build_key = keyFor(library + ".BUILDABLE");
- t << "\t\t" << build_key << " = {" << "\n"
- << "\t\t\t" << writeSettings("fileRef", key) << ";" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << "settings = {" << "\n"
- << "\t\t\t" << "};" << "\n"
- << "\t\t" << "};" << "\n";
- project->values("QMAKE_PBX_BUILD_LIBRARIES").append(build_key);
+ if (!project->values("QMAKE_PBX_LIBRARIES").contains(key)) {
+ t << "\t\t" << key << " = {" << "\n"
+ << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";" << "\n"
+ << "\t\t\t" << writeSettings("path", escapeFilePath(library)) << ";" << "\n"
+ << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(library)) << ";" << "\n";
+ if (!filetype.isNull())
+ t << "\t\t\t" << writeSettings("lastKnownFileType", filetype) << ";" << "\n";
+ t << "\t\t" << "};" << "\n";
+ project->values("QMAKE_PBX_LIBRARIES").append(key);
+ QString build_key = keyFor(library + ".BUILDABLE");
+ t << "\t\t" << build_key << " = {" << "\n"
+ << "\t\t\t" << writeSettings("fileRef", key) << ";" << "\n"
+ << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
+ << "\t\t" << "};" << "\n";
+ project->values("QMAKE_PBX_BUILD_LIBRARIES").append(build_key);
+ }
}
if(remove)
tmp.removeAt(x);
@@ -955,10 +984,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t" << phase_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("generatedFileNames", ProStringList(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", "Qt Sublibs") << ";" << "\n"
- << "\t\t\t" << writeSettings("neededFileNames", ProStringList(), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << "\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";" << "\n"
<< "\t\t" << "};" << "\n";
@@ -967,42 +995,24 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) {
tmp = project->values("QMAKE_PBX_LIBRARIES");
if(!tmp.isEmpty()) {
- QString grp("External Frameworks and Libraries"), key = keyFor(grp);
+ QString grp("Frameworks"), key = keyFor(grp);
project->values("QMAKE_PBX_GROUPS").append(key);
t << "\t\t" << key << " = {" << "\n"
<< "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_LIBRARIES"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
- << "\t\t\t" << writeSettings("path", ProStringList()) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
}
{
- QString grp("Frameworks & Libraries"), key = keyFor(grp);
+ QString grp("Link Binary With Libraries"), key = keyFor(grp);
project->values("QMAKE_PBX_BUILDPHASES").append(key);
t << "\t\t" << key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("files", project->values("QMAKE_PBX_BUILD_LIBRARIES"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXFrameworksBuildPhase", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
- << "\t\t" << "};" << "\n";
- }
- if(project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES
- QString grp("Bundle Resources"), key = keyFor(grp);
- project->values("QMAKE_PBX_BUILDPHASES").append(key);
- t << "\t\t" << key << " = {" << "\n"
- << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << "files = (" << "\n";
- if(!project->isEmpty("ICON")) {
- ProString icon = project->first("ICON");
- if (icon.length() >= 2 && (icon.at(0) == '"' || icon.at(0) == '\'') && icon.endsWith(icon.at(0)))
- icon = icon.mid(1, icon.length()-2);
- t << "\t\t\t\t" << keyFor(icon + ".BUILDABLE") << ",\n";
- }
- t << "\t\t\t" << ");" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXResourcesBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
@@ -1024,78 +1034,96 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("shellScript", fixForOutput("cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME " + escapeFilePath(destDir))) << ";" << "\n"
<< "\t\t" << "};\n";
}
- //BUNDLE_DATA BUILDPHASE (copy)
- if(!project->isEmpty("QMAKE_BUNDLE_DATA")) {
+ // Copy Bundle Resources
+ if (!project->isEmpty("QMAKE_BUNDLE_DATA")) {
ProStringList bundle_file_refs;
+ ProStringList bundle_resources_files;
+
+ bool useCopyResourcesPhase = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app";
+
//all bundle data
const ProStringList &bundle_data = project->values("QMAKE_BUNDLE_DATA");
for(int i = 0; i < bundle_data.count(); i++) {
- ProStringList pbx_files;
+ ProStringList bundle_files;
+ ProString path = project->first(ProKey(bundle_data[i] + ".path"));
//all files
const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files"));
for(int file = 0; file < files.count(); file++) {
QString fn = files[file].toQString();
- QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_COPY_FILE_REF." + bundle_data[i] + "-" + fn);
+ QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE_REF." + bundle_data[i] + "-" + fn);
bundle_file_refs += file_ref_key;
t << "\t\t" << file_ref_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("path", escapeFilePath(fn)) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(fn)), SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(fn)) << ";" << "\n"
<< "\t\t" << "};" << "\n";
- QString copy_file_key = keyFor("QMAKE_PBX_BUNDLE_COPY_FILE." + bundle_data[i] + "-" + fn);
- pbx_files += copy_file_key;
- t << "\t\t" << copy_file_key << " = {\n"
+ QString file_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE." + bundle_data[i] + "-" + fn);
+ bundle_files += file_key;
+ t << "\t\t" << file_key << " = {\n"
<< "\t\t\t" << writeSettings("fileRef", file_ref_key) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << "settings = {\n"
- << "\t\t\t" << "}" << ";" << "\n"
<< "\t\t" << "}" << ";" << "\n";
}
- //the phase
- QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]);
- QString path;
- if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) {
- //###
+
+ if (!useCopyResourcesPhase || !path.isEmpty()) {
+ // The resource copy phase doesn't support paths, so we have to use
+ // a regular file copy phase (which doesn't optimize the resources).
+ QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]);
+ if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) {
+ //###
+ }
+
+ project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
+ t << "\t\t" << phase_key << " = {\n"
+ << "\t\t\t" << writeSettings("name", "Copy '" + bundle_data[i] + "' Files to Bundle") << ";" << "\n"
+ << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";" << "\n"
+ << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("files", bundle_files, SettingsAsList, 4) << ";" << "\n"
+ << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
+ << "\t\t" << "}" << ";" << "\n";
+ } else {
+ // Otherwise we leave it to the resource copy phase below
+ bundle_resources_files += bundle_files;
+ }
+ }
+
+ if (useCopyResourcesPhase) {
+ if (!project->isEmpty("ICON")) {
+ ProString icon = project->first("ICON");
+ if (icon.length() >= 2 && (icon.at(0) == '"' || icon.at(0) == '\'') && icon.endsWith(icon.at(0))) {
+ icon = icon.mid(1, icon.length() - 2);
+ bundle_resources_files += keyFor(icon + ".BUILDABLE");
+ }
}
- path += project->first(ProKey(bundle_data[i] + ".path"));
- project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
- t << "\t\t" << phase_key << " = {\n"
- << "\t\t\t" << writeSettings("name", "Bundle Copy [" + bundle_data[i] + "]") << ";" << "\n"
+
+ QString grp("Copy Bundle Resources"), key = keyFor(grp);
+ project->values("QMAKE_PBX_BUILDPHASES").append(key);
+ t << "\t\t" << key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";" << "\n"
- << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("files", pbx_files, SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("files", bundle_resources_files, SettingsAsList, 4) << ";" << "\n"
+ << "\t\t\t" << writeSettings("isa", "PBXResourcesBuildPhase", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n"
- << "\t\t" << "}" << ";" << "\n";
+ << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
+ << "\t\t" << "};" << "\n";
}
- QString bundle_copy_key = keyFor("QMAKE_PBX_BUNDLE_COPY");
- project->values("QMAKE_PBX_GROUPS").append(bundle_copy_key);
- t << "\t\t" << bundle_copy_key << " = {" << "\n"
+
+ QString bundle_data_key = keyFor("QMAKE_PBX_BUNDLE_DATA");
+ project->values("QMAKE_PBX_GROUPS").append(bundle_data_key);
+ t << "\t\t" << bundle_data_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("children", bundle_file_refs, SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", "Source [bundle data]") << ";" << "\n"
- << "\t\t\t" << writeSettings("path", ProStringList()) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("name", "Bundle Resources") << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
- //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
- //ROOT_GROUP
- t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
- << "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_GROUPS"), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("name", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"
- << "\t\t\t" << writeSettings("path", ProStringList()) << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
- << "\t\t" << "};" << "\n";
//REFERENCE
project->values("QMAKE_PBX_PRODUCTS").append(keyFor(pbx_dir + "QMAKE_PBX_REFERENCE"));
t << "\t\t" << keyFor(pbx_dir + "QMAKE_PBX_REFERENCE") << " = {" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n";
+ << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("includeInIndex", "0", SettingsNoQuote) << ";" << "\n";
if(project->first("TEMPLATE") == "app") {
ProString targ = project->first("QMAKE_ORIG_TARGET");
if(project->isActiveConfig("bundle") && !project->isEmpty("QMAKE_BUNDLE_EXTENSION")) {
@@ -1110,7 +1138,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
targ += ".app";
t << "\t\t\t" << writeSettings("explicitFileType", "wrapper.application") << ";" << "\n";
} else {
- t << "\t\t\t" << writeSettings("explicitFileType", "wrapper.executable") << ";" << "\n";
+ t << "\t\t\t" << writeSettings("explicitFileType", "compiled.mach-o.executable") << ";" << "\n";
}
QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") :
qmake_getpwd()) + Option::dir_sep + targ;
@@ -1144,8 +1172,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
t << "\t\t\t" << writeSettings("path", escapeFilePath(lib)) << ";" << "\n";
}
- t << "\t\t\t" << writeSettings("refType", "3", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
+ t << "\t\t\t" << writeSettings("sourceTree", "BUILT_PRODUCTS_DIR", SettingsNoQuote) << ";" << "\n"
<< "\t\t" << "};" << "\n";
{ //Products group
QString grp("Products"), key = keyFor(grp);
@@ -1154,177 +1181,38 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_PRODUCTS"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("name", "Products") << ";" << "\n"
- << "\t\t\t" << writeSettings("refType", "4", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
+
+ //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER
+ //ROOT_GROUP
+ t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n"
+ << "\t\t\t" << writeSettings("children", project->values("QMAKE_PBX_GROUPS"), SettingsAsList, 4) << ";" << "\n"
+ << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("name", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"
+ << "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";" << "\n"
+ << "\t\t" << "};" << "\n";
+
//TARGET
QString target_key = keyFor(pbx_dir + "QMAKE_PBX_TARGET");
project->values("QMAKE_PBX_TARGETS").append(target_key);
t << "\t\t" << target_key << " = {" << "\n"
<< "\t\t\t" << writeSettings("buildPhases", project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES") + project->values("QMAKE_PBX_BUILDPHASES"),
- SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << "buildSettings = {" << "\n";
- ProString cCompiler = project->first("QMAKE_CC");
- if (!cCompiler.isEmpty()) {
- t << "\t\t\t\t" << writeSettings("CC", fixForOutput(findProgram(cCompiler))) << ";" << "\n";
- }
- cCompiler = project->first("QMAKE_CXX");
- if (!cCompiler.isEmpty()) {
- t << "\t\t\t\t" << writeSettings("CPLUSPLUS", fixForOutput(findProgram(cCompiler))) << ";" << "\n";
- }
-
- t << "\t\t\t\t" << writeSettings("LEXFLAGS", fixListForOutput("QMAKE_LEXFLAGS")) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("YACCFLAGS", fixListForOutput("QMAKE_YACCFLAGS")) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("OTHER_REZFLAGS", ProStringList()) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("SECTORDER_FLAGS", ProStringList()) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("WARNING_CFLAGS", ProStringList()) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("PREBINDING", ProStringList((project->isEmpty("QMAKE_DO_PREBINDING") ? "NO" : "YES")), SettingsNoQuote) << ";" << "\n";
- if((project->first("TEMPLATE") == "app" && project->isActiveConfig("app_bundle")) ||
- (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
- project->isActiveConfig("lib_bundle"))) {
- QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString());
- if(plist.isEmpty())
- plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
- if(exists(plist)) {
- QFile plist_in_file(plist);
- if(plist_in_file.open(QIODevice::ReadOnly)) {
- QTextStream plist_in(&plist_in_file);
- QString plist_in_text = plist_in.readAll();
- plist_in_text = plist_in_text.replace("@ICON@",
- (project->isEmpty("ICON") ? QString("") : project->first("ICON").toQString().section(Option::dir_sep, -1)));
- if(project->first("TEMPLATE") == "app") {
- plist_in_text = plist_in_text.replace("@EXECUTABLE@", project->first("QMAKE_ORIG_TARGET").toQString());
- } else {
- plist_in_text = plist_in_text.replace("@LIBRARY@", project->first("QMAKE_ORIG_TARGET").toQString());
- }
- if (!project->values("VERSION").isEmpty()) {
- plist_in_text = plist_in_text.replace("@SHORT_VERSION@", project->first("VER_MAJ") + "." +
- project->first("VER_MIN"));
- }
- plist_in_text = plist_in_text.replace("@TYPEINFO@",
- (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") :
- project->first("QMAKE_PKGINFO_TYPEINFO").left(4).toQString()));
- QFile plist_out_file("Info.plist");
- if(plist_out_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QTextStream plist_out(&plist_out_file);
- plist_out << plist_in_text;
- t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";" << "\n";
- }
- }
- }
- }
-#if 1
- t << "\t\t\t\t" << writeSettings("BUILD_ROOT", escapeFilePath(qmake_getpwd())) << ";" << "\n";
-#endif
- if(!project->isActiveConfig("staticlib")) {
- t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS",
- fixListForOutput("SUBLIBS")
- + fixListForOutput("QMAKE_LFLAGS")
- + fixListForOutput("QMAKE_LIBS")
- + fixListForOutput("QMAKE_LIBS_PRIVATE"),
- SettingsAsList, 6) << ";" << "\n";
- }
- if(!project->isEmpty("DESTDIR")) {
- ProString dir = project->first("DESTDIR");
- if (QDir::isRelativePath(dir.toQString()))
- dir.prepend(qmake_getpwd() + Option::dir_sep);
- t << "\t\t\t\t" << writeSettings("INSTALL_DIR", dir) << ";" << "\n";
- }
- if (project->first("TEMPLATE") == "lib") {
- t << "\t\t\t\t" << writeSettings("INSTALL_PATH", ProStringList()) << ";" << "\n";
- }
- if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") {
- t << "\t\t\t\t" << writeSettings("DYLIB_CURRENT_VERSION", project->first("VER_MAJ")+"."+project->first("VER_MIN")+"."+project->first("VER_PAT")) << ";" << "\n";
- if(project->isEmpty("COMPAT_VERSION"))
- t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("VER_MAJ")+"."+project->first("VER_MIN")) << ";" << "\n";
- if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
- project->isActiveConfig("lib_bundle"))
- t << "\t\t\t\t" << writeSettings("FRAMEWORK_VERSION", project->first("QMAKE_FRAMEWORK_VERSION")) << ";" << "\n";
- }
- if(!project->isEmpty("COMPAT_VERSION"))
- t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("COMPAT_VERSION")) << ";" << "\n";
- if(!project->isEmpty("QMAKE_MACOSX_DEPLOYMENT_TARGET"))
- t << "\t\t\t\t" << writeSettings("MACOSX_DEPLOYMENT_TARGET", project->first("QMAKE_MACOSX_DEPLOYMENT_TARGET")) << ";" << "\n";
- if(project->first("TEMPLATE") == "app") {
- t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", fixForOutput(project->first("QMAKE_ORIG_TARGET").toQString())) << ";" << "\n";
- } else {
- if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) {
- t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "STATIC") << ";" << "\n";
- } else {
- t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "DYNAMIC") << ";" << "\n";
- }
- ProString lib = project->first("QMAKE_ORIG_TARGET");
- if(!project->isActiveConfig("lib_bundle") && !project->isActiveConfig("staticlib"))
- lib.prepend("lib");
- t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", escapeFilePath(lib)) << ";" << "\n";
- }
- tmp = project->values("QMAKE_PBX_VARS");
- for(int i = 0; i < tmp.count(); i++) {
- QString var = tmp[i].toQString(), val = QString::fromLocal8Bit(qgetenv(var.toLatin1().constData()));
- if(val.isEmpty() && var == "TB")
- val = "/usr/bin/";
- t << "\t\t\t\t" << writeSettings(var, escapeFilePath(val)) << ";" << "\n";
- }
- t << "\t\t\t" << "};" << "\n"
- << "\t\t\t" << "conditionalBuildSettings = {" << "\n"
- << "\t\t\t" << "};" << "\n"
- << "\t\t\t" << writeSettings("dependencies", project->values("QMAKE_PBX_TARGET_DEPENDS"), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << writeSettings("productReference", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n"
- << "\t\t\t" << writeSettings("shouldUseHeadermap", "1", SettingsNoQuote) << ";" << "\n";
+ SettingsAsList, 4) << ";" << "\n";
+ t << "\t\t\t" << writeSettings("dependencies", project->values("QMAKE_PBX_TARGET_DEPENDS"), SettingsAsList, 4) << ";" << "\n"
+ << "\t\t\t" << writeSettings("productReference", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n";
t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST_TARGET"), SettingsNoQuote) << ";" << "\n";
t << "\t\t\t" << writeSettings("isa", "PBXNativeTarget", SettingsNoQuote) << ";" << "\n";
+ t << "\t\t\t" << writeSettings("buildRules", ProStringList(), SettingsAsList) << ";" << "\n";
if(project->first("TEMPLATE") == "app") {
- if(!project->isActiveConfig("app_bundle")) {
- if (!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
- t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
- else
- t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.tool") << ";" << "\n";
+ if (!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE")) {
+ t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
} else {
- if (!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE"))
- t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n";
- else
+ if (project->isActiveConfig("app_bundle"))
t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.application") << ";" << "\n";
- t << "\t\t\t" << "productSettingsXML = \"";
- bool read_plist = false;
- if(exists("Info.plist")) {
- QFile plist("Info.plist");
- if (plist.open(QIODevice::ReadOnly)) {
- read_plist = true;
- QTextStream stream(&plist);
- while(!stream.atEnd())
- t << stream.readLine().replace('"', "\\\"") << endl;
- }
- }
- if(!read_plist) {
- t << "<?xml version="
- << "\\\"1.0\\\" encoding=" << "\\\"UTF-8\\\"" << "?>" << "\n"
- << "\t\t\t\t" << "<!DOCTYPE plist SYSTEM \\\"file://localhost/System/"
- << "Library/DTDs/PropertyList.dtd\\\">" << "\n"
- << "\t\t\t\t" << "<plist version=\\\"0.9\\\">" << "\n"
- << "\t\t\t\t" << "<dict>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleDevelopmentRegion</key>" << "\n"
- << "\t\t\t\t\t" << "<string>English</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleExecutable</key>" << "\n"
- << "\t\t\t\t\t" << "<string>" << project->first("QMAKE_ORIG_TARGET") << "</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleIconFile</key>" << "\n"
- << "\t\t\t\t\t" << "<string>" << var("ICON").section(Option::dir_sep, -1) << "</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleInfoDictionaryVersion</key>" << "\n"
- << "\t\t\t\t\t" << "<string>6.0</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundlePackageType</key>" << "\n"
- << "\t\t\t\t\t" << "<string>APPL</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleSignature</key>" << "\n"
- << "\t\t\t\t\t" << "<string>"
- << (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") :
- project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << "</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CFBundleVersion</key>" << "\n"
- << "\t\t\t\t\t" << "<string>0.1</string>" << "\n"
- << "\t\t\t\t\t" << "<key>CSResourcesFileMapped</key>" << "\n"
- << "\t\t\t\t\t" << "<true/>" << "\n"
- << "\t\t\t\t" << "</dict>" << "\n"
- << "\t\t\t\t" << "</plist>";
- }
- t << "\";" << "\n";
+ else
+ t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.tool") << ";" << "\n";
}
t << "\t\t\t" << writeSettings("name", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"
<< "\t\t\t" << writeSettings("productName", escapeFilePath(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n";
@@ -1343,12 +1231,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
else
t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.library.dynamic") << ";" << "\n";
}
- t << "\t\t\t" << writeSettings("startupPath", "<<ProjectDirectory>>") << ";" << "\n";
if(!project->isEmpty("DESTDIR"))
t << "\t\t\t" << writeSettings("productInstallPath", escapeFilePath(project->first("DESTDIR"))) << ";" << "\n";
t << "\t\t" << "};" << "\n";
//DEBUG/RELEASE
- QString active_buildstyle;
+ QString defaultConfig;
for(int as_release = 0; as_release < 2; as_release++)
{
QMap<QString, QString> settings;
@@ -1379,6 +1266,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
QString name = (as_release ? "Release" : "Debug");
+ if (project->isActiveConfig("debug") != (bool)as_release)
+ defaultConfig = name;
for (int i = 0; i < buildConfigGroups.size(); i++) {
QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + name + buildConfigGroups.at(i));
project->values(ProKey("QMAKE_PBX_BUILDCONFIGS_" + buildConfigGroups.at(i))).append(key);
@@ -1387,15 +1276,104 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << "buildSettings = {" << "\n";
for (QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n";
- if (!project->isEmpty("PRECOMPILED_HEADER")) {
- t << "\t\t\t\t" << writeSettings("GCC_PRECOMPILE_PREFIX_HEADER", "YES") << ";" << "\n"
- << "\t\t\t\t" << writeSettings("GCC_PREFIX_HEADER", escapeFilePath(project->first("PRECOMPILED_HEADER"))) << ";" << "\n";
- }
if (buildConfigGroups.at(i) == QLatin1String("PROJECT")) {
+ if (!project->isEmpty("QMAKE_XCODE_GCC_VERSION"))
+ t << "\t\t\t\t" << writeSettings("GCC_VERSION", project->first("QMAKE_XCODE_GCC_VERSION"), SettingsNoQuote) << ";" << "\n";
+ ProString program = project->first("QMAKE_CC");
+ if (!program.isEmpty())
+ t << "\t\t\t\t" << writeSettings("CC", fixForOutput(findProgram(program))) << ";" << "\n";
+ program = project->first("QMAKE_CXX");
+ // Xcode will automatically take care of using CC with the right -x option,
+ // and will actually break if we pass CPLUSPLUS, by adding an additional set of "++"
+ if (!program.isEmpty() && !program.contains("clang++"))
+ t << "\t\t\t\t" << writeSettings("CPLUSPLUS", fixForOutput(findProgram(program))) << ";" << "\n";
+ program = project->first("QMAKE_LINK");
+ if (!program.isEmpty())
+ t << "\t\t\t\t" << writeSettings("LDPLUSPLUS", fixForOutput(findProgram(program))) << ";" << "\n";
+
+ if ((project->first("TEMPLATE") == "app" && project->isActiveConfig("app_bundle")) ||
+ (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
+ project->isActiveConfig("lib_bundle"))) {
+ QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString());
+ if (plist.isEmpty())
+ plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
+ if (exists(plist)) {
+ QFile plist_in_file(plist);
+ if (plist_in_file.open(QIODevice::ReadOnly)) {
+ QTextStream plist_in(&plist_in_file);
+ QString plist_in_text = plist_in.readAll();
+ plist_in_text = plist_in_text.replace("@ICON@",
+ (project->isEmpty("ICON") ? QString("") : project->first("ICON").toQString().section(Option::dir_sep, -1)));
+ if (project->first("TEMPLATE") == "app") {
+ plist_in_text = plist_in_text.replace("@EXECUTABLE@", project->first("QMAKE_ORIG_TARGET").toQString());
+ } else {
+ plist_in_text = plist_in_text.replace("@LIBRARY@", project->first("QMAKE_ORIG_TARGET").toQString());
+ }
+ plist_in_text = plist_in_text.replace("@BUNDLEIDENTIFIER@", QLatin1String("${PRODUCT_NAME:rfc1034identifier}"));
+ if (!project->values("VERSION").isEmpty()) {
+ plist_in_text = plist_in_text.replace("@SHORT_VERSION@", project->first("VER_MAJ") + "." +
+ project->first("VER_MIN"));
+ }
+ plist_in_text = plist_in_text.replace("@TYPEINFO@",
+ (project->isEmpty("QMAKE_PKGINFO_TYPEINFO")
+ ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4).toQString()));
+ QFile plist_out_file("Info.plist");
+ if (plist_out_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream plist_out(&plist_out_file);
+ plist_out << plist_in_text;
+ t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";" << "\n";
+ }
+ }
+ }
+ }
+
+ t << "\t\t\t\t" << writeSettings("SYMROOT", escapeFilePath(qmake_getpwd())) << ";" << "\n";
+
+ if (!project->isEmpty("DESTDIR")) {
+ ProString dir = project->first("DESTDIR");
+ if (QDir::isRelativePath(dir.toQString()))
+ dir.prepend(qmake_getpwd() + Option::dir_sep);
+ t << "\t\t\t\t" << writeSettings("TARGET_BUILD_DIR", dir) << ";" << "\n";
+ }
+
+ if (project->first("TEMPLATE") == "lib")
+ t << "\t\t\t\t" << writeSettings("INSTALL_PATH", ProStringList()) << ";" << "\n";
+
+ if (!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") {
+ t << "\t\t\t\t" << writeSettings("DYLIB_CURRENT_VERSION", project->first("VER_MAJ")+"."+project->first("VER_MIN")+"."+project->first("VER_PAT")) << ";" << "\n";
+ if (project->isEmpty("COMPAT_VERSION"))
+ t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("VER_MAJ")+"."+project->first("VER_MIN")) << ";" << "\n";
+ if (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
+ project->isActiveConfig("lib_bundle"))
+ t << "\t\t\t\t" << writeSettings("FRAMEWORK_VERSION", project->first("QMAKE_FRAMEWORK_VERSION")) << ";" << "\n";
+ }
+ if (!project->isEmpty("COMPAT_VERSION"))
+ t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("COMPAT_VERSION")) << ";" << "\n";
+
+ if (!project->isEmpty("QMAKE_MACOSX_DEPLOYMENT_TARGET"))
+ t << "\t\t\t\t" << writeSettings("MACOSX_DEPLOYMENT_TARGET", project->first("QMAKE_MACOSX_DEPLOYMENT_TARGET")) << ";" << "\n";
+ if (!project->isEmpty("QMAKE_IOS_DEPLOYMENT_TARGET"))
+ t << "\t\t\t\t" << writeSettings("IPHONEOS_DEPLOYMENT_TARGET", project->first("QMAKE_IOS_DEPLOYMENT_TARGET")) << ";" << "\n";
+
+ if (!project->isEmpty("QMAKE_XCODE_CODE_SIGN_IDENTITY"))
+ t << "\t\t\t\t" << writeSettings("CODE_SIGN_IDENTITY", project->first("QMAKE_XCODE_CODE_SIGN_IDENTITY")) << ";" << "\n";
+
+ tmp = project->values("QMAKE_PBX_VARS");
+ for (int i = 0; i < tmp.count(); i++) {
+ QString var = tmp[i].toQString(), val = QString::fromLocal8Bit(qgetenv(var.toLatin1().constData()));
+ if (val.isEmpty() && var == "TB")
+ val = "/usr/bin/";
+ t << "\t\t\t\t" << writeSettings(var, escapeFilePath(val)) << ";" << "\n";
+ }
+ if (!project->isEmpty("PRECOMPILED_HEADER")) {
+ t << "\t\t\t\t" << writeSettings("GCC_PRECOMPILE_PREFIX_HEADER", "YES") << ";" << "\n"
+ << "\t\t\t\t" << writeSettings("GCC_PREFIX_HEADER", escapeFilePath(project->first("PRECOMPILED_HEADER"))) << ";" << "\n";
+ }
t << "\t\t\t\t" << writeSettings("HEADER_SEARCH_PATHS", fixListForOutput("INCLUDEPATH") + ProStringList(fixForOutput(specdir())), SettingsAsList, 5) << ";" << "\n"
<< "\t\t\t\t" << writeSettings("LIBRARY_SEARCH_PATHS", fixListForOutput("QMAKE_PBX_LIBPATHS"), SettingsAsList, 5) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("FRAMEWORK_SEARCH_PATHS", fixListForOutput("QMAKE_FRAMEWORKPATH"), SettingsAsList, 5) << ";" << "\n"
- << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";" << "\n";
+ << "\t\t\t\t" << writeSettings("FRAMEWORK_SEARCH_PATHS", fixListForOutput("QMAKE_FRAMEWORKPATH"),
+ !project->values("QMAKE_FRAMEWORKPATH").isEmpty() ? SettingsAsList : 0, 5) << ";" << "\n";
+
{
ProStringList cflags = fixListForOutput("QMAKE_CFLAGS");
const ProStringList &prl_defines = project->values("PRL_EXPORT_DEFINES");
@@ -1446,20 +1424,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t\t" << "};" << "\n"
<< "\t\t\t" << writeSettings("name", name) << ";" << "\n"
<< "\t\t" << "};" << "\n";
-
- key = keyFor("QMAKE_PBX_BUILDSTYLE_" + name);
- project->values("QMAKE_PBX_BUILDSTYLES").append(key);
- if (project->isActiveConfig("debug") != (bool)as_release)
- active_buildstyle = name;
- t << "\t\t" << key << " = {" << "\n"
- << "\t\t\t" << writeSettings("buildRules", ProStringList(), SettingsAsList, 4) << ";" << "\n"
- << "\t\t\t" << "buildSettings = {" << "\n";
- for(QMap<QString, QString>::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it)
- t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";" << "\n";
- t << "\t\t\t" << "};" << "\n"
- << "\t\t\t" << writeSettings("isa", "PBXBuildStyle") << ";" << "\n"
- << "\t\t\t" << writeSettings("name", name) << ";" << "\n"
- << "\t\t" << "};" << "\n";
}
}
for (int i = 0; i < buildConfigGroups.size(); i++) {
@@ -1467,20 +1431,24 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n"
<< "\t\t\t" << writeSettings("buildConfigurations", project->values(ProKey("QMAKE_PBX_BUILDCONFIGS_" + buildConfigGroups.at(i))), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n"
+ << "\t\t\t" << writeSettings("defaultConfigurationName", defaultConfig) << ";" << "\n"
<< "\t\t" << "};" << "\n";
}
//ROOT
t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n"
- << "\t\t\t" << writeSettings("buildStyles", project->values("QMAKE_PBX_BUILDSTYLES"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t\t" << writeSettings("hasScannedForEncodings", "1", SettingsNoQuote) << ";" << "\n"
+ << "\t\t\t" << writeSettings("compatibilityVersion", "Xcode 3.2") << ";" << "\n"
<< "\t\t\t" << writeSettings("isa", "PBXProject", SettingsNoQuote) << ";" << "\n"
- << "\t\t\t" << writeSettings("mainGroup", keyFor("QMAKE_PBX_ROOT_GROUP")) << ";" << "\n";
+ << "\t\t\t" << writeSettings("mainGroup", keyFor("QMAKE_PBX_ROOT_GROUP")) << ";" << "\n"
+ << "\t\t\t" << writeSettings("productRefGroup", keyFor("Products")) << ";" << "\n";
t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST_PROJECT")) << ";" << "\n";
t << "\t\t\t" << writeSettings("projectDirPath", ProStringList()) << ";" << "\n"
+ << "\t\t\t" << writeSettings("projectRoot", "") << ";" << "\n"
<< "\t\t\t" << writeSettings("targets", project->values("QMAKE_PBX_TARGETS"), SettingsAsList, 4) << ";" << "\n"
<< "\t\t" << "};" << "\n";
+ // FIXME: Deal with developmentRegion and knownRegions for QMAKE_PBX_ROOT
+
//FOOTER
t << "\t" << "};" << "\n"
<< "\t" << writeSettings("rootObject", keyFor("QMAKE_PBX_ROOT")) << ";" << "\n"
@@ -1511,6 +1479,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
writingUnixMakefileGenerator = false;
}
}
+
+ qmake_setpwd(input_dir);
+
return true;
}
@@ -1724,10 +1695,9 @@ ProjectBuilderMakefileGenerator::reftypeForFile(const QString &where)
QString ProjectBuilderMakefileGenerator::sourceTreeForFile(const QString &where)
{
- QString ret = "<absolute>";
- if (QDir::isRelativePath(unescapeFilePath(where)))
- ret = "SOURCE_ROOT"; //relative
- return ret;
+ // We always use absolute paths, instead of maintaining the SRCROOT
+ // build variable and making files relative to that.
+ return QLatin1String("<absolute>");
}
QString
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 41e40e0bb6..8ad603580c 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -1218,7 +1218,7 @@ void UnixMakefileGenerator::init2()
}
if(!project->isEmpty("QMAKE_BUNDLE")) {
- QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString());
+ QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString(), qmake_getpwd());
if(plist.isEmpty())
plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE");
if(exists(Option::fixPathToLocalOS(plist))) {
diff --git a/qmake/main.cpp b/qmake/main.cpp
index 5f9fb05449..6ef0707da9 100644
--- a/qmake/main.cpp
+++ b/qmake/main.cpp
@@ -116,6 +116,11 @@ int runQMake(int argc, char **argv)
if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir))
dir = tmp_dir;
}
+#ifdef Q_OS_MAC
+ if (fi.fileName().endsWith(QStringLiteral(".pbxproj"))
+ && dir.endsWith(QStringLiteral(".xcodeproj")))
+ dir += QStringLiteral("/..");
+#endif
if(!dir.isNull() && dir != ".")
Option::output_dir = dir;
if(QDir::isRelativePath(Option::output_dir))
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index eb7aa2e64f..6062dc7b7b 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -50,6 +50,8 @@
The operating system, must be one of: (Q_OS_x)
DARWIN - Darwin OS (synonym for Q_OS_MAC)
+ MAC - Mac OS X or iOS (iPhoneOS)
+ IOS - iOS (treated as a variant of Mac OS)
MSDOS - MS-DOS and Windows
OS2 - OS/2
OS2EMX - XFree86 on OS/2 (not PM)
@@ -166,6 +168,10 @@
# elif defined(Q_OS_DARWIN32)
# define Q_OS_MAC32
# endif
+# include <TargetConditionals.h>
+# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+# define Q_OS_IOS
+# endif
#endif
#if defined(Q_OS_WIN)
@@ -202,6 +208,22 @@
# define MAC_OS_X_VERSION_10_8 1080
# endif
#
+# if !defined(__IPHONE_4_3)
+# define __IPHONE_4_3 40300
+# endif
+# if !defined(__IPHONE_5_0)
+# define __IPHONE_5_0 50000
+# endif
+# if !defined(__IPHONE_5_1)
+# define __IPHONE_5_1 50100
+# endif
+# if !defined(__IPHONE_6_0)
+# define __IPHONE_6_0 60000
+# endif
+# if !defined(__IPHONE_6_1)
+# define __IPHONE_6_1 60100
+# endif
+#
# if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_8)
# warning "This version of Mac OS X is unsupported"
# endif
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index b833eb4962..361a6c2c67 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -63,6 +63,8 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
+#include "qglobal.h"
+
#ifndef Q_OS_IOS
#include <CoreServices/CoreServices.h>
#endif
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 058cfe92ec..f21c7a5ce7 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -18,9 +18,7 @@ testcocoon {
load(testcocoon)
}
-mac {
- LIBS_PRIVATE += -framework Cocoa
-}
+mac:!ios: LIBS_PRIVATE += -framework Cocoa
CONFIG += simd
diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp
index 0b3d9dc46d..d55d6a91bf 100644
--- a/src/gui/opengl/qopenglpaintdevice.cpp
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -116,6 +116,7 @@ public:
qreal dpmx;
qreal dpmy;
+ qreal devicePixelRatio;
bool flipped;
@@ -178,6 +179,7 @@ QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz)
, ctx(QOpenGLContext::currentContext())
, dpmx(qt_defaultDpiX() * 100. / 2.54)
, dpmy(qt_defaultDpiY() * 100. / 2.54)
+ , devicePixelRatio(1.0)
, flipped(false)
, engine(0)
{
@@ -249,6 +251,14 @@ void QOpenGLPaintDevice::setSize(const QSize &size)
}
/*!
+ Sets the device pixel ratio for the paint device to \a devicePixelRatio.
+*/
+void QOpenGLPaintDevice::setDevicePixelRatio(qreal devicePixelRatio)
+{
+ d_ptr->devicePixelRatio = devicePixelRatio;
+}
+
+/*!
\reimp
*/
@@ -272,9 +282,9 @@ int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
case PdmDpiY:
return qRound(d_ptr->dpmy * 0.0254);
case PdmPhysicalDpiX:
- return qRound(d_ptr->dpmx * 0.0254);
+ return qRound(d_ptr->dpmx * 0.0254 * d_ptr->devicePixelRatio);
case PdmPhysicalDpiY:
- return qRound(d_ptr->dpmy * 0.0254);
+ return qRound(d_ptr->dpmy * 0.0254 * d_ptr->devicePixelRatio);
default:
qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
return 0;
diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h
index 731000f131..5868a5740a 100644
--- a/src/gui/opengl/qopenglpaintdevice.h
+++ b/src/gui/opengl/qopenglpaintdevice.h
@@ -68,6 +68,7 @@ public:
QOpenGLContext *context() const;
QSize size() const;
void setSize(const QSize &size);
+ void setDevicePixelRatio(qreal devicePixelRatio);
qreal dotsPerMeterX() const;
qreal dotsPerMeterY() const;
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 57df8c8bc8..580e0b31b3 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -39,7 +39,11 @@ win32: {
}
integrity:SOURCES += kernel/qdnslookup_unix.cpp kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
-mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation -framework CoreServices
+mac {
+ LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation
+ !ios: LIBS_PRIVATE += -framework CoreServices
+}
+
mac:!ios:SOURCES += kernel/qnetworkproxy_mac.cpp
else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
else:blackberry:SOURCES += kernel/qnetworkproxy_blackberry.cpp
diff --git a/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri b/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri
new file mode 100644
index 0000000000..9a19d3c278
--- /dev/null
+++ b/src/platformsupport/cfsocketnotifier/cfsocketnotifier.pri
@@ -0,0 +1,4 @@
+mac {
+ HEADERS += $$PWD/qcfsocketnotifier_p.h
+ SOURCES += $$PWD/qcfsocketnotifier.cpp
+}
diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp
new file mode 100644
index 0000000000..5dcd6a4ffd
--- /dev/null
+++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcfsocketnotifier_p.h"
+#include <QtGui/qguiapplication.h>
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/qthread.h>
+
+
+/**************************************************************************
+ Socket Notifiers
+ *************************************************************************/
+void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef,
+ const void *, void *info)
+{
+
+ QCFSocketNotifier *cfSocketNotifier = static_cast<QCFSocketNotifier *>(info);
+ int nativeSocket = CFSocketGetNative(s);
+ MacSocketInfo *socketInfo = cfSocketNotifier->macSockets.value(nativeSocket);
+ QEvent notifierEvent(QEvent::SockAct);
+
+ // There is a race condition that happen where we disable the notifier and
+ // the kernel still has a notification to pass on. We then get this
+ // notification after we've successfully disabled the CFSocket, but our Qt
+ // notifier is now gone. The upshot is we have to check the notifier
+ // every time.
+ if (callbackType == kCFSocketReadCallBack) {
+ if (socketInfo->readNotifier)
+ QGuiApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
+ } else if (callbackType == kCFSocketWriteCallBack) {
+ if (socketInfo->writeNotifier)
+ QGuiApplication::sendEvent(socketInfo->writeNotifier, &notifierEvent);
+ }
+
+ if (cfSocketNotifier->maybeCancelWaitForMoreEvents)
+ cfSocketNotifier->maybeCancelWaitForMoreEvents(cfSocketNotifier->eventDispatcher);
+}
+
+/*
+ Adds a loop source for the given socket to the current run loop.
+*/
+CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
+{
+ CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
+ if (!loopSource)
+ return 0;
+
+ CFRunLoopAddSource(CFRunLoopGetMain(), loopSource, kCFRunLoopCommonModes);
+ return loopSource;
+}
+
+/*
+ Removes the loop source for the given socket from the current run loop.
+*/
+void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
+{
+ Q_ASSERT(runloop);
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes);
+ CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
+ CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
+ CFRunLoopSourceInvalidate(runloop);
+}
+
+QCFSocketNotifier::QCFSocketNotifier()
+:eventDispatcher(0)
+{
+
+}
+
+QCFSocketNotifier::~QCFSocketNotifier()
+{
+
+}
+
+void QCFSocketNotifier::setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher)
+{
+ eventDispatcher = hostEventDispacher;
+}
+
+void QCFSocketNotifier::setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack)
+{
+ maybeCancelWaitForMoreEvents = callBack;
+}
+
+void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int nativeSocket = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != eventDispatcher->thread()
+ || eventDispatcher->thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ if (type == QSocketNotifier::Exception) {
+ qWarning("QSocketNotifier::Exception is not supported on iOS");
+ return;
+ }
+
+ // Check if we have a CFSocket for the native socket, create one if not.
+ MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
+ if (!socketInfo) {
+ socketInfo = new MacSocketInfo();
+
+ // Create CFSocket, specify that we want both read and write callbacks (the callbacks
+ // are enabled/disabled later on).
+ const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
+ CFSocketContext context = {0, this, 0, 0, 0};
+ socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
+ if (CFSocketIsValid(socketInfo->socket) == false) {
+ qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
+ return;
+ }
+
+ CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
+ flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write
+ flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation
+ CFSocketSetSocketFlags(socketInfo->socket, flags);
+
+ // Add CFSocket to runloop.
+ if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
+ qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ return;
+ }
+
+ // Disable both callback types by default. This must be done after
+ // we add the CFSocket to the runloop, or else these calls will have
+ // no effect.
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+
+ macSockets.insert(nativeSocket, socketInfo);
+ }
+
+ // Increment read/write counters and select enable callbacks if necessary.
+ if (type == QSocketNotifier::Read) {
+ Q_ASSERT(socketInfo->readNotifier == 0);
+ socketInfo->readNotifier = notifier;
+ CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ } else if (type == QSocketNotifier::Write) {
+ Q_ASSERT(socketInfo->writeNotifier == 0);
+ socketInfo->writeNotifier = notifier;
+ CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+ }
+}
+
+void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int nativeSocket = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != eventDispatcher->thread() || eventDispatcher->thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ if (type == QSocketNotifier::Exception) {
+ qWarning("QSocketNotifier::Exception is not supported on iOS");
+ return;
+ }
+ MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
+ if (!socketInfo) {
+ qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
+ return;
+ }
+
+ // Decrement read/write counters and disable callbacks if necessary.
+ if (type == QSocketNotifier::Read) {
+ Q_ASSERT(notifier == socketInfo->readNotifier);
+ socketInfo->readNotifier = 0;
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ } else if (type == QSocketNotifier::Write) {
+ Q_ASSERT(notifier == socketInfo->writeNotifier);
+ socketInfo->writeNotifier = 0;
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+ }
+
+ // Remove CFSocket from runloop if this was the last QSocketNotifier.
+ if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
+ if (CFSocketIsValid(socketInfo->socket))
+ qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
+ CFRunLoopSourceInvalidate(socketInfo->runloop);
+ CFRelease(socketInfo->runloop);
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ delete socketInfo;
+ macSockets.remove(nativeSocket);
+ }
+}
+
+void QCFSocketNotifier::removeSocketNotifiers()
+{
+ // Remove CFSockets from the runloop.
+ for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) {
+ MacSocketInfo *socketInfo = (*it);
+ if (CFSocketIsValid(socketInfo->socket)) {
+ qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
+ CFRunLoopSourceInvalidate(socketInfo->runloop);
+ CFRelease(socketInfo->runloop);
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ }
+ }
+}
diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h
new file mode 100644
index 0000000000..cd1eb8e4ca
--- /dev/null
+++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCFSOCKETNOTIFIER_P_H
+#define QCFSOCKETNOTIFIER_P_H
+
+#include <QtCore/qabstracteventdispatcher.h>
+#include <QtCore/qhash.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+struct MacSocketInfo {
+ MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {}
+ CFSocketRef socket;
+ CFRunLoopSourceRef runloop;
+ QObject *readNotifier;
+ QObject *writeNotifier;
+};
+typedef QHash<int, MacSocketInfo *> MacSocketHash;
+
+typedef void (*MaybeCancelWaitForMoreEventsFn)(QAbstractEventDispatcher *hostEventDispacher);
+
+// The CoreFoundationSocketNotifier class implements socket notifiers support using
+// CFSocket for event dispatchers running on top of the Core Foundation run loop system.
+// (currently Mac and iOS)
+//
+// The principal functions are registerSocketNotifier() and unregisterSocketNotifier().
+//
+// setHostEventDispatcher() should be called at startup.
+// removeSocketNotifiers() should be called at shutdown.
+//
+class QCFSocketNotifier
+{
+public:
+ QCFSocketNotifier();
+ ~QCFSocketNotifier();
+ void setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher);
+ void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack);
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+ void removeSocketNotifiers();
+
+ MacSocketHash macSockets;
+ QAbstractEventDispatcher *eventDispatcher;
+ MaybeCancelWaitForMoreEventsFn maybeCancelWaitForMoreEvents;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index f7977964fe..d1abf123aa 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -1,2 +1,10 @@
HEADERS += $$PWD/qcoretextfontdatabase_p.h $$PWD/qfontengine_coretext_p.h
OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.mm
+
+ios: \
+ # On iOS CoreText and CoreGraphics are stand-alone frameworks
+ LIBS += -framework CoreText -framework CoreGraphics
+else: \
+ # On Mac OS they are part of the ApplicationServices umbrella framework,
+ # even in 10.8 where they were also made available stand-alone.
+ LIBS += -framework ApplicationServices
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index ef5bdbbf0d..fbd836f763 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qglobal.h"
+
#ifndef Q_OS_IOS
#import <Cocoa/Cocoa.h>
#import <IOKit/graphics/IOGraphicsLib.h>
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 57d9b422f4..8e0f396993 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -2,13 +2,14 @@ TARGET = QtPlatformSupport
QT = core-private gui-private
CONFIG += static internal_module
-mac:LIBS += -lz -framework CoreFoundation -framework Carbon
+mac:LIBS += -lz
load(qt_module)
DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER = ../corelib/global/qt_pch.h
+include(cfsocketnotifier/cfsocketnotifier.pri)
include(cglconvenience/cglconvenience.pri)
include(dnd/dnd.pri)
include(eglconvenience/eglconvenience.pri)
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 83e2a88e6a..6ed26f9e6c 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -78,7 +78,7 @@ HEADERS += qcocoaintegration.h \
RESOURCES += qcocoaresources.qrc
-LIBS += -framework Cocoa -framework IOKit
+LIBS += -framework Cocoa -framework Carbon -framework IOKit
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index f63ac0d205..93476ee1b4 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -93,6 +93,7 @@
#include <QtGui/qwindowdefs.h>
#include <QtCore/private/qabstracteventdispatcher_p.h>
#include <QtCore/private/qtimerinfo_unix_p.h>
+#include <QtPlatformSupport/private/qcfsocketnotifier_p.h>
#include <CoreFoundation/CoreFoundation.h>
@@ -132,16 +133,9 @@ public:
void wakeUp();
void interrupt();
void flush();
-};
-struct MacSocketInfo {
- MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {}
- CFSocketRef socket;
- CFRunLoopSourceRef runloop;
- QObject *readNotifier;
- QObject *writeNotifier;
+ friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};
-typedef QHash<int, MacSocketInfo *> MacSocketHash;
class QCocoaEventDispatcherPrivate : public QAbstractEventDispatcherPrivate
{
@@ -183,7 +177,7 @@ public:
void maybeCancelWaitForMoreEvents();
void ensureNSAppInitialized();
- MacSocketHash macSockets;
+ QCFSocketNotifier cfSocketNotifier;
QList<void *> queuedUserInputEvents; // NSEvent *
CFRunLoopSourceRef postedEventsSource;
CFRunLoopObserverRef waitingObserver;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 987600c6b4..ed4f8cd1fb 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -270,58 +270,6 @@ QCocoaEventDispatcher::registeredTimers(QObject *object) const
return d->timerInfoList.registeredTimers(object);
}
-/**************************************************************************
- Socket Notifiers
- *************************************************************************/
-void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef,
- const void *, void *info) {
- QCocoaEventDispatcherPrivate *const eventDispatcher
- = static_cast<QCocoaEventDispatcherPrivate *>(info);
- int nativeSocket = CFSocketGetNative(s);
- MacSocketInfo *socketInfo = eventDispatcher->macSockets.value(nativeSocket);
- QEvent notifierEvent(QEvent::SockAct);
-
- // There is a race condition that happen where we disable the notifier and
- // the kernel still has a notification to pass on. We then get this
- // notification after we've successfully disabled the CFSocket, but our Qt
- // notifier is now gone. The upshot is we have to check the notifier
- // everytime.
- if (callbackType == kCFSocketReadCallBack) {
- if (socketInfo->readNotifier)
- QGuiApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
- } else if (callbackType == kCFSocketWriteCallBack) {
- if (socketInfo->writeNotifier)
- QGuiApplication::sendEvent(socketInfo->writeNotifier, &notifierEvent);
- }
-
- eventDispatcher->maybeCancelWaitForMoreEvents();
-}
-
-/*
- Adds a loop source for the given socket to the current run loop.
-*/
-CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
-{
- CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
- if (!loopSource)
- return 0;
-
- CFRunLoopAddSource(mainRunLoop(), loopSource, kCFRunLoopCommonModes);
- return loopSource;
-}
-
-/*
- Removes the loop source for the given socket from the current run loop.
-*/
-void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
-{
- Q_ASSERT(runloop);
- CFRunLoopRemoveSource(mainRunLoop(), runloop, kCFRunLoopCommonModes);
- CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
- CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
- CFRunLoopSourceInvalidate(runloop);
-}
-
/*
Register a QSocketNotifier with the mac event system by creating a CFSocket with
with a read/write callback.
@@ -331,130 +279,14 @@ void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSource
*/
void QCocoaEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
{
- Q_ASSERT(notifier);
- int nativeSocket = notifier->socket();
- int type = notifier->type();
-#ifndef QT_NO_DEBUG
- if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
- qWarning("QSocketNotifier: Internal error");
- return;
- } else if (notifier->thread() != thread()
- || thread() != QThread::currentThread()) {
- qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
- return;
- }
-#endif
-
Q_D(QCocoaEventDispatcher);
-
- if (type == QSocketNotifier::Exception) {
- qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
- return;
- }
-
- // Check if we have a CFSocket for the native socket, create one if not.
- MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
- if (!socketInfo) {
- socketInfo = new MacSocketInfo();
-
- // Create CFSocket, specify that we want both read and write callbacks (the callbacks
- // are enabled/disabled later on).
- const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
- CFSocketContext context = {0, d, 0, 0, 0};
- socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
- if (CFSocketIsValid(socketInfo->socket) == false) {
- qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
- return;
- }
-
- CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
- flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write
- flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation
- CFSocketSetSocketFlags(socketInfo->socket, flags);
-
- // Add CFSocket to runloop.
- if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
- qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
- CFSocketInvalidate(socketInfo->socket);
- CFRelease(socketInfo->socket);
- return;
- }
-
- // Disable both callback types by default. This must be done after
- // we add the CFSocket to the runloop, or else these calls will have
- // no effect.
- CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
- CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
-
- d->macSockets.insert(nativeSocket, socketInfo);
- }
-
- // Increment read/write counters and select enable callbacks if necessary.
- if (type == QSocketNotifier::Read) {
- Q_ASSERT(socketInfo->readNotifier == 0);
- socketInfo->readNotifier = notifier;
- CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
- } else if (type == QSocketNotifier::Write) {
- Q_ASSERT(socketInfo->writeNotifier == 0);
- socketInfo->writeNotifier = notifier;
- CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
- }
+ d->cfSocketNotifier.registerSocketNotifier(notifier);
}
-/*
- Unregister QSocketNotifer. The CFSocket correspoding to this notifier is
- removed from the runloop of this is the last notifier that users
- that CFSocket.
-*/
void QCocoaEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
{
- Q_ASSERT(notifier);
- int nativeSocket = notifier->socket();
- int type = notifier->type();
-#ifndef QT_NO_DEBUG
- if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
- qWarning("QSocketNotifier: Internal error");
- return;
- } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
- qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
- return;
- }
-#endif
-
Q_D(QCocoaEventDispatcher);
-
- if (type == QSocketNotifier::Exception) {
- qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
- return;
- }
- MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
- if (!socketInfo) {
- qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
- return;
- }
-
- // Decrement read/write counters and disable callbacks if necessary.
- if (type == QSocketNotifier::Read) {
- Q_ASSERT(notifier == socketInfo->readNotifier);
- socketInfo->readNotifier = 0;
- CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
- } else if (type == QSocketNotifier::Write) {
- Q_ASSERT(notifier == socketInfo->writeNotifier);
- socketInfo->writeNotifier = 0;
- CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
- }
-
- // Remove CFSocket from runloop if this was the last QSocketNotifier.
- if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
- if (CFSocketIsValid(socketInfo->socket))
- qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
- CFRunLoopSourceInvalidate(socketInfo->runloop);
- CFRelease(socketInfo->runloop);
- CFSocketInvalidate(socketInfo->socket);
- CFRelease(socketInfo->socket);
- delete socketInfo;
- d->macSockets.remove(nativeSocket);
- }
+ d->cfSocketNotifier.unregisterSocketNotifier(notifier);
}
bool QCocoaEventDispatcher::hasPendingEvents()
@@ -940,11 +772,19 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
{
}
+void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher)
+{
+ static_cast<QCocoaEventDispatcher *>(eventDispatcher)->d_func()->maybeCancelWaitForMoreEvents();
+}
+
QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent)
: QAbstractEventDispatcher(*new QCocoaEventDispatcherPrivate, parent)
{
Q_D(QCocoaEventDispatcher);
+ d->cfSocketNotifier.setHostEventDispatcher(this);
+ d->cfSocketNotifier.setMaybeCancelWaitForMoreEventsCallback(qt_mac_maybeCancelWaitForMoreEventsForwarder);
+
// keep our sources running when modal loops are running
CFRunLoopAddCommonMode(mainRunLoop(), (CFStringRef) NSModalPanelRunLoopMode);
@@ -1127,17 +967,8 @@ QCocoaEventDispatcher::~QCocoaEventDispatcher()
[nsevent release];
}
- // Remove CFSockets from the runloop.
- for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) {
- MacSocketInfo *socketInfo = (*it);
- if (CFSocketIsValid(socketInfo->socket)) {
- qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
- CFRunLoopSourceInvalidate(socketInfo->runloop);
- CFRelease(socketInfo->runloop);
- CFSocketInvalidate(socketInfo->socket);
- CFRelease(socketInfo->socket);
- }
- }
+ d->cfSocketNotifier.removeSocketNotifiers();
+
CFRunLoopRemoveSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
CFRelease(d->postedEventsSource);
diff --git a/src/plugins/platforms/ios/ios.json b/src/plugins/platforms/ios/ios.json
new file mode 100644
index 0000000000..f0b766dae1
--- /dev/null
+++ b/src/plugins/platforms/ios/ios.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "ios" ]
+}
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
new file mode 100644
index 0000000000..842ff17f1c
--- /dev/null
+++ b/src/plugins/platforms/ios/ios.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS += plugin.pro qtmain.pro
diff --git a/src/plugins/platforms/ios/plugin.mm b/src/plugins/platforms/ios/plugin.mm
new file mode 100644
index 0000000000..a93b6037ad
--- /dev/null
+++ b/src/plugins/platforms/ios/plugin.mm
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformintegrationplugin.h>
+#include <qpa/qplatformthemeplugin.h>
+#include "qiosintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QIOSIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "ios.json")
+ public:
+ QPlatformIntegration *create(const QString&, const QStringList&);
+};
+
+QPlatformIntegration * QIOSIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ if (system.toLower() == "ios")
+ return new QIOSIntegration;
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
+
+Q_IMPORT_PLUGIN(QIOSIntegrationPlugin)
diff --git a/src/plugins/platforms/ios/plugin.pro b/src/plugins/platforms/ios/plugin.pro
new file mode 100644
index 0000000000..591a0a67ed
--- /dev/null
+++ b/src/plugins/platforms/ios/plugin.pro
@@ -0,0 +1,36 @@
+TARGET = qios
+
+PLUGIN_TYPE = platforms
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+LIBS += -framework UIKit -framework QuartzCore
+
+OBJECTIVE_SOURCES = \
+ plugin.mm \
+ qiosintegration.mm \
+ qioswindow.mm \
+ qiosscreen.mm \
+ qioseventdispatcher.mm \
+ qiosbackingstore.mm \
+ qiosapplicationdelegate.mm \
+ qiosviewcontroller.mm \
+ qioscontext.mm \
+ qiosinputcontext.mm \
+ qiostheme.mm \
+ qiosglobal.mm
+
+HEADERS = \
+ qiosintegration.h \
+ qioswindow.h \
+ qiosscreen.h \
+ qioseventdispatcher.h \
+ qiosbackingstore.h \
+ qiosapplicationdelegate.h \
+ qiosviewcontroller.h \
+ qioscontext.h \
+ qiosinputcontext.h \
+ qiostheme.h \
+ qiosglobal.h
+
+#HEADERS = qiossoftwareinputhandler.h
diff --git a/mkspecs/unsupported/macx-iosdevice-g++-legacy/qplatformdefs.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h
index 5f80a17860..442b37f1b3 100644
--- a/mkspecs/unsupported/macx-iosdevice-g++-legacy/qplatformdefs.h
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the qmake spec of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,4 +39,15 @@
**
****************************************************************************/
-#include "../../common/ios/qplatformdefs.h"
+#import <UIKit/UIKit.h>
+#import <QtGui/QtGui>
+
+@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
+
+@interface QIOSMainWrapperApplicationDelegate : QIOSApplicationDelegate
+@end
+
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
new file mode 100644
index 0000000000..41a3fff84f
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import "qiosapplicationdelegate.h"
+#include "qioswindow.h"
+#include <QtCore/QtCore>
+
+@implementation QIOSApplicationDelegate
+
+@synthesize window;
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ Q_UNUSED(application)
+ Q_UNUSED(launchOptions)
+
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ Q_UNUSED(application)
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ Q_UNUSED(application)
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ Q_UNUSED(application)
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ Q_UNUSED(application)
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ Q_UNUSED(application)
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+- (void)dealloc
+{
+ [window release];
+ [super dealloc];
+}
+
+@end
+
+
diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h
new file mode 100644
index 0000000000..c110f0e4d1
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosbackingstore.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSBACKINGSTORE_H
+#define QIOSBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSBackingStore : public QPlatformBackingStore
+{
+public:
+ QIOSBackingStore(QWindow *window);
+ ~QIOSBackingStore();
+
+ QPaintDevice *paintDevice();
+
+ void beginPaint(const QRegion &);
+ void endPaint();
+
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+ void resize(const QSize &size, const QRegion &staticContents);
+
+private:
+ QOpenGLContext *m_context;
+ QPaintDevice *m_device;
+};
+
+QT_END_NAMESPACE
+
+#endif // QIOSBACKINGSTORE_H
diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm
new file mode 100644
index 0000000000..566ff3a672
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosbackingstore.mm
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosbackingstore.h"
+#include "qioswindow.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLPaintDevice>
+
+#include <QtDebug>
+
+QIOSBackingStore::QIOSBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , m_context(new QOpenGLContext)
+ , m_device(0)
+{
+ m_context->setFormat(window->requestedFormat());
+ m_context->setScreen(window->screen());
+ m_context->create();
+}
+
+QIOSBackingStore::~QIOSBackingStore()
+{
+ delete m_context;
+ delete m_device;
+}
+
+void QIOSBackingStore::beginPaint(const QRegion &)
+{
+ // Needed to prevent QOpenGLContext::makeCurrent() from failing
+ window()->setSurfaceType(QSurface::OpenGLSurface);
+
+ m_context->makeCurrent(window());
+
+ static_cast<QOpenGLPaintDevice *>(paintDevice())->setSize(window()->size());
+ QIOSWindow *iosWindow = static_cast<QIOSWindow *>(window()->handle());
+ static_cast<QOpenGLPaintDevice *>(paintDevice())->setSize(window()->size() * iosWindow->devicePixelRatio());
+}
+
+QPaintDevice *QIOSBackingStore::paintDevice()
+{
+ if (!m_device) {
+ QIOSWindow *iosWindow = static_cast<QIOSWindow *>(window()->handle());
+ QOpenGLPaintDevice *openGLDevice = new QOpenGLPaintDevice(window()->size() * iosWindow->devicePixelRatio());
+ openGLDevice->setDevicePixelRatio(iosWindow->devicePixelRatio());
+ m_device = openGLDevice;
+ }
+
+ return m_device;
+}
+
+void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+
+ if (window != this->window()) {
+ // We skip flushing raster-based child windows, to avoid the extra cost of copying from the
+ // parent FBO into the child FBO. Since the child is already drawn inside the parent FBO, it
+ // will become visible when flushing the parent. The only case we end up not supporting is if
+ // the child window overlaps a sibling window that's draws using a separate QOpenGLContext.
+ return;
+ }
+ m_context->swapBuffers(window);
+}
+
+void QIOSBackingStore::endPaint()
+{
+ // Calling makeDone() on the context here would be an option,
+ // but is not needed, and would actually add some overhead.
+}
+
+void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ Q_UNUSED(staticContents);
+
+ // Resizing the backing store would in our case mean resizing the QWindow,
+ // as we cheat and use an QOpenGLPaintDevice that we target at the window.
+ // That's probably not what the user intended, so we ignore resizes of the
+ // backing store and always keep the paint device's size in sync with the
+ // window size in beginPaint().
+
+ if (size != window()->size())
+ qWarning() << "QIOSBackingStore needs to have the same size as its window";
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h
new file mode 100644
index 0000000000..082ec4794c
--- /dev/null
+++ b/src/plugins/platforms/ios/qioscontext.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSCONTEXT_H
+#define QIOSCONTEXT_H
+
+#include <qpa/qplatformopenglcontext.h>
+
+@class EAGLContext;
+
+QT_BEGIN_NAMESPACE
+
+class QIOSContext : public QObject, public QPlatformOpenGLContext
+{
+ Q_OBJECT
+
+public:
+ QIOSContext(QOpenGLContext *context);
+ ~QIOSContext();
+
+ QSurfaceFormat format() const;
+
+ void swapBuffers(QPlatformSurface *surface);
+
+ bool makeCurrent(QPlatformSurface *surface);
+ void doneCurrent();
+
+ GLuint defaultFramebufferObject(QPlatformSurface *) const;
+ QFunctionPointer getProcAddress(const QByteArray &procName);
+
+private Q_SLOTS:
+ void windowDestroyed(QObject *object);
+
+private:
+ EAGLContext *m_eaglContext;
+ QSurfaceFormat m_format;
+
+ struct FramebufferObject {
+ GLuint handle;
+ GLuint colorRenderbuffer;
+ GLuint depthRenderbuffer;
+ GLint renderbufferWidth;
+ GLint renderbufferHeight;
+ };
+
+ static void deleteBuffers(const FramebufferObject &framebufferObject);
+
+ mutable QHash<QWindow *, FramebufferObject> m_framebufferObjects;
+};
+
+QT_END_NAMESPACE
+
+#endif // QIOSCONTEXT_H
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
new file mode 100644
index 0000000000..d3966964e0
--- /dev/null
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qioscontext.h"
+#include "qioswindow.h"
+
+#include <dlfcn.h>
+
+#include <QtGui/QOpenGlContext>
+
+#import <OpenGLES/EAGL.h>
+#import <QuartzCore/CAEAGLLayer.h>
+
+QIOSContext::QIOSContext(QOpenGLContext *context)
+ : QPlatformOpenGLContext()
+ , m_eaglContext([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2])
+{
+ // Start out with the requested format
+ QSurfaceFormat format = context->format();
+
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ format.setMajorVersion(2);
+ format.setMinorVersion(0);
+
+ // Even though iOS internally double-buffers its rendering, we
+ // report single-buffered here since the buffer remains unchanged
+ // when swapping unlesss you manually clear it yourself.
+ format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
+
+ m_format = format;
+}
+
+QIOSContext::~QIOSContext()
+{
+ [EAGLContext setCurrentContext:m_eaglContext];
+
+ foreach (const FramebufferObject &framebufferObject, m_framebufferObjects)
+ deleteBuffers(framebufferObject);
+
+ [EAGLContext setCurrentContext:nil];
+ [m_eaglContext release];
+}
+
+void QIOSContext::deleteBuffers(const FramebufferObject &framebufferObject)
+{
+ if (framebufferObject.handle)
+ glDeleteFramebuffers(1, &framebufferObject.handle);
+ if (framebufferObject.colorRenderbuffer)
+ glDeleteRenderbuffers(1, &framebufferObject.colorRenderbuffer);
+ if (framebufferObject.depthRenderbuffer)
+ glDeleteRenderbuffers(1, &framebufferObject.depthRenderbuffer);
+}
+
+QSurfaceFormat QIOSContext::format() const
+{
+ return m_format;
+}
+
+bool QIOSContext::makeCurrent(QPlatformSurface *surface)
+{
+ Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+
+ [EAGLContext setCurrentContext:m_eaglContext];
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject(surface));
+
+ return true;
+}
+
+void QIOSContext::doneCurrent()
+{
+ [EAGLContext setCurrentContext:nil];
+}
+
+void QIOSContext::swapBuffers(QPlatformSurface *surface)
+{
+ Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window);
+ QWindow *window = static_cast<QWindow *>(surface->surface());
+ Q_ASSERT(m_framebufferObjects.contains(window));
+
+ [EAGLContext setCurrentContext:m_eaglContext];
+ glBindRenderbuffer(GL_RENDERBUFFER, m_framebufferObjects[window].colorRenderbuffer);
+ [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER];
+}
+
+GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const
+{
+ Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window);
+ QWindow *window = static_cast<QWindow *>(surface->surface());
+
+ FramebufferObject &framebufferObject = m_framebufferObjects[window];
+
+ // Set up an FBO for the window if it hasn't been created yet
+ if (!framebufferObject.handle) {
+ [EAGLContext setCurrentContext:m_eaglContext];
+
+ glGenFramebuffers(1, &framebufferObject.handle);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle);
+
+ glGenRenderbuffers(1, &framebufferObject.colorRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ framebufferObject.colorRenderbuffer);
+
+ if (m_format.depthBufferSize() > 0 || m_format.stencilBufferSize() > 0) {
+ glGenRenderbuffers(1, &framebufferObject.depthRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.depthRenderbuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ framebufferObject.depthRenderbuffer);
+
+ if (m_format.stencilBufferSize() > 0)
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ framebufferObject.depthRenderbuffer);
+ }
+
+ connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*)));
+ }
+
+ // Ensure that the FBO's buffers match the size of the window
+ QIOSWindow *platformWindow = static_cast<QIOSWindow *>(surface);
+ if (framebufferObject.renderbufferWidth != platformWindow->effectiveWidth() ||
+ framebufferObject.renderbufferHeight != platformWindow->effectiveHeight()) {
+
+ glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer);
+ UIView *view = reinterpret_cast<UIView *>(platformWindow->winId());
+ CAEAGLLayer *layer = static_cast<CAEAGLLayer *>(view.layer);
+ [m_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
+
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferObject.renderbufferWidth);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferObject.renderbufferHeight);
+
+ if (framebufferObject.depthRenderbuffer) {
+ glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.depthRenderbuffer);
+
+ // FIXME: Support more fine grained control over depth/stencil buffer sizes
+ if (m_format.stencilBufferSize() > 0)
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES,
+ framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight);
+ else
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
+ framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight);
+ }
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ }
+
+ return framebufferObject.handle;
+}
+
+void QIOSContext::windowDestroyed(QObject *object)
+{
+ QWindow *window = static_cast<QWindow *>(object);
+ if (m_framebufferObjects.contains(window)) {
+ deleteBuffers(m_framebufferObjects[window]);
+ m_framebufferObjects.remove(window);
+ }
+}
+
+QFunctionPointer QIOSContext::getProcAddress(const QByteArray& functionName)
+{
+ return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_NEXT, functionName.constData()));
+}
+
+#include "moc_qioscontext.cpp"
+
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
new file mode 100644
index 0000000000..53a75618ce
--- /dev/null
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Copyright (c) 2007-2008, Apple, Inc.
+**
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** * Neither the name of Apple, Inc. nor the names of its contributors
+** may be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_IOS_P_H
+#define QEVENTDISPATCHER_IOS_P_H
+
+#include <QtCore/qabstracteventdispatcher.h>
+#include <QtCore/private/qtimerinfo_unix_p.h>
+#include <QtPlatformSupport/private/qcfsocketnotifier_p.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSEventDispatcher : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+
+public:
+ explicit QIOSEventDispatcher(QObject *parent = 0);
+ ~QIOSEventDispatcher();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const;
+
+ int remainingTime(int timerId);
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+private:
+ bool m_interrupted;
+
+ CFRunLoopSourceRef m_postedEventsRunLoopSource;
+ CFRunLoopSourceRef m_blockingTimerRunLoopSource;
+
+ QTimerInfoList m_timerInfoList;
+ CFRunLoopTimerRef m_runLoopTimerRef;
+
+ QCFSocketNotifier m_cfSocketNotifier;
+
+ void processPostedEvents();
+ void maybeStartCFRunLoopTimer();
+ void maybeStopCFRunLoopTimer();
+
+ static void postedEventsRunLoopCallback(void *info);
+ static void nonBlockingTimerRunLoopCallback(CFRunLoopTimerRef, void *info);
+ static void blockingTimerRunLoopCallback(void *info);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_IOS_P_H
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
new file mode 100644
index 0000000000..e9bf039047
--- /dev/null
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qioseventdispatcher.h"
+#import "qiosapplicationdelegate.h"
+#include <qdebug.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/QThread>
+#include <QtCore/private/qcoreapplication_p.h>
+#include <UIKit/UIApplication.h>
+
+QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+
+static Boolean runLoopSourceEqualCallback(const void *info1, const void *info2)
+{
+ return info1 == info2;
+}
+
+void QIOSEventDispatcher::postedEventsRunLoopCallback(void *info)
+{
+ QIOSEventDispatcher *self = static_cast<QIOSEventDispatcher *>(info);
+ self->processPostedEvents();
+}
+
+void QIOSEventDispatcher::nonBlockingTimerRunLoopCallback(CFRunLoopTimerRef, void *info)
+{
+ // The (one and only) CFRunLoopTimer has fired, which means that at least
+ // one QTimer should now fire as well. Note that CFRunLoopTimer's callback will
+ // never recurse. So if the app starts a new QEventLoop within this callback, other
+ // timers will stop working. The work-around is to forward the callback to a
+ // dedicated CFRunLoopSource that can recurse:
+ QIOSEventDispatcher *self = static_cast<QIOSEventDispatcher *>(info);
+ CFRunLoopSourceSignal(self->m_blockingTimerRunLoopSource);
+}
+
+void QIOSEventDispatcher::blockingTimerRunLoopCallback(void *info)
+{
+ // TODO:
+ // We also need to block this new timer source
+ // along with the posted event source when calling processEvents()
+ // "manually" to prevent livelock deep in CFRunLoop.
+
+ QIOSEventDispatcher *self = static_cast<QIOSEventDispatcher *>(info);
+ self->m_timerInfoList.activateTimers();
+ self->maybeStartCFRunLoopTimer();
+}
+
+void QIOSEventDispatcher::maybeStartCFRunLoopTimer()
+{
+ // Find out when the next registered timer should fire, and schedule
+ // runLoopTimer accordingly. If the runLoopTimer does not yet exist, and
+ // at least one timer is registered, start by creating the timer:
+ if (m_timerInfoList.isEmpty()) {
+ Q_ASSERT(m_runLoopTimerRef == 0);
+ return;
+ }
+
+ CFAbsoluteTime ttf = CFAbsoluteTimeGetCurrent();
+ CFTimeInterval interval;
+
+ if (m_runLoopTimerRef == 0) {
+ // start the CFRunLoopTimer
+ CFTimeInterval oneyear = CFTimeInterval(3600. * 24. * 365.);
+
+ // calculate when the next timer should fire:
+ struct timespec tv;
+ if (m_timerInfoList.timerWait(tv)) {
+ interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
+ } else {
+ // this shouldn't really happen, but in case it does, set the timer
+ // to fire a some point in the distant future:
+ interval = oneyear;
+ }
+
+ ttf += interval;
+ CFRunLoopTimerContext info = { 0, this, 0, 0, 0 };
+ // create the timer with a large interval, as recommended by the CFRunLoopTimerSetNextFireDate()
+ // documentation, since we will adjust the timer's time-to-fire as needed to keep Qt timers working
+ m_runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QIOSEventDispatcher::nonBlockingTimerRunLoopCallback, &info);
+ Q_ASSERT(m_runLoopTimerRef != 0);
+
+ CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimerRef, kCFRunLoopCommonModes);
+ } else {
+ struct timespec tv;
+ // Calculate when the next timer should fire:
+ if (m_timerInfoList.timerWait(tv)) {
+ interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
+ } else {
+ // no timers can fire, but we cannot stop the CFRunLoopTimer, set the timer to fire at some
+ // point in the distant future (the timer interval is one year)
+ interval = CFRunLoopTimerGetInterval(m_runLoopTimerRef);
+ }
+
+ ttf += interval;
+ CFRunLoopTimerSetNextFireDate(m_runLoopTimerRef, ttf);
+ }
+}
+
+void QIOSEventDispatcher::maybeStopCFRunLoopTimer()
+{
+ if (m_runLoopTimerRef == 0)
+ return;
+
+ CFRunLoopTimerInvalidate(m_runLoopTimerRef);
+ CFRelease(m_runLoopTimerRef);
+ m_runLoopTimerRef = 0;
+}
+
+void QIOSEventDispatcher::processPostedEvents()
+{
+ QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
+}
+
+QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
+ : QAbstractEventDispatcher(parent)
+ , m_interrupted(false)
+ , m_runLoopTimerRef(0)
+{
+ m_cfSocketNotifier.setHostEventDispatcher(this);
+
+ CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
+ CFRunLoopSourceContext context;
+ bzero(&context, sizeof(CFRunLoopSourceContext));
+ context.equal = runLoopSourceEqualCallback;
+ context.info = this;
+
+ // source used to handle timers:
+ context.perform = QIOSEventDispatcher::blockingTimerRunLoopCallback;
+ m_blockingTimerRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ Q_ASSERT(m_blockingTimerRunLoopSource);
+ CFRunLoopAddSource(mainRunLoop, m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+
+ // source used to handle posted events:
+ context.perform = QIOSEventDispatcher::postedEventsRunLoopCallback;
+ m_postedEventsRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ Q_ASSERT(m_postedEventsRunLoopSource);
+ CFRunLoopAddSource(mainRunLoop, m_postedEventsRunLoopSource, kCFRunLoopCommonModes);
+}
+
+QIOSEventDispatcher::~QIOSEventDispatcher()
+{
+ CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
+ CFRunLoopRemoveSource(mainRunLoop, m_postedEventsRunLoopSource, kCFRunLoopCommonModes);
+ CFRelease(m_postedEventsRunLoopSource);
+
+ qDeleteAll(m_timerInfoList);
+ maybeStopCFRunLoopTimer();
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+ CFRelease(m_blockingTimerRunLoopSource);
+
+ m_cfSocketNotifier.removeSocketNotifiers();
+}
+
+bool QIOSEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ m_interrupted = false;
+ bool eventsProcessed = false;
+
+ bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
+ bool execFlagSet = (flags & QEventLoop::DialogExec) || (flags & QEventLoop::EventLoopExec);
+ bool useExecMode = execFlagSet && !excludeUserEvents;
+
+ if (useExecMode) {
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+ while ([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] && !m_interrupted);
+ eventsProcessed = true;
+ } else {
+ if (!(flags & QEventLoop::WaitForMoreEvents))
+ wakeUp();
+ eventsProcessed = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+ }
+ return eventsProcessed;
+}
+
+bool QIOSEventDispatcher::hasPendingEvents()
+{
+ qDebug() << __FUNCTION__ << "not implemented";
+ return false;
+}
+
+void QIOSEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ m_cfSocketNotifier.registerSocketNotifier(notifier);
+}
+
+void QIOSEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ m_cfSocketNotifier.unregisterSocketNotifier(notifier);
+}
+
+void QIOSEventDispatcher::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *obj)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !obj) {
+ qWarning("QIOSEventDispatcher::registerTimer: invalid arguments");
+ return;
+ } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QIOSEventDispatcher: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ m_timerInfoList.registerTimer(timerId, interval, timerType, obj);
+ maybeStartCFRunLoopTimer();
+}
+
+bool QIOSEventDispatcher::unregisterTimer(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QIOSEventDispatcher::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ bool returnValue = m_timerInfoList.unregisterTimer(timerId);
+ m_timerInfoList.isEmpty() ? maybeStopCFRunLoopTimer() : maybeStartCFRunLoopTimer();
+ return returnValue;
+}
+
+bool QIOSEventDispatcher::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QIOSEventDispatcher::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ bool returnValue = m_timerInfoList.unregisterTimers(object);
+ m_timerInfoList.isEmpty() ? maybeStopCFRunLoopTimer() : maybeStartCFRunLoopTimer();
+ return returnValue;
+}
+
+QList<QAbstractEventDispatcher::TimerInfo> QIOSEventDispatcher::registeredTimers(QObject *object) const
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QIOSEventDispatcher:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+#endif
+
+ return m_timerInfoList.registeredTimers(object);
+}
+
+int QIOSEventDispatcher::remainingTime(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QIOSEventDispatcher::remainingTime: invalid argument");
+ return -1;
+ }
+#endif
+
+ return m_timerInfoList.timerRemainingTime(timerId);
+}
+
+void QIOSEventDispatcher::wakeUp()
+{
+ CFRunLoopSourceSignal(m_postedEventsRunLoopSource);
+ CFRunLoopWakeUp(CFRunLoopGetMain());
+}
+
+void QIOSEventDispatcher::interrupt()
+{
+ wakeUp();
+ m_interrupted = true;
+}
+
+void QIOSEventDispatcher::flush()
+{
+ // X11 only.
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
new file mode 100644
index 0000000000..3be9f8bb21
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSGLOBAL_H
+#define QIOSGLOBAL_H
+
+#import <UIKit/UIKit.h>
+#include <QtCore/QtCore>
+
+@class QIOSViewController;
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformScreen;
+
+bool isQtApplication();
+QIOSViewController *rootViewController();
+
+CGRect toCGRect(const QRect &rect);
+QRect fromCGRect(const CGRect &rect);
+CGPoint toCGPoint(const QPoint &point);
+QPoint fromCGPoint(const CGPoint &point);
+Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation);
+UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation);
+QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen);
+
+QT_END_NAMESPACE
+
+#endif // QIOSGLOBAL_H
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
new file mode 100644
index 0000000000..5860078372
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosglobal.h"
+#include "qiosapplicationdelegate.h"
+#include "qiosviewcontroller.h"
+#include "qiosscreen.h"
+
+QT_BEGIN_NAMESPACE
+
+bool isQtApplication()
+{
+ // Returns true if the plugin is in full control of the whole application. This means
+ // that we control the application delegate and the top view controller, and can take
+ // actions that impacts all parts of the application. The opposite means that we are
+ // embedded inside a native iOS application, and should be more focused on playing along
+ // with native UIControls, and less inclined to change structures that lies outside the
+ // scope of our QWindows/UIViews.
+ static bool isQt = ([[UIApplication sharedApplication].delegate isKindOfClass:[QIOSApplicationDelegate class]]);
+ return isQt;
+}
+
+QIOSViewController *rootViewController()
+{
+ static QIOSViewController *c = isQtApplication() ?
+ static_cast<QIOSViewController *>([UIApplication sharedApplication].delegate.window.rootViewController) : nil;
+ return c;
+}
+
+CGRect toCGRect(const QRect &rect)
+{
+ return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+QRect fromCGRect(const CGRect &rect)
+{
+ return QRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+}
+
+CGPoint toCGPoint(const QPoint &point)
+{
+ return CGPointMake(point.x(), point.y());
+}
+
+QPoint fromCGPoint(const CGPoint &point)
+{
+ return QPoint(point.x, point.y);
+}
+
+Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation)
+{
+ Qt::ScreenOrientation qtOrientation;
+ switch (uiDeviceOrientation) {
+ case UIDeviceOrientationPortraitUpsideDown:
+ qtOrientation = Qt::InvertedPortraitOrientation;
+ break;
+ case UIDeviceOrientationLandscapeLeft:
+ qtOrientation = Qt::InvertedLandscapeOrientation;
+ break;
+ case UIDeviceOrientationLandscapeRight:
+ qtOrientation = Qt::LandscapeOrientation;
+ break;
+ case UIDeviceOrientationFaceUp:
+ case UIDeviceOrientationFaceDown:
+ qtOrientation = static_cast<Qt::ScreenOrientation>(-1); // not supported ATM.
+ break;
+ default:
+ qtOrientation = Qt::PortraitOrientation;
+ break;
+ }
+ return qtOrientation;
+}
+
+UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation)
+{
+ UIDeviceOrientation uiOrientation;
+ switch (qtOrientation) {
+ case Qt::LandscapeOrientation:
+ uiOrientation = UIDeviceOrientationLandscapeRight;
+ break;
+ case Qt::InvertedLandscapeOrientation:
+ uiOrientation = UIDeviceOrientationLandscapeLeft;
+ break;
+ case Qt::InvertedPortraitOrientation:
+ uiOrientation = UIDeviceOrientationPortraitUpsideDown;
+ break;
+ case Qt::PrimaryOrientation:
+ case Qt::PortraitOrientation:
+ default:
+ uiOrientation = UIDeviceOrientationPortrait;
+ break;
+ }
+ return uiOrientation;
+}
+
+QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen)
+{
+ // UIScreen is always in portrait. Use this function to convert CGRects
+ // aligned with UIScreen into whatever is the current orientation of QScreen.
+ QRect geometry = screen->geometry();
+ return geometry.width() < geometry.height() ? rect
+ : QRect(rect.y(), geometry.width() - rect.width() - rect.x(), rect.height(), rect.width());
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
new file mode 100644
index 0000000000..176ad05733
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSINPUTCONTEXT_H
+#define QIOSINPUTCONTEXT_H
+
+#include <UIKit/UIKit.h>
+
+#include <qpa/qplatforminputcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+@class QIOSKeyboardListener;
+
+class QIOSInputContext : public QPlatformInputContext
+{
+public:
+ QIOSInputContext();
+ ~QIOSInputContext();
+
+ QRectF keyboardRect() const;
+ void showInputPanel();
+ void hideInputPanel();
+ bool isInputPanelVisible() const;
+
+ void focusViewChanged(UIView *view);
+
+private:
+ QIOSKeyboardListener *m_keyboardListener;
+ UIView *m_focusView;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
new file mode 100644
index 0000000000..1d3ab12de9
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosglobal.h"
+#include "qiosinputcontext.h"
+#include "qioswindow.h"
+#include <QGuiApplication>
+
+@interface QIOSKeyboardListener : NSObject {
+@public
+ QIOSInputContext *m_context;
+ BOOL m_keyboardVisible;
+ QRectF m_keyboardRect;
+}
+@end
+
+@implementation QIOSKeyboardListener
+
+- (id)initWithQIOSInputContext:(QIOSInputContext *)context
+{
+ self = [super init];
+ if (self) {
+ m_context = context;
+ m_keyboardVisible = NO;
+ // After the keyboard became undockable (iOS5), UIKeyboardWillShow/UIKeyboardWillHide
+ // no longer works for all cases. So listen to keyboard frame changes instead:
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(keyboardDidChangeFrame:)
+ name:@"UIKeyboardDidChangeFrameNotification" object:nil];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:@"UIKeyboardDidChangeFrameNotification" object:nil];
+ [super dealloc];
+}
+
+- (void) keyboardDidChangeFrame:(NSNotification *)notification
+{
+ CGRect frame;
+ [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&frame];
+
+ m_keyboardRect = fromPortraitToPrimary(fromCGRect(frame), QGuiApplication::primaryScreen()->handle());
+ m_context->emitKeyboardRectChanged();
+
+ BOOL visible = CGRectIntersectsRect(frame, [UIScreen mainScreen].bounds);
+ if (m_keyboardVisible != visible) {
+ m_keyboardVisible = visible;
+ m_context->emitInputPanelVisibleChanged();
+ }
+}
+
+@end
+
+QIOSInputContext::QIOSInputContext()
+ : QPlatformInputContext()
+ , m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
+ , m_focusView(0)
+{
+}
+
+QIOSInputContext::~QIOSInputContext()
+{
+ [m_keyboardListener release];
+ [m_focusView release];
+}
+
+QRectF QIOSInputContext::keyboardRect() const
+{
+ return m_keyboardListener->m_keyboardRect;
+}
+
+void QIOSInputContext::showInputPanel()
+{
+ // Documentation tells that one should call (and recall, if necessary) becomeFirstResponder/resignFirstResponder
+ // to show/hide the keyboard. This is slightly inconvenient, since there exist no API to get the current first
+ // responder. Rather than searching for it from the top, we let the active QIOSWindow tell us which view to use.
+ // Note that Qt will forward keyevents to whichever QObject that needs it, regardless of which UIView the input
+ // actually came from. So in this respect, we're undermining iOS' responder chain.
+ [m_focusView becomeFirstResponder];
+}
+
+void QIOSInputContext::hideInputPanel()
+{
+ [m_focusView resignFirstResponder];
+}
+
+bool QIOSInputContext::isInputPanelVisible() const
+{
+ return m_keyboardListener->m_keyboardVisible;
+}
+
+void QIOSInputContext::focusViewChanged(UIView *view)
+{
+ if ([m_focusView isFirstResponder])
+ [view becomeFirstResponder];
+ [m_focusView release];
+ m_focusView = [view retain];
+}
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
new file mode 100644
index 0000000000..329a0a3d9b
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMINTEGRATION_UIKIT_H
+#define QPLATFORMINTEGRATION_UIKIT_H
+
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSIntegration : public QPlatformIntegration, public QPlatformNativeInterface
+{
+public:
+ QIOSIntegration();
+ ~QIOSIntegration();
+
+ bool hasCapability(Capability cap) const;
+
+ QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+
+ QPlatformFontDatabase *fontDatabase() const;
+ QPlatformInputContext *inputContext() const;
+
+ QVariant styleHint(StyleHint hint) const;
+
+ QStringList themeNames() const;
+ QPlatformTheme *createPlatformTheme(const QString &name) const;
+
+ QAbstractEventDispatcher *guiThreadEventDispatcher() const;
+ QPlatformNativeInterface *nativeInterface() const;
+
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
+
+ QTouchDevice *touchDevice();
+private:
+ QPlatformFontDatabase *m_fontDatabase;
+ QPlatformInputContext *m_inputContext;
+ QPlatformScreen *m_screen;
+ QTouchDevice *m_touchDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
new file mode 100644
index 0000000000..c7541c3e38
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosintegration.h"
+#include "qioswindow.h"
+#include "qiosbackingstore.h"
+#include "qiosscreen.h"
+#include "qioseventdispatcher.h"
+#include "qioscontext.h"
+#include "qiosinputcontext.h"
+#include "qiostheme.h"
+
+#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+QIOSIntegration::QIOSIntegration()
+ : m_fontDatabase(new QCoreTextFontDatabase)
+ , m_inputContext(new QIOSInputContext)
+ , m_screen(new QIOSScreen(QIOSScreen::MainScreen))
+{
+ if (![UIApplication sharedApplication]) {
+ qWarning()
+ << "Error: You are creating QApplication before calling UIApplicationMain.\n"
+ << "If you are writing a native iOS application, and only want to use Qt for\n"
+ << "parts of the application, a good place to create QApplication is from within\n"
+ << "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"
+ << "If you instead create a cross-platform Qt application and do not intend to call\n"
+ << "UIApplicationMain, you need to link in libqtmain.a, and substitute main with qt_main.\n"
+ << "This is normally done automatically by qmake.\n";
+ exit(-1);
+ }
+
+ screenAdded(m_screen);
+
+ m_touchDevice = new QTouchDevice;
+ m_touchDevice->setType(QTouchDevice::TouchScreen);
+ m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(m_touchDevice);
+}
+
+QIOSIntegration::~QIOSIntegration()
+{
+ delete m_touchDevice;
+}
+
+bool QIOSIntegration::hasCapability(Capability cap) const
+{
+ switch (cap) {
+ case OpenGL:
+ return true;
+ case MultipleWindows:
+ return true;
+ default:
+ return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformWindow *QIOSIntegration::createPlatformWindow(QWindow *window) const
+{
+ return new QIOSWindow(window);
+}
+
+// Used when the QWindow's surface type is set by the client to QSurface::RasterSurface
+QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return new QIOSBackingStore(window);
+}
+
+// Used when the QWindow's surface type is set by the client to QSurface::OpenGLSurface
+QPlatformOpenGLContext *QIOSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ Q_UNUSED(context);
+ return new QIOSContext(context);
+}
+
+QAbstractEventDispatcher *QIOSIntegration::guiThreadEventDispatcher() const
+{
+ return new QIOSEventDispatcher();
+}
+
+QPlatformFontDatabase * QIOSIntegration::fontDatabase() const
+{
+ return m_fontDatabase;
+}
+
+QPlatformInputContext *QIOSIntegration::inputContext() const
+{
+ return m_inputContext;
+}
+
+QVariant QIOSIntegration::styleHint(StyleHint hint) const
+{
+ switch (hint) {
+ case ShowIsFullScreen:
+ return true;
+ default:
+ return QPlatformIntegration::styleHint(hint);
+ }
+}
+
+QStringList QIOSIntegration::themeNames() const
+{
+ return QStringList(QLatin1String(QIOSTheme::name));
+}
+
+QPlatformTheme *QIOSIntegration::createPlatformTheme(const QString &name) const
+{
+ if (name == QLatin1String(QIOSTheme::name))
+ return new QIOSTheme;
+
+ return QPlatformIntegration::createPlatformTheme(name);
+}
+
+QPlatformNativeInterface *QIOSIntegration::nativeInterface() const
+{
+ return const_cast<QIOSIntegration *>(this);
+}
+
+void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
+{
+ if (!window || !window->handle())
+ return 0;
+
+ QByteArray lowerCaseResource = resource.toLower();
+
+ QIOSWindow *platformWindow = static_cast<QIOSWindow *>(window->handle());
+
+ if (lowerCaseResource == "uiview")
+ return reinterpret_cast<void *>(platformWindow->winId());
+
+ return 0;
+}
+
+QTouchDevice *QIOSIntegration::touchDevice()
+{
+ return m_touchDevice;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
new file mode 100644
index 0000000000..40c7a3ccf7
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSSCREEN_H
+#define QIOSSCREEN_H
+
+#include <UIKit/UIKit.h>
+
+#include <qpa/qplatformscreen.h>
+
+@class QIOSOrientationListener;
+
+QT_BEGIN_NAMESPACE
+
+class QIOSScreen : public QPlatformScreen
+{
+public:
+ QIOSScreen(unsigned int screenIndex);
+ ~QIOSScreen();
+
+ enum ScreenIndex { MainScreen = 0 };
+
+ QRect geometry() const;
+ QRect availableGeometry() const;
+ int depth() const;
+ QImage::Format format() const;
+ QSizeF physicalSize() const;
+ QDpi logicalDpi() const;
+ qreal devicePixelRatio() const;
+
+ Qt::ScreenOrientation nativeOrientation() const;
+ Qt::ScreenOrientation orientation() const;
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask);
+
+ UIScreen *uiScreen() const;
+
+ void setPrimaryOrientation(Qt::ScreenOrientation orientation);
+
+private:
+ UIScreen *m_uiScreen;
+ QRect m_geometry;
+ QRect m_availableGeometry;
+ int m_depth;
+ QSizeF m_physicalSize;
+ QIOSOrientationListener *m_orientationListener;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
new file mode 100644
index 0000000000..3265ed8e37
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosglobal.h"
+#include "qiosscreen.h"
+#include "qioswindow.h"
+#include <qpa/qwindowsysteminterface.h>
+#include "qiosapplicationdelegate.h"
+#include "qiosviewcontroller.h"
+
+#include <sys/sysctl.h>
+
+@interface QIOSOrientationListener : NSObject {
+ @public
+ QIOSScreen *m_screen;
+}
+- (id) initWithQIOSScreen:(QIOSScreen *)screen;
+@end
+
+@implementation QIOSOrientationListener
+
+- (id) initWithQIOSScreen:(QIOSScreen *)screen
+{
+ self = [super init];
+ if (self) {
+ m_screen = screen;
+ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(orientationChanged:)
+ name:@"UIDeviceOrientationDidChangeNotification" object:nil];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:@"UIDeviceOrientationDidChangeNotification" object:nil];
+ [super dealloc];
+}
+
+- (void) orientationChanged:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ Qt::ScreenOrientation orientation = toQtScreenOrientation([UIDevice currentDevice].orientation);
+ if (orientation != -1)
+ QWindowSystemInterface::handleScreenOrientationChange(m_screen->screen(), orientation);
+}
+
+@end
+
+/*!
+ Returns the model identifier of the device.
+
+ When running under the simulator, the identifier will not
+ match the simulated device, but will be x86_64 or i386.
+*/
+static QString deviceModelIdentifier()
+{
+ static const char key[] = "hw.machine";
+
+ size_t size;
+ sysctlbyname(key, NULL, &size, NULL, 0);
+
+ char value[size];
+ sysctlbyname(key, &value, &size, NULL, 0);
+
+ return QString::fromLatin1(value);
+}
+
+QIOSScreen::QIOSScreen(unsigned int screenIndex)
+ : QPlatformScreen()
+ , m_uiScreen([[UIScreen screens] objectAtIndex:qMin(screenIndex, [[UIScreen screens] count] - 1)])
+ , m_orientationListener(0)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ QString deviceIdentifier = deviceModelIdentifier();
+
+ if (deviceIdentifier == QStringLiteral("iPhone2,1") /* iPhone 3GS */
+ || deviceIdentifier == QStringLiteral("iPod3,1") /* iPod touch 3G */) {
+ m_depth = 18;
+ } else {
+ m_depth = 24;
+ }
+
+ int unscaledDpi = 163; // Regular iPhone DPI
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
+ && deviceIdentifier != QStringLiteral("iPad2,5") /* iPad Mini */) {
+ unscaledDpi = 132;
+ };
+
+ CGRect bounds = [m_uiScreen bounds];
+ m_geometry = QRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
+
+ CGRect frame = m_uiScreen.applicationFrame;
+ m_availableGeometry = QRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+
+ const qreal millimetersPerInch = 25.4;
+ m_physicalSize = QSizeF(m_geometry.size()) / unscaledDpi * millimetersPerInch;
+
+ if (isQtApplication()) {
+ // When in a non-mixed environment, let QScreen follow the current interface orientation:
+ setPrimaryOrientation(toQtScreenOrientation(rootViewController().interfaceOrientation));
+ }
+
+ [pool release];
+}
+
+QIOSScreen::~QIOSScreen()
+{
+ [m_orientationListener release];
+}
+
+QRect QIOSScreen::geometry() const
+{
+ return m_geometry;
+}
+
+QRect QIOSScreen::availableGeometry() const
+{
+ return m_availableGeometry;
+}
+
+int QIOSScreen::depth() const
+{
+ return m_depth;
+}
+
+QImage::Format QIOSScreen::format() const
+{
+ return QImage::Format_ARGB32_Premultiplied;
+}
+
+QSizeF QIOSScreen::physicalSize() const
+{
+ return m_physicalSize;
+}
+
+QDpi QIOSScreen::logicalDpi() const
+{
+ return QDpi(72, 72);
+}
+
+qreal QIOSScreen::devicePixelRatio() const
+{
+ return [m_uiScreen scale];
+}
+
+Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
+{
+ return Qt::PortraitOrientation;
+}
+
+Qt::ScreenOrientation QIOSScreen::orientation() const
+{
+ return toQtScreenOrientation([UIDevice currentDevice].orientation);
+}
+
+void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
+{
+ if (m_orientationListener && mask == Qt::PrimaryOrientation) {
+ [m_orientationListener release];
+ m_orientationListener = 0;
+ } else if (!m_orientationListener) {
+ m_orientationListener = [[QIOSOrientationListener alloc] initWithQIOSScreen:this];
+ }
+}
+
+void QIOSScreen::setPrimaryOrientation(Qt::ScreenOrientation orientation)
+{
+ // Note that UIScreen never changes orientation, but QScreen should. To work around
+ // this, we let QIOSViewController call us whenever interface orientation changes, and
+ // use that as primary orientation. After all, the viewcontrollers geometry is what we
+ // place QWindows on top of. A problem with this approach is that QIOSViewController is
+ // not in use in a mixed environment, which results in no change to primary orientation.
+ // We see that as acceptable since Qt should most likely not interfere with orientation
+ // for that case anyway.
+ bool portrait = screen()->isPortrait(orientation);
+ if (portrait && m_geometry.width() < m_geometry.height())
+ return;
+
+ // Switching portrait/landscape means swapping width/height (and adjusting x/y):
+ m_geometry = QRect(0, 0, m_geometry.height(), m_geometry.width());
+ m_physicalSize = QSizeF(m_physicalSize.height(), m_physicalSize.width());
+ m_availableGeometry = fromPortraitToPrimary(fromCGRect(m_uiScreen.applicationFrame), this);
+
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry);
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_availableGeometry);
+}
+
+UIScreen *QIOSScreen::uiScreen() const
+{
+ return m_uiScreen;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiossoftwareinputhandler.h b/src/plugins/platforms/ios/qiossoftwareinputhandler.h
new file mode 100644
index 0000000000..5dad6b8d86
--- /dev/null
+++ b/src/plugins/platforms/ios/qiossoftwareinputhandler.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSSOFTWAREINPUTHANDLER_H
+#define QIOSSOFTWAREINPUTHANDLER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtWidgets/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSSoftwareInputHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ QIOSSoftwareInputHandler() : m_CurrentFocusWidget(0), m_CurrentFocusObject(0) {}
+ bool eventFilter(QObject *obj, QEvent *event);
+
+private slots:
+ void activeFocusChanged(bool focus);
+
+private:
+ bool closeSoftwareInputPanel(QWidget *widget);
+
+ QPointer<QWidget> m_currentFocusWidget;
+ QPointer<QObject> m_currentFocusObject;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/mkspecs/unsupported/macx-iosdevice-clang/qplatformdefs.h b/src/plugins/platforms/ios/qiostheme.h
index 5f80a17860..5ccbcac710 100644
--- a/mkspecs/unsupported/macx-iosdevice-clang/qplatformdefs.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the qmake spec of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,4 +39,26 @@
**
****************************************************************************/
-#include "../../common/ios/qplatformdefs.h"
+#ifndef QIOSTHEME_H
+#define QIOSTHEME_H
+
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSTheme : public QPlatformTheme
+{
+public:
+ QIOSTheme();
+ ~QIOSTheme();
+
+ QVariant themeHint(ThemeHint hint) const;
+
+ const QFont *font(Font type = SystemFont) const;
+
+ static const char *name;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
new file mode 100644
index 0000000000..f98781f8a7
--- /dev/null
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiostheme.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+#include <QtGui/QFont>
+
+#include <UIKit/UIFont.h>
+#include <UIKit/UIInterface.h>
+
+QT_BEGIN_NAMESPACE
+
+const char *QIOSTheme::name = "ios";
+
+QIOSTheme::QIOSTheme()
+{
+}
+
+QIOSTheme::~QIOSTheme()
+{
+}
+
+QVariant QIOSTheme::themeHint(ThemeHint hint) const
+{
+ switch (hint) {
+ case QPlatformTheme::StyleNames:
+ return QStringList(QStringLiteral("fusion"));
+ default:
+ return QPlatformTheme::themeHint(hint);
+ }
+}
+
+const QFont *QIOSTheme::font(Font type) const
+{
+ static QHash<QPlatformTheme::Font, QFont *> fonts;
+ if (fonts.isEmpty()) {
+ // The real system font on iOS is '.Helvetica Neue UI', as returned by both [UIFont systemFontOfSize]
+ // and CTFontCreateUIFontForLanguage(kCTFontSystemFontType, ...), but this font is not included when
+ // populating the available fonts in QCoreTextFontDatabase::populateFontDatabase(), since the font
+ // is internal to iOS and not supposed to be used by applications. We could potentially add this
+ // font to the font-database, but it would then show up when enumerating user fonts from Qt
+ // applications since we don't have a flag in Qt to mark a font as a private system font.
+ // For now we hard-code the font to Helvetica, which should be very close to the actual
+ // system font.
+ QLatin1String systemFontFamilyName("Helvetica");
+ fonts.insert(QPlatformTheme::SystemFont, new QFont(systemFontFamilyName, [UIFont systemFontSize]));
+ fonts.insert(QPlatformTheme::SmallFont, new QFont(systemFontFamilyName, [UIFont smallSystemFontSize]));
+ fonts.insert(QPlatformTheme::LabelFont, new QFont(systemFontFamilyName, [UIFont labelFontSize]));
+ fonts.insert(QPlatformTheme::PushButtonFont, new QFont(systemFontFamilyName, [UIFont buttonFontSize]));
+ }
+
+ return fonts.value(type, 0);
+}
+
+QT_END_NAMESPACE
diff --git a/mkspecs/common/ios/GLES/gl.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index 2b94b162eb..d5a61cb3f4 100644
--- a/mkspecs/common/ios/GLES/gl.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the qmake spec of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,5 +39,8 @@
**
****************************************************************************/
-#include <OpenGLES/ES1/gl.h>
-#include <OpenGLES/ES1/glext.h>
+#import <UIKit/UIKit.h>
+
+@interface QIOSViewController : UIViewController
+@end
+
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
new file mode 100644
index 0000000000..c52bfd7345
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import "qiosviewcontroller.h"
+
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
+#include "qiosscreen.h"
+#include "qiosglobal.h"
+
+@implementation QIOSViewController
+
+- (void)viewDidLoad
+{
+#ifdef QT_DEBUG
+ if (!self.nibName)
+ self.view.backgroundColor = [UIColor magentaColor];
+#endif
+}
+
+-(BOOL)shouldAutorotate
+{
+ // For now we assume that if the application doesn't listen to orientation
+ // updates it means it would like to enable auto-rotation, and vice versa.
+ if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
+ return !guiApp->primaryScreen()->orientationUpdateMask();
+ else
+ return YES; // Startup case: QGuiApplication is not ready yet.
+
+ // FIXME: Investigate a proper Qt API for auto-rotation and orientation locking
+}
+
+-(NSUInteger)supportedInterfaceOrientations
+{
+ // We need to tell iOS that we support all orientations in order to set
+ // status bar orientation when application content orientation changes.
+ return UIInterfaceOrientationMaskAll;
+}
+
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
+{
+ Q_UNUSED(duration);
+ Qt::ScreenOrientation orientation = toQtScreenOrientation(toInterfaceOrientation);
+ if (orientation == -1)
+ return;
+
+ QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle());
+ qiosScreen->setPrimaryOrientation(orientation);
+}
+
+@end
+
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
new file mode 100644
index 0000000000..cefb6f9388
--- /dev/null
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSWINDOW_H
+#define QIOSWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#import <UIKit/UIKit.h>
+
+class QIOSContext;
+class QIOSWindow;
+
+@interface UIView (QIOS)
+@property(readonly) QWindow *qwindow;
+@end
+
+QT_BEGIN_NAMESPACE
+
+class QIOSWindow : public QPlatformWindow
+{
+public:
+ explicit QIOSWindow(QWindow *window);
+ ~QIOSWindow();
+
+ void setGeometry(const QRect &rect);
+
+ void setWindowState(Qt::WindowState state);
+ void setParent(const QPlatformWindow *window);
+ void handleContentOrientationChange(Qt::ScreenOrientation orientation);
+ void setVisible(bool visible);
+
+ void raise() { raiseOrLower(true); }
+ void lower() { raiseOrLower(false); }
+ void requestActivateWindow();
+
+ qreal devicePixelRatio() const;
+ int effectiveWidth() const;
+ int effectiveHeight() const;
+
+ WId winId() const { return WId(m_view); };
+
+ QList<QWindowSystemInterface::TouchPoint> &touchPoints() { return m_touchPoints; }
+ QHash<UITouch *, int> &activeTouches() { return m_activeTouches; }
+ int &touchId() { return m_touchId; }
+
+private:
+ UIView *m_view;
+ QList<QWindowSystemInterface::TouchPoint> m_touchPoints;
+ QHash<UITouch *, int> m_activeTouches;
+ int m_touchId;
+
+ QRect m_requestedGeometry;
+ int m_windowLevel;
+ qreal m_devicePixelRatio;
+
+ void raiseOrLower(bool raise);
+ void updateWindowLevel();
+ bool blockedByModal();
+};
+
+QT_END_NAMESPACE
+
+#endif // QIOSWINDOW_H
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
new file mode 100644
index 0000000000..e4fb5e2e1c
--- /dev/null
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -0,0 +1,523 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosglobal.h"
+#include "qioswindow.h"
+#include "qioscontext.h"
+#include "qiosinputcontext.h"
+#include "qiosscreen.h"
+#include "qiosapplicationdelegate.h"
+#include "qiosviewcontroller.h"
+#include "qiosintegration.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
+#import <QuartzCore/CAEAGLLayer.h>
+
+#include <QtGui/QKeyEvent>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtDebug>
+
+@interface EAGLView : UIView <UIKeyInput>
+{
+@public
+ UITextAutocapitalizationType autocapitalizationType;
+ UITextAutocorrectionType autocorrectionType;
+ BOOL enablesReturnKeyAutomatically;
+ UIKeyboardAppearance keyboardAppearance;
+ UIKeyboardType keyboardType;
+ UIReturnKeyType returnKeyType;
+ BOOL secureTextEntry;
+ QIOSWindow *m_qioswindow;
+}
+
+@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
+@property(nonatomic) UITextAutocorrectionType autocorrectionType;
+@property(nonatomic) BOOL enablesReturnKeyAutomatically;
+@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
+@property(nonatomic) UIKeyboardType keyboardType;
+@property(nonatomic) UIReturnKeyType returnKeyType;
+@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
+
+@end
+
+@implementation EAGLView
+
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+-(id)initWithQIOSWindow:(QIOSWindow *)window
+{
+ if (self = [self initWithFrame:toCGRect(window->geometry())])
+ m_qioswindow = window;
+
+ return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ // Set up EAGL layer
+ CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
+ eaglLayer.opaque = TRUE;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+
+ // Set up text input
+ autocapitalizationType = UITextAutocapitalizationTypeNone;
+ autocorrectionType = UITextAutocorrectionTypeNo;
+ enablesReturnKeyAutomatically = NO;
+ keyboardAppearance = UIKeyboardAppearanceDefault;
+ keyboardType = UIKeyboardTypeDefault;
+ returnKeyType = UIReturnKeyDone;
+ secureTextEntry = NO;
+
+ if (isQtApplication())
+ self.hidden = YES;
+
+ self.multipleTouchEnabled = YES;
+ }
+
+ return self;
+}
+
+- (void)layoutSubviews
+{
+ // This method is the de facto way to know that view has been resized,
+ // or otherwise needs invalidation of its buffers. Note though that we
+ // do not get this callback when the view just changes its position, so
+ // the position of our QWindow (and platform window) will only get updated
+ // when the size is also changed.
+
+ if (!CGAffineTransformIsIdentity(self.transform))
+ qWarning() << m_qioswindow->window()
+ << "is backed by a UIView that has a transform set. This is not supported.";
+
+ QRect geometry = fromCGRect(self.frame);
+ m_qioswindow->QPlatformWindow::setGeometry(geometry);
+ QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), geometry);
+
+ // If we have a new size here we need to resize the FBO's corresponding buffers,
+ // but we defer that to when the application calls makeCurrent.
+
+ [super layoutSubviews];
+}
+
+/*
+ Touch handling:
+
+ UIKit generates [Began -> Moved -> Ended] event sequences for
+ each touch point. The iOS plugin tracks each individual
+ touch and assigns it an id for use by Qt. The id counter is
+ incremented on each began and decrement as follows:
+ 1) by one when the most recent touch ends.
+ 2) to zero when all touches ends.
+
+ The TouchPoint list is reused between events.
+*/
+- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
+{
+ QList<QWindowSystemInterface::TouchPoint> &touchPoints = m_qioswindow->touchPoints();
+ QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
+
+ // Mark all touch points as stationary
+ for (QList<QWindowSystemInterface::TouchPoint>::iterator it = touchPoints.begin(); it != touchPoints.end(); ++it)
+ it->state = Qt::TouchPointStationary;
+
+ // Update changed touch points with the new state
+ for (UITouch *touch in touches) {
+ const int touchId = activeTouches.value(touch);
+ QWindowSystemInterface::TouchPoint &touchPoint = touchPoints[touchId];
+ touchPoint.state = state;
+ if (state == Qt::TouchPointPressed)
+ touchPoint.pressure = 1.0;
+ else if (state == Qt::TouchPointReleased)
+ touchPoint.pressure = 0.0;
+
+ // Set position
+ QRect viewGeometry = fromCGRect(self.frame);
+ QPoint touchViewLocation = fromCGPoint([touch locationInView:self]);
+ QPoint touchScreenLocation = touchViewLocation + viewGeometry.topLeft();
+ touchPoint.area = QRectF(touchScreenLocation , QSize(0, 0));
+
+ CGSize fullscreenSize = self.window.rootViewController.view.bounds.size;
+ touchPoint.normalPosition = QPointF(touchScreenLocation.x() / fullscreenSize.width, touchScreenLocation.y() / fullscreenSize.height);
+ }
+}
+
+- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
+{
+ // Send touch event synchronously
+ QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp,
+ iosIntegration->touchDevice(), m_qioswindow->touchPoints());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ QWindow *window = m_qioswindow->window();
+
+ // Transfer focus to the touched window:
+ if (window != QGuiApplication::focusWindow())
+ m_qioswindow->requestActivateWindow();
+
+ // Track Cocoa touch id to Qt touch id. The UITouch pointer is constant
+ // for the touch duration.
+ QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
+ QList<QWindowSystemInterface::TouchPoint> &touchPoints = m_qioswindow->touchPoints();
+ for (UITouch *touch in touches)
+ activeTouches.insert(touch, m_qioswindow->touchId()++);
+
+ // Create new touch points if needed.
+ int newTouchPointsNeeded = m_qioswindow->touchId() - touchPoints.count();
+ for (int i = 0; i < newTouchPointsNeeded; ++i) {
+ QWindowSystemInterface::TouchPoint touchPoint;
+ touchPoint.id = touchPoints.count(); // id is the index in the touchPoints list.
+ touchPoints.append(touchPoint);
+ }
+
+ [self updateTouchList:touches withState:Qt::TouchPointPressed];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointMoved];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointReleased];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+
+ // Remove ended touch points from the active set (event processing has completed at this point)
+ QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
+ for (UITouch *touch in touches) {
+ int id = activeTouches.take(touch);
+
+ // If this touch is the most recent touch we can reuse its id
+ if (id == m_qioswindow->touchId() - 1)
+ --m_qioswindow->touchId();
+ }
+
+ // Reset the touch id when there are no more active touches
+ if (activeTouches.isEmpty())
+ m_qioswindow->touchId() = 0;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ Q_UNUSED(touches) // ### can a subset of the active touches be cancelled?
+
+ // Clear current touch points
+ m_qioswindow->activeTouches().clear();
+ m_qioswindow->touchId() = 0;
+
+ // Send cancel touch event synchronously
+ QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(event.timestamp * 1000), iosIntegration->touchDevice());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+@synthesize autocapitalizationType;
+@synthesize autocorrectionType;
+@synthesize enablesReturnKeyAutomatically;
+@synthesize keyboardAppearance;
+@synthesize keyboardType;
+@synthesize returnKeyType;
+@synthesize secureTextEntry;
+
+- (BOOL)canBecomeFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)hasText
+{
+ return YES;
+}
+
+- (void)insertText:(NSString *)text
+{
+ QString string = QString::fromUtf8([text UTF8String]);
+ int key = 0;
+ if ([text isEqualToString:@"\n"])
+ key = (int)Qt::Key_Return;
+
+ // Send key event to window system interface
+ QWindowSystemInterface::handleKeyEvent(
+ 0, QEvent::KeyPress, key, Qt::NoModifier, string, false, int(string.length()));
+ QWindowSystemInterface::handleKeyEvent(
+ 0, QEvent::KeyRelease, key, Qt::NoModifier, string, false, int(string.length()));
+}
+
+- (void)deleteBackward
+{
+ // Send key event to window system interface
+ QWindowSystemInterface::handleKeyEvent(
+ 0, QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier);
+ QWindowSystemInterface::handleKeyEvent(
+ 0, QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
+}
+
+@end
+
+@implementation UIView (QIOS)
+
+- (QWindow *)qwindow
+{
+ if ([self isKindOfClass:[EAGLView class]])
+ return static_cast<EAGLView *>(self)->m_qioswindow->window();
+ return nil;
+}
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+QIOSWindow::QIOSWindow(QWindow *window)
+ : QPlatformWindow(window)
+ , m_view([[EAGLView alloc] initWithQIOSWindow:this])
+ , m_touchId(0)
+ , m_requestedGeometry(QPlatformWindow::geometry())
+ , m_windowLevel(0)
+ , m_devicePixelRatio(1.0)
+{
+ setParent(parent());
+ setWindowState(window->windowState());
+
+ // Retina support: get screen scale factor and set it in the content view.
+ // This will make framebufferObject() create a 2x frame buffer on retina
+ // displays. Also set m_devicePixelRatio which is used for scaling the
+ // paint device.
+ if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES) {
+ m_devicePixelRatio = [[UIScreen mainScreen] scale];
+ [m_view setContentScaleFactor: m_devicePixelRatio];
+ }
+}
+
+QIOSWindow::~QIOSWindow()
+{
+ [m_view removeFromSuperview];
+ [m_view release];
+}
+
+bool QIOSWindow::blockedByModal()
+{
+ QWindow *modalWindow = QGuiApplication::modalWindow();
+ return modalWindow && modalWindow != window();
+}
+
+void QIOSWindow::setVisible(bool visible)
+{
+ QPlatformWindow::setVisible(visible);
+ m_view.hidden = !visible;
+
+ if (!isQtApplication())
+ return;
+
+ // Since iOS doesn't do window management the way a Qt application
+ // expects, we need to raise and activate windows ourselves:
+ if (visible)
+ updateWindowLevel();
+
+ if (blockedByModal()) {
+ if (visible)
+ raise();
+ return;
+ }
+
+ if (visible) {
+ requestActivateWindow();
+ } else {
+ // Activate top-most visible QWindow:
+ NSArray *subviews = rootViewController().view.subviews;
+ for (int i = int(subviews.count) - 1; i >= 0; --i) {
+ UIView *view = [subviews objectAtIndex:i];
+ if (!view.hidden) {
+ if (QWindow *window = view.qwindow) {
+ static_cast<QIOSWindow *>(window->handle())->requestActivateWindow();
+ break;
+ }
+ }
+ }
+ }
+}
+
+void QIOSWindow::setGeometry(const QRect &rect)
+{
+ // If the window is in fullscreen, just bookkeep the requested
+ // geometry in case the window goes into Qt::WindowNoState later:
+ m_requestedGeometry = rect;
+ if (window()->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen))
+ return;
+
+ // Since we don't support transformations on the UIView, we can set the frame
+ // directly and let UIKit deal with translating that into bounds and center.
+ // Changing the size of the view will end up in a call to -[EAGLView layoutSubviews]
+ // which will update QWindowSystemInterface with the new size.
+ m_view.frame = toCGRect(rect);
+}
+
+void QIOSWindow::setWindowState(Qt::WindowState state)
+{
+ // FIXME: Figure out where or how we should disable/enable the statusbar.
+ // Perhaps setting QWindow to maximized should also mean that we'll show
+ // the statusbar, and vice versa for fullscreen?
+
+ switch (state) {
+ case Qt::WindowMaximized:
+ case Qt::WindowFullScreen: {
+ // Since UIScreen does not take orientation into account when
+ // reporting geometry, we need to look at the top view instead:
+ CGSize fullscreenSize = m_view.window.rootViewController.view.bounds.size;
+ m_view.frame = CGRectMake(0, 0, fullscreenSize.width, fullscreenSize.height);
+ m_view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ break; }
+ default:
+ m_view.frame = toCGRect(m_requestedGeometry);
+ m_view.autoresizingMask = UIViewAutoresizingNone;
+ break;
+ }
+}
+
+void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
+{
+ if (parentWindow) {
+ UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId());
+ [parentView addSubview:m_view];
+ } else if (isQtApplication()) {
+ [rootViewController().view addSubview:m_view];
+ }
+}
+
+void QIOSWindow::requestActivateWindow()
+{
+ // Note that several windows can be active at the same time if they exist in the same
+ // hierarchy (transient children). But only one window can be QGuiApplication::focusWindow().
+ // Dispite the name, 'requestActivateWindow' means raise and transfer focus to the window:
+ if (blockedByModal())
+ return;
+
+ raise();
+ QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ static_cast<QIOSInputContext *>(context)->focusViewChanged(m_view);
+ QPlatformWindow::requestActivateWindow();
+}
+
+void QIOSWindow::raiseOrLower(bool raise)
+{
+ // Re-insert m_view at the correct index among its sibling views
+ // (QWindows) according to their current m_windowLevel:
+ if (!isQtApplication())
+ return;
+
+ NSArray *subviews = m_view.superview.subviews;
+ if (subviews.count == 1)
+ return;
+
+ for (int i = int(subviews.count) - 1; i >= 0; --i) {
+ UIView *view = static_cast<UIView *>([subviews objectAtIndex:i]);
+ if (view.hidden || view == m_view)
+ continue;
+ int level = static_cast<QIOSWindow *>(view.qwindow->handle())->m_windowLevel;
+ if (m_windowLevel > level || (raise && m_windowLevel == level)) {
+ [m_view.superview insertSubview:m_view aboveSubview:view];
+ return;
+ }
+ }
+ [m_view.superview insertSubview:m_view atIndex:0];
+}
+
+void QIOSWindow::updateWindowLevel()
+{
+ Qt::WindowType type = static_cast<Qt::WindowType>(int(window()->flags() & Qt::WindowType_Mask));
+
+ if (type == Qt::ToolTip)
+ m_windowLevel = 120;
+ else if (window()->flags() & Qt::WindowStaysOnTopHint)
+ m_windowLevel = 100;
+ else if (window()->isModal())
+ m_windowLevel = 30;
+ else if (type & Qt::Popup & ~Qt::Window)
+ m_windowLevel = 20;
+ else if (type == Qt::Tool)
+ m_windowLevel = 10;
+ else
+ m_windowLevel = 0;
+
+ // A window should be in at least the same m_windowLevel as its parent:
+ QWindow *transientParent = window()->transientParent();
+ QIOSWindow *transientParentWindow = transientParent ? static_cast<QIOSWindow *>(transientParent->handle()) : 0;
+ if (transientParentWindow)
+ m_windowLevel = qMax(transientParentWindow->m_windowLevel, m_windowLevel);
+}
+
+void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
+{
+ // Keep the status bar in sync with content orientation. This will ensure
+ // that the task bar (and associated gestures) are aligned correctly:
+ UIDeviceOrientation uiOrientation = fromQtScreenOrientation(orientation);
+ [[UIApplication sharedApplication] setStatusBarOrientation:uiOrientation animated:NO];
+}
+
+qreal QIOSWindow::devicePixelRatio() const
+{
+ return m_devicePixelRatio;
+}
+
+int QIOSWindow::effectiveWidth() const
+{
+ return geometry().width() * m_devicePixelRatio;
+}
+
+int QIOSWindow::effectiveHeight() const
+{
+ return geometry().height() * m_devicePixelRatio;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qtmain.mm b/src/plugins/platforms/ios/qtmain.mm
new file mode 100644
index 0000000000..10c83f4b18
--- /dev/null
+++ b/src/plugins/platforms/ios/qtmain.mm
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosapplicationdelegate.h"
+#include "qiosviewcontroller.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSMainWrapperApplicationDelegate class]));
+ }
+}
+
+extern int qt_main(int argc, char *argv[]);
+
+@implementation QIOSMainWrapperApplicationDelegate
+
+- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease];
+
+#ifdef QT_DEBUG
+ self.window.backgroundColor = [UIColor cyanColor];
+#endif
+
+ [self.window makeKeyAndVisible];
+
+ // We schedule the main-redirection for the next eventloop pass so that we
+ // can return from this function and let UIApplicationMain finish its job.
+ [NSTimer scheduledTimerWithTimeInterval:.01f target:self
+ selector:@selector(runUserMain) userInfo:nil repeats:NO];
+
+ if ([QIOSApplicationDelegate instancesRespondToSelector:_cmd])
+ return [super application:application willFinishLaunchingWithOptions:launchOptions];
+ else
+ return YES;
+}
+
+- (void)runUserMain
+{
+ NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ int argc = arguments.count;
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc; ++i) {
+ NSString *arg = [arguments objectAtIndex:i];
+ argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
+ strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+
+ qt_main(argc, argv);
+ delete[] argv;
+}
+
+@end
diff --git a/src/plugins/platforms/ios/qtmain.pro b/src/plugins/platforms/ios/qtmain.pro
new file mode 100644
index 0000000000..cbcb272217
--- /dev/null
+++ b/src/plugins/platforms/ios/qtmain.pro
@@ -0,0 +1,8 @@
+TARGET = qiosmain
+
+PLUGIN_TYPE = platforms
+load(qt_plugin)
+
+QT += gui-private
+
+OBJECTIVE_SOURCES = qtmain.mm
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 173757568f..a60a3626fa 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -6,7 +6,10 @@ contains(QT_CONFIG, xcb) {
SUBDIRS += xcb
}
-mac:!ios: SUBDIRS += cocoa
+mac {
+ ios: SUBDIRS += ios
+ else: SUBDIRS += cocoa
+}
win32: SUBDIRS += windows
diff --git a/src/printsupport/dialogs/dialogs.pri b/src/printsupport/dialogs/dialogs.pri
index 9db975e202..9659046f60 100644
--- a/src/printsupport/dialogs/dialogs.pri
+++ b/src/printsupport/dialogs/dialogs.pri
@@ -8,7 +8,7 @@ HEADERS += \
dialogs/qprintdialog.h \
dialogs/qprintpreviewdialog.h
-mac {
+mac:!ios {
OBJECTIVE_SOURCES += dialogs/qpagesetupdialog_mac.mm \
dialogs/qprintdialog_mac.mm
LIBS += -framework Cocoa
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index f9f21c6a8f..ef8ffa570b 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -82,7 +82,7 @@
#include <time.h>
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
#include <IOKit/pwr_mgt/IOPMLib.h>
#endif
@@ -2078,7 +2078,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
int callgrindChildExitCode = 0;
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
IOPMAssertionID powerID;
#endif
@@ -2093,7 +2093,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
CFStringRef reasonForActivity= CFSTR("No Display Sleep");
IOReturn ok = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &powerID);
@@ -2146,7 +2146,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
QTestLog::stopLogging();
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
IOPMAssertionRelease(powerID);
}
@@ -2163,7 +2163,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
QSignalDumper::endDump();
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
IOPMAssertionRelease(powerID);
}
diff --git a/src/widgets/kernel/mac.pri b/src/widgets/kernel/mac.pri
index 5474a41f15..4c507ae80e 100644
--- a/src/widgets/kernel/mac.pri
+++ b/src/widgets/kernel/mac.pri
@@ -1,4 +1,4 @@
-!x11::mac {
+!x11:mac:!ios {
LIBS_PRIVATE += -framework Carbon -framework Cocoa -lz
*-mwerks:INCLUDEPATH += compat
}
diff --git a/src/widgets/styles/qfusionstyle_p_p.h b/src/widgets/styles/qfusionstyle_p_p.h
index d3f2ff5f40..58595fe889 100644
--- a/src/widgets/styles/qfusionstyle_p_p.h
+++ b/src/widgets/styles/qfusionstyle_p_p.h
@@ -88,9 +88,9 @@ public:
// On mac we want a standard blue color used when the system palette is used
bool isMacSystemPalette(const QPalette &pal) const {
Q_UNUSED(pal);
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette();
- if (themePalette->color(QPalette::Normal, QPalette::Highlight) ==
+ if (themePalette && themePalette->color(QPalette::Normal, QPalette::Highlight) ==
pal.color(QPalette::Normal, QPalette::Highlight) &&
themePalette->color(QPalette::Normal, QPalette::HighlightedText) ==
pal.color(QPalette::Normal, QPalette::HighlightedText))
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 01e51d594d..eff6837c5a 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -206,7 +206,7 @@ void QStyleOption::init(const QWidget *widget)
if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget))
state &= ~QStyle::State_Enabled;
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
switch (QMacStyle::widgetSizePolicy(widget)) {
case QMacStyle::SizeSmall:
state |= QStyle::State_Small;