summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm78
-rwxr-xr-xsrc/plugins/platforms/cocoa/qcocoasystemtrayicon.h80
-rwxr-xr-xsrc/plugins/platforms/cocoa/qcocoasystemtrayicon.mm465
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm8
7 files changed, 643 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index ac79ccc414..106664a6b0 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -35,6 +35,7 @@ OBJECTIVE_SOURCES += main.mm \
qcocoasystemsettings.mm \
qcocoainputcontext.mm \
qcocoaservices.mm \
+ qcocoasystemtrayicon.mm \
HEADERS += qcocoaintegration.h \
qcocoatheme.h \
@@ -67,6 +68,7 @@ HEADERS += qcocoaintegration.h \
qcocoasystemsettings.h \
qcocoainputcontext.h \
qcocoaservices.h \
+ qcocoasystemtrayicon.h \
RESOURCES += qcocoaresources.qrc
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index f8032603e5..dac7118731 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -115,6 +115,12 @@ inline NSPoint qt_mac_flipPoint(const QPointF &p)
NSRect qt_mac_flipRect(const QRect &rect, QWindow *window);
+Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
+
+bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret);
+bool qt_mac_execute_apple_script(const char *script, AEDesc *ret);
+bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret);
+
// strip out '&' characters, and convert "&&" to a single '&', in menu
// text - since menu text is sometimes decorated with these for Windows
// accelerators.
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index c0b6f3abb6..8b09570892 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -581,6 +581,84 @@ CGFloat qt_mac_get_scalefactor()
return [[NSScreen mainScreen] userSpaceScaleFactor];
}
+Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
+{
+ switch (buttonNum) {
+ case 0:
+ return Qt::LeftButton;
+ case 1:
+ return Qt::RightButton;
+ case 2:
+ return Qt::MidButton;
+ case 3:
+ return Qt::XButton1;
+ case 4:
+ return Qt::XButton2;
+ default:
+ return Qt::NoButton;
+ }
+}
+
+bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) {
+ OSStatus err;
+ AEDesc scriptTextDesc;
+ ComponentInstance theComponent = 0;
+ OSAID scriptID = kOSANullScript, resultID = kOSANullScript;
+
+ // set up locals to a known state
+ AECreateDesc(typeNull, 0, 0, &scriptTextDesc);
+ scriptID = kOSANullScript;
+ resultID = kOSANullScript;
+
+ // open the scripting component
+ theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
+ if (!theComponent) {
+ err = paramErr;
+ goto bail;
+ }
+
+ // put the script text into an aedesc
+ err = AECreateDesc(typeUTF8Text, script, script_len, &scriptTextDesc);
+ if (err != noErr)
+ goto bail;
+
+ // compile the script
+ err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID);
+ if (err != noErr)
+ goto bail;
+
+ // run the script
+ err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID);
+
+ // collect the results - if any
+ if (ret) {
+ AECreateDesc(typeNull, 0, 0, ret);
+ if (err == errOSAScriptError)
+ OSAScriptError(theComponent, kOSAErrorMessage, typeChar, ret);
+ else if (err == noErr && resultID != kOSANullScript)
+ OSADisplay(theComponent, resultID, typeChar, kOSAModeNull, ret);
+ }
+bail:
+ AEDisposeDesc(&scriptTextDesc);
+ if (scriptID != kOSANullScript)
+ OSADispose(theComponent, scriptID);
+ if (resultID != kOSANullScript)
+ OSADispose(theComponent, resultID);
+ if (theComponent)
+ CloseComponent(theComponent);
+ return err == noErr;
+}
+
+bool qt_mac_execute_apple_script(const char *script, AEDesc *ret)
+{
+ return qt_mac_execute_apple_script(script, qstrlen(script), ret);
+}
+
+bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret)
+{
+ const QByteArray l = script.toUtf8(); return qt_mac_execute_apple_script(l.constData(), l.size(), ret);
+}
+
QString qt_mac_removeAmpersandEscapes(QString s)
{
int i = 0;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
new file mode 100755
index 0000000000..c9592cd470
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOASYSTEMTRAYICON_P_H
+#define QCOCOASYSTEMTRAYICON_P_H
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "QtCore/qstring.h"
+#include "QtGui/qpa/qplatformsystemtrayicon.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSystemTrayIconSys;
+
+class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon
+{
+public:
+ QCocoaSystemTrayIcon() : m_sys(0) {}
+
+ virtual void init();
+ virtual void cleanup();
+ virtual void updateIcon(const QIcon &icon);
+ virtual void updateToolTip(const QString &toolTip);
+ virtual void updateMenu(QPlatformMenu *menu);
+ virtual QRect geometry() const;
+ virtual void showMessage(const QString &msg, const QString &title,
+ const QIcon& icon, MessageIcon iconType, int secs);
+
+ virtual bool isSystemTrayAvailable() const;
+ virtual bool supportsMessages() const;
+
+private:
+ QSystemTrayIconSys *m_sys;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMTRAYICON
+
+#endif // QCOCOASYSTEMTRAYICON_P_H
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
new file mode 100755
index 0000000000..ce775fd0cb
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Copyright (c) 2007-2008, Apple, Inc.
+**
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** * Neither the name of Apple, Inc. nor the names of its contributors
+** may be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#define QT_MAC_SYSTEMTRAY_USE_GROWL
+
+#include "qcocoasystemtrayicon.h"
+#include <qtemporaryfile.h>
+#include <qimagewriter.h>
+#include <qapplication.h>
+#include <qdebug.h>
+
+#include "qcocoamenu.h"
+
+#include "qt_mac_p.h"
+#include "qcocoahelpers.h"
+
+#import <AppKit/AppKit.h>
+
+QT_USE_NAMESPACE
+
+@class QT_MANGLE_NAMESPACE(QNSMenu);
+@class QT_MANGLE_NAMESPACE(QNSImageView);
+
+@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject {
+@public
+ QCocoaSystemTrayIcon *systray;
+ NSStatusItem *item;
+ QCocoaMenu *menu;
+ bool menuVisible;
+ QIcon icon;
+ QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
+}
+-(id)initWithSysTray:(QCocoaSystemTrayIcon *)systray;
+-(void)dealloc;
+-(NSStatusItem*)item;
+-(QRectF)geometry;
+- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
+- (void)doubleClickSelector:(id)sender;
+@end
+
+@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView {
+ BOOL down;
+ QT_MANGLE_NAMESPACE(QNSStatusItem) *parent;
+}
+-(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent;
+-(void)menuTrackingDone:(NSNotification*)notification;
+-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
+@end
+
+@interface QT_MANGLE_NAMESPACE(QNSMenu) : NSMenu <NSMenuDelegate> {
+ QPlatformMenu *qmenu;
+}
+-(QPlatformMenu*)menu;
+-(id)initWithQMenu:(QPlatformMenu*)qmenu;
+@end
+
+QT_BEGIN_NAMESPACE
+class QSystemTrayIconSys
+{
+public:
+ QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) {
+ item = [[QT_MANGLE_NAMESPACE(QNSStatusItem) alloc] initWithSysTray:sys];
+ }
+ ~QSystemTrayIconSys() {
+ [[[item item] view] setHidden: YES];
+ [item release];
+ }
+ QT_MANGLE_NAMESPACE(QNSStatusItem) *item;
+};
+
+void QCocoaSystemTrayIcon::init()
+{
+ if (!m_sys)
+ m_sys = new QSystemTrayIconSys(this);
+}
+
+QRect QCocoaSystemTrayIcon::geometry() const
+{
+ if (!m_sys)
+ return QRect();
+
+ const QRectF geom = [m_sys->item geometry];
+ if (!geom.isNull())
+ return geom.toRect();
+ else
+ return QRect();
+}
+
+void QCocoaSystemTrayIcon::cleanup()
+{
+ delete m_sys;
+ m_sys = 0;
+}
+
+void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
+{
+ if (!m_sys)
+ return;
+
+ m_sys->item->icon = icon;
+
+ const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
+
+ CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
+ const short scale = hgt - 4;
+
+ 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);
+ }
+ NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
+ [(NSImageView*)[[m_sys->item item] view] setImage: nsimage];
+ [nsimage release];
+}
+
+void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu)
+{
+ if (!m_sys)
+ return;
+
+ m_sys->item->menu = static_cast<QCocoaMenu *>(menu);
+ if (menu && [m_sys->item->menu->nsMenu() numberOfItems] > 0) {
+ [[m_sys->item item] setHighlightMode:YES];
+ } else {
+ [[m_sys->item item] setHighlightMode:NO];
+ }
+}
+
+void QCocoaSystemTrayIcon::updateToolTip(const QString &toolTip)
+{
+ if (!m_sys)
+ return;
+ [[[m_sys->item item] view] setToolTip:QCFString::toNSString(toolTip)];
+}
+
+bool QCocoaSystemTrayIcon::isSystemTrayAvailable() const
+{
+ return true;
+}
+
+bool QCocoaSystemTrayIcon::supportsMessages() const
+{
+ return true;
+}
+
+void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message,
+ const QIcon& icon, MessageIcon, int)
+{
+ if (!m_sys)
+ return;
+
+#ifdef QT_MAC_SYSTEMTRAY_USE_GROWL
+ // Make sure that we have Growl installed on the machine we are running on.
+ QCFType<CFURLRef> cfurl;
+ OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator,
+ CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
+ if (status == kLSApplicationNotFoundErr)
+ return;
+ QCFType<CFBundleRef> bundle = CFBundleCreate(0, cfurl);
+
+ if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"),
+ kCFCompareCaseInsensitive | kCFCompareBackwards) != kCFCompareEqualTo)
+ return;
+ QPixmap notificationIconPixmap = icon.pixmap(32, 32);
+ QTemporaryFile notificationIconFile;
+ QString notificationType(QLatin1String("Notification")), notificationIcon, notificationApp(QApplication::applicationName());
+ if (notificationApp.isEmpty())
+ notificationApp = QLatin1String("Application");
+ if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
+ QImageWriter writer(&notificationIconFile, "PNG");
+ if (writer.write(notificationIconPixmap.toImage()))
+ notificationIcon = QLatin1String("image from location \"file://") + notificationIconFile.fileName() + QLatin1String("\"");
+ }
+ const QString script(QLatin1String(
+ "tell application \"System Events\"\n"
+ "set isRunning to (count of (every process whose bundle identifier is \"com.Growl.GrowlHelperApp\")) > 0\n"
+ "end tell\n"
+ "if isRunning\n"
+ "tell application id \"com.Growl.GrowlHelperApp\"\n"
+ "-- Make a list of all the notification types (all)\n"
+ "set the allNotificationsList to {\"") + notificationType + QLatin1String("\"}\n"
+
+ "-- Make a list of the notifications (enabled)\n"
+ "set the enabledNotificationsList to {\"") + notificationType + QLatin1String("\"}\n"
+
+ "-- Register our script with growl.\n"
+ "register as application \"") + notificationApp + QLatin1String("\" all notifications allNotificationsList default notifications enabledNotificationsList\n"
+
+ "-- Send a Notification...\n") +
+ QLatin1String("notify with name \"") + notificationType +
+ QLatin1String("\" title \"") + title +
+ QLatin1String("\" description \"") + message +
+ QLatin1String("\" application name \"") + notificationApp +
+ QLatin1String("\" ") + notificationIcon +
+ QLatin1String("\nend tell\nend if"));
+ qt_mac_execute_apple_script(script, 0);
+#else
+ Q_UNUSED(icon);
+ Q_UNUSED(title);
+ Q_UNUSED(message);
+#endif
+}
+QT_END_NAMESPACE
+
+@implementation NSStatusItem (Qt)
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSImageView)
+-(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent {
+ self = [super init];
+ parent = myParent;
+ down = NO;
+ return self;
+}
+
+-(void)menuTrackingDone:(NSNotification*)notification
+{
+ 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->menuVisible = false;
+
+ [self setNeedsDisplay:YES];
+}
+
+-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton
+{
+ down = YES;
+ 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];
+
+ if (clickCount == 2) {
+ [self menuTrackingDone:nil];
+ [parent doubleClickSelector:self];
+ } else {
+ [parent triggerSelector:self button:mouseButton];
+ }
+}
+
+-(void)mouseDown:(NSEvent *)mouseEvent
+{
+ [self mousePressed:mouseEvent button:Qt::LeftButton];
+}
+
+-(void)mouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
+}
+
+- (void)rightMouseDown:(NSEvent *)mouseEvent
+{
+ [self mousePressed:mouseEvent button:Qt::RightButton];
+}
+
+-(void)rightMouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
+}
+
+- (void)otherMouseDown:(NSEvent *)mouseEvent
+{
+ [self mousePressed:mouseEvent button:cocoaButton2QtButton([mouseEvent buttonNumber])];
+}
+
+-(void)otherMouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
+}
+
+-(void)drawRect:(NSRect)rect {
+ [[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down];
+ [super drawRect:rect];
+}
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSStatusItem)
+
+-(id)initWithSysTray:(QCocoaSystemTrayIcon *)sys
+{
+ self = [super init];
+ if (self) {
+ item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
+ menu = 0;
+ menuVisible = false;
+ systray = sys;
+ imageCell = [[QT_MANGLE_NAMESPACE(QNSImageView) alloc] initWithParent:self];
+ [item setView: imageCell];
+ }
+ return self;
+}
+
+-(void)dealloc {
+ [[NSStatusBar systemStatusBar] removeStatusItem:item];
+ [imageCell release];
+ [item release];
+ [super dealloc];
+
+}
+
+-(NSStatusItem*)item {
+ return item;
+}
+-(QRectF)geometry {
+ if (NSWindow *window = [[item view] window]) {
+ NSRect screenRect = [[window screen] frame];
+ NSRect windowRect = [window frame];
+ return QRectF(windowRect.origin.x, screenRect.size.height-windowRect.origin.y-windowRect.size.height, windowRect.size.width, windowRect.size.height);
+ }
+ return QRectF();
+}
+
+- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton {
+ Q_UNUSED(sender);
+ if (!systray)
+ return;
+
+ if (mouseButton == Qt::MidButton)
+ emit systray->activated(QPlatformSystemTrayIcon::MiddleClick);
+ else
+ emit systray->activated(QPlatformSystemTrayIcon::Trigger);
+
+ if (menu) {
+ NSMenu *m = menu->nsMenu();
+ [[NSNotificationCenter defaultCenter] addObserver:imageCell
+ selector:@selector(menuTrackingDone:)
+ name:NSMenuDidEndTrackingNotification
+ object:m];
+ menuVisible = true;
+ [item popUpStatusItemMenu: m];
+ }
+}
+
+- (void)doubleClickSelector:(id)sender {
+ Q_UNUSED(sender);
+ if (!systray)
+ return;
+ emit systray->activated(QPlatformSystemTrayIcon::DoubleClick);
+}
+
+@end
+
+class QSystemTrayIconQMenu : public QPlatformMenu
+{
+public:
+ void doAboutToShow() { emit aboutToShow(); }
+private:
+ QSystemTrayIconQMenu();
+};
+
+@implementation QT_MANGLE_NAMESPACE(QNSMenu)
+-(id)initWithQMenu:(QPlatformMenu*)qm {
+ self = [super init];
+ if (self) {
+ self->qmenu = qm;
+ [self setDelegate:self];
+ }
+ return self;
+}
+-(QPlatformMenu*)menu {
+ return qmenu;
+}
+@end
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index 3c071d44c3..dad3f86de4 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -58,6 +58,10 @@ public:
virtual QPlatformMenu* createPlatformMenu() const;
virtual QPlatformMenuBar* createPlatformMenuBar() const;
+#ifndef QT_NO_SYSTEMTRAYICON
+ QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const;
+#endif
+
bool usePlatformNativeDialog(DialogType dialogType) const;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const;
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 0eb2136027..6d4e240500 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -47,6 +47,7 @@
#include "qcocoafiledialoghelper.h"
#include "qcocoafontdialoghelper.h"
#include "qcocoasystemsettings.h"
+#include "qcocoasystemtrayicon.h"
#include "qcocoamenuitem.h"
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
@@ -103,6 +104,13 @@ QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialo
}
}
+#ifndef QT_NO_SYSTEMTRAYICON
+QPlatformSystemTrayIcon *QCocoaTheme::createPlatformSystemTrayIcon() const
+{
+ return new QCocoaSystemTrayIcon;
+}
+#endif
+
const QPalette *QCocoaTheme::palette(Palette type) const
{
if (type == SystemPalette) {