#cipherkeys now has two new alternative layouts, dvorak and ...

5538e28a66eb8836...

npub125uw9znxawyrvrc4lraf2ertm5k652ve4t87f74v7s7scp2qk2qswmlek0

hex

710a0a960d8ce3053b5ece2dde4b01be7d20ba0947b610e61a29ea68e00eb586

nevent

nevent1qqs8zzs2jcxcecc98d0vutw7fvqmulfqhgy50dssucdzn6nguq8ttpsprpmhxue69uhhyetvv9ujuem4d36kwatvw5hx6mm9qgs92w8z3fnwhzpkpu2l3754v34a6td29xv64nlyl2k0g0gvq4qt9qgqy90am

Kind-1 (TextNote)

2026-08-24T11:28:06Z

#cipherkeys now has two new alternative layouts, dvorak and russian. they slightly differ from the aosp of both keyboards in small ways but they make sense - the e to e-umlaut displaces the long press numbers at the top so e-umlaut is accessible (i haven't created multi-key option for long press but russian has 11 keys across the top row anyway) and the USB keyboard when plugged in switches to the proper usb layout relevant to the keyboard layout of the soft-keyboard so if you plug in a keyboard labeled in either form (or like me, just can touch type) you get exactly what you expect from it. possibly later i will add kyrgyz and kazakh keyboards but it's not a big priority. if anyone wants any other language layouts, like german, french, serbo-croatian, spanish, portuguese, just give me the key patterns you want to see (presumably the standard national keyboard, and USB will respect the layout as well.

here's the report from the robot of the changes in the release:

Release v00034 is live on GitHub, git.smesh.lol, and Zapstore. Both working trees are clean.

Session summary

Layouts added

Dvorak (v00033)

  • On-screen Dvorak keymap (DVORAK/DVORAK_SHIFT) with ,/./' repositioned and KbKey.weight for uniform punctuation widths
  • Space-bar long-press switcher + settings radio

Russian ЙЦУКЕН (v00034)

  • On-screen layout: top йцукенгшщзх (11 keys), second фывапролджэ (11), bottom ячсмитьбю (9)
  • Number long-press hints spread across the top row ¹²³⁴ё⁵⁶⁷⁸⁹⁰ - ё sits on е instead of a number
  • ьъ long-press (hint as superscript), ЬЪ when shifted
  • Email fields force QWERTY (Latin), never Cyrillic

USB / physical-keyboard support (the shared mechanism)

Three IME subtypes in method.xml, each with subtypeId + physicalKeyboardHintLanguageTag + physicalKeyboardHintLayoutType (qwerty/dvorak/russian). Two framework bugs had to be fixed for this to work at all:

  1. enableAllSubtypes() - the system's implicit subtype selection (LocaleUtils.filterByLanguage) keeps only ONE subtype per language, so same-locale subtypes (en_US qwerty + en_US dvorak) collapsed to one. Fixed by explicitly enabling all three via InputMethodManager.setExplicitlyEnabledInputMethodSubtypes().

  2. syncKeyboardLayoutSubtype() - the obvious setCurrentInputMethodSubtype() silently no-ops for non-system apps (@RequiresPermission(WRITE_SECURE_SETTINGS)). Switched to the IME-safe InputMethodService.switchInputMethod(id, subtype).

Wiring

  • CipherPrefs.keyboardLayout now accepts qwerty/dvorak/russian
  • Layout switch propagates to the physical keyboard via syncKeyboardLayoutSubtype() on onStartInput and space-bar long-press

原始 JSON

{
  "kind": 1,
  "id": "710a0a960d8ce3053b5ece2dde4b01be7d20ba0947b610e61a29ea68e00eb586",
  "pubkey": "5538e28a66eb88360f15f8fa95646bdd2daa2999aacfe4faacf43d0c0540b281",
  "created_at": 1787570886,
  "tags": [
    [
      "t",
      "cipherkeys"
    ],
    [
      "client",
      "smesh",
      "https://smesh.mleku.dev"
    ]
  ],
  "content": "#cipherkeys now has two new alternative layouts, dvorak and russian. they slightly differ from the aosp of both keyboards in small ways but they make sense - the e to e-umlaut displaces the long press numbers at the top so e-umlaut is accessible (i haven't created multi-key option for long press but russian has 11 keys across the top row anyway) and the USB keyboard when plugged in switches to the proper usb layout relevant to the keyboard layout of the soft-keyboard so if you plug in a keyboard labeled in either form (or like me, just can touch type) you get exactly what you expect from it. possibly later i will add kyrgyz and kazakh keyboards but it's not a big priority. if anyone wants any other language layouts, like german, french, serbo-croatian, spanish, portuguese, just give me the key patterns you want to see (presumably the standard national keyboard, and USB will respect the layout as well.\n\nhere's the report from the robot of the changes in the release:\n\nRelease `v00034` is live on GitHub, git.smesh.lol, and Zapstore. Both working trees are clean.\n\n## Session summary\n\n### Layouts added\n\n**Dvorak** (`v00033`)\n- On-screen Dvorak keymap (`DVORAK`/`DVORAK_SHIFT`) with `,`/`.`/`'` repositioned and `KbKey.weight` for uniform punctuation widths\n- Space-bar long-press switcher + settings radio\n\n**Russian ЙЦУКЕН** (`v00034`)\n- On-screen layout: top `йцукенгшщзх` (11 keys), second `фывапролджэ` (11), bottom `ячсмитьбю` (9)\n- Number long-press hints spread across the top row `¹²³⁴ё⁵⁶⁷⁸⁹⁰` - `ё` sits on `е` instead of a number\n- `ь`→`ъ` long-press (hint as superscript), `Ь`→`Ъ` when shifted\n- Email fields force QWERTY (Latin), never Cyrillic\n\n### USB / physical-keyboard support (the shared mechanism)\n\nThree IME subtypes in `method.xml`, each with `subtypeId` + `physicalKeyboardHintLanguageTag` + `physicalKeyboardHintLayoutType` (`qwerty`/`dvorak`/`russian`). Two framework bugs had to be fixed for this to work at all:\n\n1. **`enableAllSubtypes()`** - the system's implicit subtype selection (`LocaleUtils.filterByLanguage`) keeps only ONE subtype per language, so same-locale subtypes (en_US qwerty + en_US dvorak) collapsed to one. Fixed by explicitly enabling all three via `InputMethodManager.setExplicitlyEnabledInputMethodSubtypes()`.\n\n2. **`syncKeyboardLayoutSubtype()`** - the obvious `setCurrentInputMethodSubtype()` silently no-ops for non-system apps (`@RequiresPermission(WRITE_SECURE_SETTINGS)`). Switched to the IME-safe `InputMethodService.switchInputMethod(id, subtype)`.\n\n### Wiring\n- `CipherPrefs.keyboardLayout` now accepts `qwerty`/`dvorak`/`russian`\n- Layout switch propagates to the physical keyboard via `syncKeyboardLayoutSubtype()` on `onStartInput` and space-bar long-press",
  "sig": "c0d886be4e519b25eeb85a2b30286b56d1c32fb1b48da24025cf92a3cbc3d7959cab2d9fa6eb5f80b3066fe8053d98888a45af05b392de02a25d6975179ee7b9"
}