aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2018-11-12 14:49:30 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2018-11-12 14:52:35 +0100
commit48223256cf6cb7c4bbfb78bebab08640eeccff2c (patch)
tree4b7a34ad12390ef80025cd23fec2be4b48c4475d
parentae32806ea20235c4542b1a5d4011df5ae267b58a (diff)
parent0a656f85a9c694f25b06c6464d6e986816eecd58 (diff)
Merge #14123: gui: Add GUIUtil::bringToFront
0a656f85a9c694f25b06c6464d6e986816eecd58 qt: All tray menu actions call showNormalIfMinimized (João Barbosa) 6fc21aca6d5e16c3ece104fec8e5b3df116893b4 qt: Use GUIUtil::bringToFront where possible (João Barbosa) 5796671e1dd8a2d0b1e750c2dce19a10af624095 qt: Add GUIUtil::bringToFront (João Barbosa) 6b1d2972bf9a40f97ba3a5c95831fd179b1054cf Remove obj_c for macOS Dock icon menu (Hennadii Stepanov) 2464925e7be832d4926b6204169bbbc1646c6368 Use Qt signal for macOS Dock icon click event (Hennadii Stepanov) 53bb6be3f8a50ee9e5c4d7e9155236152e7c4b7c Remove obj_c for macOS Dock icon setting (Hennadii Stepanov) Pull request description: The sequence `show -> raise -> activateWindow` is factored out to the new function `GUIUtil::bringToFront` where a macOS fix is added in order to fix #13829. Also included: - simplification of `BitcoinGUI::showNormalIfMinimized` - simplified some connections to `BitcoinGUI::showNormalIfMinimized` - added missing connections to `BitcoinGUI::showNormalIfMinimized`. Tree-SHA512: a8e301aebc359aa353821e2af352ae356f44555724921b01da907e128653ef9dc55d8764a1bff72a579e5ff96df8a681f6804bfe83acba441da92fedff974a55
-rw-r--r--src/qt/bitcoingui.cpp66
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/guiutil.cpp34
-rw-r--r--src/qt/guiutil.h3
-rw-r--r--src/qt/macdockiconhandler.h21
-rw-r--r--src/qt/macdockiconhandler.mm100
-rw-r--r--src/qt/walletview.cpp8
7 files changed, 76 insertions, 159 deletions
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 89b80bd5c9..8c4a37fee5 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -92,12 +92,8 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
windowTitle += tr("Node");
}
windowTitle += " " + networkStyle->getTitleAddText();
-#ifndef Q_OS_MAC
QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
setWindowIcon(networkStyle->getTrayAndWindowIcon());
-#else
- MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
-#endif
setWindowTitle(windowTitle);
rpcConsole = new RPCConsole(node, _platformStyle, 0);
@@ -278,17 +274,17 @@ void BitcoinGUI::createActions()
#ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful.
- connect(overviewAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(overviewAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
- connect(sendCoinsAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
- connect(sendCoinsMenuAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
- connect(receiveCoinsAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
- connect(receiveCoinsMenuAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
- connect(historyAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
+ connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
#endif // ENABLE_WALLET
@@ -355,7 +351,9 @@ void BitcoinGUI::createActions()
connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
+ connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
+ connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
@@ -604,7 +602,7 @@ void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
void BitcoinGUI::createTrayIconMenu()
{
#ifndef Q_OS_MAC
- // return if trayIcon is unset (only on non-Mac OSes)
+ // return if trayIcon is unset (only on non-macOSes)
if (!trayIcon)
return;
@@ -613,15 +611,17 @@ void BitcoinGUI::createTrayIconMenu()
connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
#else
- // Note: On Mac, the dock icon is used to provide the tray's functionality.
+ // Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- dockIconHandler->setMainWindow(static_cast<QMainWindow*>(this));
- trayIconMenu = dockIconHandler->dockMenu();
+ connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
+
+ trayIconMenu = new QMenu(this);
+ trayIconMenu->setAsDockMenu();
#endif
- // Configuration of the tray icon (or dock icon) icon menu
+ // Configuration of the tray icon (or Dock icon) menu
#ifndef Q_OS_MAC
- // Note: On Mac, the dock icon's menu already has show / hide action.
+ // Note: On macOS, the Dock icon's menu already has Show / Hide action.
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
#endif
@@ -635,7 +635,7 @@ void BitcoinGUI::createTrayIconMenu()
trayIconMenu->addAction(openRPCConsoleAction);
}
trayIconMenu->addAction(optionsAction);
-#ifndef Q_OS_MAC // This is built-in on Mac
+#ifndef Q_OS_MAC // This is built-in on macOS
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
#endif
@@ -650,6 +650,12 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
toggleHidden();
}
}
+#else
+void BitcoinGUI::macosDockIconActivated()
+{
+ show();
+ activateWindow();
+}
#endif
void BitcoinGUI::optionsClicked()
@@ -668,10 +674,7 @@ void BitcoinGUI::aboutClicked()
void BitcoinGUI::showDebugWindow()
{
- rpcConsole->showNormal();
- rpcConsole->show();
- rpcConsole->raise();
- rpcConsole->activateWindow();
+ GUIUtil::bringToFront(rpcConsole);
}
void BitcoinGUI::showDebugWindowActivateConsole()
@@ -1158,24 +1161,11 @@ void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
if(!clientModel)
return;
- // activateWindow() (sometimes) helps with keyboard focus on Windows
- if (isHidden())
- {
- show();
- activateWindow();
- }
- else if (isMinimized())
- {
- showNormal();
- activateWindow();
- }
- else if (GUIUtil::isObscured(this))
- {
- raise();
- activateWindow();
- }
- else if(fToggleHidden)
+ if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
hide();
+ } else {
+ GUIUtil::bringToFront(this);
+ }
}
void BitcoinGUI::toggleHidden()
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 57b70803ae..e8b857c17c 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -268,6 +268,9 @@ public Q_SLOTS:
#ifndef Q_OS_MAC
/** Handle tray icon clicked */
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
+#else
+ /** Handle macOS Dock icon clicked */
+ void macosDockIconActivated();
#endif
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index a68140ccf9..b1cd2f77d0 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -60,6 +60,14 @@
#include <QFontDatabase>
#endif
+#if defined(Q_OS_MAC)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#include <objc/objc-runtime.h>
+#include <CoreServices/CoreServices.h>
+#endif
+
namespace GUIUtil {
QString dateTimeStr(const QDateTime &date)
@@ -353,6 +361,27 @@ bool isObscured(QWidget *w)
&& checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
}
+void bringToFront(QWidget* w)
+{
+#ifdef Q_OS_MAC
+ // Force application activation on macOS. With Qt 5.4 this is required when
+ // an action in the dock menu is triggered.
+ id app = objc_msgSend((id) objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+ objc_msgSend(app, sel_registerName("activateIgnoringOtherApps:"), YES);
+#endif
+
+ if (w) {
+ // activateWindow() (sometimes) helps with keyboard focus on Windows
+ if (w->isMinimized()) {
+ w->showNormal();
+ } else {
+ w->show();
+ }
+ w->activateWindow();
+ w->raise();
+ }
+}
+
void openDebugLogfile()
{
fs::path pathDebug = GetDataDir() / "debug.log";
@@ -663,13 +692,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
#elif defined(Q_OS_MAC)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
// based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreServices/CoreServices.h>
-
LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
{
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 011827e134..f1d0aa48ef 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -115,6 +115,9 @@ namespace GUIUtil
// Determine whether a widget is hidden behind other windows
bool isObscured(QWidget *w);
+ // Activate, show and raise the widget
+ void bringToFront(QWidget* w);
+
// Open debug.log
void openDebugLogfile();
diff --git a/src/qt/macdockiconhandler.h b/src/qt/macdockiconhandler.h
index 1c28593d4a..ff867e21a7 100644
--- a/src/qt/macdockiconhandler.h
+++ b/src/qt/macdockiconhandler.h
@@ -1,44 +1,27 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_QT_MACDOCKICONHANDLER_H
#define BITCOIN_QT_MACDOCKICONHANDLER_H
-#include <QMainWindow>
#include <QObject>
-QT_BEGIN_NAMESPACE
-class QIcon;
-class QMenu;
-class QWidget;
-QT_END_NAMESPACE
-
-/** Macintosh-specific dock icon handler.
+/** macOS-specific Dock icon handler.
*/
class MacDockIconHandler : public QObject
{
Q_OBJECT
public:
- ~MacDockIconHandler();
-
- QMenu *dockMenu();
- void setIcon(const QIcon &icon);
- void setMainWindow(QMainWindow *window);
static MacDockIconHandler *instance();
static void cleanup();
- void handleDockIconClickEvent();
Q_SIGNALS:
void dockIconClicked();
private:
MacDockIconHandler();
-
- QWidget *m_dummyWidget;
- QMenu *m_dockMenu;
- QMainWindow *mainWindow;
};
#endif // BITCOIN_QT_MACDOCKICONHANDLER_H
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index b9ad191da7..102adce6c5 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -1,107 +1,36 @@
-// Copyright (c) 2011-2013 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "macdockiconhandler.h"
-#include <QImageWriter>
-#include <QMenu>
-#include <QBuffer>
-#include <QWidget>
-
#undef slots
-#include <Cocoa/Cocoa.h>
#include <objc/objc.h>
#include <objc/message.h>
static MacDockIconHandler *s_instance = nullptr;
-bool dockClickHandler(id self,SEL _cmd,...) {
+bool dockClickHandler(id self, SEL _cmd, ...) {
Q_UNUSED(self)
Q_UNUSED(_cmd)
- s_instance->handleDockIconClickEvent();
+ Q_EMIT s_instance->dockIconClicked();
- // Return NO (false) to suppress the default OS X actions
+ // Return NO (false) to suppress the default macOS actions
return false;
}
void setupDockClickHandler() {
- Class cls = objc_getClass("NSApplication");
- id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication"));
-
- if (appInst != nullptr) {
- id delegate = objc_msgSend(appInst, sel_registerName("delegate"));
- Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
- SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
- if (class_getInstanceMethod(delClass, shouldHandle))
- class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
- else
- class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:");
- }
+ id app = objc_msgSend((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+ id delegate = objc_msgSend(app, sel_registerName("delegate"));
+ Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
+ SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
+ class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
}
-
MacDockIconHandler::MacDockIconHandler() : QObject()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
setupDockClickHandler();
- this->m_dummyWidget = new QWidget();
- this->m_dockMenu = new QMenu(this->m_dummyWidget);
- this->setMainWindow(nullptr);
-#if QT_VERSION >= 0x050200
- this->m_dockMenu->setAsDockMenu();
-#endif
- [pool release];
-}
-
-void MacDockIconHandler::setMainWindow(QMainWindow *window) {
- this->mainWindow = window;
-}
-
-MacDockIconHandler::~MacDockIconHandler()
-{
- delete this->m_dummyWidget;
- this->setMainWindow(nullptr);
-}
-
-QMenu *MacDockIconHandler::dockMenu()
-{
- return this->m_dockMenu;
-}
-
-void MacDockIconHandler::setIcon(const QIcon &icon)
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSImage *image = nil;
- if (icon.isNull())
- image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
- else {
- // generate NSImage from QIcon and use this as dock icon.
- QSize size = icon.actualSize(QSize(128, 128));
- QPixmap pixmap = icon.pixmap(size);
-
- // Write image into a R/W buffer from raw pixmap, then save the image.
- QBuffer notificationBuffer;
- if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) {
- QImageWriter writer(&notificationBuffer, "PNG");
- if (writer.write(pixmap.toImage())) {
- NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data()
- length:notificationBuffer.buffer().size()];
- image = [[NSImage alloc] initWithData:macImgData];
- }
- }
-
- if(!image) {
- // if testnet image could not be created, load std. app icon
- image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
- }
- }
-
- [NSApp setApplicationIconImage:image];
- [image release];
- [pool release];
}
MacDockIconHandler *MacDockIconHandler::instance()
@@ -115,14 +44,3 @@ void MacDockIconHandler::cleanup()
{
delete s_instance;
}
-
-void MacDockIconHandler::handleDockIconClickEvent()
-{
- if (this->mainWindow)
- {
- this->mainWindow->activateWindow();
- this->mainWindow->show();
- }
-
- Q_EMIT this->dockIconClicked();
-}
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 053e951921..a619992344 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -292,9 +292,7 @@ void WalletView::usedSendingAddresses()
if(!walletModel)
return;
- usedSendingAddressesPage->show();
- usedSendingAddressesPage->raise();
- usedSendingAddressesPage->activateWindow();
+ GUIUtil::bringToFront(usedSendingAddressesPage);
}
void WalletView::usedReceivingAddresses()
@@ -302,9 +300,7 @@ void WalletView::usedReceivingAddresses()
if(!walletModel)
return;
- usedReceivingAddressesPage->show();
- usedReceivingAddressesPage->raise();
- usedReceivingAddressesPage->activateWindow();
+ GUIUtil::bringToFront(usedReceivingAddressesPage);
}
void WalletView::showProgress(const QString &title, int nProgress)