DeepKeys

© nemo 1999-2018

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

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.

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.

Unicode

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.

Installation

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

InsV API

The “insert into buffer” vector gains a flag to allow modifier state and internal 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    Extra information in R3
  R3  DeepKeys state as block+28 above

< R0  preserved
  R1  b30 cleared if call supported
  R2  corrupted
  R3  preserved
   C  set if buffer full

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

RemV API

The “examine or remove from buffer” vector is extended to allow the modifiers and internal 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
  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.