Changeset View
Changeset View
Standalone View
Standalone View
src/qt/macdockiconhandler.mm
// Copyright (c) 2011-2013 The Bitcoin Core developers | // Copyright (c) 2011-2013 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "macdockiconhandler.h" | #include "macdockiconhandler.h" | ||||
#include <QBuffer> | |||||
#include <QImageWriter> | #include <QImageWriter> | ||||
#include <QMenu> | #include <QMenu> | ||||
#include <QBuffer> | |||||
#include <QWidget> | #include <QWidget> | ||||
#undef slots | #undef slots | ||||
#include <Cocoa/Cocoa.h> | #include <Cocoa/Cocoa.h> | ||||
#include <objc/objc.h> | |||||
#include <objc/message.h> | #include <objc/message.h> | ||||
#include <objc/objc.h> | |||||
static MacDockIconHandler *s_instance = nullptr; | static MacDockIconHandler *s_instance = nullptr; | ||||
bool dockClickHandler(id self,SEL _cmd,...) { | bool dockClickHandler(id self, SEL _cmd, ...) { | ||||
Q_UNUSED(self) | Q_UNUSED(self) | ||||
Q_UNUSED(_cmd) | Q_UNUSED(_cmd) | ||||
s_instance->handleDockIconClickEvent(); | s_instance->handleDockIconClickEvent(); | ||||
// Return NO (false) to suppress the default OS X actions | // Return NO (false) to suppress the default OS X actions | ||||
return false; | return false; | ||||
} | } | ||||
void setupDockClickHandler() { | void setupDockClickHandler() { | ||||
Class cls = objc_getClass("NSApplication"); | Class cls = objc_getClass("NSApplication"); | ||||
id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication")); | id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication")); | ||||
if (appInst != nullptr) { | if (appInst != nullptr) { | ||||
id delegate = objc_msgSend(appInst, sel_registerName("delegate")); | id delegate = objc_msgSend(appInst, sel_registerName("delegate")); | ||||
Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class")); | Class delClass = | ||||
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"); | (Class)objc_msgSend(delegate, sel_registerName("class")); | ||||
SEL shouldHandle = sel_registerName( | |||||
"applicationShouldHandleReopen:hasVisibleWindows:"); | |||||
if (class_getInstanceMethod(delClass, shouldHandle)) | if (class_getInstanceMethod(delClass, shouldHandle)) | ||||
class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"); | class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, | ||||
"B@:"); | |||||
else | else | ||||
class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:"); | class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler, | ||||
"B@:"); | |||||
} | } | ||||
} | } | ||||
MacDockIconHandler::MacDockIconHandler() : QObject() { | |||||
MacDockIconHandler::MacDockIconHandler() : QObject() | |||||
{ | |||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | ||||
setupDockClickHandler(); | setupDockClickHandler(); | ||||
this->m_dummyWidget = new QWidget(); | this->m_dummyWidget = new QWidget(); | ||||
this->m_dockMenu = new QMenu(this->m_dummyWidget); | this->m_dockMenu = new QMenu(this->m_dummyWidget); | ||||
this->setMainWindow(nullptr); | this->setMainWindow(nullptr); | ||||
#if QT_VERSION >= 0x050200 | #if QT_VERSION >= 0x050200 | ||||
this->m_dockMenu->setAsDockMenu(); | this->m_dockMenu->setAsDockMenu(); | ||||
#endif | #endif | ||||
[pool release]; | [pool release]; | ||||
} | } | ||||
void MacDockIconHandler::setMainWindow(QMainWindow *window) { | void MacDockIconHandler::setMainWindow(QMainWindow *window) { | ||||
this->mainWindow = window; | this->mainWindow = window; | ||||
} | } | ||||
MacDockIconHandler::~MacDockIconHandler() | MacDockIconHandler::~MacDockIconHandler() { | ||||
{ | |||||
delete this->m_dummyWidget; | delete this->m_dummyWidget; | ||||
this->setMainWindow(nullptr); | this->setMainWindow(nullptr); | ||||
} | } | ||||
QMenu *MacDockIconHandler::dockMenu() | QMenu *MacDockIconHandler::dockMenu() { | ||||
{ | |||||
return this->m_dockMenu; | return this->m_dockMenu; | ||||
} | } | ||||
void MacDockIconHandler::setIcon(const QIcon &icon) | void MacDockIconHandler::setIcon(const QIcon &icon) { | ||||
{ | |||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | ||||
NSImage *image = nil; | NSImage *image = nil; | ||||
if (icon.isNull()) | if (icon.isNull()) | ||||
image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; | image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; | ||||
else { | else { | ||||
// generate NSImage from QIcon and use this as dock icon. | // generate NSImage from QIcon and use this as dock icon. | ||||
QSize size = icon.actualSize(QSize(128, 128)); | QSize size = icon.actualSize(QSize(128, 128)); | ||||
QPixmap pixmap = icon.pixmap(size); | QPixmap pixmap = icon.pixmap(size); | ||||
// Write image into a R/W buffer from raw pixmap, then save the image. | // Write image into a R/W buffer from raw pixmap, then save the image. | ||||
QBuffer notificationBuffer; | QBuffer notificationBuffer; | ||||
if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) { | if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) { | ||||
QImageWriter writer(¬ificationBuffer, "PNG"); | QImageWriter writer(¬ificationBuffer, "PNG"); | ||||
if (writer.write(pixmap.toImage())) { | if (writer.write(pixmap.toImage())) { | ||||
NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data() | NSData *macImgData = | ||||
[NSData dataWithBytes:notificationBuffer.buffer().data() | |||||
length:notificationBuffer.buffer().size()]; | length:notificationBuffer.buffer().size()]; | ||||
image = [[NSImage alloc] initWithData:macImgData]; | image = [[NSImage alloc] initWithData:macImgData]; | ||||
} | } | ||||
} | } | ||||
if(!image) { | if (!image) { | ||||
// if testnet image could not be created, load std. app icon | // if testnet image could not be created, load std. app icon | ||||
image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; | image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; | ||||
} | } | ||||
} | } | ||||
[NSApp setApplicationIconImage:image]; | [NSApp setApplicationIconImage:image]; | ||||
[image release]; | [image release]; | ||||
[pool release]; | [pool release]; | ||||
} | } | ||||
MacDockIconHandler *MacDockIconHandler::instance() | MacDockIconHandler *MacDockIconHandler::instance() { | ||||
{ | if (!s_instance) s_instance = new MacDockIconHandler(); | ||||
if (!s_instance) | |||||
s_instance = new MacDockIconHandler(); | |||||
return s_instance; | return s_instance; | ||||
} | } | ||||
void MacDockIconHandler::cleanup() | void MacDockIconHandler::cleanup() { | ||||
{ | |||||
delete s_instance; | delete s_instance; | ||||
} | } | ||||
void MacDockIconHandler::handleDockIconClickEvent() | void MacDockIconHandler::handleDockIconClickEvent() { | ||||
{ | if (this->mainWindow) { | ||||
if (this->mainWindow) | |||||
{ | |||||
this->mainWindow->activateWindow(); | this->mainWindow->activateWindow(); | ||||
this->mainWindow->show(); | this->mainWindow->show(); | ||||
} | } | ||||
Q_EMIT this->dockIconClicked(); | Q_EMIT this->dockIconClicked(); | ||||
} | } |