Compare commits

...

31 Commits

Author SHA1 Message Date
Jules Aguillon
96c4b165ac Release 1.11.0 (14) 2022-01-16 23:50:11 +01:00
Jules Aguillon
40897f2c26 Update and improve the description
Explain better what the app is and mention some of the features.

Unfortunately, the German translation needs to be dropped because I
can't maintain it.
2022-01-16 23:44:04 +01:00
Moini
133b6ec2c1 German keyboard added (#20)
* Add German metadata translation

* Add German keyboard

Co-authored-by: Jules Aguillon <jules@j3s.fr>
2022-01-15 20:56:08 +01:00
Jules Aguillon
833dfa31bb Fix miscalculation of the space between the keys
'keyVerticalInterval' was mistakenly used to compute the height of the
keyboard and the vertical position of keys.
While the code handling pointers did not use this value, the hit box of
the bottom row was shifted by several pixels.

Make sure 'keyVerticalInterval' is only used for rendering and not for
placing the keys.
2022-01-15 20:24:27 +01:00
Jules Aguillon
fa9250a89e Contributing: Mention enabling the virtual keyboard 2022-01-15 19:51:40 +01:00
Jules Aguillon
854eb431f3 CONTRIBUTING: Document debug installation failure 2022-01-15 19:03:53 +01:00
Jules Aguillon
d4eef00a8a Add a CONTRIBUTING guide 2022-01-15 18:55:05 +01:00
Jules Aguillon
f22d040eda Update screenshots 2022-01-10 01:02:14 +01:00
Jules Aguillon
dfec26a93b Swap the Enter and Action keys when needed
When IME_FLAG_NO_ENTER_ACTION is set.
2022-01-10 00:27:22 +01:00
Jules Aguillon
53113cadd9 Add the Action key
It is placed on the top-right of the enter key on every layouts.
It sends a special event (performEditorAction) instead of writing a
newline.

The "actionId" is passed through the EditorInfo object in an obfuscated
way so it's not clear whether it's using the right one.
2022-01-09 20:26:06 +01:00
Moini
4b43645c4b Fix a few strings 2022-01-09 12:53:14 +01:00
Jules Aguillon
93e84ba7e9 Add the German language
Add the 'ß' character on the bottom-left corner of the 's' key, which is
hidden for other languages.

Co-authored-by: Moini <moini@noreply.invalid>
2022-01-09 12:49:28 +01:00
Jules Aguillon
23e59c6b09 Allow to hide more keys than just accents
Add the "FLAGS_LANGS" set of flags, which will be used to hide
individual keys that are not accents.
2022-01-09 12:47:47 +01:00
Jules Aguillon
2764e96eb1 Change the key combination for °
To Fn+*

Was previously accent^+*, which was not available for most languages.
2022-01-01 19:00:27 +01:00
Jules Aguillon
9c82c9cfdc Improve the "precision" option
Now named "swiping distance". Changed to a dropdown.
2021-12-30 22:22:25 +01:00
Jules Aguillon
8bef0728ae Turn the "precision" option to dp instead of px 2021-12-30 21:59:48 +01:00
Jules Aguillon
b05f6e8447 Simplify string definitions
Inline constants in settings.xml, strings.xml is only for strings that
can be translated.
2021-12-30 21:37:34 +01:00
Jules Aguillon
f69a0605a8 Add the Black theme
Friendly to Amoled screens.
The background of keys is the same as the background of the whole
keyboard: pure black.
Colors are also slightly stronger.
2021-12-30 00:53:48 +01:00
Jules Aguillon
29367f127d Move the border radius from Config to Theme
Also, draw activated keys with a round border too.
2021-12-30 00:52:50 +01:00
Jules Aguillon
093a00c572 Add themes
Add a "Theme" option to choose between a dark and light theme.
The light theme uses the colors of the dark theme with the luminance
inversed.

The reloading after a configuration change is changed slightly:
- Special handling is needed when the Theme is changed (recreate the views)
- The default implementation of 'onConfigurationChanged' is used
  Which triggers more refresh (but don't recreate the views)
- 'onCreateInputView' is no longer needed
2021-12-30 00:26:05 +01:00
Jules Aguillon
40b1ec63a9 Use the themes abstraction
Themes replace 'colors.xml' and soon will replace 'dimens.xml'.
2021-12-28 19:12:50 +01:00
Jules Aguillon
93704cca0a Reference the "special key font" in the Theme object
Remove the last cast of the context.
2021-12-28 17:53:58 +01:00
Jules Aguillon
15ce200ce3 Separate "handler" code
As with the previous commit, remove casts of the context.
The "handler" object is referenced in the "config" object for now.
2021-12-28 17:47:18 +01:00
Jules Aguillon
0190cfc29a Turn Config into a singleton object
The goal is to remove a cast of the 'context' into 'Keyboard2'.
2021-12-28 16:47:19 +01:00
Jules Aguillon
dd24ad323b Move Theme code to its own class 2021-12-26 23:55:18 +01:00
Jules Aguillon
86655d4959 Always send the keycode for the tab key
Don't write the tab character and always send the keycode, which is most
probably handled by applications.
2021-12-22 20:40:39 +01:00
Jules Aguillon
3e332dbf54 Use the right keycode for the home key
The previous keycode wasn't the classical "home" movement key but
Android's actual home key, which has no effect when generated from the
keyboard.
2021-12-22 20:19:59 +01:00
Jules Aguillon
d721cc86d1 Avoid crash when removing a layout
Might happen when downgrading the app.
2021-12-19 20:04:17 +01:00
Jules Aguillon
1cfecbdf48 Auto-format Java and XML files
Use xmllint.
Re-indent Java files using spaces.
2021-12-19 19:44:27 +01:00
Jules Aguillon
988d8db7e8 Use apksigner for signing the apk
The Play Store now requires the "Signing Scheme V2", which is
implemented by apksigner.
2021-12-14 00:13:34 +01:00
Jules Aguillon
e5fa23e1f7 Upgrade to Android SDK version 30 2021-12-12 23:48:05 +01:00
52 changed files with 1736 additions and 1413 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
*.keystore *.keystore
_build _build
/*-keystore.conf

View File

@@ -1,38 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="14" android:versionName="1.11.0" android:hardwareAccelerated="false">
package="juloo.keyboard2" <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="30"/>
android:versionCode="13" <application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:hardwareAccelerated="false">
android:versionName="1.10.0" <service android:name="juloo.keyboard2.Keyboard2" android:label="@string/app_name" android:permission="android.permission.BIND_INPUT_METHOD">
android:hardwareAccelerated="false">
<uses-sdk android:minSdkVersion="4"
android:targetSdkVersion="29" />
<application android:label="@string/app_name"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:hardwareAccelerated="false">
<service android:name="juloo.keyboard2.Keyboard2"
android:label="@string/app_name"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter> <intent-filter>
<action android:name="android.view.InputMethod" /> <action android:name="android.view.InputMethod"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.view.im" <meta-data android:name="android.view.im" android:resource="@xml/method"/>
android:resource="@xml/method" />
</service> </service>
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@drawable/ic_launcher" android:label="@string/settings_activity_label">
<activity android:name="juloo.keyboard2.SettingsActivity"
android:icon="@drawable/ic_launcher"
android:label="@string/settings_activity_label">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.VIBRATE" />
</manifest> </manifest>

62
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,62 @@
# Contributing
Thanks for contributing :)
## Building the app
The application doesn't use Gradle and it might be hard to use some features of
Android Studio.
Fortunately, there's not many dependencies:
- OpenJDK 8
- Android SDK: build tools `30.0.3`, platform `30`
- Make sure to have the `$ANDROID_HOME` environment variable set.
For Nix users, there's a `shell.nix` for setting-up the right environment.
Building the debug apk:
```sh
make
```
If the build succeed, the debug apk is located in
`_build/juloo.keyboard2.debug.apk`.
## Debugging on your phone
You need to have *USB debugging* enabled on your phone, see [Android's doc](https://developer.android.com/studio/debug/dev-options#enable).
It is also possible to enable *ADB over network* in the settings and connect
with `adb connect <ip of the phone>`. Make sure to be connected to a local
network that you trust.
Install the application with:
```sh
make installd
```
The debug version of the application won't be removed, both versions will stay
installed at the same time.
The application must be enabled in the settings:
System Settings > System > Languages & Input > Virtual keyboard > Manage keyboards.
## Debugging the application: INSTALL_FAILED_UPDATE_INCOMPATIBLE
`make installd` can fail with the following error message:
```
adb: failed to install _build/juloo.keyboard2.debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package juloo.keyboard2.debug signatures do not match previously installed version; ignoring!]
make: *** [Makefile:20: installd] Error 1
```
The application can't be "updated" because the temporary certificate has been
lost. The solution is to uninstall and install again.
The application must be enabled again in the settings.
```sh
adb uninstall juloo.keyboard2.debug
make installd
```

View File

@@ -2,7 +2,7 @@
PACKAGE_NAME = juloo.keyboard2 PACKAGE_NAME = juloo.keyboard2
ANDROID_PLATFORM_VERSION = android-29 ANDROID_PLATFORM_VERSION = android-30
JAVA_VERSION = 1.7 JAVA_VERSION = 1.7
SRC_DIR = srcs SRC_DIR = srcs
@@ -44,11 +44,6 @@ JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java')
RES_FILES = $(shell find $(RES_DIR) -type f) RES_FILES = $(shell find $(RES_DIR) -type f)
ASSETS_FILES = $(shell find $(ASSETS_DIR) -type f 2>/dev/null) ASSETS_FILES = $(shell find $(ASSETS_DIR) -type f 2>/dev/null)
# Align
_build/%.apk: _build/%.signed-apk
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
# Debug signing # Debug signing
DEBUG_KEYSTORE = _build/debug.keystore DEBUG_KEYSTORE = _build/debug.keystore
@@ -59,7 +54,7 @@ $(DEBUG_KEYSTORE):
-alias debug -keypass $(DEBUG_PASSWD) -keystore "$@" \ -alias debug -keypass $(DEBUG_PASSWD) -keystore "$@" \
-keyalg rsa -storepass $(DEBUG_PASSWD) -validity 10000 -keyalg rsa -storepass $(DEBUG_PASSWD) -validity 10000
_build/%.debug.signed-apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE) _build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
jarsigner -keystore $(DEBUG_KEYSTORE) \ jarsigner -keystore $(DEBUG_KEYSTORE) \
-storepass $(DEBUG_PASSWD) -keypass $(DEBUG_PASSWD) \ -storepass $(DEBUG_PASSWD) -keypass $(DEBUG_PASSWD) \
-signedjar "$@" "$<" debug -signedjar "$@" "$<" debug
@@ -70,16 +65,19 @@ _build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest
# Release signing # Release signing
# %-keystore.conf should declare KEYSTORE, KEYNAME and OPTS # %-keystore.conf should declare KEYSTORE, KEYNAME and KEYSTOREPASS
# it is interpreted as a shell script # it is interpreted as a shell script
# OPTS can be used to pass -storepass or -keypass options to jarsigner _build/%.apk: _build/%.unsigned-apk %-keystore.conf
_build/%.signed-apk: _build/%.unsigned-apk %-keystore.conf
eval `cat $(word 2,$^)` && \ eval `cat $(word 2,$^)` && \
jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore "$$KEYSTORE" $$OPTS -signedjar "$@" "$<" "$$KEYNAME" apksigner sign --in "$<" --out "$@" \
--ks "$$KEYSTORE" --ks-key-alias "$$KEYNAME" --ks-pass "pass:$$KEYSTOREPASS"
# Package # Package
_build/%.unsigned-apk: _build/classes.dex $(MANIFEST_FILE) $(ASSETS_FILES) _build/%.unsigned-apk: _build/%.unaligned-apk
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
_build/%.unaligned-apk: _build/classes.dex $(MANIFEST_FILE) $(ASSETS_FILES)
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \ $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS) -I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
[ -z "$(ASSETS_FILES)" ] || $(ANDROID_BUILD_TOOLS)/aapt add "$@" $(ASSETS_FILES) [ -z "$(ASSETS_FILES)" ] || $(ANDROID_BUILD_TOOLS)/aapt add "$@" $(ASSETS_FILES)

View File

@@ -2,15 +2,32 @@
A lightweight virtual keyboard for developers. A lightweight virtual keyboard for developers.
![Unexpected Keyboard](play_store/capture1.png) ![Unexpected Keyboard](metadata/android/en-US/images/featureGraphic.png)
All the characters you might need are available on a single screen, as well as control, alt, escape and many others. This app is a virtual keyboard for Android. The main features are easy typing of every ASCII character using the swipe gesture, dead keys for accents and modifier keys and the presence of special keys (tab, esc, arrows, etc..).
Several characters are displayed on each key. Get the one in the middle with a press and the ones in the corners by sliding your finger. The keyboard shows up to 4 extra characters in the corners of each key. These extra characters are hit by swiping the finger on the key.
Like any other keyboard app, you will need to activate it in the system settings to be able to use it. Highlight of some of the features:
This can be found in the System Settings > System > Languages & Input > Virtual keyboard > Manage keyboards.
- Every character and special keys that are also available on a PC keyboard. This is perfect for using applications like Termux.
- This includes Tab, Esc, the arrows and function keys, but also Ctrl and Alt !
- Accented keys are accessible using dead keys. First activate the accent, then type the accented letter.
- Very light and fast. Use 500x times less space than Google's keyboard and 15x times less than the default keyboard. No ad, no tracking.
- Multiple layouts: QWERTY, QWERTZ, AZERTY. Themes: White, Dark, OLED Black. And many other options.
Like any other virtual keyboards, it must be enabled in the system settings. Open the System Settings and go to:
System > Languages & Input > Virtual keyboard > Manage keyboards.
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" [<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid" alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/juloo.keyboard2/) height="80">](https://f-droid.org/packages/juloo.keyboard2/)
## Contributing
For instructions on building the application, see
[Contributing](Contributing.md).

View File

@@ -0,0 +1 @@
Eine schlanke Bildschirmtastatur für Entwickler

View File

@@ -0,0 +1 @@
Unexpected Keyboard

View File

@@ -1 +1 @@
First open-source release ! First open-source release!

View File

@@ -0,0 +1,8 @@
New languages: German
New keyboard layouts: QWERTZ
Added themes: White, Dark and OLED Black
Added the Action key near the Enter key, required for some app.
Improved some options and fixed a few bugs.

View File

@@ -1,6 +1,18 @@
All the characters you might need are available on a single screen, as well as control, alt, escape and many others. This app is a virtual keyboard for Android. The main features are easy typing of every ASCII character using the swipe gesture, dead keys for accents and modifier keys and the presence of special keys (tab, esc, arrows, etc..).
Several characters are displayed on each key. Get the one in the middle with a press and the ones in the corners by sliding your finger. The keyboard shows up to 4 extra characters in the corners of each key. These extra characters are hit by swiping the finger on the key.
Like any other keyboard app, you will need to activate it in the system settings to be able to use it. Highlight of some of the features:
This can be found in the System Settings > System > Languages & Input > Virtual keyboard > Manage keyboards.
- Every character and special keys that are also available on a PC keyboard. This is perfect for using applications like Termux.
- This includes Tab, Esc, the arrows and function keys, but also Ctrl and Alt !
- Accented keys are accessible using dead keys. First activate the accent, then type the accented letter.
- Very light and fast. Use 500x times less space than Google's keyboard and 15x times less than the default keyboard. No ad, no tracking.
- Multiple layouts: QWERTY, QWERTZ, AZERTY. Themes: White, Dark, OLED Black. And many other options.
Like any other virtual keyboards, it must be enabled in the system settings. Open the System Settings and go to:
System > Languages & Input > Virtual keyboard > Manage keyboards.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,8 @@
Nouvelle langue : Allemand
Nouvelle configuration du clavier : QWERTZ
Thèmes : Clair, Sombre et Noir OLED
Ajout de la touche Action, à côté de la touche Entrer, nécessaire pour certaines applications.
Amélioration des options et résolution de bugs.

View File

@@ -1,3 +1,18 @@
Tous les caractères dont vous pourriez avoir besoin sont disponibles sur un seul écran, ainsi que les touches control, alt, escape et bien d'autres. Cette application est un clavier virtuel pour Android. Les fonctionnalités principales sont l'accès rapide à tous les caractères ASCII en glissant le doigt, les touches mortes pour les accents et la présence des touches spéciales (Tab, Esc, les flèches, etc..).
Plusieurs caractères sont affichés sur chaque touche. Tapez celui du milieu par une simple pression et ceux des coins en faisant glisser votre doigt. Il peut y avoir un caractère supplémentaire dans chaque coin de chaque touche. Ces caractères sont tapés en glissant le doigt sur la touche.
Quelques fonctionnalités:
- Tous les caractères et toutes les touches spéciales d'un clavier PC. Idéal pour utiliser une application comme Termux.
- Cela comprend les touches Tab, Esc, les flèches et les touches fonctions mais aussi Ctrl et Alt !
- Les accents sont des touches mortes. Activez d'abord l'accent et tapez ensuite la lettre accentuée.
- Léger et rapide. Utilise 500x fois moins d'espace que le clavier de Google et 15x fois moins que le clavier de base. Pas de pub, pas de traqueur.
- Plusieurs configurations: QWERTY, QWERTZ, AZERTY. Thèmes: Clair, Sombre, Noir OLED. Et beaucoup d'autres options.
Comme tous les claviers virtuels, il doit être activé dans les paramètres systèmes. Ouvrez les paramètres et allez dans:
Système > Langue & Saisie > Clavier virtuel > Gérer.

View File

@@ -1,38 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:hardwareAccelerated="false">
android:orientation="vertical" <juloo.keyboard2.EmojiGroupButtonsBar android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
android:hardwareAccelerated="false"> <juloo.keyboard2.EmojiGridView android:id="@+id/emoji_grid" android:background="?attr/colorKeyboard" android:layout_width="fill_parent" android:layout_height="@dimen/emoji_grid_height"/>
<juloo.keyboard2.EmojiGroupButtonsBar <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content">
android:orientation="horizontal" <juloo.keyboard2.EmojiKeyButton style="@style/emojiKeyButton" key="switch_back_emoji"/>
android:layout_width="fill_parent" <juloo.keyboard2.EmojiKeyButton style="@style/emojiKeyButton" android:layout_weight="4" key="space"/>
android:layout_height="wrap_content" /> <juloo.keyboard2.EmojiKeyButton style="@style/emojiKeyButton" key="backspace"/>
<juloo.keyboard2.EmojiGridView <juloo.keyboard2.EmojiKeyButton style="@style/emojiKeyButton" key="enter"/>
android:id="@+id/emoji_grid"
android:background="@color/bg"
android:layout_width="fill_parent"
android:layout_height="@dimen/emoji_grid_height"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<juloo.keyboard2.EmojiKeyButton
style="@style/emojiKeyButton"
key="switch_back_emoji"
/>
<juloo.keyboard2.EmojiKeyButton
style="@style/emojiKeyButton"
android:layout_weight="4"
key="space"
/>
<juloo.keyboard2.EmojiKeyButton
style="@style/emojiKeyButton"
key="backspace"
/>
<juloo.keyboard2.EmojiKeyButton
style="@style/emojiKeyButton"
key="enter"
/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -1,5 +1,2 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android" <juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false" android:background="?attr/colorKeyboard"/>
android:background="@color/bg"
android:hardwareAccelerated="false"
/>

View File

@@ -4,10 +4,14 @@
<item>system</item> <item>system</item>
<item>azerty</item> <item>azerty</item>
<item>qwerty</item> <item>qwerty</item>
<item>qwertz</item>
</string-array>
<string-array name="pref_layout_entries">
<item>@string/pref_layout_e_system</item>
<item>AZERTY</item>
<item>QWERTY</item>
<item>QWERTZ</item>
</string-array> </string-array>
<string name="pref_accents_default">1</string>
<string-array name="pref_accents_entries"> <string-array name="pref_accents_entries">
<item>@string/pref_accents_e_all_installed</item> <item>@string/pref_accents_e_all_installed</item>
<item>@string/pref_accents_e_selected</item> <item>@string/pref_accents_e_selected</item>
@@ -20,4 +24,28 @@
<item>3</item> <item>3</item>
<item>4</item> <item>4</item>
</string-array> </string-array>
<string-array name="pref_theme_entries">
<item>@string/pref_theme_e_dark</item>
<item>@string/pref_theme_e_light</item>
<item>@string/pref_theme_e_black</item>
</string-array>
<string-array name="pref_theme_values">
<item>dark</item>
<item>light</item>
<item>black</item>
</string-array>
<string-array name="pref_swipe_dist_entries">
<item>@string/pref_swipe_dist_e_very_short</item>
<item>@string/pref_swipe_dist_e_short</item>
<item>@string/pref_swipe_dist_e_default</item>
<item>@string/pref_swipe_dist_e_far</item>
<item>@string/pref_swipe_dist_e_very_far</item>
</string-array>
<string-array name="pref_swipe_dist_values">
<item>5</item>
<item>7.5</item>
<item>15</item>
<item>25</item>
<item>35</item>
</string-array>
</resources> </resources>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="bg" type="color">#1B1B1B</item>
<item name="key_bg" type="color">#303030</item>
<item name="key_down_bg" type="color">#1B1B1B</item>
<item name="key_label" type="color">#FFFFFF</item>
<item name="key_label_locked" type="color">#229933</item>
<item name="key_label_activated" type="color">#226b99</item>
<item name="key_sub_label" type="color">#A0A0A0</item>
<item name="emoji_button_bg" type="color">#202020</item>
<item name="emoji_color" type="color">#FFFFFF</item>
<item name="emoji_key_bg" type="color">@color/emoji_button_bg</item>
<item name="emoji_key_text" type="color">@color/key_label</item>
</resources>

View File

@@ -7,9 +7,9 @@
<dimen name="key_vertical_interval">2dp</dimen> <dimen name="key_vertical_interval">2dp</dimen>
<dimen name="key_horizontal_interval">2dp</dimen> <dimen name="key_horizontal_interval">2dp</dimen>
<dimen name="key_height">51dp</dimen> <dimen name="key_height">51dp</dimen>
<dimen name="key_round">5dp</dimen>
<dimen name="label_text_size">18dp</dimen> <dimen name="label_text_size">18dp</dimen>
<dimen name="sublabel_text_size">12dp</dimen> <dimen name="sublabel_text_size">12dp</dimen>
<dimen name="emoji_type_button_height">56dp</dimen> <dimen name="emoji_type_button_height">56dp</dimen>
<dimen name="emoji_grid_height">250dp</dimen> <dimen name="emoji_grid_height">250dp</dimen>
<dimen name="emoji_text_size">28dp</dimen>
</resources> </resources>

View File

@@ -1,51 +1,39 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string> <string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard Settings</string> <string name="settings_activity_label">Unexpected Keyboard Settings</string>
<string name="subtype_label">%s</string>
<string name="pref_category_layout">Layout</string> <string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Change keyboard layout</string> <string name="pref_layout_title">Change keyboard layout</string>
<string name="pref_layout_summary">%s</string> <string name="pref_layout_e_system">System settings</string>
<string-array name="pref_layout_entries">
<item>System settings</item>
<item>Azerty</item>
<item>Qwerty</item>
</string-array>
<string name="pref_accents_title">Accents</string> <string name="pref_accents_title">Accents</string>
<string name="pref_accents_summary">%s</string>
<string name="pref_accents_e_all_installed">Show accents for all the installed languages</string> <string name="pref_accents_e_all_installed">Show accents for all the installed languages</string>
<string name="pref_accents_e_selected">Show accents for the selected language</string> <string name="pref_accents_e_selected">Only show accents for the selected language</string>
<string name="pref_accents_e_all">Show every accents</string> <string name="pref_accents_e_all">Show all accents</string>
<string name="pref_accents_e_none">Hide accents</string> <string name="pref_accents_e_none">Hide accents</string>
<string name="pref_category_typing">Typing</string> <string name="pref_category_typing">Typing</string>
<string name="pref_preci_title">Precision</string> <string name="pref_swipe_dist_title">Swiping distance</string>
<string name="pref_preci_summary">Distance of corner values (%spx)</string> <string name="pref_swipe_dist_summary">Distance of characters in the corners of the keys (%s)</string>
<string name="pref_long_timeout_title">Long press timeout</string> <string name="pref_long_timeout_title">Long press timeout</string>
<string name="pref_long_timeout_summary">%sms</string>
<string name="pref_long_interval_title">Long press interval</string> <string name="pref_long_interval_title">Long press interval</string>
<string name="pref_long_interval_summary">%sms</string>
<string name="pref_category_vibrate">Vibration</string> <string name="pref_category_vibrate">Vibration</string>
<string name="pref_vibrate_title">Vibration</string> <string name="pref_vibrate_title">Vibration</string>
<string name="pref_vibrate_summary">Enable/Disable vibrations on key down</string> <string name="pref_vibrate_summary">Enable/disable vibration on keypress</string>
<string name="pref_vibrate_duration_title">Duration</string> <string name="pref_vibrate_duration_title">Duration</string>
<string name="pref_vibrate_duration_summary">%sms</string>
<string name="pref_precise_repeat_title">Precise cursor movements</string> <string name="pref_precise_repeat_title">Precise cursor movements</string>
<string name="pref_precise_repeat_summary">Modulate the speed of movements by swiping more or less</string> <string name="pref_precise_repeat_summary">Modulate the speed of movements by swiping more or less</string>
<string name="pref_category_style">Style</string> <string name="pref_category_style">Style</string>
<string name="pref_margin_bottom_title">Margin bottom</string> <string name="pref_margin_bottom_title">Margin bottom</string>
<string name="pref_margin_bottom_summary">%sdp</string>
<string name="pref_key_height_title">Key height</string> <string name="pref_key_height_title">Key height</string>
<string name="pref_key_height_summary">%sdp</string>
<string name="pref_horizontal_margin_title">Horizontal margin</string> <string name="pref_horizontal_margin_title">Horizontal margin</string>
<string name="pref_horizontal_margin_summary">%sdp</string>
<string name="pref_character_size_title">Label size</string> <string name="pref_character_size_title">Label size</string>
<string name="pref_character_size_summary">Size of characters displayed on the keyboard (%.2fx)</string> <string name="pref_character_size_summary">Size of characters displayed on the keyboard (%.2fx)</string>
<string name="pref_theme">Theme</string>
<string name="pref_theme_e_dark">Dark</string>
<string name="pref_theme_e_light">Light</string>
<string name="pref_theme_e_black">Black</string>
<string name="pref_swipe_dist_e_very_short">Very short</string>
<string name="pref_swipe_dist_e_short">Short</string>
<string name="pref_swipe_dist_e_default">Normal</string>
<string name="pref_swipe_dist_e_far">Far</string>
<string name="pref_swipe_dist_e_very_far">Very far</string>
</resources> </resources>

View File

@@ -4,8 +4,8 @@
<item name="android:padding">1px</item> <item name="android:padding">1px</item>
<item name="android:gravity">center</item> <item name="android:gravity">center</item>
<item name="android:minHeight">@dimen/label_text_size</item> <item name="android:minHeight">@dimen/label_text_size</item>
<item name="android:background">@color/emoji_button_bg</item> <item name="android:background">?attr/emoji_button_bg</item>
<item name="android:textColor">@color/emoji_key_text</item> <item name="android:textColor">?attr/emoji_key_text</item>
<item name="android:textSize">@dimen/label_text_size</item> <item name="android:textSize">@dimen/label_text_size</item>
</style> </style>
<style name="emojiKeyButton"> <style name="emojiKeyButton">
@@ -13,8 +13,13 @@
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item> <item name="android:layout_weight">1</item>
<item name="android:padding">0px</item> <item name="android:padding">0px</item>
<item name="android:background">@color/emoji_key_bg</item> <item name="android:background">?attr/emoji_key_bg</item>
<item name="android:textColor">@color/emoji_key_text</item> <item name="android:textColor">?attr/emoji_key_text</item>
<item name="android:textSize">@dimen/label_text_size</item> <item name="android:textSize">@dimen/label_text_size</item>
</style> </style>
<!-- Passed to TextView.setTextAppearance -->
<style name="emojiGridButton">
<item name="android:textSize">@dimen/emoji_text_size</item>
<item name="android:textColor">?attr/emoji_color</item>
</style>
</resources> </resources>

66
res/values/themes.xml Normal file
View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="keyboard">
<!-- The background of the keyboard -->
<attr name="colorKeyboard" format="color"/>
<!-- Background of the keys -->
<attr name="colorKey" format="color"/>
<!-- Background of the keys when pressed -->
<attr name="colorKeyActivated" format="color"/>
<!-- Label colors -->
<attr name="colorLabel" format="color"/>
<attr name="colorLabelActivated" format="color"/>
<attr name="colorLabelLocked" format="color"/>
<!-- Corner labels -->
<attr name="colorSubLabel" format="color"/>
<!-- Dimens -->
<attr name="keyBorderRadius" format="dimension"/>
<!-- Emoji panel -->
<attr name="emoji_button_bg" type="color" format="color"/>
<attr name="emoji_color" type="color" format="color"/>
<attr name="emoji_key_bg" type="color" format="color"/>
<attr name="emoji_key_text" type="color" format="color"/>
</declare-styleable>
<style name="Dark">
<item name="colorKeyboard">#1B1B1B</item>
<item name="colorKey">#303030</item>
<item name="colorKeyActivated">#1B1B1B</item>
<item name="colorLabel">#FFFFFF</item>
<item name="colorLabelActivated">#226b99</item>
<item name="colorLabelLocked">#229933</item>
<item name="colorSubLabel">#A0A0A0</item>
<item name="keyBorderRadius">5dp</item>
<item name="emoji_button_bg" type="color">#202020</item>
<item name="emoji_color" type="color">#FFFFFF</item>
<item name="emoji_key_bg" type="color">?attr/emoji_button_bg</item>
<item name="emoji_key_text" type="color">?attr/colorLabel</item>
</style>
<style name="Light">
<item name="colorKeyboard">#e3e3e3</item>
<item name="colorKey">#cfcfcf</item>
<item name="colorKeyActivated">#e3e3e3</item>
<item name="colorLabel">#000000</item>
<item name="colorLabelActivated">#64afdd</item>
<item name="colorLabelLocked">#64dd76</item>
<item name="colorSubLabel">#5e5e5e</item>
<item name="keyBorderRadius">5dp</item>
<item name="emoji_button_bg" type="color">#dedede</item>
<item name="emoji_color" type="color">#000000</item>
<item name="emoji_key_bg" type="color">?attr/emoji_button_bg</item>
<item name="emoji_key_text" type="color">?attr/colorLabel</item>
</style>
<style name="Black">
<item name="colorKeyboard">#000000</item>
<item name="colorKey">#000000</item>
<item name="colorKeyActivated">#333333</item>
<item name="colorLabel">#eeeeee</item>
<item name="colorLabelActivated">#009dff</item>
<item name="colorLabelLocked">#00ff26</item>
<item name="colorSubLabel">#bbbbbb</item>
<item name="keyBorderRadius">1dp</item>
<item name="emoji_button_bg" type="color">#000000</item>
<item name="emoji_color" type="color">#ffffff</item>
<item name="emoji_key_bg" type="color">?attr/emoji_button_bg</item>
<item name="emoji_key_text" type="color">?attr/colorLabel</item>
</style>
</resources>

View File

@@ -1,44 +1,44 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="a" key1="esc" key2="1" key3="&amp;" /> <key key0="a" key1="esc" key2="1" key3="&amp;"/>
<key key0="z" key2="2" key4="~" /> <key key0="z" key2="2" key4="~"/>
<key key0="e" key2="3" key3="&quot;" key4="\#" /> <key key0="e" key2="3" key3="&quot;" key4="\#"/>
<key key0="r" key2="4" key3="'" /> <key key0="r" key2="4" key3="'"/>
<key key0="t" key2="5" key3="(" key4=")" /> <key key0="t" key2="5" key3="(" key4=")"/>
<key key0="y" key2="6" key3="-" key4="|" /> <key key0="y" key2="6" key3="-" key4="|"/>
<key key0="u" key2="7" key4="`" /> <key key0="u" key2="7" key4="`"/>
<key key0="i" key2="8" key3="_" key4="\\" /> <key key0="i" key2="8" key3="_" key4="\\"/>
<key key0="o" key2="9" /> <key key0="o" key2="9"/>
<key key0="p" key2="0" key4="\@" /> <key key0="p" key2="0" key4="\@"/>
</row> </row>
<row> <row>
<key key0="q" key1="tab" /> <key key0="q" key1="tab"/>
<key key0="s" key1="accent_ring" /> <key key0="s" key1="accent_ring" key3="ß"/>
<key key0="d" key1="accent_grave" key3="accent_aigu" /> <key key0="d" key1="accent_grave" key3="accent_aigu"/>
<key key0="f" key3="{" key4="}" /> <key key0="f" key3="{" key4="}"/>
<key key0="g" key3="[" key4="]" /> <key key0="g" key3="[" key4="]"/>
<key key0="h" key3="=" key4="+" /> <key key0="h" key3="=" key4="+"/>
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key3="^" /> <key key0="j" key1="accent_trema" key2="accent_circonflexe" key3="^"/>
<key key0="k" key2="€" key3="$" key4="£" /> <key key0="k" key2="€" key3="$" key4="£"/>
<key key0="l" key2="%" /> <key key0="l" key2="%"/>
<key key0="m" key4="*" /> <key key0="m" key4="*"/>
</row> </row>
<row> <row>
<key width="2.0" key0="shift" /> <key width="2.0" key0="shift"/>
<key key0="w" key3="&lt;" key4="&gt;" /> <key key0="w" key3="&lt;" key4="&gt;"/>
<key key0="x" /> <key key0="x"/>
<key key0="c" key1="accent_cedille" key3="," key4="\?" /> <key key0="c" key1="accent_cedille" key3="," key4="\?"/>
<key key0="v" key3=";" key4="." /> <key key0="v" key3=";" key4="."/>
<key key0="b" key3=":" key4="/" /> <key key0="b" key3=":" key4="/"/>
<key key0="n" key1="accent_tilde" key2="§" key4="!" /> <key key0="n" key1="accent_tilde" key2="§" key4="!"/>
<key width="2.0" key0="backspace" key2="delete" /> <key width="2.0" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95"> <row height="0.95">
<key width="1.8" key0="ctrl" key3="switch_numeric" /> <key width="1.8" key0="ctrl" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config" /> <key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space" /> <key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" /> <key width="1.2" key1="up" key2="right" key3="left" key4="down"/>
<key width="1.8" key0="enter" /> <key width="1.8" key0="enter" key2="action"/>
</row> </row>
</keyboard> </keyboard>

View File

@@ -1,40 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
android:settingsActivity="juloo.keyboard2.SettingsActivity" <subtype android:label="%s" android:languageTag="en" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty"/>
android:supportsSwitchingToNextInputMethod="true"> <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"/>
<subtype android:label="@string/subtype_label" <subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=aigu|tilde|trema"/>
android:languageTag="en" <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"/>
android:imeSubtypeLocale="en_US" <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"/>
android:imeSubtypeMode="keyboard" <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"/>
android:isAsciiCapable="true"
android:imeSubtypeExtraValue="default_layout=qwerty"
/>
<subtype android:label="@string/subtype_label"
android:languageTag="fr"
android:imeSubtypeLocale="fr_FR"
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:imeSubtypeExtraValue="default_layout=azerty,accents=grave|aigu|circonflexe|cedille|trema"
/>
<subtype android:label="@string/subtype_label"
android:languageTag="es"
android:imeSubtypeLocale="es_ES"
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:imeSubtypeExtraValue="default_layout=qwerty,accents=aigu|tilde|trema"
/>
<subtype android:label="@string/subtype_label"
android:languageTag="it"
android:imeSubtypeLocale="it_IT"
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:imeSubtypeExtraValue="default_layout=qwerty,accents=grave|aigu"
/>
<subtype android:label="@string/subtype_label"
android:languageTag="sv"
android:imeSubtypeLocale="sv_SE"
android:imeSubtypeMode="keyboard"
android:isAsciiCapable="true"
android:imeSubtypeExtraValue="default_layout=qwerty,accents=aigu|trema|ring"
/>
</input-method> </input-method>

View File

@@ -1,35 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key width="0.75" key0="esc" key2="~" key4="!" /> <key width="0.75" key0="esc" key2="~" key4="!"/>
<key width="0.75" key0="(" key2="[" key4="{" /> <key width="0.75" key0="(" key2="[" key4="{"/>
<key key0="7" key3="&lt;" key4="&gt;" /> <key key0="7" key3="&lt;" key4="&gt;"/>
<key key0="8" key2="∞" /> <key key0="8" key2="∞"/>
<key key0="9" key2="π" /> <key key0="9" key2="π"/>
<key width="0.75" key0="*" key1="√" key2="×" /> <key width="0.75" key0="*" key1="√" key2="×"/>
<key width="0.75" key0="/" key1="%" key3="÷" /> <key width="0.75" key0="/" key1="%" key3="÷"/>
</row> </row>
<row> <row>
<key width="0.75" key0="tab" key1=";" key2="|" key4="\\" /> <key width="0.75" key0="tab" key1=";" key2="|" key4="\\"/>
<key width="0.75" key0=")" key2="]" key4="}" /> <key width="0.75" key0=")" key2="]" key4="}"/>
<key key0="4" /> <key key0="4"/>
<key key0="5" key1="up" key2="right" key3="left" key4="down" /> <key key0="5" key1="up" key2="right" key3="left" key4="down"/>
<key key0="6" /> <key key0="6"/>
<key width="0.75" key0="+" key1="Σ" key2="$" /> <key width="0.75" key0="+" key1="Σ" key2="$"/>
<key width="0.75" key0="-" key2="^" /> <key width="0.75" key0="-" key2="^"/>
</row> </row>
<row> <row>
<key shift="0.35" width="1.15" key0="shift" key2="fn" key4="alt" /> <key shift="0.35" width="1.15" key0="shift" key2="fn" key4="alt"/>
<key key0="1" key1="superscript" key3="subscript" /> <key key0="1" key1="superscript" key3="subscript"/>
<key key0="2" /> <key key0="2"/>
<key key0="3" /> <key key0="3"/>
<key width="1.15" key0="backspace" key2="delete" /> <key width="1.15" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95"> <row height="0.95">
<key width="1.5" key0="ctrl" key3="switch_text" /> <key width="1.5" key0="ctrl" key3="switch_text"/>
<key width="1.5" key0="0" /> <key width="1.5" key0="0"/>
<key width="0.75" key0="." key2="," /> <key width="0.75" key0="." key2=","/>
<key width="0.75" key0="space" key1="&quot;" key2="'" key4="_" /> <key width="0.75" key0="space" key1="&quot;" key2="'" key4="_"/>
<key width="1.5" key0="enter" key2=" key3="=" /> <key width="1.5" key0="enter" key1="±" key2="action" key3="="/>
</row> </row>
</keyboard> </keyboard>

View File

@@ -1,44 +1,44 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="q" key1="esc" key2="1" key3="~" key4="!" /> <key key0="q" key1="esc" key2="1" key3="~" key4="!"/>
<key key0="w" key2="2" key3="\@" /> <key key0="w" key2="2" key3="\@"/>
<key key0="e" key2="3" key3="\#" /> <key key0="e" key2="3" key3="\#"/>
<key key0="r" key2="4" key3="$" /> <key key0="r" key2="4" key3="$"/>
<key key0="t" key2="5" key3="%" /> <key key0="t" key2="5" key3="%"/>
<key key0="y" key2="6" key3="^" /> <key key0="y" key2="6" key3="^"/>
<key key0="u" key2="7" key3="&amp;" /> <key key0="u" key2="7" key3="&amp;"/>
<key key0="i" key2="8" key3="*" /> <key key0="i" key2="8" key3="*"/>
<key key0="o" key2="9" key3="(" key4=")" /> <key key0="o" key2="9" key3="(" key4=")"/>
<key key0="p" key2="0" /> <key key0="p" key2="0"/>
</row> </row>
<row> <row>
<key shift="0.5" key0="a" key1="tab" key2="`" /> <key shift="0.5" key0="a" key1="tab" key2="`"/>
<key key0="s" key1="accent_ring" /> <key key0="s" key1="accent_ring" key3="ß"/>
<key key0="d" key1="accent_grave" key3="accent_aigu" /> <key key0="d" key1="accent_grave" key3="accent_aigu"/>
<key key0="f" /> <key key0="f"/>
<key key0="g" key2="-" key3="_" /> <key key0="g" key2="-" key3="_"/>
<key key0="h" key2="=" key3="+" /> <key key0="h" key2="=" key3="+"/>
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{" /> <key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
<key key0="k" key4="]" key3="[" /> <key key0="k" key4="]" key3="["/>
<key key0="l" key2="|" key3="\\" /> <key key0="l" key2="|" key3="\\"/>
</row> </row>
<row> <row>
<key width="1.5" key0="shift" /> <key width="1.5" key0="shift"/>
<key key0="z" /> <key key0="z"/>
<key key0="x" /> <key key0="x"/>
<key key0="c" key1="accent_cedille" key2="&lt;" key3="." /> <key key0="c" key1="accent_cedille" key2="&lt;" key3="."/>
<key key0="v" key2="&gt;" key3="," /> <key key0="v" key2="&gt;" key3=","/>
<key key0="b" key2="\?" key3="/" /> <key key0="b" key2="\?" key3="/"/>
<key key0="n" key1="accent_tilde" key2=":" key3=";" /> <key key0="n" key1="accent_tilde" key2=":" key3=";"/>
<key key0="m" key2="&quot;" key3="'" /> <key key0="m" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete" /> <key width="1.5" key0="backspace" key2="delete"/>
</row> </row>
<row height="0.95"> <row height="0.95">
<key width="1.8" key0="ctrl" key3="switch_numeric" /> <key width="1.8" key0="ctrl" key3="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config" /> <key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space" /> <key width="4.0" key0="space"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" /> <key width="1.2" key1="up" key2="right" key3="left" key4="down"/>
<key width="1.8" key0="enter" /> <key width="1.8" key0="enter" key2="action"/>
</row> </row>
</keyboard> </keyboard>

44
res/xml/qwertz.xml Normal file
View File

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

View File

@@ -1,102 +1,24 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/pref_category_layout"> <PreferenceCategory android:title="@string/pref_category_layout">
<ListPreference <ListPreference android:key="layout" android:title="@string/pref_layout_title" android:summary="%s" android:defaultValue="system" android:entries="@array/pref_layout_entries" android:entryValues="@array/pref_layout_values"/>
android:key="layout" <ListPreference android:key="accents" android:title="@string/pref_accents_title" android:summary="%s" android:defaultValue="1" android:entries="@array/pref_accents_entries" android:entryValues="@array/pref_accents_values"/>
android:title="@string/pref_layout_title"
android:summary="@string/pref_layout_summary"
android:defaultValue="system"
android:entries="@array/pref_layout_entries"
android:entryValues="@array/pref_layout_values" />
/>
<ListPreference
android:key="accents"
android:title="@string/pref_accents_title"
android:summary="@string/pref_accents_summary"
android:defaultValue="@string/pref_accents_default"
android:entries="@array/pref_accents_entries"
android:entryValues="@array/pref_accents_values" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_typing"> <PreferenceCategory android:title="@string/pref_category_typing">
<juloo.common.SlideBarPreference <ListPreference android:key="swipe_dist" android:title="@string/pref_swipe_dist_title" android:summary="@string/pref_swipe_dist_summary" android:defaultValue="15" android:entries="@array/pref_swipe_dist_entries" android:entryValues="@array/pref_swipe_dist_values"/>
android:key="sub_value_dist" <juloo.common.IntSlideBarPreference android:key="longpress_timeout" android:title="@string/pref_long_timeout_title" android:summary="%sms" android:defaultValue="600" min="50" max="2000"/>
android:title="@string/pref_preci_title" <juloo.common.IntSlideBarPreference android:key="longpress_interval" android:title="@string/pref_long_interval_title" android:summary="%sms" android:defaultValue="25" min="5" max="100"/>
android:summary="@string/pref_preci_summary" <CheckBoxPreference android:key="precise_repeat" android:title="@string/pref_precise_repeat_title" android:summary="@string/pref_precise_repeat_summary" android:defaultValue="true"/>
android:defaultValue="10.0"
min="5.0"
max="25.0"
/>
<juloo.common.IntSlideBarPreference
android:key="longpress_timeout"
android:title="@string/pref_long_timeout_title"
android:summary="@string/pref_long_timeout_summary"
android:defaultValue="600"
min="50"
max="2000"
/>
<juloo.common.IntSlideBarPreference
android:key="longpress_interval"
android:title="@string/pref_long_interval_title"
android:summary="@string/pref_long_interval_summary"
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"
/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_vibrate"> <PreferenceCategory android:title="@string/pref_category_vibrate">
<CheckBoxPreference <CheckBoxPreference android:key="vibrate_enabled" android:title="@string/pref_vibrate_title" android:summary="@string/pref_vibrate_summary" android:defaultValue="true"/>
android:key="vibrate_enabled" <juloo.common.IntSlideBarPreference android:key="vibrate_duration" android:title="@string/pref_vibrate_duration_title" android:summary="%sms" android:defaultValue="20" min="5" max="50"/>
android:title="@string/pref_vibrate_title"
android:summary="@string/pref_vibrate_summary"
android:defaultValue="true"
/>
<juloo.common.IntSlideBarPreference
android:key="vibrate_duration"
android:title="@string/pref_vibrate_duration_title"
android:summary="@string/pref_vibrate_duration_summary"
android:defaultValue="20"
min="5"
max="50"
/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_style"> <PreferenceCategory android:title="@string/pref_category_style">
<juloo.common.IntSlideBarPreference <ListPreference android:key="theme" android:title="@string/pref_theme" android:summary="%s" android:defaultValue="dark" android:entries="@array/pref_theme_entries" android:entryValues="@array/pref_theme_values"/>
android:key="margin_bottom" <juloo.common.IntSlideBarPreference android:key="margin_bottom" android:title="@string/pref_margin_bottom_title" android:summary="%sdp" android:defaultValue="5" min="0" max="100"/>
android:title="@string/pref_margin_bottom_title" <juloo.common.IntSlideBarPreference android:key="key_height" android:title="@string/pref_key_height_title" android:summary="%sdp" android:defaultValue="50" min="30" max="90"/>
android:summary="@string/pref_margin_bottom_summary" <juloo.common.IntSlideBarPreference android:key="horizontal_margin" android:title="@string/pref_horizontal_margin_title" android:summary="%sdp" android:defaultValue="3" min="0" max="20"/>
android:defaultValue="5" <juloo.common.SlideBarPreference android:key="character_size" android:title="@string/pref_character_size_title" android:summary="@string/pref_character_size_summary" android:defaultValue="1.0" min="0.8" max="1.2"/>
min="0"
max="100"
/>
<juloo.common.IntSlideBarPreference
android:key="key_height"
android:title="@string/pref_key_height_title"
android:summary="@string/pref_key_height_summary"
android:defaultValue="50"
min="30"
max="90"
/>
<juloo.common.IntSlideBarPreference
android:key="horizontal_margin"
android:title="@string/pref_horizontal_margin_title"
android:summary="@string/pref_horizontal_margin_summary"
android:defaultValue="3"
min="0"
max="20"
/>
<juloo.common.SlideBarPreference
android:key="character_size"
android:title="@string/pref_character_size_title"
android:summary="@string/pref_character_size_summary"
android:defaultValue="1.0"
min="0.8"
max="1.2"
/>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -4,18 +4,20 @@
} }: } }:
let let
jdk = pkgs.openjdk8;
android = pkgs.androidenv.composeAndroidPackages { android = pkgs.androidenv.composeAndroidPackages {
buildToolsVersions = [ "30.0.3" ]; buildToolsVersions = [ "30.0.3" ];
platformVersions = [ "29" ]; platformVersions = [ "30" ];
abiVersions = [ "armeabi-v7a" ]; abiVersions = [ "armeabi-v7a" ];
}; };
in apksigner = pkgs.apksigner.override {
inherit (jdk) jre;
inherit (android) build-tools;
};
pkgs.mkShell { in pkgs.mkShell {
buildInputs = with pkgs; [ buildInputs = [ pkgs.findutils jdk android.androidsdk apksigner ];
findutils openjdk8 android.androidsdk
];
ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk"; ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk";
} }

View File

@@ -11,17 +11,17 @@ import android.widget.TextView;
import android.widget.SeekBar; import android.widget.SeekBar;
/* /*
** IntSlideBarPreference ** IntSlideBarPreference
** - ** -
** Open a dialog showing a seekbar ** Open a dialog showing a seekbar
** - ** -
** xml attrs: ** xml attrs:
** android:defaultValue Default value (int) ** android:defaultValue Default value (int)
** min min value (int) ** min min value (int)
** max max value (int) ** max max value (int)
** - ** -
** Summary field allow to show the current value using %s flag ** Summary field allow to show the current value using %s flag
*/ */
public class IntSlideBarPreference extends DialogPreference public class IntSlideBarPreference extends DialogPreference
implements SeekBar.OnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener
{ {

View File

@@ -11,17 +11,17 @@ import android.widget.TextView;
import android.widget.SeekBar; import android.widget.SeekBar;
/* /*
** SideBarPreference ** SideBarPreference
** - ** -
** Open a dialog showing a seekbar ** Open a dialog showing a seekbar
** - ** -
** xml attrs: ** xml attrs:
** android:defaultValue Default value (float) ** android:defaultValue Default value (float)
** min min value (float) ** min min value (float)
** max max value (float) ** max max value (float)
** - ** -
** Summary field allow to show the current value using %f or %s flag ** Summary field allow to show the current value using %f or %s flag
*/ */
public class SlideBarPreference extends DialogPreference public class SlideBarPreference extends DialogPreference
implements SeekBar.OnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener
{ {

View File

@@ -1,24 +1,24 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.TypedValue; import android.util.TypedValue;
class Config final class Config
{ {
private Keyboard2 _context;
// From resources // From resources
public final float marginTop; public final float marginTop;
public final float keyPadding; public final float keyPadding;
public final float keyVerticalInterval; public final float keyVerticalInterval;
public final float keyHorizontalInterval; public final float keyHorizontalInterval;
public final float keyRound;
// From preferences // From preferences
public int layout; // Or '-1' for the system defaults public int layout; // Or '-1' for the system defaults
public float subValueDist; private float swipe_dist_dp;
public float swipe_dist_px;
public boolean vibrateEnabled; public boolean vibrateEnabled;
public long vibrateDuration; public long vibrateDuration;
public long longPressTimeout; public long longPressTimeout;
@@ -29,25 +29,27 @@ class Config
public boolean preciseRepeat; public boolean preciseRepeat;
public float characterSize; // Ratio public float characterSize; // Ratio
public int accents; // Values are R.values.pref_accents_v_* public int accents; // Values are R.values.pref_accents_v_*
public int theme; // Values are R.style.*
// Dynamically set // Dynamically set
public boolean shouldOfferSwitchingToNextInputMethod; public boolean shouldOfferSwitchingToNextInputMethod;
public int accent_flags_to_remove; 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 Config(Keyboard2 context) public final IKeyEventHandler handler;
private Config(Context context, IKeyEventHandler h)
{ {
Resources res = context.getResources(); Resources res = context.getResources();
_context = context;
// static values // static values
marginTop = res.getDimension(R.dimen.margin_top); marginTop = res.getDimension(R.dimen.margin_top);
keyPadding = res.getDimension(R.dimen.key_padding); keyPadding = res.getDimension(R.dimen.key_padding);
keyVerticalInterval = res.getDimension(R.dimen.key_vertical_interval); keyVerticalInterval = res.getDimension(R.dimen.key_vertical_interval);
keyHorizontalInterval = res.getDimension(R.dimen.key_horizontal_interval); keyHorizontalInterval = res.getDimension(R.dimen.key_horizontal_interval);
keyRound = res.getDimension(R.dimen.key_round);
// default values // default values
layout = -1; layout = -1;
subValueDist = 10f;
vibrateEnabled = true; vibrateEnabled = true;
vibrateDuration = 20; vibrateDuration = 20;
longPressTimeout = 600; longPressTimeout = 600;
@@ -59,41 +61,47 @@ class Config
characterSize = 1.f; characterSize = 1.f;
accents = 1; accents = 1;
// from prefs // from prefs
refresh(); refresh(context);
// initialized later // initialized later
shouldOfferSwitchingToNextInputMethod = false; shouldOfferSwitchingToNextInputMethod = false;
accent_flags_to_remove = 0; key_flags_to_remove = 0;
actionLabel = null;
actionId = 0;
swapEnterActionKey = false;
handler = h;
} }
/* /*
** Reload prefs ** Reload prefs
*/ */
public void refresh() public void refresh(Context context)
{ {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(_context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
DisplayMetrics dm = context.getResources().getDisplayMetrics();
layout = layoutId_of_string(prefs.getString("layout", "system")); layout = layoutId_of_string(prefs.getString("layout", "system"));
subValueDist = prefs.getFloat("sub_value_dist", subValueDist); swipe_dist_dp = Float.valueOf(prefs.getString("swipe_dist", "15"));
swipe_dist_px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, swipe_dist_dp, dm);
vibrateEnabled = prefs.getBoolean("vibrate_enabled", vibrateEnabled); vibrateEnabled = prefs.getBoolean("vibrate_enabled", vibrateEnabled);
vibrateDuration = prefs.getInt("vibrate_duration", (int)vibrateDuration); vibrateDuration = prefs.getInt("vibrate_duration", (int)vibrateDuration);
longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout); longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout);
longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval); longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval);
marginBottom = getDipPref(prefs, "margin_bottom", marginBottom); marginBottom = getDipPref(dm, prefs, "margin_bottom", marginBottom);
keyHeight = getDipPref(prefs, "key_height", keyHeight); // Add keyVerticalInterval to keyHeight because the space between the keys
horizontalMargin = getDipPref(prefs, "horizontal_margin", horizontalMargin); // is removed from the keys during rendering
keyHeight = getDipPref(dm, prefs, "key_height", keyHeight) + keyVerticalInterval;
horizontalMargin = getDipPref(dm, prefs, "horizontal_margin", horizontalMargin);
preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat); preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
characterSize = prefs.getFloat("character_size", characterSize); characterSize = prefs.getFloat("character_size", characterSize);
accents = Integer.valueOf(prefs.getString("accents", "1")); accents = Integer.valueOf(prefs.getString("accents", "1"));
theme = themeId_of_string(prefs.getString("theme", ""));
} }
private float getDipPref(SharedPreferences prefs, String pref_name, float def) private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
{ {
int value = prefs.getInt(pref_name, -1); int value = prefs.getInt(pref_name, -1);
if (value < 0) if (value < 0)
return (def); return (def);
return (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, return (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm));
_context.getResources().getDisplayMetrics()));
} }
public static int layoutId_of_string(String name) public static int layoutId_of_string(String name)
@@ -102,13 +110,13 @@ class Config
{ {
case "azerty": return R.xml.azerty; case "azerty": return R.xml.azerty;
case "qwerty": return R.xml.qwerty; case "qwerty": return R.xml.qwerty;
case "system": return -1; case "qwertz": return R.xml.qwertz;
default: throw new IllegalArgumentException(); case "system": default: return -1;
} }
} }
/* Used for the accents option. */ /* Used for the accents option. */
public static int accentFlag_of_name(String name) public static int extra_key_flag_of_name(String name)
{ {
switch (name) switch (name)
{ {
@@ -119,7 +127,35 @@ class Config
case "cedille": return KeyValue.FLAG_ACCENT5; case "cedille": return KeyValue.FLAG_ACCENT5;
case "trema": return KeyValue.FLAG_ACCENT6; case "trema": return KeyValue.FLAG_ACCENT6;
case "ring": return KeyValue.FLAG_ACCENT_RING; case "ring": return KeyValue.FLAG_ACCENT_RING;
case "szlig": return KeyValue.FLAG_LANG_SZLIG;
default: throw new RuntimeException(name); default: throw new RuntimeException(name);
} }
} }
public static int themeId_of_string(String name)
{
switch (name)
{
case "light": return R.style.Light;
case "black": return R.style.Black;
default: case "dark": return R.style.Dark;
}
}
private static Config _globalConfig = null;
public static void initGlobalConfig(Context context, IKeyEventHandler handler)
{
_globalConfig = new Config(context, handler);
}
public static Config globalConfig()
{
return _globalConfig;
}
public static interface IKeyEventHandler
{
public void handleKeyUp(KeyValue value, int flags);
}
} }

