Space swipe to toggle numpad layout, with side bonuses (#950)

* make the numpad key toggle-based, allowing for use in its own layout. it also remembers the symbols-shift state.
* add space swipe gesture to toggle the numpad
* fix sliding key input for the numpad key bugs
This commit is contained in:
Devy Ballard 2024-07-09 14:26:23 -06:00 committed by GitHub
parent 309d7f299e
commit 105d044aa8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 129 additions and 38 deletions

View file

@ -41,9 +41,9 @@
[
{ "label": "alpha" },
{ "label": "comma", "width": 0.1 },
{ "label": "symbol", "type": "character", "width": 0.12 },
{ "label": "symbol", "width": 0.12 },
{ "label": "0", "type": "numeric" },
{ "label": "=", "width": 0.12, "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } },
{ "label": "=", "type": "function", "width": 0.12, "popup": { "relevant": [ { "label": "≠"}, { "label": "≈"} ] } },
{ "label": "period", "width": 0.1 },
{ "label": "action" }
]

View file

@ -515,8 +515,11 @@ public class Key implements Comparable<Key> {
}
public final boolean isModifier() {
return mCode == KeyCode.SHIFT || mCode == KeyCode.SYMBOL_ALPHA || mCode == KeyCode.ALPHA || mCode == KeyCode.SYMBOL
|| mCode == KeyCode.CTRL || mCode == KeyCode.ALT || mCode == KeyCode.FN || mCode == KeyCode.META;
return switch (mCode) {
case KeyCode.SHIFT, KeyCode.SYMBOL_ALPHA, KeyCode.ALPHA, KeyCode.SYMBOL, KeyCode.NUMPAD, KeyCode.CTRL,
KeyCode.ALT, KeyCode.FN, KeyCode.META -> true;
default -> false;
};
}
public final boolean isRepeatable() {

View file

@ -97,6 +97,7 @@ public interface KeyboardActionListener {
*/
boolean onHorizontalSpaceSwipe(int steps);
boolean onVerticalSpaceSwipe(int steps);
boolean toggleNumpad(boolean withSliding, boolean forceReturnToAlpha);
void onMoveDeletePointer(int steps);
void onUpWithDeletePointerActive();
@ -107,6 +108,7 @@ public interface KeyboardActionListener {
int SWIPE_NO_ACTION = 0;
int SWIPE_MOVE_CURSOR = 1;
int SWIPE_SWITCH_LANGUAGE = 2;
int SWIPE_TOGGLE_NUMPAD = 3;
class Adapter implements KeyboardActionListener {
@Override
@ -142,6 +144,10 @@ public interface KeyboardActionListener {
return false;
}
@Override
public boolean toggleNumpad(boolean withSliding, boolean forceReturnToAlpha) {
return false;
}
@Override
public void onMoveDeletePointer(int steps) {}
@Override
public void onUpWithDeletePointerActive() {}

View file

@ -71,15 +71,22 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp
override fun onHorizontalSpaceSwipe(steps: Int): Boolean = when (Settings.getInstance().current.mSpaceSwipeHorizontal) {
KeyboardActionListener.SWIPE_MOVE_CURSOR -> onMoveCursorHorizontally(steps)
KeyboardActionListener.SWIPE_SWITCH_LANGUAGE -> onLanguageSlide(steps)
KeyboardActionListener.SWIPE_TOGGLE_NUMPAD -> toggleNumpad(false, false)
else -> false
}
override fun onVerticalSpaceSwipe(steps: Int): Boolean = when (Settings.getInstance().current.mSpaceSwipeVertical) {
KeyboardActionListener.SWIPE_MOVE_CURSOR -> onMoveCursorVertically(steps)
KeyboardActionListener.SWIPE_SWITCH_LANGUAGE -> onLanguageSlide(steps)
KeyboardActionListener.SWIPE_TOGGLE_NUMPAD -> toggleNumpad(false, false)
else -> false
}
override fun toggleNumpad(withSliding: Boolean, forceReturnToAlpha: Boolean): Boolean {
KeyboardSwitcher.getInstance().toggleNumpad(withSliding, latinIME.currentAutoCapsState, latinIME.currentRecapitalizeState, forceReturnToAlpha)
return true
}
override fun onMoveDeletePointer(steps: Int) {
inputLogic.finishInput()
val end = inputLogic.mConnection.expectedSelectionEnd

View file

@ -370,6 +370,15 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
setKeyboard(KeyboardId.ELEMENT_NUMPAD, KeyboardSwitchState.OTHER);
}
@Override
public void toggleNumpad(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode,
final boolean forceReturnToAlpha) {
if (DEBUG_ACTION) {
Log.d(TAG, "toggleNumpad");
}
mState.toggleNumpad(withSliding, autoCapsFlags, recapitalizeMode, forceReturnToAlpha, true);
}
public enum KeyboardSwitchState {
HIDDEN(-1),
SYMBOLS_SHIFTED(KeyboardId.ELEMENT_SYMBOLS_SHIFTED),

View file

@ -268,7 +268,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
// primaryCode is different from {@link Key#mKeyCode}.
private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x,
final int y, final long eventTime, final boolean isKeyRepeat) {
final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier();
final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier()
&& key.getCode() != KeyCode.NUMPAD; // we allow for the numpad to be toggled from sliding input
final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState() && !isClearlyInsideKey(key, x, y);
final int code = altersCode ? key.getAltCode() : primaryCode;
if (DEBUG_LISTENER) {
@ -879,6 +880,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
}
}
private boolean oneShotSwipe(final int swipeSetting) {
return switch (swipeSetting) {
case KeyboardActionListener.SWIPE_NO_ACTION, KeyboardActionListener.SWIPE_TOGGLE_NUMPAD -> true;
default -> false;
};
}
private void onKeySwipe(final int code, final int x, final int y, final long eventTime) {
final SettingsValues sv = Settings.getInstance().getCurrent();
final int fastTypingTimeout = 2 * sv.mKeyLongpressTimeout / 3;
@ -896,7 +904,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
if (!mInVerticalSwipe) {
sTimerProxy.cancelKeyTimersOf(this);
mInVerticalSwipe = true;
}
} else if (oneShotSwipe(sv.mSpaceSwipeVertical)) return;
if (sListener.onVerticalSpaceSwipe(stepsY)) {
mStartY += stepsY * sPointerStep;
}
@ -909,7 +917,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
if (!mInHorizontalSwipe) {
sTimerProxy.cancelKeyTimersOf(this);
mInHorizontalSwipe = true;
}
} else if (oneShotSwipe(sv.mSpaceSwipeHorizontal)) return;
if (sListener.onHorizontalSpaceSwipe(stepsX)) {
mStartX += stepsX * sPointerStep;
}
@ -1105,7 +1113,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
}
}
if (code == KeyCode.SYMBOL_ALPHA && Settings.getInstance().getCurrent().mLongPressSymbolsForNumpad) {
sListener.onCodeInput(KeyCode.NUMPAD, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false);
// toggle numpad with sliding input enabled, forcing return to the alpha layout when done
sListener.toggleNumpad(true, true);
return;
}

View file

@ -52,7 +52,6 @@ public final class KeyboardCodesSet {
"key_emoji",
"key_unspecified",
"key_clipboard",
"key_numpad",
"key_start_onehanded",
"key_stop_onehanded",
"key_switch_onehanded"
@ -78,7 +77,6 @@ public final class KeyboardCodesSet {
KeyCode.EMOJI,
KeyCode.NOT_SPECIFIED,
KeyCode.CLIPBOARD,
KeyCode.NUMPAD,
KeyCode.START_ONE_HANDED_MODE,
KeyCode.STOP_ONE_HANDED_MODE,
KeyCode.SWITCH_ONE_HANDED_MODE

View file

@ -57,7 +57,6 @@ class KeyboardIconsSet {
const val NAME_CLIPBOARD_NORMAL_KEY = "clipboard_normal_key"
const val NAME_CLEAR_CLIPBOARD_KEY = "clear_clipboard_key"
const val NAME_CUT_KEY = "cut_key"
const val NAME_NUMPAD_KEY = "numpad_key"
const val NAME_START_ONEHANDED_KEY = "start_onehanded_mode_key"
const val NAME_STOP_ONEHANDED_KEY = "stop_onehanded_mode_key"
const val NAME_SWITCH_ONEHANDED_KEY = "switch_onehanded_key"
@ -90,7 +89,6 @@ class KeyboardIconsSet {
NAME_CLIPBOARD_NORMAL_KEY to R.styleable.Keyboard_iconClipboardNormalKey,
NAME_CLEAR_CLIPBOARD_KEY to R.styleable.Keyboard_iconClearClipboardKey,
NAME_CUT_KEY to R.styleable.Keyboard_iconCutKey,
NAME_NUMPAD_KEY to R.styleable.Keyboard_iconNumpadKey,
NAME_START_ONEHANDED_KEY to R.styleable.Keyboard_iconStartOneHandedMode,
NAME_STOP_ONEHANDED_KEY to R.styleable.Keyboard_iconStopOneHandedMode,
NAME_SWITCH_ONEHANDED_KEY to R.styleable.Keyboard_iconSwitchOneHandedMode,

View file

@ -47,6 +47,8 @@ public final class KeyboardState {
void setEmojiKeyboard();
void setClipboardKeyboard();
void setNumpadKeyboard();
void toggleNumpad(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode,
final boolean forceReturnToAlpha);
void setSymbolsKeyboard();
void setSymbolsShiftedKeyboard();
@ -81,7 +83,8 @@ public final class KeyboardState {
private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 4;
private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 5;
private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 6;
private static final int SWITCH_STATE_MOMENTARY_FROM_NUMPAD = 7;
private static final int SWITCH_STATE_MOMENTARY_TO_NUMPAD = 7;
private static final int SWITCH_STATE_MOMENTARY_FROM_NUMPAD = 8;
private int mSwitchState = SWITCH_STATE_ALPHA;
private static final int MODE_ALPHABET = 0;
@ -90,6 +93,7 @@ public final class KeyboardState {
private static final int MODE_CLIPBOARD = 3;
private static final int MODE_NUMPAD = 4;
private int mMode = MODE_ALPHABET;
private int mModeBeforeNumpad = MODE_ALPHABET;
private boolean mIsSymbolShifted;
private boolean mPrevMainKeyboardWasShiftLocked;
private boolean mPrevSymbolsKeyboardWasShifted;
@ -203,7 +207,8 @@ public final class KeyboardState {
return;
}
if (state.mMode == MODE_NUMPAD) {
setNumpadKeyboard();
// don't overwrite toggle state if reloading from orientation change, etc.
setNumpadKeyboard(false, false, false);
return;
}
// Symbol mode
@ -379,17 +384,57 @@ public final class KeyboardState {
mSwitchActions.setClipboardKeyboard();
}
private void setNumpadKeyboard() {
private void setNumpadKeyboard(final boolean withSliding, final boolean forceReturnToAlpha,
final boolean rememberState) {
if (DEBUG_INTERNAL_ACTION) {
Log.d(TAG, "setNumpadKeyboard");
}
if (rememberState) {
if (mMode == MODE_ALPHABET) {
// Remember caps lock mode and reset alphabet shift state.
mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
mAlphabetShiftState.setShiftLocked(false);
} else if (mMode == MODE_SYMBOLS) {
// Remember symbols shifted state
mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
} // When d-pad is added, "selection mode" may need to be remembered if not a global state
mModeBeforeNumpad = forceReturnToAlpha ? MODE_ALPHABET : mMode;
}
mMode = MODE_NUMPAD;
mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
// Remember caps lock mode and reset alphabet shift state.
mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
mAlphabetShiftState.setShiftLocked(false);
mSwitchActions.setNumpadKeyboard();
mSwitchState = SWITCH_STATE_NUMPAD;
mSwitchState = withSliding ? SWITCH_STATE_MOMENTARY_TO_NUMPAD : SWITCH_STATE_NUMPAD;
}
public void toggleNumpad(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode,
final boolean forceReturnToAlpha, final boolean rememberState) {
if (DEBUG_INTERNAL_ACTION) {
Log.d(TAG, "toggleNumpad");
}
if (mMode != MODE_NUMPAD) setNumpadKeyboard(withSliding, forceReturnToAlpha, rememberState);
else {
if (mModeBeforeNumpad == MODE_ALPHABET || forceReturnToAlpha) {
setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
if (mPrevMainKeyboardWasShiftLocked) {
setShiftLocked(true);
}
mPrevMainKeyboardWasShiftLocked = false;
} else switch (mModeBeforeNumpad) {
case MODE_SYMBOLS -> {
if (mPrevSymbolsKeyboardWasShifted) {
setSymbolsShiftedKeyboard();
} else {
setSymbolsKeyboard();
}
mPrevSymbolsKeyboardWasShifted = false;
}
// toggling numpad and emoji layout isn't actually possible yet due to lack of toolbar
// keys or key-swipes in that layout, but included for safety.
case MODE_EMOJI -> setEmojiKeyboard();
case MODE_CLIPBOARD -> setClipboardKeyboard();
}
if (withSliding) mSwitchState = SWITCH_STATE_MOMENTARY_FROM_NUMPAD;
}
}
private void setOneHandedModeEnabled(boolean enabled) {
@ -430,6 +475,9 @@ public final class KeyboardState {
} else if (code == KeyCode.ALPHA) {
// don't start sliding, causes issues with fully customizable layouts
// (also does not allow chording, but can be fixed later)
} else if (code == KeyCode.NUMPAD) {
// don't start sliding, causes issues with fully customizable layouts
// (also does not allow chording, but can be fixed later)
} else {
mShiftKeyState.onOtherKeyPressed();
mSymbolKeyState.onOtherKeyPressed();
@ -459,17 +507,17 @@ public final class KeyboardState {
+ " sliding=" + withSliding
+ " " + stateToString(autoCapsFlags, recapitalizeMode));
}
if (code == KeyCode.SHIFT) {
onReleaseShift(withSliding, autoCapsFlags, recapitalizeMode);
} else if (code == KeyCode.CAPS_LOCK) {
setShiftLocked(!mAlphabetShiftState.isShiftLocked());
} else if (code == KeyCode.SYMBOL_ALPHA) {
onReleaseAlphaSymbol(withSliding, autoCapsFlags, recapitalizeMode);
} else if (code == KeyCode.SYMBOL) {
onReleaseSymbol(withSliding, autoCapsFlags, recapitalizeMode);
} else if (code == KeyCode.ALPHA) {
onReleaseAlpha(withSliding, autoCapsFlags, recapitalizeMode);
}
switch (code) {
case KeyCode.SHIFT -> onReleaseShift(withSliding, autoCapsFlags, recapitalizeMode);
case KeyCode.CAPS_LOCK -> setShiftLocked(!mAlphabetShiftState.isShiftLocked());
case KeyCode.SYMBOL_ALPHA -> onReleaseAlphaSymbol(withSliding, autoCapsFlags, recapitalizeMode);
case KeyCode.SYMBOL -> onReleaseSymbol(withSliding, autoCapsFlags, recapitalizeMode);
case KeyCode.ALPHA -> onReleaseAlpha(withSliding, autoCapsFlags, recapitalizeMode);
case KeyCode.NUMPAD -> {
// if no sliding, toggling is instead handled by {@link #onEvent} to accommodate toolbar key.
// also prevent sliding to clipboard layout, which isn't supported yet.
if (withSliding) setNumpadKeyboard(true, mModeBeforeNumpad == MODE_CLIPBOARD, true);
}}
}
private void onPressAlphaSymbol(final int autoCapsFlags, final int recapitalizeMode) {
@ -678,12 +726,14 @@ public final class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onFinishSlidingInput: " + stateToString(autoCapsFlags, recapitalizeMode));
}
// Switch back to the previous keyboard mode if the user cancels sliding input.
switch (mSwitchState) {
// Switch back to the previous keyboard mode if the user didn't enter the numpad.
if (mMode != MODE_NUMPAD) switch (mSwitchState) {
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL -> toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode);
case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE -> toggleShiftInSymbols();
case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT -> setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> setNumpadKeyboard();
case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> setNumpadKeyboard(false, false, false);
} else if (mSwitchState == SWITCH_STATE_MOMENTARY_TO_NUMPAD) {
toggleNumpad(false, autoCapsFlags, recapitalizeMode, false, false);
}
}
@ -763,7 +813,7 @@ public final class KeyboardState {
setClipboardKeyboard();
}
} else if (code == KeyCode.NUMPAD) {
setNumpadKeyboard();
toggleNumpad(false, autoCapsFlags, recapitalizeMode, false, true);
} else if (code == KeyCode.SYMBOL) {
setSymbolsKeyboard();
} else if (code == KeyCode.START_ONE_HANDED_MODE) {
@ -793,6 +843,7 @@ public final class KeyboardState {
case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE -> "MOMENTARY-SYMBOL-MORE";
case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT -> "MOMENTARY-ALPHA_SHIFT";
case SWITCH_STATE_NUMPAD -> "NUMPAD";
case SWITCH_STATE_MOMENTARY_TO_NUMPAD -> "MOMENTARY-TO-NUMPAD";
case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> "MOMENTARY-FROM-NUMPAD";
default -> null;
};

View file

@ -480,7 +480,6 @@ sealed interface KeyData : AbstractKeyData {
// todo (later): label and popupKeys for .com should be in localeKeyTexts, handled similar to currency key
KeyLabel.COM -> ".com"
KeyLabel.LANGUAGE_SWITCH -> "!icon/language_switch_key|!code/key_language_switch"
KeyLabel.NUMPAD -> "!icon/numpad_key|!code/key_numpad"
KeyLabel.ZWNJ -> "!icon/zwnj_key|\u200C"
KeyLabel.CURRENCY -> params.mLocaleKeyboardInfos.currencyKey.first
KeyLabel.CURRENCY1 -> params.mLocaleKeyboardInfos.currencyKey.second[0]

View file

@ -381,6 +381,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return switch (prefs.getString(PREF_SPACE_HORIZONTAL_SWIPE, "none")) {
case "move_cursor" -> KeyboardActionListener.SWIPE_MOVE_CURSOR;
case "switch_language" -> KeyboardActionListener.SWIPE_SWITCH_LANGUAGE;
case "toggle_numpad" -> KeyboardActionListener.SWIPE_TOGGLE_NUMPAD;
default -> KeyboardActionListener.SWIPE_NO_ACTION;
};
}
@ -389,6 +390,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return switch (prefs.getString(PREF_SPACE_VERTICAL_SWIPE, "none")) {
case "move_cursor" -> KeyboardActionListener.SWIPE_MOVE_CURSOR;
case "switch_language" -> KeyboardActionListener.SWIPE_SWITCH_LANGUAGE;
case "toggle_numpad" -> KeyboardActionListener.SWIPE_TOGGLE_NUMPAD;
default -> KeyboardActionListener.SWIPE_NO_ACTION;
};
}

View file

@ -37,6 +37,7 @@ fun createToolbarKey(context: Context, keyboardAttr: TypedArray, key: ToolbarKey
fun getCodeForToolbarKey(key: ToolbarKey) = when (key) {
VOICE -> KeyCode.VOICE_INPUT
CLIPBOARD -> KeyCode.CLIPBOARD
NUMPAD -> KeyCode.NUMPAD
UNDO -> KeyCode.UNDO
REDO -> KeyCode.REDO
SETTINGS -> KeyCode.SETTINGS
@ -86,6 +87,7 @@ fun getCodeForToolbarKeyLongClick(key: ToolbarKey) = when (key) {
fun getStyleableIconId(key: ToolbarKey) = when (key) {
VOICE -> R.styleable.Keyboard_iconShortcutKey
CLIPBOARD -> R.styleable.Keyboard_iconClipboardNormalKey
NUMPAD -> R.styleable.Keyboard_iconNumpadKey
UNDO -> R.styleable.Keyboard_iconUndo
REDO -> R.styleable.Keyboard_iconRedo
SETTINGS -> R.styleable.Keyboard_iconSettingsKey
@ -125,8 +127,8 @@ fun getToolbarIconByName(name: String, context: Context): Drawable? {
// names need to be aligned with resources strings (using lowercase of key.name)
enum class ToolbarKey {
VOICE, CLIPBOARD, UNDO, REDO, SETTINGS, SELECT_ALL, SELECT_WORD, COPY, CUT, PASTE, ONE_HANDED, INCOGNITO,
AUTOCORRECT, CLEAR_CLIPBOARD, CLOSE_HISTORY, EMOJI, LEFT, RIGHT, UP, DOWN, WORD_LEFT, WORD_RIGHT,
VOICE, CLIPBOARD, NUMPAD, UNDO, REDO, SETTINGS, SELECT_ALL, SELECT_WORD, COPY, CUT, PASTE, ONE_HANDED,
INCOGNITO, AUTOCORRECT, CLEAR_CLIPBOARD, CLOSE_HISTORY, EMOJI, LEFT, RIGHT, UP, DOWN, WORD_LEFT, WORD_RIGHT,
PAGE_UP, PAGE_DOWN, FULL_LEFT, FULL_RIGHT, PAGE_START, PAGE_END
}

View file

@ -111,21 +111,25 @@
<string-array name="horizontal_space_swipe_values">
<item>move_cursor</item>
<item>switch_language</item>
<item>toggle_numpad</item>
<item>none</item>
</string-array>
<string-array name="horizontal_space_swipe_entries">
<item>@string/space_swipe_move_cursor_entry</item>
<item>@string/switch_language</item>
<item>@string/space_swipe_toggle_numpad_entry</item>
<item>@string/action_none</item>
</string-array>
<string-array name="vertical_space_swipe_values">
<item>move_cursor</item>
<item>switch_language</item>
<item>toggle_numpad</item>
<item>none</item>
</string-array>
<string-array name="vertical_space_swipe_entries">
<item>@string/space_swipe_move_cursor_entry</item>
<item>@string/switch_language</item>
<item>@string/space_swipe_toggle_numpad_entry</item>
<item>@string/action_none</item>
</string-array>
</resources>

View file

@ -248,6 +248,7 @@
<string name="clipboard" tools:keep="@string/clipboard">Clipboard</string>
<string name="clear_clipboard" tools:keep="@string/clear_clipboard">Clear clipboard</string>
<string name="voice" tools:keep="@string/voice">Voice input</string>
<string name="numpad" tools:keep="@string/numpad" translatable="false">@string/layout_numpad</string>
<string name="settings" tools:keep="@string/settings">Settings</string>
<string name="select_all" tools:keep="@string/select_all" translatable="false">@android:string/selectAll</string>
<string name="select_word" tools:keep="@string/select_word">Select word</string>
@ -858,6 +859,8 @@ New dictionary:
<string name="action_none">None</string>
<!-- Option to move the cursor when swiping the spacebar -->
<string name="space_swipe_move_cursor_entry">Move Cursor</string>
<!-- Option to toggle the numpad when swiping the spacebar -->
<string name="space_swipe_toggle_numpad_entry">Toggle Numpad</string>
<!-- Title of the setting for variable toolbar direction -->
<string name="var_toolbar_direction">Variable toolbar direction</string>
<!-- Description of the variable toolbar direction setting -->

View file

@ -83,7 +83,7 @@ Usually the label is what is displayed on the key. However, there are some speci
* _alpha_: switch to alphabet keyboard (or main phone keyboard in case of phone layout)
* _symbol_: switch to symbol keyboard (or phone symbols keyboard in case of phone layout)
* _symbol_alpha_: toggle alpha / symbol keyboard
* _numpad_: switch to numpad layout
* _numpad_: toggle numpad layout
* _emoji_: switch to emoji view
* _com_: display common TLDs (.com and similar, currently not localized)
* _language_switch_: language switch key