From 50c04d631858639c630e85456e7e003a80e33493 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 2 Jul 2014 16:46:24 +0200 Subject: Session management for OS X This patch aims to implement the session management available on OS X. Currently applicationShouldTerminate is just a go through that closes everything and ends the application. The new implementation calls first appCommitData and cancels the termination properly if required. This means that if a user wishes to logout, Qt applications can now cancel that like e.g. answering to Safari asking whether it is ok to close because of a number of opened tab/window. Task-number: QTBUG-33034 Change-Id: Icedc8590a1c0934d9bc87d3a43d6702a9903bfb8 Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/cocoa.pro | 6 +- .../platforms/cocoa/qcocoaapplicationdelegate.mm | 31 +++++---- src/plugins/platforms/cocoa/qcocoaintegration.h | 8 +++ src/plugins/platforms/cocoa/qcocoaintegration.mm | 8 +++ .../platforms/cocoa/qcocoasessionmanager.cpp | 70 +++++++++++++++++++ src/plugins/platforms/cocoa/qcocoasessionmanager.h | 79 ++++++++++++++++++++++ 6 files changed, 186 insertions(+), 16 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoasessionmanager.cpp create mode 100644 src/plugins/platforms/cocoa/qcocoasessionmanager.h (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index ad6cb3a1fc..b8befcd497 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -41,7 +41,8 @@ OBJECTIVE_SOURCES += main.mm \ qcocoakeymapper.mm \ qcocoamimetypes.mm -SOURCES += messages.cpp +SOURCES += messages.cpp \ + qcocoasessionmanager.cpp HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -76,7 +77,8 @@ HEADERS += qcocoaintegration.h \ qcocoaintrospection.h \ qcocoakeymapper.h \ messages.h \ - qcocoamimetypes.h + qcocoamimetypes.h \ + qcocoasessionmanager.h contains(QT_CONFIG, opengl.*) { OBJECTIVE_SOURCES += qcocoaglcontext.mm diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index efe3269d42..6c39f1eb5a 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2013 Samuel Gaist ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -78,11 +79,13 @@ #import "qnswindowdelegate.h" #import "qcocoamenuloader.h" #include "qcocoaintegration.h" +#include "qcocoasessionmanager.h" #include #include #include #include #include +#include #include "qt_mac_p.h" #include @@ -216,6 +219,17 @@ static void cleanupCocoaApplicationDelegate() return NSTerminateNow; } + QGuiApplicationPrivate *qGuiAppPriv = QGuiApplicationPrivate::instance(); + +#ifndef QT_NO_SESSIONMANAGER + QSessionManagerPrivate *managerPrivate = static_cast(QObjectPrivate::get(qGuiAppPriv->session_manager)); + QCocoaSessionManager *cocoaSessionManager = static_cast(managerPrivate->platformSessionManager); + cocoaSessionManager->appCommitData(); + + if (cocoaSessionManager->wasCanceled()) + return NSTerminateCancel; +#endif + if ([self canQuit]) { if (!startedQuit) { startedQuit = true; @@ -239,7 +253,7 @@ static void cleanupCocoaApplicationDelegate() } } - if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) { + if (qGuiAppPriv->threadData->eventLoops.isEmpty()) { // INVARIANT: No event loop is executing. This probably // means that Qt is used as a plugin, or as a part of a native // Cocoa application. In any case it should be fine to @@ -269,10 +283,6 @@ static void cleanupCocoaApplicationDelegate() 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 @@ -283,7 +293,6 @@ static void cleanupCocoaApplicationDelegate() - (void) removeAppleEventHandlers { NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager]; - [eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication]; [eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL]; } @@ -330,7 +339,8 @@ static void cleanupCocoaApplicationDelegate() && [reflectionDelegate respondsToSelector: @selector(applicationShouldTerminateAfterLastWindowClosed:)]) return [reflectionDelegate applicationShouldTerminateAfterLastWindowClosed:sender]; - return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together. + + return qApp->quitOnLastWindowClosed(); } @@ -436,13 +446,6 @@ static void cleanupCocoaApplicationDelegate() QWindowSystemInterface::handleFileOpenEvent(QUrl(QCFString::toQString(urlString))); } -- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent -{ - Q_UNUSED(event); - Q_UNUSED(replyEvent); - [NSApp terminate:self]; -} - - (void)qtDispatcherToQAction:(id)sender { Q_UNUSED(sender); diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 5ca2ccc571..9942ac09cc 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -141,6 +141,14 @@ public: void setToolbar(QWindow *window, NSToolbar *toolbar); NSToolbar *toolbar(QWindow *window) const; void clearToolbars(); + + void setWindow(NSWindow* nsWindow, QCocoaWindow *window); + QCocoaWindow *window(NSWindow *window); + +#ifndef QT_NO_SESSIONMANAGER + QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const; +#endif + private: static QCocoaIntegration *mInstance; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 4be49ed68f..49e602f45c 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -54,6 +54,7 @@ #include "qcocoainputcontext.h" #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" +#include "qcocoasessionmanager.h" #include #include @@ -416,6 +417,13 @@ QCocoaScreen *QCocoaIntegration::screenAtIndex(int index) return mScreens.at(index); } +#ifndef QT_NO_SESSIONMANAGER +QPlatformSessionManager *QCocoaIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + return new QCocoaSessionManager(id, key); +} +#endif + bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp new file mode 100644 index 0000000000..9d0df65bc8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Samuel Gaist +** 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$ +** +****************************************************************************/ + +#ifndef QT_NO_SESSIONMANAGER +#include +#include + +QT_BEGIN_NAMESPACE + +QCocoaSessionManager::QCocoaSessionManager(const QString &id, const QString &key) + : QPlatformSessionManager(id, key), + m_canceled(false) +{ +} + +QCocoaSessionManager::~QCocoaSessionManager() +{ +} + +void QCocoaSessionManager::cancel() +{ + m_canceled = true; +} + +bool QCocoaSessionManager::wasCanceled() const +{ + return m_canceled; +} + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.h b/src/plugins/platforms/cocoa/qcocoasessionmanager.h new file mode 100644 index 0000000000..fe9ba1d075 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Samuel Gaist +** 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$ +** +****************************************************************************/ + +#ifndef QCOCOASESSIONMANAGER_H +#define QCOCOASESSIONMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#ifndef QT_NO_SESSIONMANAGER + +#include + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QCocoaSessionManager : public QPlatformSessionManager +{ +public: + QCocoaSessionManager(const QString &id, const QString &key); + virtual ~QCocoaSessionManager(); + + void cancel() Q_DECL_OVERRIDE; + bool wasCanceled() const; + +private: + bool m_canceled; + + Q_DISABLE_COPY(QCocoaSessionManager) +}; + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER + +#endif // QCOCOASESSIONMANAGER_H -- cgit v1.2.3