# keyman-touch-layout

Documentation at https://github.com/keymanapp/keyman/tree/master/common/schemas/keyman-touch-layout/README.md

* Primary version:
  * https://github.com/keymanapp/keyman/tree/master/common/schemas/keyman-touch-layout
* Deployed to:
  * https://github.com/keymanapp/api.keyman.com/tree/master/schemas/keyman-touch-layout

# .keyman-touch-layout File Format

The source format for a .keyman-touch-layout is JSON, encoded in UTF-8 without a BOM.

A .keyman-touch-layout file must contain a single top-level object, the [`root` object](#root-object).

The general structure of a .keyman-touch-layout file is:

```
{
  "platform": {
    // platform properties
    "layer": [ {
      // multiple layers in each platform
      // layer properties here
      "row": [ {
        // multiple rows in a layer
        // row properties here
        "key": [ {
          // multiple keys in a row
          // key properties here
          "sk": [ {
            // optional multiple longpress keys under a key;
            // longpress properties here
           }, ...]
        }, ... ]
      }, ... ]
    }, ... ]
  }, ...
}
```

## `root` object

The `root` object may contain up to three properties, each being a [`platform`
object](#platform-object), named `"phone"`, `"tablet"` or `"desktop"`. There
must be at least one property.

## `platform` object

The `platform` object describes the keyboard arrangement for a given platform.
Currently, this format supports three generic 'platforms':, `"phone"`,
`"tablet"` and `"desktop"`. The `"phone"` and `"tablet"` platforms are
heuristically selected based on the dimensions of the screen.

The `"desktop"` platform is not currently used by Keyman Engine for Web but may
be used in future releases, for example if we start to support touch screens on
Windows. This does not need to match a hardware layout -- it is still a
touchscreen layout description, not an on screen virtual keyboard.

**Future enhancement:** We may wish to allow for more specific layout
constraints, for example, specific device widths. To support these, we may add
extra properties to the `root` object, such as `"touch-8cm"` which would match
any touch device up to 8cm wide (unless there was another, smaller breakpoint
platform width in the same file). This would also allow keyboard designers to
specify separate landscape and portrait layouts.

The `platform` object must contain one `layer` property, and may
optionally contain three additional properties: `font`, `fontsize`, and
`displayUnderlying`.

* `layer`
: A non-empty array of [`layer` objects](#layer-object). Required.

* `font`
: An optional CSS-style font-family specification, being the name of the font to
  display on the key caps. If omitted, uses the system default UI font.

* `fontsize`
: An optional font scaling, specified in `em`s, such as `'1em'`. Default
  `'1em'`.

* `displayUnderlying`

: A boolean value, if `true`, then the base layout's key cap will be displayed
  in the top left of the key cap. Defaults to `false`.

* `defaultHint`

: A string value. Default is `"dot"`.  Controls the display of the hint text on
  the key cap, which is shown at the top right of the key cap.

  * `"none"`: show no hint on the key cap.
  * `"dot"`: show a dot on top-right of key cap if a longpress menu is
    available, default. Matches behavior for Keyman 15.0 and earlier.
  * `"longpress"`: show the default longpress key cap, if it exists.
  * `"multitap"`: show the first multitap key cap, if it exists.
  * `"flick"`: show the first flick key cap, selected in clockwise order,
    starting from North.
  * `"flick-n"`: show the key cap from the North flick, if it exists.
  * `"flick-ne"`: show the key cap from the North-East flick, if it exists.
  * `"flick-e"`: show the key cap from the East flick, if it exists.
  * `"flick-se"`: show the key cap from the South-East flick, if it exists.
  * `"flick-s"`: show the key cap from the South flick, if it exists.
  * `"flick-sw"`: show the key cap from the South-West flick, if it exists.
  * `"flick-w"`: show the key cap from the West flick, if it exists.
  * `"flick-nw"`: show the key cap from the North-West flick, if it exists.

  Introduced in Keyman 16.0.

## `layer` object

The `layer` object describes one visible layer on a touch keyboard. It has two
required properties: `id` and `row`.

The `id` for a layer object may correspond to a hardware modifier key. These
affect the modifiers in any key events generated by keys on the layer.

* `id`

: the string identifier of the layer. Required. This should use alphanumeric,
  hyphen, and underscore characters only. There are a number of reserved
  identifiers. The following identifiers are recommended for use:

   id          | Modifier        | Notes
  -------------|-----------------|----------------
  `"default"`  | -               |
  `"shift"`    | Shift           |
  `"numeric"`  | -               |
  `"symbol'"`  | -               |
  `"currency"` | -               |
  `"caps"`     | Caps Lock       | Accessed by double-tapping Shift key, 15.0+

  These additional identifiers are also reserved but used mostly for
  compatibility with desktop:

   id                          | Modifier
  -----------------------------|-----------------
  `"ctrl"`                     | either Ctrl
  `"alt"`                      | either Alt
  `"shift-ctrl"`               | Shift + Ctrl
  `"shift-alt"`                | Shift + Alt
  `"ctrl-alt"`                 | Ctrl + Alt
  `"shift-ctrl-alt"`           | Shift + Ctrl + Alt
  `"leftctrl"`                 | Left Ctrl
  `"rightctrl"`                | Right Ctrl
  `"leftalt"`                  | Left Alt
  `"leftctrl-leftalt"`         | Left Ctrl + Left Alt
  `"rightalt"`                 | Right Alt
  `"rightctrl-rightalt"`       | Right Ctrl + Right Alt
  `"leftctrl-shift"`           | Shift + Left Ctrl
  `"rightctrl-shift"`          | Shift + Right Ctrl
  `"leftalt-shift"`            | Shift + Left Alt
  `"rightalt-shift"`           | Shift + Right Alt
  `"leftctrl-leftalt-shift"`   | Shift + Left Ctrl + Left Alt
  `"rightctrl-rightalt-shift"` | Shift + Right Ctrl + Right Alt

  These legacy identifiers are reserved but deprecated:

   id              | Modifier
  -----------------|--------------------
  `"ctrlalt"`      | Ctrl + Alt
  `"ctrlshift"`    | Ctrl + Shift
  `"altshift"`     | Alt + Shift
  `"ctrlaltshift"` | Ctrl + Alt + Shift

* `row`

: A non-empty array of [`row` objects](#row-object). Required.

## `row` object

Describes a single row of keys on a touch layout layer. It has two required
properties: `id` and `key`.

* `id`

: An non-negative integer denoting where the row appears, with `0` being the top
  row. Required.

  Legacy: this value was sometimes an integer in a string. This string format is
  deprecated and will not be supported in future versions of Keyman Developer.

* `key`

: A non-empty array of [`key` objects](#key-object). Required.

## `key` object

Describes a single key on a touch layout row. See also [`sk`
object](#sk-object). A `key` object must include either an `id` or `sp` property.

* `id`

: A string identifier for the key. Must conform to the Keyman virtual key
  format. This must be one of the following:

  `K_xxxx` codes
  :   These are used for a standard Keyman Desktop key name, e.g. `K_W`,
      `K_ENTER`. You cannot make up your own `K_xxxx` names. Many of the
      `K_` ids have overloaded output behaviour, for instance, if no rule
      is matched for `K_W`, Keyman will output `w` when the key is pressed
      or touched. The standard key names are in the
      [Keyman Developer Language Reference](https://help.keyman.com/developer/language/guide/virtual-keys#common-virtual-key-codes).
      Typically, you would use only the "common" virtual key codes.

  `T_xxxx` codes
  :   These are used for any user defined names, e.g. `T_SCHWA`. If you
      wanted to use it, `T_ENTER` would also be valid. If no rule matches
      it, the key will have no output behaviour.

  `U_####[_....]` codes
  :   These are used as a shortcut for a key that will output a string of Unicode
      values, if no rule matches the key. (In Keyman 14 and earlier, only a single
      Unicode value was permitted.) This is similar to the overloaded behaviour
      for `K_` ids. Thus `####` must be valid Unicode codepoint values, in the
      range `0020-10FFFF`, with sequences separated by `_`. E.g. `U_0259` would
      generate a schwa if no rule matches. It is still valid to have a rule such
      as `+ [U_0259] > ...`. These codes are only valid for touch layouts.
      **Note**: For characters outside the BMP, use Unicode codepoints, not
      surrogate pairs (e.g. use `U_10000`, never `U_D800_DC00`).

  A key without an identifier can never generate any output. This may be the case
  for spacers or blank keys.

* `text`

: String. The string displayed on the key cap.

* `hint`

: String. If present, a small hint, often shown at top right of key cap.

  Introduced in Keyman 16.0.


* `layer`

: String. If specified, overrides the modifier associated with the layer (this
  property would be better named `modifierOverride`). It must match one of the
  reserved modifier-type layer identifiers listed above.

* `nextlayer`

: String. If present, when this key is tapped, switches to the specified layer
  after the key event is processed. This is commonly used for layer switch keys
  but may also be used for any key. See also
  [&layer](https://help.keyman.com/developer/language/reference/layer).

* `fontsize`

: String. Applies an override to the font size for the key. Note that Keyman
  will automatically scale the text to fit on the key. If present, this should
  be specified in `em` units.

* `font`

: String. Applies an override to the specified font family for the key. Note
  that as of version 15.0, this is not consistently supported, as it is not
  possible to specify more than one font to be deployed and loaded with a given
  on screen touch keyboard.

* `dk`

: String. If present, with the value `"1"`, specifies that the key is a deadkey.

  Deprecated. Use `"sp": 8` instead. Will be removed in a future version of
  Keyman Developer.

* `sp`

: Integer. Defines special key types. The following values are supported:

  `0` (default)
  : A normal key

  `1`
  : A modifier key or a "frame" key

  `2`
  : A modifier key which is marked as selected (usually with a different
    background color, such as a Shift key on the shift layer).

  `8`
  : A deadkey. Does not change the behavior of the key, but highlights the key
    in a slightly different style.  This is mostly used with desktop keyboards
    which have deadkeys translated to touch.

  `9`
  : A blank key. Indicates that the key has no key cap.

  `10`
  : A spacer. Does not draw a key cap but leaves a space equal to the width of
    the key.

  Legacy: this value was sometimes an integer in a string. This string format is
  deprecated and will not be supported in future versions of Keyman Developer.

* `pad`

: Number. Defines the width of a gap to the left of the key, often used for
  example on the left hand side of the keyboard. Defaults to `5`. The same
  layout behavior may be achieved by using 'spacer' keys. The value is a
  percentage of the standard key width.

* `width`

: Number. Defines the width of the key, default of `100`, as a percentage of the
  standard key width. The standard key width is calculated by scaling the widest
  row on the layer to the width of the keyboard area, and the resulting standard
  key width applies to all keys on the layer.

  Legacy: this value was sometimes an number in a string. This string format is
  deprecated and will not be supported in future versions of Keyman Developer.

* `sk`

: If present, defines an array of keys presented when longpressing on the key,
  an array of [`sk` objects](#sk-object). Longpress should not generally be used
  on Spacebar and it is recommend to avoid using them on modifier keys and other
  special keys.

* `flick`

: If present, defines additional keys that may be selected when using a
  flick gesture on the key, with a [`flick` object](#flick-object). Flicks
  should not be used on modifier keys, special keys, or the Spacebar.

  Introduced in Keyman 16.0.

* `multitap`

: If present, defines an array of keys that may be selected sequentially when
  tapping multiple times on the key, an array of [`sk` objects](#sk-object).
  Multitaps may not be used on layer switch keys, special keys such as the globe key, or the
  Spacebar. Beware of mixing multitaps with layer switching, as this can lead to
  a confusing user experience.

  Keyman 15+: the Shift key has a predefined multitap sequence to access the
  `caps` layer, which is available if the `caps` layer is present. This is the
  only multitap sequence supported in Keyman 15. This multitap sequence cannot
  be overridden, and is the sole case where multitap input may cause a layer switch.

  Introduced in Keyman 16.0.

## `sk` object

The `sk` object defines a key on a longpress menu. It has a subset of the
properties on the `key` object. All properties on the `key` object are
available, except for `sk`, `flick`, and `multitap`. However, the following
properties are not fully supported as of Keyman 15: `font`, `fontsize`, `pad`,
and `width`.

* `id`

: String. Required. An identifier for the longpress key. See `key` object for
  details.

* `text`

: String. The string displayed on the longpress key cap.

* `layer`

: String. If specified, overrides the modifier associated with the layer (this
  property would be better named `modifierOverride`). It must match one of the
  reserved modifier-type layer identifiers listed above.

* `nextlayer`

: String. If present, when this longpress key is tapped, switches to the
  specified layer after the key event is processed. This is commonly used for
  layer switch keys but may also be used for any longpress key. See also
  [&layer](https://help.keyman.com/developer/language/reference/layer).

* `fontsize`

: String. Not currently supported for longpress keys. See `key` object for
  details.

* `font`

: String. Not currently supported for longpress keys. See `key` object for
  details.

* `dk`

: String. See `key` object for details.

* `sp`

: Integer. Defines special key types. See `key` object for details.

* `pad`

: Number. Defines the width of a gap to the left of the key. Not currently
  supported for longpress keys. See `key` object for details.

* `width`

: Number. Defines the width of the key. Not currently supported for longpress
  keys. See `key` object for details.

* `default`

: Boolean. Defaults to `false`. If true, this will be the default key when the
  user longpresses the base key without moving their finger. Only one subkey
  should be default; if multiple subkeys have the default field set, then
  behaviour is undefined.  Given that cancel is not the preferred default
  action for a longpress, the user can cancel the longpress default by
  sliding outside the 'acceptance' area -- e.g. south of the key cap,
  which would then unhighlight the default and indicate visually that
  no output would occur when they release their finger.

## `flick` object

A object with a set of properties that define flick keys for given directions.
There may be up to eight properties, with the following reserved names. It is
not recommended to use more than 4 directions on one key, as it can be difficult
to select the correct flick if there are too many options.

The following properties may be used, corresponding with a given direction from
the center of the key. Each property must reference an [`sk` object](#sk-object):

Property Name | Direction
--------------|-----------
`n`           | North
`s`           | South
`e`           | East
`w`           | West
`ne`          | North-East
`nw`          | North-West
`se`          | South-East
`sw`          | South-West

The flick direction starts at the center of the key, and continues in the direction
shown in this diagram:

```text
nw       n       ne
  \      |      /
     ---------
    |         |
    |         |
w - |         | - e
    |         |
    |         |
     ---------
  /      |      \
sw       s       se
```

# Compiling .keyman-touch-layout files

As of Keyman 15.0, the compiler embeds the .keyman-touch-layout file, into the
output .js file, and transforms any legacy formats (such as "number in a
string") into the appropriate spec format.

# .keyman-touch-layout version history

## 2026-03-26 2.1.2 stable
* Add missing 'default' property for longpress (sk) keys to clean spec. No other
  changes.

## 2024-02-23 2.1.1 stable
* Loosen `layer.id` requirements to any non-whitespace characters, recommend
  only alphanumeric, -, _. clean spec enforces this recommendation.

## 2023-08-08 2.1 stable
* Add support for default on longpress (sk) keys. Aligns with Keyman 17.0.

## 2022-06-30 2.0 stable
* Add support for flick, multitap, hint, defaultHint. Aligns with Keyman 16.0.

## 2022-06-27 1.0 stable
* Initial schema version and full documentation

## 2018-05-28 0.2 .keyman-touch-layout format
* Changed file extension to .keyman-touch-layout in https://github.com/keymanapp/keyman/pull/897

## 0.1 -layout.js format
* Initial version