View File

@@ -24,7 +24,6 @@ public class EmojiGridView extends GridView
public static final int GROUP_LAST_USE = -1; public static final int GROUP_LAST_USE = -1;
public static final int COLUMN_WIDTH = 192; public static final int COLUMN_WIDTH = 192;
public static final float EMOJI_SIZE = 32.f;
private static final String LAST_USE_PREF = "emoji_last_use"; private static final String LAST_USE_PREF = "emoji_last_use";
@@ -48,16 +47,15 @@ public class EmojiGridView extends GridView
public void setEmojiGroup(int group) public void setEmojiGroup(int group)
{ {
_emojiArray = (group == GROUP_LAST_USE) ? getLastEmojis() : Emoji.getEmojisByGroup(group); _emojiArray = (group == GROUP_LAST_USE) ? getLastEmojis() : Emoji.getEmojisByGroup(group);
setAdapter(new EmojiViewAdpater((Keyboard2)getContext(), _emojiArray)); setAdapter(new EmojiViewAdpater(getContext(), _emojiArray));
} }
public void onItemClick(AdapterView<?> parent, View v, int pos, long id) public void onItemClick(AdapterView<?> parent, View v, int pos, long id)
{ {
Keyboard2 main = (Keyboard2)getContext(); Config config = Config.globalConfig();
Integer used = _lastUsed.get(_emojiArray[pos]); Integer used = _lastUsed.get(_emojiArray[pos]);
_lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1); _lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1);
main.handleKeyUp(_emojiArray[pos], 0); config.handler.handleKeyUp(_emojiArray[pos], 0);
saveLastUsed(); // TODO: opti saveLastUsed(); // TODO: opti
} }
@@ -118,13 +116,11 @@ public class EmojiGridView extends GridView
private static class EmojiView extends TextView private static class EmojiView extends TextView
{ {
public EmojiView(Keyboard2 context) public EmojiView(Context context)
{ {
super(context); super(context);
setTextSize(EMOJI_SIZE); setTextAppearance(context, R.style.emojiGridButton);
setGravity(Gravity.CENTER); setGravity(Gravity.CENTER);
setBackgroundColor(0x0);
setTextColor(getResources().getColor(R.color.emoji_color));
setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT)); setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT));
} }
@@ -136,13 +132,13 @@ public class EmojiGridView extends GridView
private static class EmojiViewAdpater extends BaseAdapter private static class EmojiViewAdpater extends BaseAdapter
{ {
private Keyboard2 _main; private Context _context;
private Emoji[] _emojiArray; private Emoji[] _emojiArray;
public EmojiViewAdpater(Keyboard2 main, Emoji[] emojiArray) public EmojiViewAdpater(Context context, Emoji[] emojiArray)
{ {
_main = main; _context = context;
_emojiArray = emojiArray; _emojiArray = emojiArray;
} }
@@ -168,7 +164,7 @@ public class EmojiGridView extends GridView
EmojiView view = (EmojiView)convertView; EmojiView view = (EmojiView)convertView;
if (view == null) if (view == null)
view = new EmojiView(_main); view = new EmojiView(_context);
view.setEmoji(_emojiArray[pos]); view.setEmoji(_emojiArray[pos]);
return (view); return (view);
} }

