Compare commits

..

18 Commits

Author SHA1 Message Date
8662f3afd4 Ignore presses too close from an other pointer
These might be gliches.
2022-03-16 12:35:14 +01:00
2dae2105b2 Brazilian portuguese layout (#91)
* Providing a comprehensible Brazilian Portuguese keyboard layout

removed cedille as it is already provided by an independent key;
changed layout to correspond to the locale
2022-03-15 21:05:16 +01:00
d53ee811d9 Handle CANCEL touch events
Handling this event is part of the API but was never done. This caused
unstoppable key-repeat.

This event isn't common, the only way I found on Android 10 is to switch
to the emoji keyboard while holding a key. Some apps might cause this
event more often.
2022-03-15 20:44:02 +01:00
fadedfd58f Add Swedish layout 2022-03-15 18:42:29 +01:00
f9cd4ca2d8 Log editor infos while debugging
Useful when debugging why the keyboard doesn't work as expected with a
specific app.
2022-03-15 18:42:29 +01:00
9bb7c7e66f Identify debug version in app name
Using the --product option of aapt.

Remove the app name from translations because it is never translated. It
is still possible to translate it by specifying 'product="default"'.
2022-03-14 18:37:37 +01:00
f4978f5266 Fix crash since 2ea256e 2022-03-13 00:45:16 +01:00
a0d90496c1 Improve symbols for Sup, Sub and Ord 2022-03-13 00:43:11 +01:00
7aa241b10a Make superscript and subscript modifiers lockable 2022-03-13 00:40:39 +01:00
a57bdf8cfb Avoid showing some symbols twice in Fn mode 2022-03-13 00:35:15 +01:00
ee6e892ef4 Define localized keys as a set instead of flags
Using flags for removing keys like € and ß need too many flags and won't
scale to more localized keys.
2022-03-13 00:14:18 +01:00
2ea256e769 Fix inconsistent highlighting of lockable keys
Pointers.getKeyFlags might receive a different KeyValue than what's
stored in the pointer due to caching. Compare names instead.
2022-03-12 21:38:47 +01:00
5665d6a7c5 Brazilian portuguese translations (#100)
* Translations for new setting, lockable modifier keys

Co-authored-by: Igor da Silva de Carvalho <igu@coiso.meanhouse>
2022-03-09 10:49:13 +01:00
534e4cb843 Make the font smaller for the action key 2022-03-06 19:36:09 +01:00
e303008e66 Fix action key not updating when switching field
The keyboard was updated before the action key is.
2022-03-05 20:21:37 +01:00
5404e7432d Clicking twice on CTRL or ALT will lock them in 'ON' state (#72)
* Clicking twice on CTRL or ALT will lock them in 'ON' state

* Make Locking behaviour optional, configurable in preferences

* Nest the new settings into a different page

To avoid spamming the settings page and repetition in the summaries.
Cannot be a popup unfortunately because that would require API >= 11.

* Add Fn and Meta

Co-authored-by: Jules Aguillon <jules@j3s.fr>
2022-03-05 20:17:45 +01:00
e92504ae92 Improve the code for dynamic updates of the layout 2022-03-05 19:22:01 +01:00
4964bfb87f Brazilian portuguese translations (#87)
* Added brazilian portuguese translations for app description and settings

* making the swiping option more intelligible

* fix typo on full_description pt-BR translation

Co-authored-by: Igor da Silva de Carvalho <igu@coiso.meanhouse>
2022-03-05 17:33:04 +01:00
24 changed files with 390 additions and 217 deletions

View File

@ -3,7 +3,7 @@
PACKAGE_NAME = juloo.keyboard2
ANDROID_PLATFORM_VERSION = android-30
JAVA_VERSION = 1.7
JAVA_VERSION = 1.8
SRC_DIR = srcs
ASSETS_DIR = assets
@ -19,7 +19,11 @@ release: _build/$(PACKAGE_NAME).apk
installd: _build/$(PACKAGE_NAME).debug.apk
adb install "$<"
.PHONY: release debug installd
clean:
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
_build/*.idsig
.PHONY: release debug installd clean
$(shell mkdir -p _build)
@ -60,7 +64,7 @@ _build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
# Debug apk
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug --product debug
# Release signing

View File

@ -0,0 +1,18 @@
Um teclado virtual para aparelhos Android. Os recursos principais são facilidade de digitar todos os caracteres ASCII deslizando o dedo, teclas "mortas" para acentos e teclas modificadoras e a presença de teclas especiais (tab, esc, setas, etc..).
O teclado mostra até 4 caracteres extras nos cantos de cada tecla. Esses caracteres são digitáveis com o deslizar do dedo na tecla.
Alguns dos recursos interessantes:
- Todos caracteres e teclas especiais que também estão disponíveis num teclado de PC. Perfeito para usar com aplicativos como Termux.
- Incluindo Tab, Esc, as setas e teclas de função, e também Ctrl e Alt!
- Caracteres acentuados são digitáveis usando teclas "mortas". Primeiro ative o acento e depois digite a letra.
- Muito leve e rápido. Ocupa 500x menos espaço que o teclado da Google e 15x menos espaço que o teclado padrão. Sem propaganda, sem rastreio.
- Vários layouts: QWERTY, QWERTZ, AZERTY. Temas: Branco, Escuro, Preto OLED. E muitas outras opções.
Como qualquer outro teclado virtual, tem de ser ativado nas configurações de sistema. Abra as configurações e vá para:
Sistema > Idioma e entrada > Teclado virtual > Gerenciar teclados virtuais.

View File

@ -0,0 +1 @@
Um teclado virtual leve para desenvolvedores.

View File

@ -0,0 +1 @@
Unexpected Keyboard

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard - Einstellungen</string>
<string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Tastaturlayout ändern</string>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Ajustes de Unexpected Keyboard</string>
<string name="pref_category_layout">Formato</string>
<string name="pref_layout_title">Cambiar formato de teclado</string>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard Paramètres</string>
<string name="pref_category_layout">Disposition</string>
<string name="pref_layout_title">Disposition des touches</string>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard iestatījumi</string>
<string name="pref_category_layout">Izkārtojums</string>
<string name="pref_layout_title">Mainīt tastatūras izkārtojumu</string>

49
res/values-pt/strings.xml Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="settings_activity_label">Configurações Unexpected Keyboard</string>
<string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Mudar layout do teclado</string>
<string name="pref_layout_e_system">Mesmo do sistema</string>
<string name="pref_accents_title">Acentos</string>
<string name="pref_accents_e_all_installed">Mostrar acentos para todos idiomas instalados</string>
<string name="pref_accents_e_selected">Mostrar acentos só para o idioma selecionado</string>
<string name="pref_accents_e_all">Mostrar todos acentos</string>
<string name="pref_accents_e_none">Esconder acentos</string>
<string name="pref_category_typing">Digitação</string>
<string name="pref_swipe_dist_title">Distância a deslizar</string>
<string name="pref_swipe_dist_summary">Distância até acionar os cantos das teclas (%s)</string>
<string name="pref_long_timeout_title">Tempo até repetir tecla</string>
<string name="pref_long_interval_title">Intervalo para repetir tecla</string>
<string name="pref_category_vibrate">Vibração</string>
<string name="pref_vibrate_title">Vibração</string>
<string name="pref_vibrate_summary">Ativar/desativar vibração ao digitar</string>
<string name="pref_vibrate_duration_title">Duração</string>
<string name="pref_precise_repeat_title">Precisão nos movimentos do cursor</string>
<string name="pref_precise_repeat_summary">Varia a velocidade de repetição ao depender de quanto deslizar</string>
<string name="pref_lockable_keys_title">Segurar teclas</string>
<string name="pref_lockable_keys_summary">Teclas que podem ficar seguradas ao teclar duas vezes</string>
<string name="pref_category_style">Estilo</string>
<string name="pref_margin_bottom_title">Margem de baixo</string>
<string name="pref_keyboard_height_title">Altura do teclado</string>
<string name="pref_horizontal_margin_title">Margem horizontal</string>
<string name="pref_character_size_title">Tamanho dos indicadores</string>
<string name="pref_character_size_summary">Tamanho dos caracteres visíveis no teclado (%.2fx)</string>
<string name="pref_theme">Tema</string>
<string name="pref_theme_e_system">Mesmo do sistema</string>
<string name="pref_theme_e_dark">Escuro</string>
<string name="pref_theme_e_light">Claro</string>
<string name="pref_theme_e_black">Preto</string>
<string name="pref_swipe_dist_e_very_short">Muito curto</string>
<string name="pref_swipe_dist_e_short">Curto</string>
<string name="pref_swipe_dist_e_default">Normal</string>
<string name="pref_swipe_dist_e_far">Longo</string>
<string name="pref_swipe_dist_e_very_far">Muito longo</string>
<string name="pref_key_horizontal_space">Distância horizontal entre teclas</string>
<string name="pref_key_vertical_space">Distância vertical entre teclas</string>
<string name="key_action_next">Próximo</string>
<string name="key_action_done">Pronto</string>
<string name="key_action_go">Ir</string>
<string name="key_action_prev">Anterior</string>
<string name="key_action_search">Buscar</string>
<string name="key_action_send">Enviar</string>
</resources>

View File

@ -4,8 +4,10 @@
<item>system</item>
<item>azerty</item>
<item>qwerty</item>
<item>qwerty_pt</item>
<item>qwerty_es</item>
<item>qwerty_lv</item>
<item>qwerty_sv_se</item>
<item>ru_jcuken</item>
<item>qwertz</item>
<item>bgph1</item>
@ -15,8 +17,10 @@
<item>@string/pref_layout_e_system</item>
<item>AZERTY</item>
<item>QWERTY</item>
<item>QWERTY (Brasileiro)</item>
<item>QWERTY (Español)</item>
<item>QWERTY (Latvian)</item>
<item>QWERTY (Swedish)</item>
<item>ЙЦУКЕН (Русский)</item>
<item>QWERTZ</item>
<item>Bulgarian (Phonetic Traditional)</item>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="app_name" product="debug">Unexpected Keyboard (debug)</string>
<string name="app_name" product="default">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard Settings</string>
<string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Change keyboard layout</string>
@ -21,6 +22,8 @@
<string name="pref_vibrate_duration_title">Duration</string>
<string name="pref_precise_repeat_title">Precise cursor movements</string>
<string name="pref_precise_repeat_summary">Modulate key repeat speed by swiping more or less</string>
<string name="pref_lockable_keys_title">Lockable modifiers</string>
<string name="pref_lockable_keys_summary">Modifier that can be locked by typing them twice</string>
<string name="pref_category_style">Style</string>
<string name="pref_margin_bottom_title">Margin bottom</string>
<string name="pref_keyboard_height_title">Keyboard height</string>

View File

@ -13,4 +13,7 @@
<dimen name="emoji_grid_height">250dp</dimen>
<dimen name="emoji_text_size">28dp</dimen>
<dimen name="extra_horizontal_margin">0dp</dimen>
<bool name="debug_logs" product="debug">true</bool>
<bool name="debug_logs" product="default">false</bool>
<dimen name="pointer_too_close">10dp</dimen>
</resources>

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys=euro"/>
<subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz,extra_keys=trema|szlig|euro"/>
<subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=pound|euro"/>
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys="/>
<subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz,extra_keys=accent_trema|ß|€"/>
<subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=£|€"/>
<subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty"/>
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_es,extra_keys=grave|aigu|tilde|trema|euro"/>
<subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=azerty,extra_keys=grave|aigu|circonflexe|cedille|trema|euro"/>
<subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=grave|aigu|euro"/>
<subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_lv,extra_keys=caron|cedille|macron|euro"/>
<subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=aigu|cedille|circonflexe|grave|tilde|euro"/>
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_es,extra_keys=accent_grave|accent_aigu|accent_tilde|accent_trema|"/>
<subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=azerty,extra_keys=accent_grave|accent_aigu|accent_circonflexe|accent_cedille|accent_trema|"/>
<subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=accent_grave|accent_aigu|€"/>
<subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_lv,extra_keys=accent_caron|accent_cedille|accent_macron|"/>
<subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_pt,extra_keys=accent_aigu|accent_cedille|accent_circonflexe|accent_grave|accent_tilde|"/>
<subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=ru_jcuken"/>
<subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=aigu|trema|ring|euro"/>
<subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_sv_se,extra_keys=accent_aigu|accent_trema|accent_ring|"/>
</input-method>

38
res/xml/qwerty_pt.xml Normal file
View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key1="esc" key2="1" key3="~" key4="!"/>
<key key0="w" key2="2" key3="\@"/>
<key key0="e" key1="£" key2="3" key3="\#" key4="€"/>
<key key0="r" key2="4" key3="$"/>
<key key0="t" key2="5" key3="%"/>
<key key0="y" key1="accent_caron" key2="6" key3="^" key4="accent_trema"/>
<key key0="u" key2="7" key3="&amp;"/>
<key key0="i" key2="8" key3="*"/>
<key key0="o" key2="9" key3="(" key4=")"/>
<key key0="p" key2="0" key3="\\" key4="|"/>
</row>
<row>
<key key0="a" key1="tab" key2="'" key3="`" key4="&quot;"/>
<key key0="s" key1="accent_ring" key2="accent_caron" key3="ß" key4="accent_cedille"/>
<key key0="d"/>
<key key0="f"/>
<key key0="g"/>
<key key0="h"/>
<key key0="j" key1="-" key2="=" key4="+" key3="_"/>
<key key0="k" key1="accent_grave" key2="accent_aigu" key3="accent_tilde" key4="accent_circonflexe"/>
<key key0="l" key1="[" key2="]" key3="{" key4="}"/>
<key key0="ç"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="z"/>
<key key0="x"/>
<key key0="c"/>
<key key0="v"/>
<key key0="b"/>
<key key0="n" key1="&lt;" key2="&gt;" key3="," key4="."/>
<key key0="m" key1=":" key2=";" key3="/" key4="\?"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

42
res/xml/qwerty_sv_se.xml Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key1="esc" key2="1"/>
<key key0="w" key2="2" key4="\@"/>
<key key0="e" key2="3" key4="\#" key3="€"/>
<key key0="r" key2="4" key4="$"/>
<key key0="t" key2="5" key3="&amp;" key4="|" />
<key key0="y" key2="6" key3="^" key4="%"/>
<key key0="u" key2="7" key3="~" key4="\\" />
<key key0="i" key2="8" key3="*" key4="/" />
<key key0="o" key2="9" key3="+" key4="-"/>
<key key0="p" key2="0" key3="=" />
<key key0="å" key1="\?" key3="!" key2="`" />
</row>
<row>
<key key0="a" key1="tab" />
<key key0="s" key1="accent_ring" key2="accent_cedille" key3="ß" key4="accent_tilde"/>
<key key0="d" key1="accent_grave" key2="accent_caron" key3="accent_aigu"/>
<key key0="f" key1="accent_trema" key2="accent_circonflexe"/>
<key key0="g" />
<key key0="h" />
<key key0="j" key1="{" key4="}" />
<key key0="k" key1="[" key4="]" />
<key key0="l" key1="(" key4=")" />
<key key0="ö" key1="&lt;" key4="&gt;" />
<key key0="ä" key1="'" key3="&quot;"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="z" />
<key key0="x" />
<key key0="c" />
<key key0="v" />
<key key0="b" key2=";" key4=","/>
<key key0="n" key2=":" key4="."/>
<key key0="m" key2="-" key4="_"/>
<key width="1.0" key0="." key1="!" key2="\?" key3="'" key4="," />
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@ -9,6 +9,15 @@
<juloo.common.IntSlideBarPreference android:key="longpress_timeout" android:title="@string/pref_long_timeout_title" android:summary="%sms" android:defaultValue="600" min="50" max="2000"/>
<juloo.common.IntSlideBarPreference android:key="longpress_interval" android:title="@string/pref_long_interval_title" android:summary="%sms" android:defaultValue="25" min="5" max="100"/>
<CheckBoxPreference android:key="precise_repeat" android:title="@string/pref_precise_repeat_title" android:summary="@string/pref_precise_repeat_summary" android:defaultValue="true"/>
<PreferenceScreen android:title="@string/pref_lockable_keys_title" android:summary="@string/pref_lockable_keys_summary">
<CheckBoxPreference android:key="lockable_shift" android:title="Shift" android:defaultValue="true"/>
<CheckBoxPreference android:key="lockable_ctrl" android:title="Ctrl" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_alt" android:title="Alt" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_fn" android:title="Fn" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_meta" android:title="Meta" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_sup" android:title="Sup" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_sub" android:title="Sub" android:defaultValue="false"/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_vibrate">
<CheckBoxPreference android:key="vibrate_enabled" android:title="@string/pref_vibrate_title" android:summary="@string/pref_vibrate_summary" android:defaultValue="true"/>

View File

@ -8,15 +8,19 @@ import android.os.Build;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.KeyEvent;
import java.util.Set;
import java.util.HashSet;
final class Config
{
// From resources
public final float marginTop;
public final float keyPadding;
public final float labelTextSize;
public final float sublabelTextSize;
/** Presses within this radius of an other pointer are ignored */
public final float pointerTooClose;
// From preferences
public int layout; // Or '-1' for the system defaults
@ -32,16 +36,17 @@ final class Config
public float keyVerticalInterval;
public float keyHorizontalInterval;
public boolean preciseRepeat;
public int lockable_modifiers;
public float characterSize; // Ratio
public int accents; // Values are R.values.pref_accents_v_*
public int theme; // Values are R.style.*
// Dynamically set
public boolean shouldOfferSwitchingToNextInputMethod;
public int key_flags_to_remove;
public String actionLabel; // Might be 'null'
public int actionId; // Meaningful only when 'actionLabel' isn't 'null'
public boolean swapEnterActionKey; // Swap the "enter" and "action" keys
public Set<String> extra_keys; // 'null' means all the keys
public final IKeyEventHandler handler;
@ -53,6 +58,7 @@ final class Config
keyPadding = res.getDimension(R.dimen.key_padding);
labelTextSize = res.getFloat(R.integer.label_text_size);
sublabelTextSize = res.getFloat(R.integer.sublabel_text_size);
pointerTooClose = res.getDimension(R.dimen.pointer_too_close);
// default values
layout = -1;
vibrateEnabled = true;
@ -71,10 +77,10 @@ final class Config
refresh(context);
// initialized later
shouldOfferSwitchingToNextInputMethod = false;
key_flags_to_remove = 0;
actionLabel = null;
actionId = 0;
swapEnterActionKey = false;
extra_keys = null;
handler = h;
}
@ -113,11 +119,56 @@ final class Config
keyHeight = dm.heightPixels * keyboardHeightPercent / 100 / 4;
horizontalMargin = getDipPref(dm, prefs, "horizontal_margin", horizontalMargin) + res.getDimension(R.dimen.extra_horizontal_margin);
preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
lockable_modifiers =
(prefs.getBoolean("lockable_shift", true) ? KeyValue.FLAG_SHIFT : 0)
| (prefs.getBoolean("lockable_ctrl", false) ? KeyValue.FLAG_CTRL : 0)
| (prefs.getBoolean("lockable_alt", false) ? KeyValue.FLAG_ALT : 0)
| (prefs.getBoolean("lockable_fn", false) ? KeyValue.FLAG_FN : 0)
| (prefs.getBoolean("lockable_meta", false) ? KeyValue.FLAG_META : 0)
| (prefs.getBoolean("lockable_sup", false) ? KeyValue.FLAG_ACCENT_SUPERSCRIPT : 0)
| (prefs.getBoolean("lockable_sub", false) ? KeyValue.FLAG_ACCENT_SUBSCRIPT : 0);
characterSize = prefs.getFloat("character_size", characterSize);
accents = Integer.valueOf(prefs.getString("accents", "1"));
theme = getThemeId(res, prefs.getString("theme", ""));
}
/** Update the layout according to the configuration.
* - Remove the switching key if it isn't needed
* - Remove keys from other locales (not in 'extra_keys')
* - Replace the action key to show the right label
* - Swap the enter and action keys
*/
public KeyboardData modify_layout(KeyboardData kw)
{
// Update the name to avoid caching in KeyModifier
KeyValue action_key = (actionLabel == null) ? null :
KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel);
return kw.replaceKeys(key -> {
if (key == null)
return null;
switch (key.eventCode)
{
case KeyValue.EVENT_CHANGE_METHOD:
return shouldOfferSwitchingToNextInputMethod ? key : null;
case KeyEvent.KEYCODE_ENTER:
return (swapEnterActionKey && action_key != null) ? action_key : key;
case KeyValue.EVENT_ACTION:
return (swapEnterActionKey && action_key != null) ?
KeyValue.getKeyByName("enter") : action_key;
default:
if (key.flags != 0)
{
if ((key.flags & KeyValue.FLAG_LOCALIZED) != 0 &&
extra_keys != null &&
!extra_keys.contains(key.name))
return null;
if ((key.flags & lockable_modifiers) != 0)
return key.withFlags(key.flags | KeyValue.FLAG_LOCK);
}
return key;
}});
}
private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
{
float value;
@ -152,38 +203,19 @@ final class Config
switch (name)
{
case "azerty": return R.xml.azerty;
case "qwerty": return R.xml.qwerty;
case "qwerty_lv": return R.xml.qwerty_lv;
case "qwerty_es": return R.xml.qwerty_es;
case "ru_jcuken": return R.xml.local_ru_jcuken;
case "qwertz": return R.xml.qwertz;
case "bgph1": return R.xml.local_bgph1;
case "dvorak": return R.xml.dvorak;
case "qwerty_es": return R.xml.qwerty_es;
case "qwerty_lv": return R.xml.qwerty_lv;
case "qwerty_pt": return R.xml.qwerty_pt;
case "qwerty": return R.xml.qwerty;
case "qwerty_sv_se": return R.xml.qwerty_sv_se;
case "qwertz": return R.xml.qwertz;
case "ru_jcuken": return R.xml.local_ru_jcuken;
case "system": default: return -1;
}
}
/* Used for the accents option. */
public static int extra_key_flag_of_name(String name)
{
switch (name)
{
case "aigu": return KeyValue.FLAG_ACCENT2;
case "caron": return KeyValue.FLAG_ACCENT_CARON;
case "cedille": return KeyValue.FLAG_ACCENT5;
case "circonflexe": return KeyValue.FLAG_ACCENT3;
case "grave": return KeyValue.FLAG_ACCENT1;
case "macron": return KeyValue.FLAG_ACCENT_MACRON;
case "ring": return KeyValue.FLAG_ACCENT_RING;
case "szlig": return KeyValue.FLAG_LANG_SZLIG;
case "euro": return KeyValue.FLAG_LANG_EURO;
case "pound": return KeyValue.FLAG_LANG_POUND;
case "tilde": return KeyValue.FLAG_ACCENT4;
case "trema": return KeyValue.FLAG_ACCENT6;
default: throw new RuntimeException(name);
}
}
public static int themeId_of_string(String name)
{
switch (name)

View File

@ -14,6 +14,8 @@ class KeyEventHandler implements Config.IKeyEventHandler
public void handleKeyUp(KeyValue key, int flags)
{
key = KeyModifier.handleFlags(key, flags);
if (key == null || (key.flags & KeyValue.FLAG_NOCHAR) != 0)
return;
switch (key.eventCode)
{
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return;

View File

@ -14,7 +14,7 @@ class KeyModifier
/* Modify a key according to modifiers. */
public static KeyValue handleFlags(KeyValue k, int flags)
{
if (flags == 0) // No modifier
if (k == null || flags == 0) // No modifier
return k;
SparseArray<KeyValue> ks = cacheEntry(k);
KeyValue r = ks.get(flags);
@ -22,7 +22,9 @@ class KeyModifier
return r;
r = k;
r = handleFn(r, flags);
if (r != null)
r = handleShift(r, flags);
if (r != null)
r = handleAccents(r, flags);
ks.put(flags, r);
return r;
@ -211,6 +213,7 @@ class KeyModifier
case "#": name = "£"; break;
case "*": name = "°"; break;
case "tab": name = "\\t"; break;
case "": case "£": return null; // Avoid showing these twice
default: return k;
}
return KeyValue.getKeyByName(name);

View File

@ -51,25 +51,13 @@ class KeyValue
public static final int FLAG_ACCENT_MACRON = (1 << 27);
public static final int FLAG_ACCENT_ORDINAL = (1 << 28);
public static final int FLAGS_ACCENTS = FLAG_ACCENT1 | FLAG_ACCENT2 |
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
FLAG_ACCENT_CARON | FLAG_ACCENT_MACRON | FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL | FLAG_ACCENT_RING;
// Language specific keys
public static final int FLAG_LANG_SZLIG = (1 << 25);
public static final int FLAG_LANG_EURO = (1 << 29);
public static final int FLAG_LANG_POUND = (1 << 30);
public static final int FLAGS_LANGS = FLAG_LANG_SZLIG | FLAG_LANG_EURO |
FLAG_LANG_POUND;
public static final int FLAGS_NOT_HIDDEN_ACCENTS = FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL;
// Keys that have to be enabled per language
public static final int FLAGS_HIDDEN_KEYS =
(FLAGS_ACCENTS & ~FLAGS_NOT_HIDDEN_ACCENTS) | FLAGS_LANGS;
// Language specific keys that are removed from the keyboard by default
public static final int FLAG_LOCALIZED = (1 << 25);
public final String name;
public final String symbol;
@ -88,6 +76,16 @@ class KeyValue
return new KeyValue(name, s, c, eventCode, flags);
}
public KeyValue withNameAndSymbol(String n, String s)
{
return new KeyValue(n, s, char_, eventCode, flags);
}
public KeyValue withFlags(int f)
{
return new KeyValue(name, symbol, char_, eventCode, f);
}
private static HashMap<String, KeyValue> keys = new HashMap<String, KeyValue>();
public KeyValue(String n, String s, char c, int e, int f)
@ -155,21 +153,21 @@ class KeyValue
static
{
addModifierKey("shift", "\uE808",
FLAG_LOCK | FLAG_SHIFT | FLAG_KEY_FONT | FLAG_SMALLER_FONT);
FLAG_SHIFT | FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addModifierKey("ctrl", "Ctrl", FLAG_CTRL | FLAG_SMALLER_FONT);
addModifierKey("alt", "Alt", FLAG_ALT | FLAG_SMALLER_FONT);
addModifierKey("accent_aigu", "◌́", FLAG_ACCENT2);
addModifierKey("accent_caron", "◌̌", FLAG_ACCENT_CARON);
addModifierKey("accent_cedille", "◌̧", FLAG_ACCENT5);
addModifierKey("accent_circonflexe", "◌̂", FLAG_ACCENT3);
addModifierKey("accent_grave", "◌̀", FLAG_ACCENT1);
addModifierKey("accent_macron", "◌̄", FLAG_ACCENT_MACRON);
addModifierKey("accent_tilde", "◌̃", FLAG_ACCENT4);
addModifierKey("accent_trema", "◌̈", FLAG_ACCENT6);
addModifierKey("accent_ring", "◌̊", FLAG_ACCENT_RING);
addModifierKey("superscript", "◌͆", FLAG_ACCENT_SUPERSCRIPT);
addModifierKey("subscript", "◌̺", FLAG_ACCENT_SUBSCRIPT);
addModifierKey("ordinal", "ºʳᵈ", FLAG_ACCENT_ORDINAL | FLAG_SMALLER_FONT);
addModifierKey("accent_aigu", "◌́", FLAG_ACCENT2 | FLAG_LOCALIZED);
addModifierKey("accent_caron", "◌̌", FLAG_ACCENT_CARON | FLAG_LOCALIZED);
addModifierKey("accent_cedille", "◌̧", FLAG_ACCENT5 | FLAG_LOCALIZED);
addModifierKey("accent_circonflexe", "◌̂", FLAG_ACCENT3 | FLAG_LOCALIZED);
addModifierKey("accent_grave", "◌̀", FLAG_ACCENT1 | FLAG_LOCALIZED);
addModifierKey("accent_macron", "◌̄", FLAG_ACCENT_MACRON | FLAG_LOCALIZED);
addModifierKey("accent_tilde", "◌̃", FLAG_ACCENT4 | FLAG_LOCALIZED);
addModifierKey("accent_trema", "◌̈", FLAG_ACCENT6 | FLAG_LOCALIZED);
addModifierKey("accent_ring", "◌̊", FLAG_ACCENT_RING | FLAG_LOCALIZED);
addModifierKey("superscript", "Sup", FLAG_ACCENT_SUPERSCRIPT | FLAG_SMALLER_FONT);
addModifierKey("subscript", "Sub", FLAG_ACCENT_SUBSCRIPT | FLAG_SMALLER_FONT);
addModifierKey("ordinal", "Ord", FLAG_ACCENT_ORDINAL | FLAG_SMALLER_FONT);
addModifierKey("fn", "Fn", FLAG_FN | FLAG_SMALLER_FONT);
addModifierKey("meta", "", FLAG_META);
@ -226,9 +224,9 @@ class KeyValue
addCharKey('#', KeyEvent.KEYCODE_POUND);
addCharKey('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN);
addCharKey(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN);
addCharKey('ß', EVENT_NONE, FLAG_LANG_SZLIG);
addCharKey('€', EVENT_NONE, FLAG_LANG_EURO);
addCharKey('£', EVENT_NONE, FLAG_LANG_POUND);
addCharKey('ß', EVENT_NONE, FLAG_LOCALIZED);
addCharKey('€', EVENT_NONE, FLAG_LOCALIZED);
addCharKey('£', EVENT_NONE, FLAG_LOCALIZED);
addSpecialKey("config", "\uE806", EVENT_CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT);
@ -236,7 +234,7 @@ class KeyValue
addSpecialKey("switch_emoji", "\uE812" , EVENT_SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
addSpecialKey("change_method", "\ue807", EVENT_CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("action", "Action", EVENT_ACTION); // Will always be replaced
addSpecialKey("action", "Action", EVENT_ACTION, FLAG_SMALLER_FONT); // Will always be replaced
addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
addEventKey("enter", "\ue800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);

View File

@ -18,17 +18,25 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.util.Log;
import android.util.LogPrinter;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener
{
static private final String TAG = "Keyboard2";
private Keyboard2View _keyboardView;
private int _currentTextLayout;
private ViewGroup _emojiPane = null;
private Config _config;
private boolean _debug_logs = false;
private KeyboardData getLayout(int resId)
{
return KeyboardData.load(getResources(), resId);
@ -45,6 +53,7 @@ public class Keyboard2 extends InputMethodService
_config.refresh(this);
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_keyboardView.reset();
_debug_logs = getResources().getBoolean(R.bool.debug_logs);
}
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
@ -70,32 +79,34 @@ public class Keyboard2 extends InputMethodService
_currentTextLayout = l;
}
private int extra_keys_of_subtype(InputMethodSubtype subtype)
private void extra_keys_of_subtype(Set<String> dst, InputMethodSubtype subtype)
{
String extra_keys = subtype.getExtraValueOf("extra_keys");
int flags = 0;
if (extra_keys != null)
for (String acc : extra_keys.split("\\|"))
flags |= Config.extra_key_flag_of_name(acc);
return flags;
if (extra_keys == null)
return;
String[] ks = extra_keys.split("\\|");
for (int i = 0; i < ks.length; i++)
dst.add(ks[i]);
}
private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype)
{
int to_keep = 0;
HashSet<String> extra_keys = new HashSet<String>();
switch (_config.accents)
{
case 1:
to_keep |= extra_keys_of_subtype(subtype);
extra_keys_of_subtype(extra_keys, subtype);
for (InputMethodSubtype s : getEnabledSubtypes(imm))
to_keep |= extra_keys_of_subtype(s);
extra_keys_of_subtype(extra_keys, s);
break;
case 2: to_keep |= extra_keys_of_subtype(subtype); break;
case 3: to_keep = KeyValue.FLAGS_HIDDEN_KEYS; break;
case 2:
extra_keys_of_subtype(extra_keys, subtype);
break;
case 3: extra_keys = null; break;
case 4: break;
default: throw new IllegalArgumentException();
}
_config.key_flags_to_remove = ~to_keep & KeyValue.FLAGS_HIDDEN_KEYS;
_config.extra_keys = extra_keys;
}
private void refreshSubtypeLegacyFallback()
@ -103,8 +114,8 @@ public class Keyboard2 extends InputMethodService
// Fallback for the accents option: Only respect the "None" case
switch (_config.accents)
{
case 1: case 2: case 3: _config.key_flags_to_remove = 0; break;
case 4: _config.key_flags_to_remove = KeyValue.FLAGS_HIDDEN_KEYS; break;
case 1: case 2: case 3: _config.extra_keys = null; break;
case 4: _config.extra_keys = new HashSet<String>(); break;
}
// Fallback for the layout option: Use qwerty in the "system settings" case
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
@ -176,7 +187,16 @@ public class Keyboard2 extends InputMethodService
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_emojiPane = null;
}
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
}
private void log_editor_info(EditorInfo info)
{
LogPrinter p = new LogPrinter(Log.DEBUG, TAG);
info.dump(p, "");
if (info.extras != null)
Log.d(TAG, "extras: "+info.extras.toString());
Log.d(TAG, "swapEnterActionKey: "+_config.swapEnterActionKey);
Log.d(TAG, "actionLabel: "+_config.actionLabel);
}
@Override
@ -186,7 +206,11 @@ public class Keyboard2 extends InputMethodService
refreshEditorInfo(info);
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
else
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
setInputView(_keyboardView);
if (_debug_logs)
log_editor_info(info);
}
@Override

View File

@ -55,28 +55,7 @@ public class Keyboard2View extends View
public void setKeyboard(KeyboardData kw)
{
if (!_config.shouldOfferSwitchingToNextInputMethod)
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_CHANGE_METHOD, null));
if (_config.key_flags_to_remove != 0)
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByFlags(_config.key_flags_to_remove, null));
// Replace the action key to show the right label.
KeyValue action_key = null;
if (_config.actionLabel != null)
{
action_key = new KeyValue(_config.actionLabel, _config.actionLabel,
KeyValue.CHAR_NONE, KeyValue.EVENT_ACTION, KeyValue.FLAG_NOREPEAT);
}
if (_config.swapEnterActionKey && action_key != null)
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent2(KeyEvent.KEYCODE_ENTER,
action_key, KeyValue.EVENT_ACTION,
KeyValue.getKeyByName("enter")));
else
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_ACTION, action_key));
_keyboard = kw;
_keyboard = _config.modify_layout(kw);
reset();
}
@ -106,7 +85,6 @@ public class Keyboard2View extends View
public void onPointerUp(KeyValue k)
{
if (k != null && (k.flags & KeyValue.FLAG_NOCHAR) == 0)
_config.handler.handleKeyUp(k, _flags);
updateFlags();
invalidate();
@ -114,7 +92,6 @@ public class Keyboard2View extends View
public void onPointerHold(KeyValue k)
{
if (k != null)
_config.handler.handleKeyUp(k, _flags);
}
@ -138,7 +115,7 @@ public class Keyboard2View extends View
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
_pointers.onTouchUp(event.getPointerId(event.getActionIndex()));
break ;
break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
p = event.getActionIndex();
@ -147,11 +124,14 @@ public class Keyboard2View extends View
KeyboardData.Key key = getKeyAtPosition(tx, ty);
if (key != null)
_pointers.onTouchDown(tx, ty, event.getPointerId(p), key);
break ;
break;
case MotionEvent.ACTION_MOVE:
for (p = 0; p < event.getPointerCount(); p++)
_pointers.onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
break ;
break;
case MotionEvent.ACTION_CANCEL:
_pointers.onTouchCancel(event.getPointerId(event.getActionIndex()));
break;
default:
return (false);
}
@ -236,28 +216,19 @@ public class Keyboard2View extends View
_tmpRect.set(x, y, x + keyW, y + keyH);
canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius,
isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint);
if (k.key0 != null)
drawLabel(canvas, k.key0, keyW / 2f + x, y, keyH, isKeyDown);
if (k.edgekeys)
{
if (k.key1 != null) // top key
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.TOP, isKeyDown);
if (k.key3 != null) // left key
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.CENTER, isKeyDown);
if (k.key2 != null) // right key
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
if (k.key4 != null) // bottom key
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
}
else
{
if (k.key1 != null) // top left key
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.TOP, isKeyDown);
if (k.key3 != null) // bottom left key
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown);
if (k.key2 != null) // top right key
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
if (k.key4 != null) // bottom right key
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
}
x += _keyWidth * k.width;
@ -290,8 +261,10 @@ public class Keyboard2View extends View
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown)
{
float textSize = scaleTextSize(k, _config.labelTextSize, keyH);
k = KeyModifier.handleFlags(k, _flags);
if (k == null)
return;
float textSize = scaleTextSize(k, _config.labelTextSize, keyH);
Paint p = _theme.labelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0));
p.setColor(labelColor(k, isKeyDown, _theme.labelColor));
p.setTextSize(textSize);
@ -300,8 +273,10 @@ public class Keyboard2View extends View
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, float keyW, float keyH, Paint.Align a, Vertical v, boolean isKeyDown)
{
float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH);
k = KeyModifier.handleFlags(k, _flags);
if (k == null)
return;
float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH);
Paint p = _theme.subLabelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0), a);
p.setColor(labelColor(k, isKeyDown, _theme.subLabelColor));
p.setTextSize(textSize);

