Linux 客户端的系统托盘图标消息通知的行为存在问题
altairwei opened this issue · comments
1 错误响应浏览器通知消息
简单复现 BUG 的方法:使用浏览器 Notification API 发出通知消息。这时 WizNotePlus 会错误地监听到浏览器消息的 messageClicked 信号。这个问题在 System Tray Icon Example 也能发现,也就是说 Qt 的 QSystemTrayIcon 在 Linux 上的实现存在 bug 。
WizNotePlus 的问题出现在 WizTrayIcon::onMessageClicked()
:
void WizTrayIcon::onMessageClicked()
{
m_app.mainWindow()->raise();
if (m_messageType == wizBubbleMessageCenter)
{
qint64 id = m_messageData.toLongLong();
emit viewMessageRequest(id);
}
else if (m_messageType == wizBubbleNormal)
{
emit viewMessageRequestNormal(m_messageData);
}
}
当错误的收到 messageClicked 信号后,主窗口会被激活到最上层,打断用户的浏览行为。
在 Windows 平台测试下有没有这个问题。确认 Windows 端并没有这个问题。
不同操作系统对 messageClicked
的响应:
- Linux 只有 Critical 消息被点击后才会发出 messageClicked 信号。
- MacOS 对任何类型的消息都有 messageClicked 信号发出。
- Windows 对任何类型的消息都有 messageClicked 信号发出。
对 messageClicked
的错误响应
- Linux 会错误响应消息。
- MacOS 中 Qt 不会错误响应 Chrome 发出的消息。
- Windows 中 Qt 不会错误响应 Chrome 发出的消息。
是不是只有 Chrome 发出的消息才有这个问题?
- ThunderBird 发出的消息没有这个问题。
- FireFox 发出的消息有问题。
- Deepin 浏览器发出的消息有问题。
- 不同 Qt 应用程序之间发送的消息也会相互影响。
2 系统托盘图标无法恢复的问题
在 Linux 端只要 showMessage()
使用了 QSystemTrayIcon::MessageIcon
参数,那么系统托盘图标就无法再恢复原状了。
- Linux 会将系统托盘图标改成 message 的图标。
- Linux xUbuntu 无法使用 setIcon 恢复图标。
- Linux Deepin20 可以使用 setIcon 恢复图标。
- MacOS 不会改变系统托盘图标。
- Windows 不会改变系统托盘图标。
是否可自定义消息的图标
- Linux 不可以自定义消息图标:
- xUbuntu 会显示没有图标的通知消息。但会使用默认图标更改系统托盘图标。
- Deepin20 会显示系统默认图标的通知消息。
- Windows 可以自定义消息的图标。
- MacOS 可以自定义图标,不过它自身也带了一个图标。
3 解决方案
临时解决方案
- Linux 只发送 NoIcon 的通知消息,避免系统托盘图标被更改。
- 在
onMessageClicked()
将 m_messageType 复位到 NoMessage 的状态,避免错误监听其他应用程序的消息。但这存在一个问题:如果用户完全没有点击消息的话,m_messageType 就无法复位了,这依然会导致错误监听。 - 可以考虑在 Linux 平台不监听 messageClick 信号,避免错误监听。
彻底解决方案
重新实现一个新的 WizSystemTrayIcon 类,依赖于更加底层的 API 。
src/gui/kernel/qplatformsystemtrayicon.h
src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
- Linux 只发送 NoIcon 的通知消息,避免系统托盘图标被更改。
- 在 Linux 平台不响应 messageClick 信号,避免错误监听。