View File

@@ -17,13 +17,12 @@ public class EmojiKeyButton extends Button
_key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key")); _key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key"));
setText(_key.symbol); setText(_key.symbol);
if ((_key.flags & KeyValue.FLAG_KEY_FONT) != 0) if ((_key.flags & KeyValue.FLAG_KEY_FONT) != 0)
setTypeface(((Keyboard2)context).getSpecialKeyFont()); setTypeface(Theme.getSpecialKeyFont(context));
} }
public void onClick(View v) public void onClick(View v)
{ {
Keyboard2 main = (Keyboard2)getContext(); Config config = Config.globalConfig();
config.handler.handleKeyUp(_key, 0);
main.handleKeyUp(_key, 0);
} }
} }

View File

@@ -0,0 +1,78 @@
package juloo.keyboard2;
import android.view.KeyEvent;
class KeyEventHandler implements Config.IKeyEventHandler
{
private IReceiver _recv;
public KeyEventHandler(IReceiver recv)
{
_recv = recv;
}
public void handleKeyUp(KeyValue key, int flags)
{
key = KeyModifier.handleFlags(key, flags);
switch (key.eventCode)
{
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return;
case KeyValue.EVENT_SWITCH_TEXT: _recv.setLayout(-1); return;
case KeyValue.EVENT_SWITCH_NUMERIC: _recv.setLayout(R.xml.numeric); return;
case KeyValue.EVENT_SWITCH_EMOJI: _recv.setPane_emoji(); return;
case KeyValue.EVENT_SWITCH_BACK_EMOJI: _recv.setPane_normal(); return;
case KeyValue.EVENT_CHANGE_METHOD: _recv.switchToNextInputMethod(); return;
case KeyValue.EVENT_ACTION: _recv.performAction(); return;
default:
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT)) != 0)
handleMetaKeyUp(key, flags);
else if (key.char_ != KeyValue.CHAR_NONE)
_recv.commitChar(key.char_);
else if (key.eventCode != KeyValue.EVENT_NONE)
handleMetaKeyUp(key, flags);
else
_recv.commitText(key.symbol);
}
}
// private void handleDelKey(int before, int after)
// {
// CharSequence selection = getCurrentInputConnection().getSelectedText(0);
// if (selection != null && selection.length() > 0)
// getCurrentInputConnection().commitText("", 1);
// else
// getCurrentInputConnection().deleteSurroundingText(before, after);
// }
private void handleMetaKeyUp(KeyValue key, int flags)
{
int meta = 0;
if (key.eventCode == KeyValue.EVENT_NONE)
return ;
if ((flags & KeyValue.FLAG_CTRL) != 0)
meta |= KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON;
if ((flags & KeyValue.FLAG_ALT) != 0)
meta |= KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON;
if ((flags & KeyValue.FLAG_SHIFT) != 0)
meta |= KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON;
_recv.sendKeyEvent(key.eventCode, meta);
}
public static interface IReceiver
{
public void switchToNextInputMethod();
public void setPane_emoji();
public void setPane_normal();
public void showKeyboardConfig();
public void performAction();
/** 'res_id' is '-1' for the currently selected layout. */
public void setLayout(int res_id);
public void sendKeyEvent(int eventCode, int meta);
public void commitText(String text);
public void commitChar(char c);
}
}

