From 4436094508e7d9c4be81d055eb09a323beca41a8 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 14 Dec 2020 20:37:00 +0000 Subject: [PATCH] GUI: Initialise DBus notifications in another thread QDBusInterface's constructor can hang if org.freedesktop.Notifications is missing, so avoid delaying startup waiting for a timeout --- src/qt/notificator.cpp | 25 +++++++++++++++++-------- src/qt/notificator.h | 26 +++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 88bc33098a..6577a7fe92 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -26,6 +26,18 @@ #ifdef USE_DBUS // https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128 const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; + +void DBusInitThread::run() { + auto interface = new QDBusInterface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications"); + if (!interface->isValid()) { + delete interface; + return; + } + interface->moveToThread(m_notificator.thread()); + m_notificator.interface = interface; + m_notificator.mode = Notificator::Freedesktop; +} + #endif Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon, QWidget *_parent) : @@ -39,12 +51,8 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon mode = QSystemTray; } #ifdef USE_DBUS - interface = new QDBusInterface("org.freedesktop.Notifications", - "/org/freedesktop/Notifications", "org.freedesktop.Notifications"); - if(interface->isValid()) - { - mode = Freedesktop; - } + m_dbus_init_thread = new DBusInitThread(*this); + m_dbus_init_thread->start(); #endif #ifdef Q_OS_MACOS // check if users OS has support for NSUserNotification @@ -57,6 +65,8 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon Notificator::~Notificator() { #ifdef USE_DBUS + m_dbus_init_thread->wait(); + delete m_dbus_init_thread; delete interface; #endif } @@ -216,8 +226,7 @@ void Notificator::notifyMacUserNotificationCenter(const QString &title, const QS void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) { - switch(mode) - { + switch (Mode(mode)) { #ifdef USE_DBUS case Freedesktop: notifyDBus(cls, title, text, icon, millisTimeout); diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 1fd8181a22..4231df11f0 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -11,6 +11,9 @@ #include #include +#include + +#include QT_BEGIN_NAMESPACE class QSystemTrayIcon; @@ -20,6 +23,23 @@ class QDBusInterface; #endif QT_END_NAMESPACE +class Notificator; + +#ifdef USE_DBUS +class DBusInitThread : public QThread +{ + Q_OBJECT + + Notificator& m_notificator; + +public: + DBusInitThread(Notificator& notificator) : m_notificator(notificator) {}; + +protected: + void run() override; +}; +#endif + /** Cross-platform desktop notification client. */ class Notificator: public QObject { @@ -61,11 +81,15 @@ private: UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */ }; QString programName; - Mode mode{None}; + std::atomic mode{None}; QSystemTrayIcon *trayIcon; #ifdef USE_DBUS + QThread *m_dbus_init_thread{nullptr}; +protected: QDBusInterface* interface{nullptr}; + friend class DBusInitThread; +private: void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); #endif void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout);