VibeTunnel CJK IME Input Implementation
Overview
VibeTunnel provides comprehensive Chinese, Japanese, and Korean (CJK) Input Method Editor (IME) support across both desktop and mobile platforms. The implementation uses platform-specific approaches to ensure optimal user experience:- Desktop: Cursor-positioned text input with native browser IME integration
- Mobile: Native virtual keyboard with direct input handling
Architecture
Core Components
Implementation Details
Cursor Position Tracking
File:cursor-position.ts
The cursor position tracking system uses renderer-specific cursor coordinates:
Coordinate System
Position Calculation Process
- Character Measurement: Dynamically measures actual character width using font metrics
- Absolute Positioning: Calculates page-absolute cursor coordinates
- Container Relative: Converts to position relative to
#session-terminalcontainer - IME Positioning: Returns coordinates suitable for IME input placement
Terminal Type Support
- Ghostty Terminal (
vibe-terminal): Uses the active buffer cursor and renderer cell metrics. - Buffer Terminal (
vibe-terminal-buffer): Usesbuffer.cursorX/Yfrom VT snapshot data.
Key Features
- Precise Alignment: Accounts for exact character width and line height
- Container Aware: Handles side panels and complex layouts
- Font Responsive: Adapts to different font sizes and families
- Platform Consistent: Same calculation logic across all terminal types
Error Handling
The function includes comprehensive error handling and graceful fallbacks:- Returns
nullwhen session is not running - Returns
nullwhen container element is not found - Returns
nullwhen character measurement fails - Falls back to absolute coordinates if session container is missing
Platform Detection
File:mobile-utils.ts
VibeTunnel automatically detects the platform and chooses the appropriate IME strategy:
Desktop Implementation
1. DesktopIMEInput Component
File:ime-input.ts
A dedicated component for desktop browsers that creates and manages a native text input:
- Positioned dynamically at terminal cursor location
- Uses a normal input size so browsers can anchor native candidate windows reliably
- Transparent background and hidden caret keep the terminal visually unobstructed
- Handles all CJK composition events through standard DOM APIs
- Focuses when the user clicks the terminal, with short animation-frame retries for browser timing
- Clean lifecycle management with proper cleanup
2. Desktop Input Manager Integration
File:input-manager.ts
The InputManager detects platform and creates the appropriate IME component:
3. Desktop Focus Management
File:ime-input.ts
Desktop IME focus follows terminal clicks. The implementation avoids polling because repeatedly stealing focus interferes with native candidate selection:
Mobile Implementation
1. Direct Keyboard Manager
File:direct-keyboard-manager.ts
Mobile devices use the native virtual keyboard with a visible input field:
- Standard HTML input element (not hidden)
- Native virtual keyboard with CJK support
- Quick keys toolbar for common terminal operations
- No special IME handling needed (OS provides it)
2. Mobile Input Flow
Files:session-view.ts, lifecycle-event-manager.ts
Mobile input handling follows a different flow:
- User taps terminal area
- Native virtual keyboard appears with CJK support
- User types or selects from IME candidates
- Input is sent directly to terminal
- No desktop composition bridge is needed
Platform Differences
Key Implementation Differences
| Aspect | Desktop | Mobile |
|---|---|---|
| Input Element | Cursor-positioned standard input | Visible standard input field |
| IME Handling | Custom composition events | Native OS keyboard |
| Positioning | Follows terminal cursor | Fixed position or overlay |
| Focus Management | Click focus with bounded retries | Standard focus behavior |
| Keyboard | Physical + software IME | Virtual keyboard with IME |
| Integration | Transparent terminal overlay | Visible UI component |
| Performance | Minimal overhead | Standard input performance |
Technical Architecture Differences
Desktop Implementation
Mobile Implementation
User Experience Differences
Desktop Experience
- Seamless: No visible UI changes
- Cursor following: IME popup appears at terminal cursor
- Click to focus: Click anywhere in terminal area
- Traditional: Works like native terminal IME
- Paste support: Global paste handling anywhere in terminal
Mobile Experience
- Touch-first: Designed for finger interaction
- Visible input: Clear indication of where to type
- Quick keys: Easy access to terminal-specific keys
- Gesture support: Touch gestures and haptic feedback
- Keyboard management: Handles virtual keyboard show/hide
Platform-Specific Features
Desktop Features
- Dynamic cursor positioning: IME popup follows terminal cursor exactly
- Global paste handling: Paste works anywhere in terminal area
- Composition state tracking: Via native
KeyboardEvent.isComposingplus thedata-ime-composingDOM attribute - Focus management: Click focus plus bounded browser-timing retries
- Transparent integration: Native input text appears at the terminal cursor without a separate control
- Performance optimized: Minimal resource usage when not composing
Mobile Features
- Native virtual keyboard: Full OS-level CJK IME integration
- Quick keys toolbar: Touch-friendly terminal keys (Tab, Esc, Ctrl, etc.)
- Touch-optimized UI: Larger tap targets and touch gestures
- Auto-capitalization control: Intelligently disabled for terminal accuracy
- Viewport management: Graceful handling of keyboard show/hide animations
- Direct input mode: Option to use hidden input for power users
User Experience
Desktop Workflow
Mobile Workflow
Visual Behavior
- Desktop: Transparent input text and native IME popup at the terminal cursor
- Mobile: Standard input field with native virtual keyboard
- Both platforms: Seamless CJK text input with full IME support
Performance
Optimization Features
- One input element and listener set per active desktop session
- Dynamic positioning only calculated when needed
- Minimal DOM footprint (single input element)
- Clean event delegation and lifecycle management
- Click-to-focus behavior without polling
- Proper cleanup prevents memory leaks during session changes
Code Reference
Primary Files
ime-input.ts- Desktop input creation, composition events, positioning, focus, paste, and cleanupinput-manager.ts- Input coordination, desktop/mobile selection, terminal routing, and lifecycleterminal.ts- Ghostty renderer cursor geometry used to anchor the native inputlifecycle-event-manager.ts- Keyboard interception that leaves active composition to the browserdirect-keyboard-manager.ts- Mobile keyboard handlingmobile-utils.ts- Mobile detection utilities
Supporting Files
session-view.ts- Container element and terminal integrationime-constants.ts- IME-related key filtering utilitiesterminal-constants.ts- Terminal element IDs, font settings, and IME positioning constants
Browser Compatibility
Works with all major browsers that support:- IME composition events (
compositionstart,compositionupdate,compositionend) - Clipboard API for paste functionality
- Standard DOM positioning APIs
Configuration
Automatic Platform Detection
CJK IME support is automatically configured based on the detected platform:- Desktop: Cursor-positioned IME input with native candidate-window anchoring
- Mobile: Native virtual keyboard with OS IME
Requirements
- User has CJK input method enabled in their OS
- Desktop: User clicks in terminal area to focus
- Mobile: User taps terminal or input field
- User switches to CJK input mode in their OS
Troubleshooting
Common Issues
- IME candidates not showing: Ensure browser supports composition events
- Text not appearing: Check if terminal session is active and receiving input
- Paste not working: Verify clipboard permissions in browser
Debug Information
Comprehensive logging available in browser console:🔍 Setting up IME input on desktop device- Platform detection[ime-input]- Desktop IME component events[direct-keyboard-manager]- Mobile keyboard events- State tracking through DOM attributes:
data-ime-composing- IME composition active (desktop)data-ime-input-focused- IME input has focus (desktop)
- Mobile detection logs showing user agent analysis
Recent Improvements (v1.0.0-beta.16+)
Unified Cursor Position Tracking
- Shared Utility: Created
cursor-position.tsfor consistent cursor calculation across all terminal types - Container-Aware Positioning: Fixed IME positioning issues with side panels and complex layouts
- Precise Alignment: Improved character width measurement for pixel-perfect cursor alignment
- Debug Logging: Enhanced debug output with comprehensive coordinate information
Technical Improvements
- Code Deduplication: Eliminated ~120 lines of duplicate cursor calculation code
- Maintainability: Single source of truth for cursor positioning logic
- Type Safety: Improved TypeScript interfaces and error handling
- Performance: More efficient coordinate conversion with optimized calculations
Element ID Centralization
- Constants File: Created
terminal-constants.tsto centralize all critical terminal element IDs - Prevention of Breakage: Changes to IDs like
session-terminal,buffer-container, orterminal-containernow only require updates in one location - Consistent References: All components now import
TERMINAL_IDSconstants instead of using hardcoded strings - Type Safety: Constants are strongly typed to prevent typos and ensure consistent usage across the codebase
Status: ✅ Production Ready
Platforms: Desktop (Windows, macOS, Linux) and Mobile (iOS, Android)
Version: VibeTunnel Web v1.0.0-beta.16+
Last Updated: 2026-06-13