Do gnome global shortcut registration in a background thread

This commit is contained in:
David Sansome 2011-01-09 23:11:51 +00:00
parent 2d53db13c3
commit 380fa71e86
7 changed files with 91 additions and 20 deletions

View File

@ -247,6 +247,7 @@ set(HEADERS
core/database.h core/database.h
core/deletefiles.h core/deletefiles.h
core/globalshortcuts.h core/globalshortcuts.h
core/globalshortcutbackend.h
core/gnomeglobalshortcutbackend.h core/gnomeglobalshortcutbackend.h
core/kittenloader.h core/kittenloader.h
core/mergedproxymodel.h core/mergedproxymodel.h

View File

@ -18,26 +18,63 @@
#include "globalshortcutbackend.h" #include "globalshortcutbackend.h"
#include "globalshortcuts.h" #include "globalshortcuts.h"
#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrentRun>
GlobalShortcutBackend::GlobalShortcutBackend(GlobalShortcuts *parent) GlobalShortcutBackend::GlobalShortcutBackend(GlobalShortcuts *parent)
: QObject(parent), : QObject(parent),
manager_(parent), manager_(parent),
active_(false) active_(false),
register_in_progress_(false),
should_unregister_(false)
{ {
} }
bool GlobalShortcutBackend::Register() { void GlobalShortcutBackend::Register() {
bool ret = DoRegister(); if (register_in_progress_) {
if (ret) should_unregister_ = false;
active_ = true; return;
return ret; }
if (RegisterInNewThread()) {
register_in_progress_ = true;
QFuture<bool> future = QtConcurrent::run(this, &GlobalShortcutBackend::DoRegister);
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>(this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(RegisterFinishedSlot()));
} else {
bool ret = DoRegister();
if (ret)
active_ = true;
emit RegisterFinished(ret);
}
} }
void GlobalShortcutBackend::Unregister() { void GlobalShortcutBackend::Unregister() {
if (register_in_progress_) {
should_unregister_ = true;
return;
}
DoUnregister(); DoUnregister();
active_ = false; active_ = false;
} }
void GlobalShortcutBackend::Reregister() { void GlobalShortcutBackend::RegisterFinishedSlot() {
Unregister(); QFutureWatcher<bool>* watcher = dynamic_cast<QFutureWatcher<bool>*>(sender());
Register(); 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);
}
} }

View File

@ -23,22 +23,34 @@
class GlobalShortcuts; class GlobalShortcuts;
class GlobalShortcutBackend : public QObject { class GlobalShortcutBackend : public QObject {
Q_OBJECT
public: public:
GlobalShortcutBackend(GlobalShortcuts* parent = 0); GlobalShortcutBackend(GlobalShortcuts* parent = 0);
virtual ~GlobalShortcutBackend() {} virtual ~GlobalShortcutBackend() {}
bool is_active() const { return active_; } bool is_active() const { return active_; }
bool Register(); void Register();
void Unregister(); void Unregister();
void Reregister();
signals:
void RegisterFinished(bool success);
protected: protected:
virtual bool RegisterInNewThread() const { return false; }
virtual bool DoRegister() = 0; virtual bool DoRegister() = 0;
virtual void DoUnregister() = 0; virtual void DoUnregister() = 0;
GlobalShortcuts* manager_; GlobalShortcuts* manager_;
bool active_; bool active_;
private slots:
void RegisterFinishedSlot();
private:
bool register_in_progress_;
bool should_unregister_;
}; };
#endif // GLOBALSHORTCUTBACKEND_H #endif // GLOBALSHORTCUTBACKEND_H

View File

