macOS: Fall back to QWindow::icon for application icon if not set

There are three ways to set the application (Dock/task switcher) icon:

 1. By setting an ICON in the project file
 2. By calling QGuiApplication::setWindowIcon
 3. By calling QWindow::setIcon

The third one was not working on macOS, despite being documented as
such: "The window icon might be used by the windowing system for example
to decorate the window, and/or in the task switcher."

We now update the application icon based on the active window,
unless a global application icon has been set using ICON, or
via QGuiApplication::setWindowIcon. The reason for not allowing
the window's icon to override a global application icon is that
the developer may have intended to set the document icon for a
window (to represent QWindow::filePath), and we don't want that
to affect the Dock icon of the application.

The role of QGuiApplication::setWindowIcon is a bit dubious in this,
as it's documented as "This property holds the default window icon",
which would indicate it should follow the same logic as above by not
letting it override the global ICON set in the project file, but this
would not allow runtime switching of the application icon, so the
QGuiApplication property is left as is. The property should probably
have been named QGuiApplication::applicationIcon initially.

Task-number: QTBUG-63340
Change-Id: I94d3710a8586bb729af42f59a915b8f49dded101
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Tor Arne Vestbø 2017-11-06 14:52:13 +01:00
parent 28c1e17aef
commit 59c5f7bd9d
2 changed files with 37 additions and 1 deletions

View File

@ -60,8 +60,9 @@ QT_BEGIN_NAMESPACE
class QCocoaScreen;
class QCocoaIntegration : public QPlatformIntegration
class QCocoaIntegration : public QObject, public QPlatformIntegration
{
Q_OBJECT
public:
enum Option {
UseFreeTypeFontEngine = 0x1
@ -120,6 +121,9 @@ public:
void beep() const Q_DECL_OVERRIDE;
private Q_SLOTS:
void focusWindowChanged(QWindow *);
private:
static QCocoaIntegration *mInstance;
Options mOptions;

View File

@ -179,6 +179,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
QMacInternalPasteboardMime::initializeMimeTypes();
QCocoaMimeTypes::initializeMimeTypes();
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
connect(qGuiApp, &QGuiApplication::focusWindowChanged,
this, &QCocoaIntegration::focusWindowChanged);
}
QCocoaIntegration::~QCocoaIntegration()
@ -510,4 +513,33 @@ void QCocoaIntegration::beep() const
NSBeep();
}
void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow)
{
// Don't revert icon just because we lost focus
if (!focusWindow)
return;
static bool hasDefaultApplicationIcon = [](){
NSImage *genericApplicationIcon = [[NSWorkspace sharedWorkspace]
iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)];
NSImage *applicationIcon = [NSImage imageNamed:NSImageNameApplicationIcon];
NSRect rect = NSMakeRect(0, 0, 32, 32);
return [applicationIcon CGImageForProposedRect:&rect context:nil hints:nil]
== [genericApplicationIcon CGImageForProposedRect:&rect context:nil hints:nil];
}();
// Don't let the window icon override an explicit application icon set in the Info.plist
if (!hasDefaultApplicationIcon)
return;
// Or an explicit application icon set on QGuiApplication
if (!qGuiApp->windowIcon().isNull())
return;
setApplicationIcon(focusWindow->icon());
}
#include "moc_qcocoaintegration.cpp"
QT_END_NAMESPACE