Revert Mac event loop changes.
"Make QGuiApplication::exec() run within NSApplicationMain()" "Make Qt process native and timer events on Cocoa applications" "Cocoa: Fix QFontDialog, QColorDialog auto-tests" This reverts commits 1e14762b8d79118540bd09a84dd3e48f4f5e113e e4b2a0b4bab2a17a65fedafe9bae50af1fe019f6 df7944e7d7dd8b2bbccbd639eff0ab09745d6cc3 Change-Id: I80b65b5ee0297b090f807bd420664233dfc44f7b Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
585758389c
commit
8fc97fdfc7
@ -1,20 +1,6 @@
|
|||||||
load(default_post)
|
load(default_post)
|
||||||
!no_objective_c:CONFIG += objective_c
|
!no_objective_c:CONFIG += objective_c
|
||||||
|
|
||||||
|
|
||||||
equals(TEMPLATE, app):qt: {
|
|
||||||
deps = $$replace(QT, -private$, )
|
|
||||||
deps = $$resolve_depends(deps, "QT.", ".depends" ".private_depends" ".run_depends")
|
|
||||||
contains(deps, gui): {
|
|
||||||
DEFINES += QT_NEEDS_QMAIN
|
|
||||||
CONFIG += link_prl
|
|
||||||
# When CI'ing Qt we still need to link against libqtcocoamain.a, even before deployment.
|
|
||||||
# Hence the /get variable, suffix which looks for the libraries location effective path.
|
|
||||||
QMAKE_LIBDIR += $$[QT_INSTALL_LIBS/get]
|
|
||||||
QMAKE_LIBS += -lqtcocoamain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qt:!isEmpty(QT_CONFIG) {
|
qt:!isEmpty(QT_CONFIG) {
|
||||||
# Pick a suitable default architecture for qmake-based applications.
|
# Pick a suitable default architecture for qmake-based applications.
|
||||||
# If the Qt package contains one of x86 and x86_64, pick that one. If it
|
# If the Qt package contains one of x86 and x86_64, pick that one. If it
|
||||||
|
@ -1,7 +1,109 @@
|
|||||||
TEMPLATE = subdirs
|
TARGET = qcocoa
|
||||||
|
|
||||||
cocoamain.file = cocoamain.pro
|
PLUGIN_TYPE = platforms
|
||||||
cocoaplugin.file = cocoaplugin.pro
|
PLUGIN_CLASS_NAME = QCocoaIntegrationPlugin
|
||||||
|
load(qt_plugin)
|
||||||
|
|
||||||
SUBDIRS = cocoamain cocoaplugin
|
OBJECTIVE_SOURCES += main.mm \
|
||||||
|
qcocoaintegration.mm \
|
||||||
|
qcocoatheme.mm \
|
||||||
|
qcocoabackingstore.mm \
|
||||||
|
qcocoawindow.mm \
|
||||||
|
qnsview.mm \
|
||||||
|
qnsviewaccessibility.mm \
|
||||||
|
qcocoaautoreleasepool.mm \
|
||||||
|
qnswindowdelegate.mm \
|
||||||
|
qcocoaglcontext.mm \
|
||||||
|
qcocoanativeinterface.mm \
|
||||||
|
qcocoaeventdispatcher.mm \
|
||||||
|
qcocoaapplicationdelegate.mm \
|
||||||
|
qcocoaapplication.mm \
|
||||||
|
qcocoamenu.mm \
|
||||||
|
qcocoamenuitem.mm \
|
||||||
|
qcocoamenubar.mm \
|
||||||
|
qcocoamenuloader.mm \
|
||||||
|
qcocoahelpers.mm \
|
||||||
|
qmultitouch_mac.mm \
|
||||||
|
qcocoaaccessibilityelement.mm \
|
||||||
|
qcocoaaccessibility.mm \
|
||||||
|
qcocoacolordialoghelper.mm \
|
||||||
|
qcocoafiledialoghelper.mm \
|
||||||
|
qcocoafontdialoghelper.mm \
|
||||||
|
qcocoacursor.mm \
|
||||||
|
qcocoaclipboard.mm \
|
||||||
|
qcocoadrag.mm \
|
||||||
|
qmacclipboard.mm \
|
||||||
|
qmacmime.mm \
|
||||||
|
qcocoasystemsettings.mm \
|
||||||
|
qcocoainputcontext.mm \
|
||||||
|
qcocoaservices.mm \
|
||||||
|
qcocoasystemtrayicon.mm \
|
||||||
|
qcocoaintrospection.mm \
|
||||||
|
qcocoakeymapper.mm \
|
||||||
|
|
||||||
|
SOURCES += messages.cpp
|
||||||
|
|
||||||
|
HEADERS += qcocoaintegration.h \
|
||||||
|
qcocoatheme.h \
|
||||||
|
qcocoabackingstore.h \
|
||||||
|
qcocoawindow.h \
|
||||||
|
qnsview.h \
|
||||||
|
qcocoaautoreleasepool.h \
|
||||||
|
qnswindowdelegate.h \
|
||||||
|
qcocoaglcontext.h \
|
||||||
|
qcocoanativeinterface.h \
|
||||||
|
qcocoaeventdispatcher.h \
|
||||||
|
qcocoaapplicationdelegate.h \
|
||||||
|
qcocoaapplication.h \
|
||||||
|
qcocoamenu.h \
|
||||||
|
qcocoamenuitem.h \
|
||||||
|
qcocoamenubar.h \
|
||||||
|
qcocoamenuloader.h \
|
||||||
|
qcocoahelpers.h \
|
||||||
|
qmultitouch_mac_p.h \
|
||||||
|
qcocoaaccessibilityelement.h \
|
||||||
|
qcocoaaccessibility.h \
|
||||||
|
qcocoacolordialoghelper.h \
|
||||||
|
qcocoafiledialoghelper.h \
|
||||||
|
qcocoafontdialoghelper.h \
|
||||||
|
qcocoacursor.h \
|
||||||
|
qcocoaclipboard.h \
|
||||||
|
qcocoadrag.h \
|
||||||
|
qmacclipboard.h \
|
||||||
|
qmacmime.h \
|
||||||
|
qcocoasystemsettings.h \
|
||||||
|
qcocoainputcontext.h \
|
||||||
|
qcocoaservices.h \
|
||||||
|
qcocoasystemtrayicon.h \
|
||||||
|
qcocoaintrospection.h \
|
||||||
|
qcocoakeymapper.h \
|
||||||
|
messages.h
|
||||||
|
|
||||||
|
RESOURCES += qcocoaresources.qrc
|
||||||
|
|
||||||
|
LIBS += -framework Cocoa -framework Carbon -framework IOKit
|
||||||
|
|
||||||
|
QT += core-private gui-private platformsupport-private
|
||||||
|
|
||||||
|
qtHaveModule(widgets) {
|
||||||
|
OBJECTIVE_SOURCES += \
|
||||||
|
qpaintengine_mac.mm \
|
||||||
|
qprintengine_mac.mm \
|
||||||
|
qcocoaprintersupport.mm \
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
qpaintengine_mac_p.h \
|
||||||
|
qprintengine_mac_p.h \
|
||||||
|
qcocoaprintersupport.h \
|
||||||
|
|
||||||
|
QT += widgets-private printsupport-private
|
||||||
|
}
|
||||||
|
|
||||||
|
OTHER_FILES += cocoa.json
|
||||||
|
|
||||||
|
# Acccessibility debug support
|
||||||
|
# DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
|
||||||
|
# include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri)
|
||||||
|
|
||||||
|
# Window debug support
|
||||||
|
#DEFINES += QT_COCOA_ENABLE_WINDOW_DEBUG
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# Additional Qt project file for qtmain lib on OS X
|
|
||||||
!macx:error("$$_FILE_ is intended only for OS X!")
|
|
||||||
|
|
||||||
TEMPLATE = lib
|
|
||||||
TARGET = qtcocoamain
|
|
||||||
DESTDIR = $$QT.core.libs
|
|
||||||
|
|
||||||
CONFIG += staticlib release
|
|
||||||
|
|
||||||
QT = core-private gui-private
|
|
||||||
LIBS += -framework Cocoa
|
|
||||||
|
|
||||||
HEADERS = qcocoaintrospection.h
|
|
||||||
|
|
||||||
OBJECTIVE_SOURCES = qcocoamain.mm \
|
|
||||||
qcocoaintrospection.mm
|
|
||||||
|
|
||||||
load(qt_installs)
|
|
||||||
load(qt_targets)
|
|
@ -1,109 +0,0 @@
|
|||||||
TARGET = qcocoa
|
|
||||||
|
|
||||||
PLUGIN_TYPE = platforms
|
|
||||||
PLUGIN_CLASS_NAME = QCocoaIntegrationPlugin
|
|
||||||
load(qt_plugin)
|
|
||||||
|
|
||||||
OBJECTIVE_SOURCES += main.mm \
|
|
||||||
qcocoaintegration.mm \
|
|
||||||
qcocoatheme.mm \
|
|
||||||
qcocoabackingstore.mm \
|
|
||||||
qcocoawindow.mm \
|
|
||||||
qnsview.mm \
|
|
||||||
qnsviewaccessibility.mm \
|
|
||||||
qcocoaautoreleasepool.mm \
|
|
||||||
qnswindowdelegate.mm \
|
|
||||||
qcocoaglcontext.mm \
|
|
||||||
qcocoanativeinterface.mm \
|
|
||||||
qcocoaeventdispatcher.mm \
|
|
||||||
qcocoaapplicationdelegate.mm \
|
|
||||||
qcocoaapplication.mm \
|
|
||||||
qcocoamenu.mm \
|
|
||||||
qcocoamenuitem.mm \
|
|
||||||
qcocoamenubar.mm \
|
|
||||||
qcocoamenuloader.mm \
|
|
||||||
qcocoahelpers.mm \
|
|
||||||
qmultitouch_mac.mm \
|
|
||||||
qcocoaaccessibilityelement.mm \
|
|
||||||
qcocoaaccessibility.mm \
|
|
||||||
qcocoacolordialoghelper.mm \
|
|
||||||
qcocoafiledialoghelper.mm \
|
|
||||||
qcocoafontdialoghelper.mm \
|
|
||||||
qcocoacursor.mm \
|
|
||||||
qcocoaclipboard.mm \
|
|
||||||
qcocoadrag.mm \
|
|
||||||
qmacclipboard.mm \
|
|
||||||
qmacmime.mm \
|
|
||||||
qcocoasystemsettings.mm \
|
|
||||||
qcocoainputcontext.mm \
|
|
||||||
qcocoaservices.mm \
|
|
||||||
qcocoasystemtrayicon.mm \
|
|
||||||
qcocoaintrospection.mm \
|
|
||||||
qcocoakeymapper.mm \
|
|
||||||
|
|
||||||
SOURCES += messages.cpp
|
|
||||||
|
|
||||||
HEADERS += qcocoaintegration.h \
|
|
||||||
qcocoatheme.h \
|
|
||||||
qcocoabackingstore.h \
|
|
||||||
qcocoawindow.h \
|
|
||||||
qnsview.h \
|
|
||||||
qcocoaautoreleasepool.h \
|
|
||||||
qnswindowdelegate.h \
|
|
||||||
qcocoaglcontext.h \
|
|
||||||
qcocoanativeinterface.h \
|
|
||||||
qcocoaeventdispatcher.h \
|
|
||||||
qcocoaapplicationdelegate.h \
|
|
||||||
qcocoaapplication.h \
|
|
||||||
qcocoamenu.h \
|
|
||||||
qcocoamenuitem.h \
|
|
||||||
qcocoamenubar.h \
|
|
||||||
qcocoamenuloader.h \
|
|
||||||
qcocoahelpers.h \
|
|
||||||
qmultitouch_mac_p.h \
|
|
||||||
qcocoaaccessibilityelement.h \
|
|
||||||
qcocoaaccessibility.h \
|
|
||||||
qcocoacolordialoghelper.h \
|
|
||||||
qcocoafiledialoghelper.h \
|
|
||||||
qcocoafontdialoghelper.h \
|
|
||||||
qcocoacursor.h \
|
|
||||||
qcocoaclipboard.h \
|
|
||||||
qcocoadrag.h \
|
|
||||||
qmacclipboard.h \
|
|
||||||
qmacmime.h \
|
|
||||||
qcocoasystemsettings.h \
|
|
||||||
qcocoainputcontext.h \
|
|
||||||
qcocoaservices.h \
|
|
||||||
qcocoasystemtrayicon.h \
|
|
||||||
qcocoaintrospection.h \
|
|
||||||
qcocoakeymapper.h \
|
|
||||||
messages.h
|
|
||||||
|
|
||||||
RESOURCES += qcocoaresources.qrc
|
|
||||||
|
|
||||||
LIBS += -framework Cocoa -framework Carbon -framework IOKit
|
|
||||||
|
|
||||||
QT += core-private gui-private platformsupport-private
|
|
||||||
|
|
||||||
qtHaveModule(widgets) {
|
|
||||||
OBJECTIVE_SOURCES += \
|
|
||||||
qpaintengine_mac.mm \
|
|
||||||
qprintengine_mac.mm \
|
|
||||||
qcocoaprintersupport.mm \
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
qpaintengine_mac_p.h \
|
|
||||||
qprintengine_mac_p.h \
|
|
||||||
qcocoaprintersupport.h \
|
|
||||||
|
|
||||||
QT += widgets-private printsupport-private
|
|
||||||
}
|
|
||||||
|
|
||||||
OTHER_FILES += cocoa.json
|
|
||||||
|
|
||||||
# Acccessibility debug support
|
|
||||||
# DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
|
|
||||||
# include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri)
|
|
||||||
|
|
||||||
# Window debug support
|
|
||||||
#DEFINES += QT_COCOA_ENABLE_WINDOW_DEBUG
|
|
@ -102,9 +102,13 @@
|
|||||||
|
|
||||||
- (void)qt_sendPostedMessage:(NSEvent *)event;
|
- (void)qt_sendPostedMessage:(NSEvent *)event;
|
||||||
- (BOOL)qt_filterEvent:(NSEvent *)event;
|
- (BOOL)qt_filterEvent:(NSEvent *)event;
|
||||||
- (BOOL)qt_filterOrSendEvent:(NSEvent *)event;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface QT_MANGLE_NAMESPACE(QNSApplication) : NSApplication {
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSApplication);
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
@ -83,8 +83,6 @@
|
|||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
static SEL qt_sendEvent_original_SEL = @selector(qt_sendEvent_original:);
|
|
||||||
|
|
||||||
@implementation NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
|
@implementation NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
|
||||||
|
|
||||||
- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu
|
- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu
|
||||||
@ -155,22 +153,34 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)qt_filterOrSendEvent:(NSEvent *)event
|
@end
|
||||||
{
|
|
||||||
if ([self qt_filterEvent:event])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Q_ASSERT_X([self respondsToSelector:qt_sendEvent_original_SEL], "qt_filterOrSendEvent:",
|
@implementation QNSApplication
|
||||||
"Running event loop before calling qt_redirectNSApplicationSendEvent()");
|
|
||||||
[self performSelector:qt_sendEvent_original_SEL withObject:event];
|
- (void)qt_sendEvent_original:(NSEvent *)event
|
||||||
return true;
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
// This method will only be used as a signature
|
||||||
|
// template for the method we add into NSApplication
|
||||||
|
// containing the original [NSApplication sendEvent:] implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)qt_sendEvent_replacement:(NSEvent *)event
|
- (void)qt_sendEvent_replacement:(NSEvent *)event
|
||||||
{
|
{
|
||||||
// This method (or its implementation to be precise) will
|
// This method (or its implementation to be precise) will
|
||||||
// be called instead of sendEvent: after redirection occurs.
|
// be called instead of sendEvent if redirection occurs.
|
||||||
[self qt_filterOrSendEvent:event];
|
// 'self' will then be an instance of NSApplication
|
||||||
|
// (and not QNSApplication)
|
||||||
|
if (![NSApp qt_filterEvent:event])
|
||||||
|
[self qt_sendEvent_original:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sendEvent:(NSEvent *)event
|
||||||
|
{
|
||||||
|
// This method will be called if
|
||||||
|
// no redirection occurs
|
||||||
|
if (![NSApp qt_filterEvent:event])
|
||||||
|
[super sendEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@ -179,16 +189,22 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
void qt_redirectNSApplicationSendEvent()
|
void qt_redirectNSApplicationSendEvent()
|
||||||
{
|
{
|
||||||
|
if ([NSApp isMemberOfClass:[QNSApplication class]]) {
|
||||||
|
// No need to change implementation since Qt
|
||||||
|
// already controls a subclass of NSApplication
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Change the implementation of [NSApplication sendEvent] to the
|
// Change the implementation of [NSApplication sendEvent] to the
|
||||||
// implementation of qt_sendEvent_replacement.
|
// implementation of qt_sendEvent_replacement found in QNSApplication.
|
||||||
// And keep the old implementation that gets overwritten inside a new
|
// And keep the old implementation that gets overwritten inside a new
|
||||||
// method 'qt_sendEvent_original' that we add to NSApplication
|
// method 'qt_sendEvent_original' that we add to NSApplication
|
||||||
qt_cocoa_change_implementation(
|
qt_cocoa_change_implementation(
|
||||||
[NSApplication class],
|
[NSApplication class],
|
||||||
@selector(sendEvent:),
|
@selector(sendEvent:),
|
||||||
[NSApplication class],
|
[QNSApplication class],
|
||||||
@selector(qt_sendEvent_replacement:),
|
@selector(qt_sendEvent_replacement:),
|
||||||
qt_sendEvent_original_SEL);
|
@selector(qt_sendEvent_original:));
|
||||||
}
|
}
|
||||||
|
|
||||||
void qt_resetNSApplicationSendEvent()
|
void qt_resetNSApplicationSendEvent()
|
||||||
|
@ -99,13 +99,15 @@
|
|||||||
NSMenu *dockMenu;
|
NSMenu *dockMenu;
|
||||||
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader;
|
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader;
|
||||||
NSObject <NSApplicationDelegate> *reflectionDelegate;
|
NSObject <NSApplicationDelegate> *reflectionDelegate;
|
||||||
|
bool inLaunch;
|
||||||
}
|
}
|
||||||
+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate;
|
+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate;
|
||||||
- (void)setDockMenu:(NSMenu *)newMenu;
|
- (void)setDockMenu:(NSMenu *)newMenu;
|
||||||
- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader;
|
- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader;
|
||||||
- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
|
- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
|
||||||
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate;
|
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate;
|
||||||
- (NSObject<NSApplicationDelegate> *)reflectionDelegate;
|
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
|
||||||
|
- (void) removeAppleEventHandlers;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate);
|
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate);
|
||||||
|
@ -101,6 +101,7 @@ static void cleanupCocoaApplicationDelegate()
|
|||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
|
inLaunch = true;
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(updateScreens:)
|
selector:@selector(updateScreens:)
|
||||||
@ -240,6 +241,55 @@ static void cleanupCocoaApplicationDelegate()
|
|||||||
return NSTerminateCancel;
|
return NSTerminateCancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) applicationWillFinishLaunching:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
Q_UNUSED(notification);
|
||||||
|
|
||||||
|
/*
|
||||||
|
From the Cocoa documentation: "A good place to install event handlers
|
||||||
|
is in the applicationWillFinishLaunching: method of the application
|
||||||
|
delegate. At that point, the Application Kit has installed its default
|
||||||
|
event handlers, so if you install a handler for one of the same events,
|
||||||
|
it will replace the Application Kit version."
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
If Qt is used as a plugin, we let the 3rd party application handle
|
||||||
|
events like quit and open file events. Otherwise, if we install our own
|
||||||
|
handlers, we easily end up breaking functionality the 3rd party
|
||||||
|
application depends on.
|
||||||
|
*/
|
||||||
|
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
|
||||||
|
[eventManager setEventHandler:self
|
||||||
|
andSelector:@selector(appleEventQuit:withReplyEvent:)
|
||||||
|
forEventClass:kCoreEventClass
|
||||||
|
andEventID:kAEQuitApplication];
|
||||||
|
[eventManager setEventHandler:self
|
||||||
|
andSelector:@selector(getUrl:withReplyEvent:)
|
||||||
|
forEventClass:kInternetEventClass
|
||||||
|
andEventID:kAEGetURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
// called by QCocoaIntegration's destructor before resetting the application delegate to nil
|
||||||
|
- (void) removeAppleEventHandlers
|
||||||
|
{
|
||||||
|
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
|
||||||
|
[eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
|
||||||
|
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||||
|
{
|
||||||
|
Q_UNUSED(aNotification);
|
||||||
|
inLaunch = false;
|
||||||
|
// qt_release_apple_event_handler();
|
||||||
|
|
||||||
|
|
||||||
|
// Insert code here to initialize your application
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
|
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
|
||||||
{
|
{
|
||||||
Q_UNUSED(filenames);
|
Q_UNUSED(filenames);
|
||||||
@ -247,6 +297,14 @@ static void cleanupCocoaApplicationDelegate()
|
|||||||
|
|
||||||
for (NSString *fileName in filenames) {
|
for (NSString *fileName in filenames) {
|
||||||
QString qtFileName = QCFString::toQString(fileName);
|
QString qtFileName = QCFString::toQString(fileName);
|
||||||
|
if (inLaunch) {
|
||||||
|
// We need to be careful because Cocoa will be nice enough to take
|
||||||
|
// command line arguments and send them to us as events. Given the history
|
||||||
|
// of Qt Applications, this will result in behavior people don't want, as
|
||||||
|
// they might be doing the opening themselves with the command line parsing.
|
||||||
|
if (qApp->arguments().contains(qtFileName))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
QWindowSystemInterface::handleFileOpenEvent(qtFileName);
|
QWindowSystemInterface::handleFileOpenEvent(qtFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,11 +367,6 @@ static void cleanupCocoaApplicationDelegate()
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSObject<NSApplicationDelegate> *)reflectionDelegate
|
|
||||||
{
|
|
||||||
return reflectionDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
|
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
|
||||||
{
|
{
|
||||||
[oldDelegate retain];
|
[oldDelegate retain];
|
||||||
@ -347,6 +400,20 @@ static void cleanupCocoaApplicationDelegate()
|
|||||||
[self doesNotRecognizeSelector:invocationSelector];
|
[self doesNotRecognizeSelector:invocationSelector];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
||||||
|
{
|
||||||
|
Q_UNUSED(replyEvent);
|
||||||
|
NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||||
|
QWindowSystemInterface::handleFileOpenEvent(QCFString::toQString(urlString));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
Q_UNUSED(replyEvent);
|
||||||
|
[NSApp terminate:self];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)qtDispatcherToQAction:(id)sender
|
- (void)qtDispatcherToQAction:(id)sender
|
||||||
{
|
{
|
||||||
Q_UNUSED(sender);
|
Q_UNUSED(sender);
|
||||||
|
@ -59,8 +59,6 @@ public:
|
|||||||
|
|
||||||
void setCurrentColor(const QColor&);
|
void setCurrentColor(const QColor&);
|
||||||
QColor currentColor() const;
|
QColor currentColor() const;
|
||||||
|
|
||||||
bool event(QEvent *);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -161,10 +161,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
|
|||||||
|
|
||||||
- (void)closePanel
|
- (void)closePanel
|
||||||
{
|
{
|
||||||
if (mDialogIsExecuting) {
|
|
||||||
mDialogIsExecuting = false;
|
|
||||||
[NSApp stopModal];
|
|
||||||
}
|
|
||||||
[mColorPanel close];
|
[mColorPanel close];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,22 +488,6 @@ QColor QCocoaColorDialogHelper::currentColor() const
|
|||||||
return sharedColorPanel()->currentColor();
|
return sharedColorPanel()->currentColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QCocoaColorDialogHelper::event(QEvent *e)
|
|
||||||
{
|
|
||||||
if (e->type() == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
|
|
||||||
if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return) {
|
|
||||||
emit accept();
|
|
||||||
return true;
|
|
||||||
} else if (ke->key() == Qt::Key_Escape) {
|
|
||||||
emit reject();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QT_NO_COLORDIALOG
|
#endif // QT_NO_COLORDIALOG
|
||||||
|
@ -162,6 +162,8 @@ public:
|
|||||||
bool blockSendPostedEvents;
|
bool blockSendPostedEvents;
|
||||||
// The following variables help organizing modal sessions:
|
// The following variables help organizing modal sessions:
|
||||||
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
|
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
|
||||||
|
bool currentExecIsNSAppRun;
|
||||||
|
bool nsAppRunCalledByQt;
|
||||||
bool cleanupModalSessionsNeeded;
|
bool cleanupModalSessionsNeeded;
|
||||||
NSModalSession currentModalSessionCached;
|
NSModalSession currentModalSessionCached;
|
||||||
NSModalSession currentModalSession();
|
NSModalSession currentModalSession();
|
||||||
@ -173,6 +175,7 @@ public:
|
|||||||
|
|
||||||
void cancelWaitForMoreEvents();
|
void cancelWaitForMoreEvents();
|
||||||
void maybeCancelWaitForMoreEvents();
|
void maybeCancelWaitForMoreEvents();
|
||||||
|
void ensureNSAppInitialized();
|
||||||
|
|
||||||
QCFSocketNotifier cfSocketNotifier;
|
QCFSocketNotifier cfSocketNotifier;
|
||||||
QList<void *> queuedUserInputEvents; // NSEvent *
|
QList<void *> queuedUserInputEvents; // NSEvent *
|
||||||
|
@ -86,13 +86,20 @@
|
|||||||
#include "private/qthread_p.h"
|
#include "private/qthread_p.h"
|
||||||
#include "private/qguiapplication_p.h"
|
#include "private/qguiapplication_p.h"
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include "qcocoahelpers.h"
|
|
||||||
#include "qcocoaapplication.h"
|
#undef slots
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QtCocoaEventSubTypeWakeup = SHRT_MAX,
|
||||||
|
QtCocoaEventSubTypePostMessage = SHRT_MAX-1
|
||||||
|
};
|
||||||
|
|
||||||
static inline CFRunLoopRef mainRunLoop()
|
static inline CFRunLoopRef mainRunLoop()
|
||||||
{
|
{
|
||||||
return CFRunLoopGetMain();
|
return CFRunLoopGetMain();
|
||||||
@ -111,6 +118,11 @@ static Boolean runLoopSourceEqualCallback(const void *info1, const void *info2)
|
|||||||
void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void *info)
|
void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void *info)
|
||||||
{
|
{
|
||||||
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
|
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
|
||||||
|
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
|
||||||
|
// processEvents() was called "manually," ignore this source for now
|
||||||
|
d->maybeCancelWaitForMoreEvents();
|
||||||
|
return;
|
||||||
|
}
|
||||||
CFRunLoopSourceSignal(d->activateTimersSourceRef);
|
CFRunLoopSourceSignal(d->activateTimersSourceRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,17 +377,53 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
if (!excludeUserEvents) {
|
if (!excludeUserEvents) {
|
||||||
while (!d->queuedUserInputEvents.isEmpty()) {
|
while (!d->queuedUserInputEvents.isEmpty()) {
|
||||||
event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
|
event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
|
||||||
if ([NSApp qt_filterOrSendEvent:event])
|
if (!filterNativeEvent("NSEvent", event, 0)) {
|
||||||
|
[NSApp sendEvent:event];
|
||||||
retVal = true;
|
retVal = true;
|
||||||
|
}
|
||||||
[event release];
|
[event release];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// If Qt is used as a plugin, or as an extension in a native cocoa
|
||||||
|
// application, we should not run or stop NSApplication; This will be
|
||||||
|
// done from the application itself. And if processEvents is called
|
||||||
|
// manually (rather than from a QEventLoop), we cannot enter a tight
|
||||||
|
// loop and block this call, but instead we need to return after one flush.
|
||||||
|
// Finally, if we are to exclude user input events, we cannot call [NSApp run]
|
||||||
|
// as we then loose control over which events gets dispatched:
|
||||||
|
const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
|
||||||
|
const bool canExec_Qt = (!excludeUserEvents
|
||||||
|
&& ((d->processEventsFlags & QEventLoop::DialogExec)
|
||||||
|
|| (d->processEventsFlags & QEventLoop::EventLoopExec)));
|
||||||
|
|
||||||
|
if (canExec_Qt && canExec_3rdParty) {
|
||||||
|
// We can use exec-mode, meaning that we can stay in a tight loop until
|
||||||
|
// interrupted. This is mostly an optimization, but it allow us to use
|
||||||
|
// [NSApp run], which is the normal code path for cocoa applications.
|
||||||
|
if (NSModalSession session = d->currentModalSession()) {
|
||||||
|
QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
|
||||||
|
while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
|
||||||
|
qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode);
|
||||||
|
|
||||||
|
if (!d->interrupt && session == d->currentModalSessionCached) {
|
||||||
|
// Someone called [NSApp stopModal:] from outside the event
|
||||||
|
// dispatcher (e.g to stop a native dialog). But that call wrongly stopped
|
||||||
|
// 'session' as well. As a result, we need to restart all internal sessions:
|
||||||
|
d->temporarilyStopAllModalSessions();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d->nsAppRunCalledByQt = true;
|
||||||
|
QBoolBlocker execGuard(d->currentExecIsNSAppRun, true);
|
||||||
|
[NSApp run];
|
||||||
|
}
|
||||||
|
retVal = true;
|
||||||
|
} else {
|
||||||
int lastSerialCopy = d->lastSerial;
|
int lastSerialCopy = d->lastSerial;
|
||||||
bool hadModalSession = d->currentModalSessionCached != 0;
|
bool hadModalSession = d->currentModalSessionCached != 0;
|
||||||
// We cannot block the thread (and run in a tight loop).
|
// We cannot block the thread (and run in a tight loop).
|
||||||
// Instead we will process all current pending events and return.
|
// Instead we will process all current pending events and return.
|
||||||
|
d->ensureNSAppInitialized();
|
||||||
if (NSModalSession session = d->currentModalSession()) {
|
if (NSModalSession session = d->currentModalSession()) {
|
||||||
// INVARIANT: a modal window is executing.
|
// INVARIANT: a modal window is executing.
|
||||||
if (!excludeUserEvents) {
|
if (!excludeUserEvents) {
|
||||||
@ -396,9 +444,9 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
// this case, we need more control over which events gets dispatched, and
|
// this case, we need more control over which events gets dispatched, and
|
||||||
// cannot use [NSApp runModalSession:session]:
|
// cannot use [NSApp runModalSession:session]:
|
||||||
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||||
untilDate:nil
|
untilDate:nil
|
||||||
inMode:NSModalPanelRunLoopMode
|
inMode:NSModalPanelRunLoopMode
|
||||||
dequeue:YES];
|
dequeue: YES];
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
if (IsMouseOrKeyEvent(event)) {
|
if (IsMouseOrKeyEvent(event)) {
|
||||||
@ -406,16 +454,18 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
d->queuedUserInputEvents.append(event);
|
d->queuedUserInputEvents.append(event);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ([NSApp qt_filterOrSendEvent:event])
|
if (!filterNativeEvent("NSEvent", event, 0)) {
|
||||||
|
[NSApp sendEvent:event];
|
||||||
retVal = true;
|
retVal = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (!d->interrupt && event != nil);
|
} while (!d->interrupt && event != nil);
|
||||||
} else do {
|
} else do {
|
||||||
// INVARIANT: No modal window is executing.
|
// INVARIANT: No modal window is executing.
|
||||||
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||||
untilDate:nil
|
untilDate:nil
|
||||||
inMode:NSDefaultRunLoopMode
|
inMode:NSDefaultRunLoopMode
|
||||||
dequeue:YES];
|
dequeue: YES];
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
if (flags & QEventLoop::ExcludeUserInputEvents) {
|
if (flags & QEventLoop::ExcludeUserInputEvents) {
|
||||||
@ -425,8 +475,10 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ([NSApp qt_filterOrSendEvent:event])
|
if (!filterNativeEvent("NSEvent", event, 0)) {
|
||||||
|
[NSApp sendEvent:event];
|
||||||
retVal = true;
|
retVal = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (!d->interrupt && event != nil);
|
} while (!d->interrupt && event != nil);
|
||||||
|
|
||||||
@ -505,6 +557,26 @@ void QCocoaEventDispatcher::wakeUp()
|
|||||||
QEventDispatcherMac Implementation
|
QEventDispatcherMac Implementation
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void QCocoaEventDispatcherPrivate::ensureNSAppInitialized()
|
||||||
|
{
|
||||||
|
// Some elements in Cocoa require NSApplication to be running before
|
||||||
|
// they get fully initialized, in particular the menu bar. This
|
||||||
|
// function is intended for cases where a dialog is told to execute before
|
||||||
|
// QGuiApplication::exec is called, or the application spins the events loop
|
||||||
|
// manually rather than calling QGuiApplication:exec.
|
||||||
|
// The function makes sure that NSApplication starts running, but stops
|
||||||
|
// it again as soon as the send posted events callback is called. That way
|
||||||
|
// we let Cocoa finish the initialization it seems to need. We'll only
|
||||||
|
// apply this trick at most once for any application, and we avoid doing it
|
||||||
|
// for the common case where main just starts QGuiApplication::exec.
|
||||||
|
if (nsAppRunCalledByQt || [NSApp isRunning])
|
||||||
|
return;
|
||||||
|
nsAppRunCalledByQt = true;
|
||||||
|
QBoolBlocker block1(interrupt, true);
|
||||||
|
QBoolBlocker block2(currentExecIsNSAppRun, true);
|
||||||
|
[NSApp run];
|
||||||
|
}
|
||||||
|
|
||||||
void QCocoaEventDispatcherPrivate::temporarilyStopAllModalSessions()
|
void QCocoaEventDispatcherPrivate::temporarilyStopAllModalSessions()
|
||||||
{
|
{
|
||||||
// Flush, and Stop, all created modal session, and as
|
// Flush, and Stop, all created modal session, and as
|
||||||
@ -549,6 +621,7 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
|
|||||||
if (!nswindow)
|
if (!nswindow)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ensureNSAppInitialized();
|
||||||
QBoolBlocker block1(blockSendPostedEvents, true);
|
QBoolBlocker block1(blockSendPostedEvents, true);
|
||||||
info.nswindow = nswindow;
|
info.nswindow = nswindow;
|
||||||
[(NSWindow*) info.nswindow retain];
|
[(NSWindow*) info.nswindow retain];
|
||||||
@ -693,6 +766,8 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
|
|||||||
: processEventsFlags(0),
|
: processEventsFlags(0),
|
||||||
runLoopTimerRef(0),
|
runLoopTimerRef(0),
|
||||||
blockSendPostedEvents(false),
|
blockSendPostedEvents(false),
|
||||||
|
currentExecIsNSAppRun(false),
|
||||||
|
nsAppRunCalledByQt(false),
|
||||||
cleanupModalSessionsNeeded(false),
|
cleanupModalSessionsNeeded(false),
|
||||||
currentModalSessionCached(0),
|
currentModalSessionCached(0),
|
||||||
lastSerial(-1),
|
lastSerial(-1),
|
||||||
@ -783,8 +858,19 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
|
|||||||
if (cleanupModalSessionsNeeded)
|
if (cleanupModalSessionsNeeded)
|
||||||
cleanupModalSessions();
|
cleanupModalSessions();
|
||||||
|
|
||||||
if (interrupt)
|
if (interrupt) {
|
||||||
|
if (currentExecIsNSAppRun) {
|
||||||
|
// The event dispatcher has been interrupted. But since
|
||||||
|
// [NSApplication run] is running the event loop, we
|
||||||
|
// delayed stopping it until now (to let cocoa process
|
||||||
|
// pending cocoa events first).
|
||||||
|
if (currentModalSessionCached)
|
||||||
|
temporarilyStopAllModalSessions();
|
||||||
|
[NSApp stop:NSApp];
|
||||||
|
cancelWaitForMoreEvents();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int serial = serialNumber.load();
|
int serial = serialNumber.load();
|
||||||
if (!threadData->canWait || (serial != lastSerial)) {
|
if (!threadData->canWait || (serial != lastSerial)) {
|
||||||
@ -805,6 +891,11 @@ void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
|
|||||||
void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
|
void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
|
||||||
{
|
{
|
||||||
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
|
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
|
||||||
|
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
|
||||||
|
// processEvents() was called "manually," ignore this source for now
|
||||||
|
d->maybeCancelWaitForMoreEvents();
|
||||||
|
return;
|
||||||
|
}
|
||||||
d->processPostedEvents();
|
d->processPostedEvents();
|
||||||
d->maybeCancelWaitForMoreEvents();
|
d->maybeCancelWaitForMoreEvents();
|
||||||
}
|
}
|
||||||
|
@ -203,10 +203,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
|
|||||||
|
|
||||||
- (void)closePanel
|
- (void)closePanel
|
||||||
{
|
{
|
||||||
if (mDialogIsExecuting) {
|
|
||||||
mDialogIsExecuting = false;
|
|
||||||
[NSApp stopModal];
|
|
||||||
}
|
|
||||||
[mFontPanel close];
|
[mFontPanel close];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ QCocoaIntegration::QCocoaIntegration()
|
|||||||
|
|
||||||
qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false);
|
qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false);
|
||||||
|
|
||||||
NSApplication *cocoaApplication = NSApp;
|
NSApplication *cocoaApplication = [QNSApplication sharedApplication];
|
||||||
qt_redirectNSApplicationSendEvent();
|
qt_redirectNSApplicationSendEvent();
|
||||||
|
|
||||||
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
|
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
|
||||||
@ -280,8 +280,9 @@ QCocoaIntegration::~QCocoaIntegration()
|
|||||||
if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
|
if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
|
||||||
// remove the apple event handlers installed by QCocoaApplicationDelegate
|
// remove the apple event handlers installed by QCocoaApplicationDelegate
|
||||||
QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
|
QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
|
||||||
|
[delegate removeAppleEventHandlers];
|
||||||
// reset the application delegate
|
// reset the application delegate
|
||||||
[[NSApplication sharedApplication] setDelegate:[delegate reflectionDelegate]];
|
[[NSApplication sharedApplication] setDelegate: 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the clipboard integration and destroy mime type converters.
|
// Delete the clipboard integration and destroy mime type converters.
|
||||||
|
@ -79,33 +79,43 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel)
|
void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel)
|
||||||
{
|
{
|
||||||
// The following code replaces the _implementation_ for the selector we want to hack
|
#ifndef QT_MAC_USE_COCOA
|
||||||
// (originalSel) with the implementation found in proxyClass. Then it creates
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
|
||||||
// a new 'backup' method inside baseClass containing the old, original,
|
#endif
|
||||||
// implementation (fakeSel). You can let the proxy implementation of originalSel
|
{
|
||||||
// call fakeSel if needed (similar approach to calling a super class implementation).
|
// The following code replaces the _implementation_ for the selector we want to hack
|
||||||
// fakeSel must also be implemented in proxyClass, as the signature is used
|
// (originalSel) with the implementation found in proxyClass. Then it creates
|
||||||
// as template for the method one we add into baseClass.
|
// a new 'backup' method inside baseClass containing the old, original,
|
||||||
// NB: You will typically never create any instances of proxyClass; we use it
|
// implementation (fakeSel). You can let the proxy implementation of originalSel
|
||||||
// only for stealing its contents and put it into baseClass.
|
// call fakeSel if needed (similar approach to calling a super class implementation).
|
||||||
if (!replacementSel)
|
// fakeSel must also be implemented in proxyClass, as the signature is used
|
||||||
replacementSel = originalSel;
|
// as template for the method one we add into baseClass.
|
||||||
|
// NB: You will typically never create any instances of proxyClass; we use it
|
||||||
|
// only for stealing its contents and put it into baseClass.
|
||||||
|
if (!replacementSel)
|
||||||
|
replacementSel = originalSel;
|
||||||
|
|
||||||
Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
|
Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
|
||||||
Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel);
|
Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel);
|
||||||
IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod));
|
IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod));
|
||||||
|
|
||||||
if (backupSel) {
|
if (backupSel) {
|
||||||
Method backupMethod = class_getInstanceMethod(proxyClass, backupSel);
|
Method backupMethod = class_getInstanceMethod(proxyClass, backupSel);
|
||||||
class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod));
|
class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel)
|
void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel)
|
||||||
{
|
{
|
||||||
Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
|
#ifndef QT_MAC_USE_COCOA
|
||||||
Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel);
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
|
||||||
method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass));
|
#endif
|
||||||
|
{
|
||||||
|
Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
|
||||||
|
Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel);
|
||||||
|
method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -1,181 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/legal
|
|
||||||
**
|
|
||||||
** This file is part of the plugins of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and Digia. For licensing terms and
|
|
||||||
** conditions see http://qt.digia.com/licensing. For further information
|
|
||||||
** use the contact form at http://qt.digia.com/contact-us.
|
|
||||||
**
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
||||||
** General Public License version 2.1 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
||||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Digia gives you certain additional
|
|
||||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3.0 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
||||||
** packaging of this file. Please review the following information to
|
|
||||||
** ensure the GNU General Public License version 3.0 requirements will be
|
|
||||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#include <QtGui/qpa/qwindowsysteminterface.h>
|
|
||||||
#include <QtCore/private/qcore_mac_p.h>
|
|
||||||
#include "qcocoaintrospection.h"
|
|
||||||
|
|
||||||
extern int qMain(int argc, char *argv[]);
|
|
||||||
|
|
||||||
@interface QCocoaMainWrapper : NSObject
|
|
||||||
|
|
||||||
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
|
|
||||||
- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
|
|
||||||
- (void)runUserMain;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation QCocoaMainWrapper
|
|
||||||
|
|
||||||
- (void)applicationWillFinishLaunching:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
if ([notification object] != NSApp) // Shouldn't happen AFAIK, but still
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
From the Cocoa documentation: "A good place to install event handlers
|
|
||||||
is in the applicationWillFinishLaunching: method of the application
|
|
||||||
delegate. At that point, the Application Kit has installed its default
|
|
||||||
event handlers, so if you install a handler for one of the same events,
|
|
||||||
it will replace the Application Kit version."
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
If Qt is used as a plugin, we let the 3rd party application handle
|
|
||||||
events like quit and open file events. Otherwise, if we install our own
|
|
||||||
handlers, we easily end up breaking functionality the 3rd party
|
|
||||||
application depends on.
|
|
||||||
*/
|
|
||||||
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
|
|
||||||
[eventManager setEventHandler:self
|
|
||||||
andSelector:@selector(appleEventQuit:withReplyEvent:)
|
|
||||||
forEventClass:kCoreEventClass
|
|
||||||
andEventID:kAEQuitApplication];
|
|
||||||
[eventManager setEventHandler:self
|
|
||||||
andSelector:@selector(getUrl:withReplyEvent:)
|
|
||||||
forEventClass:kInternetEventClass
|
|
||||||
andEventID:kAEGetURL];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
if ([notification object] != NSApp) // Shouldn't happen AFAIK, but still
|
|
||||||
return;
|
|
||||||
|
|
||||||
// We schedule the main-redirection for the next eventloop pass so that we
|
|
||||||
// can return from this function and let NSApplicationMain finish its job.
|
|
||||||
[NSTimer scheduledTimerWithTimeInterval:0 target:self
|
|
||||||
selector:@selector(runUserMain) userInfo:nil repeats:NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
|
||||||
{
|
|
||||||
Q_UNUSED(replyEvent);
|
|
||||||
NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
|
||||||
QWindowSystemInterface::handleFileOpenEvent(QCFString::toQString(urlString));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
Q_UNUSED(replyEvent);
|
|
||||||
[NSApp terminate:self];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)runUserMain
|
|
||||||
{
|
|
||||||
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
|
|
||||||
int argc = arguments.count;
|
|
||||||
char **argv = new char*[argc];
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
NSString *arg = [arguments objectAtIndex:i];
|
|
||||||
argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
|
|
||||||
strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
qMain(argc, argv);
|
|
||||||
delete[] argv;
|
|
||||||
|
|
||||||
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
|
|
||||||
[eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
|
|
||||||
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
|
|
||||||
|
|
||||||
[NSApp terminate:self];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
static SEL qt_infoDictionary_original_SEL = @selector(qt_infoDictionary_original);
|
|
||||||
|
|
||||||
@implementation NSBundle (QT_MANGLE_NAMESPACE(QCocoaMain))
|
|
||||||
|
|
||||||
- (Class)qt_infoDictionary_replacement
|
|
||||||
{
|
|
||||||
if (self == [NSBundle mainBundle]) {
|
|
||||||
static NSMutableDictionary *infoDict = nil;
|
|
||||||
if (!infoDict) {
|
|
||||||
infoDict = [[self performSelector:qt_infoDictionary_original_SEL] mutableCopy];
|
|
||||||
[infoDict setValue:@"NSApplication" forKey:@"NSPrincipalClass"];
|
|
||||||
}
|
|
||||||
return infoDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [self performSelector:qt_infoDictionary_original_SEL];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
QCocoaMainWrapper *mainWrapper = [[QCocoaMainWrapper alloc] init];
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:mainWrapper selector:@selector(applicationWillFinishLaunching:)
|
|
||||||
name:NSApplicationWillFinishLaunchingNotification object:nil];
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:mainWrapper selector:@selector(applicationDidFinishLaunching:)
|
|
||||||
name:NSApplicationDidFinishLaunchingNotification object:nil];
|
|
||||||
|
|
||||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
|
||||||
if (!mainBundle.principalClass) {
|
|
||||||
// Since several of the GUI based Qt utilities (e.g., qmlscene) are command
|
|
||||||
// line applications, meaning non-bundle applications, we need to make Cocoa
|
|
||||||
// believe everything is fine. So we fake the main bundle's dictionary by
|
|
||||||
// adding the "NSPrincipalClass" property. So far, this seems to be enough to
|
|
||||||
// keep NSApplicationMain() happy and running...
|
|
||||||
qt_cocoa_change_implementation([NSBundle class], @selector(infoDictionary),
|
|
||||||
[NSBundle class], @selector(qt_infoDictionary_replacement), qt_infoDictionary_original_SEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NSApplicationMain(argc, (const char **)argv);
|
|
||||||
}
|
|
@ -2166,8 +2166,6 @@ void QColorDialog::keyPressEvent(QKeyEvent *e)
|
|||||||
}
|
}
|
||||||
e->accept();
|
e->accept();
|
||||||
return;
|
return;
|
||||||
} else if (d->nativeDialogInUse && d->platformColorDialogHelper()->event(e)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
QDialog::keyPressEvent(e);
|
QDialog::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
@ -983,9 +983,14 @@ void QFontDialog::setVisible(bool visible)
|
|||||||
Q_D(QFontDialog);
|
Q_D(QFontDialog);
|
||||||
if (d->canBeNativeDialog())
|
if (d->canBeNativeDialog())
|
||||||
d->setNativeDialogVisible(visible);
|
d->setNativeDialogVisible(visible);
|
||||||
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
|
if (d->nativeDialogInUse) {
|
||||||
// updates the state correctly, but skips showing the non-native version:
|
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
|
||||||
setAttribute(Qt::WA_DontShowOnScreen, d->nativeDialogInUse);
|
// updates the state correctly, but skips showing the non-native version:
|
||||||
|
setAttribute(Qt::WA_DontShowOnScreen, true);
|
||||||
|
} else {
|
||||||
|
d->nativeDialogInUse = false;
|
||||||
|
setAttribute(Qt::WA_DontShowOnScreen, false);
|
||||||
|
}
|
||||||
QDialog::setVisible(visible);
|
QDialog::setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,10 +144,13 @@ void tst_QColorDialog::postKeyReturn() {
|
|||||||
|
|
||||||
void tst_QColorDialog::testGetRgba()
|
void tst_QColorDialog::testGetRgba()
|
||||||
{
|
{
|
||||||
QColorDialog cd;
|
#ifdef Q_OS_MAC
|
||||||
cd.show();
|
QEXPECT_FAIL("", "Sending QTest::keyClick to OSX color dialog helper fails, see QTBUG-24320", Continue);
|
||||||
QTimer::singleShot(0, this, SLOT(postKeyReturn()));
|
#endif
|
||||||
QTRY_COMPARE(cd.result(), int(QDialog::Accepted));
|
bool ok = false;
|
||||||
|
QTimer::singleShot(500, this, SLOT(postKeyReturn()));
|
||||||
|
QColorDialog::getRgba(0xffffffff, &ok);
|
||||||
|
QVERIFY(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QColorDialog::defaultOkButton()
|
void tst_QColorDialog::defaultOkButton()
|
||||||
|
@ -64,7 +64,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void postKeyReturn();
|
void postKeyReturn();
|
||||||
void testDefaultOkButton();
|
void testGetFont();
|
||||||
void testSetFont();
|
void testSetFont();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -116,12 +116,15 @@ void tst_QFontDialog::postKeyReturn() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QFontDialog::testDefaultOkButton()
|
void tst_QFontDialog::testGetFont()
|
||||||
{
|
{
|
||||||
QFontDialog fd;
|
#ifdef Q_OS_MAC
|
||||||
fd.show();
|
QEXPECT_FAIL("", "Sending QTest::keyClick to OSX font dialog helper fails, see QTBUG-24321", Continue);
|
||||||
QTimer::singleShot(0, this, SLOT(postKeyReturn()));
|
#endif
|
||||||
QTRY_COMPARE(fd.result(), int(QDialog::Accepted));
|
bool ok = false;
|
||||||
|
QTimer::singleShot(2000, this, SLOT(postKeyReturn()));
|
||||||
|
QFontDialog::getFont(&ok);
|
||||||
|
QVERIFY(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QFontDialog::runSlotWithFailsafeTimer(const char *member)
|
void tst_QFontDialog::runSlotWithFailsafeTimer(const char *member)
|
||||||
@ -141,7 +144,7 @@ void tst_QFontDialog::runSlotWithFailsafeTimer(const char *member)
|
|||||||
|
|
||||||
void tst_QFontDialog::defaultOkButton()
|
void tst_QFontDialog::defaultOkButton()
|
||||||
{
|
{
|
||||||
runSlotWithFailsafeTimer(SLOT(testDefaultOkButton()));
|
runSlotWithFailsafeTimer(SLOT(testGetFont()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QFontDialog::testSetFont()
|
void tst_QFontDialog::testSetFont()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user