tree: 7d1259289ddb8e5afa239616a079c78d719be162 [path history] [tgz]
  1. config/
  2. meta/
  3. src/
  4. tests/

Shortcut handler

This is the home of the shortcut handler binary.

Usage notes

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.

Shortcut registration

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 Shortcuts.

Supported shortcuts

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.

More information

Further details of the shortcut API are available in the for fuchsia.ui.shortcut/Shortcut.keys_required.

Implementation notes

External notifications

The shortcut handler itself reacts to two kinds of notifications:

  1. It is notified of keyboard events, through fuchsia.ui.shortcut/Manager.HandleKey3Event. Typically it is the input pipeline that calls into this protocol.

  2. 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.

Correct handling of registration events and focus changes

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:

  1. A focus chain change (someone calls fuchsia.ui.shortcut/Manager.HandleFocusChange)
  2. A registration of a new shortcut client (someone calls 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.