Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcocoahelpers.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 QCOCOAHELPERS_H
5#define QCOCOAHELPERS_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It provides helper functions
12// for the Cocoa plugin. This header file may
13// change from version to version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qguiapplication_p.h>
19#include <QtCore/qloggingcategory.h>
20#include <QtGui/qpalette.h>
21#include <QtGui/qscreen.h>
22#include <qpa/qplatformdialoghelper.h>
23
24#include <objc/runtime.h>
25#include <objc/message.h>
26
27#if defined(__OBJC__)
28
30
31struct mach_header;
32
34
39Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods)
41Q_DECLARE_LOGGING_CATEGORY(lcQpaApplication)
42Q_DECLARE_LOGGING_CATEGORY(lcQpaClipboard)
43Q_DECLARE_LOGGING_CATEGORY(lcInputDevices)
46
47class QPixmap;
48class QString;
49
50// Conversion functions
51QStringList qt_mac_NSArrayToQStringList(NSArray<NSString *> *nsarray);
52NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list);
53
54NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
55NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
56Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
57Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
58
59template <typename T>
60typename std::enable_if<std::is_pointer<T>::value, T>::type
61qt_objc_cast(id object)
62{
63 if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
64 return static_cast<T>(object);
65
66 return nil;
67}
68
70
71// Misc
74
77
80
82
83Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons);
84Qt::MouseButtons currentlyPressedMouseButtons();
85
86// strip out '&' characters, and convert "&&" to a single '&', in menu
87// text - since menu text is sometimes decorated with these for Windows
88// accelerators.
90
91enum {
92 QtCocoaEventSubTypeWakeup = SHRT_MAX,
93 QtCocoaEventSubTypePostMessage = SHRT_MAX-1
94};
95
96class QCocoaPostMessageArgs {
97public:
98 id target;
99 SEL selector;
100 int argCount;
101 id arg1;
102 id arg2;
103 QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0)
104 : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2)
105 {
106 [target retain];
107 [arg1 retain];
108 [arg2 retain];
109 }
110
111 ~QCocoaPostMessageArgs()
112 {
113 [arg2 release];
114 [arg1 release];
115 [target release];
116 }
117};
118
119template<typename T>
120T qt_mac_resolveOption(const T &fallback, const QByteArray &environment)
121{
122 // check for environment variable
123 if (!environment.isEmpty()) {
124 QByteArray env = qgetenv(environment);
125 if (!env.isEmpty())
126 return T(env.toInt()); // works when T is bool, int.
127 }
128
129 return fallback;
130}
131
132template<typename T>
133T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &property, const QByteArray &environment)
134{
135 // check for environment variable
136 if (!environment.isEmpty()) {
137 QByteArray env = qgetenv(environment);
138 if (!env.isEmpty())
139 return T(env.toInt()); // works when T is bool, int.
140 }
141
142 // check for window property
143 if (window && !property.isNull()) {
144 QVariant windowProperty = window->property(property);
145 if (windowProperty.isValid())
146 return windowProperty.value<T>();
147 }
148
149 // return default value.
150 return fallback;
151}
152
153// https://stackoverflow.com/a/52722575/2761869
154template<class R>
155struct backwards_t {
156 R r;
157 constexpr auto begin() const { using std::rbegin; return rbegin(r); }
158 constexpr auto begin() { using std::rbegin; return rbegin(r); }
159 constexpr auto end() const { using std::rend; return rend(r); }
160 constexpr auto end() { using std::rend; return rend(r); }
161};
162template<class R>
163constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
164
166
167// @compatibility_alias doesn't work with protocols
168#define QNSPanelDelegate QT_MANGLE_NAMESPACE(QNSPanelDelegate)
169
170@protocol QNSPanelDelegate
171@required
172- (void)onOkClicked;
173- (void)onCancelClicked;
174@end
175
176@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView
177
178@property (nonatomic, readonly) NSButton *okButton;
179@property (nonatomic, readonly) NSButton *cancelButton;
180@property (nonatomic, readonly) NSView *panelContents; // ARC: unretained, make it weak
181@property (nonatomic, assign) NSEdgeInsets panelContentsMargins;
182
183- (instancetype)initWithPanelDelegate:(id<QNSPanelDelegate>)panelDelegate;
184- (void)dealloc;
185
186- (NSButton *)createButtonWithTitle:(QPlatformDialogHelper::StandardButton)type;
187- (void)layout;
188
189@end
190
192
193// -------------------------------------------------------------------------
194
195// Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret:
196// - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
197// - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html
198template <typename T>
199struct objc_msgsend_requires_stret
200{ static const bool value =
201#if defined(Q_PROCESSOR_X86)
202 #define PLATFORM_USES_SEND_SUPER_STRET 1
203 // Any return value larger than two registers on i386/x86_64
204 sizeof(T) > sizeof(void*) * 2;
205#elif defined(Q_PROCESSOR_ARM_32)
206 #define PLATFORM_USES_SEND_SUPER_STRET 1
207 // Any return value larger than a single register on arm
208 sizeof(T) > sizeof(void*);
209#elif defined(Q_PROCESSOR_ARM_64)
210 #define PLATFORM_USES_SEND_SUPER_STRET 0
211 false; // Stret not used on arm64
212#endif
213};
214
215template <>
216struct objc_msgsend_requires_stret<void>
217{ static const bool value = false; };
218
219template <typename ReturnType, typename... Args>
220ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args)
221{
222 static_assert(!objc_msgsend_requires_stret<ReturnType>::value,
223 "The given return type requires stret on this platform");
224
225 typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...);
226 SuperFn superFn = reinterpret_cast<SuperFn>(objc_msgSendSuper);
227 objc_super sup = { receiver, [receiver superclass] };
228 return superFn(&sup, selector, args...);
229}
230
231#if PLATFORM_USES_SEND_SUPER_STRET
232template <typename ReturnType, typename... Args>
233ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args)
234{
235 static_assert(objc_msgsend_requires_stret<ReturnType>::value,
236 "The given return type does not use stret on this platform");
237
238 typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...);
239 SuperStretFn superStretFn = reinterpret_cast<SuperStretFn>(objc_msgSendSuper_stret);
240
241 objc_super sup = { receiver, [receiver superclass] };
242 ReturnType ret;
243 superStretFn(&ret, &sup, selector, args...);
244 return ret;
245}
246#endif
247
248template<typename... Args>
249class QSendSuperHelper {
250public:
251 QSendSuperHelper(id receiver, SEL sel, Args... args)
252 : m_receiver(receiver), m_selector(sel), m_args(std::make_tuple(args...)), m_sent(false)
253 {
254 }
255
256 ~QSendSuperHelper()
257 {
258 if (!m_sent)
259 msgSendSuper<void>(m_args);
260 }
261
262 template <typename ReturnType>
263 operator ReturnType()
264 {
265#if defined(QT_DEBUG)
266 Method method = class_getInstanceMethod(object_getClass(m_receiver), m_selector);
267 char returnTypeEncoding[256];
268 method_getReturnType(method, returnTypeEncoding, sizeof(returnTypeEncoding));
269 NSUInteger alignedReturnTypeSize = 0;
270 NSGetSizeAndAlignment(returnTypeEncoding, nullptr, &alignedReturnTypeSize);
271 Q_ASSERT(alignedReturnTypeSize == sizeof(ReturnType));
272#endif
273 m_sent = true;
274 return msgSendSuper<ReturnType>(m_args);
275 }
276
277private:
278 template <typename ReturnType, bool V>
279 using if_requires_stret = typename std::enable_if<objc_msgsend_requires_stret<ReturnType>::value == V, ReturnType>::type;
280
281 template <typename ReturnType, int... Is>
282 if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
283 {
284 return qt_msgSendSuper<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
285 }
286
287#if PLATFORM_USES_SEND_SUPER_STRET
288 template <typename ReturnType, int... Is>
289 if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
290 {
291 return qt_msgSendSuper_stret<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
292 }
293#endif
294
295 template <typename ReturnType>
296 ReturnType msgSendSuper(std::tuple<Args...>& args)
297 {
298 return msgSendSuper<ReturnType>(args, QtPrivate::makeIndexSequence<sizeof...(Args)>{});
299 }
300
301 id m_receiver;
302 SEL m_selector;
303 std::tuple<Args...> m_args;
304 bool m_sent;
305};
306
307template<typename... Args>
308QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, Args... args)
309{
310 return QSendSuperHelper<Args...>(receiver, selector, args...);
311}
312
313// Same as calling super, but the super_class field resolved at runtime instead of compile time
314#define qt_objcDynamicSuper(...) qt_objcDynamicSuperHelper(self, _cmd, ##__VA_ARGS__)
315
316// -------------------------------------------------------------------------
317
318struct InputMethodQueryResult : public QHash<int, QVariant>
319{
320 operator bool() { return !isEmpty(); }
321};
322
323InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries = Qt::ImEnabled);
324
325// -------------------------------------------------------------------------
326
327struct KeyEvent
328{
329 ulong timestamp = 0;
331
333 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
335 bool isRepeat = false;
336
337 // Scan codes are hardware dependent codes for each key. There is no way to get these
338 // from Carbon or Cocoa, so leave it 0, as documented in QKeyEvent::nativeScanCode().
339 static const quint32 nativeScanCode = 0;
340
341 quint32 nativeVirtualKey = 0;
342 NSEventModifierFlags nativeModifiers = 0;
343
344 KeyEvent(NSEvent *nsevent);
345 bool sendWindowSystemEvent(QWindow *window) const;
346};
347
349
350// -------------------------------------------------------------------------
351
352QDebug operator<<(QDebug, const NSRange &);
354
355#endif // __OBJC__
356
357#endif //QCOCOAHELPERS_H
358
\inmodule QtCore
Definition qbytearray.h:57
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
\inmodule QtCore
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore
Definition qobject.h:90
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
The QPlatformDialogHelper class allows for platform-specific customization of dialogs.
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
\inmodule QtGui
Definition qwindow.h:63
EGLImageKHR int int EGLuint64KHR * modifiers
QString text
double e
rect
[4]
Combined button and popup list for selecting options.
InvokeGenSeq< GenSeq< N > > makeIndexSequence
@ ImEnabled
MouseButton
Definition qnamespace.h:55
@ Key_unknown
@ NoModifier
DropAction
Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
QNSView * qnsview_cast(NSView *view)
Returns the view cast to a QNSview if possible.
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
Returns the QEvent::Type that corresponds to an NSEvent.type.
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
QString qt_mac_applicationName()
QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference)
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
Returns the Qt::Button that corresponds to an NSEvent.buttonNumber.
QStringList qt_mac_NSArrayToQStringList(NSArray< NSString * > *array)
void qt_mac_transformProccessToForegroundApplication()
NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
QString qt_mac_removeAmpersandEscapes(QString s)
InputMethodQueryResult queryInputMethod(QObject *object, Qt::InputMethodQueries queries)
NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
NSMutableArray< NSString * > * qt_mac_QStringListToNSMutableArray(const QStringList &list)
Qt::MouseButtons currentlyPressedMouseButtons()
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
long NSInteger
unsigned long NSUInteger
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
Definition qcore_mac_p.h:57
#define Q_FORWARD_DECLARE_OBJC_CLASS(classname)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
GLuint64 key
GLboolean r
[2]
GLuint GLuint end
GLuint object
[3]
GLint reference
GLenum type
GLenum target
struct _cl_event * event
GLuint GLuint GLuint GLuint arg1
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
GLdouble s
[6]
Definition qopenglext.h:235
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define QT_MANGLE_NAMESPACE(name)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
unsigned int quint32
Definition qtypes.h:45
unsigned long ulong
Definition qtypes.h:30
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
QFileSelector selector
[1]
QDataStream & operator<<(QDataStream &out, const MyClass &myObj)
[4]
QVBoxLayout * layout
sem release()
aWidget window() -> setWindowTitle("New Window Title")
[2]
QQuickView * view
[0]
QJSValueList args