Skip to content
CleverKeys Wiki
implemented v2.0.0 User guide

Extra Keys Technical Specification

Overview

Extra Keys configuration enables predefined actions and characters using per-key Boolean preferences. Layout placement uses KeyboardData.PreferredPos; it is not a separate left/right bottom-row list or a fixed spacebar-width calculation.

Key Components

ComponentSourceResponsibility
Catalogsrc/main/kotlin/tribixbite/cleverkeys/prefs/ExtraKeysPreference.kt:61110 predefined key identifiers
Categoriessrc/main/kotlin/tribixbite/cleverkeys/prefs/ExtraKeysPreference.kt:177Shared category partition consumed by the UI and completeness tests
Configuration screensrc/main/kotlin/tribixbite/cleverkeys/activities/ExtraKeysConfigActivity.kt:55Search, saved checkbox state, defaults and category rows
Rowsrc/main/kotlin/tribixbite/cleverkeys/activities/ExtraKeysConfigActivity.kt:217Resource-derived label, optional description, identifier and checkbox
Runtime preferencessrc/main/kotlin/tribixbite/cleverkeys/Config.kt:927Enabled predefined and custom extra-key maps
Placementsrc/main/kotlin/tribixbite/cleverkeys/KeyboardData.kt:48Preferred-position insertion and fallback

Preference Storage

ExtraKeysPreference.prefKeyOfKeyName (ExtraKeysPreference.kt:486) returns extra_key_<identifier>. Each predefined key stores a Boolean in DirectBootAwarePreferences, shared with the keyboard service. Missing values use defaultChecked (ExtraKeysPreference.kt:193), rather than one universal default.

Toggling a checkbox updates the screen’s state map and applies the corresponding preference immediately. Reset writes the catalog’s default Boolean for every key. Search and orientation changes do not alter enabled preferences.

getExtraKeys (ExtraKeysPreference.kt:475) converts enabled names into a map of KeyValue to KeyboardData.PreferredPos. Config.extra_keys_param holds this predefined map; extra_keys_custom is a separate custom-key map.

Search and Viewport Behavior

The query uses rememberSaveable (ExtraKeysConfigActivity.kt:71). Filtering matches identifiers, localized titles and optional localized descriptions, ignoring case. The activity renders ExtraKeysPreference.categorizedKeys; every advertised identifier must appear in exactly one category. Autofill belongs to System; Clear system clipboard belongs to Editing.

A single LazyColumn (ExtraKeysConfigActivity.kt:115) contains keyed search, summary and reset items followed by category and key items. Headers can scroll away to leave space for rows in landscape, split-screen or large-font configurations. The app bar remains outside the list. Query restoration and list scrolling do not toggle preferences.

Category items use category:<resource ID> keys; key items use their identifiers (ExtraKeysConfigActivity.kt:200). Row labels derive from the current key/resources rather than unkeyed remembered labels, preventing stale titles after filtering or recycling.

Layout Placement

LayoutModifier.kt:45 combines predefined/custom extras with the mandatory configuration key. It suppresses Next/Previous Layout extras with one enabled layout, computes locale extras when the layout permits them, and removes keys already present before calling KeyboardData.addExtraKeys (LayoutModifier.kt:108).

KeyboardData.PreferredPos (KeyboardData.kt:416) specifies an optional neighboring key and ordered row/column/direction candidates. A value of -1 leaves a coordinate unspecified. addExtraKeys tries each preferred position; unplaced keys then try PreferredPos.ANYWHERE. Placement is limited by available slots, so an enabled preference is not a guarantee of a new visible key on every layout.

There is no ExtraKeysManager enum, extra_keys_left/extra_keys_right storage, six-key hard cap or percentage-based spacebar sizing in this implementation. Extra-key actions use the existing KeyValue input pipeline and layout/subkey behavior.

Test Coverage

SuiteSourceProtected behavior
Hostsrc/test/kotlin/tribixbite/cleverkeys/prefs/AndroidXPreferenceMigrationTest.ktCatalog completeness and Autofill classification
Composesrc/androidTest/kotlin/tribixbite/cleverkeys/ExtraKeysConfigActivityComposeTest.ktSearch, labels, reset reachability, opt-in system-clear row, Autofill visibility, landscape row access and query recreation
SeekerRecorded in memory/todo.mdMinified-build identifier/title search, unchanged enabled count, landscape scrolling and rotation retention