@ -67,8 +67,7 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent)
connect(rating_signals_mapper_, SIGNAL(mapped(int)), SIGNAL(RateCurrentSong(int))); connect(rating_signals_mapper_, SIGNAL(mapped(int)), SIGNAL(RateCurrentSong(int)));
// Create backends - these do the actual shortcut registration // Create backends - these do the actual shortcut registration
if (IsGsdAvailable()) gnome_backend_ = new GnomeGlobalShortcutBackend(this);
gnome_backend_ = new GnomeGlobalShortcutBackend(this);
#ifndef Q_OS_DARWIN #ifndef Q_OS_DARWIN
system_backend_ = new QxtGlobalShortcutBackend(this); system_backend_ = new QxtGlobalShortcutBackend(this);
@ -76,6 +75,9 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent)
system_backend_ = new MacGlobalShortcutBackend(this); system_backend_ = new MacGlobalShortcutBackend(this);
#endif #endif
connect(gnome_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool)));
connect(system_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool)));
ReloadSettings(); ReloadSettings();
} }
@ -127,19 +129,27 @@ void GlobalShortcuts::ReloadSettings() {
} }
void GlobalShortcuts::Unregister() { void GlobalShortcuts::Unregister() {
if (gnome_backend_ && gnome_backend_->is_active()) if (gnome_backend_->is_active())
gnome_backend_->Unregister(); gnome_backend_->Unregister();
if (system_backend_ && system_backend_->is_active()) if (system_backend_->is_active())
system_backend_->Unregister(); system_backend_->Unregister();
} }
void GlobalShortcuts::Register() { void GlobalShortcuts::Register() {
if (gnome_backend_ && use_gnome_) if (use_gnome_)
gnome_backend_->Register(); gnome_backend_->Register();
else if (system_backend_) else
system_backend_->Register(); system_backend_->Register();
} }
void GlobalShortcuts::RegisterFinished(bool success) {
GlobalShortcutBackend* backend = qobject_cast<GlobalShortcutBackend*>(sender());
if (backend == gnome_backend_ && !success) {
system_backend_->Register();
}
}
bool GlobalShortcuts::IsMacAccessibilityEnabled() const { bool GlobalShortcuts::IsMacAccessibilityEnabled() const {
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
return static_cast<MacGlobalShortcutBackend*>(system_backend_)->IsAccessibilityEnabled(); return static_cast<MacGlobalShortcutBackend*>(system_backend_)->IsAccessibilityEnabled();

View File

@ -77,6 +77,9 @@ private:
int rating, const QKeySequence& default_key = QKeySequence(0)); int rating, const QKeySequence& default_key = QKeySequence(0));
Shortcut AddShortcut(const QString& id, const QString& name, const QKeySequence& default_key); Shortcut AddShortcut(const QString& id, const QString& name, const QKeySequence& default_key);
private slots:
void RegisterFinished(bool success);
private: private:
GlobalShortcutBackend* gnome_backend_; GlobalShortcutBackend* gnome_backend_;
GlobalShortcutBackend* system_backend_; GlobalShortcutBackend* system_backend_;

View File

@ -36,22 +36,29 @@ GnomeGlobalShortcutBackend::GnomeGlobalShortcutBackend(GlobalShortcuts* parent)
} }
bool GnomeGlobalShortcutBackend::DoRegister() { bool GnomeGlobalShortcutBackend::DoRegister() {
qDebug() << __PRETTY_FUNCTION__;
#ifdef QT_DBUS_LIB #ifdef QT_DBUS_LIB
qDebug() << __PRETTY_FUNCTION__ << "- starting";
// Check if the GSD service is available // 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; return false;
}
if (!interface_) { if (!interface_) {
interface_ = new QDBusInterface( 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)), connect(interface_, SIGNAL(MediaPlayerKeyPressed(QString,QString)),
this, SLOT(GnomeMediaKeyPressed(QString,QString))); this, SLOT(GnomeMediaKeyPressed(QString,QString)));
qDebug() << __PRETTY_FUNCTION__ << "- complete";
return true; return true;
#else // QT_DBUS_LIB #else // QT_DBUS_LIB
qDebug() << __PRETTY_FUNCTION__ << "- dbus not available";
return false; return false;
#endif #endif
} }

View File

@ -33,6 +33,7 @@ public:
static const char* kGsdInterface; static const char* kGsdInterface;
protected: protected:
bool RegisterInNewThread() const { return true; }
bool DoRegister(); bool DoRegister();
void DoUnregister(); void DoUnregister();