mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 17:33:05 +00:00
fix: tray item identify
https://github.com/linuxdeepin/internal-discussion/issues/616 Change-Id: I6fc26d153e82643720ac21111d52cac26fbcff06
This commit is contained in:
parent
3c134e5583
commit
f7699e3596
Notes:
gerrit
2019-01-03 19:00:34 +08:00
Verified+1: <jenkins@deepin.com> Code-Review+2: listenerri <listenerri@gmail.com> Submitted-by: listenerri <listenerri@gmail.com> Submitted-at: Thu, 03 Jan 2019 19:00:33 +0800 Reviewed-on: https://cr.deepin.io/41076 Project: dde/dde-dock Branch: refs/heads/master
@ -111,6 +111,42 @@ bool SNITrayWidget::isValid()
|
||||
return m_sniInter->isValid();
|
||||
}
|
||||
|
||||
QString SNITrayWidget::toSNIKey(const QString &sniServicePath)
|
||||
{
|
||||
QString key;
|
||||
|
||||
do {
|
||||
const QPair<QString, QString> &sap = serviceAndPath(sniServicePath);
|
||||
key = QDBusInterface(sap.first, sap.second).property("Id").toString();
|
||||
if (!key.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
key = sniServicePath;
|
||||
} while (false);
|
||||
|
||||
return QString("sni:%1").arg(key);
|
||||
}
|
||||
|
||||
bool SNITrayWidget::isSNIKey(const QString &itemKey)
|
||||
{
|
||||
return itemKey.startsWith("sni:");
|
||||
}
|
||||
|
||||
QPair<QString, QString> SNITrayWidget::serviceAndPath(const QString &servicePath)
|
||||
{
|
||||
QStringList list = servicePath.split("/");
|
||||
QPair<QString, QString> pair;
|
||||
pair.first = list.takeFirst();
|
||||
|
||||
for (auto i : list) {
|
||||
pair.second.append("/");
|
||||
pair.second.append(i);
|
||||
}
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
void SNITrayWidget::initMenu()
|
||||
{
|
||||
qDebug() << "using sni service path:" << m_dbusService;
|
||||
@ -244,20 +280,6 @@ void SNITrayWidget::paintEvent(QPaintEvent *e)
|
||||
painter.end();
|
||||
}
|
||||
|
||||
QPair<QString, QString> SNITrayWidget::serviceAndPath(const QString &servicePath)
|
||||
{
|
||||
QStringList list = servicePath.split("/");
|
||||
QPair<QString, QString> pair;
|
||||
pair.first = list.takeFirst();
|
||||
|
||||
for (auto i : list) {
|
||||
pair.second.append("/");
|
||||
pair.second.append(i);
|
||||
}
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
QPixmap SNITrayWidget::newIconPixmap(IconType iconType)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
|
@ -50,9 +50,9 @@ public:
|
||||
|
||||
bool isValid();
|
||||
|
||||
static QString toSNIKey(const QString &sniServicePath) { return QString("sni:%1").arg(sniServicePath); }
|
||||
static bool isSNIKey(const QString &itemKey) { return itemKey.startsWith("sni:"); }
|
||||
static QString toSNIServicePath(QString itemKey) { return itemKey.remove("sni:"); }
|
||||
static QString toSNIKey(const QString &sniServicePath);
|
||||
static bool isSNIKey(const QString &itemKey);
|
||||
static QPair<QString, QString> serviceAndPath(const QString &servicePath);
|
||||
|
||||
private Q_SLOTS:
|
||||
void initMenu();
|
||||
@ -64,7 +64,6 @@ private Q_SLOTS:
|
||||
private:
|
||||
QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||
void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;
|
||||
QPair<QString, QString> serviceAndPath(const QString &servicePath);
|
||||
QPixmap newIconPixmap(IconType iconType);
|
||||
|
||||
private:
|
||||
|
@ -166,11 +166,9 @@ bool TrayPlugin::itemAllowContainer(const QString &itemKey)
|
||||
|
||||
bool TrayPlugin::itemIsInContainer(const QString &itemKey)
|
||||
{
|
||||
const QString widKey = getWindowClass(XWindowTrayWidget::toWinId(itemKey));
|
||||
const QString &key = "container_" + itemKey;
|
||||
|
||||
return m_proxyInter
|
||||
->getValue(this, widKey.isEmpty() ? itemKey : widKey, false)
|
||||
.toBool();
|
||||
return m_proxyInter->getValue(this, key, false).toBool();
|
||||
}
|
||||
|
||||
int TrayPlugin::itemSortKey(const QString &itemKey)
|
||||
@ -202,9 +200,9 @@ void TrayPlugin::setSortKey(const QString &itemKey, const int order)
|
||||
|
||||
void TrayPlugin::setItemIsInContainer(const QString &itemKey, const bool container)
|
||||
{
|
||||
const QString widKey = getWindowClass(XWindowTrayWidget::toWinId(itemKey));
|
||||
const QString &key = "container_" + itemKey;
|
||||
|
||||
m_proxyInter->saveValue(this, widKey.isEmpty() ? itemKey : widKey, container);
|
||||
m_proxyInter->saveValue(this, key, container);
|
||||
}
|
||||
|
||||
void TrayPlugin::refreshIcon(const QString &itemKey)
|
||||
@ -244,27 +242,6 @@ const QVariant TrayPlugin::getValue(const QString &key, const QVariant &fallback
|
||||
return m_proxyInter->getValue(this, key, fallback);
|
||||
}
|
||||
|
||||
const QString TrayPlugin::getWindowClass(quint32 winId)
|
||||
{
|
||||
auto *connection = QX11Info::connection();
|
||||
|
||||
auto *reply = new xcb_icccm_get_wm_class_reply_t;
|
||||
auto *error = new xcb_generic_error_t;
|
||||
auto cookie = xcb_icccm_get_wm_class(connection, winId);
|
||||
auto result = xcb_icccm_get_wm_class_reply(connection, cookie, reply, &error);
|
||||
|
||||
QString ret;
|
||||
if (result == 1) {
|
||||
ret = QString("%1-%2").arg(reply->class_name).arg(reply->instance_name);
|
||||
xcb_icccm_get_wm_class_reply_wipe(reply);
|
||||
}
|
||||
|
||||
delete reply;
|
||||
delete error;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TrayPlugin::isSystemTrayItem(const QString &itemKey)
|
||||
{
|
||||
AbstractTrayWidget * const trayWidget = m_trayMap.value(itemKey, nullptr);
|
||||
@ -297,32 +274,34 @@ void TrayPlugin::sniItemsChanged()
|
||||
for (auto item : itemServicePaths) {
|
||||
sinTrayKeyList << SNITrayWidget::toSNIKey(item);
|
||||
}
|
||||
for (auto itemKey : m_trayMap.keys())
|
||||
for (auto itemKey : m_trayMap.keys()) {
|
||||
if (!sinTrayKeyList.contains(itemKey) && SNITrayWidget::isSNIKey(itemKey)) {
|
||||
trayRemoved(itemKey);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tray : sinTrayKeyList) {
|
||||
trayAdded(tray);
|
||||
for (int i = 0; i < sinTrayKeyList.size(); ++i) {
|
||||
traySNIAdded(sinTrayKeyList.at(i), itemServicePaths.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
void TrayPlugin::trayListChanged()
|
||||
{
|
||||
QList<quint32> winidList = m_trayInter->trayIcons();
|
||||
QStringList trayList;
|
||||
QStringList trayKeyList;
|
||||
|
||||
for (auto winid : winidList) {
|
||||
trayList << XWindowTrayWidget::toTrayWidgetId(winid);
|
||||
trayKeyList << XWindowTrayWidget::toTrayWidgetId(winid);
|
||||
}
|
||||
|
||||
for (auto tray : m_trayMap.keys())
|
||||
if (!trayList.contains(tray) && XWindowTrayWidget::isWinIdKey(tray)) {
|
||||
for (auto tray : m_trayMap.keys()) {
|
||||
if (!trayKeyList.contains(tray) && XWindowTrayWidget::isXWindowKey(tray)) {
|
||||
trayRemoved(tray);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tray : trayList) {
|
||||
trayAdded(tray);
|
||||
for (int i = 0; i < trayKeyList.size(); ++i) {
|
||||
trayXWindowAdded(trayKeyList.at(i), winidList.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,44 +326,53 @@ void TrayPlugin::addTrayWidget(const QString &itemKey, AbstractTrayWidget *trayW
|
||||
connect(trayWidget, &AbstractTrayWidget::requestRefershWindowVisible, this, &TrayPlugin::onRequestRefershWindowVisible, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void TrayPlugin::trayAdded(const QString &itemKey)
|
||||
void TrayPlugin::trayXWindowAdded(const QString &itemKey, quint32 winId)
|
||||
{
|
||||
if (m_trayMap.contains(itemKey)) {
|
||||
if (m_trayMap.contains(itemKey) || !XWindowTrayWidget::isXWindowKey(itemKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (XWindowTrayWidget::isWinIdKey(itemKey)) {
|
||||
auto winId = XWindowTrayWidget::toWinId(itemKey);
|
||||
getWindowClass(winId);
|
||||
AbstractTrayWidget *trayWidget = new XWindowTrayWidget(winId);
|
||||
addTrayWidget(itemKey, trayWidget);
|
||||
} else if (SNITrayWidget::isSNIKey(itemKey)) {
|
||||
const QString &sniServicePath = SNITrayWidget::toSNIServicePath(itemKey);
|
||||
AbstractTrayWidget *trayWidget = new SNITrayWidget(sniServicePath);
|
||||
connect(trayWidget, &AbstractTrayWidget::iconChanged, this, &TrayPlugin::sniItemIconChanged);
|
||||
addTrayWidget(itemKey, trayWidget);
|
||||
} else if (IndicatorTrayWidget::isIndicatorKey(itemKey)) {
|
||||
IndicatorTray *trayWidget = nullptr;
|
||||
QString indicatorKey = IndicatorTrayWidget::toIndicatorId(itemKey);
|
||||
AbstractTrayWidget *trayWidget = new XWindowTrayWidget(winId);
|
||||
addTrayWidget(itemKey, trayWidget);
|
||||
}
|
||||
|
||||
if (!m_indicatorMap.keys().contains(itemKey)) {
|
||||
trayWidget = new IndicatorTray(indicatorKey);
|
||||
m_indicatorMap[indicatorKey] = trayWidget;
|
||||
}
|
||||
else {
|
||||
trayWidget = m_indicatorMap[itemKey];
|
||||
}
|
||||
|
||||
connect(trayWidget, &IndicatorTray::delayLoaded,
|
||||
trayWidget, [ = ]() {
|
||||
addTrayWidget(itemKey, trayWidget->widget());
|
||||
});
|
||||
|
||||
connect(trayWidget, &IndicatorTray::removed, this, [=] {
|
||||
trayRemoved(itemKey);
|
||||
trayWidget->removeWidget();
|
||||
});
|
||||
void TrayPlugin::traySNIAdded(const QString &itemKey, const QString &sniServicePath)
|
||||
{
|
||||
if (m_trayMap.contains(itemKey) || !SNITrayWidget::isSNIKey(itemKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractTrayWidget *trayWidget = new SNITrayWidget(sniServicePath);
|
||||
connect(trayWidget, &AbstractTrayWidget::iconChanged, this, &TrayPlugin::sniItemIconChanged);
|
||||
addTrayWidget(itemKey, trayWidget);
|
||||
}
|
||||
|
||||
void TrayPlugin::trayIndicatorAdded(const QString &itemKey)
|
||||
{
|
||||
if (m_trayMap.contains(itemKey) || !IndicatorTrayWidget::isIndicatorKey(itemKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IndicatorTray *trayWidget = nullptr;
|
||||
QString indicatorKey = IndicatorTrayWidget::toIndicatorId(itemKey);
|
||||
|
||||
if (!m_indicatorMap.keys().contains(itemKey)) {
|
||||
trayWidget = new IndicatorTray(indicatorKey);
|
||||
m_indicatorMap[indicatorKey] = trayWidget;
|
||||
}
|
||||
else {
|
||||
trayWidget = m_indicatorMap[itemKey];
|
||||
}
|
||||
|
||||
connect(trayWidget, &IndicatorTray::delayLoaded,
|
||||
trayWidget, [ = ]() {
|
||||
addTrayWidget(itemKey, trayWidget->widget());
|
||||
});
|
||||
|
||||
connect(trayWidget, &IndicatorTray::removed, this, [=] {
|
||||
trayRemoved(itemKey);
|
||||
trayWidget->removeWidget();
|
||||
});
|
||||
}
|
||||
|
||||
void TrayPlugin::trayRemoved(const QString &itemKey)
|
||||
@ -486,6 +474,6 @@ void TrayPlugin::loadIndicator()
|
||||
QDir indicatorConfDir("/etc/dde-dock/indicator");
|
||||
|
||||
for (auto fileInfo : indicatorConfDir.entryInfoList({"*.json"}, QDir::Files | QDir::NoDotAndDotDot)) {
|
||||
trayAdded(IndicatorTrayWidget::toTrayWidgetId(fileInfo.baseName()));
|
||||
trayIndicatorAdded(IndicatorTrayWidget::toTrayWidgetId(fileInfo.baseName()));
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,6 @@ public:
|
||||
|
||||
private:
|
||||
void loadIndicator();
|
||||
const QString getWindowClass(quint32 winId);
|
||||
bool isSystemTrayItem(const QString &itemKey);
|
||||
QString itemKeyOfTrayWidget(AbstractTrayWidget *trayWidget);
|
||||
|
||||
@ -74,7 +73,9 @@ private slots:
|
||||
void addTrayWidget(const QString &itemKey, AbstractTrayWidget *trayWidget);
|
||||
void sniItemsChanged();
|
||||
void trayListChanged();
|
||||
void trayAdded(const QString &itemKey);
|
||||
void trayXWindowAdded(const QString &itemKey, quint32 winId);
|
||||
void traySNIAdded(const QString &itemKey, const QString &sniServicePath);
|
||||
void trayIndicatorAdded(const QString &itemKey);
|
||||
void trayRemoved(const QString &itemKey);
|
||||
void trayChanged(quint32 winId);
|
||||
void sniItemIconChanged();
|
||||
|
@ -38,6 +38,9 @@
|
||||
#include <xcb/composite.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
|
||||
#define NORMAL_WINDOW_PROP_NAME "WM_CLASS"
|
||||
#define WINE_WINDOW_PROP_NAME "__wine_prefix"
|
||||
|
||||
static const qreal iconSize = 16;
|
||||
|
||||
const QPoint rawXPosition(const QPoint &scaledPos)
|
||||
@ -318,6 +321,68 @@ void XWindowTrayWidget::sendClick(uint8_t mouseButton, int x, int y)
|
||||
QTimer::singleShot(100, this, [=] { setX11PassMouseEvent(true); });
|
||||
}
|
||||
|
||||
// NOTE: WM_NAME may can not obtain successfully
|
||||
QString XWindowTrayWidget::getWindowProperty(quint32 winId, QString propName)
|
||||
{
|
||||
const auto display = QX11Info::display();
|
||||
|
||||
Atom atom_prop = XInternAtom(display, propName.toLocal8Bit(), true);
|
||||
if (!atom_prop) {
|
||||
qDebug() << "Error: get window property failed, invalid property atom";
|
||||
return QString();
|
||||
}
|
||||
|
||||
Atom actual_type_return;
|
||||
int actual_format_return;
|
||||
unsigned long nitems_return;
|
||||
unsigned long bytes_after_return;
|
||||
unsigned char *prop_return;
|
||||
|
||||
int r = XGetWindowProperty(display, winId, atom_prop, 0, 100, false, AnyPropertyType,
|
||||
&actual_type_return, &actual_format_return, &nitems_return,
|
||||
&bytes_after_return, &prop_return);
|
||||
|
||||
Q_UNUSED(r);
|
||||
|
||||
// qDebug() << (r == Success)
|
||||
// << actual_type_return
|
||||
// << actual_format_return
|
||||
// << nitems_return
|
||||
// << bytes_after_return
|
||||
// << QString::fromLocal8Bit((char*)prop_return);
|
||||
|
||||
return QString::fromLocal8Bit((char*)prop_return);
|
||||
}
|
||||
|
||||
QString XWindowTrayWidget::toTrayWidgetId(quint32 winId)
|
||||
{
|
||||
QString key;
|
||||
|
||||
do {
|
||||
// is wine application
|
||||
key = getWindowProperty(winId, WINE_WINDOW_PROP_NAME).split("/").last();
|
||||
if (!key.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// is normal application
|
||||
key = getWindowProperty(winId, NORMAL_WINDOW_PROP_NAME);
|
||||
if (!key.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// fallback to window id
|
||||
key = QString::number(winId);
|
||||
} while (false);
|
||||
|
||||
return QString("window:%1").arg(key);
|
||||
}
|
||||
|
||||
bool XWindowTrayWidget::isXWindowKey(const QString &itemKey)
|
||||
{
|
||||
return itemKey.startsWith("window:");
|
||||
}
|
||||
|
||||
void XWindowTrayWidget::setActive(const bool active)
|
||||
{
|
||||
m_active = active;
|
||||
|
@ -22,11 +22,11 @@
|
||||
#ifndef TRAYWIDGET_H
|
||||
#define TRAYWIDGET_H
|
||||
|
||||
#include "abstracttraywidget.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#include <abstracttraywidget.h>
|
||||
|
||||
class XWindowTrayWidget : public AbstractTrayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -40,9 +40,9 @@ public:
|
||||
const QImage trayImage() Q_DECL_OVERRIDE;
|
||||
void sendClick(uint8_t mouseButton, int x, int y) Q_DECL_OVERRIDE;
|
||||
|
||||
static QString toTrayWidgetId(quint32 winId) { return QString("window:%1").arg(winId); }
|
||||
static bool isWinIdKey(const QString &itemKey) { return itemKey.startsWith("window:"); }
|
||||
static quint32 toWinId(QString itemKey) { return itemKey.remove("window:").toUInt() ; }
|
||||
static QString getWindowProperty(quint32 winId, QString propName);
|
||||
static QString toTrayWidgetId(quint32 winId);
|
||||
static bool isXWindowKey(const QString &itemKey);
|
||||
|
||||
private:
|
||||
QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user