This comes out of a design philosophy review on what we include when we embed OSK data into KMX. We will now avoid embedding font name into the OSK (and hence .kmx) altogether, and leave that metadata to the packaging data. Reasons: 1. The font information is specified in the .kps, so we have to do a patchup on the .kmx during packaging if we want to embed the info into the OSK. 2. The referenced font must be supplied separately anyway (via .kmp, @font-face, or system supplied, etc), so including the font facename in the keyboard is not really all that helpful. 3. Philosophically, the font is really a presentation level factor (aside from displaymap considerations). Keeping it together with future theming and styling choices, rather than the key layout data, seems appropriate. 4. This makes fewer places where font data is referenced -- in fact, to just one place: in the .kps/.kmp for LDML keyboards, which is great. This also simplifies some aspects of the embed-osk-in-kmx work, removing the need to patch the .kmx after the build, and eliminates the smelly kmx-plus-osk-token.ts file. A corresponding change has been made to the design document referenced in #14857. Test-bot: skip
8.5 KiB
| title |
|---|
| Mapping from .keyman-touch-layout to LDML |
.keyman-touch-layout is referred to as .ktl for short
Note that counts and headers will need to merge both .kvks and .keyman-touch-layout.
.keyman-touch-layout notes
touch-layout
tablet|phone|desktop -> determines minDeviceWidth and hardware
font: use only in design, not in KMX+
fontsize: use only in design, not in KMX+
displayUnderlying: lay2.forms.flags.showBaseLayout
defaultHint: resolved at compile time to generate hints for each key
layer[]
id: layr.layers.id
row[]
id (numeric)
key[]
id: key2.keys.id (along with `layer`)
text: key2.keys.text / dis2.display.display
layer: key2.keys.id
nextlayer: key2.switch
font: not supported
fontsize: not supported
sp: map to various 'special' keys by id; see below
pad: adds a "gap" key2.keys
width: map to key2.keys.width / 10
sk[]
id: key2.keys.id
text: key2.keys.to
layer: key2.keys.id
nextlayer: key2.switch
font: not supported
fontsize: not supported
sp: map to various 'special' keys by id; see below
pad: adds a "gap" key2.keys
width: map to key2.keys.width / 10
flick{} - see sk
multitap[] - see sk
hint: add to dis2 for the given key
tablet | phone | desktop element
The name of the element drives the selection of the corresponding form data:
tablet-> setsminDeviceWidthto100(mm),hardware=touchphone-> setsminDeviceWidthto0(mm),hardware=touchdesktop-> ignore, as this is not really supported in Keyman at present; alternative:hardware=us(4 keyboards in repo that currently use this: karambolpoular, orma, sxava, sxava_eo)
id and layer properties
These two properties together will form the identifier of the key. This identifier will have semantic meaning, and will be used in event generation.
nextlayer property
This can be mapped to key2.switch.
sp property
The value of the sp property will drive slightly different behaviors:
0Default -> Default key type, no additional metadata1Special -> Setsdis2.display.flags.isFrameKeyflag2Special (active) -> Setsdis2.display.flags.isHighlightedanddis2.display.flags.isFrameKeyflags8: Deadkey -> Setsdis2.display.flags.isDeadKeyflag (styling only)9: Blank -> Setsdis2.display.flags.isBlankKeyflag (styling and interactivity)10: Spacer -> Adds agapkey with the required width
LDML table notes
key2
C7043.2.15 key2—Extended keybag
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0 | 32 | ident | key2 |
key2 |
| 4 | 32 | size | int: Length of section | size in bytes |
| 8 | 32 | keyCount | int: Number of keys | # keys from .ktl |
| 12 | 32 | flicksCount | int: Number of flick lists | |
| 16 | 32 | flickCount | int: Number of flick elements | |
| 20 | 32 | kmapCount | int: Number of kmap elements | 0 |
| 24 | var | keys | keys sub-table | |
| - | var | flicks | flick lists sub-table | |
| - | var | flick | flick elements sub-table | |
| - | var | kmap | key map sub-table |
key2.keys subtable
For each key element in .ktl:
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0+ | 32 | to | str: output string OR UTF-32LE codepoint | key.text* |
| 4+ | 32 | flags | int: per-key flags | bit 1 set if gap |
| 8+ | 32 | id | str: key id | key.layer + ':' + key.id? |
| 12+ | 32 | switch | str: layer id to switch to | key.nextlayer |
| 16+ | 32 | width | int: key width*10 (supports 0.1 as min width) | key.width / 10 |
| 20+ | 32 | longPress | list: index into list with longPress key id list or 0 |
|
| 24+ | 32 | longPressDefault | str: default longpress key id or 0 | |
| 28+ | 32 | multiTap | list: index into list sect multiTap key id list or 0 |
|
| 32+ | 32 | flicks | int: index into key2.flicks subtable |
- specials will be mapped to the corresponding
dis2.flags.specialKeyCap value
layr
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0 | 32 | ident | layr |
layr |
| 4 | 32 | size | int: Length of section | size in bytes |
| 8 | 32 | listCount | int: Number of layer lists | # layer lists |
| 12 | 32 | layerCount | int: number of layer entries | # layer entries |
| 16 | 32 | rowCount | int: number of row entries | # row entries |
| 20 | 32 | keyCount | int: number of key entries | # key entries |
| 24 | var | lists | layer list sub-table | |
| - | var | layers | layers sub-table | |
| - | var | rows | rows sub-table | |
| - | var | keys | keys sub-table |
layr.lists
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0+ | 32 | hardware | str: name of hardware layout. | us (default) or iso <- kvkh102 |
| 4+ | 32 | layer | int: index to first layer element | 0 |
| 8+ | 32 | count | int: number of layer elements in this list | # layer elements <- modifiers |
| 12+ | 32 | minDeviceWidth | int: min device width in millimeters, or 0 | 0 |
layr.layers
Each layer corresponds to a .kvks visualkeyboard/encoding[@name=unicode]/layer element.
The layer[@shift] mapping is from VisualKeyboardLegalShiftStates\[\].name to keys.key.mod
and K_MODIFIERFLAG bitmask (this is not the same as the KVK bitmasks, which shall be deprecated)
The compiler starts by filling out a blank representation of each modifier layer, then
iterates through the .kvk visualkeyboard/encoding/layer/key, keying off the attribute vkey.
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0+ | 32 | id | str: layer id such as base or shift |
<-- modifier name |
| 4+ | 32 | mod | int: modifier key flags | <-- K_MODIFIERFLAG bitmask |
| 8+ | 32 | row | int: index into rows area (next section) | index to rows |
| 12+ | 32 | count | int: number of rows elements for this layer |
# rows |
layr.rows
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0+ | 32 | key | int: index into key element | index to keys |
| 4+ | 32 | count | int: count of key elements in this row | # keys |
Each row should have the full set of 'white' keys, even if they are not all used. Note that us
and iso keyboards have different row counts for rows 2-4.
layr.keys
| ∆ | Bits | Name | Description | Content |
|---|---|---|---|---|
| 0+ | 32 | key | str: key id | key id |
? this implies that key.id is required, though key2.keys subtable says it is optional.