summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Edmundson <[email protected]>2023-06-02 13:10:47 +0100
committerDavid Edmundson <[email protected]>2024-10-10 21:14:40 +0000
commitefdb5d16df6f7f400b30596f5ec70f1c5a39fb2d (patch)
tree78fe0072bdf3dd88722f9b849f32d50e3eb13458
parent9ef4c123c39c642357c9e8530d59f32f220a7824 (diff)
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 <[email protected]>
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp24
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h2
-rw-r--r--src/gui/platform/unix/qgenericunixservices.cpp14
-rw-r--r--src/gui/platform/unix/qgenericunixservices_p.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp31
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h3
8 files changed, 74 insertions, 9 deletions
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
index 2c006366cb4..862b60f12d0 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
@@ -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
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
index 3028df7215d..24c63802aa1 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
@@ -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);
diff --git a/src/gui/platform/unix/qgenericunixservices.cpp b/src/gui/platform/unix/qgenericunixservices.cpp
index 3aa071b8b26..32487b16511 100644
--- a/src/gui/platform/unix/qgenericunixservices.cpp
+++ b/src/gui/platform/unix/qgenericunixservices.cpp
@@ -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) {
diff --git a/src/gui/platform/unix/qgenericunixservices_p.h b/src/gui/platform/unix/qgenericunixservices_p.h
index 8bb49527793..9e34f090229 100644
--- a/src/gui/platform/unix/qgenericunixservices_p.h
+++ b/src/gui/platform/unix/qgenericunixservices_p.h
@@ -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;
diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp
index dd5596653cd..d31773a34db 100644
--- a/src/plugins/platforms/xcb/qxcbatom.cpp
+++ b/src/plugins/platforms/xcb/qxcbatom.cpp
@@ -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.
};
diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h
index bc677eaf3e3..7dd52f122c7 100644
--- a/src/plugins/platforms/xcb/qxcbatom.h
+++ b/src/plugins/platforms/xcb/qxcbatom.h
@@ -211,6 +211,10 @@ public:
Atom_ICC_PROFILE,
+ // AppMenu
+ Atom_KDE_NET_WM_APPMENU_SERVICE_NAME,
+ Atom_KDE_NET_WM_APPMENU_OBJECT_PATH,
+
NAtoms
};
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 4dafae31e31..fc5a7e55c50 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -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 &parameters, 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
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index a1e0c3f3e1b..a5323496f75 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -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;