Flesh out custom layout doc (#651)

This commit is contained in:
Spike 2024-06-08 16:22:46 -04:00 committed by GitHub
parent 6ac973cfda
commit 8b99c04a21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 85 additions and 76 deletions

View File

@ -1,113 +1,122 @@
# Custom layouts
You select a key layout for Unexpected Keyboard by calling up the Settings page (swipe the gear icon) and, at the top of the page, either tapping an existing layout or tapping _Add an alternate layout_. This displays a menu of available layouts. You can define your own layout by choosing _Custom layout_ at the bottom of this menu. Unexpected Keyboard now displays code in the XML format. You make changes by replacing this with different code and tapping OK.
Unexpected Keyboard allows custom layouts to be defined, loaded, and used in the app. These layouts are defined in XML.
We recommend you keep your work in a file outside Unexpected Keyboard (named something like `MyChanges.xml`). If you installed a new version of Unexpected from a different website (with a different signature), then the work you did solely by editing the XML inside Unexpected would be lost.
## Existing keyboard layouts
Put initial contents into your file in one of these ways:
* Copypaste the code Unexpected displays for _Custom layout_.
* Make a copy of one of the built-in layouts found in [`/srcs/layouts`](https://github.com/Julow/Unexpected-Keyboard/tree/master/srcs/layouts).
* Use the [web-based editor](https://unexpected-keyboard-layout-editor.lixquid.com/). Interact with this web page to define keys and swipes and move keys to desired positions, and it will write the XML code for you. You can make the web page put the XML in a text file or copy it to the clipboard.
The XML data files for the keyboard layouts that come with the app can be seen [in `/srcs/layouts`](https://github.com/Julow/Unexpected-Keyboard/tree/master/srcs/layouts).
When you have prepared suitable XML code in one of these ways, copy it to the clipboard and paste it into Unexpected Keyboard.
## Structure
## XML language overview
A layout XML file comprises tags that start with `<` and end with `>`.
* Every layout file starts with this declaration:
`<?xml version="1.0" encoding="utf-8"?>`
* Certain tags come in pairs—an opening tag and a closing tag—and apply to everything between them.
* The `<keyboard>`...`</keyboard>` pair says that the material between them is the definition of your keyboard. There can be only one of these.
* The `<row>`...`</row>` pair encloses the definition of a single row.
* An optional `<modmap>`...`</modmap>` pair contains instructions if you want to change the behavior of a modifier key such as Shift.
* Stand-alone tags include `<key`...`/>`, which defines a single key.
A complete keyboard file with a single row containing a single Turkish "i" key is provided below:
A tag can have properties, defined using an equals sign and a pair of ASCII double quotes. For example, `<key key0="a" />` defines the "a" key. The `key0` property of the `key` tag says which key you are defining, and the tag's location inside `<row>`...`</row>` specifies where it will go in the row.
### Example
Here is a complete keyboard file with a single row containing an "a" key on the left and a "b" key on the right:
<?xml version="1.0" encoding="utf-8"?>
<keyboard name="Keyboard Name" script="latin">
<modmap>
<shift a="i" b="İ" />
</modmap>
<keyboard name="Simple example" script="latin">
<row>
<key key0="i" />
<key key0="a" />
<key key0="b" />
</row>
</keyboard>
Shift assignments can be changed on a per-character basis.
## Keyboard metadata
The `<keyboard>`...`</keyboard>` pair follows the declaration tag and encloses the whole keyboard. The following properties may be used (The first two appear in the example above):
* `name`: The name of the keyboard. The name you specify will appear in the Settings menu. If not present, the layout will just appear as “Custom layout”.
* `script`: The (main) writing system that the keyboard supports. The possible values are `arabic`, `armenian`, `bengali`, `cyrillic`, `devanagari`, `gujarati`, `hangul`, `hebrew`, `latin`, `persian`, `shavian`, and `urdu`. It defaults to `latin`.
* `numpad_script`: The script to use for the numpad. This is useful for scripts where a different, non-ASCII set of numerals is used, like Devanagari and Arabic. It defaults to the same as `script`.
* `bottom_row`: Whether or not to show the common bottom row. It accepts `true` or `false`, and defaults to `true`. If your custom layout defines the bottom row, then specify `bottom_row=false` to disable the built-in bottom row.
### Crash course to XML
## Row
The `<row>`...`</row>` pair encloses one row on the keyboard. It has only one optional property:
* `height`: The height of the row: a positive floating-point value.
An XML document is made out of tags.
A row's default height is 1.0 (one quarter of the keyboard height specified on the Settings menu). The `height` property makes the row taller or shorter than this. For example, if you define a 5-row keyboard but one row has `height="0.7"`, then the keyboard's total height is 4.7 units. If the total is different from 4.0, the keyboard will be taller or shorter than that specified in Settings.
Paired tags start with `<` and end with `>`, and must be closed by another tag that starts with `</`. They can have other tags as children. Paired tags used in Unexpected Keyboard include `<row>`...`</row>` and `<keyboard>`...`</keyboard>`.
## Key
The `<key />` tag defines a key on the keyboard. Its position in the sequence of keys inside `<row>`...`</row>` indicates its position in the row from left to right. What the key does is defined by optional properties.
Auto-terminating tags start with `<` and end with `/>`, and can't have any children. Auto-terminating tags used in Unexpected Keyboard include `<key />` and `<shift />`.
### Taps
What the key does when tapped is defined by the `key0` property. For example, `<key key0="a" />` defines the "a" key. Unexpected Keyboard provides a legend in the middle of the key.
An XML tag can have attributes, defined using an equals sign and a pair of ASCII double quotes.
When the Shift modifier is tapped, the "a" key becomes the "A" key and the legend temporarily changes. The Fn modifier makes a different change. You can override this behavior with a modmap (see below).
If you do not like XML, you can also use [this third-party GUI editor](https://unexpected-keyboard-layout-editor.lixquid.com/) to create or edit a keyboard layout.
### XML declaration
Every keyboard XML starts with `<?xml version="1.0" encoding="utf-8"?>`.
### Keyboard metadata
The `<keyboard>` tag encloses the whole keyboard. The following properties may be used:
* `name`: The name of the keyboard as it appears in the settings menu. If not present, it will just be called “Custom layout”.
* `bottom_row`: Whether or not to show the common bottom row. Accepts `true` or `false`, and defaults to `true`.
* `script`: The (main) writing system that it supports. Possible values are `arabic`, `armenian`, `bengali`, `cyrillic`, `devanagari`, `gujarati`, `hangul`, `hebrew`, `latin`, `persian`, `shavian`, and `urdu`. Defaults to `latin`.
* `numpad_script`: The script to use for the numpad. This is useful for scripts where a different, non-ASCII set of numerals is used, like Devanagari and Arabic. Defaults to the same as `script`.
### Modmap
The `<modmap>` tag encloses custom mappings for the Shift and Fn keys behavior.
Each entry contains two mandatory properties: `a` for the base character before the modifier is applied, and `b` for the modified character.
For example, to make the `I` key behave as in Turkish:
<modmap>
<shift a="i" b="İ" />
</modmap>
There can be as many of these tags inside `<modmap>` as needed.
Shift and Fn modmaps also affect the clockwise circle and the roundtrip gestures.
### Row
The `<row>` tag encloses one row on the keyboard. It requires no properties, and supports the following:
* `height`: The height of the row. Defaults to 1, and accepts a positive floating point value.
The total height of the keyboard is defined in Settings as a percentage of the total height of the screen, which can be different between portrait and landscape. The height of a row is relative to the other ones, and are scaled to keep the height of the keyboard constant.
### Key
The `<key />` tag defines a key on the keyboard. It requires at least one of the following properties:
* `key0`: What the key should do when it is tapped.
* `nw`, `ne`, `sw`, `se`, `w`, `e`, `n`, `s`: What the key should do when it is swiped. They are based on cardinal directions, and uses the convention that North is up. These are the new set of keywords, and should not be used with the other set of keywords.
### Swipes
The following optional properties define the effects of swipes:
* `n`, `ne`, `e`, `se`, `s`, `sw`, `w`, `nw`: What the key should do when it is swiped in the direction of that compass point. ("North" means upward and "East" is to the right.)
nw | n | ne
:-: | :--: | :-:
w | key0 | e
sw | s | se
* `key1` through `key8`: The older set of keywords for what the key should do when it is swiped. The directions are ordered as follows:
* `key1` through `key8` is an older way to achieve the same effects. The directions are ordered as follows:
key1 | key7 | key2
:--: | :--: | :--:
:-: | :--: | :-:
key5 | key0 | key6
key3 | key8 | key4
The following properties are optionally supported:
You can define a swipe only once with either compass-point or numeric notation. Unexpected Keyboard automatically puts a small legend in that direction from the center of the key.
* `width`: The width of the key relative to the normal width. Defaults to `1` and accepts a positive floating point value.
* `shift`: How much empty space to add to the left of this key. Defaults to `0` and accepts a non-negative floating point value.
* `indication`: An extra label to show under the main label, intended to be used as a legend for 2A typing (e.g. `<key key0="2" indication="ABC" />`). Caution: if you have `key8` defined, it overlaps!
* `slider`: If set to `true`, the keys `w` and `e` are sent repeatedly when the key is being slid on. Intended to be used on the space bar, and in fact used on the default space bar.
* `anticircle`: The key value to send when doing an anti-clockwise circle gesture on the key. The clockwise circle and round-trip gestures are not configurable that way.
* `slider`: If `slider="true"`, and the key also has `w` and `e` properties, then the key tracks horizontal finger motion precisely and sends the `w` and `e` keystrokes repeatedly. In built-in layouts, this makes the space bar send left and right characters as the user slides on the space bar.
* `anticircle`: The key value to send when doing an anti-clockwise gesture on the key. (The clockwise gesture applies a Shift modifier and the round-trip gesture applies a Fn modifier. These results can be redefined using a modmap, as explained below.)
### Layout
A key may have the following properties to control the row's layout:
* `width`: The width of the key, a positive floating-point value. It defaults to 1.0
* `shift`: How much empty space to add to the left of this key, a non-negative floating-point value. It defaults to 0.0
Normally, a key's width is 1.0 unit. Unexpected Keyboard occupies the full width of the screen, and the row defining the highest number of units (in widths plus shifts) is as wide as the screen. A row whose width is a smaller number of units has empty space on the right.
### Extra legend
* `indication`: An optional extra legend to show under the main label. For example, `<key key0="2" indication="ABC" />` displays ABC at the bottom of the 2 key, as on a pinpad or some telephones. If the key also defines a downward swipe with `s` or `key8`, the legends overlap.
## Possible key values
The properties that define the effects of tapping or swiping a key may be one of the built-in strings documented on [this page](Possible-key-values). For example, `se="cut"` says that a southeast swipe produces the "cut" key (Ctrl-C).
`key0` and `nw` through `se` (`key1` through `key8`) take arbitrary strings of characters, and if they don't match any of the special values, it is printed verbatim. (This is intended behavior.)
Some of those strings begin with `loc `. These are place-holders; the tap or swipe does nothing unless enabled through the "Add keys to keyboard" option in the Settings menu, or implicitly enabled by the language the device is set to use. For example, `ne="loc accent_aigu"` says that a northeast swipe produces the acute accent combinatorial key—if enabled.
Special values for the keys are documented in [this page](Possible-key-values).
If the string defining a tap or a swipe is anything other than one of the built-in strings, the defined string is output *verbatim.* This is what most of the taps and swipes on a typical keyboard do. So `key0="a"` simply outputs the letter a.
### `loc ` prefix
The string can output multiple characters, but cannot combine the built-in strings to specify a sequence of keystrokes.
Keys prefixed with `loc ` do not appear by default, and are only visible when they are enabled through the "Add keys to keyboard" option in the settings menu, or the language installed on the device is detected to require it.
## Modmap
The `<modmap>`...`</modmap>` pair encloses custom mappings for modifier keys.
A modmap can contain the following tags, each of which must have an `a` and a `b` property:
* `<shift a="`...`" b="`...`" />` —This says that, if the Shift modifier is on (or the user made a clockwise gesture on a key), and if the key would normally generate the value after "a", it must instead generate the value after "b".
* `<fn a="`...`" b="`...`" />` —This says that, if the Fn modifier is on (or the user made a round-trip gesture on a key), and if the key would normally generate the value after "a", it must instead generate the value after "b".
The "a" and "b" values are as specified above in _Possible key values_. A `<fn`...`/>` tag modifies a gesture only if no `<shift`...`/>` tag did.
There can be as many of these tags inside `<modmap>` as needed.
### Example
Turkish keyboards use the Latin alphabet, but when "i" is shifted, it should produce "İ". This is achieved with the following modmap:
<modmap>
<shift a="i" b="İ" />
</modmap>
## Portrait vs. landscape
Unexpected Keyboard remembers *separately* which layout has last been used in portrait and landscape orientation. That is to say, you may have one custom layout for portrait orientation, but another custom layout for landscape orientation, and Unexpected Keyboard will switch between them without your intervention.
## Contributing your layout
The Unexpected Keyboard project enthusiastically accepts user contributions, including custom layouts. (See the guidance for layouts at [CONTRIBUTING.md](https://github.com/Julow/Unexpected-Keyboard/blob/master/CONTRIBUTING.md#Adding-a-layout)).
* Submit a layout that has innovations of possible interest to other users at [Unexpected-Keyboard-layouts](https://github.com/Julow/Unexpected-Keyboard-layouts).
* Propose that your layout be included in the set of built-in layouts by making a Pull Request for an addition to [srcs/layouts](https://github.com/Julow/Unexpected-Keyboard/tree/master/srcs/layouts). Please show that such a layout is standard in your locale or has a substantial number of users.

View File

@ -35,7 +35,7 @@ Value | Meaning
`capslock` | Actives and locks Shift
## Special keys
These keys are sent to apps, which are free to ignore them. The keyboard do not perform editing in response to these keys.
These keys are sent to apps, which are free to ignore them. The keyboard does not perform editing in response to these keys.
`esc`, `enter`,
`up`, `right`,
@ -83,7 +83,7 @@ Value | Meaning
`accent_slash` | Slash through. `ø`
`accent_arrow_right` | Right arrow above, used to denote a vector. `a⃗`
`accent_breve` | Breve. `ă`
`accent_bar` | Bar/strikethrough. ``
`accent_bar` | Bar/strikethrough. `ɨ`
`accent_dot_below` | Dot below. `ạ`
`accent_horn` | Horn accent. `ơ`
`accent_hook_above` | Hook accent. `ả`