From e4af18d67df67cc3cc4b66759593eb799e2dc4fe Mon Sep 17 00:00:00 2001 From: Fabian Vogt Date: Tue, 8 Dec 2020 22:12:52 +0100 Subject: [PATCH] Fix global menu for Xwayland windows In a Plasma Wayland session, kded does not use the XCB QPA and so Qt doesn't have an X11 connection. For X11 windows, it has to set some properties on registration to make them known, so just make an X11 connection in that case. --- appmenu/appmenu.cpp | 31 ++++++++++++++++++++++++++----- appmenu/appmenu.h | 9 +++++++++ appmenu/menuimporter.cpp | 3 ++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/appmenu/appmenu.cpp b/appmenu/appmenu.cpp index 4ab710677..236ed2610 100644 --- a/appmenu/appmenu.cpp +++ b/appmenu/appmenu.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #if HAVE_X11 #include @@ -100,16 +99,32 @@ AppMenuModule::AppMenuModule(QObject* parent, const QList&) if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kappmenuview"))) { setupMenuImporter(); } + +#if HAVE_X11 + if (!QX11Info::connection()) { + m_xcbConn = xcb_connect(nullptr, nullptr); + } +#endif } -AppMenuModule::~AppMenuModule() = default; +AppMenuModule::~AppMenuModule() +{ +#if HAVE_X11 + if (m_xcbConn) { + xcb_disconnect(m_xcbConn); + } +#endif +} void AppMenuModule::slotWindowRegistered(WId id, const QString &serviceName, const QDBusObjectPath &menuObjectPath) { #if HAVE_X11 - if (KWindowSystem::isPlatformX11()) { - auto *c = QX11Info::connection(); + auto *c = QX11Info::connection(); + if (!c) { + c = m_xcbConn; + } + if(c) { static xcb_atom_t s_serviceNameAtom = XCB_ATOM_NONE; static xcb_atom_t s_objectPathAtom = XCB_ATOM_NONE; @@ -126,8 +141,14 @@ void AppMenuModule::slotWindowRegistered(WId id, const QString &serviceName, con } } - xcb_change_property(c, XCB_PROP_MODE_REPLACE, id, atom, XCB_ATOM_STRING, + auto cookie = xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, id, atom, XCB_ATOM_STRING, 8, value.length(), value.constData()); + xcb_generic_error_t *error; + if ((error = xcb_request_check(c, cookie))) { + qWarning() << "Got an error"; + free(error); + return; + } }; // TODO only set the property if it doesn't already exist diff --git a/appmenu/appmenu.h b/appmenu/appmenu.h index b66fbfadf..14e023b78 100644 --- a/appmenu/appmenu.h +++ b/appmenu/appmenu.h @@ -27,6 +27,11 @@ #ifndef APPMENUMODULE_H #define APPMENUMODULE_H +#include +#ifdef HAVE_X11 +#include +#endif + #include #include @@ -92,6 +97,10 @@ private: AppmenuDBus *m_appmenuDBus; QDBusServiceWatcher *m_menuViewWatcher; QPointer m_menu; + +#ifdef HAVE_X11 + xcb_connection_t *m_xcbConn = nullptr; +#endif }; #endif diff --git a/appmenu/menuimporter.cpp b/appmenu/menuimporter.cpp index 3d00cc53b..63ad19f8f 100644 --- a/appmenu/menuimporter.cpp +++ b/appmenu/menuimporter.cpp @@ -67,9 +67,10 @@ void MenuImporter::RegisterWindow(WId id, const QDBusObjectPath& path) { KWindowInfo info(id, NET::WMWindowType, NET::WM2WindowClass); NET::WindowTypes mask = NET::AllTypesMask; + auto type = info.windowType(mask); // Menu can try to register, right click in gimp for example - if (info.windowType(mask) & (NET::Menu|NET::DropdownMenu|NET::PopupMenu)) { + if (type != NET::Unknown && (type & (NET::Menu|NET::DropdownMenu|NET::PopupMenu))) { return; }