View File

@@ -73,11 +73,7 @@ class KeyModifier
default: return (char)KeyCharacterMap.getDeadChar('\u00B4', c); default: return (char)KeyCharacterMap.getDeadChar('\u00B4', c);
} }
case KeyValue.FLAG_ACCENT3: case KeyValue.FLAG_ACCENT3:
switch (c) return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
{
case '*': return '°';
default: return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
}
case KeyValue.FLAG_ACCENT4: case KeyValue.FLAG_ACCENT4:
switch (c) switch (c)
{ {
@@ -186,6 +182,7 @@ class KeyModifier
case "esc": name = "insert"; break; case "esc": name = "insert"; break;
case "$": name = ""; break; case "$": name = ""; break;
case "#": name = "£"; break; case "#": name = "£"; break;
case "*": name = "°"; break;
default: return k; default: return k;
} }
return KeyValue.getKeyByName(name); return KeyValue.getKeyByName(name);

View File

@@ -13,6 +13,7 @@ class KeyValue
public static final int EVENT_SWITCH_EMOJI = -5; public static final int EVENT_SWITCH_EMOJI = -5;
public static final int EVENT_SWITCH_BACK_EMOJI = -6; public static final int EVENT_SWITCH_BACK_EMOJI = -6;
public static final int EVENT_CHANGE_METHOD = -7; public static final int EVENT_CHANGE_METHOD = -7;
public static final int EVENT_ACTION = -8;
public static final char CHAR_NONE = '\0'; public static final char CHAR_NONE = '\0';
// Behavior flags // Behavior flags
@@ -47,6 +48,17 @@ class KeyValue
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 | FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
FLAG_ACCENT_SUPERSCRIPT | FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_RING; FLAG_ACCENT_SUPERSCRIPT | FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_RING;
// Language specific keys
public static final int FLAG_LANG_SZLIG = (1 << 25);
public static final int FLAGS_LANGS = FLAG_LANG_SZLIG;
public static final int FLAGS_NOT_HIDDEN_ACCENTS = FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT;
// Keys that have to be enabled per language
public static final int FLAGS_HIDDEN_KEYS =
(FLAGS_ACCENTS & ~FLAGS_NOT_HIDDEN_ACCENTS) | FLAGS_LANGS;
public final String name; public final String name;
public final String symbol; public final String symbol;
public final char char_; public final char char_;
@@ -90,10 +102,15 @@ class KeyValue
keys.put(name, new KeyValue(name, symbol, c, event, flags)); keys.put(name, new KeyValue(name, symbol, c, event, flags));
} }
private static void addCharKey(char c, int event) private static void addCharKey(char c, int event, int flags)
{ {
String name = String.valueOf(c); String name = String.valueOf(c);
addKey(name, name, c, event, 0); addKey(name, name, c, event, flags);
}
private static void addCharKey(char c, int event)
{
addCharKey(c, event, 0);
} }
private static void addModifierKey(String name, String symbol, int extra_flags) private static void addModifierKey(String name, String symbol, int extra_flags)
@@ -190,6 +207,7 @@ class KeyValue
addCharKey('#', KeyEvent.KEYCODE_POUND); addCharKey('#', KeyEvent.KEYCODE_POUND);
addCharKey('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN); addCharKey('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN);
addCharKey(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN); addCharKey(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN);
addCharKey('ß', EVENT_NONE, FLAG_LANG_SZLIG);
addSpecialKey("config", "Conf", EVENT_CONFIG); addSpecialKey("config", "Conf", EVENT_CONFIG);
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT); addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT);
@@ -197,6 +215,7 @@ class KeyValue
addSpecialKey("switch_emoji", ":)", EVENT_SWITCH_EMOJI); addSpecialKey("switch_emoji", ":)", EVENT_SWITCH_EMOJI);
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI); addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
addSpecialKey("change_method", "", EVENT_CHANGE_METHOD); addSpecialKey("change_method", "", EVENT_CHANGE_METHOD);
addSpecialKey("action", "Action", EVENT_ACTION); // Will always be replaced
addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE); addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE);
addEventKey("enter", "\uE800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT); addEventKey("enter", "\uE800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
@@ -206,7 +225,7 @@ class KeyValue
addEventKey("left", "\uE80A", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT); addEventKey("left", "\uE80A", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addEventKey("page_up", "", KeyEvent.KEYCODE_PAGE_UP); addEventKey("page_up", "", KeyEvent.KEYCODE_PAGE_UP);
addEventKey("page_down", "", KeyEvent.KEYCODE_PAGE_DOWN); addEventKey("page_down", "", KeyEvent.KEYCODE_PAGE_DOWN);
addEventKey("home", "", KeyEvent.KEYCODE_HOME); addEventKey("home", "", KeyEvent.KEYCODE_MOVE_HOME);
addEventKey("end", "", KeyEvent.KEYCODE_MOVE_END); addEventKey("end", "", KeyEvent.KEYCODE_MOVE_END);
addEventKey("backspace", "", KeyEvent.KEYCODE_DEL, FLAG_PRECISE_REPEAT); addEventKey("backspace", "", KeyEvent.KEYCODE_DEL, FLAG_PRECISE_REPEAT);
addEventKey("delete", "", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_PRECISE_REPEAT); addEventKey("delete", "", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_PRECISE_REPEAT);
@@ -221,8 +240,8 @@ class KeyValue
addEventKey("f8", "F8", KeyEvent.KEYCODE_F8); addEventKey("f8", "F8", KeyEvent.KEYCODE_F8);
addEventKey("f9", "F9", KeyEvent.KEYCODE_F9); addEventKey("f9", "F9", KeyEvent.KEYCODE_F9);
addEventKey("f10", "F10", KeyEvent.KEYCODE_F10); addEventKey("f10", "F10", KeyEvent.KEYCODE_F10);
addEventKey("tab", "", KeyEvent.KEYCODE_TAB);
addKey("tab", "", '\t', KeyEvent.KEYCODE_TAB, 0);
addKey("space", " ", ' ', KeyEvent.KEYCODE_SPACE, 0); addKey("space", " ", ' ', KeyEvent.KEYCODE_SPACE, 0);
} }
} }

