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