# How Sumire Handles Tablet-Specific Keyboard Layouts with Gesture Detection in JapaneseKeyboard

> Sumire tailors tablet keyboard layouts using TenKeyQWERTYMode.Sumire and a unified gesture pipeline. Discover its flick, tap, and long-press detection for an optimized input experience.

- Repository: [Kazu/japanesekeyboard](https://github.com/kazumaproject/japanesekeyboard)
- Tags: deep-dive
- Published: 2026-03-05

---

**Sumire implements tablet-optimized keyboard layouts by detecting the `TenKeyQWERTYMode.Sumire` state in [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt), inflating a `TabletKeyboardView`, and routing all touch events through a shared gesture pipeline that supports flick, tap, long-press, and double-tap interactions.**

Sumire serves as the dedicated tablet mode within the JapaneseKeyboard IME hierarchy, providing a full-sized layout optimized for larger screens while maintaining gesture parity with the ten-key and QWERTY modes. The implementation reuses the generic key-handling logic through shared listener interfaces, ensuring consistent flick gestures and input behavior across all device form factors. Understanding how Sumire handles tablet-specific keyboard layouts with gesture detection requires examining the mode detection logic, view initialization, and the touch event processing pipeline.

## Activating Sumire Tablet Mode

The IME detects tablet mode through the `TenKeyQWERTYMode` sealed class defined in [`core/src/main/java/com/kazumaproject/core/domain/state/TenKeyQWERTYMode.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/core/src/main/java/com/kazumaproject/core/domain/state/TenKeyQWERTYMode.kt). When `TenKeyQWERTYMode.Sumire` is active, the service triggers a specialized layout creation pathway distinct from the standard phone layouts.

### Detecting TenKeyQWERTYMode.Sumire

In [`app/src/main/java/com/kazumaproject/markdownhelperkeyboard/ime_service/IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/app/src/main/java/com/kazumaproject/markdownhelperkeyboard/ime_service/IMEService.kt), the `onStartInputView` method checks the current mode value to determine which keyboard view to inflate:

```kotlin
if (qwertyMode.value == TenKeyQWERTYMode.Sumire) {
    mainLayoutBinding?.let { mainView ->
        when (mainView.keyboardView.currentInputMode.value) {
            InputMode.ModeJapanese -> { … }
            InputMode.ModeEnglish  -> {
                customKeyboardMode = KeyboardInputMode.ENGLISH
                createNewKeyboardLayoutForSumire()
            }
            InputMode.ModeNumber   -> {
                customKeyboardMode = KeyboardInputMode.SYMBOLS
                createNewKeyboardLayoutForSumire()
            }
        }
    }
}

```

### Creating the Tablet Layout

The `createNewKeyboardLayoutForSumire()` method, located around line 1120 in [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt), performs three critical initialization steps:

1. **Inflates the tablet layout** – Sets `tabletView.isVisible = true` and attaches the `TabletKeyboardView` instance.
2. **Initializes the key map** – Instantiates `KeyMap()` and associates each `Key` enum with its corresponding physical button on the tablet view.
3. **Registers listeners** – Sets the view’s `setOnFlickListener` and `setOnLongPressListener` callbacks to the same `FlickListener` and `LongPressListener` implementations used by the ten-key and QWERTY keyboards.

This approach ensures that Sumire leverages the existing key-processing infrastructure while presenting a layout optimized for tablet screen real estate.

## Gesture Detection Architecture

All gesture handling for the tablet view resides in [`tabletkey/src/main/java/com/kazumaproject/tabletkey/TabletKeyboardView.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/tabletkey/src/main/java/com/kazumaproject/tabletkey/TabletKeyboardView.kt) (lines 707–1082). The class implements `View.OnTouchListener` and contains a specialized `GestureDetector` that enhances the base flick detection with tablet-specific interactions.

### Touch Event Pipeline

The `onTouch` implementation starting at line 998 processes all touch events through a standardized pipeline:

- **ACTION_DOWN**: Creates a `pressedKey` record, emits `flickListener?.onFlick(GestureType.Down, …)`, and initiates the long-press timer.
- **ACTION_MOVE**: Calls `getGestureType(event)` to analyze movement vectors, returning `FlickLeft`, `FlickTop`, `FlickRight`, `FlickBottom`, or `Tap`. The `setFlickInActionMove(gestureType)` method updates the pop-up preview and notifies the listener.
- **ACTION_UP**: Resolves the final gesture type and, if the key maps to a `KeyTapFlickInfo`, emits the appropriate character via `flickListener?.onFlick`.
- **ACTION_POINTER_DOWN/UP**: Handles two-finger gestures for "small-flick" operations (used for small dakuten and handakuten), forwarding these to `setFlickActionPointerDown`.

### English Mode Double-Tap Detection

The tablet view instantiates a `GestureDetector` that remains active exclusively when the current input mode is English:

```kotlin
private val gestureDetector =
    GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onDoubleTap(e: MotionEvent): Boolean {
            return if (currentInputMode.get() == InputMode.ModeEnglish) {
                val key = pressedKeyByMotionEvent(e, 0)
                if (key == Key.KeyKuten) {
                    hideAllPopWindow()
                    enableCapsLock()
                    skipNextTouches = true
                }
                true
            } else false
        }
    })