View File

@@ -12,9 +12,11 @@ import android.os.IBinder;
import android.text.InputType; import android.text.InputType;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -30,7 +32,6 @@ public class Keyboard2 extends InputMethodService
private Keyboard2View _keyboardView; private Keyboard2View _keyboardView;
private int _currentTextLayout; private int _currentTextLayout;
private ViewGroup _emojiPane = null; private ViewGroup _emojiPane = null;
private Typeface _specialKeyFont = null;
private Config _config; private Config _config;
@@ -51,24 +52,14 @@ public class Keyboard2 extends InputMethodService
public void onCreate() public void onCreate()
{ {
super.onCreate(); super.onCreate();
_specialKeyFont = Typeface.createFromAsset(getAssets(), "fonts/keys.ttf");
PreferenceManager.setDefaultValues(this, R.xml.settings, false); PreferenceManager.setDefaultValues(this, R.xml.settings, false);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
_config = new Config(this); Config.initGlobalConfig(this, new KeyEventHandler(this.new Receiver()));
_keyboardView = (Keyboard2View)getLayoutInflater().inflate(R.layout.keyboard, null); _config = Config.globalConfig();
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_keyboardView.reset(); _keyboardView.reset();
} }
public Config getConfig()
{
return (_config);
}
public Typeface getSpecialKeyFont()
{
return (_specialKeyFont);
}
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm) private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
{ {
String pkg = getPackageName(); String pkg = getPackageName();
@@ -80,7 +71,7 @@ public class Keyboard2 extends InputMethodService
private void refreshSubtypeLayout(InputMethodSubtype subtype) private void refreshSubtypeLayout(InputMethodSubtype subtype)
{ {
int l = _config.layout;; int l = _config.layout;
if (l == -1) if (l == -1)
{ {
String s = subtype.getExtraValueOf("default_layout"); String s = subtype.getExtraValueOf("default_layout");
@@ -90,33 +81,32 @@ public class Keyboard2 extends InputMethodService
_currentTextLayout = l; _currentTextLayout = l;
} }
private int accents_of_subtype(InputMethodSubtype subtype) private int extra_keys_of_subtype(InputMethodSubtype subtype)
{ {
String accents_option = subtype.getExtraValueOf("accents"); String extra_keys = subtype.getExtraValueOf("extra_keys");
int flags = 0; int flags = 0;
if (accents_option != null) if (extra_keys != null)
for (String acc : accents_option.split("\\|")) for (String acc : extra_keys.split("\\|"))
flags |= Config.accentFlag_of_name(acc); flags |= Config.extra_key_flag_of_name(acc);
return flags; return flags;
} }
private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype) private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype)
{ {
final int DONT_REMOVE = KeyValue.FLAG_ACCENT_SUPERSCRIPT | KeyValue.FLAG_ACCENT_SUBSCRIPT; int to_keep = 0;
int to_keep = DONT_REMOVE;
switch (_config.accents) switch (_config.accents)
{ {
case 1: case 1:
to_keep |= accents_of_subtype(subtype); to_keep |= extra_keys_of_subtype(subtype);
for (InputMethodSubtype s : getEnabledSubtypes(imm)) for (InputMethodSubtype s : getEnabledSubtypes(imm))
to_keep |= accents_of_subtype(s); to_keep |= extra_keys_of_subtype(s);
break; break;
case 2: to_keep |= accents_of_subtype(subtype); break; case 2: to_keep |= extra_keys_of_subtype(subtype); break;
case 3: to_keep = KeyValue.FLAGS_ACCENTS; break; case 3: to_keep = KeyValue.FLAGS_HIDDEN_KEYS; break;
case 4: break; case 4: break;
default: throw new IllegalArgumentException(); default: throw new IllegalArgumentException();
} }
_config.accent_flags_to_remove = ~to_keep & KeyValue.FLAGS_ACCENTS; _config.key_flags_to_remove = ~to_keep & KeyValue.FLAGS_HIDDEN_KEYS;
} }
private void refreshSubtypeLegacyFallback() private void refreshSubtypeLegacyFallback()
@@ -124,8 +114,8 @@ public class Keyboard2 extends InputMethodService
// Fallback for the accents option: Only respect the "None" case // Fallback for the accents option: Only respect the "None" case
switch (_config.accents) switch (_config.accents)
{ {
case 1: case 2: case 3: _config.accent_flags_to_remove = 0; break; case 1: case 2: case 3: _config.key_flags_to_remove = 0; break;
case 4: _config.accent_flags_to_remove = KeyValue.FLAGS_ACCENTS; break; case 4: _config.key_flags_to_remove = KeyValue.FLAGS_HIDDEN_KEYS; break;
} }
// Fallback for the layout option: Use qwerty in the "system settings" case // Fallback for the layout option: Use qwerty in the "system settings" case
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout; _currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
@@ -148,25 +138,54 @@ public class Keyboard2 extends InputMethodService
} }
} }
@Override private String actionLabel_of_imeAction(int action)
public View onCreateInputView()
{ {
ViewGroup parent = (ViewGroup)_keyboardView.getParent(); switch (action)
{
case EditorInfo.IME_ACTION_UNSPECIFIED:
case EditorInfo.IME_ACTION_NEXT: return "Next";
case EditorInfo.IME_ACTION_DONE: return "Done";
case EditorInfo.IME_ACTION_GO: return "Go";
case EditorInfo.IME_ACTION_PREVIOUS: return "Prev";
case EditorInfo.IME_ACTION_SEARCH: return "Search";
case EditorInfo.IME_ACTION_SEND: return "Send";
case EditorInfo.IME_ACTION_NONE:
default: return null;
}
}
if (parent != null) private void refreshEditorInfo(EditorInfo info)
parent.removeView(_keyboardView); {
return (_keyboardView); // First try to look at 'info.actionLabel', if it isn't set, look at
// 'imeOptions'.
if (info.actionLabel != null)
{
_config.actionLabel = info.actionLabel.toString();
_config.actionId = info.actionId;
_config.swapEnterActionKey = false;
}
else
{
int action = info.imeOptions & EditorInfo.IME_MASK_ACTION;
_config.actionLabel = actionLabel_of_imeAction(action); // Might be null
_config.actionId = action;
_config.swapEnterActionKey =
(info.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0;
}
} }
@Override @Override
public void onStartInputView(EditorInfo info, boolean restarting) public void onStartInputView(EditorInfo info, boolean restarting)
{ {
// Update '_config' before calling 'KeyboardView.setKeyboard'
refreshSubtypeImm(); refreshSubtypeImm();
refreshEditorInfo(info);
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0) if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
_keyboardView.setKeyboard(getLayout(R.xml.numeric)); _keyboardView.setKeyboard(getLayout(R.xml.numeric));
else else
_keyboardView.setKeyboard(getLayout(_currentTextLayout)); _keyboardView.setKeyboard(getLayout(_currentTextLayout));
_keyboardView.reset(); // Layout might need to change due to rotation _keyboardView.reset(); // Layout might need to change due to rotation
setInputView(_keyboardView);
} }
@Override @Override
@@ -186,92 +205,89 @@ public class Keyboard2 extends InputMethodService
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{ {
_config.refresh(); int prev_theme = _config.theme;
_config.refresh(this);
refreshSubtypeImm(); refreshSubtypeImm();
_keyboardView.refreshConfig(_config, getLayout(_currentTextLayout)); _keyboardView.refreshConfig(getLayout(_currentTextLayout));
// Refreshing the theme config requires re-creating the views
if (prev_theme != _config.theme)
{
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_emojiPane = null;
}
} }
@Override /** Not static */
public void onConfigurationChanged(Configuration newConfig) public class Receiver implements KeyEventHandler.IReceiver
{ {
_keyboardView.reset(); public void switchToNextInputMethod()
}
public void handleKeyUp(KeyValue key, int flags)
{
if (getCurrentInputConnection() == null)
return ;
key = KeyModifier.handleFlags(key, flags);
if (key.eventCode == KeyValue.EVENT_CONFIG)
{
Intent intent = new Intent(this, SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
else if (key.eventCode == KeyValue.EVENT_SWITCH_TEXT)
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
else if (key.eventCode == KeyValue.EVENT_SWITCH_NUMERIC)
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
else if (key.eventCode == KeyValue.EVENT_SWITCH_EMOJI)
{
if (_emojiPane == null)
_emojiPane = (ViewGroup)getLayoutInflater().inflate(R.layout.emoji_pane, null);
setInputView(_emojiPane);
}
else if (key.eventCode == KeyValue.EVENT_SWITCH_BACK_EMOJI)
setInputView(_keyboardView);
else if (key.eventCode == KeyValue.EVENT_CHANGE_METHOD)
{ {
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
imm.switchToNextInputMethod(getConnectionToken(), false); imm.switchToNextInputMethod(getConnectionToken(), false);
} }
else if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT)) != 0)
handleMetaKeyUp(key, flags); public void setPane_emoji()
// else if (eventCode == KeyEvent.KEYCODE_DEL)
// handleDelKey(1, 0);
// else if (eventCode == KeyEvent.KEYCODE_FORWARD_DEL)
// handleDelKey(0, 1);
else if (key.char_ == KeyValue.CHAR_NONE)
{ {
if (key.eventCode != KeyValue.EVENT_NONE) if (_emojiPane == null)
handleMetaKeyUp(key, flags); _emojiPane = (ViewGroup)inflate_view(R.layout.emoji_pane);
else setInputView(_emojiPane);
getCurrentInputConnection().commitText(key.symbol, 1);
}
else
sendKeyChar(key.char_);
} }
// private void handleDelKey(int before, int after) public void setPane_normal()
// {
// CharSequence selection = getCurrentInputConnection().getSelectedText(0);
// if (selection != null && selection.length() > 0)
// getCurrentInputConnection().commitText("", 1);
// else
// getCurrentInputConnection().deleteSurroundingText(before, after);
// }
private void handleMetaKeyUp(KeyValue key, int flags)
{ {
int metaState = 0; setInputView(_keyboardView);
KeyEvent event; }
if (key.eventCode == KeyValue.EVENT_NONE) public void performAction()
return ; {
if ((flags & KeyValue.FLAG_CTRL) != 0) InputConnection conn = getCurrentInputConnection();
metaState |= KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON; if (conn == null)
if ((flags & KeyValue.FLAG_ALT) != 0) return;
metaState |= KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON; conn.performEditorAction(_config.actionId);
if ((flags & KeyValue.FLAG_SHIFT) != 0) }
metaState |= KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON;
event = new KeyEvent(1, 1, KeyEvent.ACTION_DOWN, key.eventCode, 0, metaState); public void setLayout(int res_id)
getCurrentInputConnection().sendKeyEvent(event); {
getCurrentInputConnection().sendKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP)); if (res_id == -1)
res_id = _currentTextLayout;
_keyboardView.setKeyboard(getLayout(res_id));
}
public void sendKeyEvent(int eventCode, int meta)
{
InputConnection conn = getCurrentInputConnection();
if (conn == null)
return;
KeyEvent event = new KeyEvent(1, 1, KeyEvent.ACTION_DOWN, eventCode, 0, meta);
conn.sendKeyEvent(event);
conn.sendKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
}
public void showKeyboardConfig()
{
Intent intent = new Intent(Keyboard2.this, SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
public void commitText(String text)
{
getCurrentInputConnection().commitText(text, 1);
}
public void commitChar(char c)
{
sendKeyChar(c);
}
} }
private IBinder getConnectionToken() private IBinder getConnectionToken()
{ {
return getWindow().getWindow().getAttributes().token; return getWindow().getWindow().getAttributes().token;
} }
private View inflate_view(int layout)
{
return View.inflate(new ContextThemeWrapper(this, _config.theme), layout, null);
}
} }

