Runtime: Expose trigger for keyboard events

Hello! Apologies for a wall of text right out of the blue but just wanted to make a suggestion to resolve a blocker I’m facing on a plugin I tried to build.

I could build what I describe here myself but I wanted to raise the discussion before starting to make PRs

What
I want to be able to bind keyboard events to plugin actions.

Why
Some workflows are sped up by using hotkeys instead of clicking around for menu options.

Example use case
I want to instantiate a complex, but predefined group of shapes whereever the users mouse is pointing.

Blockers to the above

  1. I can only create objects in response to the plugin loading, or interacting in the plugin modal, and (possibly, I haven’t tested yet) interacting with a shape on the viewport.

Given all of these require clicking somewhere else, I can’t use the current mouse position for placement.

I can register key events inside the UI modal itself but as this is an iframe it obviously only captures events happening inside the iframe context.

  1. Any of these only work if the plugin is actively running somewhere already. I may raise some separate feature suggestions for improving the use of plugins that may need to be always on instead of requiring users to reopen the plugin panels every time they reopen the document

Note*
I’m aware my use case also requires exposing information that is to my knowledge also not yet exposed, ie pointer position. I would suggest that there also needs to be an exposed property on the Viewport to access Pointer position in viewport space. I can raise this as a separate discussion if needed, but given the inability to run a plugin logic without mouse interaction, it would be useless to implement on its own.

Proposal

  • Add a new EventMaps type of keyboard or hotkey
  • Expose this to the penpot.on() to allow triggering actions based on user key events
  • Expose a new property on the viewport currentPointerPosition, or a method getCurrentPointerPosition if we don’t want the overhead of constant updates. †

Concerns
There could be a privacy and security concern with allowing unfettered keyboard reading inside the penpot window. (Given the context is still inside a design tool; I’m not sure what would be gained by reading peoples inputs, but, I digress) this could be mitigated by further adding:

  • manifest.permissions: [‘events:read-keyboard’]

if this is still not suitable then I’d recommend a new manifest entry exposing known keybinds to the plugin. eg;

  • manifest.keybinds: [ {key: ‘n’, ctrl: true } ]

This would require more discussion and thought as we then have to solve for keybind conflicts between PenPot itself, and other plugins. I have ideas on how this could be managed but perhaps that is a later discussion if there is interest.

† viewport pointer location also needs to factor in canvas offsets, zoom levels, and size of sidepanels depending on how the viewport renderer currently tracks its info. Given the shapes can be drawn in a precise location and click events work to select them, this logic likely already exists.