sil2100//vx developer log

Welcome to my personal web page

Status update. LP API, release process and Qt5 QPA shortcuts

Things are very busy as always - not having enough time to write a full-content article I decided to at least post a quick update on what I'm working on currently. Most of it is of course Ubuntu related: besides preparations for the next Ubuntu Touch update (OTA-7) and dealing with the finalization of the previous one (OTA-6), I'm also working on two Ubuntu User articles and, additionally, working my way to becoming an Ubuntu Core Developer. I'm also investigating a bug related to Qt5 QPlatformTheme keyboard shortcut handling.

2015-08-31 15:01

Empty

First of all: I'm currently working on two new articles for the Ubuntu User magazine in my free time - one about the Ubuntu Touch release process, second regarding the programming basics of the Launchpad API and its Python bindings. The first version of the former is almost ready but will probably still go through multiple iterations before it's done. It's roughly based on the presentation I gave on DWO2015 conference a while ago. If all goes well both of them should be available in the winter issue.

Besides that, my work as the release manager for Ubuntu Touch continues. There have been many changes in both our tools and processes lately, many improvements but also many new difficulties showing up. The next update's (OTA-7) focus will be convergence - which brings new challanges to our existing platform models. So there's much going on. Not to mention the after-work additional projects, one being a web-based work management tool which we wrote. I was mainly responsible for the JavaScript (jQuery), HTML and OData parts - but also had to deal with some C# in-between. That was certainly something new as I never had much experience in Microsoft technologies.

But now something more interesting for developers now. I'm also working on an appmenu-qt5 bug reported a while ago (LP: #1380702) which in fact has actually been around from the very beginning. It seems that Qt5 applications in Ubuntu have broken keyboard shortcuts for all their menu entries. That's really bad! I tried looking into why that's happening, since appmenu-qt5 is a really simple, thin layer between the app and the system. So in theory it shouldn't actually meddle in things like application shortcuts.

What I found out is: Qt5, whenever it detects that we're providing a QPlatformMenuBar from the QPA platformtheme, hides the source QMenuBar - which makes perfect sense when you think about it. As a quick reminder: a QPlatformMenuBar is a class that you can define and use in Qt5 if your system implements menus or menu bars in any other way than the default one. This happens for Ubuntu and MacOS for instance, as both have global menus at the top of the screen by default. Anyway, the point is that in Qt every widget that is hidden does not get any keyboard shortcuts working. So it made sense why it never worked from the start. Even the Qt5 documentation mentions this:

(...) Warning: You should not normally need to use this function since Qt's shortcut system enables/disables shortcuts automatically as widgets become hidden/visible and gain or lose focus.

Qt5 documentation for QWidget::setShortcutEnabled

But then I started wondering... if that's the case, why no one complained that keyboard shortcuts were not working for MacOS?
I first dived into the cocoa platformtheme plugin source looking for answers but found nothing. There was no code that could have made it work. So I started actually looking into the documentation and later, as the documentation had no implementation details, the Qt5 shortcut code itself. Most Qt5 shortcut handling is done by the QShortcut and QShortcutMap objects. To understand the situation better I had to understand where and how Qt5 actually disables the shortcuts whenever a widget is hidden. When I found the actual code it also became perfectly clear why it worked for the cocoa platformtheme:


 static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window)
 {
     bool visible = w->isVisible();
 #ifdef Q_OS_MAC
     if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
         visible = true;
 #endif

     if (!visible || !w->isEnabled())
         return false;

 // (...)

The correctWidgetContext() function is something that is called by the qWidgetShortcutContextMatcher() function on every addition of a new QShortcut to a QShortcutMap. If it evaluates to false, the shortcut is not considered. And, as we can see, it's hard-coded with an #ifdef to work for the MacOS case, which is really really bad design. I suppose it's a leftover from the Qt4 times before the introduction of QPA, but still... Didn't expect that.
My solution which I'm preparing for upstream proposal right now is to actually get it working the right way - so giving the power to decide whether it should override the visibility parameter or not to the platformtheme itself. It's a relatively small and safe change too. Let's see how it goes.

But I must say I'm enjoying working on Qt5 and appmenu-qt5 from time to time again now. That's the C++ fun I've been missing for a while now.