View File

@@ -1,16 +1,15 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Vibrator; import android.os.Vibrator;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.PopupWindow; import android.widget.PopupWindow;
@@ -37,18 +36,7 @@ public class Keyboard2View extends View
private float _keyWidth; private float _keyWidth;
private Paint _keyBgPaint = new Paint(); private Theme _theme;
private Paint _keyDownBgPaint = new Paint();
private Paint _keyLabelPaint;
private Paint _keySubLabelPaint;
private Paint _specialKeyLabelPaint;
private Paint _specialKeySubLabelPaint;
private int _lockedColor;
private int _activatedColor;
private int _labelColor;
private int _subLabelColor;
private float _labelTextSize;
private float _sublabelTextSize;
private static RectF _tmpRect = new RectF(); private static RectF _tmpRect = new RectF();
@@ -57,47 +45,42 @@ public class Keyboard2View extends View
super(context, attrs); super(context, attrs);
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); _vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
_handler = new Handler(this); _handler = new Handler(this);
refreshConfig(((Keyboard2)context).getConfig(), null); _theme = new Theme(getContext(), attrs);
_config = Config.globalConfig();
refreshConfig(null);
setOnTouchListener(this); setOnTouchListener(this);
} }
/* Internally calls [reset()]. */ /* Internally calls [reset()]. */
public void refreshConfig(Config config, KeyboardData kw) public void refreshConfig(KeyboardData kw)
{ {
Resources res = getResources();
_config = config;
_lockedColor = res.getColor(R.color.key_label_locked);
_activatedColor = res.getColor(R.color.key_label_activated);
_labelColor = res.getColor(R.color.key_label);
_subLabelColor = res.getColor(R.color.key_sub_label);
_labelTextSize = res.getDimension(R.dimen.label_text_size) * config.characterSize;
_sublabelTextSize = res.getDimension(R.dimen.sublabel_text_size) * config.characterSize;
_keyBgPaint.setColor(res.getColor(R.color.key_bg));
_keyDownBgPaint.setColor(res.getColor(R.color.key_down_bg));
_keyLabelPaint = initLabelPaint(Paint.Align.CENTER, null);
_keySubLabelPaint = initLabelPaint(Paint.Align.LEFT, null);
Typeface specialKeysFont = ((Keyboard2)getContext()).getSpecialKeyFont();
_specialKeyLabelPaint = initLabelPaint(Paint.Align.CENTER, specialKeysFont);
_specialKeySubLabelPaint = initLabelPaint(Paint.Align.LEFT, specialKeysFont);
if (kw != null) if (kw != null)
setKeyboard(kw); // handle layout options then calls reset(). setKeyboard(kw); // handle layout options then calls reset().
} }
private Paint initLabelPaint(Paint.Align align, Typeface font)
{
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(align);
if (font != null)
paint.setTypeface(font);
return (paint);
}
public void setKeyboard(KeyboardData kw) public void setKeyboard(KeyboardData kw)
{ {
if (!_config.shouldOfferSwitchingToNextInputMethod) if (!_config.shouldOfferSwitchingToNextInputMethod)
kw = kw.removeKeys(new KeyboardData.RemoveKeysByEvent(KeyValue.EVENT_CHANGE_METHOD)); kw = kw.replaceKeys(
if (_config.accent_flags_to_remove != 0) new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_CHANGE_METHOD, null));
kw = kw.removeKeys(new KeyboardData.RemoveKeysByFlags(_config.accent_flags_to_remove)); 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 = kw;
reset(); reset();
} }
@@ -180,7 +163,7 @@ public class Keyboard2View extends View
moveY -= key.downY; moveY -= key.downY;
float absDist = Math.abs(moveX) + Math.abs(moveY); float absDist = Math.abs(moveX) + Math.abs(moveY);
key.ptrDist = absDist; key.ptrDist = absDist;
if (absDist < _config.subValueDist) if (absDist < _config.swipe_dist_px)
newValue = key.key.key0; newValue = key.key.key0;
else if (moveX < 0) else if (moveX < 0)
newValue = (moveY < 0) ? key.key.key1 : key.key.key3; newValue = (moveY < 0) ? key.key.key1 : key.key.key3;
@@ -301,7 +284,7 @@ public class Keyboard2View extends View
private void handleKeyUp(KeyDown key) private void handleKeyUp(KeyDown key)
{ {
if (key.value != null && (key.flags & (KeyValue.FLAG_LOCKED | KeyValue.FLAG_NOCHAR)) == 0) if (key.value != null && (key.flags & (KeyValue.FLAG_LOCKED | KeyValue.FLAG_NOCHAR)) == 0)
((Keyboard2)getContext()).handleKeyUp(key.value, _flags); _config.handler.handleKeyUp(key.value, _flags);
} }
private void handleKeyDown(KeyValue key) private void handleKeyDown(KeyValue key)
@@ -348,11 +331,11 @@ public class Keyboard2View extends View
if (_config.preciseRepeat && (key.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0) if (_config.preciseRepeat && (key.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
{ {
// Modulate repeat interval depending on the distance of the pointer // Modulate repeat interval depending on the distance of the pointer
float accel = Math.min(4.f, Math.max(0.3f, key.ptrDist / (_config.subValueDist * 15.f))); float accel = Math.min(4.f, Math.max(0.3f, key.ptrDist / (_config.swipe_dist_px * 15.f)));
nextInterval = (long)((float)nextInterval / accel); nextInterval = (long)((float)nextInterval / accel);
} }
_handler.sendEmptyMessageDelayed(msg.what, nextInterval); _handler.sendEmptyMessageDelayed(msg.what, nextInterval);
((Keyboard2)getContext()).handleKeyUp(key.value, _flags); _config.handler.handleKeyUp(key.value, _flags);
return (true); return (true);
} }
} }
@@ -366,7 +349,7 @@ public class Keyboard2View extends View
int width = dm.widthPixels; int width = dm.widthPixels;
int height = int height =
(int)(_config.keyHeight * _keyboard.keysHeight (int)(_config.keyHeight * _keyboard.keysHeight
+ _keyboard.rows.size() * _config.keyVerticalInterval + _keyboard.rows.size()
+ _config.marginTop + _config.marginBottom); + _config.marginTop + _config.marginBottom);
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
_keyWidth = (width - (_config.horizontalMargin * 2)) / _keyboard.keysWidth; _keyWidth = (width - (_config.horizontalMargin * 2)) / _keyboard.keysWidth;
@@ -375,24 +358,22 @@ public class Keyboard2View extends View
@Override @Override
protected void onDraw(Canvas canvas) protected void onDraw(Canvas canvas)
{ {
float y = _config.marginTop; float y = _config.marginTop + _config.keyVerticalInterval / 2;
for (KeyboardData.Row row : _keyboard.rows) for (KeyboardData.Row row : _keyboard.rows)
{ {
y += row.shift * _config.keyHeight; y += row.shift * _config.keyHeight;
float x = _config.horizontalMargin; float x = _config.horizontalMargin + _config.keyHorizontalInterval / 2;
float keyH = row.height * _config.keyHeight; float keyH = row.height * _config.keyHeight - _config.keyVerticalInterval;
for (KeyboardData.Key k : row.keys) for (KeyboardData.Key k : row.keys)
{ {
x += k.shift * _keyWidth + _config.keyHorizontalInterval; x += k.shift * _keyWidth;
float keyW = _keyWidth * k.width - _config.keyHorizontalInterval; float keyW = _keyWidth * k.width - _config.keyHorizontalInterval;
KeyDown keyDown = getKeyDown(k); KeyDown keyDown = getKeyDown(k);
_tmpRect.set(x, y, x + keyW, y + keyH); _tmpRect.set(x, y, x + keyW, y + keyH);
if (keyDown != null) canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius,
canvas.drawRect(_tmpRect, _keyDownBgPaint); (keyDown != null) ? _theme.keyDownBgPaint : _theme.keyBgPaint);
else
canvas.drawRoundRect(_tmpRect, _config.keyRound, _config.keyRound, _keyBgPaint);
if (k.key0 != null) if (k.key0 != null)
drawLabel(canvas, k.key0, keyW / 2f + x, (keyH + _labelTextSize) / 2f + y, keyDown); drawLabel(canvas, k.key0, keyW / 2f + x, (keyH + _theme.labelTextSize) / 2f + y, keyDown);
float subPadding = _config.keyPadding; float subPadding = _config.keyPadding;
if (k.key1 != null) if (k.key1 != null)
drawSubLabel(canvas, k.key1, x + subPadding, y + subPadding, false, true, keyDown); drawSubLabel(canvas, k.key1, x + subPadding, y + subPadding, false, true, keyDown);
@@ -402,9 +383,9 @@ public class Keyboard2View extends View
drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + subPadding, true, true, keyDown); drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + subPadding, true, true, keyDown);
if (k.key4 != null) if (k.key4 != null)
drawSubLabel(canvas, k.key4, x + keyW - subPadding, y + keyH - subPadding, true, false, keyDown); drawSubLabel(canvas, k.key4, x + keyW - subPadding, y + keyH - subPadding, true, false, keyDown);
x += keyW; x += _keyWidth * k.width;
} }
y += keyH + _config.keyVerticalInterval; y += row.height * _config.keyHeight;
} }
} }
@@ -422,9 +403,9 @@ public class Keyboard2View extends View
if (kd != null) if (kd != null)
{ {
if ((kd.flags & KeyValue.FLAG_LOCKED) != 0) if ((kd.flags & KeyValue.FLAG_LOCKED) != 0)
return _lockedColor; return _theme.lockedColor;
if (kd.pointerId == -1) if (kd.pointerId == -1)
return _activatedColor; return _theme.activatedColor;
} }
} }
return defaultColor; return defaultColor;
@@ -433,26 +414,25 @@ public class Keyboard2View extends View
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, KeyDown keyDown) private void drawLabel(Canvas canvas, KeyValue k, float x, float y, KeyDown keyDown)
{ {
k = KeyModifier.handleFlags(k, _flags); k = KeyModifier.handleFlags(k, _flags);
Paint p = ((k.flags & KeyValue.FLAG_KEY_FONT) != 0) ? _specialKeyLabelPaint : _keyLabelPaint; Paint p = _theme.labelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0));
p.setColor(labelColor(k, keyDown, _labelColor)); p.setColor(labelColor(k, keyDown, _theme.labelColor));
p.setTextSize(_labelTextSize * scaleTextSize(k)); p.setTextSize(_theme.labelTextSize * scaleTextSize(k));
canvas.drawText(k.symbol, x, y, p); canvas.drawText(k.symbol, x, y, p);
} }
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, boolean right, boolean up, KeyDown keyDown) private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, boolean right, boolean up, KeyDown keyDown)
{ {
k = KeyModifier.handleFlags(k, _flags); k = KeyModifier.handleFlags(k, _flags);
Paint p = ((k.flags & KeyValue.FLAG_KEY_FONT) != 0) ? _specialKeySubLabelPaint : _keySubLabelPaint; Paint p = _theme.subLabelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0), right);
p.setColor(labelColor(k, keyDown, _subLabelColor)); p.setColor(labelColor(k, keyDown, _theme.subLabelColor));
p.setTextAlign(right ? Paint.Align.RIGHT : Paint.Align.LEFT); p.setTextSize(_theme.sublabelTextSize * scaleTextSize(k));
p.setTextSize(_sublabelTextSize * scaleTextSize(k));
y -= up ? p.ascent() : p.descent(); y -= up ? p.ascent() : p.descent();
canvas.drawText(k.symbol, x, y, p); canvas.drawText(k.symbol, x, y, p);
} }
private float scaleTextSize(KeyValue k) private float scaleTextSize(KeyValue k)
{ {
return (k.symbol.length() < 2) ? 1.f : 0.8f; return ((k.symbol.length() < 2) ? 1.f : 0.8f) * _config.characterSize;
} }
private static class KeyDown private static class KeyDown

