[RFC] saving and loading of global shortcuts

Andreas Hartmetz ahartmetz at gmail.com
Wed Jun 27 20:26:11 BST 2007


Hello list,

There is a design issue with KGlobalAccel which has no obvious "perfect" 
solution so I am asking for your input. A quick outline of the global 
shortcuts infrastructure in my local working branch:

[Basic functionality]
- You call KAction::setGlobalShortcut() to set a shortcut for an action. 
KAction then calls KGlobalAccel which is, among other things, the interface 
to KdedGlobalAccel (communication via DBus). KdedGlobalAccel is a KDED module 
as you might have guessed.
- KdedGlobalAccel then grabs the shortcut key in a platform-specific way and 
makes an entry of the mapping key<->action where actions are identified by 
their main component name and their own name.
- When a key grab triggers, KdedGlobalAccel calls (via DBus) KGlobalAccel 
which tells the action to trigger.

[Conflict resolution]
KdedGlobalAccel has a list of all global shortcuts. If you try to assign a key 
twice, it will tell the appropriate KdedGlobalAccel/KGlobalAccel that the 
corresponding shortcut was changed to an empty one, which goes back to the 
KAction.
When manually assigning shortcuts, the config widget asks 
KGlobalAccel/KdedGlobalAccel for conflicts and presents options to the user 
to fix them.
To prevent all clashes as good as possible, KdedGlobalAccel remembers key<-> 
action mappings even after the corresponding application shuts down.

[The issues]
The problem, now, is about KGlobalAccel::readSettings() and writeSettings(). 
They tell KdedGlobalAccel to save/load the mapping of the calling 
applications's shortcuts to/from a global config file. If an application A 
which had some shortcuts changed by the user or automatically, to avoid 
clashes, loads without callling readSettings(), it might snatch some 
shortcuts that were reassigned and "belong" to application B. Same thing if 
the changes (to resolve conflicts) were never saved to disk. They will be 
gone after a restart of KDED.
Properly saving and loading global shortcuts, therefore, is pretty much 
mandatory.

Ossi came up with an ugly but pragmatic solution [my attempts were all a bit 
lacking in the reliability department] which I fleshed out a bit:
Force applications and KParts (<-research needed...) to tell KGlobalAccel when 
they are done assigning their global shortcuts by calling doneSetup(), 
commit() or whatever, and at that point:
- change shortcuts to their saved values, if any
- save any changes that were made automatically to avoid conflicts
- Actually enable the shortcuts (the "force applications..." part)
Any further changes to shortcuts (they are quite rare) would then be saved to 
disk immediately or with some seconds latency to keep the in-memory and the 
on-disk state of KdedGlobal shortcuts in sync at all times.
What's so ugly about this is, of course, an incompatible API change and the 
general ugliness of KAction::setGlobalShortcut() not being enough to actually 
get a working global shortcut. What's good is that it works reliably.
Of course shortcuts could be saved to disk at every change and loaded as soon 
as an action is created and has a name to refer to, at some cost in 
performance - and IMO it wouldn'd be any less ugly.

ATM about all applications seem to set their global shortcuts in one single 
function where it's rather trivial to put a single doneSetup() call at the 
end.

I am asking for any better ideas or other people who are also convinced that 
this is ugly but necessary.

If you wonder how this was done in KDE 3, the answer is "not". There was no 
working conflict resolution for global shortcuts. On the plus side, it had 
working global *multikey* shortcuts (like Ctrl+A,B) which have a code 
size/usefulness ratio that makes them unattractive, especially because some 
code involved in this [KShortcutMenu or KActionMenu or whatever] was dropped 
between KDE 3 and 4. 
Additional code size would be ~1000 lines with a tricky hack or two, which I 
have no intention to write.

Cheers,
Andreas




More information about the kde-core-devel mailing list