Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcocoaapplication.mm
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/****************************************************************************
5**
6** Copyright (c) 2007-2008, Apple, Inc.
7**
8** All rights reserved.
9**
10** Redistribution and use in source and binary forms, with or without
11** modification, are permitted provided that the following conditions are met:
12**
13** * Redistributions of source code must retain the above copyright notice,
14** this list of conditions and the following disclaimer.
15**
16** * Redistributions in binary form must reproduce the above copyright notice,
17** this list of conditions and the following disclaimer in the documentation
18** and/or other materials provided with the distribution.
19**
20** * Neither the name of Apple, Inc. nor the names of its contributors
21** may be used to endorse or promote products derived from this software
22** without specific prior written permission.
23**
24** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35**
36****************************************************************************/
37
38#include <AppKit/AppKit.h>
39
40#include "qcocoaapplication.h"
41
42#include "qcocoaintrospection.h"
44#include "qcocoahelpers.h"
45#include "qcocoawindow.h"
46#include <qguiapplication.h>
47#include <qdebug.h>
48
50
51static void qt_sendPostedMessage(NSEvent *event)
52{
53 // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5!
54 // That is why we need to split the address in two parts:
55 quint64 lower = [event data1];
56 quint64 upper = [event data2];
57 QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32));
58 // Special case for convenience: if the argument is an NSNumber, we unbox it directly.
59 // Use NSValue instead if this behaviour is unwanted.
60 id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 longValue] : args->arg1;
61 id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 longValue] : args->arg2;
62 switch (args->argCount) {
63 case 0:
64 [args->target performSelector:args->selector];
65 break;
66 case 1:
67 [args->target performSelector:args->selector withObject:a1];
68 break;
69 case 3:
70 [args->target performSelector:args->selector withObject:a1 withObject:a2];
71 break;
72 }
73
74 delete args;
75}
76
77static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSEvent");
78
79static bool qt_filterEvent(NSEvent *event)
80{
81 if (qApp && qApp->eventDispatcher()->
82 filterNativeEvent(q_macLocalEventType, static_cast<void*>(event), nullptr))
83 return true;
84
85 if (event.type == NSEventTypeApplicationDefined) {
86 switch (static_cast<short>(event.subtype)) {
87 case QtCocoaEventSubTypePostMessage:
89 return true;
90 default:
91 break;
92 }
93 }
94
95 return false;
96}
97
99{
100 // Cocoa is known for not sending key up events for key
101 // equivalents, regardless of whether it's an actual
102 // recognized key equivalent. We decide to force fate
103 // and forward the key event to the key (focus) window.
104 // However, non-Qt windows will not (and should not) get
105 // any special treatment, only QWindow-owned NSWindows.
106 if (event.type == NSEventTypeKeyUp && (event.modifierFlags & NSEventModifierFlagCommand)) {
107 NSWindow *targetWindow = event.window;
108 if ([targetWindow.class conformsToProtocol:@protocol(QNSWindowProtocol)])
109 [targetWindow sendEvent:event];
110 }
111}
112
113@implementation QNSApplication
114
115- (void)QT_MANGLE_NAMESPACE(qt_sendEvent_original):(NSEvent *)event
116{
118 // This method will only be used as a signature
119 // template for the method we add into NSApplication
120 // containing the original [NSApplication sendEvent:] implementation
121}
122
123- (void)QT_MANGLE_NAMESPACE(qt_sendEvent_replacement):(NSEvent *)event
124{
125 // This method (or its implementation to be precise) will
126 // be called instead of sendEvent if redirection occurs.
127 // 'self' will then be an instance of NSApplication
128 // (and not QNSApplication)
129 if (!qt_filterEvent(event)) {
130 [self QT_MANGLE_NAMESPACE(qt_sendEvent_original):event];
132 }
133}
134
135- (void)sendEvent:(NSEvent *)event
136{
137 // This method will be called if
138 // no redirection occurs
139 if (!qt_filterEvent(event)) {
140 [super sendEvent:event];
142 }
143}
144
145@end
146
148
150{
152 // In a plugin we cannot chain sendEvent hooks: a second plugin could
153 // store the implementation of the first, which during the program flow
154 // can be unloaded.
155 return;
156
157 if ([NSApp isMemberOfClass:[QNSApplication class]]) {
158 // No need to change implementation since Qt
159 // already controls a subclass of NSApplication
160 return;
161 }
162
163 // Change the implementation of [NSApplication sendEvent] to the
164 // implementation of qt_sendEvent_replacement found in QNSApplication.
165 // And keep the old implementation that gets overwritten inside a new
166 // method 'qt_sendEvent_original' that we add to NSApplication
168 [NSApplication class],
169 @selector(sendEvent:),
170 [QNSApplication class],
171 @selector(QT_MANGLE_NAMESPACE(qt_sendEvent_replacement):),
172 @selector(QT_MANGLE_NAMESPACE(qt_sendEvent_original):));
173 }
174
176{
178 return;
179
180
181 qt_cocoa_change_back_implementation([NSApplication class],
182 @selector(sendEvent:),
183 @selector(QT_MANGLE_NAMESPACE(qt_sendEvent_original):));
184}
185
\inmodule QtCore
Definition qbytearray.h:57
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
Combined button and popup list for selecting options.
@ AA_PluginApplication
Definition qnamespace.h:430
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
static bool qt_filterEvent(NSEvent *event)
static QT_USE_NAMESPACE void qt_sendPostedMessage(NSEvent *event)
QT_BEGIN_NAMESPACE void qt_redirectNSApplicationSendEvent()
static void qt_maybeSendKeyEquivalentUpEvent(NSEvent *event)
void qt_resetNSApplicationSendEvent()
static const QByteArray q_macLocalEventType
QT_BEGIN_NAMESPACE void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel=nil, SEL backupSel=nil)
void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel)
#define qApp
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
struct _cl_event * event
#define a2
#define a1
#define QT_MANGLE_NAMESPACE(name)
#define Q_UNUSED(x)
unsigned long long quint64
Definition qtypes.h:61
QJSValueList args