View File

@@ -57,11 +57,11 @@ class KeyboardData
return new KeyboardData(rows); return new KeyboardData(rows);
} }
public KeyboardData removeKeys(MapKeys f) public KeyboardData replaceKeys(MapKeys f)
{ {
ArrayList<Row> rows_ = new ArrayList<Row>(); ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows) for (Row r : rows)
rows_.add(r.removeKeys(f)); rows_.add(r.replaceKeys(f));
return new KeyboardData(rows_); return new KeyboardData(rows_);
} }
@@ -105,11 +105,11 @@ class KeyboardData
return new Row(keys, h, shift); return new Row(keys, h, shift);
} }
public Row removeKeys(MapKeys f) public Row replaceKeys(MapKeys f)
{ {
ArrayList<Key> keys_ = new ArrayList<Key>(); ArrayList<Key> keys_ = new ArrayList<Key>();
for (Key k : keys) for (Key k : keys)
keys_.add(k.removeKeys(f)); keys_.add(k.replaceKeys(f));
return new Row(keys_, height, shift); return new Row(keys_, height, shift);
} }
} }
@@ -157,7 +157,7 @@ class KeyboardData
return new Key(k0, k1, k2, k3, k4, width, shift); return new Key(k0, k1, k2, k3, k4, width, shift);
} }
public Key removeKeys(MapKeys f) 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); return new Key(f.map(key0), f.map(key1), f.map(key2), f.map(key3), f.map(key4), width, shift);
} }
@@ -168,27 +168,63 @@ class KeyboardData
public abstract KeyValue map(KeyValue k); public abstract KeyValue map(KeyValue k);
} }
public static class RemoveKeysByFlags implements MapKeys public static class ReplaceKeysByFlags implements MapKeys
{ {
private final int _flags; private final int _flags;
private final KeyValue _replacement;
public RemoveKeysByFlags(int flags) { _flags = flags; } public ReplaceKeysByFlags(int flags, KeyValue r)
{
_flags = flags;
_replacement = r;
}
public KeyValue map(KeyValue k) public KeyValue map(KeyValue k)
{ {
return (k == null || (k.flags & _flags) != 0) ? null : k; return (k != null && (k.flags & _flags) != 0) ? _replacement : k;
} }
} }
public static class RemoveKeysByEvent implements MapKeys public static class ReplaceKeysByEvent implements MapKeys
{ {
private final int _eventCode; private final int _eventCode;
private final KeyValue _replacement;
public RemoveKeysByEvent(int ev) { _eventCode = ev; } public ReplaceKeysByEvent(int ev, KeyValue r)
{
_eventCode = ev;
_replacement = r;
}
public KeyValue map(KeyValue k) public KeyValue map(KeyValue k)
{ {
return (k == null || k.eventCode == _eventCode) ? null : 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;
} }
} }
} }

