xcb: Report location of DBus menubar on window properties
KDE extended the DBus menubar protocol to report the DBus service and path on the window itself, this makes looking it up easier than going through a broker. On Qt5 this worked because we handled the entire DBus menu from scratch in KDE's own platformtheme, but given Qt now has direct dbusmenu bar support it makes sense to have the remaining reporting side all in one place. Change-Id: I78044992fa1840c40a66384033ed790ce0cd7f96 Task-number: QTBUG-116352 Reviewed-by: Liang Qi <liang.qi@qt.io>
This commit is contained in:
parent
9ef4c123c3
commit
efdb5d16df
@ -4,6 +4,10 @@
|
||||
#include "qdbusmenubar_p.h"
|
||||
#include "qdbusmenuregistrarproxy_p.h"
|
||||
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qgenericunixservices_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -18,7 +22,6 @@ QDBusMenuBar::QDBusMenuBar()
|
||||
: QPlatformMenuBar()
|
||||
, m_menu(new QDBusPlatformMenu())
|
||||
, m_menuAdaptor(new QDBusMenuAdaptor(m_menu))
|
||||
, m_windowId(0)
|
||||
{
|
||||
QDBusMenuItem::registerDBusTypes();
|
||||
connect(m_menu, &QDBusPlatformMenu::propertiesUpdated,
|
||||
@ -88,7 +91,7 @@ void QDBusMenuBar::handleReparent(QWindow *newParentWindow)
|
||||
{
|
||||
if (newParentWindow) {
|
||||
unregisterMenuBar();
|
||||
m_windowId = newParentWindow->winId();
|
||||
m_window = newParentWindow;
|
||||
registerMenuBar();
|
||||
}
|
||||
}
|
||||
@ -116,30 +119,39 @@ void QDBusMenuBar::registerMenuBar()
|
||||
return;
|
||||
|
||||
QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this);
|
||||
QDBusPendingReply<> r = registrar.RegisterWindow(m_windowId, QDBusObjectPath(m_objectPath));
|
||||
QDBusPendingReply<> r = registrar.RegisterWindow(m_window->winId(), QDBusObjectPath(m_objectPath));
|
||||
r.waitForFinished();
|
||||
if (r.isError()) {
|
||||
qWarning("Failed to register window menu, reason: %s (\"%s\")",
|
||||
qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message()));
|
||||
connection.unregisterObject(m_objectPath);
|
||||
return;
|
||||
}
|
||||
const auto unixServices = dynamic_cast<QGenericUnixServices *>(
|
||||
QGuiApplicationPrivate::platformIntegration()->services());
|
||||
unixServices->registerDBusMenuForWindow(m_window, connection.baseService(), m_objectPath);
|
||||
}
|
||||
|
||||
void QDBusMenuBar::unregisterMenuBar()
|
||||
{
|
||||
QDBusConnection connection = QDBusConnection::sessionBus();
|
||||
|
||||
if (m_windowId) {
|
||||
if (m_window) {
|
||||
QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this);
|
||||
QDBusPendingReply<> r = registrar.UnregisterWindow(m_windowId);
|
||||
QDBusPendingReply<> r = registrar.UnregisterWindow(m_window->winId());
|
||||
r.waitForFinished();
|
||||
if (r.isError())
|
||||
qWarning("Failed to unregister window menu, reason: %s (\"%s\")",
|
||||
qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message()));
|
||||
|
||||
const auto unixServices = dynamic_cast<QGenericUnixServices *>(
|
||||
QGuiApplicationPrivate::platformIntegration()->services());
|
||||
unixServices->unregisterDBusMenuForWindow(m_window);
|
||||
}
|
||||
|
||||
if (!m_objectPath.isEmpty())
|
||||
if (!m_objectPath.isEmpty()) {
|
||||
connection.unregisterObject(m_objectPath);
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -42,7 +42,7 @@ private:
|
||||
QDBusPlatformMenu *m_menu;
|
||||
QDBusMenuAdaptor *m_menuAdaptor;
|
||||
QHash<quintptr, QDBusPlatformMenuItem *> m_menuItems;
|
||||
uint m_windowId;
|
||||
QPointer<QWindow> m_window;
|
||||
QString m_objectPath;
|
||||
|
||||
QDBusPlatformMenuItem *menuItemForMenu(QPlatformMenu *menu);
|
||||
|
@ -577,6 +577,20 @@ QString QGenericUnixServices::portalWindowIdentifier(QWindow *window)
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
void QGenericUnixServices::registerDBusMenuForWindow(QWindow *window, const QString &service, const QString &path)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(service);
|
||||
Q_UNUSED(path);
|
||||
}
|
||||
|
||||
void QGenericUnixServices::unregisterDBusMenuForWindow(QWindow *window)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
}
|
||||
|
||||
|
||||
bool QGenericUnixServices::hasCapability(Capability capability) const
|
||||
{
|
||||
switch (capability) {
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
void setApplicationBadge(qint64 number);
|
||||
virtual QString portalWindowIdentifier(QWindow *window);
|
||||
|
||||
virtual void registerDBusMenuForWindow(QWindow *window, const QString &service, const QString &path);
|
||||
virtual void unregisterDBusMenuForWindow(QWindow *window);
|
||||
|
||||
private:
|
||||
QString m_webBrowser;
|
||||
QString m_documentLauncher;
|
||||
|
@ -204,6 +204,8 @@ static const char *xcb_atomnames = {
|
||||
"EDID_DATA\0"
|
||||
"XFree86_DDC_EDID1_RAWDATA\0"
|
||||
"_ICC_PROFILE\0"
|
||||
"_KDE_NET_WM_APPMENU_SERVICE_NAME\0"
|
||||
"_KDE_NET_WM_APPMENU_OBJECT_PATH\0"
|
||||
// \0\0 terminates loop.
|
||||
};
|
||||
|
||||
|
@ -211,6 +211,10 @@ public:
|
||||
|
||||
Atom_ICC_PROFILE,
|
||||
|
||||
// AppMenu
|
||||
Atom_KDE_NET_WM_APPMENU_SERVICE_NAME,
|
||||
Atom_KDE_NET_WM_APPMENU_OBJECT_PATH,
|
||||
|
||||
NAtoms
|
||||
};
|
||||
|
||||
|
@ -93,10 +93,12 @@ static bool runningUnderDebugger()
|
||||
#endif
|
||||
}
|
||||
|
||||
class QXcbUnixServices : public QGenericUnixServices
|
||||
class QXcbUnixServices : public QGenericUnixServices, public QXcbObject
|
||||
{
|
||||
public:
|
||||
QString portalWindowIdentifier(QWindow *window) override;
|
||||
void registerDBusMenuForWindow(QWindow *window, const QString &service, const QString &path) override;
|
||||
void unregisterDBusMenuForWindow(QWindow *window) override;
|
||||
};
|
||||
|
||||
|
||||
@ -173,6 +175,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char
|
||||
m_connection = nullptr;
|
||||
return;
|
||||
}
|
||||
m_services->setConnection(m_connection);
|
||||
|
||||
m_fontDatabase.reset(new QGenericUnixFontDatabase());
|
||||
|
||||
@ -601,4 +604,30 @@ QString QXcbUnixServices::portalWindowIdentifier(QWindow *window)
|
||||
return "x11:"_L1 + QString::number(window->winId(), 16);
|
||||
}
|
||||
|
||||
void QXcbUnixServices::registerDBusMenuForWindow(QWindow *window, const QString &service, const QString &path)
|
||||
{
|
||||
const QByteArray serviceValue = service.toLatin1();
|
||||
const QByteArray pathValue = path.toLatin1();
|
||||
|
||||
xcb_change_property(xcb_connection(),
|
||||
XCB_PROP_MODE_REPLACE, window->winId(),
|
||||
atom(QXcbAtom::Atom_KDE_NET_WM_APPMENU_SERVICE_NAME),
|
||||
XCB_ATOM_STRING, 8,
|
||||
serviceValue.length(),
|
||||
serviceValue.constData());
|
||||
|
||||
xcb_change_property(xcb_connection(),
|
||||
XCB_PROP_MODE_REPLACE, window->winId(),
|
||||
atom(QXcbAtom::Atom_KDE_NET_WM_APPMENU_OBJECT_PATH),
|
||||
XCB_ATOM_STRING, 8,
|
||||
pathValue.length(),
|
||||
pathValue.constData());
|
||||
}
|
||||
|
||||
void QXcbUnixServices::unregisterDBusMenuForWindow(QWindow *window)
|
||||
{
|
||||
xcb_delete_property(xcb_connection(), window->winId(), atom(QXcbAtom::Atom_KDE_NET_WM_APPMENU_SERVICE_NAME));
|
||||
xcb_delete_property(xcb_connection(), window->winId(), atom(QXcbAtom::Atom_KDE_NET_WM_APPMENU_OBJECT_PATH));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -18,6 +18,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QXcbConnection;
|
||||
class QAbstractEventDispatcher;
|
||||
class QXcbNativeInterface;
|
||||
class QXcbUnixServices;
|
||||
|
||||
class Q_XCB_EXPORT QXcbIntegration : public QPlatformIntegration
|
||||
#ifndef QT_NO_OPENGL
|
||||
@ -115,7 +116,7 @@ private:
|
||||
mutable QScopedPointer<QPlatformAccessibility> m_accessibility;
|
||||
#endif
|
||||
|
||||
QScopedPointer<QPlatformServices> m_services;
|
||||
QScopedPointer<QXcbUnixServices> m_services;
|
||||
|
||||
mutable QByteArray m_wmClass;
|
||||
const char *m_instanceName;
|
||||
|
Loading…
x
Reference in New Issue
Block a user