ssh-workbench/docs/KEYBOARD.md
jima 379d2e0677 Edge-to-edge layout, SFTP footer at nav bar, cleanup
- enableEdgeToEdge() before super.onCreate() for proper inset handling
- SFTP rendered at Box level (outside terminal Column) so Scaffold
  bottomBar with navigationBarsPadding() reaches the nav bar edge
- SFTP only composed when active tab (prevents invisible touch blocking)
- Status bar + 41dp top padding on SFTP overlay for tab bar visibility
- Removed windowInsetsPadding from terminal Column (edge-to-edge handles it)
- Cleaned unused imports and debug parameters
- docs: number row modes in KEYBOARD.md, SFTP folder reconnect done in FUTURE.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 00:36:19 +02:00

7.9 KiB
Raw Permalink Blame History

Keyboard System

Last updated: 2026-04-03 See also: docs/GLOSSARY.md for abbreviations


Glossary

Abbrev Name Description
TV Terminal View Terminal surface — displays sessions, receives input
AKB Android Keyboard System IME (Gboard, Samsung, etc.)
CKB Custom Keyboard Our Canvas-based keyboard (lib-terminal-keyboard)
AQB AKB QuickBar QuickBar when using the Android Keyboard
CQB CKB QuickBar QuickBar when using the Custom Keyboard

Architecture

Two keyboard modes, selected in Settings → Keyboard → Keyboard Type:

┌─────────────────────────────────────────┐
│  TV (TerminalSurfaceView)               │
├─────────────────────────────────────────┤
│  QuickBar (AQB or CQB)                │  ← always visible (if enabled)
├─────────────────────────────────────────┤
│  CKB (custom keyboard pages)           │  ← only in CKB mode
│  — or —                                │
│  AKB (system IME, managed by Android)  │  ← only in AKB mode
└─────────────────────────────────────────┘

CKB Mode

  • Our custom Canvas keyboard (lib-terminal-keyboard) renders below the QB
  • System IME is explicitly hidden (softInputEnabled = false)
  • CQB keys: ESC, TAB, :, ~, |, arrows, Shift+Tab, vim, nano, tmux, screen
  • CKB settings: language, height, page indicators, key colors, hints, repeat delay, long press delay
  • CQB settings: position, size, color

AKB Mode

  • System IME manages itself (Android handles show/hide)
  • CKB view is hidden (container.visibility = GONE)
  • AQB sits above the system keyboard or at screen top
  • AQB settings: position, size, color (independent from CQB)

Preferences

Shared (both modes)

Pref Key Default
Keyboard type keyboard_type "custom"
Haptic feedback haptic_feedback true
Show QuickBar quick_bar_visible true

CKB-only

Pref Key Default
Language keyboard_language "en"
Height (portrait) keyboard_height_percent 0.27
Height (landscape) keyboard_height_landscape 0.27
Same size both keyboard_same_size_both true
Page indicators show_page_indicators true
Key color preset key_color_preset "default"
Key color custom key_color_custom ""
Show hints show_key_hints true
Key repeat delay key_repeat_delay 400
Long press delay long_press_delay 350

CQB (Custom Keyboard QuickBar)

Pref Key Default
Position quick_bar_position "above_keyboard"
Size quick_bar_size 42
Color preset qb_color_preset "default"
Color custom qb_color_custom ""

AQB (Android Keyboard QuickBar)

Positions: top, vertical_left, vertical_right, none (no above_keyboard/below_keyboard — no CKB to be relative to)

Pref Key Default
Position aqb_position "top"
Size aqb_size 42
Color preset aqb_color_preset "default"
Color custom aqb_color_custom ""

Settings UI

Settings → Keyboard section adapts based on keyboard_type:

CKB selected: Haptic, Show QB, Type selector, "Keyboard Settings" button → opens KeyboardSettingsDialog (two tabs: Keyboard + QuickBar)

AKB selected: Haptic, Show QB, Type selector, "QuickBar Settings" button → opens KeyboardSettingsDialog.showAqb() (position, size, color only)


Key Files

