Skip to content
CleverKeys Wiki
implemented v1.2.7 User guide

Special Characters Technical Specification

Overview

Special character access through long-press popups, short swipe subkeys, and symbol keyboard layers.

Key Components

ComponentFilePurpose
KeyValueKeyValue.ktCharacter and action definitions
KeyModifierKeyModifier.ktModifier state handling
PointersPointers.kt:400-600Long-press and swipe detection
KeyboardDataKeyboardData.ktLayout and subkey definitions
KeyPopupKeyPopup.ktLong-press popup rendering

Subkey System

Each key can have up to 8 subkeys in cardinal and diagonal directions:

// KeyboardData.kt - Key definition structure
data class Key(
    val key0: KeyValue,      // Main key (tap)
    val key1: KeyValue?,     // North (swipe up)
    val key2: KeyValue?,     // North-East
    val key3: KeyValue?,     // East (swipe right)
    val key4: KeyValue?,     // South-East
    val key5: KeyValue?,     // South (swipe down)
    val key6: KeyValue?,     // South-West
    val key7: KeyValue?,     // West (swipe left)
    val key8: KeyValue?      // North-West
)

Layout XML Format

Subkeys defined in layout XML files (res/xml/):

<!-- Example: latn_qwerty_us.xml -->
<key
    key0="e"
    key1="3"
    key2="ê"
    key3="ë"
    key4="ē"
    key5="é"
    key6="è"
    key7="€"
    key8="ę" />

Long-Press Detection

// Pointers.kt:~450
private fun handleLongPress(ptr: Pointer) {
    if (ptr.flags and FLAG_P_LONG_PRESS == 0) {
        ptr.flags = ptr.flags or FLAG_P_LONG_PRESS
        val key = ptr.key
        if (key.hasSubkeys()) {
            showKeyPopup(key, ptr)
        }
    }
}

Character Categories

CategoryUnicode RangeExample
Latin ExtendedU+00C0-U+00FFàáâãäå
Latin Extended-AU+0100-U+017Fāăą
CurrencyU+20A0-U+20CF€£¥₹
Math OperatorsU+2200-U+22FF×÷±≠
General PunctuationU+2000-U+206F—–…

Configuration

SettingKeyDefault
Long-Press Timeoutlongpress_timeout400ms
Short Gesture Minshort_gesture_min_distance28%
Short Gesture Maxshort_gesture_max_distance65%

Modifier Interaction

Special characters interact with shift/caps lock:

// KeyValue.kt
fun withModifiers(mods: Int): KeyValue {
    return when {
        mods and MOD_SHIFT != 0 -> this.uppercase()
        else -> this
    }
}