From 730c5b3b96715c2bca0af6971bf6f66feffc49a3 Mon Sep 17 00:00:00 2001 From: kleuter Date: Wed, 18 Nov 2020 11:25:51 +0100 Subject: [PATCH] 5.13.2: original files to be modified by backport big sur detection (https://github.com/qt/qtbase/commit/25e0e6273d9e9ba20147aa3c7479830fd12a254d) --- .../global/qoperatingsystemversion.cpp | 544 ++++++++++++++++ .../corelib/global/qoperatingsystemversion.h | 159 +++++ .../src/corelib/global/qsystemdetection.h | 282 +++++++++ .../qtbase/src/corelib/kernel/qcore_mac.cpp | 162 +++++ .../qtbase/src/corelib/kernel/qcore_mac_p.h | 402 ++++++++++++ .../plugins/platforms/cocoa/qcocoahelpers.h | 378 +++++++++++ .../plugins/platforms/cocoa/qcocoahelpers.mm | 599 ++++++++++++++++++ 7 files changed, 2526 insertions(+) create mode 100644 5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp create mode 100644 5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h create mode 100644 5.13.2/qtbase/src/corelib/global/qsystemdetection.h create mode 100644 5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp create mode 100644 5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h create mode 100644 5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h create mode 100644 5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp new file mode 100644 index 0000000..bc6adb5 --- /dev/null +++ b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp @@ -0,0 +1,544 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion.h" +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +#include "qoperatingsystemversion_p.h" +#endif + +#include +#include + +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#include +#endif + +QT_BEGIN_NAMESPACE + +/*! + \class QOperatingSystemVersion + \inmodule QtCore + \since 5.9 + \brief The QOperatingSystemVersion class provides information about the + operating system version. + + Unlike other version functions in QSysInfo, QOperatingSystemVersion provides + access to the full version number that \a developers typically use to vary + behavior or determine whether to enable APIs or features based on the + operating system version (as opposed to the kernel version number or + marketing version). + + This class is also a complete replacement for QSysInfo::macVersion and + QSysInfo::windowsVersion, additionally providing access to the third (micro) + version number component. + + Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS), + and Windows are supported. + + The \a majorVersion(), \a minorVersion(), and \a microVersion() functions + return the parts of the operating system version number based on: + + \table + \header + \li Platforms + \li Value + \row + \li Android + \li result of parsing + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{android.os.Build.VERSION.RELEASE} + using QVersionNumber, with a fallback to + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{android.os.Build.VERSION.SDK_INT} + to determine the major and minor version component if the former + fails + \row + \li Apple Platforms + \li majorVersion, minorVersion, and patchVersion from + \l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{NSProcessInfo.operatingSystemVersion} + \row + \li Windows + \li dwMajorVersion, dwMinorVersion, and dwBuildNumber from + \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{RtlGetVersion} - + note that this function ALWAYS return the version number of the + underlying operating system, as opposed to the shim underneath + GetVersionEx that hides the real version number if the + application is not manifested for that version of the OS + \endtable + + Because QOperatingSystemVersion stores both a version number and an OS type, the OS type + can be taken into account when performing comparisons. For example, on a macOS system running + macOS Sierra (v10.12), the following expression will return \c false even though the + major version number component of the object on the left hand side of the expression (10) is + greater than that of the object on the right (9): + + \snippet code/src_corelib_global_qoperatingsystemversion.cpp 0 + + This allows expressions for multiple operating systems to be joined with a logical OR operator + and still work as expected. For example: + + \snippet code/src_corelib_global_qoperatingsystemversion.cpp 1 + + A more naive comparison algorithm might incorrectly return true on all versions of macOS, + including Mac OS 9. This behavior is achieved by overloading the comparison operators to return + \c false whenever the OS types of the QOperatingSystemVersion instances being compared do not + match. Be aware that due to this it can be the case \c x >= y and \c x < y are BOTH \c false + for the same instances of \c x and \c y. +*/ + +/*! + \enum QOperatingSystemVersion::OSType + + This enum provides symbolic names for the various operating + system families supported by QOperatingSystemVersion. + + \value Android The Google Android operating system. + \value IOS The Apple iOS operating system. + \value MacOS The Apple macOS operating system. + \value TvOS The Apple tvOS operating system. + \value WatchOS The Apple watchOS operating system. + \value Windows The Microsoft Windows operating system. + + \value Unknown An unknown or unsupported operating system. +*/ + +/*! + \fn QOperatingSystemVersion::QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1) + + Constructs a QOperatingSystemVersion consisting of the OS type \a osType, and + major, minor, and micro version numbers \a vmajor, \a vminor and \a vmicro, respectively. +*/ + +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::current() + + Returns a QOperatingSystemVersion indicating the current OS and its version number. + + \sa currentType() +*/ +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion version; + version.m_os = currentType(); +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifndef QT_BOOTSTRAPPED + const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField( + "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString()); + if (!v.isNull()) { + version.m_major = v.majorVersion(); + version.m_minor = v.minorVersion(); + version.m_micro = v.microVersion(); + return version; + } +#endif + + version.m_major = -1; + version.m_minor = -1; + + static const struct { + uint major : 4; + uint minor : 4; + } versions[] = { + { 1, 0 }, // API level 1 + { 1, 1 }, // API level 2 + { 1, 5 }, // API level 3 + { 1, 6 }, // API level 4 + { 2, 0 }, // API level 5 + { 2, 0 }, // API level 6 + { 2, 1 }, // API level 7 + { 2, 2 }, // API level 8 + { 2, 3 }, // API level 9 + { 2, 3 }, // API level 10 + { 3, 0 }, // API level 11 + { 3, 1 }, // API level 12 + { 3, 2 }, // API level 13 + { 4, 0 }, // API level 14 + { 4, 0 }, // API level 15 + { 4, 1 }, // API level 16 + { 4, 2 }, // API level 17 + { 4, 3 }, // API level 18 + { 4, 4 }, // API level 19 + { 4, 4 }, // API level 20 + { 5, 0 }, // API level 21 + { 5, 1 }, // API level 22 + { 6, 0 }, // API level 23 + { 7, 0 }, // API level 24 + { 7, 1 }, // API level 25 + { 8, 0 }, // API level 26 + }; + + // This will give us at least the first 2 version components + const size_t versionIdx = size_t(QJNIObjectPrivate::getStaticField( + "android/os/Build$VERSION", "SDK_INT")) - 1; + if (versionIdx < sizeof(versions) / sizeof(versions[0])) { + version.m_major = versions[versionIdx].major; + version.m_minor = versions[versionIdx].minor; + } + + // API level 6 was exactly version 2.0.1 + version.m_micro = versionIdx == 5 ? 1 : -1; +#else + version.m_major = -1; + version.m_minor = -1; + version.m_micro = -1; +#endif + return version; +} +#endif + +static inline int compareVersionComponents(int lhs, int rhs) +{ + return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0; +} + +int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, + const QOperatingSystemVersion &v2) +{ + if (v1.m_major == v2.m_major) { + if (v1.m_minor == v2.m_minor) { + return compareVersionComponents(v1.m_micro, v2.m_micro); + } + return compareVersionComponents(v1.m_minor, v2.m_minor); + } + return compareVersionComponents(v1.m_major, v2.m_major); +} + +/*! + \fn int QOperatingSystemVersion::majorVersion() const + + Returns the major version number, that is, the first segment of the + operating system's version number. + + See the main class documentation for what the major version number is on a given + operating system. + + -1 indicates an unknown or absent version number component. + + \sa minorVersion(), microVersion() +*/ + +/*! + \fn int QOperatingSystemVersion::minorVersion() const + + Returns the minor version number, that is, the second segment of the + operating system's version number. + + See the main class documentation for what the minor version number is on a given + operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), microVersion() +*/ + +/*! + \fn int QOperatingSystemVersion::microVersion() const + + Returns the micro version number, that is, the third segment of the + operating system's version number. + + See the main class documentation for what the micro version number is on a given + operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), minorVersion() +*/ + +/*! + \fn int QOperatingSystemVersion::segmentCount() const + + Returns the number of integers stored in the version number. +*/ + +/*! + \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const + + Returns the OS type identified by the QOperatingSystemVersion. + + \sa name() +*/ + +/*! + \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::currentType() + + Returns the current OS type without constructing a QOperatingSystemVersion instance. + + \sa current() +*/ + +/*! + \fn QString QOperatingSystemVersion::name() const + + Returns a string representation of the OS type identified by the QOperatingSystemVersion. + + \sa type() +*/ +QString QOperatingSystemVersion::name() const +{ + switch (type()) { + case QOperatingSystemVersion::Windows: + return QStringLiteral("Windows"); + case QOperatingSystemVersion::MacOS: { + if (majorVersion() < 10) + return QStringLiteral("Mac OS"); + if (majorVersion() == 10 && minorVersion() < 8) + return QStringLiteral("Mac OS X"); + if (majorVersion() == 10 && minorVersion() < 12) + return QStringLiteral("OS X"); + return QStringLiteral("macOS"); + } + case QOperatingSystemVersion::IOS: { + if (majorVersion() < 4) + return QStringLiteral("iPhone OS"); + return QStringLiteral("iOS"); + } + case QOperatingSystemVersion::TvOS: + return QStringLiteral("tvOS"); + case QOperatingSystemVersion::WatchOS: + return QStringLiteral("watchOS"); + case QOperatingSystemVersion::Android: + return QStringLiteral("Android"); + case QOperatingSystemVersion::Unknown: + default: + return QString(); + } +} + +#ifdef Q_COMPILER_INITIALIZER_LISTS +/*! + \fn bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) const + + Returns whether the OS type identified by the QOperatingSystemVersion + matches any of the OS types in \a types. +*/ +bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) const +{ + for (const auto &t : qAsConst(types)) { + if (type() == t) + return true; + } + return false; +} +#endif + +/*! + \variable QOperatingSystemVersion::Windows7 + \brief a version corresponding to Windows 7 (version 6.1). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows7 = + QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1); + +/*! + \variable QOperatingSystemVersion::Windows8 + \brief a version corresponding to Windows 8 (version 6.2). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8 = + QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2); + +/*! + \variable QOperatingSystemVersion::Windows8_1 + \brief a version corresponding to Windows 8.1 (version 6.3). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 = + QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3); + +/*! + \variable QOperatingSystemVersion::Windows10 + \brief a version corresponding to Windows 10 (version 10.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows10 = + QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10); + +/*! + \variable QOperatingSystemVersion::OSXMavericks + \brief a version corresponding to OS X Mavericks (version 10.9). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9); + +/*! + \variable QOperatingSystemVersion::OSXYosemite + \brief a version corresponding to OS X Yosemite (version 10.10). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10); + +/*! + \variable QOperatingSystemVersion::OSXElCapitan + \brief a version corresponding to OS X El Capitan (version 10.11). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11); + +/*! + \variable QOperatingSystemVersion::MacOSSierra + \brief a version corresponding to macOS Sierra (version 10.12). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12); + +/*! + \variable QOperatingSystemVersion::MacOSHighSierra + \brief a version corresponding to macOS High Sierra (version 10.13). + \since 5.9.1 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSHighSierra = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 13); + +/*! + \variable QOperatingSystemVersion::MacOSMojave + \brief a version corresponding to macOS Mojave (version 10.14). + \since 5.11.2 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSMojave = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 14); + +/*! + \variable QOperatingSystemVersion::MacOSCatalina + \brief a version corresponding to macOS Catalina (version 10.15). + \since 5.12.5 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSCatalina = + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 15); + +/*! + \variable QOperatingSystemVersion::AndroidJellyBean + \brief a version corresponding to Android Jelly Bean (version 4.1, API level 16). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1); + +/*! + \variable QOperatingSystemVersion::AndroidJellyBean_MR1 + \brief a version corresponding to Android Jelly Bean, maintenance release 1 + (version 4.2, API level 17). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR1 = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 2); + +/*! + \variable QOperatingSystemVersion::AndroidJellyBean_MR2 + \brief a version corresponding to Android Jelly Bean, maintenance release 2 + (version 4.3, API level 18). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR2 = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 3); + +/*! + \variable QOperatingSystemVersion::AndroidKitKat + \brief a version corresponding to Android KitKat (versions 4.4 & 4.4W, API levels 19 & 20). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4); + +/*! + \variable QOperatingSystemVersion::AndroidLollipop + \brief a version corresponding to Android Lollipop (version 5.0, API level 21). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0); + +/*! + \variable QOperatingSystemVersion::AndroidLollipop_MR1 + \brief a version corresponding to Android Lollipop, maintenance release 1 + (version 5.1, API level 22). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop_MR1 = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 1); + +/*! + \variable QOperatingSystemVersion::AndroidMarshmallow + \brief a version corresponding to Android Marshmallow (version 6.0, API level 23). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 6, 0); + +/*! + \variable QOperatingSystemVersion::AndroidNougat + \brief a version corresponding to Android Nougat (version 7.0, API level 24). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 0); + +/*! + \variable QOperatingSystemVersion::AndroidNougat_MR1 + \brief a version corresponding to Android Nougat, maintenance release 1 + (version 7.0, API level 25). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 1); + +/*! + \variable QOperatingSystemVersion::AndroidOreo + \brief a version corresponding to Android Oreo (version 8.0, API level 26). + \since 5.9.2 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo = + QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0); + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QOperatingSystemVersion(" << ov.name() + << ", " << ov.majorVersion() << '.' << ov.minorVersion() + << '.' << ov.microVersion() << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + +QT_END_NAMESPACE diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h new file mode 100644 index 0000000..89c60c4 --- /dev/null +++ b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QOPERATINGSYSTEMVERSION_H +#define QOPERATINGSYSTEMVERSION_H + +QT_BEGIN_NAMESPACE + +class QString; +class QVersionNumber; + +class Q_CORE_EXPORT QOperatingSystemVersion +{ +public: + enum OSType { + Unknown = 0, + Windows, + MacOS, + IOS, + TvOS, + WatchOS, + Android + }; + + static const QOperatingSystemVersion Windows7; + static const QOperatingSystemVersion Windows8; + static const QOperatingSystemVersion Windows8_1; + static const QOperatingSystemVersion Windows10; + + static const QOperatingSystemVersion OSXMavericks; + static const QOperatingSystemVersion OSXYosemite; + static const QOperatingSystemVersion OSXElCapitan; + static const QOperatingSystemVersion MacOSSierra; + static const QOperatingSystemVersion MacOSHighSierra; + static const QOperatingSystemVersion MacOSMojave; + static const QOperatingSystemVersion MacOSCatalina; + + static const QOperatingSystemVersion AndroidJellyBean; + static const QOperatingSystemVersion AndroidJellyBean_MR1; + static const QOperatingSystemVersion AndroidJellyBean_MR2; + static const QOperatingSystemVersion AndroidKitKat; + static const QOperatingSystemVersion AndroidLollipop; + static const QOperatingSystemVersion AndroidLollipop_MR1; + static const QOperatingSystemVersion AndroidMarshmallow; + static const QOperatingSystemVersion AndroidNougat; + static const QOperatingSystemVersion AndroidNougat_MR1; + static const QOperatingSystemVersion AndroidOreo; + + Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType, + int vmajor, int vminor = -1, int vmicro = -1) + : m_os(osType), + m_major(qMax(-1, vmajor)), + m_minor(vmajor < 0 ? -1 : qMax(-1, vminor)), + m_micro(vmajor < 0 || vminor < 0 ? -1 : qMax(-1, vmicro)) + { } + + static QOperatingSystemVersion current(); + + static Q_DECL_CONSTEXPR OSType currentType() + { +#if defined(Q_OS_WIN) + return Windows; +#elif defined(Q_OS_MACOS) + return MacOS; +#elif defined(Q_OS_IOS) + return IOS; +#elif defined(Q_OS_TVOS) + return TvOS; +#elif defined(Q_OS_WATCHOS) + return WatchOS; +#elif defined(Q_OS_ANDROID) + return Android; +#else + return Unknown; +#endif + } + + Q_DECL_CONSTEXPR int majorVersion() const { return m_major; } + Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; } + Q_DECL_CONSTEXPR int microVersion() const { return m_micro; } + + Q_DECL_CONSTEXPR int segmentCount() const + { return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; } + +#ifdef Q_COMPILER_INITIALIZER_LISTS + bool isAnyOfType(std::initializer_list types) const; +#endif + Q_DECL_CONSTEXPR OSType type() const { return m_os; } + QString name() const; + + friend bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) + { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; } + + friend bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) + { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; } + + friend bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) + { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; } + + friend bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) + { return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; } + +private: + QOperatingSystemVersion() = default; + OSType m_os; + int m_major; + int m_minor; + int m_micro; + + static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2); +}; +Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE); + +#ifndef QT_NO_DEBUG_STREAM +class QDebug; +Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov); +#endif + +QT_END_NAMESPACE + +#endif // QOPERATINGSYSTEMVERSION_H diff --git a/5.13.2/qtbase/src/corelib/global/qsystemdetection.h b/5.13.2/qtbase/src/corelib/global/qsystemdetection.h new file mode 100644 index 0000000..3e38e67 --- /dev/null +++ b/5.13.2/qtbase/src/corelib/global/qsystemdetection.h @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLOBAL_H +# include +#endif + +#ifndef QSYSTEMDETECTION_H +#define QSYSTEMDETECTION_H + +/* + The operating system, must be one of: (Q_OS_x) + + DARWIN - Any Darwin system (macOS, iOS, watchOS, tvOS) + MACOS - macOS + IOS - iOS + WATCHOS - watchOS + TVOS - tvOS + WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008) + WINRT - WinRT (Windows Runtime) + CYGWIN - Cygwin + SOLARIS - Sun Solaris + HPUX - HP-UX + LINUX - Linux [has variants] + FREEBSD - FreeBSD [has variants] + NETBSD - NetBSD + OPENBSD - OpenBSD + INTERIX - Interix + AIX - AIX + HURD - GNU Hurd + QNX - QNX [has variants] + QNX6 - QNX RTP 6.1 + LYNX - LynxOS + BSD4 - Any BSD 4.4 system + UNIX - Any UNIX BSD/SYSV system + ANDROID - Android platform + HAIKU - Haiku + + The following operating systems have variants: + LINUX - both Q_OS_LINUX and Q_OS_ANDROID are defined when building for Android + - only Q_OS_LINUX is defined if building for other Linux systems + FREEBSD - Q_OS_FREEBSD is defined only when building for FreeBSD with a BSD userland + - Q_OS_FREEBSD_KERNEL is always defined on FreeBSD, even if the userland is from GNU +*/ + +#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__)) +# include +# if defined(TARGET_OS_MAC) && TARGET_OS_MAC +# define Q_OS_DARWIN +# define Q_OS_BSD4 +# ifdef __LP64__ +# define Q_OS_DARWIN64 +# else +# define Q_OS_DARWIN32 +# endif +# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +# define QT_PLATFORM_UIKIT +# if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH +# define Q_OS_WATCHOS +# elif defined(TARGET_OS_TV) && TARGET_OS_TV +# define Q_OS_TVOS +# else +# // TARGET_OS_IOS is only available in newer SDKs, +# // so assume any other iOS-based platform is iOS for now +# define Q_OS_IOS +# endif +# else +# // TARGET_OS_OSX is only available in newer SDKs, +# // so assume any non iOS-based platform is macOS for now +# define Q_OS_MACOS +# endif +# else +# error "Qt has not been ported to this Apple platform - see http://www.qt.io/developers" +# endif +#elif defined(__ANDROID__) || defined(ANDROID) +# define Q_OS_ANDROID +# define Q_OS_LINUX +#elif defined(__CYGWIN__) +# define Q_OS_CYGWIN +#elif !defined(SAG_COM) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) +# define Q_OS_WIN32 +# define Q_OS_WIN64 +#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) +# if defined(WINAPI_FAMILY) +# ifndef WINAPI_FAMILY_PC_APP +# define WINAPI_FAMILY_PC_APP WINAPI_FAMILY_APP +# endif +# if defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +# define Q_OS_WINRT +# elif WINAPI_FAMILY==WINAPI_FAMILY_PC_APP +# define Q_OS_WINRT +# else +# define Q_OS_WIN32 +# endif +# else +# define Q_OS_WIN32 +# endif +#elif defined(__sun) || defined(sun) +# define Q_OS_SOLARIS +#elif defined(hpux) || defined(__hpux) +# define Q_OS_HPUX +#elif defined(__native_client__) +# define Q_OS_NACL +#elif defined(__EMSCRIPTEN__) +# define Q_OS_WASM +#elif defined(__linux__) || defined(__linux) +# define Q_OS_LINUX +#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) +# ifndef __FreeBSD_kernel__ +# define Q_OS_FREEBSD +# endif +# define Q_OS_FREEBSD_KERNEL +# define Q_OS_BSD4 +#elif defined(__NetBSD__) +# define Q_OS_NETBSD +# define Q_OS_BSD4 +#elif defined(__OpenBSD__) +# define Q_OS_OPENBSD +# define Q_OS_BSD4 +#elif defined(__INTERIX) +# define Q_OS_INTERIX +# define Q_OS_BSD4 +#elif defined(_AIX) +# define Q_OS_AIX +#elif defined(__Lynx__) +# define Q_OS_LYNX +#elif defined(__GNU__) +# define Q_OS_HURD +#elif defined(__QNXNTO__) +# define Q_OS_QNX +#elif defined(__INTEGRITY) +# define Q_OS_INTEGRITY +#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */ +# define Q_OS_VXWORKS +#elif defined(__HAIKU__) +# define Q_OS_HAIKU +#elif defined(__MAKEDEPEND__) +#else +# error "Qt has not been ported to this OS - see http://www.qt-project.org/" +#endif + +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT) +# define Q_OS_WINDOWS +# define Q_OS_WIN +#endif + +#if defined(Q_OS_WIN) +# undef Q_OS_UNIX +#elif !defined(Q_OS_UNIX) +# define Q_OS_UNIX +#endif + +// Compatibility synonyms +#ifdef Q_OS_DARWIN +#define Q_OS_MAC +#endif +#ifdef Q_OS_DARWIN32 +#define Q_OS_MAC32 +#endif +#ifdef Q_OS_DARWIN64 +#define Q_OS_MAC64 +#endif +#ifdef Q_OS_MACOS +#define Q_OS_MACX +#define Q_OS_OSX +#endif + +#ifdef Q_OS_DARWIN +# include +# include +# +# ifdef Q_OS_MACOS +# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6 +# undef __MAC_OS_X_VERSION_MIN_REQUIRED +# define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6 +# endif +# if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +# undef MAC_OS_X_VERSION_MIN_REQUIRED +# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6 +# endif +# endif +# +# // Numerical checks are preferred to named checks, but to be safe +# // we define the missing version names in case Qt uses them. +# +# if !defined(__MAC_10_11) +# define __MAC_10_11 101100 +# endif +# if !defined(__MAC_10_12) +# define __MAC_10_12 101200 +# endif +# if !defined(__MAC_10_13) +# define __MAC_10_13 101300 +# endif +# if !defined(__MAC_10_14) +# define __MAC_10_14 101400 +# endif +# if !defined(__MAC_10_15) +# define __MAC_10_15 101500 +# endif +# if !defined(MAC_OS_X_VERSION_10_11) +# define MAC_OS_X_VERSION_10_11 __MAC_10_11 +# endif +# if !defined(MAC_OS_X_VERSION_10_12) +# define MAC_OS_X_VERSION_10_12 __MAC_10_12 +# endif +# if !defined(MAC_OS_X_VERSION_10_13) +# define MAC_OS_X_VERSION_10_13 __MAC_10_13 +# endif +# if !defined(MAC_OS_X_VERSION_10_14) +# define MAC_OS_X_VERSION_10_14 __MAC_10_14 +# endif +# if !defined(MAC_OS_X_VERSION_10_15) +# define MAC_OS_X_VERSION_10_15 __MAC_10_15 +# endif +# +# if !defined(__IPHONE_10_0) +# define __IPHONE_10_0 100000 +# endif +# if !defined(__IPHONE_10_1) +# define __IPHONE_10_1 100100 +# endif +# if !defined(__IPHONE_10_2) +# define __IPHONE_10_2 100200 +# endif +# if !defined(__IPHONE_10_3) +# define __IPHONE_10_3 100300 +# endif +# if !defined(__IPHONE_11_0) +# define __IPHONE_11_0 110000 +# endif +# if !defined(__IPHONE_12_0) +# define __IPHONE_12_0 120000 +# endif +#endif + +#ifdef __LSB_VERSION__ +# if __LSB_VERSION__ < 40 +# error "This version of the Linux Standard Base is unsupported" +# endif +#ifndef QT_LINUXBASE +# define QT_LINUXBASE +#endif +#endif + +#endif // QSYSTEMDETECTION_H diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp b/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp new file mode 100644 index 0000000..b048576 --- /dev/null +++ b/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qhash.h" +#include "qpair.h" +#include "qmutex.h" +#include "qvarlengtharray.h" + +QT_BEGIN_NAMESPACE + +QCFString::operator QString() const +{ + if (string.isEmpty() && value) + const_cast(this)->string = QString::fromCFString(value); + return string; +} + +QCFString::operator CFStringRef() const +{ + if (!value) + const_cast(this)->value = string.toCFString(); + return value; +} + +// -------------------------------------------------------------------------- + +#if defined(QT_USE_APPLE_UNIFIED_LOGGING) + +bool AppleUnifiedLogger::willMirrorToStderr() +{ + // When running under Xcode or LLDB, one or more of these variables will + // be set, which triggers libsystem_trace.dyld to log messages to stderr + // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables + // is not an option, as that would silence normal NSLog or os_log calls, + // so instead we skip our own stderr output. See rdar://36919139. + static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE") + || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR") + || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR"); + return willMirror; +} + +QT_MAC_WEAK_IMPORT(_os_log_default); +bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context, + const QString &message, const QString &optionalSubsystem) +{ + QString subsystem = optionalSubsystem; + if (subsystem.isNull()) { + static QString bundleIdentifier = []() { + if (CFBundleRef bundle = CFBundleGetMainBundle()) { + if (CFStringRef identifier = CFBundleGetIdentifier(bundle)) + return QString::fromCFString(identifier); + } + return QString(); + }(); + subsystem = bundleIdentifier; + } + + const bool isDefault = !context.category || !strcmp(context.category, "default"); + os_log_t log = isDefault ? OS_LOG_DEFAULT : + cachedLog(subsystem, QString::fromLatin1(context.category)); + os_log_type_t logType = logTypeForMessageType(msgType); + + if (!os_log_type_enabled(log, logType)) + return false; + + // Logging best practices says we should not include symbolication + // information or source file line numbers in messages, as the system + // will automatically captures this information. In our case, what + // the system captures is the call to os_log_with_type below, which + // isn't really useful, but we still don't want to include the context's + // info, as that would clutter the logging output. See rdar://35958308. + + // The format must be a string constant, so we can't pass on the + // message. This means we won't be able to take advantage of the + // unified logging's custom format specifiers such as %{BOOL}d. + // We use the 'public' format specifier to prevent the logging + // system from redacting our log message. + os_log_with_type(log, logType, "%{public}s", qPrintable(message)); + + return willMirrorToStderr(); +} + +os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType) +{ + switch (msgType) { + case QtDebugMsg: return OS_LOG_TYPE_DEBUG; + case QtInfoMsg: return OS_LOG_TYPE_INFO; + case QtWarningMsg: return OS_LOG_TYPE_DEFAULT; + case QtCriticalMsg: return OS_LOG_TYPE_ERROR; + case QtFatalMsg: return OS_LOG_TYPE_FAULT; + } + + return OS_LOG_TYPE_DEFAULT; +} + +os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString &category) +{ + static QBasicMutex mutex; + QMutexLocker locker(&mutex); + + static QHash, os_log_t> logs; + const auto cacheKey = qMakePair(subsystem, category); + os_log_t log = logs.value(cacheKey); + + if (!log) { + log = os_log_create(subsystem.toLatin1().constData(), + category.toLatin1().constData()); + logs.insert(cacheKey, log); + + // Technically we should release the os_log_t resource when done + // with it, but since we don't know when a category is disabled + // we keep all cached os_log_t instances until shutdown, where + // the OS will clean them up for us. + } + + return log; +} + +#endif // QT_USE_APPLE_UNIFIED_LOGGING + +// -------------------------------------------------------------------------- + +QT_END_NAMESPACE diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h b/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h new file mode 100644 index 0000000..168e041 --- /dev/null +++ b/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCORE_MAC_P_H +#define QCORE_MAC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qglobal_p.h" + +#ifndef __IMAGECAPTURE__ +# define __IMAGECAPTURE__ +#endif + +// -------------------------------------------------------------------------- + +#if defined(QT_BOOTSTRAPPED) +#include +#else +#include +#endif + +#ifdef __OBJC__ +#include +#include +#endif + +#include "qstring.h" +#include "qscopedpointer.h" + +#if defined( __OBJC__) && defined(QT_NAMESPACE) +#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__) +#else +#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) +#endif + +#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import)); + +QT_BEGIN_NAMESPACE +template +class QAppleRefCounted +{ +public: + QAppleRefCounted(const T &t = T()) : value(t) {} + QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); } + QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } + ~QAppleRefCounted() { if (value) ReleaseFunction(value); } + operator T() const { return value; } + void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value))) + { qSwap(value, other.value); } + QAppleRefCounted &operator=(const QAppleRefCounted &other) + { QAppleRefCounted copy(other); swap(copy); return *this; } + QAppleRefCounted &operator=(QAppleRefCounted &&other) + { QAppleRefCounted moved(std::move(other)); swap(moved); return *this; } + T *operator&() { return &value; } +protected: + T value; +}; + + +#ifdef Q_OS_MACOS +class QMacRootLevelAutoReleasePool +{ +public: + QMacRootLevelAutoReleasePool(); + ~QMacRootLevelAutoReleasePool(); +private: + QScopedPointer pool; +}; +#endif + +/* + Helper class that automates refernce counting for CFtypes. + After constructing the QCFType object, it can be copied like a + value-based type. + + Note that you must own the object you are wrapping. + This is typically the case if you get the object from a Core + Foundation function with the word "Create" or "Copy" in it. If + you got the object from a "Get" function, either retain it or use + constructFromGet(). One exception to this rule is the + HIThemeGet*Shape functions, which in reality are "Copy" functions. +*/ +template +class QCFType : public QAppleRefCounted +{ +public: + using QAppleRefCounted::QAppleRefCounted; + template X as() const { return reinterpret_cast(this->value); } + static QCFType constructFromGet(const T &t) + { + if (t) + CFRetain(t); + return QCFType(t); + } +}; + +class Q_CORE_EXPORT QCFString : public QCFType +{ +public: + inline QCFString(const QString &str) : QCFType(0), string(str) {} + inline QCFString(const CFStringRef cfstr = 0) : QCFType(cfstr) {} + inline QCFString(const QCFType &other) : QCFType(other) {} + operator QString() const; + operator CFStringRef() const; + +private: + QString string; +}; + +#ifdef Q_OS_MACOS +Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key); +Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); +Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); +#endif + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool); +#endif + +Q_CORE_EXPORT bool qt_apple_isApplicationExtension(); + +#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED) +Q_CORE_EXPORT bool qt_apple_isSandboxed(); +# ifdef __OBJC__ +QT_END_NAMESPACE +@interface NSObject (QtSandboxHelpers) +- (id)qt_valueForPrivateKey:(NSString *)key; +@end +QT_BEGIN_NAMESPACE +# endif +#endif + +#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS) +QT_END_NAMESPACE +# if defined(Q_OS_MACOS) +Q_FORWARD_DECLARE_OBJC_CLASS(NSApplication); +using AppleApplication = NSApplication; +# else +Q_FORWARD_DECLARE_OBJC_CLASS(UIApplication); +using AppleApplication = UIApplication; +# endif +QT_BEGIN_NAMESPACE +Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication(); +#endif + +// -------------------------------------------------------------------------- + +#if !defined(QT_BOOTSTRAPPED) +#define QT_USE_APPLE_UNIFIED_LOGGING + +QT_END_NAMESPACE +#include +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT AppleUnifiedLogger +{ +public: + static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message, + const QString &subsystem = QString()); + static bool willMirrorToStderr(); +private: + static os_log_type_t logTypeForMessageType(QtMsgType msgType); + static os_log_t cachedLog(const QString &subsystem, const QString &category); +}; + +#endif + +// -------------------------------------------------------------------------- + +#if !defined(QT_BOOTSTRAPPED) + +QT_END_NAMESPACE +#include +QT_BEGIN_NAMESPACE + +template using QAppleOsType = QAppleRefCounted; + +class Q_CORE_EXPORT QAppleLogActivity +{ +public: + QAppleLogActivity() : activity(nullptr) {} + QAppleLogActivity(os_activity_t activity) : activity(activity) {} + ~QAppleLogActivity() { if (activity) leave(); } + + QAppleLogActivity(const QAppleLogActivity &) = delete; + QAppleLogActivity& operator=(const QAppleLogActivity &) = delete; + + QAppleLogActivity(QAppleLogActivity&& other) + : activity(other.activity), state(other.state) { other.activity = nullptr; } + + QAppleLogActivity& operator=(QAppleLogActivity &&other) + { + if (this != &other) { + activity = other.activity; + state = other.state; + other.activity = nullptr; + } + return *this; + } + + QAppleLogActivity&& enter() + { + if (activity) + os_activity_scope_enter(static_cast(*this), &state); + return std::move(*this); + } + + void leave() { + if (activity) + os_activity_scope_leave(&state); + } + + operator os_activity_t() + { + return reinterpret_cast(static_cast(activity)); + } + +private: + // Work around API_AVAILABLE not working for templates by using void* + QAppleOsType activity; + os_activity_scope_state_s state; +}; + +#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \ + if (!(condition)) \ + return QAppleLogActivity(); \ + return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \ + }() + +#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N +#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1) + +#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__) +#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) +#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC + +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent) +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__) + +QT_MAC_WEAK_IMPORT(_os_activity_current); +#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT) +#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description) +#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__) + +#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter(); + +#endif // !defined(QT_BOOTSTRAPPED) + +// ------------------------------------------------------------------------- + +#if defined( __OBJC__) +class QMacNotificationObserver +{ +public: + QMacNotificationObserver() {} + + template + QMacNotificationObserver(id object, NSNotificationName name, Functor callback) { + observer = [[NSNotificationCenter defaultCenter] addObserverForName:name + object:object queue:nil usingBlock:^(NSNotification *) { + callback(); + } + ]; + } + + QMacNotificationObserver(const QMacNotificationObserver& other) = delete; + QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) { + other.observer = nil; + } + + QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete; + QMacNotificationObserver &operator=(QMacNotificationObserver&& other) { + if (this != &other) { + remove(); + observer = other.observer; + other.observer = nil; + } + return *this; + } + + void remove() { + if (observer) + [[NSNotificationCenter defaultCenter] removeObserver:observer]; + observer = nil; + } + ~QMacNotificationObserver() { remove(); } + +private: + id observer = nil; +}; + +QT_END_NAMESPACE +@interface QT_MANGLE_NAMESPACE(KeyValueObserver) : NSObject +@end +QT_NAMESPACE_ALIAS_OBJC_CLASS(KeyValueObserver); +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QMacKeyValueObserver +{ +public: + using Callback = std::function; + + QMacKeyValueObserver() {} + + // Note: QMacKeyValueObserver must not outlive the object observed! + QMacKeyValueObserver(id object, NSString *keyPath, Callback callback, + NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew) + : object(object), keyPath(keyPath), callback(new Callback(callback)) + { + addObserver(options); + } + + QMacKeyValueObserver(const QMacKeyValueObserver &other) + : QMacKeyValueObserver(other.object, other.keyPath, *other.callback.get()) {} + + QMacKeyValueObserver(QMacKeyValueObserver &&other) { swap(other, *this); } + + ~QMacKeyValueObserver() { removeObserver(); } + + QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) { + QMacKeyValueObserver tmp(other); + swap(tmp, *this); + return *this; + } + + QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) { + QMacKeyValueObserver tmp(std::move(other)); + swap(tmp, *this); + return *this; + } + + void removeObserver(); + +private: + void swap(QMacKeyValueObserver &first, QMacKeyValueObserver &second) { + std::swap(first.object, second.object); + std::swap(first.keyPath, second.keyPath); + std::swap(first.callback, second.callback); + } + + void addObserver(NSKeyValueObservingOptions options); + + id object = nil; + NSString *keyPath = nullptr; + std::unique_ptr callback; + + static KeyValueObserver *observer; +}; +#endif + +// ------------------------------------------------------------------------- + +QT_END_NAMESPACE + +#endif // QCORE_MAC_P_H diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h new file mode 100644 index 0000000..69a1854 --- /dev/null +++ b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOAHELPERS_H +#define QCOCOAHELPERS_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It provides helper functions +// for the Cocoa lighthouse plugin. This header file may +// change from version to version without notice, or even be removed. +// +// We mean it. +// +#include "qt_mac_p.h" +#include +#include +#include +#include + +#include +#include + +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView)); + +struct mach_header; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow) +Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing) +Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse) +Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) + +class QPixmap; +class QString; + +// Conversion functions +QStringList qt_mac_NSArrayToQStringList(NSArray *nsarray); +NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &list); + +NSDragOperation qt_mac_mapDropAction(Qt::DropAction action); +NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); +Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); +Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); + +template +typename std::enable_if::value, T>::type +qt_objc_cast(id object) +{ + if ([object isKindOfClass:[typename std::remove_pointer::type class]]) + return static_cast(object); + + return nil; +} + +QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view); + +// Misc +void qt_mac_transformProccessToForegroundApplication(); +QString qt_mac_applicationName(); + +QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference); +QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference); + +Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); +Qt::MouseButton cocoaButton2QtButton(NSEvent *event); + +QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event); + +Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons); +Qt::MouseButtons currentlyPressedMouseButtons(); + +// strip out '&' characters, and convert "&&" to a single '&', in menu +// text - since menu text is sometimes decorated with these for Windows +// accelerators. +QString qt_mac_removeAmpersandEscapes(QString s); + +enum { + QtCocoaEventSubTypeWakeup = SHRT_MAX, + QtCocoaEventSubTypePostMessage = SHRT_MAX-1 +}; + +class QCocoaPostMessageArgs { +public: + id target; + SEL selector; + int argCount; + id arg1; + id arg2; + QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0) + : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2) + { + [target retain]; + [arg1 retain]; + [arg2 retain]; + } + + ~QCocoaPostMessageArgs() + { + [arg2 release]; + [arg1 release]; + [target release]; + } +}; + +template +T qt_mac_resolveOption(const T &fallback, const QByteArray &environment) +{ + // check for environment variable + if (!environment.isEmpty()) { + QByteArray env = qgetenv(environment); + if (!env.isEmpty()) + return T(env.toInt()); // works when T is bool, int. + } + + return fallback; +} + +template +T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &property, const QByteArray &environment) +{ + // check for environment variable + if (!environment.isEmpty()) { + QByteArray env = qgetenv(environment); + if (!env.isEmpty()) + return T(env.toInt()); // works when T is bool, int. + } + + // check for window property + if (window && !property.isNull()) { + QVariant windowProperty = window->property(property); + if (windowProperty.isValid()) + return windowProperty.value(); + } + + // return default value. + return fallback; +} + +// https://stackoverflow.com/a/52722575/2761869 +template +struct backwards_t { + R r; + constexpr auto begin() const { using std::rbegin; return rbegin(r); } + constexpr auto begin() { using std::rbegin; return rbegin(r); } + constexpr auto end() const { using std::rend; return rend(r); } + constexpr auto end() { using std::rend; return rend(r); } +}; +template +constexpr backwards_t backwards(R&& r) { return {std::forward(r)}; } + +// ------------------------------------------------------------------------- + +#if !defined(Q_PROCESSOR_X86_64) +#error "32-bit builds are not supported" +#endif + +class QMacVersion +{ +public: + enum VersionTarget { + ApplicationBinary, + QtLibraries + }; + + static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary); + static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary); + static QOperatingSystemVersion currentRuntime(); + +private: + QMacVersion() = default; + using VersionTuple = QPair; + static VersionTuple versionsForImage(const mach_header *machHeader); + static VersionTuple applicationVersion(); + static VersionTuple libraryVersion(); +}; + +// ------------------------------------------------------------------------- + +QT_END_NAMESPACE + +// @compatibility_alias doesn't work with protocols +#define QNSPanelDelegate QT_MANGLE_NAMESPACE(QNSPanelDelegate) + +@protocol QNSPanelDelegate +@required +- (void)onOkClicked; +- (void)onCancelClicked; +@end + +@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView + +@property (nonatomic, readonly) NSButton *okButton; +@property (nonatomic, readonly) NSButton *cancelButton; +@property (nonatomic, readonly) NSView *panelContents; // ARC: unretained, make it weak +@property (nonatomic, assign) NSEdgeInsets panelContentsMargins; + +- (instancetype)initWithPanelDelegate:(id)panelDelegate; +- (void)dealloc; + +- (NSButton *)createButtonWithTitle:(const char *)title; +- (void)layout; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper); + +// ------------------------------------------------------------------------- + +// QAppleRefCounted expects the retain function to return the object +io_object_t q_IOObjectRetain(io_object_t obj); +// QAppleRefCounted expects the release function to return void +void q_IOObjectRelease(io_object_t obj); + +template +class QIOType : public QAppleRefCounted +{ + using QAppleRefCounted::QAppleRefCounted; +}; + +// ------------------------------------------------------------------------- + +// Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret: +// - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html +// - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html +template +struct objc_msgsend_requires_stret +{ static const bool value = +#if defined(Q_PROCESSOR_X86) + // Any return value larger than two registers on i386/x86_64 + sizeof(T) > sizeof(void*) * 2; +#elif defined(Q_PROCESSOR_ARM_32) + // Any return value larger than a single register on arm + sizeof(T) > sizeof(void*); +#elif defined(Q_PROCESSOR_ARM_64) + // Stret not used on arm64 + false; +#endif +}; + +template <> +struct objc_msgsend_requires_stret +{ static const bool value = false; }; + +template +ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args) +{ + static_assert(!objc_msgsend_requires_stret::value, + "The given return type requires stret on this platform"); + + typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...); + SuperFn superFn = reinterpret_cast(objc_msgSendSuper); + objc_super sup = { receiver, [receiver superclass] }; + return superFn(&sup, selector, args...); +} + +template +ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args) +{ + static_assert(objc_msgsend_requires_stret::value, + "The given return type does not use stret on this platform"); + + typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...); + SuperStretFn superStretFn = reinterpret_cast(objc_msgSendSuper_stret); + + objc_super sup = { receiver, [receiver superclass] }; + ReturnType ret; + superStretFn(&ret, &sup, selector, args...); + return ret; +} + +template +class QSendSuperHelper { +public: + QSendSuperHelper(id receiver, SEL sel, Args... args) + : m_receiver(receiver), m_selector(sel), m_args(std::make_tuple(args...)), m_sent(false) + { + } + + ~QSendSuperHelper() + { + if (!m_sent) + msgSendSuper(m_args); + } + + template + operator ReturnType() + { +#if defined(QT_DEBUG) + Method method = class_getInstanceMethod(object_getClass(m_receiver), m_selector); + char returnTypeEncoding[256]; + method_getReturnType(method, returnTypeEncoding, sizeof(returnTypeEncoding)); + NSUInteger alignedReturnTypeSize = 0; + NSGetSizeAndAlignment(returnTypeEncoding, nullptr, &alignedReturnTypeSize); + Q_ASSERT(alignedReturnTypeSize == sizeof(ReturnType)); +#endif + m_sent = true; + return msgSendSuper(m_args); + } + +private: + template + using if_requires_stret = typename std::enable_if::value == V, ReturnType>::type; + + template + if_requires_stret msgSendSuper(std::tuple& args, QtPrivate::IndexesList) + { + return qt_msgSendSuper(m_receiver, m_selector, std::get(args)...); + } + + template + if_requires_stret msgSendSuper(std::tuple& args, QtPrivate::IndexesList) + { + return qt_msgSendSuper_stret(m_receiver, m_selector, std::get(args)...); + } + + template + ReturnType msgSendSuper(std::tuple& args) + { + return msgSendSuper(args, QtPrivate::makeIndexSequence{}); + } + + id m_receiver; + SEL m_selector; + std::tuple m_args; + bool m_sent; +}; + +template +QSendSuperHelper qt_objcDynamicSuperHelper(id receiver, SEL selector, Args... args) +{ + return QSendSuperHelper(receiver, selector, args...); +} + +// Same as calling super, but the super_class field resolved at runtime instead of compile time +#define qt_objcDynamicSuper(...) qt_objcDynamicSuperHelper(self, _cmd, ##__VA_ARGS__) + +#endif //QCOCOAHELPERS_H + diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm new file mode 100644 index 0000000..c9eafa8 --- /dev/null +++ b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -0,0 +1,599 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qcocoahelpers.h" +#include "qnsview.h" + +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_WIDGETS +#include +#endif + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); +Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing"); +Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg); +Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg); + +// +// Conversion Functions +// + +QStringList qt_mac_NSArrayToQStringList(NSArray *array) +{ + QStringList result; + for (NSString *string in array) + result << QString::fromNSString(string); + return result; +} + +NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &list) +{ + NSMutableArray *result = [NSMutableArray arrayWithCapacity:list.size()]; + for (const QString &string : list) + [result addObject:string.toNSString()]; + return result; +} + +struct dndenum_mapper +{ + NSDragOperation mac_code; + Qt::DropAction qt_code; + bool Qt2Mac; +}; + +static dndenum_mapper dnd_enums[] = { + { NSDragOperationLink, Qt::LinkAction, true }, + { NSDragOperationMove, Qt::MoveAction, true }, + { NSDragOperationDelete, Qt::MoveAction, true }, + { NSDragOperationCopy, Qt::CopyAction, true }, + { NSDragOperationGeneric, Qt::CopyAction, false }, + { NSDragOperationEvery, Qt::ActionMask, false }, + { NSDragOperationNone, Qt::IgnoreAction, false } +}; + +NSDragOperation qt_mac_mapDropAction(Qt::DropAction action) +{ + for (int i=0; dnd_enums[i].qt_code; i++) { + if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) { + return dnd_enums[i].mac_code; + } + } + return NSDragOperationNone; +} + +NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions) +{ + NSDragOperation nsActions = NSDragOperationNone; + for (int i=0; dnd_enums[i].qt_code; i++) { + if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code)) + nsActions |= dnd_enums[i].mac_code; + } + return nsActions; +} + +Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions) +{ + Qt::DropAction action = Qt::IgnoreAction; + for (int i=0; dnd_enums[i].mac_code; i++) { + if (nsActions & dnd_enums[i].mac_code) + return dnd_enums[i].qt_code; + } + return action; +} + +Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions) +{ + Qt::DropActions actions = Qt::IgnoreAction; + + for (int i=0; dnd_enums[i].mac_code; i++) { + if (dnd_enums[i].mac_code == NSDragOperationEvery) + continue; + + if (nsActions & dnd_enums[i].mac_code) + actions |= dnd_enums[i].qt_code; + } + return actions; +} + +/*! + Returns the view cast to a QNSview if possible. + + If the view is not a QNSView, nil is returned, which is safe to + send messages to, effectivly making [qnsview_cast(view) message] + a no-op. + + For extra verbosity and clearer code, please consider checking + that the platform window is not a foreign window before using + this cast, via QPlatformWindow::isForeignWindow(). + + Do not use this method soley to check for foreign windows, as + that will make the code harder to read for people not working + primarily on macOS, who do not know the difference between the + NSView and QNSView cases. +*/ +QNSView *qnsview_cast(NSView *view) +{ + return qt_objc_cast(view); +} + +// +// Misc +// + +// Sets the activation policy for this process to NSApplicationActivationPolicyRegular, +// unless either LSUIElement or LSBackgroundOnly is set in the Info.plist. +void qt_mac_transformProccessToForegroundApplication() +{ + bool forceTransform = true; + CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), + CFSTR("LSUIElement")); + if (value) { + CFTypeID valueType = CFGetTypeID(value); + // Officially it's supposed to be a string, a boolean makes sense, so we'll check. + // A number less so, but OK. + if (valueType == CFStringGetTypeID()) + forceTransform = !(QString::fromCFString(static_cast(value)).toInt()); + else if (valueType == CFBooleanGetTypeID()) + forceTransform = !CFBooleanGetValue(static_cast(value)); + else if (valueType == CFNumberGetTypeID()) { + int valueAsInt; + CFNumberGetValue(static_cast(value), kCFNumberIntType, &valueAsInt); + forceTransform = !valueAsInt; + } + } + + if (forceTransform) { + value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), + CFSTR("LSBackgroundOnly")); + if (value) { + CFTypeID valueType = CFGetTypeID(value); + if (valueType == CFBooleanGetTypeID()) + forceTransform = !CFBooleanGetValue(static_cast(value)); + else if (valueType == CFStringGetTypeID()) + forceTransform = !(QString::fromCFString(static_cast(value)).toInt()); + else if (valueType == CFNumberGetTypeID()) { + int valueAsInt; + CFNumberGetValue(static_cast(value), kCFNumberIntType, &valueAsInt); + forceTransform = !valueAsInt; + } + } + } + + if (forceTransform) { + [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; + } +} + +QString qt_mac_applicationName() +{ + QString appName; + CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("CFBundleName")); + if (string) + appName = QString::fromCFString(static_cast(string)); + + if (appName.isEmpty()) { + QString arg0 = QGuiApplicationPrivate::instance()->appName(); + if (arg0.contains("/")) { + QStringList parts = arg0.split(QLatin1Char('/')); + appName = parts.at(parts.count() - 1); + } else { + appName = arg0; + } + } + return appName; +} + +// ------------------------------------------------------------------------- + +/*! + \fn QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference) + \fn QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) + + Flips the Y coordinate of the point/rect between quadrant I and IV. + + The native coordinate system on macOS uses quadrant I, with origin + in bottom left, and Qt uses quadrant IV, with origin in top left. + + By flipping the Y coordinate, we can map the point/rect between + the two coordinate systems. + + The flip is always in relation to a reference rectangle, e.g. + the frame of the parent view, or the screen geometry. In the + latter case the specialized QCocoaScreen::mapFrom/To functions + should be used instead. +*/ +QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference) +{ + return QPointF(pos.x(), reference.height() - pos.y()); +} + +QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) +{ + return QRectF(qt_mac_flip(rect.bottomLeft(), reference), rect.size()); +} + +// ------------------------------------------------------------------------- + +/*! + \fn Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) + + Returns the Qt::Button that corresponds to an NSEvent.buttonNumber. + + \note AppKit will use buttonNumber 0 to indicate both "left button" + and "no button". Only NSEvents that describes mouse press/release + events (e.g NSEventTypeOtherMouseDown) will contain a valid + button number. +*/ +Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) +{ + if (buttonNum >= 0 && buttonNum <= 31) + return Qt::MouseButton(1 << buttonNum); + return Qt::NoButton; +} + +/*! + \fn Qt::MouseButton cocoaButton2QtButton(NSEvent *event) + + Returns the Qt::Button that corresponds to an NSEvent.buttonNumber. + + \note AppKit will use buttonNumber 0 to indicate both "left button" + and "no button". Only NSEvents that describes mouse press/release/dragging + events (e.g NSEventTypeOtherMouseDown) will contain a valid + button number. + + \note Wacom tablet might not return the correct button number for NSEvent buttonNumber + on right clicks. Decide here that the button is the "right" button. +*/ +Qt::MouseButton cocoaButton2QtButton(NSEvent *event) +{ + if (cocoaEvent2QtMouseEvent(event) == QEvent::MouseMove) + return Qt::NoButton; + + switch (event.type) { + case NSEventTypeRightMouseUp: + case NSEventTypeRightMouseDown: + return Qt::RightButton; + + default: + break; + } + + return cocoaButton2QtButton(event.buttonNumber); +} + +/*! + \fn QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event) + + Returns the QEvent::Type that corresponds to an NSEvent.type. +*/ +QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event) +{ + switch (event.type) { + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + return QEvent::MouseButtonPress; + + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseUp: + case NSEventTypeOtherMouseUp: + return QEvent::MouseButtonRelease; + + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeOtherMouseDragged: + return QEvent::MouseMove; + + case NSEventTypeMouseMoved: + return QEvent::MouseMove; + + default: + break; + } + + return QEvent::None; +} + +/*! + \fn Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons) + + Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons. +*/ +Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons) +{ + return static_cast(pressedMouseButtons & Qt::MouseButtonMask); +} + +/*! + \fn Qt::MouseButtons currentlyPressedMouseButtons() + + Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons. +*/ +Qt::MouseButtons currentlyPressedMouseButtons() +{ + return cocoaMouseButtons2QtMouseButtons(NSEvent.pressedMouseButtons); +} + +QString qt_mac_removeAmpersandEscapes(QString s) +{ + return QPlatformTheme::removeMnemonics(s).trimmed(); +} + +// ------------------------------------------------------------------------- + +#if !defined(Q_PROCESSOR_X86_64) +#error "32-bit builds are not supported" +#endif + +QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target) +{ + switch (target) { + case ApplicationBinary: return applicationVersion().second; + case QtLibraries: return libraryVersion().second; + } + Q_UNREACHABLE(); +} + +QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target) +{ + switch (target) { + case ApplicationBinary: return applicationVersion().first; + case QtLibraries: return libraryVersion().first; + } + Q_UNREACHABLE(); +} + +QOperatingSystemVersion QMacVersion::currentRuntime() +{ + return QOperatingSystemVersion::current(); +} + +QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader) +{ + static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk) { + return qMakePair( + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, + dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff), + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, + sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff) + ); + }; + + auto commandCursor = uintptr_t(machHeader) + sizeof(mach_header_64); + for (uint32_t i = 0; i < machHeader->ncmds; ++i) { + load_command *loadCommand = reinterpret_cast(commandCursor); + if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) { + auto versionCommand = reinterpret_cast(loadCommand); + return makeVersionTuple(versionCommand->version, versionCommand->sdk); +#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13) + } else if (loadCommand->cmd == LC_BUILD_VERSION) { + auto versionCommand = reinterpret_cast(loadCommand); + return makeVersionTuple(versionCommand->minos, versionCommand->sdk); +#endif + } + commandCursor += loadCommand->cmdsize; + } + Q_ASSERT_X(false, "QCocoaIntegration", "Could not find any version load command"); + Q_UNREACHABLE(); +} + +QMacVersion::VersionTuple QMacVersion::applicationVersion() +{ + static VersionTuple version = []() { + const mach_header *executableHeader = nullptr; + for (uint32_t i = 0; i < _dyld_image_count(); ++i) { + auto header = _dyld_get_image_header(i); + if (header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + Q_ASSERT_X(executableHeader, "QCocoaIntegration", "Failed to resolve Mach-O header of executable"); + return versionsForImage(executableHeader); + }(); + return version; +} + +QMacVersion::VersionTuple QMacVersion::libraryVersion() +{ + static VersionTuple version = []() { + Dl_info cocoaPluginImage; + dladdr((const void *)&QMacVersion::libraryVersion, &cocoaPluginImage); + Q_ASSERT_X(cocoaPluginImage.dli_fbase, "QCocoaIntegration", "Failed to resolve Mach-O header of Cocoa plugin"); + return versionsForImage(static_cast(cocoaPluginImage.dli_fbase)); + }(); + return version; +} + +QT_END_NAMESPACE + +/*! \internal + + This NSView derived class is used to add OK/Cancel + buttons to NSColorPanel and NSFontPanel. It replaces + the panel's content view, while reparenting the former + content view into itself. It also takes care of setting + the target-action for the OK/Cancel buttons and making + sure the layout is consistent. + */ +@implementation QNSPanelContentsWrapper { + NSButton *_okButton; + NSButton *_cancelButton; + NSView *_panelContents; + NSEdgeInsets _panelContentsMargins; +} + +@synthesize okButton = _okButton; +@synthesize cancelButton = _cancelButton; +@synthesize panelContents = _panelContents; +@synthesize panelContentsMargins = _panelContentsMargins; + +- (instancetype)initWithPanelDelegate:(id)panelDelegate +{ + if ((self = [super initWithFrame:NSZeroRect])) { + // create OK and Cancel buttons and add these as subviews + _okButton = [self createButtonWithTitle:"&OK"]; + _okButton.action = @selector(onOkClicked); + _okButton.target = panelDelegate; + + _cancelButton = [self createButtonWithTitle:"Cancel"]; + _cancelButton.action = @selector(onCancelClicked); + _cancelButton.target = panelDelegate; + + _panelContents = nil; + + _panelContentsMargins = NSEdgeInsetsMake(0, 0, 0, 0); + } + + return self; +} + +- (void)dealloc +{ + [_okButton release]; + _okButton = nil; + [_cancelButton release]; + _cancelButton = nil; + + _panelContents = nil; + + [super dealloc]; +} + +- (NSButton *)createButtonWithTitle:(const char *)title +{ + NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect]; + button.buttonType = NSMomentaryLightButton; + button.bezelStyle = NSRoundedBezelStyle; + const QString &cleanTitle = QPlatformTheme::removeMnemonics(QCoreApplication::translate("QDialogButtonBox", title)); + // FIXME: Not obvious, from Cocoa's documentation, that QString::toNSString() makes a deep copy + button.title = (NSString *)cleanTitle.toCFString(); + ((NSButtonCell *)button.cell).font = + [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeRegular]]; + [self addSubview:button]; + return button; +} + +- (void)layout +{ + static const CGFloat ButtonMinWidth = 78.0; // 84.0 for Carbon + static const CGFloat ButtonMinHeight = 32.0; + static const CGFloat ButtonSpacing = 0.0; + static const CGFloat ButtonTopMargin = 0.0; + static const CGFloat ButtonBottomMargin = 7.0; + static const CGFloat ButtonSideMargin = 9.0; + + NSSize frameSize = self.frame.size; + + [self.okButton sizeToFit]; + NSSize okSizeHint = self.okButton.frame.size; + + [self.cancelButton sizeToFit]; + NSSize cancelSizeHint = self.cancelButton.frame.size; + + const CGFloat buttonWidth = qMin(qMax(ButtonMinWidth, + qMax(okSizeHint.width, cancelSizeHint.width)), + CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5)); + const CGFloat buttonHeight = qMax(ButtonMinHeight, + qMax(okSizeHint.height, cancelSizeHint.height)); + + NSRect okRect = { { frameSize.width - ButtonSideMargin - buttonWidth, + ButtonBottomMargin }, + { buttonWidth, buttonHeight } }; + self.okButton.frame = okRect; + self.okButton.needsDisplay = YES; + + NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - buttonWidth, + ButtonBottomMargin }, + { buttonWidth, buttonHeight } }; + self.cancelButton.frame = cancelRect; + self.cancelButton.needsDisplay = YES; + + // The third view should be the original panel contents. Cache it. + if (!self.panelContents) + for (NSView *view in self.subviews) + if (view != self.okButton && view != self.cancelButton) { + _panelContents = view; + break; + } + + const CGFloat buttonBoxHeight = ButtonBottomMargin + buttonHeight + ButtonTopMargin; + const NSRect panelContentsFrame = NSMakeRect( + self.panelContentsMargins.left, + buttonBoxHeight + self.panelContentsMargins.bottom, + frameSize.width - (self.panelContentsMargins.left + self.panelContentsMargins.right), + frameSize.height - buttonBoxHeight - (self.panelContentsMargins.top + self.panelContentsMargins.bottom)); + self.panelContents.frame = panelContentsFrame; + self.panelContents.needsDisplay = YES; + + self.needsDisplay = YES; + [super layout]; +} + +// ------------------------------------------------------------------------- + +io_object_t q_IOObjectRetain(io_object_t obj) +{ + kern_return_t ret = IOObjectRetain(obj); + Q_ASSERT(!ret); + return obj; +} + +void q_IOObjectRelease(io_object_t obj) +{ + kern_return_t ret = IOObjectRelease(obj); + Q_ASSERT(!ret); +} + +@end