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
81struct CGPoint;
82struct CGSize;
83struct CGRect;
84#if defined(Q_OS_MACOS)
85struct NSEdgeInsets;
86#else
87struct UIEdgeInsets;
88#endif
89
90// @compatibility_alias doesn't work with categories or their methods
91#define QtExtras QT_MANGLE_NAMESPACE(QtExtras)
92
93QT_BEGIN_NAMESPACE
94template <typename T, typename U, auto RetainFunction, auto ReleaseFunction>
95class QAppleRefCounted
96{
97public:
98 Q_NODISCARD_CTOR QAppleRefCounted() : value() {}
99 Q_NODISCARD_CTOR QAppleRefCounted(const T &t) : value(t) {}
100 Q_NODISCARD_CTOR QAppleRefCounted(T &&t)
101 noexcept(std::is_nothrow_move_constructible<T>::value)
102 : value(std::move(t)) {}
103 Q_NODISCARD_CTOR QAppleRefCounted(QAppleRefCounted &&other)
104 noexcept(std::is_nothrow_move_assignable<T>::value &&
105 std::is_nothrow_move_constructible<T>::value)
106 : value(std::exchange(other.value, T())) {}
107 Q_NODISCARD_CTOR QAppleRefCounted(const QAppleRefCounted &other)
108 : value(other.value)
109 { if (value) RetainFunction(value); }
110 ~QAppleRefCounted() { if (value) ReleaseFunction(value); }
111 operator T() const { return value; }
112 void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value)))
113 { qSwap(value, other.value); }
114 QAppleRefCounted &operator=(const QAppleRefCounted &other)
115 { QAppleRefCounted copy(other); swap(copy); return *this; }
116 QAppleRefCounted &operator=(QAppleRefCounted &&other)
117 noexcept(std::is_nothrow_move_assignable<T>::value &&
118 std::is_nothrow_move_constructible<T>::value)
119 { QAppleRefCounted moved(std::move(other)); swap(moved); return *this; }
120 T *operator&() { return &value; }
121protected:
122 T value;
123};
124
126{
127public:
128 Q_NODISCARD_CTOR Q_CORE_EXPORT QMacAutoReleasePool();
130private:
132 void *pool;
133};
134
135#ifdef Q_OS_MACOS
136class QMacRootLevelAutoReleasePool
137{
138public:
139 Q_NODISCARD_CTOR QMacRootLevelAutoReleasePool();
140 ~QMacRootLevelAutoReleasePool();
141private:
142 std::optional<QMacAutoReleasePool> pool = std::nullopt;
143};
144#endif
145
146/*
147 Helper class that automates reference counting for CFtypes.
148 After constructing the QCFType object, it can be copied like a
149 value-based type.
150
151 Note that you must own the object you are wrapping.
152 This is typically the case if you get the object from a Core
153 Foundation function with the word "Create" or "Copy" in it. If
154 you got the object from a "Get" function, either retain it or use
155 constructFromGet(). One exception to this rule is the
156 HIThemeGet*Shape functions, which in reality are "Copy" functions.
157*/
158template <typename T>
160{
162public:
163 using Base::Base;
164 Q_NODISCARD_CTOR explicit QCFType(CFTypeRef r) : Base(static_cast<T>(r)) {}
165 template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
166 static QCFType constructFromGet(const T &t)
167 {
168 if (t)
169 CFRetain(t);
170 return QCFType<T>(t);
171 }
172};
173
174#ifdef Q_OS_MACOS
175template <typename T>
176class QIOType : public QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>
177{
178 using QAppleRefCounted<T, io_object_t, IOObjectRetain, IOObjectRelease>::QAppleRefCounted;
179};
180#endif
181
195
196class Q_CORE_EXPORT QObjCWeakPointerBase
197{
198public:
199 QObjCWeakPointerBase(NSObject *object = nil);
200 QObjCWeakPointerBase(const QObjCWeakPointerBase &other);
201 QObjCWeakPointerBase &operator=(const QObjCWeakPointerBase &other);
202
203protected:
204 ~QObjCWeakPointerBase();
205 NSObject *get() const;
206 union {
207 NSObject *m_object = nil;
208#if __has_feature(objc_arc_weak) && __has_feature(objc_arc_fields)
209 // Used by qcore_mac.mm, built with -fobjc-weak, to track lifetime
210 __weak id m_weakReference;
211#endif
212 };
213};
214
215template <typename T>
217{
218public:
219 using QObjCWeakPointerBase::QObjCWeakPointerBase;
220 operator T*() const { return static_cast<T*>(get()); }
221};
222
223// -------------------------------------------------------------------------
224
225#ifdef Q_OS_MACOS
226Q_CORE_EXPORT bool qt_mac_runningUnderRosetta();
227Q_CORE_EXPORT std::optional<uint32_t> qt_mac_sipConfiguration();
228Q_CORE_EXPORT bool qt_mac_processHasEntitlement(const QString &entitlement);
229#ifdef QT_BUILD_INTERNAL
230Q_AUTOTEST_EXPORT void qt_mac_ensureResponsible();
231#endif
232#endif
233
234#ifndef QT_NO_DEBUG_STREAM
235Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
236Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string);
237Q_CORE_EXPORT QDebug operator<<(QDebug, CGPoint);
238Q_CORE_EXPORT QDebug operator<<(QDebug, CGSize);
239Q_CORE_EXPORT QDebug operator<<(QDebug, CGRect);
240#if defined(Q_OS_MACOS)
241Q_CORE_EXPORT QDebug operator<<(QDebug, NSEdgeInsets);
242#else
243Q_CORE_EXPORT QDebug operator<<(QDebug, UIEdgeInsets);
244#endif
245#endif
246
247Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
249
250#if !defined(QT_BOOTSTRAPPED)
251Q_CORE_EXPORT bool qt_apple_isSandboxed();
252
253#if defined(__OBJC__)
254QT_END_NAMESPACE
255@interface NSObject (QtExtras)
256- (id)qt_valueForPrivateKey:(NSString *)key;
257@end
258QT_BEGIN_NAMESPACE
259#endif
260#endif // !QT_BOOTSTRAPPED
261
262#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
264# if defined(Q_OS_MACOS)
267# else
269using AppleApplication = UIApplication;
270# endif
271QT_BEGIN_NAMESPACE
272Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
273#endif
274
275// --------------------------------------------------------------------------
276
277#if !defined(QT_BOOTSTRAPPED)
278#define QT_USE_APPLE_UNIFIED_LOGGING
279
281#include <os/log.h>
283
284class Q_CORE_EXPORT AppleUnifiedLogger
285{
286public:
287 static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
288 const QString &message)
289 { return messageHandler(msgType, context, message, QString()); }
290 static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context,
291 const QString &message, const QString &subsystem);
292 static bool preventsStderrLogging();
293private:
294 static os_log_type_t logTypeForMessageType(QtMsgType msgType);
295 static os_log_t cachedLog(const QString &subsystem, const QString &category);
296};
297
298#endif
299
300// --------------------------------------------------------------------------
301
302#if !defined(QT_BOOTSTRAPPED) && !__has_feature(objc_arc)
303
305#include <os/activity.h>
307
308template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
309
310class Q_CORE_EXPORT QAppleLogActivity
311{
312public:
313 QAppleLogActivity() : activity(nullptr) {}
314 QAppleLogActivity(os_activity_t activity) : activity(activity) {}
315 ~QAppleLogActivity() { if (activity) leave(); }
316
317 Q_DISABLE_COPY(QAppleLogActivity)
318
319 QAppleLogActivity(QAppleLogActivity &&other)
320 : activity(std::exchange(other.activity, nullptr)), state(other.state)
321 {
322 }
323
324 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QAppleLogActivity)
325
326 QAppleLogActivity &&enter()
327 {
328 if (activity)
329 os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
330 return std::move(*this);
331 }
332
333 void leave()
334 {
335 if (activity)
336 os_activity_scope_leave(&state);
337 }
338
339 operator os_activity_t()
340 {
341 return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
342 }
343
344 void swap(QAppleLogActivity &other)
345 {
346 activity.swap(other.activity);
347 std::swap(state, other.state);
348 }
349
350private:
351 // Work around API_AVAILABLE not working for templates by using void*
352 QAppleOsType<void *> activity;
353 os_activity_scope_state_s state;
354};
355
356#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() {
357 if (!(condition))
358 return QAppleLogActivity();
359 return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT));
360 }()
361
362#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
363#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT_2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT_3(true, description, parent)
364#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
365
366QT_MAC_WEAK_IMPORT(_os_activity_current);
367#define QT_APPLE_LOG_ACTIVITY_2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
368#define QT_APPLE_LOG_ACTIVITY_1(description) QT_APPLE_LOG_ACTIVITY_2(true, description)
369#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
370
371#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
372
373#endif // !defined(QT_BOOTSTRAPPED) && !__has_feature(objc_arc)
374
375// -------------------------------------------------------------------------
376
377class Q_CORE_EXPORT QMacNotificationObserver
378{
379public:
380 QMacNotificationObserver() {}
381
382#if defined( __OBJC__)
383 template<typename Functor>
384 QMacNotificationObserver(NSObject *object, NSNotificationName name, Functor callback) {
385 observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
386 object:object queue:nil usingBlock:^(NSNotification *notification) {
387 if constexpr (std::is_invocable_v<Functor, NSNotification *>)
388 callback(notification);
389 else
390 callback();
391 }
392 ];
393 }
394#endif
395
396 QMacNotificationObserver(const QMacNotificationObserver &other) = delete;
397 QMacNotificationObserver(QMacNotificationObserver &&other)
398 : observer(std::exchange(other.observer, nullptr))
399 {
400 }
401
402 QMacNotificationObserver &operator=(const QMacNotificationObserver &other) = delete;
403 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacNotificationObserver)
404
405 void swap(QMacNotificationObserver &other) noexcept
406 {
407 std::swap(observer, other.observer);
408 }
409
410 void remove();
411 ~QMacNotificationObserver() { remove(); }
412
413private:
414 NSObject *observer = nullptr;
415};
416
418QT_DECLARE_NAMESPACED_OBJC_INTERFACE(KeyValueObserver, NSObject)
420
422{
423public:
424 using Callback = std::function<void()>;
425
426 QMacKeyValueObserver() = default;
427
428#if defined( __OBJC__)
429 QMacKeyValueObserver(NSObject *object, NSString *keyPath, Callback callback,
430 NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew)
431 : object(object), keyPath(keyPath), callback(new Callback(callback))
432 {
433 addObserver(options);
434 }
435#endif
436
437 QMacKeyValueObserver(const QMacKeyValueObserver &other);
438
439 QMacKeyValueObserver(QMacKeyValueObserver &&other) noexcept { swap(other); }
440
441 ~QMacKeyValueObserver() { removeObserver(); }
442
443 QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other)
444 {
445 QMacKeyValueObserver tmp(other);
446 swap(tmp);
447 return *this;
448 }
449
450 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMacKeyValueObserver)
451
452 void removeObserver();
453
454 void swap(QMacKeyValueObserver &other) noexcept
455 {
456 std::swap(object, other.object);
457 std::swap(keyPath, other.keyPath);
458 callback.swap(other.callback);
459 }
460
461private:
462#if defined( __OBJC__)
463 void addObserver(NSKeyValueObservingOptions options);
464#endif
465
466 QObjCWeakPointer<NSObject> object;
467 NSString *keyPath = nullptr;
468 std::unique_ptr<Callback> callback;
469
470 static KeyValueObserver *observer;
471};
472
473// -------------------------------------------------------------------------
474
475class Q_CORE_EXPORT QMacVersion
476{
477public:
478 enum VersionTarget {
479 ApplicationBinary,
480 QtLibraries
481 };
482
483 static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary);
484 static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary);
485 static QOperatingSystemVersion currentRuntime();
486
487private:
488 QMacVersion() = default;
489 using VersionTuple = std::pair<QOperatingSystemVersion, QOperatingSystemVersion>;
490 static VersionTuple versionsForImage(const mach_header *machHeader);
491 static VersionTuple applicationVersion();
492 static VersionTuple libraryVersion();
493};
494
495// -------------------------------------------------------------------------
496
497#ifdef __OBJC__
498template <typename T>
499typename std::enable_if<std::is_pointer<T>::value, T>::type
500qt_objc_cast(id object)
501{
502 if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
503 return static_cast<T>(object);
504
505 return nil;
506}
507#endif
508
509// -------------------------------------------------------------------------
510
511QT_END_NAMESPACE
512
513#endif // QCORE_MAC_P_H
static QCFType constructFromGet(const T &t)
X as() const
Q_CORE_EXPORT ~QMacAutoReleasePool()
Definition qcore_mac.mm:346
Combined button and popup list for selecting options.
const QString & asString(const QString &s)
Definition qstring.h:1678
#define __has_feature(x)
#define QT_APPLE_LOG_ACTIVITY_2(condition, description)
Q_CORE_EXPORT bool qt_apple_isApplicationExtension()
Definition qcore_mac.mm:506
#define QT_APPLE_LOG_ACTIVITY(...)
#define QtExtras
Definition qcore_mac_p.h:91
#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:536
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:2582
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:1683