From 7ac4592ebbedc2ee0411515a04618a9e373ca5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E6=9C=8B=E7=A8=8B?= Date: Fri, 16 Sep 2022 13:10:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=89=98=E7=9B=98=E6=9C=8D=E5=8A=A1=E5=AF=B9=E5=BA=94=E8=BF=9B?= =?UTF-8?q?=E7=A8=8B=E7=8A=B6=E6=80=81=E5=BC=82=E5=B8=B8=E6=97=B6=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E4=BB=BB=E5=8A=A1=E6=A0=8F=E5=8D=A1=E6=AD=BB=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fcitx进程异常时,其statusnotifieritem服务被任务栏调用会导致任务栏卡死 Log: 解决部分情况下任务栏卡死问题 Influence: 托盘服务 Bug: https://pms.uniontech.com/bug-view-121947.html Change-Id: Ia7bc9cf077b3b707677a5fe5388b483600ba0de8 --- .../window/tray/widgets/snitrayitemwidget.cpp | 62 +++++------------ frame/window/tray/widgets/snitrayitemwidget.h | 1 - plugins/tray/snitraywidget.cpp | 66 +++++-------------- plugins/tray/snitraywidget.h | 1 - plugins/tray/trayplugin.cpp | 10 +++ 5 files changed, 44 insertions(+), 96 deletions(-) diff --git a/frame/window/tray/widgets/snitrayitemwidget.cpp b/frame/window/tray/widgets/snitrayitemwidget.cpp index 6bf5b319e..a93215a21 100644 --- a/frame/window/tray/widgets/snitrayitemwidget.cpp +++ b/frame/window/tray/widgets/snitrayitemwidget.cpp @@ -29,6 +29,9 @@ #include #include +#include +#include +#include #include @@ -86,6 +89,7 @@ SNITrayItemWidget::SNITrayItemWidget(const QString &sniServicePath, QWidget *par 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(); @@ -147,30 +151,11 @@ SNITrayItemWidget::SNITrayItemWidget(const QString &sniServicePath, QWidget *par connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] { onSNIStatusChanged(m_sniInter->status()); }); - - initSNIPropertys(); } QString SNITrayItemWidget::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 SNITrayItemWidget::updateIcon() @@ -181,13 +166,18 @@ void SNITrayItemWidget::updateIcon() void SNITrayItemWidget::sendClick(uint8_t mouseButton, int x, int y) { switch (mouseButton) { - case XCB_BUTTON_INDEX_1: - // left button click invalid - if (LeftClickInvalidIdList.contains(m_sniId)) { - showContextMenu(x, y); - } else { - m_sniInter->Activate(x, y); - } + case XCB_BUTTON_INDEX_1: { + QFuture 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); @@ -256,24 +246,6 @@ uint SNITrayItemWidget::servicePID(const QString &servicePath) return conn.interface()->servicePid(serviceName); } -void SNITrayItemWidget::initSNIPropertys() -{ - m_sniAttentionIconName = m_sniInter->attentionIconName(); - m_sniAttentionIconPixmap = m_sniInter->attentionIconPixmap(); - m_sniAttentionMovieName = m_sniInter->attentionMovieName(); - m_sniCategory = m_sniInter->category(); - m_sniIconName = m_sniInter->iconName(); - m_sniIconPixmap = m_sniInter->iconPixmap(); - m_sniIconThemePath = m_sniInter->iconThemePath(); - m_sniId = m_sniInter->id(); - m_sniMenuPath = m_sniInter->menu(); - m_sniOverlayIconName = m_sniInter->overlayIconName(); - m_sniOverlayIconPixmap = m_sniInter->overlayIconPixmap(); - m_sniStatus = m_sniInter->status(); - - m_updateIconTimer->start(); -} - void SNITrayItemWidget::initMenu() { const QString &sniMenuPath = m_sniMenuPath.path(); diff --git a/frame/window/tray/widgets/snitrayitemwidget.h b/frame/window/tray/widgets/snitrayitemwidget.h index eddcb4732..1af8f46c3 100644 --- a/frame/window/tray/widgets/snitrayitemwidget.h +++ b/frame/window/tray/widgets/snitrayitemwidget.h @@ -81,7 +81,6 @@ Q_SIGNALS: void statusChanged(SNITrayItemWidget::ItemStatus status); private Q_SLOTS: - void initSNIPropertys(); void initMenu(); void refreshIcon(); void refreshOverlayIcon(); diff --git a/plugins/tray/snitraywidget.cpp b/plugins/tray/snitraywidget.cpp index 8d88b3059..2500c09c6 100644 --- a/plugins/tray/snitraywidget.cpp +++ b/plugins/tray/snitraywidget.cpp @@ -30,6 +30,9 @@ #include #include +#include +#include +#include #include @@ -39,7 +42,6 @@ DGUI_USE_NAMESPACE const QStringList ItemCategoryList {"ApplicationStatus", "Communications", "SystemServices", "Hardware"}; const QStringList ItemStatusList {"Passive", "Active", "NeedsAttention"}; -const QStringList LeftClickInvalidIdList {"sogou-qimpanel",}; QPointer SNITrayWidget::PopupWindow = nullptr; Dock::Position SNITrayWidget::DockPosition = Dock::Position::Top; using namespace Dock; @@ -93,7 +95,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; @@ -154,30 +156,11 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent) connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] { onSNIStatusChanged(m_sniInter->status()); }); - - initSNIPropertys(); } 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() @@ -188,13 +171,18 @@ void SNITrayWidget::updateIcon() void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y) { switch (mouseButton) { - case XCB_BUTTON_INDEX_1: - // left button click invalid - if (LeftClickInvalidIdList.contains(m_sniId)) { - showContextMenu(x, y); - } else { - m_sniInter->Activate(x, y); - } + case XCB_BUTTON_INDEX_1: { + QFuture 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); @@ -263,26 +251,6 @@ uint SNITrayWidget::servicePID(const QString &servicePath) return conn.interface()->servicePid(serviceName); } -void SNITrayWidget::initSNIPropertys() -{ - m_sniAttentionIconName = m_sniInter->attentionIconName(); - m_sniAttentionIconPixmap = m_sniInter->attentionIconPixmap(); - m_sniAttentionMovieName = m_sniInter->attentionMovieName(); - m_sniCategory = m_sniInter->category(); - m_sniIconName = m_sniInter->iconName(); - m_sniIconPixmap = m_sniInter->iconPixmap(); - m_sniIconThemePath = m_sniInter->iconThemePath(); - m_sniId = m_sniInter->id(); - m_sniMenuPath = m_sniInter->menu(); - m_sniOverlayIconName = m_sniInter->overlayIconName(); - m_sniOverlayIconPixmap = m_sniInter->overlayIconPixmap(); - m_sniStatus = m_sniInter->status(); - - m_updateIconTimer->start(); -// m_updateOverlayIconTimer->start(); -// m_updateAttentionIconTimer->start(); -} - void SNITrayWidget::initMenu() { const QString &sniMenuPath = m_sniMenuPath.path(); diff --git a/plugins/tray/snitraywidget.h b/plugins/tray/snitraywidget.h index 65b487fd1..17517bda4 100644 --- a/plugins/tray/snitraywidget.h +++ b/plugins/tray/snitraywidget.h @@ -79,7 +79,6 @@ Q_SIGNALS: void statusChanged(SNITrayWidget::ItemStatus status); private Q_SLOTS: - void initSNIPropertys(); void initMenu(); void refreshIcon(); void refreshOverlayIcon(); diff --git a/plugins/tray/trayplugin.cpp b/plugins/tray/trayplugin.cpp index 1060c963a..22d737a44 100644 --- a/plugins/tray/trayplugin.cpp +++ b/plugins/tray/trayplugin.cpp @@ -480,12 +480,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 reply = peerInter.call("Ping"); + if (!reply.isValid()) + return false; + return true; });