This is the home of the shortcut handler binary.
The shortcut handler allows clients to register the keyboard shortcuts they are interested in. If the shortcut manager notices a sequence of keys matching one of the clients' expressed shortcut interests, it notifies the respective client. The client can then execute an action based on the shortcut that was activated.
The clients register through the fuchsia.ui.shortcut/Registry
protocol, by calling Registry.SetView(ViewRef, client_end:Listener)
, providing its ViewRef
and the client end of the fuchsia.ui.shortcut/Listener
protocol by which it will receive shortcut notifications. The ViewRef
is necessary for the shortcut manager to understand where in the view hierarchy this particular client is, and this information together with the focus chain information is used to determine which view should receive the focus. The client then calls fuchsia.ui.shortcut/Registry.RegisterShortcut
as many times as needed to define individual Shortcut
s.
The shortcut manager does not support arbitrary key sequences as key shortcuts. While this choice does not yield the most universal shortcut support, it is adequate for Fuchsia‘s present needs, and will be evolved as Fuchsia’s shortcut supporting needs evolve.
When registering a shortcut key sequence, the Shortcut
API requires the developer to pick a unique 32-bit unsigned integer as a shortcut identifier. This identifier will be sent back via fuchsia.ui.shortcut/Listener.OnShortcut
when the key sequence is recognized. At the moment there is no facility to modify the shortcuts once defined. If clients come about that do require more involved shortcut processing, the shortcut API will need to be evolved too to meet that request.
A shortcut key sequence is specified as a split between a set of required keys, set in Shortcut.required_keys
, and a singular activation key set in Shortcut.key3
. The required keys all need to be armed (actuated) before actuation of the key will have any effect. Once all the required keys are armed, the key must have a state transition as specified in Shortcut.trigger
to activate the shortcut. For example, a shortcut like Ctrl+Shift+A
requires Ctrl
and Shift
to be specified in Shortcut.requried_keys
, and A
to be set in Shortcut.key3
. The shortcut would therefore be triggered when the following happen in succession:
Shift
is pressed and held.Ctrl
is pressed and held.A
is pressed and held.But, for example, the following sequence of events would not trigger a shortcut as defined above:
Shift
is pressed and held.A
is pressed and held.Ctrl
is pressed and held.The shortcut manager can trigger on key actuation or de-actuation today. It stands to reason that there could be more activation events defined in the future.
A possible value for trigger
is either KEY_PRESSED
or KEY_PRESSED_AND_RELEASED
, as defined in fuchsia.ui.shortcut.Trigger
. This may prevent some more exotic activations such as a release after an arbitrary number of actuations (instead of after just one).
At the time of this writing, the shortcut protocol has limitations in what it can support, and the way the API is formulated prevents some shortcuts, such as the “sided” combination of LeftShift+RightShift
from being defined in an economical way. That is, it is not possible to define a single shortcut that will trigger on both Shift
keys held down. Instead, you would need to define two shortcuts, one with LeftShift
in required_keys
and with RightShift
as key
, and another with RightShift
in required_keys
, and with LeftShift
as key
. This duplication is subject to combinatorial explosion for similar “sided” shortcuts. It does not make for an elegant API, and does not mesh well with shortcut definition on other platforms, where there are usually no special trigger keys.
Similarly, the current shortcut manager does not take into account non-US keymaps, possibly leading to confusing handling of “sacred” shortcuts. We consider this an incidental difficulty that will be removed in the future.
Further details of the shortcut API are available in the README.md for fuchsia.ui.shortcut/Shortcut.keys_required
.
The shortcut handler itself reacts to two kinds of notifications:
It is notified of keyboard events, through fuchsia.ui.shortcut/Manager.HandleKey3Event
. Typically it is the input pipeline that calls into this protocol.
It is notified of the change of focus through fuchsia.ui.shortcut/Manager.HandleFocusChange
. This is also typically done by the input pipeline, although at the time of this writing there also exists an unexpected detour via the Ermine shell which should be removed.
For efficiency reasons, the shortcut handler keeps focused_registries
, a list of all shortcut registries that match the currently pertinent focus chain.
This list is invalidated by:
fuchsia.ui.shortcut/Manager.HandleFocusChange
)fuchsia.ui.shortcut/Registry.Register
).It is obvious why (1) invalidates: a whole another set of handlers may now be armed after a focus goes elsewhere. It is not quite so obvious why (2) invalidates too. A client may register a shortcut after the focus chain update has been received. Not recomputing at registration time will break the focused registries invariant, as we'd have a registry with an armed ViewRef
that is not in focused_registries
.