F10 for accessibility in KF6!
F10 for the Main Menu!
We now have a new KStandardShortcut. With https://commits.kde.org/kconfig/782e43f8076e5f4a10111a6b4d2cc6b1741c9798 the F10
key is now assigned to “Open Main Menu”. This is in my opinion a big win for accessibility because up until now for blind people there was no consistent way in our software to open the main menu.
You can see the problem for yourself if you try to get to the menu bar in your favourite KDE application. Notice how you can't get there using the Tab key? You actually need to hold down the Alt
key and then use mnemonics i.e. the underlined letter to jump right there. Now blind people obviously can't see those underlined letters or there might not even be a menu bar in the first place so there actually was no reliable way for them to explore all the actions our software had to offer.
So now we decided (or rather I suggested and everyone seems to agree) to have F10 as the key to open the main menu. Why F10
you ask? Well, mostly because everyone else is already using it: Gnome, Microsoft, Chrome/ium, and Firefox (but Alt
also works here). We don't want users to have to care which toolkit they use when they just want to open the main menu, so F10
was the logical choice.
However, only deciding on a standard shortcut obviously isn't enough. The opening of the main menu also needs to be implemented. My goal was to implement this for many applications for free. The other goal was to not disrupt those applications too much by taking away their F10
key. Unfortunately, a little bit of disruption is still necessary and this blog is here to announce this.
So considering that we have applications that use the menu bar as their main menu and others that use a hamburger menu and others that might have neither of those or some custom main menu, the best I did for now is to implement F10
to open a main menu in KHamburgerMenu
. This is handled as a normal keyboard shortcut that is assigned to KHamburgerMenu
by default and which will open either the menu bar or the hamburger menu depending on what the application currently uses. Even if the application currently has both the main menu and a hamburger menu button completely hidden my implementation makes sure that a menu still opens so no blind person ever has to wonder why nothing happened.
All of this means that after upgrading to KF6, pressing F10
in your KHamburgerMenu
-using application might have a keyboard shortcut conflict. This won't/shouldn't lead to a crash or anything, just to an annoying popup. This can be avoided by assigning one of the conflicting actions to something else either in application code or by the user.
If an application does not use KHamburgerMenu
, there will be no change at all. I would however encourage everyone to make F10
open the main menu for every application. That's typically very easy to implement. QMenuBar
for example has a method for this. But honestly, if we are talking about an application that could be using KHamburgerMenu
, it might be about as much work to implement a very minimal KHamburgerMenu
. In kdenlive they only had to add 20 lines for this: https://invent.kde.org/multimedia/kdenlive/-/commit/cb38d57691cfba311c0e59fd748d88a5b8690ba8 This implementation will allow users to re-assign the keyboard shortcut.
I haven't really checked how to best do this in Kirigami-based applications.
Anyways, with F10
by itself partially dealt with, there is one more F10
related accessibility feature I need to talk about:
Shift+F10 to Open Context Menus!
You see, people who can't use a mouse pointer or other pointing device rely on the keyboard to open context menus. However, many keyboards these days do not have a Menu
key. Therefore there is no way to open context menus by only using a keyboard! Well, at least not in KDE applications. Actually, this is again a situation where everyone else has already decided that context menus should be triggered by Shift+F10
. This is already recommended by the Web Accessibility Initiative, Microsoft, and implemented in Chrome/ium and Firefox. We are, however, behind on this.
So on to the implementation. Skip to the end of this section if you only want to know what I will be doing and how this might affect your application.
How can I make every application also listen for Shift+F10
? It would be really nice if, from one day to the other, all of our software would open context menus on Shift+F10
. This can be accomplished by binding Shift+F10
to the Menu
key which is surprisingly easy to do even as an end user. If you want to have this functionality today, do the following (not sure if it works on Wayland):
Create an
.Xmodmap
file in your home directory (https://linux.die.net/man/1/xmodmap):cd xmodmap -pke > .Xmodmap
This file will be used to re-assign keys or keyboard shortcuts.
Open that file and change the line that looks somewhat like this
keycode 76 = F10 F10 F10 F10 F10 F10 XF86Switch_VT_10
to this
keycode 76 = F10 Menu F10 F10 F10 F10 XF86Switch_VT_10
Replacing this second occurrence of
F10
in this line withMenu
will tell the softwareXmodmap
that from now on, pressing the key with the keycode76
simultaneously withShift
should be translated to aMenu
key press.
Delete this file later if you don't want key re-assignment anymore.
Now obviously this means that no software anywhere will be able to use Shift+F10
for anything. Or rather: It will always be interpreted as a Menu
key, so the Menu
key and Shift+F10
would always do the same.
Honestly, it might be a bit rude to take away Shift+F10
from all software, but I am not sure if this would even be a problem. I kind of doubt that there are many applications that have any crucial functionality on Shift+F10
and do not allow to re-assign this. If this was the only downside to this approach, I might have tried to convince the wider KDE community that this or something similar was the best way forward. However, the thing is that this only solves the problem in situations in which we/Plasma have control over the system. This won't fix any of our software when it is used in a system in which one can't interpret Shift+F10
as Menu
.
A different idea I had, which is a bit more targeted, would have been to instead implement the above as part of the KDE platform. Qt software adapts itself to the platform it runs on, so we have some control there which we can force upon software by implementing a platform plugin (see https://doc.qt.io/qt-6/qpa.html or https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/xcb/qxcbkeyboard.cpp#n903). This would then only affect Qt software instead of affecting the whole system, but once again: This only works as long as our software runs on a platform that we control.
So this needs to be implemented on a non-system layer. Frameworks perhaps? What about interpreting Shift+F10
as Menu
through an EventFilter
on top of the QApplication
?
This works and is portable but I would still take away softwares' autonomy to use Shift+F10
as they please (or at least require them to opt out). It is also not nice for performance reasons because such an EventFilter
will slightly slow down every user interaction with the application.
Okay, let's try to be even more cautious and choose a different implementation. Let's simply override QMainWindow::keyPressEvent()
. Unfortunately this means that only key press events on children of QMainWindow
can be handled. Key presses on secondary windows the application might have won't be within our grasp. However, on the plus side, key presses will only arrive at this method if they hadn't be handled by the application already. So we wouldn't be taking away Shift+F10
from the application! Good news!
So this is what I am going to do: I will override
the QMainWindow::keyPressEvent()
in the KXmlGui framework so that we post our own context menu events whenever a Shift+F10
key press comes in. This works pretty well so far from my testing. It doesn't always work unfortunately because the context menu opening was, in some cases, implemented in a way that expects either right-clicks or Menu
key presses in a hard-coded way. They don't react to QContextMenuEvent
s as they should. So in those cases I might adapt some widgets so they behave nicely.
This will result in applications using the KXmlGui framework reacting to Shift+F10
by opening context menus if the applications don't already handle or use Shift+F10
themselves. If applications really absolutely do not want anything to happen when Shift+F10
is pressed, they can filter these events out beforehand.
Shout-out and Thanks
This work is being supported by the NLnet foundation and the European Commission! The project I am being funded for isn't really specifically about accessibility, but the people at NLnet are so nice and forward-thinking that I am allowed to do a good amount of work on improving accessibility in Dolphin as part of my grant. As is the nature of open source, in this case many KDE applications will benefit from this work.
I also want to mention Fushan Wen here even though he had nothing to do with any of the work mentioned in this blog post simply because he has been doing outstanding work for accessibility in KDE for many month now.