From 380fa71e8665c4d60a4aea096913efb18d3e3eb3 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 9 Jan 2011 23:11:51 +0000 Subject: [PATCH] Do gnome global shortcut registration in a background thread --- src/CMakeLists.txt | 1 + src/core/globalshortcutbackend.cpp | 55 +++++++++++++++++++++---- src/core/globalshortcutbackend.h | 16 ++++++- src/core/globalshortcuts.cpp | 22 +++++++--- src/core/globalshortcuts.h | 3 ++ src/core/gnomeglobalshortcutbackend.cpp | 13 ++++-- src/core/gnomeglobalshortcutbackend.h | 1 + 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be850f396..ac7c1a0fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -247,6 +247,7 @@ set(HEADERS core/database.h core/deletefiles.h core/globalshortcuts.h + core/globalshortcutbackend.h core/gnomeglobalshortcutbackend.h core/kittenloader.h core/mergedproxymodel.h diff --git a/src/core/globalshortcutbackend.cpp b/src/core/globalshortcutbackend.cpp index 178e112ef..bb3770299 100644 --- a/src/core/globalshortcutbackend.cpp +++ b/src/core/globalshortcutbackend.cpp @@ -18,26 +18,63 @@ #include "globalshortcutbackend.h" #include "globalshortcuts.h" +#include +#include +#include + GlobalShortcutBackend::GlobalShortcutBackend(GlobalShortcuts *parent) : QObject(parent), manager_(parent), - active_(false) + active_(false), + register_in_progress_(false), + should_unregister_(false) { } -bool GlobalShortcutBackend::Register() { - bool ret = DoRegister(); - if (ret) - active_ = true; - return ret; +void GlobalShortcutBackend::Register() { + if (register_in_progress_) { + should_unregister_ = false; + return; + } + + if (RegisterInNewThread()) { + register_in_progress_ = true; + QFuture future = QtConcurrent::run(this, &GlobalShortcutBackend::DoRegister); + + QFutureWatcher* watcher = new QFutureWatcher(this); + watcher->setFuture(future); + connect(watcher, SIGNAL(finished()), SLOT(RegisterFinishedSlot())); + } else { + bool ret = DoRegister(); + if (ret) + active_ = true; + emit RegisterFinished(ret); + } } void GlobalShortcutBackend::Unregister() { + if (register_in_progress_) { + should_unregister_ = true; + return; + } + DoUnregister(); active_ = false; } -void GlobalShortcutBackend::Reregister() { - Unregister(); - Register(); +void GlobalShortcutBackend::RegisterFinishedSlot() { + QFutureWatcher* watcher = dynamic_cast*>(sender()); + const bool success = watcher->result(); + watcher->deleteLater(); + + register_in_progress_ = false; + if (success) + active_ = true; + + if (should_unregister_) { + Unregister(); + should_unregister_ = false; + } else { + emit RegisterFinished(success); + } } diff --git a/src/core/globalshortcutbackend.h b/src/core/globalshortcutbackend.h index cad773da8..3dd88dc52 100644 --- a/src/core/globalshortcutbackend.h +++ b/src/core/globalshortcutbackend.h @@ -23,22 +23,34 @@ class GlobalShortcuts; class GlobalShortcutBackend : public QObject { + Q_OBJECT + public: GlobalShortcutBackend(GlobalShortcuts* parent = 0); virtual ~GlobalShortcutBackend() {} bool is_active() const { return active_; } - bool Register(); + void Register(); void Unregister(); - void Reregister(); + +signals: + void RegisterFinished(bool success); protected: + virtual bool RegisterInNewThread() const { return false; } virtual bool DoRegister() = 0; virtual void DoUnregister() = 0; GlobalShortcuts* manager_; bool active_; + +private slots: + void RegisterFinishedSlot(); + +private: + bool register_in_progress_; + bool should_unregister_; }; #endif // GLOBALSHORTCUTBACKEND_H diff --git a/src/core/globalshortcuts.cpp b/src/core/globalshortcuts.cpp index 0857b440a..04ad6a774 100644 --- a/src/core/globalshortcuts.cpp +++ b/src/core/globalshortcuts.cpp @@ -67,8 +67,7 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent) connect(rating_signals_mapper_, SIGNAL(mapped(int)), SIGNAL(RateCurrentSong(int))); // Create backends - these do the actual shortcut registration - if (IsGsdAvailable()) - gnome_backend_ = new GnomeGlobalShortcutBackend(this); + gnome_backend_ = new GnomeGlobalShortcutBackend(this); #ifndef Q_OS_DARWIN system_backend_ = new QxtGlobalShortcutBackend(this); @@ -76,6 +75,9 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent) system_backend_ = new MacGlobalShortcutBackend(this); #endif + connect(gnome_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool))); + connect(system_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool))); + ReloadSettings(); } @@ -127,19 +129,27 @@ void GlobalShortcuts::ReloadSettings() { } void GlobalShortcuts::Unregister() { - if (gnome_backend_ && gnome_backend_->is_active()) + if (gnome_backend_->is_active()) gnome_backend_->Unregister(); - if (system_backend_ && system_backend_->is_active()) + if (system_backend_->is_active()) system_backend_->Unregister(); } void GlobalShortcuts::Register() { - if (gnome_backend_ && use_gnome_) + if (use_gnome_) gnome_backend_->Register(); - else if (system_backend_) + else system_backend_->Register(); } +void GlobalShortcuts::RegisterFinished(bool success) { + GlobalShortcutBackend* backend = qobject_cast(sender()); + + if (backend == gnome_backend_ && !success) { + system_backend_->Register(); + } +} + bool GlobalShortcuts::IsMacAccessibilityEnabled() const { #ifdef Q_OS_MAC return static_cast(system_backend_)->IsAccessibilityEnabled(); diff --git a/src/core/globalshortcuts.h b/src/core/globalshortcuts.h index 41bc0d490..bb53f280d 100644 --- a/src/core/globalshortcuts.h +++ b/src/core/globalshortcuts.h @@ -77,6 +77,9 @@ private: int rating, const QKeySequence& default_key = QKeySequence(0)); Shortcut AddShortcut(const QString& id, const QString& name, const QKeySequence& default_key); +private slots: + void RegisterFinished(bool success); + private: GlobalShortcutBackend* gnome_backend_; GlobalShortcutBackend* system_backend_; diff --git a/src/core/gnomeglobalshortcutbackend.cpp b/src/core/gnomeglobalshortcutbackend.cpp index 2d03e3f88..7496cfc22 100644 --- a/src/core/gnomeglobalshortcutbackend.cpp +++ b/src/core/gnomeglobalshortcutbackend.cpp @@ -36,22 +36,29 @@ GnomeGlobalShortcutBackend::GnomeGlobalShortcutBackend(GlobalShortcuts* parent) } bool GnomeGlobalShortcutBackend::DoRegister() { - qDebug() << __PRETTY_FUNCTION__; #ifdef QT_DBUS_LIB + qDebug() << __PRETTY_FUNCTION__ << "- starting"; // Check if the GSD service is available - if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(kGsdService)) + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(kGsdService)) { + qDebug() << __PRETTY_FUNCTION__ << "- gnome settings daemon not registered"; return false; + } if (!interface_) { interface_ = new QDBusInterface( - kGsdService, kGsdPath, kGsdInterface, QDBusConnection::sessionBus(), this); + kGsdService, kGsdPath, kGsdInterface, QDBusConnection::sessionBus()); + interface_->moveToThread(thread()); + interface_->setParent(this); } connect(interface_, SIGNAL(MediaPlayerKeyPressed(QString,QString)), this, SLOT(GnomeMediaKeyPressed(QString,QString))); + qDebug() << __PRETTY_FUNCTION__ << "- complete"; + return true; #else // QT_DBUS_LIB + qDebug() << __PRETTY_FUNCTION__ << "- dbus not available"; return false; #endif } diff --git a/src/core/gnomeglobalshortcutbackend.h b/src/core/gnomeglobalshortcutbackend.h index 068a53bf9..c9ca93b41 100644 --- a/src/core/gnomeglobalshortcutbackend.h +++ b/src/core/gnomeglobalshortcutbackend.h @@ -33,6 +33,7 @@ public: static const char* kGsdInterface; protected: + bool RegisterInNewThread() const { return true; } bool DoRegister(); void DoUnregister();