Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcore_mac_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QCORE_MAC_P_H
5#define QCORE_MAC_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "private/qglobal_p.h"
19
20#include <QtCore/qoperatingsystemversion.h>
21
22#include <optional>
23
24#ifdef Q_OS_MACOS
25#include <mach/port.h>
26struct mach_header;
27typedef int kern_return_t;
28typedef mach_port_t io_object_t;
29extern "C" {
30kern_return_t IOObjectRetain(io_object_t object);
31kern_return_t IOObjectRelease(io_object_t object);
32}
33#endif
34
35#ifndef __IMAGECAPTURE__
36# define __IMAGECAPTURE__
37#endif
38
39// --------------------------------------------------------------------------
40
41#if defined(QT_BOOTSTRAPPED)
42#include <ApplicationServices/ApplicationServices.h>
43#else
44#include <CoreFoundation/CoreFoundation.h>
45#endif
46
47#ifdef __OBJC__
48#include <Foundation/Foundation.h>
49#include <functional>
50#endif
51
52#include "qstring.h"
53#include "qpair.h"
54
55#if defined( __OBJC__) && defined(QT_NAMESPACE)
56#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
57#else
58#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
59#endif
60
61#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import));
62
63#if defined(__OBJC__)
64#define QT_DECLARE_NAMESPACED_OBJC_INTERFACE(classname, definition)
65 @interface QT_MANGLE_NAMESPACE(classname) :
66 definition
67 @end
68 QT_NAMESPACE_ALIAS_OBJC_CLASS(classname);
69#else
70#define QT_DECLARE_NAMESPACED_OBJC_INTERFACE(classname, definition)
71 Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(classname));
72 using classname = QT_MANGLE_NAMESPACE(classname);
73#endif
74
75#define QT_FORWARD_DECLARE_OBJC_ENUM(name, type)
76 typedef type name;
77
80
81// @compatibility_alias doesn't work with categories or their methods
82#define QtExtras QT_MANGLE_NAMESPACE(QtExtras)
83
84QT_BEGIN_NAMESPACE
85template <typename T, typename U, auto RetainFunction, auto ReleaseFunction>
86class QAppleRefCounted
87{
88public:
89 Q_NODISCARD_CTOR QAppleRefCounted() : value() {}
90 Q_NODISCARD_CTOR QAppleRefCounted(const T &t) : value(t) {}
91 Q_NODISCARD_CTOR QAppleRefCounted(T &&t)
92 noexcept(std::is_nothrow_move_constructible<T>::value)
93 : value(std::move(t)) {}
94 Q_NODISCARD_CTOR QAppleRefCounted(QAppleRefCounted &&other)
95 noexcept(std::is_nothrow_move_assignable<T>::value &&
96 std::is_nothrow_move_constructible<T>::value)
97 : value(std::exchange(other.value, T())) {}
98 Q_NODISCARD_CTOR QAppleRefCounted(const QAppleRefCounted &other)
99 : value(other.value)
100 { if (value) RetainFunction(value); }
101 ~QAppleRefCounted() { if (value) ReleaseFunction(value); }
102 operator T() const { return value; }
103 void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value)))
104 { qSwap(value, other.value); }
105 QAppleRefCounted &operator=(const QAppleRefCounted &other)
106 { QAppleRefCounted copy(other); swap(copy); return *this; }
107 QAppleRefCounted &operator=(QAppleRefCounted &&other)
108 noexcept(std::is_nothrow_move_assignable<T>::value &&
109 std::is_nothrow_move_constructible<T>::value)
110 { QAppleRefCounted moved(std::move(other)); swap(moved); return *this; }
111 T *operator&() { return &value; }
112protected:
113 T value;
114};
115
117{
118public:
119 Q_NODISCARD_CTOR Q_CORE_EXPORT QMacAutoReleasePool();
121private:
123 void *pool;
124};
125
126#ifdef Q_OS_MACOS
127class QMacRootLevelAutoReleasePool
128{
129public:
130 Q_NODISCARD_CTOR QMacRootLevelAutoReleasePool();
131 ~QMacRootLevelAutoReleasePool();
132private:
133 std::optional<QMacAutoReleasePool> pool = std::nullopt;
134};
135#endif
136
137/*
138 Helper class that automates reference counting for CFtypes.
139 After constructing the QCFType object, it can be copied like a
140 value-based type.
141
142 Note that you must own the object you are wrapping.
143 This is typically the case if you get the object from a Core
144 Foundation function with the word "Create" or "Copy" in it. If
145 you got the object from a "Get" function, either retain it or use
146 constructFromGet(). One exception to this rule is the
147 HIThemeGet*Shape functions, which in reality are "Copy" functions.
148*/
149template <typename T>
151{
153public:
154 using Base::Base;
155 Q_NODISCARD_CTOR explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {}
156 template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
157 static QCFType constructFromGet(const T &t)
158 {
159 if (t)
160 CFRetain(t);
161 return QCFType<T>(t);
162 }
163};
164
165#ifdef Q_OS_MACOS
166template <typename T>
167class QIOType : public QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>
168{
169 using QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>::QAppleRefCounted;
170};
171#endif
172
186
187class Q_CORE_EXPORT QObjCWeakPointerBase
188{
189public:
190 QObjCWeakPointerBase(NSObject *object = nil);
191 QObjCWeakPointerBase(const QObjCWeakPointerBase &other);
192 QObjCWeakPointerBase &operator=(const QObjCWeakPointerBase &other);
193
194protected:
195 ~QObjCWeakPointerBase();
196 NSObject *get() const;
197 union {
198 NSObject *m_object = nil;
199#if __has_feature(objc_arc_weak) && __has_feature(objc_arc_fields)
200 // Used by qcore_mac.mm, built with -fobjc-weak, to track lifetime
201 __weak id m_weakReference;
202#endif
203 };
204};
205
206template <typename T>
208{
209public:
210 using QObjCWeakPointerBase::QObjCWeakPointerBase;
211 operator T*() const { return static_cast<T*>(get()); }
212};
213
214// -------------------------------------------------------------------------
215
216#ifdef Q_OS_MACOS
217Q_CORE_EXPORT bool qt_mac_runningUnderRosetta();
218Q_CORE_EXPORT std::optional<uint32_t> qt_mac_sipConfiguration();
219#ifdef QT_BUILD_INTERNAL
220Q_AUTOTEST_EXPORT void qt_mac_ensureResponsible();
221#endif
222#endif
223
224#ifndef QT_NO_DEBUG_STREAM
225Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
226Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string);
227#endif
228
229Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
231
232#if !defined(QT_BOOTSTRAPPED)
233Q_CORE_EXPORT bool qt_apple_isSandboxed();
234
235#if defined(__OBJC__)
236QT_END_NAMESPACE
237@interface NSObject (QtExtras)
238- (id)qt_valueForPrivateKey:(NSString *)key;
239@end
240QT_BEGIN_NAMESPACE
241#endif
242#endif // !QT_BOOTSTRAPPED
243
244#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
246# if defined(Q_OS_MACOS)
249# else
251using AppleApplication = UIApplication;
252# endif
253QT_BEGIN_NAMESPACE
254Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
255#endif
256
257// --------------------------------------------------------------------------
258
259#if !defined(QT_BOOTSTRAPPED)
260#define QT_USE_APPLE_UNIFIED_LOGGING
261
263#include <os/log.h>
265
266class Q_CORE_EXPORT AppleUnifiedLogger
267{
268public:
269 static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
270 const QString &message)
271 { return messageHandler(msgType, context, message, QString()); }
272 static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
273 const QString &message, const QString &subsystem);
274 static bool preventsStderrLogging();
275private:
276 static os_log_type_t logTypeForMessageType(QtMsgType msgType);
277 static os_log_t cachedLog(const QString &subsystem, const QString &category);
278};
279
280#endif
281
282// --------------------------------------------------------------------------
283
284#if !defined(QT_BOOTSTRAPPED) && !__has_feature(objc_arc)
285
287#include <os/activity.h>
289
290template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
291
292class Q_CORE_EXPORT QAppleLogActivity
293{
294public:
295 QAppleLogActivity() : activity(nullptr) {}
296 QAppleLogActivity(os_activity_t activity) : activity(activity) {}
297 ~QAppleLogActivity() { if (activity) leave(); }
298
299 Q_DISABLE_COPY(QAppleLogActivity)
300
301 QAppleLogActivity(QAppleLogActivity &&other)
302 : activity(std::exchange(other.activity, nullptr)), state(other.state)
303 {
304 }
305
306 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QAppleLogActivity)
307
308 QAppleLogActivity &&enter()
309 {
310 if (activity)
311 os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
312 return std::move(*this);
313 }
314
315 void leave()
316 {
317 if (activity)
318 os_activity_scope_leave(&state);
319 }
320
321 operator os_activity_t()
322 {
323 return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
324 }
325
326 void swap(QAppleLogActivity &other)
327 {
328 activity.swap(other.activity);
329 std::swap(state, other.state);
330 }
331
332private:
333 // Work around API_AVAILABLE not working for templates by using void*
334 QAppleOsType<void *> activity;
335 os_activity_scope_state_s state;
336};
337
338#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() {
339 if (!(condition))
340 return QAppleLogActivity();
341 return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT));
342 }()
343
344#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
345#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(true, description, parent)
346#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
347
348QT_MAC_WEAK_IMPORT(_os_activity_current);
349#define QT_APPLE_LOG_ACTIVITY_2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
350#define QT_APPLE_LOG_ACTIVITY_1(description) QT_APPLE_LOG_ACTIVITY_2(true, description)
351#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
352
353#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
354
355#endif // !defined(QT_BOOTSTRAPPED) && !__has_feature(objc_arc)
356
357// -------------------------------------------------------------------------
358
359class Q_CORE_EXPORT QMacNotificationObserver
360{
361public:
362 QMacNotificationObserver() {}
363
364#if defined( __OBJC__)
365 template<typename Functor>
366 QMacNotificationObserver(NSObject *object, NSNotificationName name, Functor callback) {
367 observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
368 object:object queue:nil usingBlock:^(NSNotification *notification) {
369 if constexpr (std::is_invocable_v<Functor, NSNotification *>)
370 callback(notification);
371 else
372 callback();
373 }
374 ];
375 }
376#endif
377
378 QMacNotificationObserver(const QMacNotificationObserver &other) = delete;
379 QMacNotificationObserver(QMacNotificationObserver &&other)
380 : observer(std::exchange(other.observer, nullptr))
381 {
382 }
383
384 QMacNotificationObserver &operator=(const QMacNotificationObserver &other) = delete;
385 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacNotificationObserver)
386
387 void swap(QMacNotificationObserver &other) noexcept
388 {
389 std::swap(observer, other.observer);
390 }
391
392 void remove();
393 ~QMacNotificationObserver() { remove(); }
394
395private:
396 NSObject *observer = nullptr;
397};
398
400QT_DECLARE_NAMESPACED_OBJC_INTERFACE(KeyValueObserver, NSObject)
402
404{
405public:
406 using Callback = std::function<void()>;
407
408 QMacKeyValueObserver() = default;
409
410#if defined( __OBJC__)
411 QMacKeyValueObserver(NSObject *object, NSString *keyPath, Callback callback,
412 NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew)
413 : object(object), keyPath(keyPath), callback(new Callback(callback))
414 {
415 addObserver(options);
416 }
417#endif
418
419 QMacKeyValueObserver(const QMacKeyValueObserver &other);
420
421 QMacKeyValueObserver(QMacKeyValueObserver &&other) noexcept { swap(other); }
422
423 ~QMacKeyValueObserver() { removeObserver(); }
424
425 QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other)
426 {
427 QMacKeyValueObserver tmp(other);
428 swap(tmp);
429 return *this;
430 }
431
432 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacKeyValueObserver)
433
434 void removeObserver();
435
436 void swap(QMacKeyValueObserver &other) noexcept
437 {
438 std::swap(object, other.object);
439 std::swap(keyPath, other.keyPath);
440 callback.swap(other.callback);
441 }
442
443private:
444#if defined( __OBJC__)
445 void addObserver(NSKeyValueObservingOptions options);
446#endif
447
448 QObjCWeakPointer<NSObject> object;
449 NSString *keyPath = nullptr;
450 std::unique_ptr<Callback> callback;
451
452 static KeyValueObserver *observer;
453};
454
455// -------------------------------------------------------------------------
456
457class Q_CORE_EXPORT QMacVersion
458{
459public:
460 enum VersionTarget {
461 ApplicationBinary,
462 QtLibraries
463 };
464
465 static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary);
466 static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary);
467 static QOperatingSystemVersion currentRuntime();
468
469private:
470 QMacVersion() = default;
471 using VersionTuple = std::pair<QOperatingSystemVersion, QOperatingSystemVersion>;
472 static VersionTuple versionsForImage(const mach_header *machHeader);
473 static VersionTuple applicationVersion();
474 static VersionTuple libraryVersion();
475};
476
477// -------------------------------------------------------------------------
478
479#ifdef __OBJC__
480template <typename T>
481typename std::enable_if<std::is_pointer<T>::value, T>::type
482qt_objc_cast(id object)
483{
484 if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
485 return static_cast<T>(object);
486
487 return nil;
488}
489#endif
490
491// -------------------------------------------------------------------------
492
493QT_END_NAMESPACE
494
495#endif // QCORE_MAC_P_H
static QCFType constructFromGet(const T &t)
X as() const
Q_CORE_EXPORT ~QMacAutoReleasePool()
Definition qcore_mac.mm:304
const QString & asString(const QString &s)
Definition qstring.h:1680
#define __has_feature(x)
#define QT_APPLE_LOG_ACTIVITY_2(condition, description)
Q_CORE_EXPORT bool qt_apple_isApplicationExtension()
Definition qcore_mac.mm:447
#define QT_APPLE_LOG_ACTIVITY(...)
#define QtExtras
Definition qcore_mac_p.h:82
#define QT_MAC_WEAK_IMPORT(symbol)
Definition qcore_mac_p.h:61
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(condition, description, parent)
Q_FORWARD_DECLARE_OBJC_CLASS(NSString)
Q_CORE_EXPORT bool qt_apple_isSandboxed()
Definition qcore_mac.mm:522
Q_CORE_EXPORT bool qt_apple_runningWithLiquidGlass()
#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...)
#define QT_DECLARE_NAMESPACED_OBJC_INTERFACE(classname, definition)
Definition qcore_mac_p.h:70
Q_FORWARD_DECLARE_OBJC_CLASS(NSObject)
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2568
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker))
QT_REQUIRE_CONFIG(filesystemwatcher)
static QT_BEGIN_NAMESPACE void callBackFunction(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[])
#define qPrintable(string)
Definition qstring.h:1685