Shortcut configuration in 2020
Last year I spent some time working one the (formerly global) shortcuts settings module, including rewriting it from scratch. Given that Plasma 5.21 is to be released soon, I though it was a good opportunity to do a write up of what has happened in this area in the past year. I want to apologize in advance for the size of this blog post that turned out longer than I expected.
What was wrong with the old one?
The old module consisted of a list on the left listing all applications and system services that had registered shortcuts. The main portion of the view was filled by the area used to edit the key combinations to trigger the various actions. This editor was the same component that is used by our applications to configure shortcuts inside them. Normally reusing code and components is a good thing but in this case the two main issues, that the module had, stemmed from the fact that it just displayed different shortcut editors depending on which application was selected on the left list:
- As the search bar was actually part of the different shortcut editors, it was not possible to search through all shortcuts at once. If you searched for a particular action or wanted to find out which one used a particular key combination you had to go through every application and system service which is cumbersome and annoying.
- It only listed up to two default and two custom key combinations. Also it was only possible to have two of those active at once and selecting a default one would clear the custom one. On the other hand, some services like KRunner had more than two key combinations by default which means it was impossible to configure all of them.
Considering that the bulk of the user interface needed to be rewritten anyways, I decided to do a total rewrite of the settings module and separate it in a QML user interface backed by C++ code that contains the logic and manages the data that is displayed. This approach is now commonly used in Plasma and the benefits of it can be seen in the next section.
The actual user interface is similar to the old one. On the left all applications and system services with global shortcuts are listed and in the centre the configuration is happening. The user interface of this part has been totally redone. After selecting an entry in the left list, the items corresponding to actions of that entry are initially all collapsed displaying the name of the action and all currently active key combinations for that action. After expanding such an item it is now possible to toggle the state of each default key combination and add as many custom ones as one likes. Using the search bar on the top now filters all entries and searching for names or key combinations is possible.
This rewrite was the biggest change to the shortcuts module included here and was released with Plasma 5.19, the second Plasma release of 2020. During this process a bunch of services lumped together under the name “KDE Daemon” have been split into separate entries with appropriate icons. This should also make finding the thing you are looking for even easier.
Integrating Standard Shortcuts
An issue that came up frequently was the split between global shortcuts and standard shortcuts, what resided where and the lack of
consistency between both configuration interfaces. Because of the aforementioned split between frontend and backend, integrating the standard shortcuts into the global
shortcuts module and creating a combined shortcuts module was straightforward. The hardest part was adapting
KConcatenateRowsProxyModel
for merging
the two data models of global and standard shortcuts. KConcatenateRowsProxyModel
only allows appending flat models like a list or table but
the shortcut data was represented as a two level tree. As you can see
practically no changes to the user interface in the package/contents/ui
folder were required.
Plasma 5.20 was the first released that included the combined shortcuts settings module and in addition to merging both modules,
every standard shortcut has been categorized to make it easier to find a specific one.
Custom Conflict tracking
Another feature
that landed in Plasma 5.20 was that the settings module checks now for conflicts itself. Normally the component that records the
key combinations also checks after the recording has finished if the entered key combination is not already in use. This allows applications to
include such a control easily without everything having to implement the various checks and dialogs. The checks are made against the currently
active shortcut configuration which is of course correct. However this can be annoying while doing more extensive configuration changes than
changing a single shortcut before clicking the Apply
button.
Imagine the following scenario: a user doesn’t like that Dolphin opens when pressing Meta+E
and would rather like to use Print
which is the
default shortcut of Spectacle. As a first step the user goes to the action of Dolphin, disables the default shortcut and enters Print
, a dialog
opens and warns them that the key is already used by another shortcut and they accept it since they want to change what the key does. Now the user
realizes that they have no shortcut for opening Spectacle anymore but they can easily assign the freed Meta+E
combination. However when entering
this combination another prompts pops up warning that Meta+E
is already in use although it was explicitly disabled by the user.
The above example highlights that the conflict detection in the settings module should not check against the configuration that is currently active
but rather use the current state of the settings window as it expresses the intent of the user what the resulting configuration should be. This means
that in the example the first dialog would be still displayed because Spectacle still has shortcut when the user tries to assign the key to Dolphin but
the second warning is not shown since in the resulting configuration Meta+E
would not be taken already.
Highlighting changed settings
A new feature that we started moving towards Plasma 5.20 and is implemented for almost every settings module in Plasma 5.21 is highlighting non default setting when the corresponding button in the sidebar of System Settings is pressed. For Plasma 5.21 I also added this facility to the shortcuts module. In addition to indicating a non default state of the module in the sidebar of system settings, the individual application entries show the same indicator as do the items that represent the various actions of an application. Once expanded, unchecked default shortcut and added custom shortcuts are highlighted.
Recording key sequences
When rewriting the user interface to use QML instead of Widgets, the control used to record the key presses when entering a new shortcuts has been changed as well
(even if it may look the same). KDE has a control for recording key sequences for both Qt Widgets and QML in
KKeySequenceWidget
and
KeySequenceItem
shipped as part of the KXmlGui and KDeclarative frameworks respectively. The former is the older one of them and the latter used to contain a copy of the recording
logic of it. However switching the settings page to KeySequenceItem
uncovered some bugs subtle differences between the two. Even though
all
of
the
bugs
were
fixed
, this showed that maintaining both copies and having to sync changes between them was not a good way forward.
On Wayland there was a serious flaw present in both classes. It was not possible to capture a key sequence that was an active global shortcut because doing so would
trigger it. On X the application could just grab the keyboard but this is not possible on Wayland since all inputs always go through the compositor. There exists a
wayland protocol
for this use case to request the compositor to disable shortcuts. KWin already supported the server side of this protocol but we had no client side implementation of
the protocol in our libraries. Instead of having to add this in two places I took the opportunity to deduplicate the recording code. For this I added a new class called
KeySequenceRecorder
to the KGuiAddons framework which is a common dependency of both
KXmlGui and KDeclarative. This class is a non visual component that listens to key presses happening in a window, records a key sequence from that and also handles the
inhibition of shortcuts while the recording is happening. Afterwards I ported both controls (here
and here) to use the new class internally and as a result only having one place where the recording code lives instead of two.
Future work
I think currently the settings module is in a good shape and I don’t expect the need for a huge amount of work there in the near future. Another area I could imagine exploring is the idea to align the layout and visuals of the shortcuts dialog used in applications with the one of the new settings module because it shares the issue of displaying and configuring a maximum of two key combinations and for consistency reasons.