File Purpose
lib-terminal-keyboard/ Standalone keyboard library (Canvas, JSON layouts, language packs)
TerminalKeyboard.kt Entry point, Builder, touch handling, popup management
KeyboardView.kt ViewPager2 for swipeable keyboard pages
KeyboardPageView.kt Canvas rendering + hit testing per page
QuickBarView.kt Canvas QB with infinite scroll, menu keys, modifier highlights
ModifierStateManager.kt CTRL/ALT/SHIFT state machine (IDLE ↔ ARMED on tap, long-press → LOCKED)
KeyboardSettingsDialog.kt CKB+CQB settings dialog + AQB settings dialog + KeyboardPreview composable
QuickBarCustomizerScreen.kt QB key/app customizer — two-tab Compose dialog (pro)
QuickBarCustomizer.kt Key pool, serialization, defaults for QB customizer
TerminalPreferences.kt DataStore prefs for all keyboard settings
SettingsScreen.kt Compose settings UI with mode-aware keyboard section
TerminalPane.kt Wires keyboard to terminal (CKB visibility, QB, key events)
MainActivity.kt Keyboard instance lifecycle, QB/CKB attachment, size routing

QuickBar Keys

CQB (Custom Keyboard mode)

Defined in layout_qwerty.jsonquickBar.keys: ESC, TAB, :, ~, |, ←, →, Shift+Tab, vim, nano, tmux, screen

AQB (System Keyboard mode)

Separate key set via QuickBarView.systemKeyboardQuickBarKeys(): CTRL, ESC, TAB, :, /, ←, →, ↑, ↓, HOME, END, PGUP, PGDN, F1-F12. Uses minimum key width (36dp) based on smallest key weight.


QuickBar Customizer (Pro)

Full-screen dialog for customizing QB keys and app shortcuts. Two tabs:

  • Keys tab: Active keys with drag-and-drop reorder (drag handle) and delete (trashcan). Available keys in a 4-column grid with tap-to-add (+). 55 keys in the master pool (4 modifiers + 13 navigation + 26 symbols + 12 F-keys).
  • App Shortcuts tab: Drag-and-drop reorder, add/remove apps (trashcan + drag handle). Expand to see/edit individual key maps with drag-and-drop reorder (label + action). Action format: hex bytes (01 63), escape sequences (\eOP), or text macros (\r for Enter).

Access: KB Settings → QuickBar tab → Customize button, or AQB Settings → Customize button.

CQB and AQB have independent custom configurations stored in DataStore (cqb_custom_keys, cqb_custom_apps, aqb_custom_keys, aqb_custom_apps). Empty = use defaults from JSON layout.

Key files:

File Purpose
QuickBarCustomizerScreen.kt Compose UI — two-tab dialog, dialogs for add/edit
QuickBarCustomizer.kt QuickBarKeyPool (master key list), serialization, resolveKeys()

Number Row Modes

Setting: number_row_mode (default "left"). Options:

Mode Behavior
top Dedicated number row above QWERTY (legacy)
left Mini numpad (3×3+1) on the left side, keyboard takes remaining width
right Mini numpad on the right side
hidden No number row; numbers via long-press on QWERTY keys with top-right corner hints

Mini Section (JSON)

Defined in layout_qwerty*.json under "mini" key:

"mini": { "widthPercent": 10, "rows": [...] }

Model: MiniSection in KeyboardLayout.kt. Parsed by LayoutParser.parseMiniSection().

Implementation

  • NumberRowTransform.kt — transforms the parsed layout based on mode (removes number row, adds hints for hidden)
  • TerminalKeyboard.attachMiniTo(container) — creates a KeyboardPageView for the mini section with touch handling
  • In MainActivity: LinearLayout with weighted children (mini + main) inside AndroidView. clipChildren re-enabled after attachTo to prevent SurfaceView rendering issues.

Temporary Hide (CKB only)

  • Tab bar kebab menu → "Hide keyboard" / "Show keyboard" toggles ckbHidden Compose state (not a pref change)
  • CKB view hidden, QB stays visible
  • Tapping TV fires onTapShowKeyboard → resets ckbHidden
  • Does not affect AKB mode (system IME has its own show/hide)