Browse Source

Merge pull request #4043

d282c1f [Qt] catch Windows shutdown events while client is running (Philip Kaufmann)
try
Wladimir J. van der Laan 11 years ago
parent
commit
c63b2e25a5
No known key found for this signature in database GPG Key ID: 74810B012346C9A6
  1. 6
      src/qt/Makefile.am
  2. 22
      src/qt/bitcoin.cpp
  3. 57
      src/qt/winshutdownmonitor.cpp
  4. 29
      src/qt/winshutdownmonitor.h

6
src/qt/Makefile.am

@ -211,7 +211,8 @@ BITCOIN_QT_H = \
walletframe.h \
walletmodel.h \
walletmodeltransaction.h \
walletview.h
walletview.h \
winshutdownmonitor.h
RES_ICONS = \
res/icons/add.png \
@ -277,7 +278,8 @@ BITCOIN_QT_CPP = \
rpcconsole.cpp \
splashscreen.cpp \
trafficgraphwidget.cpp \
utilitydialog.cpp
utilitydialog.cpp \
winshutdownmonitor.cpp
if ENABLE_WALLET
BITCOIN_QT_CPP += \

22
src/qt/bitcoin.cpp

@ -15,6 +15,7 @@
#include "optionsmodel.h"
#include "splashscreen.h"
#include "utilitydialog.h"
#include "winshutdownmonitor.h"
#ifdef ENABLE_WALLET
#include "paymentserver.h"
#include "walletmodel.h"
@ -189,6 +190,9 @@ public:
/// Get process return value
int getReturnValue() { return returnValue; }
/// Get window identifier of QMainWindow (BitcoinGUI)
WId getMainWinId() const;
public slots:
void initializeResult(int retval);
void shutdownResult(int retval);
@ -444,6 +448,14 @@ void BitcoinApplication::handleRunawayException(const QString &message)
::exit(1);
}
WId BitcoinApplication::getMainWinId() const
{
if (!window)
return 0;
return window->winId();
}
#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
@ -558,10 +570,15 @@ int main(int argc, char *argv[])
/// 9. Main GUI initialization
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
// Install qDebug() message handler to route to debug.log
#if QT_VERSION < 0x050000
// Install qDebug() message handler to route to debug.log
qInstallMsgHandler(DebugMessageHandler);
#else
#if defined(Q_OS_WIN)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp->installNativeEventFilter(new WinShutdownMonitor());
#endif
// Install qDebug() message handler to route to debug.log
qInstallMessageHandler(DebugMessageHandler);
#endif
// Load GUI settings from QSettings
@ -577,6 +594,9 @@ int main(int argc, char *argv[])
{
app.createWindow(isaTestNet);
app.requestInitialize();
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Bitcoin Core did't yet exit safely..."), (HWND)app.getMainWinId());
#endif
app.exec();
app.requestShutdown();
app.exec();

57
src/qt/winshutdownmonitor.cpp

@ -0,0 +1,57 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "winshutdownmonitor.h"
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
#include "init.h"
#include <windows.h>
#include <QDebug>
// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
Q_UNUSED(eventType);
MSG *pMsg = static_cast<MSG *>(pMessage);
switch(pMsg->message)
{
case WM_QUERYENDSESSION:
{
// Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
// Windows session end until we have finished client shutdown.
StartShutdown();
*pnResult = FALSE;
return true;
}
case WM_ENDSESSION:
{
*pnResult = FALSE;
return true;
}
}
return false;
}
void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
if (shutdownBRCreate == NULL) {
qDebug() << "registerShutdownBlockReason : GetProcAddress for ShutdownBlockReasonCreate failed";
return;
}
if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
qDebug() << "registerShutdownBlockReason : Successfully registered: " + strReason;
else
qDebug() << "registerShutdownBlockReason : Failed to register: " + strReason;
}
#endif

29
src/qt/winshutdownmonitor.h

@ -0,0 +1,29 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef WINSHUTDOWNMONITOR_H
#define WINSHUTDOWNMONITOR_H
#ifdef WIN32
#include <QByteArray>
#include <QString>
#if QT_VERSION >= 0x050000
#include <windef.h> // for HWND
#include <QAbstractNativeEventFilter>
class WinShutdownMonitor : public QAbstractNativeEventFilter
{
public:
/** Implements QAbstractNativeEventFilter interface for processing Windows messages */
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult);
/** Register the reason for blocking shutdown on Windows to allow clean client exit */
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);
};
#endif
#endif
#endif // WINSHUTDOWNMONITOR_H
Loading…
Cancel
Save