diff options
-rwxr-xr-x | src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 96 | ||||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/icons.qrc | 11 | ||||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray16x16.png | bin | 0 -> 101 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray18x18.png | bin | 0 -> 108 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray25x15.png | bin | 0 -> 109 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray32x32.png | bin | 0 -> 117 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray36x36.png | bin | 0 -> 151 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray50x30.png | bin | 0 -> 167 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/macsystray64x64.png | bin | 0 -> 204 bytes | |||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/main.cpp | 88 | ||||
-rw-r--r-- | tests/manual/cocoa/qsystemtrayicon/qsystemtrayicon.pro | 7 |
11 files changed, 170 insertions, 32 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index 83c960d931..e449fd37d6 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -187,6 +187,14 @@ void QCocoaSystemTrayIcon::cleanup() m_sys = 0; } +static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); } +static QList<QSize> sortByHeight(const QList<QSize> sizes) +{ + QList<QSize> sorted = sizes; + std::sort(sorted.begin(), sorted.end(), heightCompareFunction); + return sorted; +} + void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) { if (!m_sys) @@ -196,16 +204,62 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; + // The reccomended maximum title bar icon height is 18 points + // (device independent pixels). The menu height on past and + // current OS X versions is 22 points. Provide some future-proofing + // by deriving the icon height from the menu height. + const int padding = 4; + const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + const int maxImageHeight = menuHeight - padding; + + // Select pixmap based on the device pixel height. Ideally we would use + // the devicePixelRatio of the target screen, but that value is not + // known until draw time. Use qApp->devicePixelRatio, which returns the + // devicePixelRatio for the "best" screen on the system. + qreal devicePixelRatio = qApp->devicePixelRatio(); + const int maxPixmapHeight = maxImageHeight * devicePixelRatio; + const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal; + QSize selectedSize; + Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) { + // Select a pixmap based on the height. We want the largest pixmap + // with a height smaller or equal to maxPixmapHeight. The pixmap + // may rectangular; assume it has a reasonable size. If there is + // not suitable pixmap use the smallest one the icon can provide. + if (size.height() <= maxPixmapHeight) { + selectedSize = size; + } else { + if (!selectedSize.isValid()) + selectedSize = size; + break; + } + } - QPixmap pm = m_sys->item->icon.pixmap(QSize(scale, scale), - menuVisible ? QIcon::Selected : QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); + QPixmap pixmap = icon.pixmap(selectedSize, mode); + + // Draw a low-resolution icon if there is not enough pixels for a retina + // icon. This prevents showing a small icon on retina displays. + if (devicePixelRatio > 1.0 && selectedSize.height() < maxPixmapHeight / 2) + devicePixelRatio = 1.0; + + // Scale large pixmaps to fit the available menu bar area. + if (pixmap.height() > maxPixmapHeight) + pixmap = pixmap.scaledToHeight(maxPixmapHeight, Qt::SmoothTransformation); + + // The icon will be stretched over the full height of the menu bar + // therefore we create a second pixmap which has the full height + QSize fullHeightSize(!pixmap.isNull() ? pixmap.width(): + menuHeight * devicePixelRatio, + menuHeight * devicePixelRatio); + QPixmap fullHeightPixmap(fullHeightSize); + fullHeightPixmap.fill(Qt::transparent); + if (!pixmap.isNull()) { + QPainter p(&fullHeightPixmap); + QRect r = pixmap.rect(); + r.moveCenter(fullHeightPixmap.rect().center()); + p.drawPixmap(r, pixmap); } - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); + + NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap)); [(NSImageView*)[[m_sys->item item] view] setImage: nsimage]; [nsimage release]; } @@ -327,18 +381,7 @@ QT_END_NAMESPACE Q_UNUSED(notification); down = NO; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; - - QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); - } - NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); - [self setImage: nsaltimage]; - [nsaltimage release]; - + parent->systray->updateIcon(parent->icon); parent->menuVisible = false; [self setNeedsDisplay:YES]; @@ -350,18 +393,7 @@ QT_END_NAMESPACE int clickCount = [mouseEvent clickCount]; [self setNeedsDisplay:YES]; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; - - QPixmap pm = parent->icon.pixmap(QSize(scale, scale), - parent->menuVisible ? QIcon::Selected : QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); - } - NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); - [self setImage: nsaltimage]; - [nsaltimage release]; + parent->systray->updateIcon(parent->icon); if (clickCount == 2) { [self menuTrackingDone:nil]; diff --git a/tests/manual/cocoa/qsystemtrayicon/icons.qrc b/tests/manual/cocoa/qsystemtrayicon/icons.qrc new file mode 100644 index 0000000000..2486dcab34 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/icons.qrc @@ -0,0 +1,11 @@ +<RCC> + <qresource prefix="/"> + <file>macsystray18x18.png</file> + <file>macsystray36x36.png</file> + <file>macsystray25x15.png</file> + <file>macsystray50x30.png</file> + <file>macsystray16x16.png</file> + <file>macsystray32x32.png</file> + <file>macsystray64x64.png</file> + </qresource> +</RCC> diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray16x16.png b/tests/manual/cocoa/qsystemtrayicon/macsystray16x16.png Binary files differnew file mode 100644 index 0000000000..e6930f16c6 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray16x16.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray18x18.png b/tests/manual/cocoa/qsystemtrayicon/macsystray18x18.png Binary files differnew file mode 100644 index 0000000000..4316516d85 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray18x18.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray25x15.png b/tests/manual/cocoa/qsystemtrayicon/macsystray25x15.png Binary files differnew file mode 100644 index 0000000000..c1a98b898c --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray25x15.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray32x32.png b/tests/manual/cocoa/qsystemtrayicon/macsystray32x32.png Binary files differnew file mode 100644 index 0000000000..35f0f28ae7 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray32x32.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray36x36.png b/tests/manual/cocoa/qsystemtrayicon/macsystray36x36.png Binary files differnew file mode 100644 index 0000000000..d2c6df066c --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray36x36.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray50x30.png b/tests/manual/cocoa/qsystemtrayicon/macsystray50x30.png Binary files differnew file mode 100644 index 0000000000..afea90b7fe --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray50x30.png diff --git a/tests/manual/cocoa/qsystemtrayicon/macsystray64x64.png b/tests/manual/cocoa/qsystemtrayicon/macsystray64x64.png Binary files differnew file mode 100644 index 0000000000..b2a126d78f --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/macsystray64x64.png diff --git a/tests/manual/cocoa/qsystemtrayicon/main.cpp b/tests/manual/cocoa/qsystemtrayicon/main.cpp new file mode 100644 index 0000000000..9b3fc2bd13 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite 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$ +** +****************************************************************************/ +#include <QtWidgets> + +int main(int argc, char**argv) +{ + QApplication app(argc, argv); + + QWidget window; + window.show(); + + QSystemTrayIcon systrayIcon(&window); + + + enum Iconset { Square, // square icons, reccomended size (18 device-independent pixels or less) + Rectangular, // rectangular icons, good size + PowerOfTwo, // standard pow-2 icons, not optimized for the OS X menu bar + Small, // Not enough pixels + UnreasonablyLarge // please do something reasonable with my unreasonably large pixmap + }; + + // Select icon set and load images + Iconset iconset = Square; + QIcon icon; + switch (iconset) { + case Square: + icon.addFile(":/macsystray36x36.png"); + icon.addFile(":/macsystray18x18.png"); + break; + case Rectangular: + icon.addFile(":/macsystray50x30.png"); + icon.addFile(":/macsystray25x15.png"); + break; + case PowerOfTwo: + icon.addFile(":/macsystray16x16.png"); + icon.addFile(":/macsystray32x32.png"); + icon.addFile(":/macsystray64x64.png"); + break; + case Small: + icon.addFile(":/macsystray16x16.png"); + case UnreasonablyLarge: + icon.addFile(":/macsystray64x64.png"); + break; + } + + systrayIcon.setIcon(icon); + systrayIcon.show(); + + return app.exec(); +} diff --git a/tests/manual/cocoa/qsystemtrayicon/qsystemtrayicon.pro b/tests/manual/cocoa/qsystemtrayicon/qsystemtrayicon.pro new file mode 100644 index 0000000000..459ebafa38 --- /dev/null +++ b/tests/manual/cocoa/qsystemtrayicon/qsystemtrayicon.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = qsystemtrayicon +INCLUDEPATH += . +QT += widgets + +SOURCES += main.cpp +RESOURCES += icons.qrc |