```

This implementation enables a double-tap shortcut on the period key (`Key.KeyKuten`) to toggle caps-lock in English mode, a tablet-specific optimization for faster text entry.

### Flick and Multi-Touch Handling

The `getGestureType()` function analyzes motion event coordinates to determine flick direction, while `setFlickActionPointerDown` manages multi-touch scenarios. These methods map physical gestures to `KeyInfo` data (such as `KeyInfo.flickLeft`), ensuring that flick gestures on the tablet produce the same character outputs as the ten-key layout.

## Implementation Example

The following code demonstrates the complete flow from mode selection to gesture handling:

```kotlin
// Switch to Sumire mode
tenKeyQWERTYMode.update { TenKeyQWERTYMode.Sumire }

// IMEService creates the tablet layout
private fun createNewKeyboardLayoutForSumire() {
    mainLayoutBinding?.tabletView?.apply {
        isVisible = true
        keyboardView.setOnFlickListener(flickListener)
        keyboardView.setOnLongPressListener(longPressListener)
    }
}

// TabletKeyboardView processes gestures
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
    if (currentInputMode.get() == InputMode.ModeEnglish) {
        gestureDetector.onTouchEvent(event!!)
    }
    
    when (event?.action) {
        MotionEvent.ACTION_DOWN -> {
            pressedKey = detectKeyAt(event.x, event.y)
            flickListener?.onFlick(GestureType.Down, pressedKey, null)
        }
        MotionEvent.ACTION_MOVE -> {
            val gesture = getGestureType(event)
            if (gesture != GestureType.Null) {
                setFlickInActionMove(gesture)
            }
        }
        MotionEvent.ACTION_UP -> {
            val finalGesture = getGestureType(event)
            currentKeyInfo?.let { info ->
                flickListener?.onFlick(finalGesture, pressedKey, 
                    info.flickFor(finalGesture))
            }
        }
    }
    return true
}

```

## Summary

- **Sumire** is defined as `TenKeyQWERTYMode.Sumire` in the core domain state, serving as the dedicated tablet mode in the JapaneseKeyboard hierarchy.
- **Layout initialization** occurs in [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt) through `createNewKeyboardLayoutForSumire()`, which makes the tablet view visible and registers shared listeners.
- **Gesture consistency** is maintained by reusing the same `FlickListener` and `LongPressListener` interfaces across all keyboard modes.
- **Enhanced detection** in [`TabletKeyboardView.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/TabletKeyboardView.kt) includes a `GestureDetector` for double-tap shortcuts in English mode and custom vector analysis for flick directions.
- **Multi-touch support** handles two-finger gestures for small dakuten and handakuten inputs, identical to the ten-key implementation.

## Frequently Asked Questions

### How does Sumire detect tablet mode versus phone mode?

The IME checks the `TenKeyQWERTYMode` state in [`IMEService.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/IMEService.kt). When `qwertyMode.value == TenKeyQWERTYMode.Sumire`, the system calls `createNewKeyboardLayoutForSumire()` instead of the standard phone layout methods, inflating `TabletKeyboardView` rather than the compact mobile views.

### What gesture types does the Sumire tablet layout support?

Sumire supports **flick gestures** (up, down, left, right), **tap**, **long-press**, and **double-tap** (specifically for caps-lock toggle on the period key in English mode). It also handles **two-finger gestures** for small dakuten and handakuten character inputs, maintaining feature parity with the ten-key layout.

### Where is the gesture detection logic implemented in the source code?

The primary implementation resides in [`tabletkey/src/main/java/com/kazumaproject/tabletkey/TabletKeyboardView.kt`](https://github.com/kazumaproject/japanesekeyboard/blob/main/tabletkey/src/main/java/com/kazumaproject/tabletkey/TabletKeyboardView.kt) between lines 707 and 1082. Key methods include `onTouch()` (line 998), `getGestureType()` for vector analysis, and `setFlickActionPointerDown()` for multi-touch handling.

### Does Sumire use different listeners than the standard QWERTY keyboard?

No. Sumire registers the same `FlickListener` and `LongPressListener` instances used by the ten-key and QWERTY keyboards via `setOnFlickListener()` and `setOnLongPressListener()`. This design ensures consistent behavior and reduces code duplication across the different input modes.