forked from openkylin/ukui-panel
托盘 sniWatcher 增加查询pid接口,合并ukui-sni方案
This commit is contained in:
parent
45c643d87b
commit
3a3f70f27c
|
@ -20,6 +20,7 @@
|
|||
#include "statusnotifieritem_interface.h"
|
||||
SniDaemon::SniDaemon()
|
||||
{
|
||||
qDBusRegisterMetaType<UintList>();
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
dbus.registerObject(QStringLiteral("/StatusNotifierWatcher"),"org.kde.StatusNotifierWatcher",this,QDBusConnection::ExportAllContents);
|
||||
dbus.registerService(QStringLiteral("org.kde.StatusNotifierWatcher"));
|
||||
|
@ -38,59 +39,70 @@ SniDaemon::~SniDaemon()
|
|||
dbus.unregisterService(QStringLiteral("org.kde.StatusNotifierWatcher"));
|
||||
}
|
||||
|
||||
|
||||
void SniDaemon::serviceUnregistered(const QString& name)
|
||||
{
|
||||
qDebug()<<"Service "<< name << "unregistered";
|
||||
m_serviceWatcher->removeWatchedService(name);
|
||||
|
||||
QString match = name + QLatin1Char('/');
|
||||
QStringList::Iterator it = m_registeredServices.begin();
|
||||
qDebug()<<m_registeredServices;
|
||||
while (it != m_registeredServices.end()) {
|
||||
if (it->startsWith(match)) {
|
||||
QString name = *it;
|
||||
it = m_registeredServices.erase(it);
|
||||
emit StatusNotifierItemUnregistered(name);
|
||||
} else {
|
||||
++it;
|
||||
for(const QString &servicePath : m_registeredServices.keys()) {
|
||||
if(servicePath.startsWith(match)) {
|
||||
QString pid = m_registeredServices.take(servicePath);
|
||||
Q_EMIT StatusNotifierItemUnregistered(servicePath);
|
||||
if(!m_registeredServices.values().contains(pid) && pid.toUInt() > 0) {
|
||||
Q_EMIT StatusNotifierItemUnregistered(pid.toUInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_statusNotifierHostServices.contains(name)) {
|
||||
m_statusNotifierHostServices.remove(name);
|
||||
emit StatusNotifierHostUnregistered();
|
||||
Q_EMIT StatusNotifierHostUnregistered();
|
||||
}
|
||||
}
|
||||
|
||||
void SniDaemon::RegisterStatusNotifierItem(const QString &serviceOrPath)
|
||||
void SniDaemon::RegisterStatusNotifierItem(const QString &service)
|
||||
{
|
||||
QString service;
|
||||
QString realService;
|
||||
QString path;
|
||||
if (serviceOrPath.startsWith(QLatin1Char('/'))) {
|
||||
service = message().service();
|
||||
path = serviceOrPath;
|
||||
int slash = service.indexOf('/');
|
||||
if (slash == 0) {
|
||||
realService = message().service();
|
||||
path = service;
|
||||
} else if (slash > 0){
|
||||
realService = service.left(slash);
|
||||
path = service.mid(slash);
|
||||
} else {
|
||||
service = serviceOrPath;
|
||||
realService = service;
|
||||
path = QStringLiteral("/StatusNotifierItem");
|
||||
}
|
||||
QString notifierItemId = service + path;
|
||||
QString notifierItemId = realService + path;
|
||||
if (m_registeredServices.contains(notifierItemId)) {
|
||||
return;
|
||||
}
|
||||
m_serviceWatcher->addWatchedService(service);
|
||||
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(service).value()) {
|
||||
//check if the service has registered a SystemTray object
|
||||
org::kde::StatusNotifierItem trayclient(service, path, QDBusConnection::sessionBus());
|
||||
if (trayclient.isValid()) {
|
||||
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(realService).value()) {
|
||||
org::kde::StatusNotifierItem item(realService, path, QDBusConnection::sessionBus());
|
||||
if (item.isValid()) {
|
||||
qDebug() << "Registering" << notifierItemId << "to system tray";
|
||||
m_registeredServices.append(notifierItemId);
|
||||
emit StatusNotifierItemRegistered(notifierItemId);
|
||||
} else {
|
||||
m_serviceWatcher->removeWatchedService(service);
|
||||
m_serviceWatcher->addWatchedService(service);
|
||||
QString pid = "0";
|
||||
if (realService.contains(QStringLiteral("org.ukui.proxy.StatusNotifierItem"))) {
|
||||
QString pidStr = realService.section("-", 1, 1);
|
||||
if (!pidStr.isEmpty()) {
|
||||
pid = pidStr;
|
||||
}
|
||||
} else {
|
||||
QDBusReply<uint> pidReply = connection().interface()->servicePid(message().service());
|
||||
if (pidReply.isValid()) {
|
||||
pid = QString::number(pidReply.value());
|
||||
}
|
||||
}
|
||||
m_registeredServices.insert(notifierItemId, pid);
|
||||
Q_EMIT StatusNotifierItemRegistered(notifierItemId);
|
||||
if (pid.toUInt() > 0) {
|
||||
Q_EMIT StatusNotifierItemRegistered(pid.toUInt());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_serviceWatcher->removeWatchedService(service);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,13 +115,25 @@ void SniDaemon::RegisterStatusNotifierHost(const QString &service)
|
|||
|
||||
m_statusNotifierHostServices.insert(service);
|
||||
m_serviceWatcher->addWatchedService(service);
|
||||
emit StatusNotifierHostRegistered();
|
||||
Q_EMIT StatusNotifierHostRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SniDaemon::RegisteredStatusNotifierItems() const
|
||||
{
|
||||
return m_registeredServices;
|
||||
return m_registeredServices.keys();
|
||||
}
|
||||
|
||||
UintList SniDaemon::RegisteredStatusNotifierItemPids() const
|
||||
{
|
||||
QStringList pidList = m_registeredServices.values();
|
||||
pidList.removeDuplicates();
|
||||
pidList.removeAll("0");
|
||||
UintList pids;
|
||||
for (const QString &pid : pidList) {
|
||||
pids.append(pid.toInt());
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
bool SniDaemon::IsStatusNotifierHostRegistered() const
|
||||
|
|
|
@ -20,14 +20,21 @@
|
|||
#define SNIDAEMON_H
|
||||
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QMetaType>
|
||||
#include <QStringList>
|
||||
#include <QDBusAbstractInterface>
|
||||
#include <QList>
|
||||
|
||||
typedef QList<quint32> UintList;
|
||||
Q_DECLARE_METATYPE(UintList)
|
||||
|
||||
class SniDaemon : public QObject, protected QDBusContext
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierWatcher")
|
||||
|
||||
Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ RegisteredStatusNotifierItems)
|
||||
Q_PROPERTY(UintList RegisteredStatusNotifierItemPids READ RegisteredStatusNotifierItemPids)
|
||||
Q_PROPERTY(bool IsStatusNotifierHostRegistered READ IsStatusNotifierHostRegistered)
|
||||
Q_PROPERTY(int ProtocolVersion READ ProtocolVersion)
|
||||
public:
|
||||
|
@ -35,7 +42,7 @@ public:
|
|||
~SniDaemon();
|
||||
|
||||
QStringList RegisteredStatusNotifierItems() const;
|
||||
|
||||
UintList RegisteredStatusNotifierItemPids() const;
|
||||
bool IsStatusNotifierHostRegistered() const;
|
||||
|
||||
int ProtocolVersion() const;
|
||||
|
@ -46,7 +53,8 @@ public Q_SLOTS:
|
|||
|
||||
private:
|
||||
QDBusServiceWatcher *m_serviceWatcher = nullptr;
|
||||
QStringList m_registeredServices;
|
||||
// QStringList m_registeredServices;
|
||||
QMultiMap<QString, QString> m_registeredServices;
|
||||
QSet<QString> m_statusNotifierHostServices;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -54,6 +62,8 @@ Q_SIGNALS:
|
|||
void StatusNotifierItemUnregistered(const QString &service);
|
||||
void StatusNotifierHostRegistered();
|
||||
void StatusNotifierHostUnregistered();
|
||||
void StatusNotifierItemRegistered(quint32 pid);
|
||||
void StatusNotifierItemUnregistered(quint32 pid);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void serviceUnregistered(const QString& name);
|
||||
|
|
|
@ -100,13 +100,24 @@ SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent):
|
|||
qDBusRegisterMetaType<KDbusImageStruct>();
|
||||
qRegisterMetaType<KDbusImageVector>("KDbusImageVector");
|
||||
qDBusRegisterMetaType<KDbusImageVector>();
|
||||
|
||||
uint pid = getPid(m_windowId);
|
||||
QString serviceName;
|
||||
if(pid > 0) {
|
||||
uint count = 0;
|
||||
if(m_pidToProxyCount.contains(pid)) {
|
||||
count = m_pidToProxyCount.value(pid) + 1;
|
||||
m_pidToProxyCount.insert(pid, count);
|
||||
} else {
|
||||
m_pidToProxyCount.insert(pid, 1);
|
||||
}
|
||||
serviceName = QStringLiteral("org.ukui.proxy.StatusNotifierItem-") + QString::number(pid) + QStringLiteral("-") + QString::number(count);
|
||||
m_dbus.registerService(serviceName);
|
||||
}
|
||||
m_dbus.registerObject(QStringLiteral("/StatusNotifierItem"), this,QDBusConnection::ExportAllContents);
|
||||
|
||||
|
||||
auto statusNotifierWatcher = new org::kde::StatusNotifierWatcher(QStringLiteral(SNI_WATCHER_SERVICE_NAME), QStringLiteral(SNI_WATCHER_PATH), QDBusConnection::sessionBus(), this);
|
||||
qDebug()<<"sni-proxy:RegisterStatusNotifierItem = " <<m_dbus.baseService();
|
||||
auto reply = statusNotifierWatcher->RegisterStatusNotifierItem(m_dbus.baseService());
|
||||
auto reply = statusNotifierWatcher->RegisterStatusNotifierItem(serviceName.isEmpty()? m_dbus.baseService() : serviceName);
|
||||
reply.waitForFinished();
|
||||
if (reply.isError()) {
|
||||
qWarning() << "could not register SNI:" << reply.error().message();
|
||||
|
@ -673,3 +684,17 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
|
|||
|
||||
sendingClickEvent = false;
|
||||
}
|
||||
|
||||
uint SNIProxy::getPid(const xcb_window_t windowId)
|
||||
{
|
||||
xcb_intern_atom_cookie_t cookie1 = xcb_intern_atom(QX11Info::connection(), false, 11, "_NET_WM_PID");
|
||||
xcb_intern_atom_reply_t *reply1 = xcb_intern_atom_reply(QX11Info::connection(), cookie1, nullptr);
|
||||
m_pidAtom = reply1->atom;
|
||||
free(reply1);
|
||||
xcb_get_property_cookie_t cookie2 = xcb_get_property(QX11Info::connection(), false, windowId, m_pidAtom, XCB_ATOM_CARDINAL, 0, 1);
|
||||
xcb_get_property_reply_t *reply2 = xcb_get_property_reply(QX11Info::connection(), cookie2, nullptr);
|
||||
uint pid = 0;
|
||||
pid = *(uint *)xcb_get_property_value(reply2);
|
||||
free(reply2);
|
||||
return pid;
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ private:
|
|||
void stackContainerWindow(const uint32_t stackMode) const;
|
||||
QString winidtoDesktopFileName(const WId& wid) const;
|
||||
|
||||
uint getPid(const xcb_window_t windowId);
|
||||
|
||||
QDBusConnection m_dbus;
|
||||
xcb_window_t m_windowId;
|
||||
xcb_window_t m_containerWid;
|
||||
|
@ -166,6 +168,8 @@ private:
|
|||
QPixmap m_pixmap;
|
||||
bool sendingClickEvent;
|
||||
InjectMode m_injectMode;
|
||||
xcb_atom_t m_pidAtom;
|
||||
QMap<uint, uint> m_pidToProxyCount;
|
||||
};
|
||||
|
||||
#endif // SNIPROXY_H
|
||||
|
|
Loading…
Reference in New Issue