1 // Copyright (c) 2011-2013 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include "macdockiconhandler.h"
7 #include <QImageWriter>
13 #include <Cocoa/Cocoa.h>
14 #include <objc/objc.h>
15 #include <objc/message.h>
17 #if QT_VERSION < 0x050000
18 extern void qt_mac_set_dock_menu(QMenu *);
21 static MacDockIconHandler *s_instance = nullptr;
23 bool dockClickHandler(id self,SEL _cmd,...) {
27 s_instance->handleDockIconClickEvent();
29 // Return NO (false) to suppress the default OS X actions
33 void setupDockClickHandler() {
34 Class cls = objc_getClass("NSApplication");
35 id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication"));
37 if (appInst != nullptr) {
38 id delegate = objc_msgSend(appInst, sel_registerName("delegate"));
39 Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
40 SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
41 if (class_getInstanceMethod(delClass, shouldHandle))
42 class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
44 class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:");
49 MacDockIconHandler::MacDockIconHandler() : QObject()
51 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
53 setupDockClickHandler();
54 this->m_dummyWidget = new QWidget();
55 this->m_dockMenu = new QMenu(this->m_dummyWidget);
56 this->setMainWindow(nullptr);
57 #if QT_VERSION < 0x050000
58 qt_mac_set_dock_menu(this->m_dockMenu);
59 #elif QT_VERSION >= 0x050200
60 this->m_dockMenu->setAsDockMenu();
65 void MacDockIconHandler::setMainWindow(QMainWindow *window) {
66 this->mainWindow = window;
69 MacDockIconHandler::~MacDockIconHandler()
71 delete this->m_dummyWidget;
72 this->setMainWindow(nullptr);
75 QMenu *MacDockIconHandler::dockMenu()
77 return this->m_dockMenu;
80 void MacDockIconHandler::setIcon(const QIcon &icon)
82 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
85 image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
87 // generate NSImage from QIcon and use this as dock icon.
88 QSize size = icon.actualSize(QSize(128, 128));
89 QPixmap pixmap = icon.pixmap(size);
91 // Write image into a R/W buffer from raw pixmap, then save the image.
92 QBuffer notificationBuffer;
93 if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) {
94 QImageWriter writer(¬ificationBuffer, "PNG");
95 if (writer.write(pixmap.toImage())) {
96 NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data()
97 length:notificationBuffer.buffer().size()];
98 image = [[NSImage alloc] initWithData:macImgData];
103 // if testnet image could not be created, load std. app icon
104 image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
108 [NSApp setApplicationIconImage:image];
113 MacDockIconHandler *MacDockIconHandler::instance()
116 s_instance = new MacDockIconHandler();
120 void MacDockIconHandler::cleanup()
125 void MacDockIconHandler::handleDockIconClickEvent()
127 if (this->mainWindow)
129 this->mainWindow->activateWindow();
130 this->mainWindow->show();
133 Q_EMIT this->dockIconClicked();