helloSystem/Menu

Show menu for Qt applications with default Qt platform plugin and theme

probonopd opened this issue · 5 comments

Qt5 and Qt6 with the default Unix platform plugin and theme QGenericUnixTheme do export their menus via D-Bus, but Menu can't use them, presumably because Qt does not set the atoms _KDE_NET_WM_APPMENU_OBJECT_PATH(STRING) and _KDE_NET_WM_APPMENU_SERVICE_NAME(STRING) on windows.

It looks to me like Scribus (a Qt6 application) is sending its menus over D-Bus, but for some reason Menu is not using them:

# Unlike with Qt5, it seems like with Qt6 the default platform theme sends menus over D-Bus
unset QT_QPA_PLATFORMTHEME
scribus

Here is a log of D-Bus activity, made with dbus-monitor "interface='com.canonical.dbusmenu'" 2>&1 > /tmp/scribus.log:

scribus.zip

The "proprietary" _KDE... properties (which I never quite understood the sudden need for - I remember having seen working global menus before those existed; and it seems like Gtk also doesn't need them) are not set on the window by Qt:

% xprop | grep _KDE (((click on Scribus window)))
_KDE_NET_WM_FRAME_STRUT(CARDINAL) = 0, 0, 22, 0
_KDE_NET_WM_USER_CREATION_TIME(CARDINAL) = 6714610

I wonder what good it is that Qt5/6 tries to export the menus over D-Bus but is not setting _KDE_NET_WM_APPMENU_OBJECT_PATH(STRING) and _KDE_NET_WM_APPMENU_SERVICE_NAME(STRING). Does this mean we might be able to change Menu to make use of the D-Bus information even if those are not set?

For example, could Menu itself figure out the values needed for those, and set them on the windows (similar to what we are already doing for, e.g., _EXECUTABLE_PATH) if Qt5/6 is not doing it?

@jsm222 wdyt?

Edit: Updated the issue since this is the same in Qt6 and Qt5. (The reason I revisited this topic is that currently we only ship QtPlugin for Qt5, not yet for Qt6.)

In other words, could we port something like

https://github.com/helloSystem/QtPlugin/blob/846b6a115bf1574deaef6e37d9e2f33fad649a59/platformthemeplugin/pandaplatformtheme.cpp#L168-L182

static const QByteArray s_x11AppMenuServiceNamePropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_SERVICE_NAME");
static const QByteArray s_x11AppMenuObjectPathPropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_OBJECT_PATH");

        QObject::connect(menu, &QDBusMenuBar::windowChanged, menu, [this, menu](QWindow *newWindow, QWindow *oldWindow) {
            const QString &serviceName = QDBusConnection::sessionBus().baseService();
            const QString &objectPath = menu->objectPath();

            if (m_x11Integration) {
                if (oldWindow) {
                    m_x11Integration->setWindowProperty(oldWindow, s_x11AppMenuServiceNamePropertyName, {});
                    m_x11Integration->setWindowProperty(oldWindow, s_x11AppMenuObjectPathPropertyName, {});
                }

                if (newWindow) {
                    m_x11Integration->setWindowProperty(newWindow, s_x11AppMenuServiceNamePropertyName, serviceName.toUtf8());
                    m_x11Integration->setWindowProperty(newWindow, s_x11AppMenuObjectPathPropertyName, objectPath.toUtf8());
                }
            }

from https://github.com/helloSystem/QtPlugin into https://github.com/helloSystem/Menu so that it works with the default Qt platform plugins and theme?

In case that is not possible, should we attempt to send a patch to Qt so that it would set the needed atoms? (It would probably help for general acceptance if they were not _KDE "proprietary".)

So, essentially this is a "rediscovery" of

from 3 years ago where @davidedmundson had given a hint at a possible solution which I still haven't fully digested.