keyboard: add KeyboardMap and KeyboardListener

This is a squashed version of #38