View File

@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
class KeyboardData
{
@ -184,7 +185,8 @@ class KeyboardData
public Key replaceKeys(MapKeys f)
{
return new Key(f.map(key0), f.map(key1), f.map(key2), f.map(key3), f.map(key4), width, shift, edgekeys);
return new Key(f.apply(key0), f.apply(key1), f.apply(key2),
f.apply(key3), f.apply(key4), width, shift, edgekeys);
}
/** New key with the width multiplied by 's'. */
@ -194,70 +196,7 @@ class KeyboardData
}
}
public static abstract interface MapKeys
{
public abstract KeyValue map(KeyValue k);
}
public static class ReplaceKeysByFlags implements MapKeys
{
private final int _flags;
private final KeyValue _replacement;
public ReplaceKeysByFlags(int flags, KeyValue r)
{
_flags = flags;
_replacement = r;
}
public KeyValue map(KeyValue k)
{
return (k != null && (k.flags & _flags) != 0) ? _replacement : k;
}
}
public static class ReplaceKeysByEvent implements MapKeys
{
private final int _eventCode;
private final KeyValue _replacement;
public ReplaceKeysByEvent(int ev, KeyValue r)
{
_eventCode = ev;
_replacement = r;
}
public KeyValue map(KeyValue k)
{
return (k != null && k.eventCode == _eventCode) ? _replacement : k;
}
}
/* Replace two keys at the same time. Used for swaping keys. */
public static class ReplaceKeysByEvent2 implements MapKeys
{
private final int _e1;
private final KeyValue _r1;
private final int _e2;
private final KeyValue _r2;
public ReplaceKeysByEvent2(int e1, KeyValue r1, int e2, KeyValue r2)
{
_e1 = e1;
_r1 = r1;
_e2 = e2;
_r2 = r2;
}
public KeyValue map(KeyValue k)
{
if (k == null)
return null;
if (k.eventCode == _e1) return _r1;
if (k.eventCode == _e2) return _r2;
return k;
}
}
public static abstract interface MapKeys extends Function<KeyValue, KeyValue> { }
/** Parsing utils */

