OS X: Add support for ApplicationState capability

Currently a click on e.g. the dock icon is not propagated to the
application so if for example the main widget is hidden, it can't be
brought back. Also neither applicationDidBecomeActive nor
applicationDidResignActive do anything. This patch fixes it

[ChangeLog][QPA][OS X] Add support for ApplicationState capability.
Application can now detect when an application states has changed
as well when the dock icon has been clicked.

Task-number: QTBUG-10899
Change-Id: I53d3e6eed4adc62b343e7aa3e3d8068d3248e7df
Reviewed-by: Jake Petroules <jake.petroules@petroules.com>
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
bb10
Samuel Gaist 2014-04-22 18:22:23 +02:00 committed by The Qt Project
parent ceab0eb021
commit 787692a09e
7 changed files with 35 additions and 12 deletions

View File

@ -1528,8 +1528,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::WindowScreenChanged:
QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
break;
case QWindowSystemInterfacePrivate::ApplicationStateChanged:
QGuiApplicationPrivate::setApplicationState(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e)->newState);
case QWindowSystemInterfacePrivate::ApplicationStateChanged: {
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e);
QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); }
break;
case QWindowSystemInterfacePrivate::FlushEvents:
QWindowSystemInterface::deferredFlushWindowSystemEvents();
@ -2834,9 +2835,9 @@ Qt::ApplicationState QGuiApplication::applicationState()
\sa applicationState()
*/
void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state)
void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, bool forcePropagate)
{
if (applicationState == state)
if ((applicationState == state) && !forcePropagate)
return;
applicationState = state;

View File

@ -288,7 +288,7 @@ public:
static QRect applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window);
static void setApplicationState(Qt::ApplicationState state);
static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false);
protected:
virtual void notifyThemeChanged();

View File

@ -133,11 +133,11 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *tlw, QScreen *sc
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState)
void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate)
{
Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState);
new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}

View File

@ -148,7 +148,7 @@ public:
static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState);
static void handleWindowScreenChanged(QWindow *w, QScreen *newScreen);
static void handleApplicationStateChanged(Qt::ApplicationState newState);
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
static void handleExposeEvent(QWindow *tlw, const QRegion &region);

View File

@ -176,11 +176,12 @@ public:
class ApplicationStateChangedEvent : public WindowSystemEvent {
public:
ApplicationStateChangedEvent(Qt::ApplicationState newState)
: WindowSystemEvent(ApplicationStateChanged), newState(newState)
ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false)
: WindowSystemEvent(ApplicationStateChanged), newState(newState), forcePropagate(forcePropagate)
{ }
Qt::ApplicationState newState;
bool forcePropagate;
};
class FlushEventsEvent : public WindowSystemEvent {

View File

@ -333,6 +333,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
/*
onApplicationChangedActivation(true);
@ -356,6 +357,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
/*
onApplicationChangedActivation(false);
@ -367,6 +369,26 @@ static void cleanupCocoaApplicationDelegate()
*/
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
Q_UNUSED(theApplication);
Q_UNUSED(flag);
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
/*
true to force delivery of the event even if the application state is already active,
because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
of the active state of the application or number of visible windows. For example, a browser
app that has no windows opened would need the event be to delivered even if it was already
active in order to create a new window as per OS X conventions.
*/
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
return NO;
}
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];

View File

@ -405,14 +405,13 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case MultipleWindows:
case ForeignWindows:
case RasterGLSurface:
case ApplicationState:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
}
QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const
{
return new QCocoaWindow(window);