[System Tray] SNI fallback to context menu on failing Activate

This patch primarily is aimed at applications using libappindicator.
For example:
* Steam
* Discord
* Deluge
libappindicator doesn't provide functionality for raising an application,
but only a context menu. Since it also doesn't even provide the corresponding
DBus method, we use the resulting error to try to display the context menu
instead, which matches the behaviour on Unity and Gnome.

BUG: 375351

Reviewers: #plasma, davidedmundson

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D4301
wilder-5.14
Roman Gilg 9 years ago
parent 749216bdcd
commit 5d5518455d
  1. 9
      applets/systemtray/package/contents/ui/items/StatusNotifierItem.qml
  2. 9
      dataengines/statusnotifieritem/statusnotifieritemjob.cpp
  3. 1
      dataengines/statusnotifieritem/statusnotifieritemjob.h
  4. 15
      dataengines/statusnotifieritem/statusnotifieritemsource.cpp
  5. 2
      dataengines/statusnotifieritem/statusnotifieritemsource.h

@ -68,7 +68,14 @@ AbstractItem {
var operation = service.operationDescription("Activate"); var operation = service.operationDescription("Activate");
operation.x = pos.x; operation.x = pos.x;
operation.y = pos.y; operation.y = pos.y;
service.startOperationCall(operation); var job = service.startOperationCall(operation);
job.finished.connect(function () {
if (!job.result) {
// On error try to invoke the context menu.
// Workaround primarily for apps using libappindicator.
contextMenu(mouse);
}
});
break; break;
} }
case Qt.MiddleButton: case Qt.MiddleButton:

@ -25,6 +25,7 @@ StatusNotifierItemJob::StatusNotifierItemJob(StatusNotifierItemSource *source, c
m_source(source) m_source(source)
{ {
connect(source, SIGNAL(contextMenuReady(QMenu*)), this, SLOT(contextMenuReady(QMenu*))); connect(source, SIGNAL(contextMenuReady(QMenu*)), this, SLOT(contextMenuReady(QMenu*)));
connect(source, SIGNAL(activateResult(bool)), this, SLOT(activateCallback(bool)));
} }
StatusNotifierItemJob::~StatusNotifierItemJob() StatusNotifierItemJob::~StatusNotifierItemJob()
@ -35,7 +36,6 @@ void StatusNotifierItemJob::start()
{ {
if (operationName() == QString::fromLatin1("Activate")) { if (operationName() == QString::fromLatin1("Activate")) {
m_source->activate(parameters()[QStringLiteral("x")].toInt(), parameters()[QStringLiteral("y")].toInt()); m_source->activate(parameters()[QStringLiteral("x")].toInt(), parameters()[QStringLiteral("y")].toInt());
setResult(0);
} else if (operationName() == QString::fromLatin1("SecondaryActivate")) { } else if (operationName() == QString::fromLatin1("SecondaryActivate")) {
m_source->secondaryActivate(parameters()[QStringLiteral("x")].toInt(), parameters()[QStringLiteral("y")].toInt()); m_source->secondaryActivate(parameters()[QStringLiteral("x")].toInt(), parameters()[QStringLiteral("y")].toInt());
setResult(0); setResult(0);
@ -47,6 +47,13 @@ void StatusNotifierItemJob::start()
} }
} }
void StatusNotifierItemJob::activateCallback(bool success)
{
if (operationName() == QString::fromLatin1("Activate")) {
setResult(QVariant(success));
}
}
void StatusNotifierItemJob::contextMenuReady(QMenu *menu) void StatusNotifierItemJob::contextMenuReady(QMenu *menu)
{ {
if (operationName() == QString::fromLatin1("ContextMenu")) { if (operationName() == QString::fromLatin1("ContextMenu")) {

@ -44,6 +44,7 @@ protected:
void start() override; void start() override;
private Q_SLOTS: private Q_SLOTS:
void activateCallback(bool success);
void contextMenuReady(QMenu *menu); void contextMenuReady(QMenu *menu);
private: private:

@ -469,10 +469,23 @@ void StatusNotifierItemSource::overlayIcon(QIcon *icon, QIcon *overlay)
void StatusNotifierItemSource::activate(int x, int y) void StatusNotifierItemSource::activate(int x, int y)
{ {
if (m_statusNotifierItemInterface && m_statusNotifierItemInterface->isValid()) { if (m_statusNotifierItemInterface && m_statusNotifierItemInterface->isValid()) {
m_statusNotifierItemInterface->call(QDBus::NoBlock, QStringLiteral("Activate"), x, y); QDBusMessage message = QDBusMessage::createMethodCall(m_statusNotifierItemInterface->service(),
m_statusNotifierItemInterface->path(), m_statusNotifierItemInterface->interface(), QStringLiteral("Activate"));
message << x << y;
QDBusPendingCall call = m_statusNotifierItemInterface->connection().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, &StatusNotifierItemSource::activateCallback);
} }
} }
void StatusNotifierItemSource::activateCallback(QDBusPendingCallWatcher *call)
{
QDBusPendingReply<void> reply = *call;
emit activateResult(!reply.isError());
call->deleteLater();
}
void StatusNotifierItemSource::secondaryActivate(int x, int y) void StatusNotifierItemSource::secondaryActivate(int x, int y)
{ {
if (m_statusNotifierItemInterface && m_statusNotifierItemInterface->isValid()) { if (m_statusNotifierItemInterface && m_statusNotifierItemInterface->isValid()) {

@ -50,6 +50,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void contextMenuReady(QMenu *menu); void contextMenuReady(QMenu *menu);
void activateResult(bool success);
private Q_SLOTS: private Q_SLOTS:
void contextMenuReady(); void contextMenuReady();
@ -60,6 +61,7 @@ private Q_SLOTS:
void performRefresh(); void performRefresh();
void syncStatus(QString); void syncStatus(QString);
void refreshCallback(QDBusPendingCallWatcher *); void refreshCallback(QDBusPendingCallWatcher *);
void activateCallback(QDBusPendingCallWatcher *);
private: private:

Loading…
Cancel
Save