mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +00:00
fix: 修复部分托盘服务对应进程状态异常时导致任务栏卡死问题
fcitx进程异常时,其statusnotifieritem服务被任务栏调用会导致任务栏卡死 Log: 解决部分情况下任务栏卡死问题 Influence: 托盘服务 Bug: https://pms.uniontech.com/bug-view-121947.html Change-Id: Ia7bc9cf077b3b707677a5fe5388b483600ba0de8
This commit is contained in:
parent
c7826edd46
commit
7ac4592ebb
@ -29,6 +29,9 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDBusPendingCall>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
#include <QFuture>
|
||||||
|
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@ -86,6 +89,7 @@ SNITrayItemWidget::SNITrayItemWidget(const QString &sniServicePath, QWidget *par
|
|||||||
setOwnerPID(conn.interface()->servicePid(m_dbusService));
|
setOwnerPID(conn.interface()->servicePid(m_dbusService));
|
||||||
|
|
||||||
m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this);
|
m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this);
|
||||||
|
m_sniInter->setSync(false);
|
||||||
|
|
||||||
if (!m_sniInter->isValid()) {
|
if (!m_sniInter->isValid()) {
|
||||||
qDebug() << "SNI dbus interface is invalid!" << m_dbusService << m_dbusPath << m_sniInter->lastError();
|
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, [ = ] {
|
connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] {
|
||||||
onSNIStatusChanged(m_sniInter->status());
|
onSNIStatusChanged(m_sniInter->status());
|
||||||
});
|
});
|
||||||
|
|
||||||
initSNIPropertys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SNITrayItemWidget::itemKeyForConfig()
|
QString SNITrayItemWidget::itemKeyForConfig()
|
||||||
{
|
{
|
||||||
QString key;
|
return QString("sni:%1").arg(m_sniId.isEmpty() ? m_sniServicePath : m_sniId);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SNITrayItemWidget::updateIcon()
|
void SNITrayItemWidget::updateIcon()
|
||||||
@ -181,13 +166,18 @@ void SNITrayItemWidget::updateIcon()
|
|||||||
void SNITrayItemWidget::sendClick(uint8_t mouseButton, int x, int y)
|
void SNITrayItemWidget::sendClick(uint8_t mouseButton, int x, int y)
|
||||||
{
|
{
|
||||||
switch (mouseButton) {
|
switch (mouseButton) {
|
||||||
case XCB_BUTTON_INDEX_1:
|
case XCB_BUTTON_INDEX_1: {
|
||||||
// left button click invalid
|
QFuture<void> future = QtConcurrent::run([ = ] {
|
||||||
if (LeftClickInvalidIdList.contains(m_sniId)) {
|
StatusNotifierItem inter(m_dbusService, m_dbusPath, QDBusConnection::sessionBus());
|
||||||
showContextMenu(x, y);
|
QDBusPendingReply<> reply = inter.Activate(x, y);
|
||||||
} else {
|
// try to invoke context menu while calling activate get a error.
|
||||||
m_sniInter->Activate(x, y);
|
// primarily work for apps using libappindicator.
|
||||||
}
|
reply.waitForFinished();
|
||||||
|
if (reply.isError()) {
|
||||||
|
showContextMenu(x,y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case XCB_BUTTON_INDEX_2:
|
case XCB_BUTTON_INDEX_2:
|
||||||
m_sniInter->SecondaryActivate(x, y);
|
m_sniInter->SecondaryActivate(x, y);
|
||||||
@ -256,24 +246,6 @@ uint SNITrayItemWidget::servicePID(const QString &servicePath)
|
|||||||
return conn.interface()->servicePid(serviceName);
|
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()
|
void SNITrayItemWidget::initMenu()
|
||||||
{
|
{
|
||||||
const QString &sniMenuPath = m_sniMenuPath.path();
|
const QString &sniMenuPath = m_sniMenuPath.path();
|
||||||
|
@ -81,7 +81,6 @@ Q_SIGNALS:
|
|||||||
void statusChanged(SNITrayItemWidget::ItemStatus status);
|
void statusChanged(SNITrayItemWidget::ItemStatus status);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initSNIPropertys();
|
|
||||||
void initMenu();
|
void initMenu();
|
||||||
void refreshIcon();
|
void refreshIcon();
|
||||||
void refreshOverlayIcon();
|
void refreshOverlayIcon();
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDBusPendingCall>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
#include <QFuture>
|
||||||
|
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@ -39,7 +42,6 @@ DGUI_USE_NAMESPACE
|
|||||||
|
|
||||||
const QStringList ItemCategoryList {"ApplicationStatus", "Communications", "SystemServices", "Hardware"};
|
const QStringList ItemCategoryList {"ApplicationStatus", "Communications", "SystemServices", "Hardware"};
|
||||||
const QStringList ItemStatusList {"Passive", "Active", "NeedsAttention"};
|
const QStringList ItemStatusList {"Passive", "Active", "NeedsAttention"};
|
||||||
const QStringList LeftClickInvalidIdList {"sogou-qimpanel",};
|
|
||||||
QPointer<DockPopupWindow> SNITrayWidget::PopupWindow = nullptr;
|
QPointer<DockPopupWindow> SNITrayWidget::PopupWindow = nullptr;
|
||||||
Dock::Position SNITrayWidget::DockPosition = Dock::Position::Top;
|
Dock::Position SNITrayWidget::DockPosition = Dock::Position::Top;
|
||||||
using namespace Dock;
|
using namespace Dock;
|
||||||
@ -93,7 +95,7 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent)
|
|||||||
setOwnerPID(conn.interface()->servicePid(m_dbusService));
|
setOwnerPID(conn.interface()->servicePid(m_dbusService));
|
||||||
|
|
||||||
m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this);
|
m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this);
|
||||||
|
m_sniInter->setSync(false);
|
||||||
if (!m_sniInter->isValid()) {
|
if (!m_sniInter->isValid()) {
|
||||||
qDebug() << "SNI dbus interface is invalid!" << m_dbusService << m_dbusPath << m_sniInter->lastError();
|
qDebug() << "SNI dbus interface is invalid!" << m_dbusService << m_dbusPath << m_sniInter->lastError();
|
||||||
return;
|
return;
|
||||||
@ -154,30 +156,11 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent)
|
|||||||
connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] {
|
connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] {
|
||||||
onSNIStatusChanged(m_sniInter->status());
|
onSNIStatusChanged(m_sniInter->status());
|
||||||
});
|
});
|
||||||
|
|
||||||
initSNIPropertys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SNITrayWidget::itemKeyForConfig()
|
QString SNITrayWidget::itemKeyForConfig()
|
||||||
{
|
{
|
||||||
QString key;
|
return QString("sni:%1").arg(m_sniId.isEmpty() ? m_sniServicePath : m_sniId);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SNITrayWidget::updateIcon()
|
void SNITrayWidget::updateIcon()
|
||||||
@ -188,13 +171,18 @@ void SNITrayWidget::updateIcon()
|
|||||||
void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y)
|
void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y)
|
||||||
{
|
{
|
||||||
switch (mouseButton) {
|
switch (mouseButton) {
|
||||||
case XCB_BUTTON_INDEX_1:
|
case XCB_BUTTON_INDEX_1: {
|
||||||
// left button click invalid
|
QFuture<void> future = QtConcurrent::run([ = ] {
|
||||||
if (LeftClickInvalidIdList.contains(m_sniId)) {
|
StatusNotifierItem inter(m_dbusService, m_dbusPath, QDBusConnection::sessionBus());
|
||||||
showContextMenu(x, y);
|
QDBusPendingReply<> reply = inter.Activate(x, y);
|
||||||
} else {
|
// try to invoke context menu while calling activate get a error.
|
||||||
m_sniInter->Activate(x, y);
|
// primarily work for apps using libappindicator.
|
||||||
}
|
reply.waitForFinished();
|
||||||
|
if (reply.isError()) {
|
||||||
|
showContextMenu(x,y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case XCB_BUTTON_INDEX_2:
|
case XCB_BUTTON_INDEX_2:
|
||||||
m_sniInter->SecondaryActivate(x, y);
|
m_sniInter->SecondaryActivate(x, y);
|
||||||
@ -263,26 +251,6 @@ uint SNITrayWidget::servicePID(const QString &servicePath)
|
|||||||
return conn.interface()->servicePid(serviceName);
|
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()
|
void SNITrayWidget::initMenu()
|
||||||
{
|
{
|
||||||
const QString &sniMenuPath = m_sniMenuPath.path();
|
const QString &sniMenuPath = m_sniMenuPath.path();
|
||||||
|
@ -79,7 +79,6 @@ Q_SIGNALS:
|
|||||||
void statusChanged(SNITrayWidget::ItemStatus status);
|
void statusChanged(SNITrayWidget::ItemStatus status);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initSNIPropertys();
|
|
||||||
void initMenu();
|
void initMenu();
|
||||||
void refreshIcon();
|
void refreshIcon();
|
||||||
void refreshOverlayIcon();
|
void refreshOverlayIcon();
|
||||||
|
@ -480,12 +480,22 @@ void TrayPlugin::traySNIAdded(const QString &itemKey, const QString &sniServiceP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1、确保服务有效
|
||||||
QDBusInterface sniItemDBus(sniServerName, "/" + list.last());
|
QDBusInterface sniItemDBus(sniServerName, "/" + list.last());
|
||||||
if (!sniItemDBus.isValid()) {
|
if (!sniItemDBus.isValid()) {
|
||||||
qDebug() << "sni dbus service error : " << sniServerName;
|
qDebug() << "sni dbus service error : " << sniServerName;
|
||||||
return false;
|
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;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user