View File

@ -53,7 +53,7 @@ public final class Pointers implements Handler.Callback
public int getKeyFlags(KeyValue kv)
{
for (Pointer p : _ptrs)
if (p.value == kv)
if (p.value != null && p.value.name == kv.name) // Physical equality
return p.flags;
return -1;
}
@ -95,8 +95,22 @@ public final class Pointers implements Handler.Callback
}
}
public void onTouchCancel(int pointerId)
{
Pointer ptr = getPtr(pointerId);
if (ptr == null)
return;
stopKeyRepeat(ptr);
removePtr(ptr);
_handler.onPointerFlagsChanged();
}
public void onTouchDown(float x, float y, int pointerId, KeyboardData.Key key)
{
// Ignore new pointers that are too close to an existing pointer. This
// might be glitches.
if (isPointerNearby(x, y))
return;
KeyValue value = key.key0;
Pointer ptr = new Pointer(pointerId, key, value, x, y);
_ptrs.add(ptr);
@ -113,7 +127,8 @@ public final class Pointers implements Handler.Callback
float dx = x - ptr.downX;
float dy = y - ptr.downY;
float dist = Math.abs(dx) + Math.abs(dy);
ptr.ptrDist = dist;
ptr.ptrDistX = dx;
ptr.ptrDistY = dy;
KeyValue newValue;
if (dist < _config.swipe_dist_px)
{
@ -189,6 +204,20 @@ public final class Pointers implements Handler.Callback
}
}
/** Check if a pointer is within a radius of 'pointerTooClose' */
private boolean isPointerNearby(float x, float y)
{
for (Pointer p : _ptrs)
{
float dx = p.downX + p.ptrDistX - x;
float dy = p.downY + p.ptrDistY - y;
float d = Math.abs(dx) + Math.abs(dy);
if (d < _config.pointerTooClose)
return true;
}
return false;
}
// Key repeat
/** Message from [_keyrepeat_handler]. */
@ -240,12 +269,13 @@ public final class Pointers implements Handler.Callback
private float modulatePreciseRepeat(Pointer ptr)
{
float ptrDist = Math.abs(ptr.ptrDistX) + Math.abs(ptr.ptrDistY);
if (ptr.repeatingPtrDist < 0.f)
ptr.repeatingPtrDist = ptr.ptrDist; // First repeat
if (ptr.ptrDist > ptr.repeatingPtrDist * 2.f)
ptr.repeatingPtrDist = ptr.ptrDist / 2.f; // Large swipe, move the middle point
ptr.repeatingPtrDist = ptrDist; // First repeat
if (ptrDist > ptr.repeatingPtrDist * 2.f)
ptr.repeatingPtrDist = ptrDist / 2.f; // Large swipe, move the middle point
float left = ptr.repeatingPtrDist / 2.f;
float accel = (ptr.ptrDist - left) / (ptr.repeatingPtrDist - left);
float accel = (ptrDist - left) / (ptr.repeatingPtrDist - left);
return Math.min(8.f, Math.max(0.1f, accel));
}
@ -258,7 +288,8 @@ public final class Pointers implements Handler.Callback
public float downX;
public float downY;
/** Distance of the pointer to the initial press. */
public float ptrDist;
public float ptrDistX;
public float ptrDistY;
public int flags;
/** Identify timeout messages. */
public int timeoutWhat;
@ -272,7 +303,8 @@ public final class Pointers implements Handler.Callback
value = v;
downX = x;
downY = y;
ptrDist = 0.f;
ptrDistX = 0.f;
ptrDistY = 0.f;
flags = (v == null) ? 0 : v.flags;
timeoutWhat = -1;
repeatingPtrDist = -1.f;