© nemo 1999-2020

DeepKeys is a RISC OS module that augments and improves keyboard handling

The current version is 2.10 (21 Feb 2020) [32bit]

DeepKeys replaces the standard byte-wide keyboard buffer with a word-wide buffer. It also stores keyboard modifiers and physical key numbers with every keypress. Finally, it delivers this meta-information to Wimp tasks through an extension to the standard Wimp Poll KeyPress message, and (new for 2.09!) outside the desktop via an extension to OS_ReadC.

Buffer Codes

Without DeepKeys, the keyboard buffer is made of bytes, so only codes 0-255 can be inserted into the buffer. In a convention dating back to the BBC Micro, codes 128-255 are reserved for function keys, cursor keys, tab etc, so character codes in the range 128-255 are preceded by a zero byte. Therefore character zero is also preceded by a zero byte.

Wimp tasks do not read the keyboard buffer – they receive KeyPress events from Wimp_Poll, which hides the zero byte prefix and remaps character codes. KeyPress codes delivered from the Wimp are in the range 0-255 for characters, and 256-511 for the metakeys.

Now With Less!

DeepKeys allows word-sized codes to be inserted into the keyboard buffer. Until RISC OS 4 the Wimp delivered these codes as KeyPress poll messages without modification. Unfortunately, RO4 truncates keypress codes to a single byte, plus the standard metakeys. It is therefore possible to insert code &181 into the keyboard buffer and the task will receive a KeyPress event for code &181, meaning F1 has been pressed.

In RISC OS 3 it was also possible to insert a code such as &123456, which was delivered to the task unmodified. This is not currently possible in RISC OS 4. This regrettable truncation also affects Wimp_ProcessKey in the same way.

The intention was to allow virtual key codes to be defined, which are not restricted to a particular physical keyboard layout. There can be codes with fixed meaning, such as “Scan”, “Calculator” or “Open new spreadsheet”, or dynamically allocated codes for USB devices such as numeric keypads or MIDI controllers.

Command line programs that read the keyboard through OS_ReadC will receive word-sized results, and should try not to truncate the code to a byte before interpreting it. For example, OS_ReadLine correctly excludes such keypresses as they are NOT characters.


Note that because of the Wimp’s use of codes 256-511, it is NOT possible to treat such codes as Unicode. UTF-8 encoding is recommended for Unicode characters. In a system that did not use the WindowManager, or in some future version that delivered function keys etc as codes outside the Unicode range, it would be possible to insert Unicode directly into the keyboard buffer. DeepKeys places no interpretation on the codes it manages.

Modifiers and Physical Keys

KeyPress messages from the Wimp, and codes read direct from the buffer using the extended RemV API, are accompanied by the keyboard modifiers pressed when the key code was generated, and the physical key number of the last non-modifier pressed. Codes inserted with the extended InsV API specify their own modifiers and physical key number.

This can be used to implement sophisticated hot-key functionality in Wimp tasks, as it is now easy to tell the difference between Return, Enter, Ctrl-M, Alt-1-3, Ctrl-Return, Ctrl-Enter and Ctrl-Shift-Return, even though they all produce the same keypress code. In each case the modifiers and physical key number are different.

Note that one should always choose the default action for a keypress code (having exhausted other possibilities) even if the physical key number seems wrong – the keypress code may have been inserted into the keyboard buffer by a program using the ‘old’ interface, rather than by the keyboard driver, and it will have gained the modifiers and physical key number of the physical keyboard. Programs using the extended interface can specify the intended modifiers and physical key number when inserting keypresses into the keyboard buffer.


DeepKeys completely replaces the kernel’s keyboard buffer handling. If VectorExtend is available, DeepKeys will insert itself into various vectors at an appropriate priority when it is loaded. Otherwise, it must be loaded as early as possible – for this reason it has the official name !!DeepKeys and should be installed in <Boot$ToBeLoaded> (!Boot...Choices.Boot.PreDesk).

Wimp_Poll API

The KeyPress message block returned from Wimp_Poll for event 8 is augmented:

+16   Window handle

+20   Icon number or -1

+24   Keypress code

+28   DeepKeys state:

      b0  Left Shift

      b1  Right Shift

      b2  Left Ctrl

      b3  Right Ctrl

      b4  Left Alt

      b5  Right Alt

      b6  Left Logo (eg Windows key)

      b7  Right Logo

      b8  Menu key

   b9-14  reserved

     b15  0

  b16-31  Low-level key number

The presence of DeepKeys can be detected by setting b15 of block+28 before calling Wimp_Poll – it will be clear on a KeyPress event if DeepKeys is present. As of 2.09 the message length is also increased to 32.


The “insert into buffer” vector gains a flag to allow modifier state and low-level key number to be inserted into the keyboard buffer at the same time as the associated buffer code, which can now be a word.

> R0  keypress to be inserted (a word)

  R1  buffer number and flags:

      b0-29  0

      b30    DeepKeys state in R3, or word-pairs in block mode

      b31    block mode

  R2  pointer if block mode (to key/modifier word-pairs if b30, else bytes)

  R3  DeepKeys state as above if not block mode, otherwise block length

< R0  preserved

  R1  b30 cleared if call supported

  R2  corrupted if b31 was clear, else ptr to first value not inserted

  R3  preserved if b31 was clear, else number of bytes not inserted

   C  set if buffer full

The presence of DeepKeys can be detected by R1b30 being cleared on exit. Note that the DeepKeys implements block mode for the keyboard buffer, which the Kernel does not.


The “examine or remove from buffer” vector is extended to allow the modifiers and low-level key number to be read at the same time as the buffer code.

> R1  buffer number and flags:

      b0-29  0

      b30    return DeepKeys state in R3, or word-pairs in block mode

      b31    block mode (R2 & R3 on entry)

  R2  pointer to block, if b31 (key/modifier word pairs if b30, else bytes)

  R3  bytes in block, if b31

  V   examine, else remove

if b31 clear:

< R0  corrupted (remove) or next value (examine)

  R1  b30 cleared if call supported

  R2  keypress (remove) or corrupted (examine)

  R3  DeepKeys state as above if R1b30 set on entry, else preserved

if b31 set:

buffer is filled with bytes when b30 is clear, or keypress/modifier word-pairs when b30 set

< R0  corrupted

  R1  b30 cleared if call supported

  R2  pointer past entries placed in buffer

  R3  number of bytes left in buffer

The presence of DeepKeys can be detected by R1b30 being cleared on exit.

Block mode (b31 set) without DeepKeys state (b30 clear) is not recommended, as values in the returned block will be truncated to bytes, even if they were words.

RdchV / OS_ReadC API

New for 2.09

A pair of magic values allows the programmer to receive modifier state at the same time as the keypress code when using OS_ReadC or RdchV:

> R0  "DpKy" (&794B7044)

  R1  1<<15

< R0  keypress code as usual (or 27 for Escape)

  R1  DeepKeys modifier state

  C   set if read failed

The presence of DeepKeys can be detected by R1b15 being cleared on exit.