You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

macdockiconhandler.mm 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright (c) 2011-2013 The Starwels developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "macdockiconhandler.h"
  5. #include <QImageWriter>
  6. #include <QMenu>
  7. #include <QBuffer>
  8. #include <QWidget>
  9. #undef slots
  10. #include <Cocoa/Cocoa.h>
  11. #include <objc/objc.h>
  12. #include <objc/message.h>
  13. #if QT_VERSION < 0x050000
  14. extern void qt_mac_set_dock_menu(QMenu *);
  15. #endif
  16. static MacDockIconHandler *s_instance = NULL;
  17. bool dockClickHandler(id self,SEL _cmd,...) {
  18. Q_UNUSED(self)
  19. Q_UNUSED(_cmd)
  20. s_instance->handleDockIconClickEvent();
  21. // Return NO (false) to suppress the default OS X actions
  22. return false;
  23. }
  24. void setupDockClickHandler() {
  25. Class cls = objc_getClass("NSApplication");
  26. id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication"));
  27. if (appInst != NULL) {
  28. id delegate = objc_msgSend(appInst, sel_registerName("delegate"));
  29. Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
  30. SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
  31. if (class_getInstanceMethod(delClass, shouldHandle))
  32. class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
  33. else
  34. class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:");
  35. }
  36. }
  37. MacDockIconHandler::MacDockIconHandler() : QObject()
  38. {
  39. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  40. setupDockClickHandler();
  41. this->m_dummyWidget = new QWidget();
  42. this->m_dockMenu = new QMenu(this->m_dummyWidget);
  43. this->setMainWindow(NULL);
  44. #if QT_VERSION < 0x050000
  45. qt_mac_set_dock_menu(this->m_dockMenu);
  46. #elif QT_VERSION >= 0x050200
  47. this->m_dockMenu->setAsDockMenu();
  48. #endif
  49. [pool release];
  50. }
  51. void MacDockIconHandler::setMainWindow(QMainWindow *window) {
  52. this->mainWindow = window;
  53. }
  54. MacDockIconHandler::~MacDockIconHandler()
  55. {
  56. delete this->m_dummyWidget;
  57. this->setMainWindow(NULL);
  58. }
  59. QMenu *MacDockIconHandler::dockMenu()
  60. {
  61. return this->m_dockMenu;
  62. }
  63. void MacDockIconHandler::setIcon(const QIcon &icon)
  64. {
  65. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  66. NSImage *image = nil;
  67. if (icon.isNull())
  68. image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
  69. else {
  70. // generate NSImage from QIcon and use this as dock icon.
  71. QSize size = icon.actualSize(QSize(128, 128));
  72. QPixmap pixmap = icon.pixmap(size);
  73. // Write image into a R/W buffer from raw pixmap, then save the image.
  74. QBuffer notificationBuffer;
  75. if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) {
  76. QImageWriter writer(&notificationBuffer, "PNG");
  77. if (writer.write(pixmap.toImage())) {
  78. NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data()
  79. length:notificationBuffer.buffer().size()];
  80. image = [[NSImage alloc] initWithData:macImgData];
  81. }
  82. }
  83. if(!image) {
  84. // if ai image could not be created, load std. app icon
  85. image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
  86. }
  87. }
  88. [NSApp setApplicationIconImage:image];
  89. [image release];
  90. [pool release];
  91. }
  92. MacDockIconHandler *MacDockIconHandler::instance()
  93. {
  94. if (!s_instance)
  95. s_instance = new MacDockIconHandler();
  96. return s_instance;
  97. }
  98. void MacDockIconHandler::cleanup()
  99. {
  100. delete s_instance;
  101. }
  102. void MacDockIconHandler::handleDockIconClickEvent()
  103. {
  104. if (this->mainWindow)
  105. {
  106. this->mainWindow->activateWindow();
  107. this->mainWindow->show();
  108. }
  109. Q_EMIT this->dockIconClicked();
  110. }