Merge "Merge branch 'ios' into dev" into refs/staging/dev

This commit is contained in:
Tor Arne Vestbø 2013-02-28 18:31:11 +01:00 committed by The Qt Project
commit 0520631b2b
94 changed files with 4129 additions and 1643 deletions

9
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 =
}

View File

@ -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
QMAKE_IOS_CXXFLAGS += -fvisibility-inlines-hidden
QMAKE_IOS_OBJ_CFLAGS += -Wno-arc-abi
# Device or simulator specific flags
*simulator* {
QMAKE_IOS_CFLAGS += -fexceptions -fasm-blocks
QMAKE_IOS_OBJ_CFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
}
# 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
# 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
# But these only apply to non-ARM targets
!contains(QT_ARCH, arm): QMAKE_IOS_CFLAGS += -fexceptions -fasm-blocks
# 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}")
}
}
# 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

View File

@ -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 =

View File

@ -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 =

View File

@ -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
#
# QMAKE_XCODE_DEVELOPER_PATH - set in mkspecs/common/xcode.conf
# iOS SDK device type
!*simulator*: QMAKE_IOS_DEVICE_TYPE = iPhoneOS
else {
QMAKE_IOS_DEVICE_TYPE = iPhoneSimulator
QT_QPA_DEFAULT_PLATFORM = ios
# Use simulator SDK version
QMAKE_IOS_SDK_VERSION = $$QMAKE_IOS_SIMULATOR_SDK_VERSION
QMAKE_IOS_SIMULATOR_SDK_VERSION =
}
QMAKE_XCODE_TOOLCHAIN_BIN_PATH = $$QMAKE_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/bin
!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_CODE_SIGN_IDENTITY = "iPhone Developer"
# iOS platform /Developer path
QMAKE_IOS_DEV_PATH = $$QMAKE_IOS_XCODE_PATH/Developer/Platforms/$${QMAKE_IOS_DEVICE_TYPE}.platform/Developer
QMAKE_IOS_XCODE_PATH =
# 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
# 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 =
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
}

View File

@ -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 =

View File

@ -42,8 +42,6 @@
#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H
#define QT_QPA_DEFAULT_PLATFORM_NAME "cocoa"
// Get Qt defines/settings
#include "qglobal.h"

13
mkspecs/common/xcode.conf Normal file
View File

@ -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.")

View File

@ -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.")
}

25
mkspecs/features/ios.prf Normal file
View File

@ -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
}

View File

@ -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)

View File

@ -0,0 +1,4 @@
# Unset makefile generator, so we can auto-detect value in default_post
unset(MAKEFILE_GENERATOR)
load(default_pre)

View File

@ -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

View File

@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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;
}
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"
<< "\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("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\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"
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");
}
}
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("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\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n"
<< "\t\t" << "};" << "\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";
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";
else
t << "\t\t\t" << writeSettings("productType", "com.apple.product-type.tool") << ";" << "\n";
} else {
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.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";
}
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

View File

@ -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))) {

View File

@ -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))

View File

@ -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

View File

@ -63,6 +63,8 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#include "qglobal.h"
#ifndef Q_OS_IOS
#include <CoreServices/CoreServices.h>
#endif

View File

@ -18,9 +18,7 @@ testcocoon {
load(testcocoon)
}
mac {
LIBS_PRIVATE += -framework Cocoa
}
mac:!ios: LIBS_PRIVATE += -framework Cocoa
CONFIG += simd

View File

@ -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)
{
@ -248,6 +250,14 @@ void QOpenGLPaintDevice::setSize(const QSize &size)
d_ptr->size = 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;

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1,4 @@
mac {
HEADERS += $$PWD/qcfsocketnotifier_p.h
SOURCES += $$PWD/qcfsocketnotifier.cpp
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -39,6 +39,8 @@
**
****************************************************************************/
#include "qglobal.h"
#ifndef Q_OS_IOS
#import <Cocoa/Cocoa.h>
#import <IOKit/graphics/IOGraphicsLib.h>

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -0,0 +1,3 @@
{
"Keys": [ "ios" ]
}

View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS += plugin.pro qtmain.pro

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,35 @@
**
****************************************************************************/
#include "../../common/ios/qplatformdefs.h"
#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

View File

@ -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];
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,8 @@
TARGET = qiosmain
PLUGIN_TYPE = platforms
load(qt_plugin)
QT += gui-private
OBJECTIVE_SOURCES = qtmain.mm

View File

@ -6,7 +6,10 @@ contains(QT_CONFIG, xcb) {
SUBDIRS += xcb
}
mac:!ios: SUBDIRS += cocoa
mac {
ios: SUBDIRS += ios
else: SUBDIRS += cocoa
}
win32: SUBDIRS += windows

View File

@ -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

View File

@ -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);
}

View File

@ -1,4 +1,4 @@
!x11::mac {
!x11:mac:!ios {
LIBS_PRIVATE += -framework Carbon -framework Cocoa -lz
*-mwerks:INCLUDEPATH += compat
}

View File

@ -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))

View File

@ -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;