diff options
Diffstat (limited to 'src/corelib/kernel/qcore_mac_p.h')
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 251 |
1 files changed, 147 insertions, 104 deletions
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 306d6ac8bb..e63c320805 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QCORE_MAC_P_H #define QCORE_MAC_P_H @@ -53,6 +17,19 @@ #include "private/qglobal_p.h" +#include <QtCore/qoperatingsystemversion.h> + +#ifdef Q_OS_MACOS +#include <mach/port.h> +struct mach_header; +typedef int kern_return_t; +typedef mach_port_t io_object_t; +extern "C" { +kern_return_t IOObjectRetain(io_object_t object); +kern_return_t IOObjectRelease(io_object_t object); +} +#endif + #ifndef __IMAGECAPTURE__ # define __IMAGECAPTURE__ #endif @@ -72,6 +49,7 @@ #include "qstring.h" #include "qscopedpointer.h" +#include "qpair.h" #if defined( __OBJC__) && defined(QT_NAMESPACE) #define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__) @@ -99,20 +77,26 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); Q_FORWARD_DECLARE_OBJC_CLASS(NSString); +// @compatibility_alias doesn't work with categories or their methods +#define QtExtras QT_MANGLE_NAMESPACE(QtExtras) + QT_BEGIN_NAMESPACE -template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)> +template <typename T, typename U, auto RetainFunction, auto ReleaseFunction> class QAppleRefCounted { public: - QAppleRefCounted() : value() {} - QAppleRefCounted(const T &t) : value(t) {} - QAppleRefCounted(T &&t) noexcept(std::is_nothrow_move_constructible<T>::value) + Q_NODISCARD_CTOR QAppleRefCounted() : value() {} + Q_NODISCARD_CTOR QAppleRefCounted(const T &t) : value(t) {} + Q_NODISCARD_CTOR QAppleRefCounted(T &&t) + noexcept(std::is_nothrow_move_constructible<T>::value) : value(std::move(t)) {} - QAppleRefCounted(QAppleRefCounted &&other) + Q_NODISCARD_CTOR QAppleRefCounted(QAppleRefCounted &&other) noexcept(std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value) - : value(qExchange(other.value, T())) {} - QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); } + : value(std::exchange(other.value, T())) {} + Q_NODISCARD_CTOR 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) noexcept(noexcept(qSwap(value, other.value))) @@ -128,12 +112,21 @@ protected: T value; }; +class QMacAutoReleasePool +{ +public: + Q_NODISCARD_CTOR Q_CORE_EXPORT QMacAutoReleasePool(); + Q_CORE_EXPORT ~QMacAutoReleasePool(); +private: + Q_DISABLE_COPY(QMacAutoReleasePool) + void *pool; +}; #ifdef Q_OS_MACOS class QMacRootLevelAutoReleasePool { public: - QMacRootLevelAutoReleasePool(); + Q_NODISCARD_CTOR QMacRootLevelAutoReleasePool(); ~QMacRootLevelAutoReleasePool(); private: QScopedPointer<QMacAutoReleasePool> pool; @@ -141,7 +134,7 @@ private: #endif /* - Helper class that automates refernce counting for CFtypes. + Helper class that automates reference counting for CFtypes. After constructing the QCFType object, it can be copied like a value-based type. @@ -158,7 +151,7 @@ class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease> using Base = QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>; public: using Base::Base; - explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {} + Q_NODISCARD_CTOR explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {} template <typename X> X as() const { return reinterpret_cast<X>(this->value); } static QCFType constructFromGet(const T &t) { @@ -168,15 +161,23 @@ public: } }; -class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef> +#ifdef Q_OS_MACOS +template <typename T> +class QIOType : public QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease> +{ + using QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>::QAppleRefCounted; +}; +#endif + +class QCFString : public QCFType<CFStringRef> { public: using QCFType<CFStringRef>::QCFType; - 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; + Q_NODISCARD_CTOR QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {} + Q_NODISCARD_CTOR QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {} + Q_NODISCARD_CTOR QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {} + Q_CORE_EXPORT operator QString() const; + Q_CORE_EXPORT operator CFStringRef() const; private: QString string; @@ -184,6 +185,11 @@ private: #ifdef Q_OS_MACOS Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); +Q_CORE_EXPORT bool qt_mac_runningUnderRosetta(); +Q_CORE_EXPORT std::optional<uint32_t> qt_mac_sipConfiguration(); +#ifdef QT_BUILD_INTERNAL +Q_AUTOTEST_EXPORT void qt_mac_ensureResponsible(); +#endif #endif #ifndef QT_NO_DEBUG_STREAM @@ -193,16 +199,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string); Q_CORE_EXPORT bool qt_apple_isApplicationExtension(); -#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED) +#if !defined(QT_BOOTSTRAPPED) Q_CORE_EXPORT bool qt_apple_isSandboxed(); -# ifdef __OBJC__ + +#if defined(__OBJC__) QT_END_NAMESPACE -@interface NSObject (QtSandboxHelpers) +@interface NSObject (QtExtras) - (id)qt_valueForPrivateKey:(NSString *)key; @end QT_BEGIN_NAMESPACE -# endif #endif +#endif // !QT_BOOTSTRAPPED #if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS) QT_END_NAMESPACE @@ -229,9 +236,12 @@ 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(); + static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, + const QString &message) + { return messageHandler(msgType, context, message, QString()); } + static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, + const QString &message, const QString &subsystem); + static bool preventsStderrLogging(); private: static os_log_type_t logTypeForMessageType(QtMsgType msgType); static os_log_t cachedLog(const QString &subsystem, const QString &category); @@ -256,30 +266,24 @@ public: 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; } + Q_DISABLE_COPY(QAppleLogActivity) - QAppleLogActivity& operator=(QAppleLogActivity &&other) + QAppleLogActivity(QAppleLogActivity &&other) + : activity(std::exchange(other.activity, nullptr)), state(other.state) { - if (this != &other) { - activity = other.activity; - state = other.state; - other.activity = nullptr; - } - return *this; } - QAppleLogActivity&& enter() + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QAppleLogActivity) + + QAppleLogActivity &&enter() { if (activity) os_activity_scope_enter(static_cast<os_activity_t>(*this), &state); return std::move(*this); } - void leave() { + void leave() + { if (activity) os_activity_scope_leave(&state); } @@ -289,6 +293,12 @@ public: return reinterpret_cast<os_activity_t>(static_cast<void *>(activity)); } + void swap(QAppleLogActivity &other) + { + activity.swap(other.activity); + std::swap(state, other.state); + } + private: // Work around API_AVAILABLE not working for templates by using void* QAppleOsType<void *> activity; @@ -301,13 +311,13 @@ private: return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \ }() -#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_3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(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_2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT) +#define QT_APPLE_LOG_ACTIVITY_1(description) QT_APPLE_LOG_ACTIVITY_2(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(); @@ -332,19 +342,18 @@ public: } #endif - QMacNotificationObserver(const QMacNotificationObserver& other) = delete; - QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) { - other.observer = nullptr; + QMacNotificationObserver(const QMacNotificationObserver &other) = delete; + QMacNotificationObserver(QMacNotificationObserver &&other) + : observer(std::exchange(other.observer, nullptr)) + { } - QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete; - QMacNotificationObserver &operator=(QMacNotificationObserver&& other) { - if (this != &other) { - remove(); - observer = other.observer; - other.observer = nullptr; - } - return *this; + QMacNotificationObserver &operator=(const QMacNotificationObserver &other) = delete; + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacNotificationObserver) + + void swap(QMacNotificationObserver &other) noexcept + { + qt_ptr_swap(observer, other.observer); } void remove(); @@ -363,7 +372,7 @@ class Q_CORE_EXPORT QMacKeyValueObserver public: using Callback = std::function<void()>; - QMacKeyValueObserver() {} + QMacKeyValueObserver() = default; #if defined( __OBJC__) // Note: QMacKeyValueObserver must not outlive the object observed! @@ -377,31 +386,29 @@ public: QMacKeyValueObserver(const QMacKeyValueObserver &other); - QMacKeyValueObserver(QMacKeyValueObserver &&other) { swap(other, *this); } + QMacKeyValueObserver(QMacKeyValueObserver &&other) noexcept { swap(other); } ~QMacKeyValueObserver() { removeObserver(); } - QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) { + QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) + { QMacKeyValueObserver tmp(other); - swap(tmp, *this); + swap(tmp); return *this; } - QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) { - QMacKeyValueObserver tmp(std::move(other)); - swap(tmp, *this); - return *this; - } + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacKeyValueObserver) 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 swap(QMacKeyValueObserver &other) noexcept + { + qt_ptr_swap(object, other.object); + qt_ptr_swap(keyPath, other.keyPath); + callback.swap(other.callback); } +private: #if defined( __OBJC__) void addObserver(NSKeyValueObservingOptions options); #endif @@ -415,6 +422,42 @@ private: // ------------------------------------------------------------------------- +class Q_CORE_EXPORT 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 = std::pair<QOperatingSystemVersion, QOperatingSystemVersion>; + static VersionTuple versionsForImage(const mach_header *machHeader); + static VersionTuple applicationVersion(); + static VersionTuple libraryVersion(); +}; + +// ------------------------------------------------------------------------- + +#ifdef __OBJC__ +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; +} +#endif + +// ------------------------------------------------------------------------- + QT_END_NAMESPACE #endif // QCORE_MAC_P_H |