With Plasma 5.8 LTS out the door it’s time to look ahead at future Plasma releases. In our first long term support release we introduced “modifier only shortcuts” that allow you to open the application launcher with just the Meta key. Judging from feedback on the Internet this is one of the best features introduced in all of KDE’s history ;) I was quite surprised to find that the global menu is a close second.
Global Menu in Qt 5.7
Since Qt 5.7, thanks to Dmitry Shachnev, QGenericUnixTheme out of the box supports exporting a QMenuBar over DBus and registering it to the com.canonical.AppMenu.Registrar. When I updated to said version I was disappointed that it didn’t “just work”. The reason being that Plasma ships its own Qt Platform Theme that is responsible for enforcing Plasma look and feel settings on Qt applications as well as providing the file dialog. We do this by inheriting from QPlatformTheme which isn’t the aforementioned unix theme, which is private. Since the Plasma-Integration repository is bound to a specific Qt version already anyway, I now use private Qt imports to get hold of the unix theme so we don’t need to re-implement all of that logic, which was the reason I waited for Qt 5.7 for all of this.
What about Wayland?
The global menu infrastructure works by having an application notify a registrar service that it has a menu bar on a certain window accessible on a certain DBus service:
com.canonical.AppMenu.Registrar /com/canonical/AppMenu/Registrar com.canonical.AppMenu.Registrar.RegisterWindow WinId /MenuBar/123
Those of you familar with Wayland might notice that it uses global window IDs, which don’t exist in a Wayland world. That means, no global menu on Wayland, I thought, not without significant re-engineering effort.
Martin Gräßlin then came up with the brilliant idea of writing the DBus service name (it’s omitted in the above call since the registar knows who is calling) and object path onto the windows as properties. This way we don’t need to deal with any window IDs and can even omit the registrar! All we need to do is query the active window for those properties:
_KDE_NET_WM_APPMENU_OBJECT_PATH(STRING) = "/MenuBar/123" _KDE_NET_WM_APPMENU_SERVICE_NAME(STRING) = ":1.1337"
On Wayland we then make use of Qt’s Extended Surface protocol which allows you to set arbitrary properties on a window. To my surprise kwin_wayland was engineered in such a way that it works with X clients going through Xwayland with no further adjustment needed!
When we return a new QDBusMenuBar from our platform theme, we then write the properties on the window the menu bar is attached to. This required some changes to Qt code so it actually tells us the window. Unfortunately, we now have to ship a copy of QDBusMenuBar – still better than duplicating everything. I’ve also seen a ticket on Qt’s bug tracker about providing public better access to Qt’s DBus menu implementation. We currently also ship our own system tray implementation for the same reason (and because ours is older but we’d love to get rid of it).
What about non-Qt applications?
As you could probably tell by the Registrar service name, this stuff wasn’t invented by us. In theory, any application could export its menu through DBus and both Chrome and Firefox do exactly that. I’ve also seen LibreOffice do it at some point but I couldn’t get it to work and neither could I with Gimp and Inkscape.
They won’t work with this new approach anyway, right? We kept the Registrar but all it now does is write the DBus service name and object path on the window with the ID in the RegisterWindow call. This way we don’t need any special-casing in KWin, even. Unfortunately, this won’t work on Wayland then.
What’s up next?
The last bit in this feature frenzy is the application menu KRunner plugin, aka “Unity HUD”. It allows you to search through a potentially complex menu structure of an application using KRunner. Back in Plasma 4 I stopped remembering shortcuts just used it to find all actions I needed.
One issue I came across is that for the application menu runner to work, an application would need to export its menu. However, non-KDE applications like VLC player and Firefox hide their menu bars in this case. This means you cannot really use the application menu runner when you don’t want a global menu or window decoration menu button. I don’t know how to proceed here…
My initial plan was to have three options in Applicaton Behavior settings, Menu “in application” (the default with no global menu service running), “window decoration button” and “in a widget”. Theoretically you could use the window decoration and global menu applet simultaneously, though.
Another obstacle is keyboard activation. When you press Alt+F it would open the “File” menu. With global menu or decoration button I found no way of implementing this. There’s a “request activaton” signal but I never saw anybody actually emit it. What I could perhaps do is add another “modifier only shortcut” when just pressing Alt which then passes focus to and/or opens the menu. Do you know how Unity handles this?
If you like what you saw and want to help make this happen, especially if you have answers to my above questions, be sure to ping me in #plasma on Freenode IRC!