diff options
Diffstat (limited to 'src/plugins/platforms/cocoa')
35 files changed, 352 insertions, 353 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 83e2a88e6a..6ed26f9e6c 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -78,7 +78,7 @@ HEADERS += qcocoaintegration.h \ RESOURCES += qcocoaresources.qrc -LIBS += -framework Cocoa -framework IOKit +LIBS += -framework Cocoa -framework Carbon -framework IOKit QT += core-private gui-private platformsupport-private diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 070f23f028..adeb423cf9 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -41,7 +41,7 @@ #include "qcocoaaccessibility.h" #include "qcocoaaccessibilityelement.h" #include <qaccessible.h> -#include <qaccessible2.h> +#include <QtGui/private/qaccessible2_p.h> #include <private/qcore_mac_p.h> #ifndef QT_NO_COCOA_ACCESSIBILITY diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h index 7ebe7a4e9d..3b1fbe042d 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h @@ -41,6 +41,7 @@ #ifndef QCOCOAACCESIBILITYELEMENT_H #define QCOCOAACCESIBILITYELEMENT_H +#include <QtCore/qglobal.h> #import <Cocoa/Cocoa.h> #import <AppKit/NSAccessibility.h> diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index f5f37c5b00..df496a413b 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -43,7 +43,7 @@ #include "qcocoahelpers.h" #include <QAccessible> -#include "QAccessibleActionInterface" +#include <QtGui/private/qaccessible2_p.h> #import <AppKit/NSAccessibility.h> diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h index 6dd7ea2fb3..e44b2d1b6d 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h @@ -93,19 +93,6 @@ @class QT_MANGLE_NAMESPACE(QCocoaMenuLoader); -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 - -@protocol NSApplicationDelegate <NSObject> -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames; -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender; -- (void)applicationDidBecomeActive:(NSNotification *)notification; -- (void)applicationDidResignActive:(NSNotification *)notification; -@end - -#endif - @interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> { bool startedQuit; NSMenu *dockMenu; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 31726268f1..4881dcef71 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -92,8 +92,10 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint // m_cgImage is only a reference to the data inside m_qImage, it is not a copy. CGImageRelease(m_cgImage); m_cgImage = 0; - if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(win->handle())) - [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; + if (!m_qImage.isNull()) { + if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(win->handle())) + [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; + } } void QCocoaBackingStore::resize(const QSize &size, const QRegion &) diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index a36a855bcd..12808b7041 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -65,8 +65,9 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) { Q_UNUSED(window); + const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; // Check for a suitable built-in NSCursor first: - switch (cursor->shape()) { + switch (newShape) { case Qt::ArrowCursor: [[NSCursor arrowCursor] set]; break; @@ -104,7 +105,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) default : { // No suitable OS cursor exist, use cursors provided // by Qt for the rest. Check for a cached cursor: - NSCursor *cocoaCursor = m_cursors.value(cursor->shape()); + NSCursor *cocoaCursor = m_cursors.value(newShape); if (cocoaCursor && cursor->shape() == Qt::BitmapCursor) { [cocoaCursor release]; cocoaCursor = 0; @@ -115,7 +116,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) [[NSCursor arrowCursor] set]; return; } - m_cursors.insert(cursor->shape(), cocoaCursor); + m_cursors.insert(newShape, cocoaCursor); } [cocoaCursor set]; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index f63ac0d205..93476ee1b4 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -93,6 +93,7 @@ #include <QtGui/qwindowdefs.h> #include <QtCore/private/qabstracteventdispatcher_p.h> #include <QtCore/private/qtimerinfo_unix_p.h> +#include <QtPlatformSupport/private/qcfsocketnotifier_p.h> #include <CoreFoundation/CoreFoundation.h> @@ -132,16 +133,9 @@ public: void wakeUp(); void interrupt(); void flush(); -}; -struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} - CFSocketRef socket; - CFRunLoopSourceRef runloop; - QObject *readNotifier; - QObject *writeNotifier; + friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; -typedef QHash<int, MacSocketInfo *> MacSocketHash; class QCocoaEventDispatcherPrivate : public QAbstractEventDispatcherPrivate { @@ -183,7 +177,7 @@ public: void maybeCancelWaitForMoreEvents(); void ensureNSAppInitialized(); - MacSocketHash macSockets; + QCFSocketNotifier cfSocketNotifier; QList<void *> queuedUserInputEvents; // NSEvent * CFRunLoopSourceRef postedEventsSource; CFRunLoopObserverRef waitingObserver; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index a0734530c5..5c487b0bdd 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -149,10 +149,10 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer() CFTimeInterval oneyear = CFTimeInterval(3600. * 24. * 365.); // Q: when should the CFRunLoopTimer fire for the first time? - struct timeval tv; + struct timespec tv; if (timerInfoList.timerWait(tv)) { // A: when we have timers to fire, of course - interval = qMax(tv.tv_sec + tv.tv_usec / 1000000., 0.0000001); + interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001); } else { // this shouldn't really happen, but in case it does, set the timer to fire a some point in the distant future interval = oneyear; @@ -172,10 +172,10 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer() CFTimeInterval interval; // Q: when should the timer first next? - struct timeval tv; + struct timespec tv; if (timerInfoList.timerWait(tv)) { // A: when we have timers to fire, of course - interval = qMax(tv.tv_sec + tv.tv_usec / 1000000., 0.0000001); + interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001); } else { // no timers can fire, but we cannot stop the CFRunLoopTimer, set the timer to fire at some // point in the distant future (the timer interval is one year) @@ -270,58 +270,6 @@ QCocoaEventDispatcher::registeredTimers(QObject *object) const return d->timerInfoList.registeredTimers(object); } -/************************************************************************** - Socket Notifiers - *************************************************************************/ -void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, - const void *, void *info) { - QCocoaEventDispatcherPrivate *const eventDispatcher - = static_cast<QCocoaEventDispatcherPrivate *>(info); - int nativeSocket = CFSocketGetNative(s); - MacSocketInfo *socketInfo = eventDispatcher->macSockets.value(nativeSocket); - QEvent notifierEvent(QEvent::SockAct); - - // There is a race condition that happen where we disable the notifier and - // the kernel still has a notification to pass on. We then get this - // notification after we've successfully disabled the CFSocket, but our Qt - // notifier is now gone. The upshot is we have to check the notifier - // everytime. - if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) - QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); - } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) - QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); - } - - eventDispatcher->maybeCancelWaitForMoreEvents(); -} - -/* - Adds a loop source for the given socket to the current run loop. -*/ -CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket) -{ - CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); - if (!loopSource) - return 0; - - CFRunLoopAddSource(mainRunLoop(), loopSource, kCFRunLoopCommonModes); - return loopSource; -} - -/* - Removes the loop source for the given socket from the current run loop. -*/ -void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop) -{ - Q_ASSERT(runloop); - CFRunLoopRemoveSource(mainRunLoop(), runloop, kCFRunLoopCommonModes); - CFSocketDisableCallBacks(socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack); - CFRunLoopSourceInvalidate(runloop); -} - /* Register a QSocketNotifier with the mac event system by creating a CFSocket with with a read/write callback. @@ -331,130 +279,14 @@ void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSource */ void QCocoaEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier) { - Q_ASSERT(notifier); - int nativeSocket = notifier->socket(); - int type = notifier->type(); -#ifndef QT_NO_DEBUG - if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { - qWarning("QSocketNotifier: Internal error"); - return; - } else if (notifier->thread() != thread() - || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); - return; - } -#endif - Q_D(QCocoaEventDispatcher); - - if (type == QSocketNotifier::Exception) { - qWarning("QSocketNotifier::Exception is not supported on Mac OS X"); - return; - } - - // Check if we have a CFSocket for the native socket, create one if not. - MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket); - if (!socketInfo) { - socketInfo = new MacSocketInfo(); - - // Create CFSocket, specify that we want both read and write callbacks (the callbacks - // are enabled/disabled later on). - const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack; - CFSocketContext context = {0, d, 0, 0, 0}; - socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context); - if (CFSocketIsValid(socketInfo->socket) == false) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket"); - return; - } - - CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation - CFSocketSetSocketFlags(socketInfo->socket, flags); - - // Add CFSocket to runloop. - if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - return; - } - - // Disable both callback types by default. This must be done after - // we add the CFSocket to the runloop, or else these calls will have - // no effect. - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - - d->macSockets.insert(nativeSocket, socketInfo); - } - - // Increment read/write counters and select enable callbacks if necessary. - if (type == QSocketNotifier::Read) { - Q_ASSERT(socketInfo->readNotifier == 0); - socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } else if (type == QSocketNotifier::Write) { - Q_ASSERT(socketInfo->writeNotifier == 0); - socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } + d->cfSocketNotifier.registerSocketNotifier(notifier); } -/* - Unregister QSocketNotifer. The CFSocket correspoding to this notifier is - removed from the runloop of this is the last notifier that users - that CFSocket. -*/ void QCocoaEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier) { - Q_ASSERT(notifier); - int nativeSocket = notifier->socket(); - int type = notifier->type(); -#ifndef QT_NO_DEBUG - if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { - qWarning("QSocketNotifier: Internal error"); - return; - } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); - return; - } -#endif - Q_D(QCocoaEventDispatcher); - - if (type == QSocketNotifier::Exception) { - qWarning("QSocketNotifier::Exception is not supported on Mac OS X"); - return; - } - MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket); - if (!socketInfo) { - qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier"); - return; - } - - // Decrement read/write counters and disable callbacks if necessary. - if (type == QSocketNotifier::Read) { - Q_ASSERT(notifier == socketInfo->readNotifier); - socketInfo->readNotifier = 0; - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } else if (type == QSocketNotifier::Write) { - Q_ASSERT(notifier == socketInfo->writeNotifier); - socketInfo->writeNotifier = 0; - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } - - // Remove CFSocket from runloop if this was the last QSocketNotifier. - if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) { - if (CFSocketIsValid(socketInfo->socket)) - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - delete socketInfo; - d->macSockets.remove(nativeSocket); - } + d->cfSocketNotifier.unregisterSocketNotifier(notifier); } bool QCocoaEventDispatcher::hasPendingEvents() @@ -467,37 +299,35 @@ bool QCocoaEventDispatcher::hasPendingEvents() static bool IsMouseOrKeyEvent( NSEvent* event ) { bool result = false; - + switch( [event type] ) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSRightMouseDown: + case NSRightMouseUp: case NSMouseMoved: // ?? - case NSLeftMouseDragged: + case NSLeftMouseDragged: case NSRightMouseDragged: - case NSMouseEntered: - case NSMouseExited: - case NSKeyDown: - case NSKeyUp: + case NSMouseEntered: + case NSMouseExited: + case NSKeyDown: + case NSKeyUp: case NSFlagsChanged: // key modifiers changed? case NSCursorUpdate: // ?? - case NSScrollWheel: - case NSTabletPoint: - case NSTabletProximity: - case NSOtherMouseDown: - case NSOtherMouseUp: + case NSScrollWheel: + case NSTabletPoint: + case NSTabletProximity: + case NSOtherMouseDown: + case NSOtherMouseUp: case NSOtherMouseDragged: #ifndef QT_NO_GESTURES -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 case NSEventTypeGesture: // touch events case NSEventTypeMagnify: case NSEventTypeSwipe: case NSEventTypeRotate: case NSEventTypeBeginGesture: case NSEventTypeEndGesture: -#endif #endif // QT_NO_GESTURES result = true; break; @@ -809,7 +639,7 @@ static void setChildrenWorksWhenModal(QWindow *window, bool worksWhenModal) Q_UNUSED(worksWhenModal) // For NSPanels (but not NSWindows, sadly), we can set the flag - // worksWhenModal, so that they are active even when they are not modal. + // worksWhenModal, so that they are active even when they are not modal. /* ### not ported QList<QDialog *> dialogs = window->findChildren<QDialog *>(); @@ -850,7 +680,7 @@ void QCocoaEventDispatcherPrivate::cleanupModalSessions() // this to actually end the sessions for real (rather than at the // point they were marked as stopped), is that ending a session // when no other session runs below it on the stack will make cocoa - // drop some events on the floor. + // drop some events on the floor. QCocoaAutoReleasePool pool; int stackSize = cocoaModalSessionStack.size(); @@ -942,11 +772,19 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate() { } +void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher) +{ + static_cast<QCocoaEventDispatcher *>(eventDispatcher)->d_func()->maybeCancelWaitForMoreEvents(); +} + QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent) : QAbstractEventDispatcher(*new QCocoaEventDispatcherPrivate, parent) { Q_D(QCocoaEventDispatcher); + d->cfSocketNotifier.setHostEventDispatcher(this); + d->cfSocketNotifier.setMaybeCancelWaitForMoreEventsCallback(qt_mac_maybeCancelWaitForMoreEventsForwarder); + // keep our sources running when modal loops are running CFRunLoopAddCommonMode(mainRunLoop(), (CFStringRef) NSModalPanelRunLoopMode); @@ -1021,7 +859,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents() 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 + // delayed stopping it until now (to let cocoa process // pending cocoa events first). if (currentModalSessionCached) temporarilyStopAllModalSessions(); @@ -1129,17 +967,8 @@ QCocoaEventDispatcher::~QCocoaEventDispatcher() [nsevent release]; } - // Remove CFSockets from the runloop. - for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - } - } + d->cfSocketNotifier.removeSocketNotifiers(); + CFRunLoopRemoveSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes); CFRelease(d->postedEventsSource); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 61646041fb..9cc0353dc6 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -77,11 +77,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate); @interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 : NSObject<NSOpenSavePanelDelegate> -#else - : NSObject -#endif { @public NSOpenPanel *mOpenPanel; @@ -216,7 +212,7 @@ static QString strippedText(QString s) - (void)closePanel { *mCurrentSelection = QT_PREPEND_NAMESPACE(QCFString::toQString)([[mSavePanel URL] path]); - if ([mSavePanel respondsToSelector:@selector(closePanel:)]) + if ([mSavePanel respondsToSelector:@selector(close)]) [mSavePanel close]; if ([mSavePanel isSheet]) [NSApp endSheet: mSavePanel]; @@ -230,6 +226,7 @@ static QString strippedText(QString s) bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; + [self updateProperties]; [mOpenPanel setAllowedFileTypes:nil]; [mOpenPanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())] : [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]]; @@ -274,6 +271,7 @@ static QString strippedText(QString s) bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; + [self updateProperties]; [mSavePanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())] : [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]]; [mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : nil]; @@ -405,6 +403,9 @@ static QString strippedText(QString s) [mSavePanel setCanCreateDirectories:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::ReadOnly)))]; [mOpenPanel setAllowsMultipleSelection:(fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::ExistingFiles))]; [mOpenPanel setResolvesAliases:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::DontResolveSymlinks)))]; + [mOpenPanel setTitle:QCFString::toNSString(mOptions->windowTitle())]; + [mSavePanel setTitle:QCFString::toNSString(mOptions->windowTitle())]; + [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead? QStringList ext = [self acceptableExtensionsForSave]; const QString defaultSuffix = mOptions->defaultSuffix(); @@ -577,13 +578,16 @@ extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding void QCocoaFileDialogHelper::setDirectory(const QString &directory) { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); - [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory)]]; + if (delegate) + [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory)]]; } QString QCocoaFileDialogHelper::directory() const { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); - return QCFString::toQString([delegate->mSavePanel directory]); + if (delegate) + return QCFString::toQString([delegate->mSavePanel directory]); + return QString(); } void QCocoaFileDialogHelper::selectFile(const QString &filename) @@ -600,12 +604,16 @@ void QCocoaFileDialogHelper::selectFile(const QString &filename) QStringList QCocoaFileDialogHelper::selectedFiles() const { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); - return [delegate selectedFiles]; + if (delegate) + return [delegate selectedFiles]; + return QStringList(); } void QCocoaFileDialogHelper::setFilter() { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); + if (!delegate) + return; const SharedPointerFileDialogOptions &opts = options(); [delegate->mSavePanel setTitle:QCFString::toNSString(opts->windowTitle())]; if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) @@ -618,9 +626,13 @@ void QCocoaFileDialogHelper::setFilter() void QCocoaFileDialogHelper::selectNameFilter(const QString &filter) { + if (!options()) + return; const int index = options()->nameFilters().indexOf(filter); if (index != -1) { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); + if (!delegate) + return; [delegate->mPopUpButton selectItemAtIndex:index]; [delegate filterChanged:nil]; } @@ -629,7 +641,11 @@ void QCocoaFileDialogHelper::selectNameFilter(const QString &filter) QString QCocoaFileDialogHelper::selectedNameFilter() const { QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); + if (!delegate) + return QString(); int index = [delegate->mPopUpButton indexOfSelectedItem]; + if (index >= options()->nameFilters().count()) + return QString(); return index != -1 ? options()->nameFilters().at(index) : QString(); } @@ -675,6 +691,8 @@ bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModalit { createNSOpenSavePanelDelegate(); QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate); + if (!delegate) + return false; if (windowModality == Qt::NonModal) [delegate showModelessPanel]; else if (windowModality == Qt::WindowModal && parent) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index d0f5a58e22..d4673baaef 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -49,11 +49,19 @@ #import <Cocoa/Cocoa.h> QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share) - : m_format(format) + : m_context(nil), + m_shareContext(nil), + m_format(format) { + // we only support OpenGL contexts under Cocoa + if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) + m_format.setRenderableType(QSurfaceFormat::OpenGL); + if (m_format.renderableType() != QSurfaceFormat::OpenGL) + return; + QCocoaAutoReleasePool pool; // For the SG Canvas render thread - NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(format)); + NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(m_format)); m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil; m_context = [NSOpenGLContext alloc]; @@ -70,6 +78,10 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo const GLint interval = 1; [m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval]; + if (format.alphaBufferSize() > 0) { + int zeroOpacity = 0; + [m_context setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity]; + } } QCocoaGLContext::~QCocoaGLContext() diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 831ab579f5..c801d9d926 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -84,8 +84,6 @@ HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion); OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); -CGFloat qt_mac_get_scalefactor(); - QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 91a6f5a4c7..5ec2cea362 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -47,6 +47,7 @@ #include <QtGui> #include <qpa/qplatformscreen.h> #include <private/qguiapplication_p.h> +#include <private/qwindow_p.h> #ifndef QT_NO_WIDGETS #include <QtWidgets/QWidget> @@ -466,20 +467,17 @@ QString qt_mac_removeMnemonics(const QString &original) return returnText; } - -CGColorSpaceRef m_genericColorSpace = 0; -QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; -bool m_postRoutineRegistered = false; +static CGColorSpaceRef m_genericColorSpace = 0; +static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; +static bool m_postRoutineRegistered = false; CGColorSpaceRef qt_mac_genericColorSpace() { #if 0 if (!m_genericColorSpace) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); } else -#endif { m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); } @@ -587,10 +585,28 @@ QString qt_mac_applicationName() return appName; } +/* + Mac window coordinates are in the first quadrant: 0, 0 is at the lower-left + corner of the primary screen. This function converts the given rect to an + NSRect for the window geometry, flipping from 4th quadrant to 1st quadrant + and simultaneously ensuring that as much of the window as possible will be + onscreen. If the rect is too tall for the screen, the OS will reduce the + window's height anyway; but by moving the window upwards we can have more + of it onscreen. But the application can still control the y coordinate + in case it really wants the window to be positioned partially offscreen. +*/ NSRect qt_mac_flipRect(const QRect &rect, QWindow *window) { QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window); - int flippedY = onScreen->geometry().height() - rect.y() - rect.height(); + int flippedY = onScreen->geometry().height() - (rect.y() + rect.height()); + + // In case of automatic positioning, try to put as much of the window onscreen as possible. + if (window->isTopLevel() && qt_window_private(const_cast<QWindow*>(window))->positionAutomatic && flippedY < 0) + flippedY = onScreen->geometry().height() - onScreen->availableGeometry().height() - onScreen->availableGeometry().y(); +#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG + qDebug() << Q_FUNC_INFO << rect << "flippedY" << flippedY << + "screen" << onScreen->geometry() << "available" << onScreen->availableGeometry(); +#endif return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } @@ -616,11 +632,6 @@ InvalidContext: return err; } -CGFloat qt_mac_get_scalefactor() -{ - return [[NSScreen mainScreen] userSpaceScaleFactor]; -} - Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum == 0) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 93831158d0..d0fcf93b8c 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -105,7 +105,9 @@ void QCocoaScreen::updateGeometry() m_physicalSize = QSizeF(size.width, size.height); m_logicalDpi.first = 72; m_logicalDpi.second = 72; - m_refreshRate = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(dpy)); + float refresh = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(dpy)); + if (refresh > 0) + m_refreshRate = refresh; // Get m_name (brand/model of the monitor) NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName); diff --git a/src/plugins/platforms/cocoa/qcocoaintrospection.mm b/src/plugins/platforms/cocoa/qcocoaintrospection.mm index ffb6ae4294..806effc929 100644 --- a/src/plugins/platforms/cocoa/qcocoaintrospection.mm +++ b/src/plugins/platforms/cocoa/qcocoaintrospection.mm @@ -83,7 +83,6 @@ void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class prox if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) #endif { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 // The following code replaces the _implementation_ for the selector we want to hack // (originalSel) with the implementation found in proxyClass. Then it creates // a new 'backup' method inside baseClass containing the old, original, @@ -104,7 +103,6 @@ void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class prox Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); } -#endif } } @@ -114,11 +112,9 @@ void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL b if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) #endif { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 Method originalMethod = class_getInstanceMethod(baseClass, originalSel); Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); -#endif } } diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 09b62a9bcd..439b7f1a75 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -51,8 +51,6 @@ @class NSMenu; @class NSObject; -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QCocoaMenu : public QPlatformMenu @@ -71,11 +69,17 @@ public: void syncMenuItem(QPlatformMenuItem *menuItem); void setEnabled(bool enabled); void setVisible(bool visible); + void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item); + void syncSeparatorsCollapsible(bool enable); void syncModalState(bool modal); - virtual void setText(const QString &text); + virtual void setIcon(const QIcon &icon) { Q_UNUSED(icon) } + + void setText(const QString &text); + void setMinimumWidth(int width); + void setFont(const QFont &font); void setParentItem(QCocoaMenuItem* item); @@ -102,6 +106,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 676f0683fa..0fe4c48510 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -47,6 +47,8 @@ #include <QtCore/QtDebug> #include "qcocoaapplication.h" #include "qcocoamenuloader.h" +#include "qcocoawindow.h" +#import "qnsview.h" static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader() { @@ -133,6 +135,20 @@ void QCocoaMenu::setText(const QString &text) [m_nativeItem setTitle:QCFString::toNSString(stripped)]; } +void QCocoaMenu::setMinimumWidth(int width) +{ + m_nativeMenu.minimumWidth = width; +} + +void QCocoaMenu::setFont(const QFont &font) +{ + if (font.resolve()) { + NSFont *customMenuFont = [NSFont fontWithName:QCFString::toNSString(font.family()) + size:font.pointSize()]; + m_nativeMenu.font = customMenuFont; + } +} + void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) { QCocoaAutoReleasePool pool; @@ -290,9 +306,26 @@ void QCocoaMenu::setVisible(bool visible) [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; } +void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) +{ + QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0; + NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil; + NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil; + NSPoint nsPos = NSMakePoint(pos.x(), pos.y()); + [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:view]; + + // The call above blocks, and also swallows any mouse release event, + // so we need to clear any mouse button that triggered the menu popup. + if ([view isKindOfClass:[QNSView class]]) + [(QNSView *)view resetMouseButtons]; +} + QPlatformMenuItem *QCocoaMenu::menuItemAt(int position) const { - return m_menuItems.at(position); + if (0 <= position && position < m_menuItems.count()) + return m_menuItems.at(position); + + return 0; } QPlatformMenuItem *QCocoaMenu::menuItemForTag(quintptr tag) const diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index fe5193a50c..0e6d17343d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -51,8 +51,6 @@ @class NSMenuItem; @class NSMenu; -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QCocoaMenu; @@ -76,6 +74,7 @@ public: void setFont(const QFont &font); void setRole(MenuRole role); void setShortcut(const QKeySequence& shortcut); + void setCheckable(bool checkable) { Q_UNUSED(checkable) } void setChecked(bool isChecked); void setEnabled(bool isEnabled); @@ -110,8 +109,6 @@ private: quintptr m_tag; }; -QT_END_HEADER - QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index 040b687c4e..83cf1ffada 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -55,6 +55,7 @@ public: QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE; + QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE; QList<QPrinterInfo> availablePrinters() Q_DECL_OVERRIDE; QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index a48db02949..cfa23b7a30 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -138,3 +138,34 @@ QPrinterInfo QCocoaPrinterSupport::printerInfoFromPMPrinter(const PMPrinter &pri return createPrinterInfo(name, description, location, makeAndModel, isDefault, 0); } + +QList<QPair<QString, QSizeF> > QCocoaPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const +{ + QList<QPair<QString, QSizeF> > returnValue; + if (printerInfo.isNull()) + return returnValue; + + PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName())); + if (!printer) + return returnValue; + + CFArrayRef array; + if (PMPrinterGetPaperList(printer, &array) != noErr) { + PMRelease(printer); + return returnValue; + } + + int count = CFArrayGetCount(array); + for (int i = 0; i < count; ++i) { + PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); + double width, height; + if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) { + static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4; + QCFString paperName; + if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr) + returnValue.append(qMakePair(QString(paperName), QSizeF(width * OnePointInMillimeters, height * OnePointInMillimeters))); + } + } + PMRelease(printer); + return returnValue; +} diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h index 89ab51cf05..61a6ba3e2f 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h @@ -43,6 +43,8 @@ #ifndef QCOCOASYSTEMTRAYICON_P_H #define QCOCOASYSTEMTRAYICON_P_H +#include <QtCore/qglobal.h> + #ifndef QT_NO_SYSTEMTRAYICON #include "QtCore/qstring.h" diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index e092db8172..99f533b33a 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -93,7 +93,11 @@ QT_USE_NAMESPACE @class QT_MANGLE_NAMESPACE(QNSMenu); @class QT_MANGLE_NAMESPACE(QNSImageView); -@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject { +@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 + <NSUserNotificationCenterDelegate> +#endif + { @public QCocoaSystemTrayIcon *systray; NSStatusItem *item; @@ -108,6 +112,11 @@ QT_USE_NAMESPACE -(QRectF)geometry; - (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton; - (void)doubleClickSelector:(id)sender; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification; +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification; +#endif @end @interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView { @@ -132,9 +141,19 @@ class QSystemTrayIconSys public: QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) { item = [[QT_MANGLE_NAMESPACE(QNSStatusItem) alloc] initWithSysTray:sys]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item]; + } +#endif } ~QSystemTrayIconSys() { [[[item item] view] setHidden: YES]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil]; + } +#endif [item release]; } QT_MANGLE_NAMESPACE(QNSStatusItem) *item; @@ -223,6 +242,18 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess if (!m_sys) return; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + NSUserNotification *notification = [[NSUserNotification alloc] init]; + notification.title = [NSString stringWithUTF8String:title.toUtf8().data()]; + notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()]; + + [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; + + return; + } +#endif + #ifdef QT_MAC_SYSTEMTRAY_USE_GROWL // Make sure that we have Growl installed on the machine we are running on. QCFType<CFURLRef> cfurl; @@ -439,6 +470,20 @@ QT_END_NAMESPACE emit systray->activated(QPlatformSystemTrayIcon::DoubleClick); } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { + Q_UNUSED(center); + Q_UNUSED(notification); + return YES; +} + +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { + Q_UNUSED(center); + Q_UNUSED(notification); + emit systray->messageClicked(); +} +#endif + @end class QSystemTrayIconQMenu : public QPlatformMenu diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 08c516b4f4..fdb3f4672f 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -116,6 +116,8 @@ public: bool setMouseGrabEnabled(bool grab); QMargins frameMargins() const; + void requestActivateWindow(); + WId winId() const; void setParent(const QPlatformWindow *window); @@ -159,6 +161,8 @@ protected: QCocoaWindow *parentCocoaWindow() const; void syncWindowState(Qt::WindowState newState); + void updateOpaque(); + // private: public: // for QNSView friend class QCocoaBackingStore; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 467025c77b..9466b68bec 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -420,6 +420,8 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) NSInteger level = this->windowLevel(flags); [m_nsWindow setStyleMask:styleMask]; [m_nsWindow setLevel:level]; + [m_nsWindow setIgnoresMouseEvents:((flags & Qt::ToolTip) == Qt::ToolTip) ? YES : NO]; + // TODO deal with WindowTransparentForInput; setIgnoresMouseEvents is too extreme, you can't click the titlebar setWindowShadow(flags); } @@ -534,20 +536,30 @@ void QCocoaWindow::propagateSizeHints() } } +void QCocoaWindow::updateOpaque() +{ + bool translucent = window()->format().alphaBufferSize() > 0 + || window()->opacity() < 1 + || (m_contentView && [m_contentView hasMask]); + [m_nsWindow setOpaque:!translucent]; +} + + void QCocoaWindow::setOpacity(qreal level) { - if (m_nsWindow) + if (m_nsWindow) { [m_nsWindow setAlphaValue:level]; + updateOpaque(); + } } void QCocoaWindow::setMask(const QRegion ®ion) { - if (m_nsWindow) { - [m_nsWindow setOpaque:NO]; + if (m_nsWindow) [m_nsWindow setBackgroundColor:[NSColor clearColor]]; - } [m_qtView setMaskRegion:®ion]; + updateOpaque(); } bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) @@ -691,6 +703,13 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) setOpacity(opacity); } +void QCocoaWindow::requestActivateWindow() +{ + NSWindow *window = [m_contentView window]; + [ window makeFirstResponder : m_contentView ]; + [ window makeKeyWindow ]; +} + NSWindow * QCocoaWindow::createNSWindow() { QCocoaAutoReleasePool pool; @@ -753,6 +772,12 @@ NSWindow * QCocoaWindow::createNSWindow() NSInteger level = windowLevel(flags); [createdWindow setLevel:level]; + + if (window()->format().alphaBufferSize() > 0) { + [createdWindow setBackgroundColor:[NSColor clearColor]]; + [createdWindow setOpaque:NO]; + } + m_windowModality = window()->modality(); return createdWindow; } diff --git a/src/plugins/platforms/cocoa/qmacdefines_mac.h b/src/plugins/platforms/cocoa/qmacdefines_mac.h index 18c1ac84de..c03b398836 100644 --- a/src/plugins/platforms/cocoa/qmacdefines_mac.h +++ b/src/plugins/platforms/cocoa/qmacdefines_mac.h @@ -79,15 +79,11 @@ */ /* This is just many defines. Therefore it doesn't need things like: -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE QT_END_NAMESPACE -QT_END_HEADER - Yes, it is an informative comment ;-) */ diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index 337d962c7f..fc0048f998 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -42,8 +42,6 @@ #include "qmultitouch_mac_p.h" #include "qcocoahelpers.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - QT_BEGIN_NAMESPACE QHash<qint64, QCocoaTouch*> QCocoaTouch::_currentTouches; @@ -214,6 +212,3 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) } QT_END_NAMESPACE - -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h index 1244b8223f..736eb3f878 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h +++ b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h @@ -61,8 +61,6 @@ #include <qhash.h> #include <QtCore> -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - QT_BEGIN_NAMESPACE class QCocoaTouch @@ -92,7 +90,5 @@ class QCocoaTouch QT_END_NAMESPACE -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - #endif // QMULTITOUCH_MAC_P_H diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 853b4b99e1..5ccea3c387 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -86,6 +86,10 @@ QT_END_NAMESPACE - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; +- (BOOL)becomeFirstResponder; +- (BOOL)hasMask; + +- (void)resetMouseButtons; - (void)handleMouseEvent:(NSEvent *)theEvent; - (void)mouseDown:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0c122eaf2d..e608731cc1 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -304,6 +304,11 @@ static QTouchDevice *touchDevice = 0; [self setNeedsDisplayInRect:NSMakeRect(br.x(), br.y(), br.width(), br.height())]; } +- (BOOL) hasMask +{ + return m_maskData != 0; +} + - (void) setMaskRegion:(const QRegion *)region { m_shouldInvalidateWindowShadow = true; @@ -397,8 +402,27 @@ static QTouchDevice *touchDevice = 0; return YES; } +- (BOOL)becomeFirstResponder +{ + QWindow *focusWindow = m_window; + + // For widgets we need to do a bit of trickery as the window + // to activate is the window of the top-level widget. + if (m_window->metaObject()->className() == QStringLiteral("QWidgetWindow")) { + while (focusWindow->parent()) { + focusWindow = focusWindow->parent(); + } + } + QWindowSystemInterface::handleWindowActivated(focusWindow); + return YES; +} + - (BOOL)acceptsFirstResponder { + if (m_window->flags() & Qt::WindowDoesNotAcceptFocus) + return NO; + if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip) + return NO; return YES; } @@ -447,6 +471,11 @@ static QTouchDevice *touchDevice = 0; } } +- (void)resetMouseButtons +{ + m_buttons = Qt::NoButton; +} + - (void)handleMouseEvent:(NSEvent *)theEvent { QPoint qtWindowPoint, qtScreenPoint; diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm index 8ee39bf767..e05ffbe343 100644 --- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm +++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm @@ -46,7 +46,7 @@ #include "qcocoaaccessibility.h" #include "qcocoaaccessibilityelement.h" -#include "QAccessibleActionInterface" +#include <QtGui/private/qaccessible2_p.h> #include <QtCore/QDebug> #import <AppKit/NSAccessibility.h> diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h index 53bbeb1318..98ad7b8c9d 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.h +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -46,26 +46,6 @@ #include "qcocoawindow.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -@protocol NSWindowDelegate <NSObject> -//- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; -//- (void)windowDidMiniaturize:(NSNotification*)notification; -- (void)windowDidResize:(NSNotification *)notification; -- (void)windowWillClose:(NSNotification *)notification; -//- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame; -- (void)windowDidMove:(NSNotification *)notification; -//- (BOOL)windowShouldClose:(id)window; -//- (void)windowDidDeminiaturize:(NSNotification *)notification; -//- (void)windowDidBecomeMain:(NSNotification*)notification; -//- (void)windowDidResignMain:(NSNotification*)notification; -//- (void)windowDidBecomeKey:(NSNotification*)notification; -//- (void)windowDidResignKey:(NSNotification*)notification; -//- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu; -//- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard; -//- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; -@end -#endif - @interface QNSWindowDelegate : NSObject <NSWindowDelegate> { QCocoaWindow *m_cocoaWindow; diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 0b6392fb65..301beb11c1 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE QCoreGraphicsPaintEngine utility functions *****************************************************************************/ -void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) +static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) { CGAffineTransform old_xform = CGAffineTransformIdentity; if (orig_xform) { //setup xforms @@ -90,14 +90,11 @@ void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig if (rgn.isEmpty()) { CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); } else { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QCFType<HIMutableShapeRef> shape = qt_mac_QRegionToHIMutableShape(rgn); Q_ASSERT(!HIShapeIsEmpty(shape)); HIShapeReplacePathInCGContext(shape, hd); - } else -#endif - { + } else { QVector<QRect> rects = rgn.rects(); const int count = rects.size(); for (int i = 0; i < count; i++) { @@ -338,11 +335,9 @@ CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() { #if 0 if (!m_genericColorSpace) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); } else -#endif { m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); } @@ -1185,7 +1180,6 @@ extern "C" { void QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { int cg_mode = kCGBlendModeNormal; switch (mode) { @@ -1267,11 +1261,9 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) if (cg_mode > -1) { CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); } - } else -#endif - // The standard porter duff ops. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3 + } else if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3 && mode <= QPainter::CompositionMode_Xor) { + // The standard porter duff ops. int cg_mode = kCGCompositeModeCopy; switch (mode) { case QPainter::CompositionMode_SourceOver: @@ -1317,7 +1309,6 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) if (cg_mode > -1) CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); } else { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) bool needPrivateAPI = false; if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { int cg_mode = kCGBlendModeNormal; @@ -1367,7 +1358,6 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) else CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); } -#endif } } @@ -1376,13 +1366,8 @@ QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints) { Q_D(QCoreGraphicsPaintEngine); CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing); - static const CGFloat ScaleFactor = qt_mac_get_scalefactor(); - if (ScaleFactor > 1.) { - CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh); - } else { - CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? - kCGInterpolationHigh : kCGInterpolationNone); - } + CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? + kCGInterpolationHigh : kCGInterpolationNone); bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing; if (!textAntialiasing || d->disabledSmoothFonts) { d->disabledSmoothFonts = !textAntialiasing; diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h index 2763a14690..fa000b9f92 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h @@ -122,8 +122,6 @@ public: void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) { QPaintEngine::drawPolygon(points, pointCount, mode); } - bool supportsTransformations(qreal, const QTransform &) const { return true; }; - protected: friend class QMacPrintEngine; friend class QMacPrintEnginePrivate; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 54019372bc..4748005f1a 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -180,6 +180,38 @@ QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const return QPlatformPrinterSupport::convertQSizeFToPaperSize(sizef); } +void QMacPrintEnginePrivate::setPaperName(const QString &name) +{ + Q_Q(QMacPrintEngine); + PMPrinter printer; + + if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { + CFArrayRef array; + if (PMPrinterGetPaperList(printer, &array) != noErr) { + PMRelease(printer); + return; + } + int count = CFArrayGetCount(array); + for (int i = 0; i < count; ++i) { + PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); + QCFString paperName; + if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr) { + if (QString(paperName) == name) { + PMPageFormat tmp; + PMCreatePageFormatWithPMPaper(&tmp, paper); + PMCopyPageFormat(tmp, format()); + q->setProperty(QPrintEngine::PPK_Orientation, orient); + if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { + // Don't know, warn for the moment. + qWarning("QMacPrintEngine, problem setting paper name"); + } + } + } + } + PMRelease(printer); + } +} + QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const { Q_ASSERT_X(printInfo, "QMacPrinterEngine::supportedResolutions", @@ -190,23 +222,7 @@ QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { PMResolution res; OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount); - if (status == kPMNotImplemented) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) - // *Sigh* we have to use the non-indexed version. - if (PMPrinterGetPrinterResolution(printer, kPMMinSquareResolution, &res) == noErr) - resolutions.append(int(res.hRes)); - if (PMPrinterGetPrinterResolution(printer, kPMMaxSquareResolution, &res) == noErr) { - QVariant var(int(res.hRes)); - if (!resolutions.contains(var)) - resolutions.append(var); - } - if (PMPrinterGetPrinterResolution(printer, kPMDefaultResolution, &res) == noErr) { - QVariant var(int(res.hRes)); - if (!resolutions.contains(var)) - resolutions.append(var); - } -#endif - } else if (status == noErr) { + if (status == noErr) { // According to the docs, index start at 1. for (UInt32 i = 1; i <= resCount; ++i) { if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr) @@ -617,6 +633,9 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_PaperSize: d->setPaperSize(QPrinter::PaperSize(value.toInt())); break; + case PPK_PaperName: + d->setPaperName(value.toString()); + break; case PPK_PrinterName: { bool printerNameSet = false; OSStatus status = noErr; @@ -755,6 +774,9 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_PaperSize: ret = d->paperSize(); break; + case PPK_PaperName: + ret = QCFString::toQString([d->printInfo localizedPaperName]); + break; case PPK_PaperRect: { QRect r; PMRect macrect; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index e122cc5822..28183118d8 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -53,6 +53,8 @@ // We mean it. // +#include <QtCore/qglobal.h> + #ifndef QT_NO_PRINTER #include <QtPrintSupport/qprinter.h> @@ -142,6 +144,7 @@ public: bool newPage_helper(); void setPaperSize(QPrinter::PaperSize ps); QPrinter::PaperSize paperSize() const; + void setPaperName(const QString &name); QList<QVariant> supportedResolutions() const; inline bool isPrintSessionInitialized() const { |