fix: 修复部分托盘服务对应进程状态异常时导致任务栏卡死问题

fcitx进程异常时,其statusnotifieritem服务被任务栏调用会导致任务栏卡死

Log: 解决部分情况下任务栏卡死问题
Influence: 托盘服务
Bug: https://pms.uniontech.com/bug-view-126671.html
Change-Id: Icdf906577623a100ddc473690bbbc82277a1797c
This commit is contained in:
Your Name 2022-04-26 14:45:47 +08:00
parent 810ed44f31
commit 576807f431
2 changed files with 26 additions and 27 deletions

View File

@ -30,6 +30,8 @@
#include <QPainter>
#include <QApplication>
#include <QDBusPendingCall>
#include <QtConcurrent>
#include <QFuture>
#include <xcb/xproto.h>
@ -88,7 +90,7 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent)
setOwnerPID(conn.interface()->servicePid(m_dbusService));
m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this);
m_sniInter->setSync(false);
if (!m_sniInter->isValid()) {
qDebug() << "SNI dbus interface is invalid!" << m_dbusService << m_dbusPath << m_sniInter->lastError();
return;
@ -155,24 +157,7 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent)
QString SNITrayWidget::itemKeyForConfig()
{
QString key;
do {
key = m_sniId;
if (!key.isEmpty()) {
break;
}
key = QDBusInterface(m_dbusService, m_dbusPath, StatusNotifierItem::staticInterfaceName())
.property("Id").toString();
if (!key.isEmpty()) {
break;
}
key = m_sniServicePath;
} while (false);
return QString("sni:%1").arg(key);
return QString("sni:%1").arg(m_sniId.isEmpty() ? m_sniServicePath : m_sniId);
}
void SNITrayWidget::updateIcon()
@ -182,16 +167,20 @@ void SNITrayWidget::updateIcon()
void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y)
{
QDBusPendingReply<> reply;
switch (mouseButton) {
case XCB_BUTTON_INDEX_1:
reply = m_sniInter->Activate(x, y);
// try to invoke context menu while calling activate get a error.
// primarily work for apps using libappindicator.
reply.waitForFinished();
if (reply.isError()) {
showContextMenu(x,y);
}
{
QFuture<void> future = QtConcurrent::run([ = ] {
StatusNotifierItem inter(m_dbusService, m_dbusPath, QDBusConnection::sessionBus());
QDBusPendingReply<> reply = inter.Activate(x, y);
// try to invoke context menu while calling activate get a error.
// primarily work for apps using libappindicator.
reply.waitForFinished();
if (reply.isError()) {
showContextMenu(x,y);
}
});
}
break;
case XCB_BUTTON_INDEX_2:
m_sniInter->SecondaryActivate(x, y);

View File

@ -485,12 +485,22 @@ void TrayPlugin::traySNIAdded(const QString &itemKey, const QString &sniServiceP
return false;
}
// 1、确保服务有效
QDBusInterface sniItemDBus(sniServerName, "/" + list.last());
if (!sniItemDBus.isValid()) {
qDebug() << "sni dbus service error : " << sniServerName;
return false;
}
// 部分服务虽然有效但是在dbus总线上只能看到服务其他信息都无法获取,这里通过Ping进行二次确认
// 参考: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces
// 2、通过Ping接口确认服务是否正常
QDBusInterface peerInter(sniServerName, "/" + list.last(), "org.freedesktop.DBus.Peer");
QDBusReply<void> reply = peerInter.call("Ping");
if (!reply.isValid())
return false;
return true;
});