5.13.2: original files to be modified by backport big sur detection (25e0e6273d)

This commit is contained in:
kleuter 2020-11-18 11:25:51 +01:00
parent 7b3f7dfada
commit 730c5b3b96
7 changed files with 2526 additions and 0 deletions

View File

@ -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 <qversionnumber.h>
#include <qdebug.h>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <private/qjni_p.h>
#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<jint>(
"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<OSType> 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<OSType> 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

View File

@ -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 <QtCore/qglobal.h>
#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<OSType> 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

View File

@ -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 <QtCore/qglobal.h>
#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 <TargetConditionals.h>
# 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 <Availability.h>
# include <AvailabilityMacros.h>
#
# 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

View File

@ -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 <private/qcore_mac_p.h>
#include <new>
#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<QCFString*>(this)->string = QString::fromCFString(value);
return string;
}
QCFString::operator CFStringRef() const
{
if (!value)
const_cast<QCFString*>(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<QPair<QString, QString>, 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

View File

@ -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 <ApplicationServices/ApplicationServices.h>
#else
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#include <functional>
#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 <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
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<QMacAutoReleasePool> 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 <typename T>
class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>
{
public:
using QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>::QAppleRefCounted;
template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
static QCFType constructFromGet(const T &t)
{
if (t)
CFRetain(t);
return QCFType<T>(t);
}
};
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
{
public:
inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(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 <os/log.h>
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 <os/activity.h>
QT_BEGIN_NAMESPACE
template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
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<os_activity_t>(*this), &state);
return std::move(*this);
}
void leave() {
if (activity)
os_activity_scope_leave(&state);
}
operator os_activity_t()
{
return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
}
private:
// Work around API_AVAILABLE not working for templates by using void*
QAppleOsType<void *> 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<typename Functor>
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<void()>;
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> callback;
static KeyValueObserver *observer;
};
#endif
// -------------------------------------------------------------------------
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H

View File

@ -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 <private/qguiapplication_p.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpalette.h>
#include <QtGui/qscreen.h>
#include <objc/runtime.h>
#include <objc/message.h>
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<NSString *> *nsarray);
NSMutableArray<NSString *> *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 T>
typename std::enable_if<std::is_pointer<T>::value, T>::type
qt_objc_cast(id object)
{
if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
return static_cast<T>(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<typename T>
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<typename T>
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<T>();
}
// return default value.
return fallback;
}
// https://stackoverflow.com/a/52722575/2761869
template<class R>
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<class R>
constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(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<QOperatingSystemVersion, QOperatingSystemVersion>;
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<QNSPanelDelegate>)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 <typename T>
class QIOType : public QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>
{
using QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>::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 <typename T>
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<void>
{ static const bool value = false; };
template <typename ReturnType, typename... Args>
ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args)
{
static_assert(!objc_msgsend_requires_stret<ReturnType>::value,
"The given return type requires stret on this platform");
typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...);
SuperFn superFn = reinterpret_cast<SuperFn>(objc_msgSendSuper);
objc_super sup = { receiver, [receiver superclass] };
return superFn(&sup, selector, args...);
}
template <typename ReturnType, typename... Args>
ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args)
{
static_assert(objc_msgsend_requires_stret<ReturnType>::value,
"The given return type does not use stret on this platform");
typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...);
SuperStretFn superStretFn = reinterpret_cast<SuperStretFn>(objc_msgSendSuper_stret);
objc_super sup = { receiver, [receiver superclass] };
ReturnType ret;
superStretFn(&ret, &sup, selector, args...);
return ret;
}
template<typename... Args>
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<void>(m_args);
}
template <typename ReturnType>
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<ReturnType>(m_args);
}
private:
template <typename ReturnType, bool V>
using if_requires_stret = typename std::enable_if<objc_msgsend_requires_stret<ReturnType>::value == V, ReturnType>::type;
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper_stret<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
template <typename ReturnType>
ReturnType msgSendSuper(std::tuple<Args...>& args)
{
return msgSendSuper<ReturnType>(args, QtPrivate::makeIndexSequence<sizeof...(Args)>{});
}
id m_receiver;
SEL m_selector;
std::tuple<Args...> m_args;
bool m_sent;
};
template<typename... Args>
QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, Args... args)
{
return QSendSuperHelper<Args...>(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

View File

@ -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 <qpa/qplatformtheme.h>
#include "qcocoahelpers.h"
#include "qnsview.h"
#include <QtCore>
#include <QtGui>
#include <qpa/qplatformscreen.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
#include <QtGui/private/qcoregraphics_p.h>
#ifndef QT_NO_WIDGETS
#include <QtWidgets/QWidget>
#endif
#include <algorithm>
#include <mach-o/dyld.h>
#include <dlfcn.h>
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<NSString *> *array)
{
QStringList result;
for (NSString *string in array)
result << QString::fromNSString(string);
return result;
}
NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list)
{
NSMutableArray<NSString *> *result = [NSMutableArray<NSString *> 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<QNSView *>(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<CFStringRef>(value)).toInt());
else if (valueType == CFBooleanGetTypeID())
forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
else if (valueType == CFNumberGetTypeID()) {
int valueAsInt;
CFNumberGetValue(static_cast<CFNumberRef>(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<CFBooleanRef>(value));
else if (valueType == CFStringGetTypeID())
forceTransform = !(QString::fromCFString(static_cast<CFStringRef>(value)).toInt());
else if (valueType == CFNumberGetTypeID()) {
int valueAsInt;
CFNumberGetValue(static_cast<CFNumberRef>(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<CFStringRef>(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<Qt::MouseButton>(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<load_command *>(commandCursor);
if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) {
auto versionCommand = reinterpret_cast<version_min_command *>(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<build_version_command *>(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<mach_header*>(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<QNSPanelDelegate>)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