From d57cbc615ba07fe57653d89b003e4128a909a792 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 15 Jul 2019 14:38:55 +0300 Subject: [PATCH] Backport #12783: macOS: disable AppNap during sync (and mixing) (#3024) * Merge #12783: macOS: disable AppNap during sync 1e0f3c44992fb82e6bf36c2ef9277b0759c17c4c macOS: disable AppNap during sync (Alexey Ivanov) Pull request description: Code based on pull/5804. Tested only on macOS 10.13.3 and should support 10.9+. What macOS versions bitcoin core currently supports? Tree-SHA512: 85809b8d8d8a05169437b4268988da0b7372c29c6da3223ebdc106dc16dcb6d3caa5c52ace3591467005b50a63fd8b2ab1cb071cb4f450032932df25d5063315 * Refactor * Drop `#include ` from `src/qt/bitcoingui.h` Was included by mistake. --- share/qt/Info.plist.in | 3 -- src/Makefile.qt.include | 4 ++- src/qt/bitcoingui.cpp | 19 +++++++++++ src/qt/bitcoingui.h | 8 +++++ src/qt/macos_appnap.h | 24 ++++++++++++++ src/qt/macos_appnap.mm | 71 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/qt/macos_appnap.h create mode 100644 src/qt/macos_appnap.mm diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 41f37eb43cb9b..ff1f26cdd959d 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -97,9 +97,6 @@ NSHighResolutionCapable True - LSAppNapIsDisabled - True - NSRequiresAquaSystemAppearance True diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 56a6dca1895ff..26eb4dfc8544a 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -103,7 +103,8 @@ QT_MOC_CPP = \ BITCOIN_MM = \ qt/macdockiconhandler.mm \ - qt/macnotificationhandler.mm + qt/macnotificationhandler.mm \ + qt/macos_appnap.mm QT_MOC = \ qt/dash.moc \ @@ -142,6 +143,7 @@ BITCOIN_QT_H = \ qt/intro.h \ qt/macdockiconhandler.h \ qt/macnotificationhandler.h \ + qt/macos_appnap.h \ qt/modaloverlay.h \ qt/masternodelist.h \ qt/networkstyle.h \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index cc90e89d64151..b6c4ca816a07f 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -24,6 +24,7 @@ #include "utilitydialog.h" #ifdef ENABLE_WALLET +#include "privatesend/privatesend-client.h" #include "walletframe.h" #include "walletmodel.h" #endif // ENABLE_WALLET @@ -266,6 +267,10 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle * connect(progressBar, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay())); } #endif + +#ifdef Q_OS_MAC + m_app_nap_inhibitor = new CAppNapInhibitor; +#endif } BitcoinGUI::~BitcoinGUI() @@ -277,6 +282,7 @@ BitcoinGUI::~BitcoinGUI() if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) trayIcon->hide(); #ifdef Q_OS_MAC + delete m_app_nap_inhibitor; delete appMenuBar; MacDockIconHandler::cleanup(); #endif @@ -950,6 +956,19 @@ void BitcoinGUI::updateHeadersSyncProgressLabel() void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header) { +#ifdef Q_OS_MAC + // Disabling macOS App Nap on initial sync, disk, reindex operations and mixing. + bool disableAppNap = !masternodeSync.IsSynced(); +#ifdef ENABLE_WALLET + disableAppNap |= privateSendClient.fPrivateSendRunning; +#endif // ENABLE_WALLET + if (disableAppNap) { + m_app_nap_inhibitor->disableAppNap(); + } else { + m_app_nap_inhibitor->enableAppNap(); + } +#endif // Q_OS_MAC + if (modalOverlay) { if (header) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index df1fd19933ea1..ef08389982f15 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -19,6 +19,10 @@ #include #include +#ifdef Q_OS_MAC +#include +#endif + class ClientModel; class NetworkStyle; class Notificator; @@ -131,6 +135,10 @@ class BitcoinGUI : public QMainWindow HelpMessageDialog *helpMessageDialog; ModalOverlay *modalOverlay; +#ifdef Q_OS_MAC + CAppNapInhibitor* m_app_nap_inhibitor = nullptr; +#endif + /** Keep track of previous number of blocks, to detect progress */ int prevBlocks; int spinnerFrame; diff --git a/src/qt/macos_appnap.h b/src/qt/macos_appnap.h new file mode 100644 index 0000000000000..8c2cd840b01c8 --- /dev/null +++ b/src/qt/macos_appnap.h @@ -0,0 +1,24 @@ +// 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_MACOS_APPNAP_H +#define BITCOIN_QT_MACOS_APPNAP_H + +#include + +class CAppNapInhibitor final +{ +public: + explicit CAppNapInhibitor(); + ~CAppNapInhibitor(); + + void disableAppNap(); + void enableAppNap(); + +private: + class CAppNapImpl; + std::unique_ptr impl; +}; + +#endif // BITCOIN_QT_MACOS_APPNAP_H diff --git a/src/qt/macos_appnap.mm b/src/qt/macos_appnap.mm new file mode 100644 index 0000000000000..363c60091fb63 --- /dev/null +++ b/src/qt/macos_appnap.mm @@ -0,0 +1,71 @@ +// 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 "macos_appnap.h" + +#include +#include +#include + +class CAppNapInhibitor::CAppNapImpl +{ +public: + ~CAppNapImpl() + { + if(activityId) + enableAppNap(); + } + + void disableAppNap() + { + if (!activityId) + { + @autoreleasepool { + const NSActivityOptions activityOptions = + NSActivityUserInitiatedAllowingIdleSystemSleep & + ~(NSActivitySuddenTerminationDisabled | + NSActivityAutomaticTerminationDisabled); + + id processInfo = [NSProcessInfo processInfo]; + if ([processInfo respondsToSelector:@selector(beginActivityWithOptions:reason:)]) + { + activityId = [processInfo beginActivityWithOptions: activityOptions reason:@"Temporarily disable App Nap for dash-qt."]; + [activityId retain]; + } + } + } + } + + void enableAppNap() + { + if(activityId) + { + @autoreleasepool { + id processInfo = [NSProcessInfo processInfo]; + if ([processInfo respondsToSelector:@selector(endActivity:)]) + [processInfo endActivity:activityId]; + + [activityId release]; + activityId = nil; + } + } + } + +private: + NSObject* activityId; +}; + +CAppNapInhibitor::CAppNapInhibitor() : impl(new CAppNapImpl()) {} + +CAppNapInhibitor::~CAppNapInhibitor() = default; + +void CAppNapInhibitor::disableAppNap() +{ + impl->disableAppNap(); +} + +void CAppNapInhibitor::enableAppNap() +{ + impl->enableAppNap(); +}