View File

@@ -0,0 +1,83 @@
package juloo.keyboard2;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
public class Theme
{
public final Paint keyBgPaint = new Paint();
public final Paint keyDownBgPaint = new Paint();
public final int lockedColor;
public final int activatedColor;
public final int labelColor;
public final int subLabelColor;
public final float labelTextSize;
public final float sublabelTextSize;
public final float keyBorderRadius;
private final Paint _keyLabelPaint;
private final Paint _specialKeyLabelPaint;
private final Paint _keySubLabelPaint;
private final Paint _specialKeySubLabelPaint;
public Theme(Context context, AttributeSet attrs)
{
TypedArray s = context.getTheme().obtainStyledAttributes(attrs, R.styleable.keyboard, 0, 0);
keyBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKey, 0));
keyDownBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKeyActivated, 0));
// colorKeyboard = s.getColor(R.styleable.keyboard_colorKeyboard, 0);
labelColor = s.getColor(R.styleable.keyboard_colorLabel, 0);
activatedColor = s.getColor(R.styleable.keyboard_colorLabelActivated, 0);
lockedColor = s.getColor(R.styleable.keyboard_colorLabelLocked, 0);
subLabelColor = s.getColor(R.styleable.keyboard_colorSubLabel, 0);
keyBorderRadius = s.getDimension(R.styleable.keyboard_keyBorderRadius, 0);
s.recycle();
Resources res = context.getResources();
labelTextSize = res.getDimension(R.dimen.label_text_size);
sublabelTextSize = res.getDimension(R.dimen.sublabel_text_size);
_keyLabelPaint = initLabelPaint(Paint.Align.CENTER, null);
_keySubLabelPaint = initLabelPaint(Paint.Align.LEFT, null);
Typeface specialKeyFont = getSpecialKeyFont(context);
_specialKeyLabelPaint = initLabelPaint(Paint.Align.CENTER, specialKeyFont);
_specialKeySubLabelPaint = initLabelPaint(Paint.Align.LEFT, specialKeyFont);
}
public Paint labelPaint(boolean special_font)
{
Paint p = special_font ? _specialKeyLabelPaint : _keyLabelPaint;
return p;
}
public Paint subLabelPaint(boolean special_font, boolean align_right)
{
Paint p = special_font ? _specialKeySubLabelPaint : _keySubLabelPaint;
p.setTextAlign(align_right ? Paint.Align.RIGHT : Paint.Align.LEFT);
return p;
}
private Paint initLabelPaint(Paint.Align align, Typeface font)
{
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(align);
if (font != null)
paint.setTypeface(font);
return (paint);
}
private static Typeface _specialKeyFont = null;
static public Typeface getSpecialKeyFont(Context context)
{
if (_specialKeyFont == null)
{
_specialKeyFont = Typeface.createFromAsset(context.getAssets(), "fonts/keys.ttf");
}
return _specialKeyFont;
}
}