Compare commits
171 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8d8a58462c | ||
|
5562ee1391 | ||
|
120c0a9d23 | ||
|
aaff8689e3 | ||
|
2b348b7a31 | ||
|
19289bec27 | ||
|
aa78229b2a | ||
|
d62e7647e0 | ||
|
9411f59ed5 | ||
|
b85b67c2f0 | ||
|
695f5b4371 | ||
|
b995da9985 | ||
|
5f47beb5b0 | ||
|
2dda39f453 | ||
|
fbf8901bdb | ||
|
723c7e9aec | ||
|
2b6c2b98e0 | ||
|
281f779121 | ||
|
6b3123090c | ||
|
363a65223c | ||
|
4355225646 | ||
|
21c76b5b41 | ||
|
ed2dea9630 | ||
|
67487d0ef0 | ||
|
611f2c8111 | ||
|
6db57500ee | ||
|
1b6deb7fed | ||
|
94751bae3e | ||
|
0fb7150a06 | ||
|
f3aa218de4 | ||
|
c093b45c96 | ||
|
3373c59b90 | ||
|
0d1ddcce3f | ||
|
f736a169a4 | ||
|
743f6cbc91 | ||
|
47f9043096 | ||
|
a516246e52 | ||
|
ba6d62dee2 | ||
|
e872c58788 | ||
|
57c6208b50 | ||
|
d733f8c78c | ||
|
e63ff8f837 | ||
|
fe35d5fd5a | ||
|
2eb615dbf6 | ||
|
2dae2105b2 | ||
|
d53ee811d9 | ||
|
fadedfd58f | ||
|
f9cd4ca2d8 | ||
|
9bb7c7e66f | ||
|
f4978f5266 | ||
|
a0d90496c1 | ||
|
7aa241b10a | ||
|
a57bdf8cfb | ||
|
ee6e892ef4 | ||
|
2ea256e769 | ||
|
5665d6a7c5 | ||
|
534e4cb843 | ||
|
e303008e66 | ||
|
5404e7432d | ||
|
e92504ae92 | ||
|
4964bfb87f | ||
|
39da035135 | ||
|
4ee29f355e | ||
|
87144fd3a8 | ||
|
f6d4554669 | ||
|
1451857c92 | ||
|
23685ddb3c | ||
|
ce5cee42a1 | ||
|
067ab90847 | ||
|
937d5d728e | ||
|
d6757019dc | ||
|
5581cf33f9 | ||
|
35058628c1 | ||
|
d581c8b1e4 | ||
|
44b1086be9 | ||
|
d277ed1a8a | ||
|
7aa280b888 | ||
|
14dabb6f51 | ||
|
84bce23fec | ||
|
583aa55259 | ||
|
4873b8e22a | ||
|
c85e9a91d1 | ||
|
51ff795be4 | ||
|
632a9ac590 | ||
|
d73be58c1a | ||
|
04c84a8f66 | ||
|
d2570bc2ea | ||
|
4b1a6e4b92 | ||
|
c05fdea765 | ||
|
4e98ab7515 | ||
|
fda6895dc8 | ||
|
b488c766b1 | ||
|
94fed03a67 | ||
|
adb77466f5 | ||
|
6ab6a6811b | ||
|
b1ef21f62f | ||
|
75c736709d | ||
|
1ff8526d24 | ||
|
a76541458d | ||
|
d014a7dd8c | ||
|
93edc4ac42 | ||
|
7383cc4b68 | ||
|
95c8acc31e | ||
|
e86173b895 | ||
|
be0f4a1fc9 | ||
|
b913d6842f | ||
|
93b4cc2e7b | ||
|
7a451d5a36 | ||
|
2d2f0dd51d | ||
|
8631dfb723 | ||
|
c9f7f2cfc8 | ||
|
f2893437d2 | ||
|
2f47d2400b | ||
|
348c278eae | ||
|
7af579a1bc | ||
|
4333575bb9 | ||
|
e0217c650d | ||
|
1723288f5d | ||
|
88e21758bc | ||
|
e031de6b57 | ||
|
baf867a9f9 | ||
|
04f15fbfee | ||
|
cb95e99f50 | ||
|
28f98cc129 | ||
|
3ab2228065 | ||
|
eda171d57a | ||
|
0bf7ff5f34 | ||
|
aa12466767 | ||
|
100e0b270d | ||
|
38adf7d7b9 | ||
|
9485770372 | ||
|
c489b5aba7 | ||
|
96c4b165ac | ||
|
40897f2c26 | ||
|
133b6ec2c1 | ||
|
833dfa31bb | ||
|
fa9250a89e | ||
|
854eb431f3 | ||
|
d4eef00a8a | ||
|
f22d040eda | ||
|
dfec26a93b | ||
|
53113cadd9 | ||
|
4b43645c4b | ||
|
93e84ba7e9 | ||
|
23e59c6b09 | ||
|
2764e96eb1 | ||
|
9c82c9cfdc | ||
|
8bef0728ae | ||
|
b05f6e8447 | ||
|
f69a0605a8 | ||
|
29367f127d | ||
|
093a00c572 | ||
|
40b1ec63a9 | ||
|
93704cca0a | ||
|
15ce200ce3 | ||
|
0190cfc29a | ||
|
dd24ad323b | ||
|
86655d4959 | ||
|
3e332dbf54 | ||
|
d721cc86d1 | ||
|
1cfecbdf48 | ||
|
988d8db7e8 | ||
|
e5fa23e1f7 | ||
|
d787d982cf | ||
|
573c13fb82 | ||
|
58e37b484c | ||
|
cca832954e | ||
|
0727ea38e9 | ||
|
5e5c7ef86a | ||
|
d8d3cf85e5 | ||
|
7775213504 |
55
.github/workflows/make-apk.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Make Apk CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
Build-Apk:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cache fontforge and extra dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /usr/local/bin
|
||||
key: usr-local-bin
|
||||
- name: Install latest FontForge version (using AppImage)
|
||||
run: |
|
||||
# Get most recent version of FontForge
|
||||
# Using AppImage there is no dependecy problem, it is the latest version and it's easier to cache
|
||||
cd /usr/local/bin
|
||||
sudo wget -c -N https://github.com/fontforge/fontforge/releases/download/20220308/FontForge-2022-03-08-582bd41-x86_64.AppImage
|
||||
sudo chmod +x ./FontForge-2022-03-08-582bd41-x86_64.AppImage
|
||||
sudo ln --symbolic --force /usr/local/bin/FontForge-2022-03-08-582bd41-x86_64.AppImage /usr/local/bin/fontforge
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'zulu' # See 'Supported distributions' for available options
|
||||
java-version: '11'
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Cache debug certificate
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: _build/debug.keystore
|
||||
key: debug-keystore
|
||||
- name: Restore debug keystore from github Secrets
|
||||
run: |
|
||||
mkdir -p _build
|
||||
cd "$GITHUB_WORKSPACE/_build"
|
||||
# Check if exist and use the secret named DEBUG_KEYSTORE
|
||||
# The contents of the secret can be obtained -
|
||||
# from the debug.keystore.asc from you local _build folder
|
||||
if [[ ! "${{ secrets.DEBUG_KEYSTORE }}" == "" ]]; then
|
||||
echo "${{ secrets.DEBUG_KEYSTORE }}" > "debug.keystore.asc"
|
||||
if [[ -s "debug.keystore.asc" ]]; then
|
||||
gpg -d --passphrase "debug0" --batch "debug.keystore.asc" > "debug.keystore"
|
||||
fi
|
||||
fi
|
||||
- name: Build
|
||||
run: make
|
||||
- name: Save debug apk
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: debug apk
|
||||
path: _build/*.apk
|
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
*.keystore
|
||||
*.keystore.asc
|
||||
_build
|
||||
/*-keystore.conf
|
||||
|
@@ -1,38 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="juloo.keyboard2"
|
||||
android:versionCode="12"
|
||||
android:versionName="1.9.2"
|
||||
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>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im"
|
||||
android:resource="@xml/method" />
|
||||
</service>
|
||||
|
||||
<activity android:name="juloo.keyboard2.SettingsActivity"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/settings_activity_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="20" android:versionName="1.14.1" android:hardwareAccelerated="false">
|
||||
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="30"/>
|
||||
<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>
|
||||
<action android:name="android.view.InputMethod"/>
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
|
||||
</service>
|
||||
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@drawable/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/android:Theme.Material">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
</manifest>
|
||||
|
103
CONTRIBUTING.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# 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 (minimum `28.0.1`), 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`.
|
||||
|
||||
## Using the local debug.keystore on the Github CI actions
|
||||
|
||||
It's possible to save the local debug.keystore into a github secret, so the same keystore is utilized to build the debug apk in the CI github actions.
|
||||
Doing this, they wil have the same signature, thus the debug apk can be updated without having to uninstall it first.
|
||||
|
||||
After you sucessfully run `make`, (thus a debug.keystore exists) you can use this second command to generate a base64 stringified version of it
|
||||
|
||||
```sh
|
||||
cd _build
|
||||
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
|
||||
```
|
||||
|
||||
A file will be generated inside the local `_build/` folder, called `debug.keystore.asc`
|
||||
|
||||
You can copy the content of this file, and with that, paste it into a new github secret in your repo settings.
|
||||
|
||||
The secret must be named `DEBUG_KEYSTORE`
|
||||
|
||||
## Debugging on your phone
|
||||
|
||||
First [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb#Enabling).
|
||||
Then connect your phone to your computer using an USB cable or wireless
|
||||
debugging.
|
||||
|
||||
And finally, 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 > Languages & input > On-screen keyboard > Manage on-screen 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
|
||||
```
|
||||
|
||||
## Guidelines
|
||||
|
||||
### Add a localized layout
|
||||
|
||||
Localized layouts (a layout specific to a language) are generally accepted.
|
||||
See for example: 4333575 (Bulgarian), 88e2175 (Latvian), 133b6ec (German).
|
||||
|
||||
This keyboard is intended for programmers. If your language uses the Latin script, make sure it is possible to type every letters on the QWERTY keyboard.
|
||||
This is generally done using dead-keys, for example: 0bf7ff5 (Latvian), 573c13f (Swedish).
|
||||
It is also possible to add some characters that are hidden in other languages, for example 93e84ba (ß), though the space is limited.
|
||||
|
||||
### Add a programming layout
|
||||
|
||||
A programming layout must contains every ASCII characters as well as every dead-keys.
|
||||
Currently, the only example is QWERTY.
|
||||
|
||||
### Translations
|
||||
|
||||
Translations are always welcome ! See for example: 1723288 (Latvian), baf867a (French).
|
||||
The app can be translated by writing `res/values-<language code>/strings.xml` (for example `values-fr`, `values-lv`), based on the default: `res/values/strings.xml` (English).
|
||||
|
||||
The store description is found in `metadata/android/<locale>/`, `short_description.txt` and `full_description.txt`.
|
||||
The full description changes very infrequently (it was changed once in 6 years). But if it changes too much, outdated translation might be removed.
|
||||
|
||||
Translating changelogs is not useful because they evolve too fast. Changelogs are generally written entirely just before a release, translating them would delay releases too much. Old changelogs are not shown to anyone currently.
|
55
Makefile
@@ -2,11 +2,10 @@
|
||||
|
||||
PACKAGE_NAME = juloo.keyboard2
|
||||
|
||||
ANDROID_PLATFORM_VERSION = android-29
|
||||
JAVA_VERSION = 1.7
|
||||
ANDROID_PLATFORM_VERSION = android-30
|
||||
JAVA_VERSION = 1.8
|
||||
|
||||
SRC_DIR = srcs
|
||||
ASSETS_DIR = assets
|
||||
RES_DIR = res
|
||||
|
||||
EXTRA_JARS =
|
||||
@@ -19,7 +18,11 @@ release: _build/$(PACKAGE_NAME).apk
|
||||
installd: _build/$(PACKAGE_NAME).debug.apk
|
||||
adb install "$<"
|
||||
|
||||
.PHONY: release debug installd
|
||||
clean:
|
||||
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
|
||||
_build/*.idsig _build/assets
|
||||
|
||||
.PHONY: release debug installd clean
|
||||
|
||||
$(shell mkdir -p _build)
|
||||
|
||||
@@ -42,12 +45,6 @@ JAVAC_FLAGS = -source $(JAVA_VERSION) -target $(JAVA_VERSION) -encoding utf8
|
||||
MANIFEST_FILE = AndroidManifest.xml
|
||||
JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java')
|
||||
RES_FILES = $(shell find $(RES_DIR) -type f)
|
||||
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
|
||||
|
||||
@@ -59,31 +56,34 @@ $(DEBUG_KEYSTORE):
|
||||
-alias debug -keypass $(DEBUG_PASSWD) -keystore "$@" \
|
||||
-keyalg rsa -storepass $(DEBUG_PASSWD) -validity 10000
|
||||
|
||||
_build/%.debug.signed-apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
|
||||
jarsigner -keystore $(DEBUG_KEYSTORE) \
|
||||
-storepass $(DEBUG_PASSWD) -keypass $(DEBUG_PASSWD) \
|
||||
-signedjar "$@" "$<" debug
|
||||
_build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
|
||||
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
|
||||
--ks $(DEBUG_KEYSTORE) --ks-key-alias debug --ks-pass "pass:$(DEBUG_PASSWD)"
|
||||
|
||||
# Debug apk
|
||||
|
||||
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug
|
||||
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug --product debug
|
||||
|
||||
# Release signing
|
||||
|
||||
# %-keystore.conf should declare KEYSTORE, KEYNAME and OPTS
|
||||
# %-keystore.conf should declare KEYSTORE, KEYNAME and KEYSTOREPASS
|
||||
# it is interpreted as a shell script
|
||||
# OPTS can be used to pass -storepass or -keypass options to jarsigner
|
||||
_build/%.signed-apk: _build/%.unsigned-apk %-keystore.conf
|
||||
_build/%.apk: _build/%.unsigned-apk %-keystore.conf
|
||||
eval `cat $(word 2,$^)` && \
|
||||
jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore "$$KEYSTORE" $$OPTS -signedjar "$@" "$<" "$$KEYNAME"
|
||||
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
|
||||
--ks "$$KEYSTORE" --ks-key-alias "$$KEYNAME" --ks-pass "pass:$$KEYSTOREPASS"
|
||||
|
||||
# Package
|
||||
|
||||
_build/%.unsigned-apk: _build/classes.dex $(MANIFEST_FILE) $(ASSETS_FILES)
|
||||
_build/%.unsigned-apk: _build/%.unaligned-apk
|
||||
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
|
||||
|
||||
APK_EXTRA_FILES = classes.dex assets/special_font.ttf
|
||||
|
||||
_build/%.unaligned-apk: $(addprefix _build/,$(APK_EXTRA_FILES)) $(MANIFEST_FILE)
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \
|
||||
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
|
||||
[ -z "$(ASSETS_FILES)" ] || $(ANDROID_BUILD_TOOLS)/aapt add "$@" $(ASSETS_FILES)
|
||||
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) classes.dex
|
||||
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) $(APK_EXTRA_FILES)
|
||||
|
||||
# R.java
|
||||
|
||||
@@ -95,6 +95,15 @@ $(R_FILE): $(RES_FILES) $(MANIFEST_FILE)
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(RES_DIR) -J $(GEN_DIR) \
|
||||
-M $(MANIFEST_FILE) -I $(ANDROID_PLATFORM)/android.jar
|
||||
|
||||
# Special font
|
||||
|
||||
SPECIAL_FONT_GLYPHS = $(wildcard $(CURDIR)/srcs/special_font/*.svg)
|
||||
SPECIAL_FONT_SCRIPT = $(CURDIR)/srcs/special_font/build.pe
|
||||
|
||||
_build/assets/special_font.ttf: $(SPECIAL_FONT_SCRIPT) $(SPECIAL_FONT_GLYPHS)
|
||||
mkdir -p $(@D)
|
||||
fontforge -lang=ff -script $(SPECIAL_FONT_SCRIPT) $(CURDIR)/$@ $(SPECIAL_FONT_GLYPHS)
|
||||
|
||||
# Compile java classes and build classes.dex
|
||||
|
||||
OBJ_DIR = _build/class
|
||||
@@ -108,4 +117,4 @@ _build/classes.dex: $(JAVA_FILES) $(R_FILE)
|
||||
-classpath $(ANDROID_PLATFORM)/android.jar:$(EXTRA_JARS) \
|
||||
-sourcepath $(SRC_DIR):$(GEN_DIR) \
|
||||
$^
|
||||
$(ANDROID_BUILD_TOOLS)/dx --dex --output="$@" $(OBJ_DIR) $(subst :, ,$(EXTRA_JARS))
|
||||
$(ANDROID_BUILD_TOOLS)/d8 --output $(@D) $(OBJ_DIR)/*/*/* $(subst :, ,$(EXTRA_JARS))
|
||||
|
34
README.md
@@ -2,11 +2,35 @@
|
||||
|
||||
A lightweight virtual keyboard for developers.
|
||||
|
||||

|
||||

|
||||
|
||||
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.
|
||||
This can be found in the System Settings > System > Languages & Input > Virtual keyboard > Manage keyboards.
|
||||
Highlight of some of the features:
|
||||
|
||||
- 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 > On-screen keyboard > Manage on-screen keyboards.
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/packages/juloo.keyboard2/)
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png"
|
||||
alt="Get it on Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=juloo.keyboard2)
|
||||
|
||||
## Contributing
|
||||
|
||||
For instructions on building the application, see
|
||||
[Contributing](CONTRIBUTING.md).
|
||||
|
18
metadata/android/de-DE/full_description.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Diese App ist eine virtuelle Tastatur für Android. Hauptfunktionen sind das einfache Tippen eines jeden ASCII-Zeichens durch Wischgesten, Hilfstasten, Tottasten für Akzente, sowie das Vorhandensein spezieller Tasten (Tabulator, Esc, Pfeiltasten etc.).
|
||||
|
||||
Die Tastatur hat bis zu vier Extrazeichen in den Ecken jeder Taste. Diese Extrazeichen werden durch das Wischen mit dem Finger auf der Taste ausgewählt.
|
||||
|
||||
Highlights mancher Funktionen:
|
||||
|
||||
- Jedes Zeichen und jede spezielle Taste gibt es auch auf einer PC-Tastatur. Das ist perfekt für die Nutzung von Anwendungen wie Termux.
|
||||
|
||||
- Dies schließt auch Tab, Esc und die Pfeil- und Funktionstasten sowie Strg und Alt mit ein!
|
||||
|
||||
- Akzenttasten sind über Tottasten verfügbar. Nach Aktivieren des Akzents kan der akzentuierte Buchstabe getippt werden.
|
||||
|
||||
- Sehr schlank und schnell. Braucht 500x weniger Speicherplatz als Googles Tastatur und 15x weniger als die Standardtastatur. Keine Werbung, kein Tracking.
|
||||
|
||||
- Verschiedene Layouts: QWERTY, QWERTZ, AZERTY. Themes: Weiß, Dunkel, OLED Schwarz. Und viele weitere Optionen.
|
||||
|
||||
Wie jede andere virtuelle Tastatur muss diese Tastatur in den Systemeinstellungen aktiviert werden. Dazu Systemeinstellungen öffnen und wie folgt vorgehen:
|
||||
System > Sprachen und Eingabe > Bildschirmtastatur > Bildschirmtastaturen verwalten.
|
1
metadata/android/de-DE/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Eine schlanke Bildschirmtastatur für Entwickler
|
1
metadata/android/de-DE/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
@@ -1 +1 @@
|
||||
First open-source release !
|
||||
First open-source release!
|
||||
|
3
metadata/android/en-US/changelogs/13.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Add support for Swedish
|
||||
- Fix keyboard shortcuts not working in some applications
|
||||
- Fix a graphical bug and add some tweaks
|
8
metadata/android/en-US/changelogs/14.txt
Normal 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.
|
8
metadata/android/en-US/changelogs/15.txt
Normal 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.
|
13
metadata/android/en-US/changelogs/16.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
New languages: Latvian (thanks @eandersons), Bulgarian (thanks Zdravko Iskrenov)
|
||||
New layouts: Bulgarian traditional, Latvian
|
||||
|
||||
The application can now be translated.
|
||||
Translations: French, Latvian (thanks @eandersons)
|
||||
|
||||
Improve the behavior of the Action key.
|
||||
The globe key now opens the keyboard switching dialog.
|
||||
The literal tab character can be typed with Fn+Tab.
|
||||
Add options to control the spacing between the keys.
|
||||
Better integration with the system theme.
|
||||
|
||||
Thanks to all the contributors: @Moini, @sdrapha, @eandersons, @Poussinou, Zdravko Iskrenov
|
13
metadata/android/en-US/changelogs/17.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
New languages: Portuguese (thanks @sdrapha), Russian (thanks @carrot-cookie), Spanish (thanks @gh0ste)
|
||||
New layouts: Dvorak (thanks @AlexandraAlter), Russian Jcuken, Spanish Qwerty
|
||||
|
||||
Added the Meta key (the equivalent of the Win on Windows)
|
||||
Added ordinal symbols on the number pane (thanks @sdrapha)
|
||||
Better position for the arrow keys (thanks @MaxGyver83)
|
||||
Improvements to some of the symbols (thanks @MaxGyver83, @Roy-Orbison)
|
||||
Improvements to the layouts
|
||||
Improvements to the key-repeat for arrows
|
||||
Fixed Shift+Arrows for selecting text
|
||||
Fixed dark theme bugs on Xiaomi phones
|
||||
|
||||
Thanks to all the contributors: @sdrapha, @MaxGyver83, @AlexandraAlter, @Roy-Orbison, @carrot-cookie, @gh0ste
|
5
metadata/android/en-US/changelogs/18.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Improved text size, especially on large screens
|
||||
Increased contrasts
|
||||
Improved symbols (thanks @sdrapha)
|
||||
German translation (thanks @polyctena)
|
||||
Fix to some layouts.
|
21
metadata/android/en-US/changelogs/19.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
Translations: Brazilian portuguese (@igorSilCar), Chinese-Simplified (@9-2-1), Korean (@notnickid)
|
||||
New layouts: Swedish (@thabubble), Korean (@notnickid)
|
||||
|
||||
Improved computation of the swipe gesture and fix unstoppable key-repeat on
|
||||
some devices.
|
||||
|
||||
Moved keys away from the edges of the screen and other improvements to the layouts.
|
||||
|
||||
Improved rendering of some symbols.
|
||||
|
||||
Added more characters to the keyboard:
|
||||
- New combinations to Fn (@ArenaL5)
|
||||
- Currency symbols
|
||||
- Added arrow and box symbols (@sdrapha)
|
||||
- F11 and F12.
|
||||
|
||||
Option for making modifiers lockable. (@sdrapha)
|
||||
Fixes to the Spanish layout and other fixes. (@ArenaL5)
|
||||
Many other fixes.
|
||||
|
||||
Huge thanks to the contributors: @igorSilCar, @sdrapha, @ArenaL5, @notnickid, @9-2-1, @thabubble
|
25
metadata/android/en-US/changelogs/20.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
Quick fix release.
|
||||
|
||||
Previously:
|
||||
|
||||
Translations: Brazilian portuguese (@igorSilCar), Chinese-Simplified (@9-2-1), Korean (@notnickid)
|
||||
New layouts: Swedish (@thabubble), Korean (@notnickid)
|
||||
|
||||
Improved computation of the swipe gesture and fix unstoppable key-repeat on
|
||||
some devices.
|
||||
|
||||
Moved keys away from the edges of the screen and other improvements to the layouts.
|
||||
|
||||
Improved rendering of some symbols.
|
||||
|
||||
Added more characters to the keyboard:
|
||||
- New combinations to Fn (@ArenaL5)
|
||||
- Currency symbols
|
||||
- Added arrow and box symbols (@sdrapha)
|
||||
- F11 and F12.
|
||||
|
||||
Option for making modifiers lockable. (@sdrapha)
|
||||
Fixes to the Spanish layout and other fixes. (@ArenaL5)
|
||||
Many other fixes.
|
||||
|
||||
Huge thanks to the contributors: @igorSilCar, @sdrapha, @ArenaL5, @notnickid, @9-2-1, @thabubble
|
@@ -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.
|
||||
This can be found in the System Settings > System > Languages & Input > Virtual keyboard > Manage keyboards.
|
||||
Highlight of some of the features:
|
||||
|
||||
- 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 > On-screen keyboard > Manage on-screen keyboards.
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 62 KiB |
BIN
metadata/android/en-US/images/phoneScreenshots/6.png
Normal file
After Width: | Height: | Size: 20 KiB |
1
metadata/android/es-ES/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Un teclado virtual ligero para desarrolladores.
|
1
metadata/android/es-ES/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
@@ -1,3 +0,0 @@
|
||||
- Ajout de l'Espagnol et l'Italien
|
||||
- Nouvel emplacement pour les accents (encore) et ajout de nouveaux caratères
|
||||
- Correction de bugs (un crash sur d'anciennes versions d'Android et un rare glitch graphique après une rotation)
|
@@ -1 +0,0 @@
|
||||
Première version open-source !
|
@@ -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 à l'écran > Gérer les claviers à l'écran.
|
||||
|
18
metadata/android/ko-KR/full_description.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
이 앱은 안드로이드용 가상 키보드입니다. 주요 기능은 스와이프 제스처를 사용하여 모든 ASCII 문자를 쉽게 입력할 수 있다는 점과 악센트 및 수정자 키를 위한 데드 키와 특수 키(tab, esc, 방향키 등)이 있다는 것입니다.
|
||||
|
||||
키보드는 각 키의 모서리에 최대 4개의 추가 문자를 표시합니다. 이러한 추가 문자는 키에서 손가락을 스와이프하여 적중됩니다.
|
||||
|
||||
일부 하이라이트 기능:
|
||||
|
||||
- PC 키보드에서 사용할 수 있는 모든 문자 및 특수 키를 사요 가능합니다. 이것은 Termux와 같은 앱을 사용하는 데 효과적입니다.
|
||||
|
||||
- 여기에는 Tab, Esc, 방향키 및 function 키뿐만이 아닌 Ctrl 및 Alt 키도 포함되어 있습니다 !
|
||||
|
||||
- 악센트 키는 데드 키를 사용하여 액세스할 수 있습니다. 먼저 악센트 키를 활성화한 다음 악센트 문자를 입력합니다.
|
||||
|
||||
- 매우 가볍고 빠릅니다. Google 키보드보다 500배, 기본 키보드보다 15배 적은 공간을 사용합니다. 광고와 사용 기록 추적 없음.
|
||||
|
||||
- 다중 레이아웃: QWERTY, QWERTZ, AZERTY. 다양한 테마: White, Dark, OLED Black. 또한 다른 많은 옵션들.
|
||||
|
||||
다른 가상 키보드와 마찬가지로 시스템 설정에서 활성화해야 합니다. 시스템 설정을 열고 다음으로 이동합니다.
|
||||
시스템 > 언어 및 입력 > 키보드 > 키보드 관리.
|
1
metadata/android/ko-KR/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
개발자들을 위한 가벼운 가상 키보드.
|
1
metadata/android/ko-KR/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
18
metadata/android/lv-LV/full_description.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Šī lietotne ir tastatūra Android tālruņiem. Galvenās iespējas ir ērta ASCII rakstzīmju ievadīšana ar pavilkšanas kustību, taustiņi piekļūšanai uzsvara zīmēm un pārveidošanas taustiņiem un īpašo taustiņu esamība (Tab, Esc, bultas utt.).
|
||||
|
||||
Tastatūrā ir redzamas līdz 4 papildus rakstzīmēm katra taustiņa stūros. Tām var piekļūt ar pirksta pavilkšanu uz taustiņa attiecīgajā virzienā.
|
||||
|
||||
Izceltās iespējas:
|
||||
|
||||
- Visas rakstzīmes un īpašie taustiņi, kas ir atrodami arī datora tastatūrā. Tas lieliski noder tādās lietotnēs kā, piemēram, Termux.
|
||||
|
||||
- Ir iekļauti Tab, Esc, bultas un darbību taustiņi, kā arī Ctrl un Alt.
|
||||
|
||||
- Uzsvara zīmju taustiņi ir pieejami ar īpašām pogām. Vispirms jāizvēlas uzsvara zīmes veids, tad jāievada vēlamais burts.
|
||||
|
||||
- Ļoti viegla un ātra. Izmanto 500 reižu mazāk vietas kā Google tastatūra un 15 reižu mazāk kā noklusējuma tastatūra. Bez reklāmām un izsekošanas.
|
||||
|
||||
- Dažādi izkārtojumi: QWERTY, QWERTZ, AZERTY. Izskats: Gaišs, Tumšs, OLED melns. Kā arī daudzas citas papildiespējas.
|
||||
|
||||
Kā jebkura cita tālruņa tastatūra, tā ir jāiespējo ierīces iestatījumos. Jāatver Iestatījumi un tad:
|
||||
Sistēma > Valodas un ievade > Virtuālā tastatūra > Pārvaldīt tastatūras.
|
1
metadata/android/lv-LV/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Viegla un ātra tālruņa tastatūra izstrādātājiem.
|
18
metadata/android/pt-BR/full_description.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Um teclado virtual para aparelhos Android. Os recursos principais são facilidade de digitar todos os caracteres ASCII deslizando o dedo, teclas "mortas" para acentos e teclas modificadoras e a presença de teclas especiais (tab, esc, setas, etc..).
|
||||
|
||||
O teclado mostra até 4 caracteres extras nos cantos de cada tecla. Esses caracteres são digitáveis com o deslizar do dedo na tecla.
|
||||
|
||||
Alguns dos recursos interessantes:
|
||||
|
||||
- Todos caracteres e teclas especiais que também estão disponíveis num teclado de PC. Perfeito para usar com aplicativos como Termux.
|
||||
|
||||
- Incluindo Tab, Esc, as setas e teclas de função, e também Ctrl e Alt!
|
||||
|
||||
- Caracteres acentuados são digitáveis usando teclas "mortas". Primeiro ative o acento e depois digite a letra.
|
||||
|
||||
- Muito leve e rápido. Ocupa 500x menos espaço que o teclado da Google e 15x menos espaço que o teclado padrão. Sem propaganda, sem rastreio.
|
||||
|
||||
- Vários layouts: QWERTY, QWERTZ, AZERTY. Temas: Branco, Escuro, Preto OLED. E muitas outras opções.
|
||||
|
||||
Como qualquer outro teclado virtual, tem de ser ativado nas configurações de sistema. Abra as configurações e vá para:
|
||||
Sistema > Idioma e entrada > Teclado virtual > Gerenciar teclados virtuais.
|
1
metadata/android/pt-BR/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Um teclado virtual leve para desenvolvedores.
|
1
metadata/android/pt-BR/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
@@ -1,38 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:hardwareAccelerated="false">
|
||||
<juloo.keyboard2.EmojiGroupButtonsBar
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<juloo.keyboard2.EmojiGridView
|
||||
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 xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:hardwareAccelerated="false">
|
||||
<juloo.keyboard2.EmojiGroupButtonsBar android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
||||
<juloo.keyboard2.EmojiGridView android:id="@+id/emoji_grid" android:background="?attr/colorKeyboard" 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>
|
||||
|
@@ -1,5 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:background="@color/bg"
|
||||
android:hardwareAccelerated="false"
|
||||
/>
|
||||
<juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false" android:background="?attr/colorKeyboard"/>
|
||||
|
47
res/values-de/strings.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Unexpected Keyboard - Einstellungen</string>
|
||||
<string name="pref_category_layout">Layout</string>
|
||||
<string name="pref_layout_title">Tastaturlayout ändern</string>
|
||||
<string name="pref_layout_e_system">Systemeinstellung</string>
|
||||
<string name="pref_accents_title">Akzente</string>
|
||||
<string name="pref_accents_e_all_installed">Akzente für alle installierten Sprachen anzeigen</string>
|
||||
<string name="pref_accents_e_selected">Akzente nur für die gewählte Sprache anzeigen</string>
|
||||
<string name="pref_accents_e_all">Alle Akzente anzeigen</string>
|
||||
<string name="pref_accents_e_none">Akzente verbergen</string>
|
||||
<string name="pref_category_typing">Tippen</string>
|
||||
<string name="pref_swipe_dist_title">Länge der Wischgeste</string>
|
||||
<string name="pref_swipe_dist_summary">Abstand der Zeichen in den Ecken der Tasten (%s)</string>
|
||||
<string name="pref_long_timeout_title">Zeitüberschreitung bei Tastenwiederholung</string>
|
||||
<string name="pref_long_interval_title">Intervall der Tastenwiederholung</string>
|
||||
<string name="pref_category_vibrate">Vibration</string>
|
||||
<string name="pref_vibrate_title">Vibration</string>
|
||||
<string name="pref_vibrate_summary">Vibration bei Tastendruck ein-/ausschalten</string>
|
||||
<string name="pref_vibrate_duration_title">Dauer</string>
|
||||
<string name="pref_precise_repeat_title">Präzise Cursorsteuerung</string>
|
||||
<string name="pref_precise_repeat_summary">Geschwindigkeit der Tastenwiederholung durch weniger oder mehr Wischen anpassen</string>
|
||||
<string name="pref_category_style">Design</string>
|
||||
<string name="pref_margin_bottom_title">Unterer Abstand</string>
|
||||
<string name="pref_keyboard_height_title">Höhe der Tastatur</string>
|
||||
<string name="pref_horizontal_margin_title">Horizontaler Abstand</string>
|
||||
<string name="pref_character_size_title">Größe der Beschriftung</string>
|
||||
<string name="pref_character_size_summary">Größe der Buchstaben auf den Tasten (%.2fx)</string>
|
||||
<string name="pref_theme">Theme</string>
|
||||
<string name="pref_theme_e_system">Systemeinstellung</string>
|
||||
<string name="pref_theme_e_dark">Dunkel</string>
|
||||
<string name="pref_theme_e_light">Hell</string>
|
||||
<string name="pref_theme_e_black">Schwarz</string>
|
||||
<string name="pref_swipe_dist_e_very_short">Sehr kurz</string>
|
||||
<string name="pref_swipe_dist_e_short">Kurz</string>
|
||||
<string name="pref_swipe_dist_e_default">Normal</string>
|
||||
<string name="pref_swipe_dist_e_far">Weit</string>
|
||||
<string name="pref_swipe_dist_e_very_far">Sehr weit</string>
|
||||
<string name="pref_key_horizontal_space">Horizontaler Abstand zwischen den Tasten</string>
|
||||
<string name="pref_key_vertical_space">Vertikaler Abstand zwischen den Tasten</string>
|
||||
<string name="key_action_next">Nächstes</string>
|
||||
<string name="key_action_done">Fertig</string>
|
||||
<string name="key_action_go">Los</string>
|
||||
<string name="key_action_prev">Vorheriges</string>
|
||||
<string name="key_action_search">Suchen</string>
|
||||
<string name="key_action_send">Senden</string>
|
||||
</resources>
|
49
res/values-es/strings.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Ajustes de Unexpected Keyboard</string>
|
||||
<string name="pref_category_layout">Formato</string>
|
||||
<string name="pref_layout_title">Cambiar formato de teclado</string>
|
||||
<string name="pref_layout_e_system">Ajustes del sistema</string>
|
||||
<string name="pref_accents_title">Acentos</string>
|
||||
<string name="pref_accents_e_all_installed">Mostrar acentos para todos los lenguajes instalados</string>
|
||||
<string name="pref_accents_e_selected">Solo mostrar acentos para el lenguaje seleccionado</string>
|
||||
<string name="pref_accents_e_all">Mostrar todos los acentos</string>
|
||||
<string name="pref_accents_e_none">Ocultar acentos</string>
|
||||
<string name="pref_category_typing">Escribiendo</string>
|
||||
<string name="pref_swipe_dist_title">Distancia para deslizar</string>
|
||||
<string name="pref_swipe_dist_summary">Distancia de caracteres en las esquinas de las letras (%s)</string>
|
||||
<string name="pref_long_timeout_title">Tiempo de espera de repetición de tecla</string>
|
||||
<string name="pref_long_interval_title">Intervalo de repetición de tecla</string>
|
||||
<string name="pref_category_vibrate">Vibración</string>
|
||||
<string name="pref_vibrate_title">Vibración</string>
|
||||
<string name="pref_vibrate_summary">Habilitar/deshabilitar vibración al presionar una tecla</string>
|
||||
<string name="pref_vibrate_duration_title">Duración</string>
|
||||
<string name="pref_precise_repeat_title">Movimientos de cursor preciso</string>
|
||||
<string name="pref_precise_repeat_summary">Modular la velocidad de repetición de teclas según si se desliza más o menos</string>
|
||||
<string name="pref_lockable_keys_title">Bloqueo de teclas modificadoras</string>
|
||||
<string name="pref_lockable_keys_summary">Teclas modificadoras que se pueden bloquear pulsándolas dos veces</string>
|
||||
<string name="pref_category_style">Estilo</string>
|
||||
<string name="pref_margin_bottom_title">Margen del pie</string>
|
||||
<string name="pref_keyboard_height_title">Altura del teclado</string>
|
||||
<string name="pref_horizontal_margin_title">Margen horizontal</string>
|
||||
<string name="pref_character_size_title">Tamaño de etiqueta</string>
|
||||
<string name="pref_character_size_summary">Tamaño de caracteres mostrados en el teclado (%.2fx)</string>
|
||||
<string name="pref_theme">Tema</string>
|
||||
<string name="pref_theme_e_system">Ajustes de sistema</string>
|
||||
<string name="pref_theme_e_dark">Oscuro</string>
|
||||
<string name="pref_theme_e_light">Claro</string>
|
||||
<string name="pref_theme_e_black">Negro</string>
|
||||
<string name="pref_swipe_dist_e_very_short">Muy corto</string>
|
||||
<string name="pref_swipe_dist_e_short">Corto</string>
|
||||
<string name="pref_swipe_dist_e_default">Normal</string>
|
||||
<string name="pref_swipe_dist_e_far">Lejano</string>
|
||||
<string name="pref_swipe_dist_e_very_far">Muy lejano</string>
|
||||
<string name="pref_key_horizontal_space">Espaciado horizontal entre las teclas</string>
|
||||
<string name="pref_key_vertical_space">Espaciado vertical entre las teclas</string>
|
||||
<string name="key_action_next">Siguiente</string>
|
||||
<string name="key_action_done">Hecho</string>
|
||||
<string name="key_action_go">Ir</string>
|
||||
<string name="key_action_prev">Anterior</string>
|
||||
<string name="key_action_search">Buscar</string>
|
||||
<string name="key_action_send">Enviar</string>
|
||||
</resources>
|
47
res/values-fr/strings.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Unexpected Keyboard Paramètres</string>
|
||||
<string name="pref_category_layout">Disposition</string>
|
||||
<string name="pref_layout_title">Disposition des touches</string>
|
||||
<string name="pref_layout_e_system">Paramètre système</string>
|
||||
<string name="pref_accents_title">Accents</string>
|
||||
<string name="pref_accents_e_all_installed">Afficher les accents pour les langues installées</string>
|
||||
<string name="pref_accents_e_selected">Afficher les accents pour la langue sélectionnée</string>
|
||||
<string name="pref_accents_e_all">Afficher tous les accents</string>
|
||||
<string name="pref_accents_e_none">Cacher les accents</string>
|
||||
<string name="pref_category_typing">Saisie</string>
|
||||
<string name="pref_swipe_dist_title">Distance de swipe</string>
|
||||
<string name="pref_swipe_dist_summary">La distance des caractères dans les coins (%s)</string>
|
||||
<string name="pref_long_timeout_title">Délai avant répétition</string>
|
||||
<string name="pref_long_interval_title">Écart entre répétitions</string>
|
||||
<string name="pref_category_vibrate">Vibration</string>
|
||||
<string name="pref_vibrate_title">Vibreur</string>
|
||||
<string name="pref_vibrate_summary">Vibration a chaque touche</string>
|
||||
<string name="pref_vibrate_duration_title">Durée</string>
|
||||
<string name="pref_precise_repeat_title">Mouvement précis du curseur</string>
|
||||
<string name="pref_precise_repeat_summary">Modifier la vitesse de répétition en bougeant le doigt</string>
|
||||
<string name="pref_category_style">Style</string>
|
||||
<string name="pref_margin_bottom_title">Marge du bas</string>
|
||||
<string name="pref_keyboard_height_title">Hauteur du clavier</string>
|
||||
<string name="pref_horizontal_margin_title">Marge des côtés</string>
|
||||
<string name="pref_character_size_title">Taille des labels</string>
|
||||
<string name="pref_character_size_summary">Taille des caractères affichés sur les touches (%.2fx)</string>
|
||||
<string name="pref_theme">Thème</string>
|
||||
<string name="pref_theme_e_system">Paramètre système</string>
|
||||
<string name="pref_theme_e_dark">Sombre</string>
|
||||
<string name="pref_theme_e_light">Clair</string>
|
||||
<string name="pref_theme_e_black">Noir</string>
|
||||
<string name="pref_swipe_dist_e_very_short">Très courte</string>
|
||||
<string name="pref_swipe_dist_e_short">Courte</string>
|
||||
<string name="pref_swipe_dist_e_default">Normale</string>
|
||||
<string name="pref_swipe_dist_e_far">Longue</string>
|
||||
<string name="pref_swipe_dist_e_very_far">Très longue</string>
|
||||
<string name="pref_key_horizontal_space">Espacement horizontal entre les touches</string>
|
||||
<string name="pref_key_vertical_space">Espacement vertical entre les touches</string>
|
||||
<string name="key_action_next">Suiv.</string>
|
||||
<string name="key_action_done">Fin</string>
|
||||
<string name="key_action_go">Aller</string>
|
||||
<string name="key_action_prev">Prec.</string>
|
||||
<string name="key_action_search">Chercher</string>
|
||||
<string name="key_action_send">Envoyer</string>
|
||||
</resources>
|
47
res/values-ko/strings.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Unexpected Keyboard 설정</string>
|
||||
<string name="pref_category_layout">레이아웃</string>
|
||||
<string name="pref_layout_title">키보드 레이아웃 변경</string>
|
||||
<string name="pref_layout_e_system">시스템 세팅</string>
|
||||
<string name="pref_accents_title">악센트</string>
|
||||
<string name="pref_accents_e_all_installed">설치된 모든 언어의 악센트 표시</string>
|
||||
<string name="pref_accents_e_selected">선택한 언어의 악센트만 표시</string>
|
||||
<string name="pref_accents_e_all">모든 언어의 악센트 표시</string>
|
||||
<string name="pref_accents_e_none">모든 언어의 악센트 숨기기</string>
|
||||
<string name="pref_category_typing">타자</string>
|
||||
<string name="pref_swipe_dist_title">스와이프 범위</string>
|
||||
<string name="pref_swipe_dist_summary">키 모서리 문자의 입력 범위 (%s)</string>
|
||||
<string name="pref_long_timeout_title">키 길게 누르기 지연</string>
|
||||
<string name="pref_long_interval_title">키 반복 간격</string>
|
||||
<string name="pref_category_vibrate">진동</string>
|
||||
<string name="pref_vibrate_title">진동</string>
|
||||
<string name="pref_vibrate_summary">키 누를 때 진동 키거/끄기</string>
|
||||
<string name="pref_vibrate_duration_title">지속 시간</string>
|
||||
<string name="pref_precise_repeat_title">정확한 커서 움직임</string>
|
||||
<string name="pref_precise_repeat_summary">더 많거나 적은 스와이프로 키 반복 조절</string>
|
||||
<string name="pref_category_style">스타일</string>
|
||||
<string name="pref_margin_bottom_title">아래 넓이</string>
|
||||
<string name="pref_keyboard_height_title">키보드 높이</string>
|
||||
<string name="pref_horizontal_margin_title">양 옆 넓이</string>
|
||||
<string name="pref_character_size_title">폰트 크기</string>
|
||||
<string name="pref_character_size_summary">키보드의 표시되는 폰트 크기 (%.2fx)</string>
|
||||
<string name="pref_theme">테마</string>
|
||||
<string name="pref_theme_e_system">시스템 테마</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">매우 짧음</string>
|
||||
<string name="pref_swipe_dist_e_short">짧음</string>
|
||||
<string name="pref_swipe_dist_e_default">보통</string>
|
||||
<string name="pref_swipe_dist_e_far">넓음</string>
|
||||
<string name="pref_swipe_dist_e_very_far">매우 넓음</string>
|
||||
<string name="pref_key_horizontal_space">키보드 양 옆 간격</string>
|
||||
<string name="pref_key_vertical_space">키보드 세로 간격</string>
|
||||
<string name="key_action_next">다음</string>
|
||||
<string name="key_action_done">확인</string>
|
||||
<string name="key_action_go">Go</string>
|
||||
<string name="key_action_prev">이전</string>
|
||||
<string name="key_action_search">검색</string>
|
||||
<string name="key_action_send">보내기</string>
|
||||
</resources>
|
@@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="horizontal_margin">12dp</dimen>
|
||||
<dimen name="margin_bottom">3dp</dimen>
|
||||
<dimen name="key_padding">3dp</dimen>
|
||||
<dimen name="key_height">36dp</dimen>
|
||||
<dimen name="label_text_size">18dp</dimen>
|
||||
<dimen name="sublabel_text_size">11dp</dimen>
|
||||
<dimen name="emoji_type_button_height">48dp</dimen>
|
||||
<dimen name="horizontal_margin">12dp</dimen>
|
||||
<dimen name="margin_bottom">3dp</dimen>
|
||||
<dimen name="key_padding">3dp</dimen>
|
||||
<dimen name="key_height">36dp</dimen>
|
||||
<item name="label_text_size" type="integer" format="float">0.4</item>
|
||||
<item name="sublabel_text_size" type="integer" format="float">0.3</item>
|
||||
<dimen name="emoji_type_button_height">48dp</dimen>
|
||||
<dimen name="extra_horizontal_margin">20dp</dimen>
|
||||
</resources>
|
||||
|
45
res/values-lv/strings.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Unexpected Keyboard iestatījumi</string>
|
||||
<string name="pref_category_layout">Izkārtojums</string>
|
||||
<string name="pref_layout_title">Mainīt tastatūras izkārtojumu</string>
|
||||
<string name="pref_layout_e_system">Ierīces iestatījumi</string>
|
||||
<string name="pref_accents_title">Uzsvara zīmes</string>
|
||||
<string name="pref_accents_e_all_installed">Rādīt uzsvara zīmes visām uzstādītajām valodām</string>
|
||||
<string name="pref_accents_e_selected">Rādīt uzsvara zīmes tikai atlasītajām valodām</string>
|
||||
<string name="pref_accents_e_all">Rādīt visas uzsvara zīmes</string>
|
||||
<string name="pref_accents_e_none">Paslēpt uzsvara zīmes</string>
|
||||
<string name="pref_category_typing">Rakstīšana</string>
|
||||
<string name="pref_swipe_dist_title">Pavilkšanas attālums</string>
|
||||
<string name="pref_swipe_dist_summary">Taustiņu stūros esošo rakstzīmju attālums (%s)</string>
|
||||
<string name="pref_long_timeout_title">Taustiņa atkārtošanās ātrums</string>
|
||||
<string name="pref_long_interval_title">Taustiņa atkārtošanās aizture</string>
|
||||
<string name="pref_category_vibrate">Trīcēšana</string>
|
||||
<string name="pref_vibrate_title">Trīcēšana</string>
|
||||
<string name="pref_vibrate_summary">Iespējot/atspējot taustiņa piespiešanas trīcēšanu</string>
|
||||
<string name="pref_vibrate_duration_title">Ilgums</string>
|
||||
<string name="pref_precise_repeat_title">Pielāgojama kursora kustība</string>
|
||||
<string name="pref_precise_repeat_summary">Mainīt taustiņa atkārtošanās ātrumu ar pavilkšanas attālumu</string>
|
||||
<string name="pref_category_style">Izskata pielāgojumi</string>
|
||||
<string name="pref_margin_bottom_title">Apakšējā apmale</string>
|
||||
<string name="pref_keyboard_height_title">Tastatūras augstums</string>
|
||||
<string name="pref_horizontal_margin_title">Līmeniskā apmale</string>
|
||||
<string name="pref_character_size_title">Iezīmes izmērs</string>
|
||||
<string name="pref_character_size_summary">Tastatūrā attēloto rakstzīmju izmērs (%.2fx)</string>
|
||||
<string name="pref_theme">Izskats</string>
|
||||
<string name="pref_theme_e_system">Ierīces iestatījumi</string>
|
||||
<string name="pref_theme_e_dark">Tumšs</string>
|
||||
<string name="pref_theme_e_light">Gaišs</string>
|
||||
<string name="pref_theme_e_black">Melns</string>
|
||||
<string name="pref_swipe_dist_e_very_short">Ļoti tuvs</string>
|
||||
<string name="pref_swipe_dist_e_short">Tuvs</string>
|
||||
<string name="pref_swipe_dist_e_default">Vidējs</string>
|
||||
<string name="pref_swipe_dist_e_far">Tāls</string>
|
||||
<string name="pref_swipe_dist_e_very_far">Ļoti tāls</string>
|
||||
<string name="key_action_next">Nākamais</string>
|
||||
<string name="key_action_done">Darīts</string>
|
||||
<string name="key_action_go">Aiziet</string>
|
||||
<string name="key_action_prev">Iepriekšējais</string>
|
||||
<string name="key_action_search">Meklēt</string>
|
||||
<string name="key_action_send">Sūtīt</string>
|
||||
</resources>
|
49
res/values-pt/strings.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="settings_activity_label">Configurações Unexpected Keyboard</string>
|
||||
<string name="pref_category_layout">Layout</string>
|
||||
<string name="pref_layout_title">Mudar layout do teclado</string>
|
||||
<string name="pref_layout_e_system">Mesmo do sistema</string>
|
||||
<string name="pref_accents_title">Acentos</string>
|
||||
<string name="pref_accents_e_all_installed">Mostrar acentos para todos idiomas instalados</string>
|
||||
<string name="pref_accents_e_selected">Mostrar acentos só para o idioma selecionado</string>
|
||||
<string name="pref_accents_e_all">Mostrar todos acentos</string>
|
||||
<string name="pref_accents_e_none">Esconder acentos</string>
|
||||
<string name="pref_category_typing">Digitação</string>
|
||||
<string name="pref_swipe_dist_title">Distância a deslizar</string>
|
||||
<string name="pref_swipe_dist_summary">Distância até acionar os cantos das teclas (%s)</string>
|
||||
<string name="pref_long_timeout_title">Tempo até repetir tecla</string>
|
||||
<string name="pref_long_interval_title">Intervalo para repetir tecla</string>
|
||||
<string name="pref_category_vibrate">Vibração</string>
|
||||
<string name="pref_vibrate_title">Vibração</string>
|
||||
<string name="pref_vibrate_summary">Ativar/desativar vibração ao digitar</string>
|
||||
<string name="pref_vibrate_duration_title">Duração</string>
|
||||
<string name="pref_precise_repeat_title">Precisão nos movimentos do cursor</string>
|
||||
<string name="pref_precise_repeat_summary">Varia a velocidade de repetição ao depender de quanto deslizar</string>
|
||||
<string name="pref_lockable_keys_title">Segurar teclas</string>
|
||||
<string name="pref_lockable_keys_summary">Teclas que podem ficar seguradas ao teclar duas vezes</string>
|
||||
<string name="pref_category_style">Estilo</string>
|
||||
<string name="pref_margin_bottom_title">Margem de baixo</string>
|
||||
<string name="pref_keyboard_height_title">Altura do teclado</string>
|
||||
<string name="pref_horizontal_margin_title">Margem horizontal</string>
|
||||
<string name="pref_character_size_title">Tamanho dos indicadores</string>
|
||||
<string name="pref_character_size_summary">Tamanho dos caracteres visíveis no teclado (%.2fx)</string>
|
||||
<string name="pref_theme">Tema</string>
|
||||
<string name="pref_theme_e_system">Mesmo do sistema</string>
|
||||
<string name="pref_theme_e_dark">Escuro</string>
|
||||
<string name="pref_theme_e_light">Claro</string>
|
||||
<string name="pref_theme_e_black">Preto</string>
|
||||
<string name="pref_swipe_dist_e_very_short">Muito curto</string>
|
||||
<string name="pref_swipe_dist_e_short">Curto</string>
|
||||
<string name="pref_swipe_dist_e_default">Normal</string>
|
||||
<string name="pref_swipe_dist_e_far">Longo</string>
|
||||
<string name="pref_swipe_dist_e_very_far">Muito longo</string>
|
||||
<string name="pref_key_horizontal_space">Distância horizontal entre teclas</string>
|
||||
<string name="pref_key_vertical_space">Distância vertical entre teclas</string>
|
||||
<string name="key_action_next">Próximo</string>
|
||||
<string name="key_action_done">Pronto</string>
|
||||
<string name="key_action_go">Ir</string>
|
||||
<string name="key_action_prev">Anterior</string>
|
||||
<string name="key_action_search">Buscar</string>
|
||||
<string name="key_action_send">Enviar</string>
|
||||
</resources>
|
51
res/values-zh-rCN/strings.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name" product="debug">Unexpected Keyboard (debug)</string>
|
||||
<string name="app_name" product="default">Unexpected Keyboard</string>
|
||||
<string name="settings_activity_label">Unexpected Keyboard 设置</string>
|
||||
<string name="pref_category_layout">布局</string>
|
||||
<string name="pref_layout_title">改变键盘布局</string>
|
||||
<string name="pref_layout_e_system">系统设置</string>
|
||||
<string name="pref_accents_title">声调</string>
|
||||
<string name="pref_accents_e_all_installed">显示所有安装的语言的声调符号</string>
|
||||
<string name="pref_accents_e_selected">只显示选择的语言的声调符号</string>
|
||||
<string name="pref_accents_e_all">显示所有声调符号</string>
|
||||
<string name="pref_accents_e_none">隐藏声调符号</string>
|
||||
<string name="pref_category_typing">输入</string>
|
||||
<string name="pref_swipe_dist_title">滑动触发距离</string>
|
||||
<string name="pref_swipe_dist_summary">输入按键四角的符号需要滑动的距离 (%s)</string>
|
||||
<string name="pref_long_timeout_title">长按到开始重复输入的时间</string>
|
||||
<string name="pref_long_interval_title">长按后每次重复输入的时间间隔</string>
|
||||
<string name="pref_category_vibrate">振动</string>
|
||||
<string name="pref_vibrate_title">振动</string>
|
||||
<string name="pref_vibrate_summary">启用或者禁用按下按键时振动</string>
|
||||
<string name="pref_vibrate_duration_title">每次振动持续的时间</string>
|
||||
<string name="pref_precise_repeat_title">精确控制光标移速</string>
|
||||
<string name="pref_precise_repeat_summary">按键重复按下速度由手指滑动的距离决定</string>
|
||||
<string name="pref_lockable_keys_title">组合键锁定</string>
|
||||
<string name="pref_lockable_keys_summary">可以通过输入两次锁定任何组合键(Ctrl, Alt, Fn, 声调符号等)</string>
|
||||
<string name="pref_category_style">样式</string>
|
||||
<string name="pref_margin_bottom_title">键盘下边距</string>
|
||||
<string name="pref_keyboard_height_title">键盘高度</string>
|
||||
<string name="pref_horizontal_margin_title">键盘左右边距</string>
|
||||
<string name="pref_character_size_title">字符大小</string>
|
||||
<string name="pref_character_size_summary">按键上显示的字符的大小 (%.2fx)</string>
|
||||
<string name="pref_theme">主题</string>
|
||||
<string name="pref_theme_e_system">跟随系统设置</string>
|
||||
<string name="pref_theme_e_dark">暗色</string>
|
||||
<string name="pref_theme_e_light">亮色</string>
|
||||
<string name="pref_theme_e_black">黑色</string>
|
||||
<string name="pref_swipe_dist_e_very_short">非常短</string>
|
||||
<string name="pref_swipe_dist_e_short">短</string>
|
||||
<string name="pref_swipe_dist_e_default">中(默认)</string>
|
||||
<string name="pref_swipe_dist_e_far">长</string>
|
||||
<string name="pref_swipe_dist_e_very_far">非常长</string>
|
||||
<string name="pref_key_horizontal_space">按键的左右边距</string>
|
||||
<string name="pref_key_vertical_space">按键的上下边距</string>
|
||||
<string name="key_action_next">下一项</string>
|
||||
<string name="key_action_done">完成</string>
|
||||
<string name="key_action_go">前往</string>
|
||||
<string name="key_action_prev">前一项</string>
|
||||
<string name="key_action_search">搜索</string>
|
||||
<string name="key_action_send">发送</string>
|
||||
</resources>
|
@@ -4,10 +4,40 @@
|
||||
<item>system</item>
|
||||
<item>azerty</item>
|
||||
<item>qwerty</item>
|
||||
<item>qwerty_pt</item>
|
||||
<item>qwerty_es</item>
|
||||
<item>qwerty_ko</item>
|
||||
<item>qwerty_lv</item>
|
||||
<item>qwerty_sv_se</item>
|
||||
<item>ru_jcuken</item>
|
||||
<item>qwertz</item>
|
||||
<item>bgph1</item>
|
||||
<item>dvorak</item>
|
||||
</string-array>
|
||||
<string-array name="pref_layout_entries">
|
||||
<item>@string/pref_layout_e_system</item>
|
||||
<item>AZERTY</item>
|
||||
<item>QWERTY</item>
|
||||
<item>QWERTY (Brasileiro)</item>
|
||||
<item>QWERTY (Español)</item>
|
||||
<item>QWERTY (Korean)</item>
|
||||
<item>QWERTY (Latvian)</item>
|
||||
<item>QWERTY (Swedish)</item>
|
||||
<item>ЙЦУКЕН (Русский)</item>
|
||||
<item>QWERTZ</item>
|
||||
<item>Bulgarian (Phonetic Traditional)</item>
|
||||
<item>Dvorak</item>
|
||||
</string-array>
|
||||
<string-array name="pref_programming_layout_values">
|
||||
<item>none</item>
|
||||
<item>qwerty</item>
|
||||
<item>dvorak</item>
|
||||
</string-array>
|
||||
<string-array name="pref_programming_layout_entries">
|
||||
<item>@string/pref_programming_layout_none</item>
|
||||
<item>QWERTY</item>
|
||||
<item>Dvorak</item>
|
||||
</string-array>
|
||||
|
||||
<string name="pref_accents_default">1</string>
|
||||
|
||||
<string-array name="pref_accents_entries">
|
||||
<item>@string/pref_accents_e_all_installed</item>
|
||||
<item>@string/pref_accents_e_selected</item>
|
||||
@@ -20,4 +50,30 @@
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</string-array>
|
||||
<string-array name="pref_theme_entries">
|
||||
<item>@string/pref_theme_e_system</item>
|
||||
<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>system</item>
|
||||
<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>
|
||||
|
@@ -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>
|
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="horizontal_margin">3dp</dimen>
|
||||
<dimen name="margin_top">3dp</dimen>
|
||||
<dimen name="margin_bottom">7dp</dimen>
|
||||
<dimen name="key_padding">2dp</dimen>
|
||||
<dimen name="key_vertical_interval">2dp</dimen>
|
||||
<dimen name="key_horizontal_interval">2dp</dimen>
|
||||
<dimen name="key_height">51dp</dimen>
|
||||
<dimen name="key_round">5dp</dimen>
|
||||
<dimen name="label_text_size">18dp</dimen>
|
||||
<dimen name="sublabel_text_size">12dp</dimen>
|
||||
<dimen name="emoji_type_button_height">56dp</dimen>
|
||||
<dimen name="emoji_grid_height">250dp</dimen>
|
||||
</resources>
|
@@ -1,51 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Unexpected Keyboard</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="app_name" product="debug">Unexpected Keyboard (debug)</string>
|
||||
<string name="app_name" product="default">Unexpected Keyboard</string>
|
||||
<string name="settings_activity_label">Unexpected Keyboard Settings</string>
|
||||
<string name="pref_category_layout">Layout</string>
|
||||
<string name="pref_layout_title">Change keyboard layout</string>
|
||||
<string name="pref_layout_summary">%s</string>
|
||||
<string-array name="pref_layout_entries">
|
||||
<item>System settings</item>
|
||||
<item>Azerty</item>
|
||||
<item>Qwerty</item>
|
||||
</string-array>
|
||||
|
||||
<string name="pref_layout_e_system">System settings</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_selected">Show accents for the selected language</string>
|
||||
<string name="pref_accents_e_all">Show every accents</string>
|
||||
<string name="pref_accents_e_all_installed">Show accents for all installed languages</string>
|
||||
<string name="pref_accents_e_selected">Only show accents for the selected language</string>
|
||||
<string name="pref_accents_e_all">Show all accents</string>
|
||||
<string name="pref_accents_e_none">Hide accents</string>
|
||||
|
||||
<string name="pref_category_typing">Typing</string>
|
||||
<string name="pref_preci_title">Precision</string>
|
||||
<string name="pref_preci_summary">Distance of corner values (%spx)</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_summary">%sms</string>
|
||||
|
||||
<string name="pref_category_vibrate">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_duration_title">Duration</string>
|
||||
<string name="pref_vibrate_duration_summary">%sms</string>
|
||||
<string name="pref_programming_layout_title">Keyboard layout for programming</string>
|
||||
<string name="pref_programming_layout_none">None</string>
|
||||
<string name="pref_category_typing">Typing</string>
|
||||
<string name="pref_swipe_dist_title">Swiping distance</string>
|
||||
<string name="pref_swipe_dist_summary">Distance of characters in the corners of the keys (%s)</string>
|
||||
<string name="pref_long_timeout_title">Key repeat timeout</string>
|
||||
<string name="pref_long_interval_title">Key repeat interval</string>
|
||||
<string name="pref_category_vibrate">Vibration</string>
|
||||
<string name="pref_vibrate_title">Vibration</string>
|
||||
<string name="pref_vibrate_summary">Enable/disable vibration on keypress</string>
|
||||
<string name="pref_vibrate_duration_title">Duration</string>
|
||||
<string name="pref_precise_repeat_title">Precise cursor movements</string>
|
||||
<string name="pref_precise_repeat_summary">Modulate the speed of movements by swiping more or less</string>
|
||||
|
||||
<string name="pref_category_style">Style</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_summary">%sdp</string>
|
||||
<string name="pref_horizontal_margin_title">Horizontal margin</string>
|
||||
<string name="pref_horizontal_margin_summary">%sdp</string>
|
||||
<string name="pref_precise_repeat_summary">Modulate key repeat speed by swiping more or less</string>
|
||||
<string name="pref_lockable_keys_title">Lockable modifiers</string>
|
||||
<string name="pref_lockable_keys_summary">Modifiers that can be locked by typing them twice</string>
|
||||
<string name="pref_category_style">Style</string>
|
||||
<string name="pref_margin_bottom_title">Margin bottom</string>
|
||||
<string name="pref_keyboard_height_title">Keyboard height</string>
|
||||
<string name="pref_horizontal_margin_title">Horizontal margin</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_theme">Theme</string>
|
||||
<string name="pref_theme_e_system">System settings</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>
|
||||
<string name="pref_key_horizontal_space">Horizontal spacing between the keys</string>
|
||||
<string name="pref_key_vertical_space">Vertical spacing between the keys</string>
|
||||
<string name="key_action_next">Next</string>
|
||||
<string name="key_action_done">Done</string>
|
||||
<string name="key_action_go">Go</string>
|
||||
<string name="key_action_prev">Prev</string>
|
||||
<string name="key_action_search">Search</string>
|
||||
<string name="key_action_send">Send</string>
|
||||
</resources>
|
||||
|
@@ -1,20 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="emojiTypeButton">
|
||||
<item name="android:padding">1px</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:minHeight">@dimen/label_text_size</item>
|
||||
<item name="android:background">@color/emoji_button_bg</item>
|
||||
<item name="android:textColor">@color/emoji_key_text</item>
|
||||
<item name="android:textSize">@dimen/label_text_size</item>
|
||||
</style>
|
||||
<style name="emojiKeyButton">
|
||||
<item name="android:layout_width">0px</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:padding">0px</item>
|
||||
<item name="android:background">@color/emoji_key_bg</item>
|
||||
<item name="android:textColor">@color/emoji_key_text</item>
|
||||
<item name="android:textSize">@dimen/label_text_size</item>
|
||||
</style>
|
||||
<style name="emojiTypeButton">
|
||||
<item name="android:padding">1px</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:minHeight">18dp</item>
|
||||
<item name="android:background">?attr/emoji_button_bg</item>
|
||||
<item name="android:textColor">?attr/emoji_key_text</item>
|
||||
<item name="android:textSize">18dp</item>
|
||||
</style>
|
||||
<style name="emojiKeyButton">
|
||||
<item name="android:layout_width">0px</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:padding">0px</item>
|
||||
<item name="android:background">?attr/emoji_key_bg</item>
|
||||
<item name="android:textColor">?attr/emoji_key_text</item>
|
||||
<item name="android:textSize">18dp</item>
|
||||
</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>
|
||||
|
72
res/values/themes.xml
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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="android:isLightTheme">false</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="colorKeyboard">#1b1b1b</item>
|
||||
<item name="colorKey">#333333</item>
|
||||
<item name="colorKeyActivated">#1b1b1b</item>
|
||||
<item name="colorLabel">#ffffff</item>
|
||||
<item name="colorLabelActivated">#3399ff</item>
|
||||
<item name="colorLabelLocked">#33cc33</item>
|
||||
<item name="colorSubLabel">#cccccc</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="android:isLightTheme">true</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="colorKeyboard">#e3e3e3</item>
|
||||
<item name="colorKey">#cccccc</item>
|
||||
<item name="colorKeyActivated">#e3e3e3</item>
|
||||
<item name="colorLabel">#000000</item>
|
||||
<item name="colorLabelActivated">#0066cc</item>
|
||||
<item name="colorLabelLocked">#33cc33</item>
|
||||
<item name="colorSubLabel">#333333</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="android:isLightTheme">false</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<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>
|
18
res/values/values.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="horizontal_margin">3dp</dimen>
|
||||
<dimen name="margin_top">3dp</dimen>
|
||||
<dimen name="margin_bottom">7dp</dimen>
|
||||
<dimen name="key_padding">2dp</dimen>
|
||||
<dimen name="key_vertical_interval">2dp</dimen>
|
||||
<dimen name="key_horizontal_interval">2dp</dimen>
|
||||
<dimen name="key_height">51dp</dimen>
|
||||
<item name="label_text_size" type="integer" format="float">0.33</item>
|
||||
<item name="sublabel_text_size" type="integer" format="float">0.22</item>
|
||||
<dimen name="emoji_type_button_height">56dp</dimen>
|
||||
<dimen name="emoji_grid_height">250dp</dimen>
|
||||
<dimen name="emoji_text_size">28dp</dimen>
|
||||
<dimen name="extra_horizontal_margin">0dp</dimen>
|
||||
<bool name="debug_logs" product="debug">true</bool>
|
||||
<bool name="debug_logs" product="default">false</bool>
|
||||
</resources>
|
@@ -1,44 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="a" key1="esc" key2="1" key3="&" />
|
||||
<key key0="z" key2="2" key4="~" />
|
||||
<key key0="e" key2="3" key3=""" key4="\#" />
|
||||
<key key0="r" key2="4" key3="'" />
|
||||
<key key0="t" key2="5" key3="(" key4=")" />
|
||||
<key key0="y" key2="6" key3="-" key4="|" />
|
||||
<key key0="u" key2="7" key4="`" />
|
||||
<key key0="i" key2="8" key3="_" key4="\\" />
|
||||
<key key0="o" key2="9" />
|
||||
<key key0="p" key2="0" key4="\@" />
|
||||
</row>
|
||||
<row>
|
||||
<key key0="q" key1="tab" />
|
||||
<key key0="s" />
|
||||
<key key0="d" key1="accent_grave" key3="accent_aigu" />
|
||||
<key key0="f" key3="{" key4="}" />
|
||||
<key key0="g" key3="[" key4="]" />
|
||||
<key key0="h" key3="=" key4="+" />
|
||||
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key3="^" />
|
||||
<key key0="k" key2="€" key3="$" key4="£" />
|
||||
<key key0="l" key2="%" />
|
||||
<key key0="m" key4="*" />
|
||||
</row>
|
||||
<row>
|
||||
<key width="2.0" key0="shift" />
|
||||
<key key0="w" key3="<" key4=">" />
|
||||
<key key0="x" />
|
||||
<key key0="c" key1="accent_cedille" key3="," key4="\?" />
|
||||
<key key0="v" key3=";" key4="." />
|
||||
<key key0="b" key3=":" key4="/" />
|
||||
<key key0="n" key1="accent_tilde" key2="§" key4="!" />
|
||||
<key width="2.0" 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>
|
||||
<row>
|
||||
<key key0="a" key2="1" key4="esc"/>
|
||||
<key key0="z" key2="2" key3="&" key4="~"/>
|
||||
<key key0="e" key2="3" key3=""" key4="\#"/>
|
||||
<key key0="r" key2="4" key3="'"/>
|
||||
<key key0="t" key2="5" key3="(" key4=")"/>
|
||||
<key key0="y" key2="6" key3="-" key4="|"/>
|
||||
<key key0="u" key2="7" key4="`"/>
|
||||
<key key0="i" key2="8" key3="_" key4="\\"/>
|
||||
<key key0="o" key2="9" key3="\@" key4="f11_placeholder"/>
|
||||
<key key0="p" key1="0" key3="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="q" key2="tab"/>
|
||||
<key key0="s" key1="accent_ring" key3="ß"/>
|
||||
<key key0="d" key1="accent_grave" key3="accent_aigu"/>
|
||||
<key key0="f" key3="{" key4="}"/>
|
||||
<key key0="g" key3="[" key4="]"/>
|
||||
<key key0="h" key3="=" key4="+"/>
|
||||
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key3="^"/>
|
||||
<key key0="k" key2="€" key3="$" key4="£"/>
|
||||
<key key0="l" key2="%"/>
|
||||
<key key0="m" key3="*"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="2.0" key0="shift"/>
|
||||
<key key0="w" key3="<" key4=">"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c" key1="accent_cedille" key3="," key4="\?"/>
|
||||
<key key0="v" key3=";" key4="."/>
|
||||
<key key0="b" key3=":" key4="/"/>
|
||||
<key key0="n" key1="accent_tilde" key2="§" key4="!"/>
|
||||
<key width="2.0" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
8
res/xml/bottom_row.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<row height="0.95">
|
||||
<key width="1.8" key0="ctrl" key2="meta" key4="switch_numeric"/>
|
||||
<key width="1.2" key0="fn" key1="alt" key2="change_method" key3="switch_emoji" key4="config"/>
|
||||
<key width="4.0" key0="space" key1="switch_programming" edgekeys="true"/>
|
||||
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
|
||||
<key width="1.8" key0="enter" key2="action"/>
|
||||
</row>
|
37
res/xml/dvorak.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="shift" width="1.5" key2="esc" key4="tab"/>
|
||||
<key key0="p" key1="accent_ring" key2="." key3="<" key4="f11_placeholder"/>
|
||||
<key key0="y" key1="accent_grave" key2="," key3=">" key4="f12_placeholder"/>
|
||||
<key key0="f" key4="€"/>
|
||||
<key key0="g" key2="\\" key3="|"/>
|
||||
<key key0="c" key1="accent_trema" key2="accent_circonflexe" key3="{" key4="}"/>
|
||||
<key key0="r" key3="[" key4="]"/>
|
||||
<key key0="l" key2="=" key3="+" key4="£"/>
|
||||
<key key0="backspace" key2="delete" width="1.5"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="a" key2="1" key4="!"/>
|
||||
<key key0="o" key1="accent_macron" key2="2" key3="\@"/>
|
||||
<key key0="e" key1="accent_caron" key2="3" key3="\#"/>
|
||||
<key key0="u" key2="4" key3="$"/>
|
||||
<key key0="i" key2="5" key3="%"/>
|
||||
<key key0="d" key2="6" key3="^"/>
|
||||
<key key0="h" key2="7" key3="&"/>
|
||||
<key key0="t" key2="8" key3="*"/>
|
||||
<key key0="n" key2="9" key3="(" key4=")"/>
|
||||
<key key0="s" key1="0" key3="ß"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="q" shift="0.5" key1="accent_tilde" key2="`" key3="~"/>
|
||||
<key key0="j" key1="accent_aigu" key2="'" key3="""/>
|
||||
<key key0="k" key2=";" key3=":"/>
|
||||
<key key0="x" key1="accent_cedille"/>
|
||||
<key key0="b"/>
|
||||
<key key0="m" key2="/" key3="\?"/>
|
||||
<key key0="w"/>
|
||||
<key key0="v"/>
|
||||
<key key0="z" key2="-" key3="_"/>
|
||||
</row>
|
||||
</keyboard>
|
37
res/xml/local_bgph1.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="я" key2="1" key4="esc"/>
|
||||
<key key0="в" key1="!" key2="2" key3="\@" key4="ч"/>
|
||||
<key key0="е" key2="3" key3="\#" key4="№"/>
|
||||
<key key0="р" key2="4" key3="$"/>
|
||||
<key key0="т" key2="5" key3="%"/>
|
||||
<key key0="ъ" key2="6" key3="^" key4="€"/>
|
||||
<key key0="у" key2="7" key3="&" key4="§"/>
|
||||
<key key0="и" key2="8" key3="*"/>
|
||||
<key key0="о" key1="accent_macron" key2="9" key3="(" key4=")"/>
|
||||
<key key0="п" key1="0" key3="f11_placeholder" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="а" key1="tab" key2="`"/>
|
||||
<key key0="с" key2="£"/>
|
||||
<key key0="д" key1="accent_grave" key3="accent_aigu"/>
|
||||
<key key0="ф"/>
|
||||
<key key0="г" key1="accent_caron" key2="-" key3="_"/>
|
||||
<key key0="х" key2="=" key3="+"/>
|
||||
<key key0="й" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
|
||||
<key key0="к" key2="ш" key3="[" key4="]"/>
|
||||
<key key0="л" key1="щ" key2="|" key3="\\" key4="ю"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="з"/>
|
||||
<key key0="ь" key1="accent_ring" key3="ѝ"/>
|
||||
<key key0="ц" key1="accent_cedille" key2="<" key3="."/>
|
||||
<key key0="ж" key2=">" key3=","/>
|
||||
<key key0="б" key2="\?" key3="/"/>
|
||||
<key key0="н" key1="accent_tilde" key2=":" key3=";"/>
|
||||
<key key0="м" key2=""" key3="'"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
43
res/xml/local_ru_jcuken.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="й" key2="1" key4="esc"/>
|
||||
<key key0="ц" key2="2" key3="\@" key4="~"/>
|
||||
<key key0="у" key2="3" key3="\#" key4="!"/>
|
||||
<key key0="к" key2="4" key3="$"/>
|
||||
<key key0="е" key1="ё" key2="5" key3="%"/>
|
||||
<key key0="н" key2="6" key3="^"/>
|
||||
<key key0="г" key2="7" key3="&"/>
|
||||
<key key0="ш" key2="8" key3="*"/>
|
||||
<key key0="щ" key2="9" key3="(" key4=")"/>
|
||||
<key key0="з" key2="0"/>
|
||||
<key key0="х" key1="{" key2="}" key4="f11_placeholder"/>
|
||||
<key key0="ъ" key1="[" key2="]" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="ф" key1="tab" key2="`"/>
|
||||
<key key0="ы"/>
|
||||
<key key0="в"/>
|
||||
<key key0="а"/>
|
||||
<key key0="п"/>
|
||||
<key key0="р"/>
|
||||
<key key0="о"/>
|
||||
<key key0="л"/>
|
||||
<key key0="д" key2="-" key3="_"/>
|
||||
<key key0="ж" key2="=" key3="+"/>
|
||||
<key key0="э" key2="|" key3="\\"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="я"/>
|
||||
<key key0="ч"/>
|
||||
<key key0="с"/>
|
||||
<key key0="м"/>
|
||||
<key key0="и" key2="<" key3="."/>
|
||||
<key key0="т" key2=">" key3=","/>
|
||||
<key key0="ь" key2="\?" key3="/"/>
|
||||
<key key0="б" key2=":" key3=";"/>
|
||||
<key key0="ю" key2=""" key3="'"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
@@ -1,33 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="juloo.keyboard2.SettingsActivity"
|
||||
android:supportsSwitchingToNextInputMethod="true">
|
||||
<subtype android:label="@string/subtype_label"
|
||||
android:languageTag="en"
|
||||
android:imeSubtypeLocale="en_US"
|
||||
android:imeSubtypeMode="keyboard"
|
||||
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"
|
||||
/>
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
|
||||
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys=€"/>
|
||||
<subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz,extra_keys=accent_trema|ß|€"/>
|
||||
<subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=£|€"/>
|
||||
<subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty"/>
|
||||
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_es,extra_keys=accent_grave|accent_aigu|accent_tilde|accent_trema|€"/>
|
||||
<subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=azerty,extra_keys=accent_grave|accent_aigu|accent_circonflexe|accent_cedille|accent_trema|€"/>
|
||||
<subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=accent_grave|accent_aigu|€"/>
|
||||
<subtype android:label="%s" android:languageTag="ko" android:imeSubtypeLocale="ko_KR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_ko"/>
|
||||
<subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_lv,extra_keys=accent_caron|accent_cedille|accent_macron|€"/>
|
||||
<subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_pt,extra_keys=accent_aigu|accent_cedille|accent_circonflexe|accent_grave|accent_tilde|€"/>
|
||||
<subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=ru_jcuken"/>
|
||||
<subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_sv_se,extra_keys=accent_aigu|accent_trema|accent_ring|€"/>
|
||||
</input-method>
|
||||
|
@@ -1,35 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<keyboard bottom_row="false">
|
||||
<row>
|
||||
<key width="0.75" key0="esc" key2="~" key4="!" />
|
||||
<key width="0.75" key0="(" key2="[" key4="{" />
|
||||
<key key0="7" key3="<" key4=">" />
|
||||
<key key0="8" key2="∞" />
|
||||
<key key0="9" key2="π" />
|
||||
<key width="0.75" key0="*" key1="√" key2="×" />
|
||||
<key width="0.75" key0="/" key1="%" key3="÷" />
|
||||
<key width="0.75" key0="esc" key2="~" key4="!"/>
|
||||
<key width="0.75" key0="(" key2="[" key4="{"/>
|
||||
<key key0="7" key1="<" key2=">"/>
|
||||
<key key0="8" key2="∞"/>
|
||||
<key key0="9" key2="π"/>
|
||||
<key width="0.75" key0="*" key1="√" key2="×"/>
|
||||
<key width="0.75" key0="/" key1="%" key3="÷"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="0.75" key0="tab" key1=";" key2="|" key4="\\" />
|
||||
<key width="0.75" key0=")" key2="]" key4="}" />
|
||||
<key key0="4" />
|
||||
<key key0="5" key1="up" key2="right" key3="left" key4="down" />
|
||||
<key key0="6" />
|
||||
<key width="0.75" key0="+" key1="Σ" key2="$" />
|
||||
<key width="0.75" key0="-" key2="^" />
|
||||
<key width="0.75" key0="tab" key2="|" key4="\\"/>
|
||||
<key width="0.75" key0=")" key2="]" key4="}"/>
|
||||
<key key0="4" key1="box" key3="arrows"/>
|
||||
<key key0="5" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
|
||||
<key key0="6"/>
|
||||
<key width="0.75" key0="+" key1="Σ" key2="$"/>
|
||||
<key width="0.75" key0="-" key1="^"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.35" width="1.15" key0="shift" key2="fn" key4="alt" />
|
||||
<key key0="1" key1="superscript" key3="subscript" />
|
||||
<key key0="2" />
|
||||
<key key0="3" />
|
||||
<key width="1.15" key0="backspace" key2="delete" />
|
||||
<key shift="0.35" width="1.15" key0="shift" key2="fn" key4="alt"/>
|
||||
<key key0="1" key1="superscript" key2="ordinal" key3="subscript"/>
|
||||
<key key0="2"/>
|
||||
<key key0="3"/>
|
||||
<key width="1.15" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
<row height="0.95">
|
||||
<key width="1.5" key0="ctrl" key3="switch_text" />
|
||||
<key width="1.5" key0="0" />
|
||||
<key width="0.75" key0="." key2="," />
|
||||
<key width="0.75" key0="space" key1=""" key2="'" key4="_" />
|
||||
<key width="1.5" key0="enter" key2="±" key3="=" />
|
||||
<row height="0.95">
|
||||
<key width="1.5" key0="switch_text" key2="ctrl"/>
|
||||
<key width="1.5" key0="0" key3="f11_placeholder" key4="f12_placeholder"/>
|
||||
<key width="0.75" key0="." key1=":" key2="," key3=";"/>
|
||||
<key width="0.75" key0="space" key1=""" key2="'" key4="_"/>
|
||||
<key width="1.5" key0="enter" key1="±" key2="action" key3="="/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
@@ -1,44 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key1="esc" key2="1" key3="~" key4="!" />
|
||||
<key key0="w" key2="2" key3="\@" />
|
||||
<key key0="e" key2="3" key3="\#" />
|
||||
<key key0="r" key2="4" key3="$" />
|
||||
<key key0="t" key2="5" key3="%" />
|
||||
<key key0="y" key2="6" key3="^" />
|
||||
<key key0="u" key2="7" key3="&" />
|
||||
<key key0="i" key2="8" key3="*" />
|
||||
<key key0="o" key2="9" key3="(" key4=")" />
|
||||
<key key0="p" key2="0" />
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="a" key1="tab" key2="`" />
|
||||
<key key0="s" />
|
||||
<key key0="d" key1="accent_grave" key3="accent_aigu" />
|
||||
<key key0="f" />
|
||||
<key key0="g" key2="-" key3="_" />
|
||||
<key key0="h" key2="=" key3="+" />
|
||||
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{" />
|
||||
<key key0="k" key4="]" key3="[" />
|
||||
<key key0="l" key2="|" key3="\\" />
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift" />
|
||||
<key key0="z" />
|
||||
<key key0="x" />
|
||||
<key key0="c" key1="accent_cedille" key2="<" key3="." />
|
||||
<key key0="v" key2=">" key3="," />
|
||||
<key key0="b" key2="\?" key3="/" />
|
||||
<key key0="n" key1="accent_tilde" key2=":" key3=";" />
|
||||
<key key0="m" key2=""" key3="'" />
|
||||
<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>
|
||||
<row>
|
||||
<key key0="q" key2="1" key4="esc"/>
|
||||
<key key0="w" key1="~" key2="2" key3="\@"/>
|
||||
<key key0="e" key1="!" key2="3" key3="\#" key4="€"/>
|
||||
<key key0="r" key2="4" key3="$"/>
|
||||
<key key0="t" key2="5" key3="%"/>
|
||||
<key key0="y" key2="6" key3="^"/>
|
||||
<key key0="u" key2="7" key3="&"/>
|
||||
<key key0="i" key2="8" key3="*"/>
|
||||
<key key0="o" key1="accent_macron" key2="9" key3="(" key4=")"/>
|
||||
<key key0="p" key1="0" key3="f11_placeholder" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="a" key1="tab" key2="`"/>
|
||||
<key key0="s" key1="accent_ring" key3="ß"/>
|
||||
<key key0="d" key1="accent_grave" key2="£" key3="accent_aigu"/>
|
||||
<key key0="f"/>
|
||||
<key key0="g" key1="accent_caron" key2="-" key3="_"/>
|
||||
<key key0="h" key2="=" key3="+"/>
|
||||
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
|
||||
<key key0="k" key3="[" key4="]"/>
|
||||
<key key0="l" key2="|" key3="\\"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="z"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c" key1="accent_cedille" key2="<" key3="."/>
|
||||
<key key0="v" key2=">" key3=","/>
|
||||
<key key0="b" key2="\?" key3="/"/>
|
||||
<key key0="n" key1="accent_tilde" key2=":" key3=";"/>
|
||||
<key key0="m" key2=""" key3="'"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
||||
|
38
res/xml/qwerty_es.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key2="1" key4="esc"/>
|
||||
<key key0="w" key1="~" key2="2" key3="\@"/>
|
||||
<key key0="e" key1="!" key2="3" key3="\#" key4="€"/>
|
||||
<key key0="r" key2="4" key3="$"/>
|
||||
<key key0="t" key2="5" key3="%"/>
|
||||
<key key0="y" key2="6" key3="^"/>
|
||||
<key key0="u" key2="7" key3="&"/>
|
||||
<key key0="i" key2="8" key3="*"/>
|
||||
<key key0="o" key1="accent_macron" key2="9" key3="(" key4=")"/>
|
||||
<key key0="p" key1="0" key3="f11_placeholder" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="a" key2="tab" key4="`"/>
|
||||
<key key0="s" key1="accent_ring" key2="¡" key3="ß"/>
|
||||
<key key0="d" key1="accent_grave" key2="£" key3="accent_aigu"/>
|
||||
<key key0="f"/>
|
||||
<key key0="g" key1="accent_caron" key2="-" key3="_"/>
|
||||
<key key0="h" key2="=" key3="+"/>
|
||||
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
|
||||
<key key0="k" key3="[" key4="]"/>
|
||||
<key key0="l" key2="|" key3="\\"/>
|
||||
<key key0="ñ" key1="·" key3="ç" />
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="z"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c" key1="accent_cedille" key2="<" key3="."/>
|
||||
<key key0="v" key2=">" key3=","/>
|
||||
<key key0="b" key2="\?" key3="/" key4="¿"/>
|
||||
<key key0="n" key1="accent_tilde" key2=":" key3=";"/>
|
||||
<key key0="m" key2=""" key3="'"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
37
res/xml/qwerty_ko.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="ㅂ" key2="1" key4="esc"/>
|
||||
<key key0="ㅈ" key1="~" key2="2" key3="\@"/>
|
||||
<key key0="ㄷ" key1="!" key2="3" key3="\#" key4="€"/>
|
||||
<key key0="ㄱ" key2="4" key3="$"/>
|
||||
<key key0="ㅅ" key2="5" key3="%"/>
|
||||
<key key0="ㅛ" key2="6" key3="^"/>
|
||||
<key key0="ㅕ" key2="7" key3="&"/>
|
||||
<key key0="ㅑ" key2="8" key3="*"/>
|
||||
<key key0="ㅐ" key2="9" key3="(" key4=")"/>
|
||||
<key key0="ㅔ" key1="0" key3="f11_placeholder" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="ㅁ" key1="tab" key2="`"/>
|
||||
<key key0="ㄴ" key3="ß"/>
|
||||
<key key0="ㅇ" key2="£"/>
|
||||
<key key0="ㄹ"/>
|
||||
<key key0="ㅎ" key2="-" key3="_"/>
|
||||
<key key0="ㅗ" key2="=" key3="+"/>
|
||||
<key key0="ㅓ" key4="}" key3="{"/>
|
||||
<key key0="ㅏ" key3="[" key4="]"/>
|
||||
<key key0="ㅣ" key2="|" key3="\\"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="ㅋ"/>
|
||||
<key key0="ㅌ"/>
|
||||
<key key0="ㅊ" key2="<" key3="."/>
|
||||
<key key0="ㅍ" key2=">" key3=","/>
|
||||
<key key0="ㅠ" key2="\?" key3="/"/>
|
||||
<key key0="ㅜ" key2=":" key3=";"/>
|
||||
<key key0="ㅡ" key2=""" key3="'"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
37
res/xml/qwerty_lv.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key2="1" key4="esc"/>
|
||||
<key key0="w" key1="~" key2="2" key3="\@" key4="!"/>
|
||||
<key key0="e" key1="ē" key2="3" key3="\#" key4="€"/>
|
||||
<key key0="r" key1="ŗ" key2="4" key3="$" key4="f11_placeholder"/>
|
||||
<key key0="t" key2="5" key3="%" key4="f12_placeholder"/>
|
||||
<key key0="y" key2="6" key3="^"/>
|
||||
<key key0="u" key1="ū" key2="7" key3="&" key4="*"/>
|
||||
<key key0="i" key1="ī" key2="8" key3="(" key4=")"/>
|
||||
<key key0="o" key1="ō" key2="9" key3="{" key4="}"/>
|
||||
<key key0="p" key1="0"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="a" key1="ā" key2="tab"/>
|
||||
<key key0="s" key1="š" key3="ß"/>
|
||||
<key key0="d" key2="£"/>
|
||||
<key key0="f"/>
|
||||
<key key0="g" key1="ģ"/>
|
||||
<key key0="h" key2="accent_macron" key3="accent_caron" key4="accent_cedille"/>
|
||||
<key key0="j" key1="+" key2="=" key3="-" key4="_"/>
|
||||
<key key0="k" key1="ķ" key3="[" key4="]"/>
|
||||
<key key0="l" key1="ļ" key2="|" key3="/" key4="\\"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="z" key1="ž"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c" key1="č"/>
|
||||
<key key0="v"/>
|
||||
<key key0="b" key2="\?" key3="<" key4=">"/>
|
||||
<key key0="n" key1="ņ" key2="`" key3=":" key4=";"/>
|
||||
<key key0="m" key1="'" key2=""" key3="," key4="."/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
38
res/xml/qwerty_pt.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key2="1" key4="esc"/>
|
||||
<key key0="w" key1="~" key2="2" key3="\@" key4="!"/>
|
||||
<key key0="e" key1="£" key2="3" key3="\#" key4="€"/>
|
||||
<key key0="r" key2="4" key3="$" key4="f11_placeholder"/>
|
||||
<key key0="t" key2="5" key3="%" key4="f12_placeholder"/>
|
||||
<key key0="y" key1="accent_caron" key2="6" key3="^" key4="accent_trema"/>
|
||||
<key key0="u" key2="7" key3="&"/>
|
||||
<key key0="i" key2="8" key3="*"/>
|
||||
<key key0="o" key2="9" key3="(" key4=")"/>
|
||||
<key key0="p" key1="0" key3="\\"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="a" key2="tab" key4="`"/>
|
||||
<key key0="s" key1="'" key3="ß" key4="accent_cedille"/>
|
||||
<key key0="d" key1=""" key2="accent_ring"/>
|
||||
<key key0="f" key2="accent_caron"/>
|
||||
<key key0="g"/>
|
||||
<key key0="h"/>
|
||||
<key key0="j" key1="-" key2="=" key4="+" key3="_"/>
|
||||
<key key0="k" key1="accent_grave" key2="accent_aigu" key3="accent_tilde" key4="accent_circonflexe"/>
|
||||
<key key0="l" key1="[" key2="]" key3="{" key4="}"/>
|
||||
<key key0="ç" key1="|"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="z"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c"/>
|
||||
<key key0="v"/>
|
||||
<key key0="b"/>
|
||||
<key key0="n" key1="<" key2=">" key3="," key4="."/>
|
||||
<key key0="m" key1=":" key2=";" key3="/" key4="\?"/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
41
res/xml/qwerty_sv_se.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key4="esc" key2="1"/>
|
||||
<key key0="w" key2="2" key3="`" key4="\@"/>
|
||||
<key key0="e" key2="3" key4="\#" key3="€"/>
|
||||
<key key0="r" key2="4" key4="$"/>
|
||||
<key key0="t" key2="5" key3="&" key4="|"/>
|
||||
<key key0="y" key2="6" key3="^" key4="%"/>
|
||||
<key key0="u" key2="7" key3="~" key4="\\"/>
|
||||
<key key0="i" key2="8" key3="*" key4="/"/>
|
||||
<key key0="o" key2="9" key3="+" key4="-"/>
|
||||
<key key0="p" key2="0" key3="=" key4="f11_placeholder"/>
|
||||
<key key0="å" key1="\?" key3="!" key4="f12_placeholder"/>
|
||||
</row>
|
||||
<row>
|
||||
<key key0="a" key2="tab"/>
|
||||
<key key0="s" key1="accent_ring" key2="accent_cedille" key3="ß" key4="accent_tilde"/>
|
||||
<key key0="d" key1="accent_grave" key2="accent_caron" key3="accent_aigu"/>
|
||||
<key key0="f" key1="accent_trema" key2="accent_circonflexe"/>
|
||||
<key key0="g"/>
|
||||
<key key0="h"/>
|
||||
<key key0="j" key1="{" key4="}"/>
|
||||
<key key0="k" key1="[" key4="]"/>
|
||||
<key key0="l" key1="(" key4=")"/>
|
||||
<key key0="ö" key1="<" key4=">"/>
|
||||
<key key0="ä" key1="'" key3="""/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="z"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c"/>
|
||||
<key key0="v"/>
|
||||
<key key0="b" key2=";" key4=","/>
|
||||
<key key0="n" key2=":" key4="."/>
|
||||
<key key0="m" key2="-" key4="_"/>
|
||||
<key width="1.0" key0="." key1="!" key2="\?" key3="'" key4=","/>
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
37
res/xml/qwertz.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keyboard>
|
||||
<row>
|
||||
<key key0="q" key2="1" key4="esc"/>
|
||||
<key key0="w" key1="^" key2="2" key3=""" key4="\@"/>
|
||||
<key key0="e" key1="§" key2="3" key3="!" key4="€"/>
|
||||
<key key0="r" key2="4" key3="$" key4="f11_placeholder"/>
|
||||
<key key0="t" key2="5" key3="%" key4="f12_placeholder"/>
|
||||
<key key0="z" key2="6" key3="&" key4="{"/>
|
||||
<key key0="u" key2="7" key3="ü" key4="}"/>
|
||||
<key key0="i" key1="(" key2="8" key3="[" key4="]"/>
|
||||
<key key0="o" key1=")" key2="9" key3="ö" key4="="/>
|
||||
<key key0="p" key1="0" key3="\?"/>
|
||||
</row>
|
||||
<row>
|
||||
<key shift="0.5" key0="a" key1="tab" key2="`" key3="ä"/>
|
||||
<key key0="s" key3="ß"/>
|
||||
<key key0="d" key2="£"/>
|
||||
<key key0="f" key1="~"/>
|
||||
<key key0="g" key3="-"/>
|
||||
<key key0="h" key3="+"/>
|
||||
<key key0="j" key3="*"/>
|
||||
<key key0="k" key3="/" key4="\\"/>
|
||||
<key key0="l" key1="'" key3="\#"/>
|
||||
</row>
|
||||
<row>
|
||||
<key width="1.5" key0="shift"/>
|
||||
<key key0="y" key1=">" key2="|" key3="<"/>
|
||||
<key key0="x"/>
|
||||
<key key0="c"/>
|
||||
<key key0="v" />
|
||||
<key key0="b" key1=";" key3=","/>
|
||||
<key key0="n" key1=":" key3="."/>
|
||||
<key key0="m" key1="_" />
|
||||
<key width="1.5" key0="backspace" key2="delete"/>
|
||||
</row>
|
||||
</keyboard>
|
@@ -1,102 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory android:title="@string/pref_category_layout">
|
||||
<ListPreference
|
||||
android:key="layout"
|
||||
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 android:title="@string/pref_category_typing">
|
||||
<juloo.common.SlideBarPreference
|
||||
android:key="sub_value_dist"
|
||||
android:title="@string/pref_preci_title"
|
||||
android:summary="@string/pref_preci_summary"
|
||||
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 android:title="@string/pref_category_vibrate">
|
||||
<CheckBoxPreference
|
||||
android:key="vibrate_enabled"
|
||||
android:title="@string/pref_vibrate_title"
|
||||
android:summary="@string/pref_vibrate_summary"
|
||||
android:defaultValue="true"
|
||||
/>
|
||||
<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 android:title="@string/pref_category_style">
|
||||
<juloo.common.IntSlideBarPreference
|
||||
android:key="margin_bottom"
|
||||
android:title="@string/pref_margin_bottom_title"
|
||||
android:summary="@string/pref_margin_bottom_summary"
|
||||
android:defaultValue="5"
|
||||
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="60"
|
||||
/>
|
||||
<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 android:title="@string/pref_category_layout">
|
||||
<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"/>
|
||||
<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"/>
|
||||
<ListPreference android:key="programming_layout" android:title="@string/pref_programming_layout_title" android:summary="%s" android:defaultValue="none" android:entries="@array/pref_programming_layout_entries" android:entryValues="@array/pref_programming_layout_values"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_category_typing">
|
||||
<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"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="longpress_timeout" android:title="@string/pref_long_timeout_title" android:summary="%sms" android:defaultValue="600" min="50" max="2000"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="longpress_interval" android:title="@string/pref_long_interval_title" android:summary="%sms" android:defaultValue="25" min="5" max="100"/>
|
||||
<CheckBoxPreference android:key="precise_repeat" android:title="@string/pref_precise_repeat_title" android:summary="@string/pref_precise_repeat_summary" android:defaultValue="true"/>
|
||||
<PreferenceScreen android:title="@string/pref_lockable_keys_title" android:summary="@string/pref_lockable_keys_summary">
|
||||
<CheckBoxPreference android:key="lockable_shift" android:title="Shift" android:defaultValue="true"/>
|
||||
<CheckBoxPreference android:key="lockable_ctrl" android:title="Ctrl" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_alt" android:title="Alt" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_fn" android:title="Fn" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_meta" android:title="Meta" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_sup" android:title="Sup" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_sub" android:title="Sub" android:defaultValue="false"/>
|
||||
<CheckBoxPreference android:key="lockable_box" android:title="Box" android:defaultValue="false"/>
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_category_vibrate">
|
||||
<CheckBoxPreference android:key="vibrate_enabled" android:title="@string/pref_vibrate_title" android:summary="@string/pref_vibrate_summary" android:defaultValue="true"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="vibrate_duration" android:title="@string/pref_vibrate_duration_title" android:summary="%sms" android:defaultValue="20" min="5" max="100"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_category_style">
|
||||
<ListPreference android:key="theme" android:title="@string/pref_theme" android:summary="%s" android:defaultValue="system" android:entries="@array/pref_theme_entries" android:entryValues="@array/pref_theme_values"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="margin_bottom" android:title="@string/pref_margin_bottom_title" android:summary="%sdp" android:defaultValue="5" min="0" max="100"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="keyboard_height" android:title="@string/pref_keyboard_height_title" android:summary="%s%%" android:defaultValue="35" min="25" max="50"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="horizontal_margin" android:title="@string/pref_horizontal_margin_title" android:summary="%sdp" 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"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="key_vertical_space" android:title="@string/pref_key_vertical_space" android:summary="%sdp" android:defaultValue="2" min="0" max="8"/>
|
||||
<juloo.common.IntSlideBarPreference android:key="key_horizontal_space" android:title="@string/pref_key_horizontal_space" android:summary="%sdp" android:defaultValue="2" min="0" max="8"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
@@ -4,18 +4,16 @@
|
||||
} }:
|
||||
|
||||
let
|
||||
jdk = pkgs.openjdk8;
|
||||
|
||||
android = pkgs.androidenv.composeAndroidPackages {
|
||||
buildToolsVersions = [ "30.0.3" ];
|
||||
platformVersions = [ "29" ];
|
||||
platformVersions = [ "30" ];
|
||||
abiVersions = [ "armeabi-v7a" ];
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
findutils openjdk8 android.androidsdk
|
||||
];
|
||||
buildInputs = [ pkgs.findutils jdk android.androidsdk pkgs.fontforge ];
|
||||
ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk";
|
||||
}
|
||||
|
@@ -11,106 +11,110 @@ import android.widget.TextView;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
/*
|
||||
** IntSlideBarPreference
|
||||
** -
|
||||
** Open a dialog showing a seekbar
|
||||
** -
|
||||
** xml attrs:
|
||||
** android:defaultValue Default value (int)
|
||||
** min min value (int)
|
||||
** max max value (int)
|
||||
** -
|
||||
** Summary field allow to show the current value using %s flag
|
||||
*/
|
||||
** IntSlideBarPreference
|
||||
** -
|
||||
** Open a dialog showing a seekbar
|
||||
** -
|
||||
** xml attrs:
|
||||
** android:defaultValue Default value (int)
|
||||
** min min value (int)
|
||||
** max max value (int)
|
||||
** -
|
||||
** Summary field allow to show the current value using %s flag
|
||||
*/
|
||||
public class IntSlideBarPreference extends DialogPreference
|
||||
implements SeekBar.OnSeekBarChangeListener
|
||||
implements SeekBar.OnSeekBarChangeListener
|
||||
{
|
||||
private LinearLayout _layout;
|
||||
private TextView _textView;
|
||||
private SeekBar _seekBar;
|
||||
private LinearLayout _layout;
|
||||
private TextView _textView;
|
||||
private SeekBar _seekBar;
|
||||
|
||||
private int _min;
|
||||
private int _min;
|
||||
|
||||
private String _initialSummary;
|
||||
private String _initialSummary;
|
||||
|
||||
public IntSlideBarPreference(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
_initialSummary = getSummary().toString();
|
||||
_textView = new TextView(context);
|
||||
_textView.setPadding(48, 40, 48, 40);
|
||||
_seekBar = new SeekBar(context);
|
||||
_seekBar.setOnSeekBarChangeListener(this);
|
||||
_min = attrs.getAttributeIntValue(null, "min", 0);
|
||||
int max = attrs.getAttributeIntValue(null, "max", 0);
|
||||
_seekBar.setMax(max - _min);
|
||||
_layout = new LinearLayout(getContext());
|
||||
_layout.setOrientation(LinearLayout.VERTICAL);
|
||||
_layout.addView(_textView);
|
||||
_layout.addView(_seekBar);
|
||||
}
|
||||
public IntSlideBarPreference(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
_initialSummary = getSummary().toString();
|
||||
_textView = new TextView(context);
|
||||
_textView.setPadding(48, 40, 48, 40);
|
||||
_seekBar = new SeekBar(context);
|
||||
_seekBar.setOnSeekBarChangeListener(this);
|
||||
_min = attrs.getAttributeIntValue(null, "min", 0);
|
||||
int max = attrs.getAttributeIntValue(null, "max", 0);
|
||||
_seekBar.setMax(max - _min);
|
||||
_layout = new LinearLayout(getContext());
|
||||
_layout.setOrientation(LinearLayout.VERTICAL);
|
||||
_layout.addView(_textView);
|
||||
_layout.addView(_seekBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
updateText();
|
||||
}
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
updateText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
|
||||
{
|
||||
int value;
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (restorePersistedValue)
|
||||
{
|
||||
value = getPersistedInt(_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (Integer)defaultValue;
|
||||
persistInt(value);
|
||||
}
|
||||
_seekBar.setProgress(value - _min);
|
||||
updateText();
|
||||
}
|
||||
if (restorePersistedValue)
|
||||
{
|
||||
value = getPersistedInt(_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (Integer)defaultValue;
|
||||
persistInt(value);
|
||||
}
|
||||
_seekBar.setProgress(value - _min);
|
||||
updateText();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray a, int index)
|
||||
{
|
||||
return (a.getInt(index, _min));
|
||||
}
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray a, int index)
|
||||
{
|
||||
return (a.getInt(index, _min));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult)
|
||||
{
|
||||
if (positiveResult)
|
||||
persistInt(_seekBar.getProgress() + _min);
|
||||
}
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult)
|
||||
{
|
||||
if (positiveResult)
|
||||
persistInt(_seekBar.getProgress() + _min);
|
||||
else
|
||||
_seekBar.setProgress(getPersistedInt(_min) - _min);
|
||||
|
||||
protected View onCreateDialogView()
|
||||
{
|
||||
ViewGroup parent = (ViewGroup)_layout.getParent();
|
||||
updateText();
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
parent.removeView(_layout);
|
||||
return (_layout);
|
||||
}
|
||||
protected View onCreateDialogView()
|
||||
{
|
||||
ViewGroup parent = (ViewGroup)_layout.getParent();
|
||||
|
||||
private void updateText()
|
||||
{
|
||||
String f = String.format(_initialSummary, _seekBar.getProgress() + _min);
|
||||
if (parent != null)
|
||||
parent.removeView(_layout);
|
||||
return (_layout);
|
||||
}
|
||||
|
||||
_textView.setText(f);
|
||||
setSummary(f);
|
||||
}
|
||||
private void updateText()
|
||||
{
|
||||
String f = String.format(_initialSummary, _seekBar.getProgress() + _min);
|
||||
|
||||
_textView.setText(f);
|
||||
setSummary(f);
|
||||
}
|
||||
}
|
||||
|
@@ -11,117 +11,121 @@ import android.widget.TextView;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
/*
|
||||
** SideBarPreference
|
||||
** -
|
||||
** Open a dialog showing a seekbar
|
||||
** -
|
||||
** xml attrs:
|
||||
** android:defaultValue Default value (float)
|
||||
** min min value (float)
|
||||
** max max value (float)
|
||||
** -
|
||||
** Summary field allow to show the current value using %f or %s flag
|
||||
*/
|
||||
** SideBarPreference
|
||||
** -
|
||||
** Open a dialog showing a seekbar
|
||||
** -
|
||||
** xml attrs:
|
||||
** android:defaultValue Default value (float)
|
||||
** min min value (float)
|
||||
** max max value (float)
|
||||
** -
|
||||
** Summary field allow to show the current value using %f or %s flag
|
||||
*/
|
||||
public class SlideBarPreference extends DialogPreference
|
||||
implements SeekBar.OnSeekBarChangeListener
|
||||
implements SeekBar.OnSeekBarChangeListener
|
||||
{
|
||||
private static final int STEPS = 100;
|
||||
private static final int STEPS = 100;
|
||||
|
||||
private LinearLayout _layout;
|
||||
private TextView _textView;
|
||||
private SeekBar _seekBar;
|
||||
private LinearLayout _layout;
|
||||
private TextView _textView;
|
||||
private SeekBar _seekBar;
|
||||
|
||||
private float _min;
|
||||
private float _max;
|
||||
private float _value;
|
||||
private float _min;
|
||||
private float _max;
|
||||
private float _value;
|
||||
|
||||
private String _initialSummary;
|
||||
private String _initialSummary;
|
||||
|
||||
public SlideBarPreference(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
_initialSummary = getSummary().toString();
|
||||
_textView = new TextView(context);
|
||||
_textView.setPadding(48, 40, 48, 40);
|
||||
_seekBar = new SeekBar(context);
|
||||
_seekBar.setOnSeekBarChangeListener(this);
|
||||
_seekBar.setMax(STEPS);
|
||||
_min = float_of_string(attrs.getAttributeValue(null, "min"));
|
||||
_value = _min;
|
||||
_max = Math.max(1f, float_of_string(attrs.getAttributeValue(null, "max")));
|
||||
_layout = new LinearLayout(getContext());
|
||||
_layout.setOrientation(LinearLayout.VERTICAL);
|
||||
_layout.addView(_textView);
|
||||
_layout.addView(_seekBar);
|
||||
}
|
||||
public SlideBarPreference(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
_initialSummary = getSummary().toString();
|
||||
_textView = new TextView(context);
|
||||
_textView.setPadding(48, 40, 48, 40);
|
||||
_seekBar = new SeekBar(context);
|
||||
_seekBar.setOnSeekBarChangeListener(this);
|
||||
_seekBar.setMax(STEPS);
|
||||
_min = float_of_string(attrs.getAttributeValue(null, "min"));
|
||||
_value = _min;
|
||||
_max = Math.max(1f, float_of_string(attrs.getAttributeValue(null, "max")));
|
||||
_layout = new LinearLayout(getContext());
|
||||
_layout.setOrientation(LinearLayout.VERTICAL);
|
||||
_layout.addView(_textView);
|
||||
_layout.addView(_seekBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
_value = Math.round(progress * (_max - _min)) / (float)STEPS + _min;
|
||||
updateText();
|
||||
}
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
_value = Math.round(progress * (_max - _min)) / (float)STEPS + _min;
|
||||
updateText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
|
||||
{
|
||||
if (restorePersistedValue)
|
||||
{
|
||||
_value = getPersistedFloat(_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = (Float)defaultValue;
|
||||
persistFloat(_value);
|
||||
}
|
||||
_seekBar.setProgress((int)((_value - _min) * STEPS / (_max - _min)));
|
||||
updateText();
|
||||
}
|
||||
@Override
|
||||
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
|
||||
{
|
||||
if (restorePersistedValue)
|
||||
{
|
||||
_value = getPersistedFloat(_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = (Float)defaultValue;
|
||||
persistFloat(_value);
|
||||
}
|
||||
_seekBar.setProgress((int)((_value - _min) * STEPS / (_max - _min)));
|
||||
updateText();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray a, int index)
|
||||
{
|
||||
return (a.getFloat(index, _min));
|
||||
}
|
||||
@Override
|
||||
protected Object onGetDefaultValue(TypedArray a, int index)
|
||||
{
|
||||
return (a.getFloat(index, _min));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult)
|
||||
{
|
||||
if (positiveResult)
|
||||
persistFloat(_value);
|
||||
}
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult)
|
||||
{
|
||||
if (positiveResult)
|
||||
persistFloat(_value);
|
||||
else
|
||||
_seekBar.setProgress((int)((getPersistedFloat(_min) - _min) * STEPS / (_max - _min)));
|
||||
|
||||
protected View onCreateDialogView()
|
||||
{
|
||||
ViewGroup parent = (ViewGroup)_layout.getParent();
|
||||
updateText();
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
parent.removeView(_layout);
|
||||
return (_layout);
|
||||
}
|
||||
protected View onCreateDialogView()
|
||||
{
|
||||
ViewGroup parent = (ViewGroup)_layout.getParent();
|
||||
|
||||
private void updateText()
|
||||
{
|
||||
String f = String.format(_initialSummary, _value);
|
||||
if (parent != null)
|
||||
parent.removeView(_layout);
|
||||
return (_layout);
|
||||
}
|
||||
|
||||
_textView.setText(f);
|
||||
setSummary(f);
|
||||
}
|
||||
private void updateText()
|
||||
{
|
||||
String f = String.format(_initialSummary, _value);
|
||||
|
||||
private static float float_of_string(String str)
|
||||
{
|
||||
if (str == null)
|
||||
return (0f);
|
||||
return (Float.parseFloat(str));
|
||||
}
|
||||
_textView.setText(f);
|
||||
setSummary(f);
|
||||
}
|
||||
|
||||
private static float float_of_string(String str)
|
||||
{
|
||||
if (str == null)
|
||||
return (0f);
|
||||
return (Float.parseFloat(str));
|
||||
}
|
||||
}
|
||||
|
@@ -1,124 +1,256 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
class Config
|
||||
final class Config
|
||||
{
|
||||
private Keyboard2 _context;
|
||||
|
||||
// From resources
|
||||
public final float marginTop;
|
||||
public final float keyPadding;
|
||||
public final float keyVerticalInterval;
|
||||
public final float keyHorizontalInterval;
|
||||
public final float keyRound;
|
||||
public final float marginTop;
|
||||
public final float keyPadding;
|
||||
|
||||
public final float labelTextSize;
|
||||
public final float sublabelTextSize;
|
||||
|
||||
// From preferences
|
||||
public int layout; // Or '-1' for the system defaults
|
||||
public float subValueDist;
|
||||
public boolean vibrateEnabled;
|
||||
public long vibrateDuration;
|
||||
public long longPressTimeout;
|
||||
public long longPressInterval;
|
||||
public float marginBottom;
|
||||
public float keyHeight;
|
||||
public float horizontalMargin;
|
||||
public int programming_layout; // Or '-1' for none
|
||||
public float swipe_dist_px;
|
||||
public boolean vibrateEnabled;
|
||||
public long vibrateDuration;
|
||||
public long longPressTimeout;
|
||||
public long longPressInterval;
|
||||
public float marginBottom;
|
||||
public float keyHeight;
|
||||
public float horizontalMargin;
|
||||
public float keyVerticalInterval;
|
||||
public float keyHorizontalInterval;
|
||||
public boolean preciseRepeat;
|
||||
public int lockable_modifiers;
|
||||
public float characterSize; // Ratio
|
||||
public int accents; // Values are R.values.pref_accents_v_*
|
||||
public int theme; // Values are R.style.*
|
||||
|
||||
// Dynamically set
|
||||
public boolean shouldOfferSwitchingToNextInputMethod;
|
||||
public int accent_flags_to_remove;
|
||||
public boolean shouldOfferSwitchingToProgramming;
|
||||
public String actionLabel; // Might be 'null'
|
||||
public int actionId; // Meaningful only when 'actionLabel' isn't 'null'
|
||||
public boolean swapEnterActionKey; // Swap the "enter" and "action" keys
|
||||
public Set<String> extra_keys; // 'null' means all the keys
|
||||
|
||||
public Config(Keyboard2 context)
|
||||
{
|
||||
Resources res = context.getResources();
|
||||
public final IKeyEventHandler handler;
|
||||
|
||||
_context = context;
|
||||
// static values
|
||||
marginTop = res.getDimension(R.dimen.margin_top);
|
||||
keyPadding = res.getDimension(R.dimen.key_padding);
|
||||
keyVerticalInterval = res.getDimension(R.dimen.key_vertical_interval);
|
||||
keyHorizontalInterval = res.getDimension(R.dimen.key_horizontal_interval);
|
||||
keyRound = res.getDimension(R.dimen.key_round);
|
||||
// default values
|
||||
private Config(Context context, IKeyEventHandler h)
|
||||
{
|
||||
Resources res = context.getResources();
|
||||
// static values
|
||||
marginTop = res.getDimension(R.dimen.margin_top);
|
||||
keyPadding = res.getDimension(R.dimen.key_padding);
|
||||
labelTextSize = Float.valueOf(res.getString(R.integer.label_text_size));
|
||||
sublabelTextSize = Float.valueOf(res.getString(R.integer.sublabel_text_size));
|
||||
// default values
|
||||
layout = -1;
|
||||
subValueDist = 10f;
|
||||
vibrateEnabled = true;
|
||||
vibrateDuration = 20;
|
||||
longPressTimeout = 600;
|
||||
longPressInterval = 65;
|
||||
marginBottom = res.getDimension(R.dimen.margin_bottom);
|
||||
keyHeight = res.getDimension(R.dimen.key_height);
|
||||
horizontalMargin = res.getDimension(R.dimen.horizontal_margin);
|
||||
programming_layout = -1;
|
||||
vibrateEnabled = true;
|
||||
vibrateDuration = 20;
|
||||
longPressTimeout = 600;
|
||||
longPressInterval = 65;
|
||||
marginBottom = res.getDimension(R.dimen.margin_bottom);
|
||||
keyHeight = res.getDimension(R.dimen.key_height);
|
||||
horizontalMargin = res.getDimension(R.dimen.horizontal_margin);
|
||||
keyVerticalInterval = res.getDimension(R.dimen.key_vertical_interval);
|
||||
keyHorizontalInterval = res.getDimension(R.dimen.key_horizontal_interval);
|
||||
preciseRepeat = true;
|
||||
characterSize = 1.f;
|
||||
accents = 1;
|
||||
// from prefs
|
||||
refresh();
|
||||
// from prefs
|
||||
refresh(context);
|
||||
// initialized later
|
||||
shouldOfferSwitchingToNextInputMethod = false;
|
||||
accent_flags_to_remove = 0;
|
||||
}
|
||||
shouldOfferSwitchingToProgramming = false;
|
||||
actionLabel = null;
|
||||
actionId = 0;
|
||||
swapEnterActionKey = false;
|
||||
extra_keys = null;
|
||||
handler = h;
|
||||
}
|
||||
|
||||
/*
|
||||
** Reload prefs
|
||||
*/
|
||||
public void refresh()
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(_context);
|
||||
|
||||
layout = layoutId_of_string(prefs.getString("layout", "system"));
|
||||
subValueDist = prefs.getFloat("sub_value_dist", subValueDist);
|
||||
vibrateEnabled = prefs.getBoolean("vibrate_enabled", vibrateEnabled);
|
||||
vibrateDuration = prefs.getInt("vibrate_duration", (int)vibrateDuration);
|
||||
longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout);
|
||||
longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval);
|
||||
marginBottom = getDipPref(prefs, "margin_bottom", marginBottom);
|
||||
keyHeight = getDipPref(prefs, "key_height", keyHeight);
|
||||
horizontalMargin = getDipPref(prefs, "horizontal_margin", horizontalMargin);
|
||||
/*
|
||||
** Reload prefs
|
||||
*/
|
||||
public void refresh(Context context)
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Resources res = context.getResources();
|
||||
DisplayMetrics dm = res.getDisplayMetrics();
|
||||
// The height of the keyboard is relative to the height of the screen. This
|
||||
// is not the actual size of the keyboard, which will be bigger if the
|
||||
// layout has a fifth row.
|
||||
int keyboardHeightPercent;
|
||||
if (res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) // Landscape mode
|
||||
{
|
||||
keyboardHeightPercent = 55;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyboardHeightPercent = prefs.getInt("keyboard_height", 35);
|
||||
}
|
||||
String layout_s = prefs.getString("layout", "system");
|
||||
layout = layout_s.equals("system") ? -1 : layoutId_of_string(layout_s);
|
||||
String prog_layout_s = prefs.getString("programming_layout", "none");
|
||||
programming_layout = prog_layout_s.equals("none") ? -1 : layoutId_of_string(prog_layout_s);
|
||||
// The swipe distance is defined relatively to the "exact physical pixels
|
||||
// per inch of the screen", which isn't affected by the scaling settings.
|
||||
// Take the mean of both dimensions as an approximation of the diagonal.
|
||||
float physical_scaling = (dm.widthPixels + dm.heightPixels) / (dm.xdpi + dm.ydpi);
|
||||
swipe_dist_px = Float.valueOf(prefs.getString("swipe_dist", "15")) * physical_scaling;;
|
||||
vibrateEnabled = prefs.getBoolean("vibrate_enabled", vibrateEnabled);
|
||||
vibrateDuration = prefs.getInt("vibrate_duration", (int)vibrateDuration);
|
||||
longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout);
|
||||
longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval);
|
||||
marginBottom = getDipPref(dm, prefs, "margin_bottom", marginBottom);
|
||||
keyVerticalInterval = getDipPref(dm, prefs, "key_vertical_space", keyVerticalInterval);
|
||||
keyHorizontalInterval = getDipPref(dm, prefs, "key_horizontal_space", keyHorizontalInterval);
|
||||
// Do not substract keyVerticalInterval from keyHeight because this is done
|
||||
// during rendered.
|
||||
keyHeight = dm.heightPixels * keyboardHeightPercent / 100 / 4;
|
||||
horizontalMargin = getDipPref(dm, prefs, "horizontal_margin", horizontalMargin) + res.getDimension(R.dimen.extra_horizontal_margin);
|
||||
preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
|
||||
characterSize = prefs.getFloat("character_size", characterSize);
|
||||
lockable_modifiers =
|
||||
(prefs.getBoolean("lockable_shift", true) ? KeyValue.FLAG_SHIFT : 0)
|
||||
| (prefs.getBoolean("lockable_ctrl", false) ? KeyValue.FLAG_CTRL : 0)
|
||||
| (prefs.getBoolean("lockable_alt", false) ? KeyValue.FLAG_ALT : 0)
|
||||
| (prefs.getBoolean("lockable_fn", false) ? KeyValue.FLAG_FN : 0)
|
||||
| (prefs.getBoolean("lockable_meta", false) ? KeyValue.FLAG_META : 0)
|
||||
| (prefs.getBoolean("lockable_sup", false) ? KeyValue.FLAG_ACCENT_SUPERSCRIPT : 0)
|
||||
| (prefs.getBoolean("lockable_sub", false) ? KeyValue.FLAG_ACCENT_SUBSCRIPT : 0)
|
||||
| (prefs.getBoolean("lockable_box", false) ? KeyValue.FLAG_ACCENT_BOX : 0);
|
||||
characterSize = prefs.getFloat("character_size", characterSize);
|
||||
accents = Integer.valueOf(prefs.getString("accents", "1"));
|
||||
}
|
||||
theme = getThemeId(res, prefs.getString("theme", ""));
|
||||
}
|
||||
|
||||
private float getDipPref(SharedPreferences prefs, String pref_name, float def)
|
||||
{
|
||||
int value = prefs.getInt(pref_name, -1);
|
||||
/** Update the layout according to the configuration.
|
||||
* - Remove the switching key if it isn't needed
|
||||
* - Remove keys from other locales (not in 'extra_keys')
|
||||
* - Replace the action key to show the right label
|
||||
* - Swap the enter and action keys
|
||||
*/
|
||||
public KeyboardData modify_layout(KeyboardData kw)
|
||||
{
|
||||
// Update the name to avoid caching in KeyModifier
|
||||
KeyValue action_key = (actionLabel == null) ? null :
|
||||
KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel);
|
||||
return kw.replaceKeys(key -> {
|
||||
if (key == null)
|
||||
return null;
|
||||
switch (key.eventCode)
|
||||
{
|
||||
case KeyValue.EVENT_CHANGE_METHOD:
|
||||
return shouldOfferSwitchingToNextInputMethod ? key : null;
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
return (swapEnterActionKey && action_key != null) ? action_key : key;
|
||||
case KeyValue.EVENT_ACTION:
|
||||
return (swapEnterActionKey && action_key != null) ?
|
||||
KeyValue.getKeyByName("enter") : action_key;
|
||||
case KeyValue.EVENT_SWITCH_PROGRAMMING:
|
||||
return shouldOfferSwitchingToProgramming ? key : null;
|
||||
default:
|
||||
if (key.flags != 0)
|
||||
{
|
||||
if ((key.flags & KeyValue.FLAG_LOCALIZED) != 0 &&
|
||||
extra_keys != null &&
|
||||
!extra_keys.contains(key.name))
|
||||
return null;
|
||||
if ((key.flags & lockable_modifiers) != 0)
|
||||
return key.withFlags(key.flags | KeyValue.FLAG_LOCK);
|
||||
}
|
||||
return key;
|
||||
}});
|
||||
}
|
||||
|
||||
if (value < 0)
|
||||
return (def);
|
||||
return (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
|
||||
_context.getResources().getDisplayMetrics()));
|
||||
}
|
||||
private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
|
||||
{
|
||||
float value;
|
||||
try { value = prefs.getInt(pref_name, -1); }
|
||||
catch (Exception e) { value = prefs.getFloat(pref_name, -1f); }
|
||||
if (value < 0f)
|
||||
return (def);
|
||||
return (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm));
|
||||
}
|
||||
|
||||
private int getThemeId(Resources res, String theme_name)
|
||||
{
|
||||
switch (theme_name)
|
||||
{
|
||||
case "light": return R.style.Light;
|
||||
case "black": return R.style.Black;
|
||||
case "dark": return R.style.Dark;
|
||||
default:
|
||||
case "system":
|
||||
if (Build.VERSION.SDK_INT >= 8)
|
||||
{
|
||||
int night_mode = res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
if ((night_mode & Configuration.UI_MODE_NIGHT_NO) != 0)
|
||||
return R.style.Light;
|
||||
}
|
||||
return R.style.Dark;
|
||||
}
|
||||
}
|
||||
|
||||
public static int layoutId_of_string(String name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "azerty": return R.xml.azerty;
|
||||
case "bgph1": return R.xml.local_bgph1;
|
||||
case "dvorak": return R.xml.dvorak;
|
||||
case "qwerty_es": return R.xml.qwerty_es;
|
||||
case "qwerty_ko": return R.xml.qwerty_ko;
|
||||
case "qwerty_lv": return R.xml.qwerty_lv;
|
||||
case "qwerty_pt": return R.xml.qwerty_pt;
|
||||
case "qwerty": return R.xml.qwerty;
|
||||
case "system": return -1;
|
||||
default: throw new IllegalArgumentException();
|
||||
case "qwerty_sv_se": return R.xml.qwerty_sv_se;
|
||||
case "qwertz": return R.xml.qwertz;
|
||||
case "ru_jcuken": return R.xml.local_ru_jcuken;
|
||||
default: return R.xml.qwerty; // The config might store an invalid layout, don't crash
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for the accents option. */
|
||||
public static int accentFlag_of_name(String name)
|
||||
public static int themeId_of_string(String name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "grave": return KeyValue.FLAG_ACCENT1;
|
||||
case "aigu": return KeyValue.FLAG_ACCENT2;
|
||||
case "circonflexe": return KeyValue.FLAG_ACCENT3;
|
||||
case "tilde": return KeyValue.FLAG_ACCENT4;
|
||||
case "cedille": return KeyValue.FLAG_ACCENT5;
|
||||
case "trema": return KeyValue.FLAG_ACCENT6;
|
||||
default: throw new RuntimeException(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);
|
||||
}
|
||||
}
|
||||
|
@@ -10,35 +10,35 @@ import java.util.HashMap;
|
||||
|
||||
public class Emoji extends KeyValue
|
||||
{
|
||||
private final String _desc;
|
||||
private final String _desc;
|
||||
|
||||
private static HashMap<String, Emoji> emojis_by_name = new HashMap<String, Emoji>();
|
||||
|
||||
protected Emoji(String name, String bytecode, String desc)
|
||||
{
|
||||
super(name, bytecode, CHAR_NONE, EVENT_NONE, 0);
|
||||
_desc = desc;
|
||||
protected Emoji(String name, String bytecode, String desc)
|
||||
{
|
||||
super(name, bytecode, CHAR_NONE, EVENT_NONE, 0);
|
||||
_desc = desc;
|
||||
emojis_by_name.put(name, this);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return (_desc);
|
||||
}
|
||||
public String getDescription()
|
||||
{
|
||||
return (_desc);
|
||||
}
|
||||
|
||||
public static int num_groups = 0;
|
||||
|
||||
private static Emoji[][] emojis_by_group = new Emoji[][]{};
|
||||
|
||||
public static Emoji getEmojiByName(String name)
|
||||
{
|
||||
public static Emoji getEmojiByName(String name)
|
||||
{
|
||||
return emojis_by_name.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static Emoji[] getEmojisByGroup(int group_id)
|
||||
{
|
||||
return (emojis_by_group[group_id]);
|
||||
}
|
||||
public static Emoji[] getEmojisByGroup(int group_id)
|
||||
{
|
||||
return (emojis_by_group[group_id]);
|
||||
}
|
||||
|
||||
/* Read the list of emojis from a raw file. Will initialize only once. */
|
||||
public static void init(Resources res)
|
||||
|
@@ -19,158 +19,154 @@ import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class EmojiGridView extends GridView
|
||||
implements GridView.OnItemClickListener
|
||||
implements GridView.OnItemClickListener
|
||||
{
|
||||
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 float EMOJI_SIZE = 32.f;
|
||||
public static final int COLUMN_WIDTH = 192;
|
||||
|
||||
private static final String LAST_USE_PREF = "emoji_last_use";
|
||||
private static final String LAST_USE_PREF = "emoji_last_use";
|
||||
|
||||
private Emoji[] _emojiArray;
|
||||
private HashMap<Emoji, Integer> _lastUsed;
|
||||
private Emoji[] _emojiArray;
|
||||
private HashMap<Emoji, Integer> _lastUsed;
|
||||
|
||||
/*
|
||||
** TODO: adapt column width and emoji size
|
||||
** TODO: use ArraySet instead of Emoji[]
|
||||
*/
|
||||
public EmojiGridView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
/*
|
||||
** TODO: adapt column width and emoji size
|
||||
** TODO: use ArraySet instead of Emoji[]
|
||||
*/
|
||||
public EmojiGridView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
Emoji.init(context.getResources());
|
||||
setOnItemClickListener(this);
|
||||
setColumnWidth(COLUMN_WIDTH);
|
||||
loadLastUsed();
|
||||
setEmojiGroup((_lastUsed.size() == 0) ? 0 : GROUP_LAST_USE);
|
||||
}
|
||||
setOnItemClickListener(this);
|
||||
setColumnWidth(COLUMN_WIDTH);
|
||||
loadLastUsed();
|
||||
setEmojiGroup((_lastUsed.size() == 0) ? 0 : GROUP_LAST_USE);
|
||||
}
|
||||
|
||||
public void setEmojiGroup(int group)
|
||||
{
|
||||
_emojiArray = (group == GROUP_LAST_USE) ? getLastEmojis() : Emoji.getEmojisByGroup(group);
|
||||
setAdapter(new EmojiViewAdpater((Keyboard2)getContext(), _emojiArray));
|
||||
}
|
||||
public void setEmojiGroup(int group)
|
||||
{
|
||||
_emojiArray = (group == GROUP_LAST_USE) ? getLastEmojis() : Emoji.getEmojisByGroup(group);
|
||||
setAdapter(new EmojiViewAdpater(getContext(), _emojiArray));
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View v, int pos, long id)
|
||||
{
|
||||
Keyboard2 main = (Keyboard2)getContext();
|
||||
Integer used = _lastUsed.get(_emojiArray[pos]);
|
||||
public void onItemClick(AdapterView<?> parent, View v, int pos, long id)
|
||||
{
|
||||
Config config = Config.globalConfig();
|
||||
Integer used = _lastUsed.get(_emojiArray[pos]);
|
||||
_lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1);
|
||||
config.handler.handleKeyUp(_emojiArray[pos], 0);
|
||||
saveLastUsed(); // TODO: opti
|
||||
}
|
||||
|
||||
_lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1);
|
||||
main.handleKeyUp(_emojiArray[pos], 0);
|
||||
saveLastUsed(); // TODO: opti
|
||||
}
|
||||
@Override
|
||||
public void onMeasure(int wSpec, int hSpec)
|
||||
{
|
||||
super.onMeasure(wSpec, hSpec);
|
||||
setNumColumns(getMeasuredWidth() / COLUMN_WIDTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasure(int wSpec, int hSpec)
|
||||
{
|
||||
super.onMeasure(wSpec, hSpec);
|
||||
setNumColumns(getMeasuredWidth() / COLUMN_WIDTH);
|
||||
}
|
||||
private Emoji[] getLastEmojis()
|
||||
{
|
||||
final HashMap<Emoji, Integer> map = _lastUsed;
|
||||
Emoji[] array = new Emoji[map.size()];
|
||||
|
||||
private Emoji[] getLastEmojis()
|
||||
{
|
||||
final HashMap<Emoji, Integer> map = _lastUsed;
|
||||
Emoji[] array = new Emoji[map.size()];
|
||||
map.keySet().toArray(array);
|
||||
Arrays.sort(array, 0, array.length, new Comparator<Emoji>()
|
||||
{
|
||||
public int compare(Emoji a, Emoji b)
|
||||
{
|
||||
return (map.get(b).intValue() - map.get(a).intValue());
|
||||
}
|
||||
});
|
||||
return (array);
|
||||
}
|
||||
|
||||
map.keySet().toArray(array);
|
||||
Arrays.sort(array, 0, array.length, new Comparator<Emoji>()
|
||||
{
|
||||
public int compare(Emoji a, Emoji b)
|
||||
{
|
||||
return (map.get(b).intValue() - map.get(a).intValue());
|
||||
}
|
||||
});
|
||||
return (array);
|
||||
}
|
||||
private void saveLastUsed()
|
||||
{
|
||||
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
|
||||
private void saveLastUsed()
|
||||
{
|
||||
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
for (Emoji emoji : _lastUsed.keySet())
|
||||
set.add(String.valueOf(_lastUsed.get(emoji)) + "-" + emoji.name);
|
||||
edit.putStringSet(LAST_USE_PREF, set);
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
for (Emoji emoji : _lastUsed.keySet())
|
||||
set.add(String.valueOf(_lastUsed.get(emoji)) + "-" + emoji.name);
|
||||
edit.putStringSet(LAST_USE_PREF, set);
|
||||
edit.apply();
|
||||
}
|
||||
private void loadLastUsed()
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
Set<String> lastUseSet = prefs.getStringSet(LAST_USE_PREF, null);
|
||||
|
||||
private void loadLastUsed()
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
Set<String> lastUseSet = prefs.getStringSet(LAST_USE_PREF, null);
|
||||
_lastUsed = new HashMap<Emoji, Integer>();
|
||||
if (lastUseSet != null)
|
||||
for (String emojiData : lastUseSet)
|
||||
{
|
||||
String[] data = emojiData.split("-", 2);
|
||||
Emoji emoji;
|
||||
|
||||
_lastUsed = new HashMap<Emoji, Integer>();
|
||||
if (lastUseSet != null)
|
||||
for (String emojiData : lastUseSet)
|
||||
{
|
||||
String[] data = emojiData.split("-", 2);
|
||||
Emoji emoji;
|
||||
if (data.length != 2)
|
||||
continue ;
|
||||
emoji = Emoji.getEmojiByName(data[1]);
|
||||
if (emoji == null)
|
||||
continue ;
|
||||
_lastUsed.put(emoji, Integer.valueOf(data[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if (data.length != 2)
|
||||
continue ;
|
||||
emoji = Emoji.getEmojiByName(data[1]);
|
||||
if (emoji == null)
|
||||
continue ;
|
||||
_lastUsed.put(emoji, Integer.valueOf(data[0]));
|
||||
}
|
||||
}
|
||||
private static class EmojiView extends TextView
|
||||
{
|
||||
public EmojiView(Context context)
|
||||
{
|
||||
super(context);
|
||||
setTextAppearance(context, R.style.emojiGridButton);
|
||||
setGravity(Gravity.CENTER);
|
||||
setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
private static class EmojiView extends TextView
|
||||
{
|
||||
public EmojiView(Keyboard2 context)
|
||||
{
|
||||
super(context);
|
||||
setTextSize(EMOJI_SIZE);
|
||||
setGravity(Gravity.CENTER);
|
||||
setBackgroundColor(0x0);
|
||||
setTextColor(getResources().getColor(R.color.emoji_color));
|
||||
setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
public void setEmoji(Emoji emoji)
|
||||
{
|
||||
setText(emoji.symbol);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEmoji(Emoji emoji)
|
||||
{
|
||||
setText(emoji.symbol);
|
||||
}
|
||||
}
|
||||
private static class EmojiViewAdpater extends BaseAdapter
|
||||
{
|
||||
private Context _context;
|
||||
|
||||
private static class EmojiViewAdpater extends BaseAdapter
|
||||
{
|
||||
private Keyboard2 _main;
|
||||
private Emoji[] _emojiArray;
|
||||
|
||||
private Emoji[] _emojiArray;
|
||||
public EmojiViewAdpater(Context context, Emoji[] emojiArray)
|
||||
{
|
||||
_context = context;
|
||||
_emojiArray = emojiArray;
|
||||
}
|
||||
|
||||
public EmojiViewAdpater(Keyboard2 main, Emoji[] emojiArray)
|
||||
{
|
||||
_main = main;
|
||||
_emojiArray = emojiArray;
|
||||
}
|
||||
public int getCount()
|
||||
{
|
||||
if (_emojiArray == null)
|
||||
return (0);
|
||||
return (_emojiArray.length);
|
||||
}
|
||||
|
||||
public int getCount()
|
||||
{
|
||||
if (_emojiArray == null)
|
||||
return (0);
|
||||
return (_emojiArray.length);
|
||||
}
|
||||
public Object getItem(int pos)
|
||||
{
|
||||
return (_emojiArray[pos]);
|
||||
}
|
||||
|
||||
public Object getItem(int pos)
|
||||
{
|
||||
return (_emojiArray[pos]);
|
||||
}
|
||||
public long getItemId(int pos)
|
||||
{
|
||||
return (pos);
|
||||
}
|
||||
|
||||
public long getItemId(int pos)
|
||||
{
|
||||
return (pos);
|
||||
}
|
||||
public View getView(int pos, View convertView, ViewGroup parent)
|
||||
{
|
||||
EmojiView view = (EmojiView)convertView;
|
||||
|
||||
public View getView(int pos, View convertView, ViewGroup parent)
|
||||
{
|
||||
EmojiView view = (EmojiView)convertView;
|
||||
|
||||
if (view == null)
|
||||
view = new EmojiView(_main);
|
||||
view.setEmoji(_emojiArray[pos]);
|
||||
return (view);
|
||||
}
|
||||
}
|
||||
if (view == null)
|
||||
view = new EmojiView(_context);
|
||||
view.setEmoji(_emojiArray[pos]);
|
||||
return (view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,24 +6,23 @@ import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
public class EmojiKeyButton extends Button
|
||||
implements View.OnClickListener
|
||||
implements View.OnClickListener
|
||||
{
|
||||
KeyValue _key;
|
||||
KeyValue _key;
|
||||
|
||||
public EmojiKeyButton(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
setOnClickListener(this);
|
||||
_key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key"));
|
||||
setText(_key.symbol);
|
||||
if ((_key.flags & KeyValue.FLAG_KEY_FONT) != 0)
|
||||
setTypeface(((Keyboard2)context).getSpecialKeyFont());
|
||||
}
|
||||
public EmojiKeyButton(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
setOnClickListener(this);
|
||||
_key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key"));
|
||||
setText(_key.symbol);
|
||||
if ((_key.flags & KeyValue.FLAG_KEY_FONT) != 0)
|
||||
setTypeface(Theme.getSpecialKeyFont(context));
|
||||
}
|
||||
|
||||
public void onClick(View v)
|
||||
{
|
||||
Keyboard2 main = (Keyboard2)getContext();
|
||||
|
||||
main.handleKeyUp(_key, 0);
|
||||
}
|
||||
public void onClick(View v)
|
||||
{
|
||||
Config config = Config.globalConfig();
|
||||
config.handler.handleKeyUp(_key, 0);
|
||||
}
|
||||
}
|
||||
|
@@ -10,28 +10,28 @@ import android.widget.Button;
|
||||
/* Emoji "types" are groups. This class is misnamed. */
|
||||
|
||||
public class EmojiTypeButton extends Button
|
||||
implements View.OnTouchListener
|
||||
implements View.OnTouchListener
|
||||
{
|
||||
private int _emojiType;
|
||||
private int _emojiType;
|
||||
|
||||
static private final int DEFAULT_GROUP = 0;
|
||||
|
||||
public EmojiTypeButton(Context context, int group_id, String symbol)
|
||||
{
|
||||
super(new ContextThemeWrapper(context, R.style.emojiTypeButton), null, 0);
|
||||
public EmojiTypeButton(Context context, int group_id, String symbol)
|
||||
{
|
||||
super(new ContextThemeWrapper(context, R.style.emojiTypeButton), null, 0);
|
||||
_emojiType = group_id;
|
||||
setText(symbol);
|
||||
setOnTouchListener(this);
|
||||
}
|
||||
setText(symbol);
|
||||
setOnTouchListener(this);
|
||||
}
|
||||
|
||||
public boolean onTouch(View view, MotionEvent event)
|
||||
{
|
||||
EmojiGridView emojiGrid;
|
||||
public boolean onTouch(View view, MotionEvent event)
|
||||
{
|
||||
EmojiGridView emojiGrid;
|
||||
|
||||
if (event.getAction() != MotionEvent.ACTION_DOWN)
|
||||
return (false);
|
||||
emojiGrid = (EmojiGridView)((ViewGroup)(getParent().getParent())).findViewById(R.id.emoji_grid);
|
||||
emojiGrid.setEmojiGroup(_emojiType);
|
||||
return (true);
|
||||
}
|
||||
if (event.getAction() != MotionEvent.ACTION_DOWN)
|
||||
return (false);
|
||||
emojiGrid = (EmojiGridView)((ViewGroup)(getParent().getParent())).findViewById(R.id.emoji_grid);
|
||||
emojiGrid.setEmojiGroup(_emojiType);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
104
srcs/juloo.keyboard2/KeyEventHandler.java
Normal file
@@ -0,0 +1,104 @@
|
||||
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)
|
||||
{
|
||||
if (key == null || (key.flags & KeyValue.FLAG_NOCHAR) != 0)
|
||||
return;
|
||||
switch (key.eventCode)
|
||||
{
|
||||
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return;
|
||||
case KeyValue.EVENT_SWITCH_TEXT: _recv.switchMain(); return;
|
||||
case KeyValue.EVENT_SWITCH_NUMERIC: _recv.switchNumeric(); 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;
|
||||
case KeyValue.EVENT_SWITCH_PROGRAMMING: _recv.switchProgramming(); return;
|
||||
default:
|
||||
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT | KeyValue.FLAG_META)) != 0)
|
||||
handleKeyUpWithModifier(key, flags);
|
||||
else if (key.char_ != KeyValue.CHAR_NONE)
|
||||
_recv.commitChar(key.char_);
|
||||
else if (key.eventCode != KeyValue.EVENT_NONE)
|
||||
handleKeyUpWithModifier(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 int sendMetaKey(int eventCode, int metaFlags, int metaState, boolean down)
|
||||
{
|
||||
int action;
|
||||
int updatedMetaState;
|
||||
if (down) { action = KeyEvent.ACTION_DOWN; updatedMetaState = metaState | metaFlags; }
|
||||
else { action = KeyEvent.ACTION_UP; updatedMetaState = metaState & ~metaFlags; }
|
||||
_recv.sendKeyEvent(action, eventCode, metaState);
|
||||
return updatedMetaState;
|
||||
}
|
||||
|
||||
/* Send key events corresponding to pressed modifier keys. */
|
||||
private int sendMetaKeys(int flags, int metaState, boolean down)
|
||||
{
|
||||
if ((flags & KeyValue.FLAG_CTRL) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_ALT) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_SHIFT) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down);
|
||||
if ((flags & KeyValue.FLAG_META) != 0)
|
||||
metaState = sendMetaKey(KeyEvent.KEYCODE_META_LEFT, KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_ON, metaState, down);
|
||||
return metaState;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't set KeyEvent.FLAG_SOFT_KEYBOARD.
|
||||
*/
|
||||
private void handleKeyUpWithModifier(KeyValue key, int flags)
|
||||
{
|
||||
if (key.eventCode == KeyValue.EVENT_NONE)
|
||||
return ;
|
||||
int metaState = sendMetaKeys(flags, 0, true);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_DOWN, key.eventCode, metaState);
|
||||
_recv.sendKeyEvent(KeyEvent.ACTION_UP, key.eventCode, metaState);
|
||||
sendMetaKeys(flags, metaState, false);
|
||||
}
|
||||
|
||||
public static interface IReceiver
|
||||
{
|
||||
public void switchToNextInputMethod();
|
||||
public void setPane_emoji();
|
||||
public void setPane_normal();
|
||||
public void showKeyboardConfig();
|
||||
public void performAction();
|
||||
|
||||
public void switchMain();
|
||||
public void switchNumeric();
|
||||
public void switchProgramming();
|
||||
|
||||
public void sendKeyEvent(int eventAction, int eventCode, int meta);
|
||||
|
||||
public void commitText(String text);
|
||||
public void commitChar(char c);
|
||||
}
|
||||
}
|
@@ -7,25 +7,29 @@ import java.util.HashMap;
|
||||
|
||||
class KeyModifier
|
||||
{
|
||||
/* Cache key is KeyValue's name */
|
||||
/** Cache key is KeyValue's name */
|
||||
private static HashMap<String, SparseArray<KeyValue>> _cache =
|
||||
new HashMap<String, SparseArray<KeyValue>>();
|
||||
|
||||
/* Modify a key according to modifiers. */
|
||||
/** Represents a removed key, because a cache entry can't be [null]. */
|
||||
private static final KeyValue removed_key = KeyValue.getKeyByName("removed");
|
||||
|
||||
/** Modify a key according to modifiers. */
|
||||
public static KeyValue handleFlags(KeyValue k, int flags)
|
||||
{
|
||||
if (flags == 0) // No modifier
|
||||
return k;
|
||||
if (k == null)
|
||||
return null;
|
||||
SparseArray<KeyValue> ks = cacheEntry(k);
|
||||
KeyValue r = ks.get(flags);
|
||||
if (r != null) // Found in cache
|
||||
return r;
|
||||
r = k;
|
||||
r = handleFn(r, flags);
|
||||
r = handleShift(r, flags);
|
||||
r = handleAccents(r, flags);
|
||||
ks.put(flags, r);
|
||||
return r;
|
||||
if (r == null) // Cold cache
|
||||
{
|
||||
r = k;
|
||||
r = handleFn(r, flags);
|
||||
r = handleShift(r, flags);
|
||||
r = handleAccents(r, flags);
|
||||
ks.put(flags, r);
|
||||
}
|
||||
return (r == removed_key) ? null : r;
|
||||
}
|
||||
|
||||
private static KeyValue handleAccents(KeyValue k, int flags)
|
||||
@@ -45,16 +49,8 @@ class KeyModifier
|
||||
char c = k.char_;
|
||||
if (k.char_ != KeyValue.CHAR_NONE)
|
||||
c = Character.toUpperCase(c);
|
||||
if (c == k.char_) // More rules if toUpperCase() did nothing
|
||||
switch (k.symbol)
|
||||
{
|
||||
case "→": c = '⇒'; break;
|
||||
case "←": c = '⇐'; break;
|
||||
case "<": c = '«'; break;
|
||||
case ">": c = '»'; break;
|
||||
case "“": c = '”'; break;
|
||||
default: return k;
|
||||
}
|
||||
if (c == k.char_) // Used to have more rules if toUpperCase() did nothing
|
||||
return k;
|
||||
return k.withCharAndSymbol(c);
|
||||
}
|
||||
|
||||
@@ -65,42 +61,37 @@ class KeyModifier
|
||||
case KeyValue.FLAG_ACCENT1:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02CB', c);
|
||||
case KeyValue.FLAG_ACCENT2:
|
||||
switch (c)
|
||||
{
|
||||
case '`': return '´';
|
||||
case '<': return '‘';
|
||||
case '>': return '‘';
|
||||
default: return (char)KeyCharacterMap.getDeadChar('\u00B4', c);
|
||||
}
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00B4', c);
|
||||
case KeyValue.FLAG_ACCENT3:
|
||||
switch (c)
|
||||
{
|
||||
case '*': return '°';
|
||||
default: return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
|
||||
}
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
|
||||
case KeyValue.FLAG_ACCENT4:
|
||||
switch (c)
|
||||
{
|
||||
case '?': return '¿';
|
||||
case '!': return '¡';
|
||||
default: return (char)KeyCharacterMap.getDeadChar('\u02DC', c);
|
||||
}
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02DC', c);
|
||||
case KeyValue.FLAG_ACCENT5:
|
||||
switch (c)
|
||||
{
|
||||
case 'u': return 'µ';
|
||||
case '"': return '„';
|
||||
case '\'': return '’';
|
||||
case '-': return '¬';
|
||||
case 'a': return 'æ';
|
||||
case 'o': return 'œ';
|
||||
default: return (char)KeyCharacterMap.getDeadChar('\u00B8', c);
|
||||
}
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00B8', c);
|
||||
case KeyValue.FLAG_ACCENT6:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00A8', c);
|
||||
case KeyValue.FLAG_ACCENT_CARON:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02C7', c);
|
||||
case KeyValue.FLAG_ACCENT_RING:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u02DA', c);
|
||||
case KeyValue.FLAG_ACCENT_MACRON:
|
||||
return (char)KeyCharacterMap.getDeadChar('\u00AF', c);
|
||||
case KeyValue.FLAG_ACCENT_ORDINAL:
|
||||
switch (c)
|
||||
{
|
||||
case '-': return '÷';
|
||||
default: return (char)KeyCharacterMap.getDeadChar('\u00A8', c);
|
||||
case 'a': return 'ª';
|
||||
case 'o': return 'º';
|
||||
case '1': return 'ª';
|
||||
case '2': return 'º';
|
||||
case '3': return 'ⁿ';
|
||||
case '4': return 'ᵈ';
|
||||
case '5': return 'ᵉ';
|
||||
case '6': return 'ʳ';
|
||||
case '7': return 'ˢ';
|
||||
case '8': return 'ᵗ';
|
||||
case '9': return 'ʰ';
|
||||
case '*': return '°';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_SUPERSCRIPT:
|
||||
switch (c)
|
||||
@@ -148,6 +139,74 @@ class KeyModifier
|
||||
case 'o': return 'ₒ';
|
||||
default: return c;
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_ARROWS:
|
||||
if ((flags & KeyValue.FLAG_SHIFT) == 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '↙';
|
||||
case '2': return '↓';
|
||||
case '3': return '↘';
|
||||
case '4': return '←';
|
||||
case '6': return '→';
|
||||
case '7': return '↖';
|
||||
case '8': return '↑';
|
||||
case '9': return '↗';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '⇙';
|
||||
case '2': return '⇓';
|
||||
case '3': return '⇘';
|
||||
case '4': return '⇐';
|
||||
case '6': return '⇒';
|
||||
case '7': return '⇖';
|
||||
case '8': return '⇑';
|
||||
case '9': return '⇗';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
case KeyValue.FLAG_ACCENT_BOX:
|
||||
if ((flags & KeyValue.FLAG_SHIFT) == 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '└';
|
||||
case '2': return '┴';
|
||||
case '3': return '┘';
|
||||
case '4': return '├';
|
||||
case '5': return '┼';
|
||||
case '6': return '┤';
|
||||
case '7': return '┌';
|
||||
case '8': return '┬';
|
||||
case '9': return '┐';
|
||||
case '0': return '─';
|
||||
case '.': return '│';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': return '╚';
|
||||
case '2': return '╩';
|
||||
case '3': return '╝';
|
||||
case '4': return '╠';
|
||||
case '5': return '╬';
|
||||
case '6': return '╣';
|
||||
case '7': return '╔';
|
||||
case '8': return '╦';
|
||||
case '9': return '╗';
|
||||
case '0': return '═';
|
||||
case '.': return '║';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
default: return c; // Can't happen
|
||||
}
|
||||
}
|
||||
@@ -155,7 +214,15 @@ class KeyModifier
|
||||
private static KeyValue handleFn(KeyValue k, int flags)
|
||||
{
|
||||
if ((flags & KeyValue.FLAG_FN) == 0)
|
||||
return k;
|
||||
{
|
||||
switch (k.name)
|
||||
{
|
||||
// Remove some keys when Fn is *not* activated
|
||||
case "f11_placeholder":
|
||||
case "f12_placeholder": return removed_key;
|
||||
default: return k;
|
||||
}
|
||||
}
|
||||
String name;
|
||||
switch (k.name)
|
||||
{
|
||||
@@ -169,16 +236,54 @@ class KeyModifier
|
||||
case "8": name = "f8"; break;
|
||||
case "9": name = "f9"; break;
|
||||
case "0": name = "f10"; break;
|
||||
case "f11_placeholder": name = "f11"; break;
|
||||
case "f12_placeholder": name = "f12"; break;
|
||||
case "up": name = "page_up"; break;
|
||||
case "down": name = "page_down"; break;
|
||||
case "left": name = "home"; break;
|
||||
case "right": name = "end"; break;
|
||||
case ">": name = "→"; break;
|
||||
case "<": name = "←"; break;
|
||||
case "\"": name = "“"; break;
|
||||
case "<": name = "«"; break;
|
||||
case ">": name = "»"; break;
|
||||
case "{": name = "‹"; break;
|
||||
case "}": name = "›"; break;
|
||||
case "[": name = "‘"; break;
|
||||
case "]": name = "’"; break;
|
||||
case "(": name = "“"; break;
|
||||
case ")": name = "”"; break;
|
||||
case "'": name = "‚"; break;
|
||||
case "\"": name = "„"; break;
|
||||
case "-": name = "–"; break;
|
||||
case "_": name = "—"; break;
|
||||
case "^": name = "¬"; break;
|
||||
case "%": name = "‰"; break;
|
||||
case "=": name = "≈"; break;
|
||||
case "u": name = "µ"; break;
|
||||
case "a": name = "æ"; break;
|
||||
case "o": name = "œ"; break;
|
||||
case "esc": name = "insert"; break;
|
||||
case "*": name = "°"; break;
|
||||
case ".": name = "…"; break;
|
||||
case ",": name = "·"; break;
|
||||
case "!": name = "¡"; break;
|
||||
case "?": name = "¿"; break;
|
||||
case "tab": name = "\\t"; break;
|
||||
case "space": name = "nbsp"; break;
|
||||
case "↖": name = "⇖"; break;
|
||||
case "↑": name = "⇑"; break;
|
||||
case "↗": name = "⇗"; break;
|
||||
case "←": name = "⇐"; break;
|
||||
case "→": name = "⇒"; break;
|
||||
case "↙": name = "⇙"; break;
|
||||
case "↓": name = "⇓"; break;
|
||||
case "↘": name = "⇘"; break;
|
||||
// Currency symbols
|
||||
case "e": name = "€"; break;
|
||||
case "l": name = "£"; break;
|
||||
case "r": name = "₹"; break;
|
||||
case "y": name = "¥"; break;
|
||||
case "c": name = "¢"; break;
|
||||
case "p": name = "₱"; break;
|
||||
case "€": case "£": return removed_key; // Avoid showing these twice
|
||||
default: return k;
|
||||
}
|
||||
return KeyValue.getKeyByName(name);
|
||||
|
@@ -6,22 +6,27 @@ import java.util.HashMap;
|
||||
|
||||
class KeyValue
|
||||
{
|
||||
public static final int EVENT_NONE = -1;
|
||||
public static final int EVENT_CONFIG = -2;
|
||||
public static final int EVENT_SWITCH_TEXT = -3;
|
||||
public static final int EVENT_SWITCH_NUMERIC = -4;
|
||||
public static final int EVENT_SWITCH_EMOJI = -5;
|
||||
public static final int EVENT_SWITCH_BACK_EMOJI = -6;
|
||||
public static final int EVENT_CHANGE_METHOD = -7;
|
||||
public static final char CHAR_NONE = '\0';
|
||||
public static final int EVENT_NONE = -1;
|
||||
public static final int EVENT_CONFIG = -2;
|
||||
public static final int EVENT_SWITCH_TEXT = -3;
|
||||
public static final int EVENT_SWITCH_NUMERIC = -4;
|
||||
public static final int EVENT_SWITCH_EMOJI = -5;
|
||||
public static final int EVENT_SWITCH_BACK_EMOJI = -6;
|
||||
public static final int EVENT_CHANGE_METHOD = -7;
|
||||
public static final int EVENT_ACTION = -8;
|
||||
public static final int EVENT_SWITCH_PROGRAMMING = -9;
|
||||
public static final char CHAR_NONE = '\0';
|
||||
|
||||
// Behavior flags
|
||||
public static final int FLAG_KEEP_ON = 1;
|
||||
public static final int FLAG_LATCH = 1;
|
||||
public static final int FLAG_LOCK = (1 << 1);
|
||||
public static final int FLAG_NOREPEAT = (1 << 2);
|
||||
public static final int FLAG_NOCHAR = (1 << 3);
|
||||
public static final int FLAG_PRECISE_REPEAT = (1 << 4);
|
||||
|
||||
// Rendering flags
|
||||
public static final int FLAG_KEY_FONT = (1 << 5);
|
||||
public static final int FLAG_SMALLER_FONT = (1 << 6);
|
||||
|
||||
// Internal flags
|
||||
public static final int FLAG_LOCKED = (1 << 8);
|
||||
@@ -31,6 +36,7 @@ class KeyValue
|
||||
public static final int FLAG_SHIFT = (1 << 11);
|
||||
public static final int FLAG_ALT = (1 << 12);
|
||||
public static final int FLAG_FN = (1 << 13);
|
||||
public static final int FLAG_META = (1 << 14);
|
||||
|
||||
// Accent flags
|
||||
public static final int FLAG_ACCENT1 = (1 << 16); // Grave
|
||||
@@ -41,10 +47,21 @@ class KeyValue
|
||||
public static final int FLAG_ACCENT6 = (1 << 21); // Tréma
|
||||
public static final int FLAG_ACCENT_SUPERSCRIPT = (1 << 22);
|
||||
public static final int FLAG_ACCENT_SUBSCRIPT = (1 << 23);
|
||||
public static final int FLAG_ACCENT_RING = (1 << 24);
|
||||
public static final int FLAG_ACCENT_CARON = (1 << 26);
|
||||
public static final int FLAG_ACCENT_MACRON = (1 << 27);
|
||||
public static final int FLAG_ACCENT_ORDINAL = (1 << 28);
|
||||
public static final int FLAG_ACCENT_ARROWS = (1 << 29);
|
||||
public static final int FLAG_ACCENT_BOX = (1 << 30);
|
||||
|
||||
public static final int FLAGS_ACCENTS = FLAG_ACCENT1 | FLAG_ACCENT2 |
|
||||
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
|
||||
FLAG_ACCENT_SUPERSCRIPT | FLAG_ACCENT_SUBSCRIPT;
|
||||
FLAG_ACCENT_CARON | FLAG_ACCENT_MACRON | FLAG_ACCENT_SUPERSCRIPT |
|
||||
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL | FLAG_ACCENT_ARROWS |
|
||||
FLAG_ACCENT_BOX | FLAG_ACCENT_RING;
|
||||
|
||||
// Language specific keys that are removed from the keyboard by default
|
||||
public static final int FLAG_LOCALIZED = (1 << 25);
|
||||
|
||||
public final String name;
|
||||
public final String symbol;
|
||||
@@ -63,6 +80,16 @@ class KeyValue
|
||||
return new KeyValue(name, s, c, eventCode, flags);
|
||||
}
|
||||
|
||||
public KeyValue withNameAndSymbol(String n, String s)
|
||||
{
|
||||
return new KeyValue(n, s, char_, eventCode, flags);
|
||||
}
|
||||
|
||||
public KeyValue withFlags(int f)
|
||||
{
|
||||
return new KeyValue(name, symbol, char_, eventCode, f);
|
||||
}
|
||||
|
||||
private static HashMap<String, KeyValue> keys = new HashMap<String, KeyValue>();
|
||||
|
||||
public KeyValue(String n, String s, char c, int e, int f)
|
||||
@@ -74,14 +101,15 @@ class KeyValue
|
||||
flags = f;
|
||||
}
|
||||
|
||||
public static KeyValue getKeyByName(String name)
|
||||
public static KeyValue getKeyByName(String name)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
KeyValue kv = KeyValue.keys.get(name);
|
||||
if (kv != null)
|
||||
return kv;
|
||||
return new KeyValue(name, name, CHAR_NONE, EVENT_NONE, 0);
|
||||
char c = (name.length() == 1) ? name.charAt(0) : CHAR_NONE;
|
||||
return new KeyValue(name, name, c, EVENT_NONE, 0);
|
||||
}
|
||||
|
||||
private static void addKey(String name, String symbol, char c, int event, int flags)
|
||||
@@ -89,21 +117,31 @@ class KeyValue
|
||||
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);
|
||||
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)
|
||||
{
|
||||
addKey(name, symbol, CHAR_NONE, EVENT_NONE,
|
||||
FLAG_KEEP_ON | FLAG_NOCHAR | FLAG_NOREPEAT | extra_flags);
|
||||
FLAG_LATCH | FLAG_NOCHAR | FLAG_NOREPEAT | extra_flags);
|
||||
}
|
||||
|
||||
private static void addSpecialKey(String name, String symbol, int event)
|
||||
{
|
||||
addKey(name, symbol, CHAR_NONE, event, FLAG_NOREPEAT);
|
||||
addSpecialKey(name, symbol, event, 0);
|
||||
}
|
||||
|
||||
private static void addSpecialKey(String name, String symbol, int event, int flags)
|
||||
{
|
||||
addKey(name, symbol, CHAR_NONE, event, flags | FLAG_NOREPEAT);
|
||||
}
|
||||
|
||||
private static void addEventKey(String name, String symbol, int event)
|
||||
@@ -118,22 +156,26 @@ class KeyValue
|
||||
|
||||
static
|
||||
{
|
||||
String chars = "<>&\"_°~{|^}$*:!£%µ?.§€";
|
||||
for (int i = 0; i < chars.length(); i++)
|
||||
addCharKey(chars.charAt(i), EVENT_NONE);
|
||||
|
||||
addModifierKey("shift", "⇧", FLAG_LOCK | FLAG_SHIFT);
|
||||
addModifierKey("ctrl", "Ctrl", FLAG_CTRL);
|
||||
addModifierKey("alt", "Alt", FLAG_ALT);
|
||||
addModifierKey("accent_grave", "◌̀", FLAG_ACCENT1);
|
||||
addModifierKey("accent_aigu", "◌́", FLAG_ACCENT2);
|
||||
addModifierKey("accent_circonflexe", "◌̂", FLAG_ACCENT3);
|
||||
addModifierKey("accent_tilde", "◌̃", FLAG_ACCENT4);
|
||||
addModifierKey("accent_cedille", "◌̧", FLAG_ACCENT5);
|
||||
addModifierKey("accent_trema", "◌̈", FLAG_ACCENT6);
|
||||
addModifierKey("superscript", "◌͆", FLAG_ACCENT_SUPERSCRIPT);
|
||||
addModifierKey("subscript", "◌̺", FLAG_ACCENT_SUBSCRIPT);
|
||||
addModifierKey("fn", "Fn", FLAG_FN);
|
||||
addModifierKey("shift", "\n", // Can't write u000A because Java is stupid
|
||||
FLAG_SHIFT | FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("ctrl", "Ctrl", FLAG_CTRL | FLAG_SMALLER_FONT);
|
||||
addModifierKey("alt", "Alt", FLAG_ALT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("accent_aigu", "\u0050", FLAG_ACCENT2 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_caron", "\u0051", FLAG_ACCENT_CARON | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_cedille", "\u0052", FLAG_ACCENT5 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_circonflexe", "\u0053", FLAG_ACCENT3 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_grave", "\u0054", FLAG_ACCENT1 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_macron", "\u0055", FLAG_ACCENT_MACRON | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_ring", "\u0056", FLAG_ACCENT_RING | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_tilde", "\u0057", FLAG_ACCENT4 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("accent_trema", "\u0058", FLAG_ACCENT6 | FLAG_KEY_FONT | FLAG_LOCALIZED);
|
||||
addModifierKey("superscript", "Sup", FLAG_ACCENT_SUPERSCRIPT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("subscript", "Sub", FLAG_ACCENT_SUBSCRIPT | FLAG_SMALLER_FONT);
|
||||
addModifierKey("ordinal", "Ord", FLAG_ACCENT_ORDINAL | FLAG_SMALLER_FONT);
|
||||
addModifierKey("arrows", "Arr", FLAG_ACCENT_ARROWS | FLAG_SMALLER_FONT);
|
||||
addModifierKey("box", "Box", FLAG_ACCENT_BOX | FLAG_SMALLER_FONT);
|
||||
addModifierKey("fn", "Fn", FLAG_FN | FLAG_SMALLER_FONT);
|
||||
addModifierKey("meta", "Meta", FLAG_META | FLAG_SMALLER_FONT);
|
||||
|
||||
addCharKey('a', KeyEvent.KEYCODE_A);
|
||||
addCharKey('b', KeyEvent.KEYCODE_B);
|
||||
@@ -188,27 +230,32 @@ class KeyValue
|
||||
addCharKey('#', KeyEvent.KEYCODE_POUND);
|
||||
addCharKey('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN);
|
||||
addCharKey(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN);
|
||||
addCharKey('ß', EVENT_NONE, FLAG_LOCALIZED);
|
||||
addCharKey('€', EVENT_NONE, FLAG_LOCALIZED);
|
||||
addCharKey('£', EVENT_NONE, FLAG_LOCALIZED);
|
||||
|
||||
addSpecialKey("config", "Conf", EVENT_CONFIG);
|
||||
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT);
|
||||
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC);
|
||||
addSpecialKey("switch_emoji", ":)", EVENT_SWITCH_EMOJI);
|
||||
addSpecialKey("config", "\u0004", EVENT_CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_emoji", "\u0001" , EVENT_SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
|
||||
addSpecialKey("change_method", "⊞", EVENT_CHANGE_METHOD);
|
||||
addSpecialKey("switch_programming", "Prog", EVENT_SWITCH_PROGRAMMING, FLAG_SMALLER_FONT);
|
||||
addSpecialKey("change_method", "\u0009", EVENT_CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
addSpecialKey("action", "Action", EVENT_ACTION, FLAG_SMALLER_FONT); // Will always be replaced
|
||||
|
||||
addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE);
|
||||
addEventKey("enter", "\uE800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
|
||||
addEventKey("up", "\uE80B", KeyEvent.KEYCODE_DPAD_UP, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("right", "\uE80C", KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("down", "\uE809", KeyEvent.KEYCODE_DPAD_DOWN, 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_DOWN);
|
||||
addEventKey("page_down", "⇟", KeyEvent.KEYCODE_PAGE_UP);
|
||||
addEventKey("home", "↖", KeyEvent.KEYCODE_HOME);
|
||||
addEventKey("end", "↗", KeyEvent.KEYCODE_MOVE_END);
|
||||
addEventKey("backspace", "⌫", KeyEvent.KEYCODE_DEL, FLAG_PRECISE_REPEAT);
|
||||
addEventKey("delete", "⌦", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_PRECISE_REPEAT);
|
||||
addEventKey("insert", "Ins", KeyEvent.KEYCODE_INSERT);
|
||||
addEventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
|
||||
addEventKey("enter", "\u000E", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
|
||||
addEventKey("up", "\u0005", KeyEvent.KEYCODE_DPAD_UP, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("right", "\u0006", KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("down", "\u0007", KeyEvent.KEYCODE_DPAD_DOWN, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("left", "\u0008", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
|
||||
addEventKey("page_up", "\u0002", KeyEvent.KEYCODE_PAGE_UP, FLAG_KEY_FONT);
|
||||
addEventKey("page_down", "\u0003", KeyEvent.KEYCODE_PAGE_DOWN, FLAG_KEY_FONT);
|
||||
addEventKey("home", "\u000B", KeyEvent.KEYCODE_MOVE_HOME, FLAG_KEY_FONT);
|
||||
addEventKey("end", "\u000C", KeyEvent.KEYCODE_MOVE_END, FLAG_KEY_FONT);
|
||||
addEventKey("backspace", "\u0011", KeyEvent.KEYCODE_DEL, FLAG_KEY_FONT);
|
||||
addEventKey("delete", "\u0010", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_KEY_FONT);
|
||||
addEventKey("insert", "Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT);
|
||||
addEventKey("f1", "F1", KeyEvent.KEYCODE_F1);
|
||||
addEventKey("f2", "F2", KeyEvent.KEYCODE_F2);
|
||||
addEventKey("f3", "F3", KeyEvent.KEYCODE_F3);
|
||||
@@ -219,8 +266,12 @@ class KeyValue
|
||||
addEventKey("f8", "F8", KeyEvent.KEYCODE_F8);
|
||||
addEventKey("f9", "F9", KeyEvent.KEYCODE_F9);
|
||||
addEventKey("f10", "F10", KeyEvent.KEYCODE_F10);
|
||||
addEventKey("f11", "F11", KeyEvent.KEYCODE_F11, FLAG_SMALLER_FONT);
|
||||
addEventKey("f12", "F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT);
|
||||
addEventKey("tab", "\u000F", KeyEvent.KEYCODE_TAB, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
|
||||
addKey("tab", "↹", '\t', KeyEvent.KEYCODE_TAB, 0);
|
||||
addKey("space", " ", ' ', KeyEvent.KEYCODE_SPACE, 0);
|
||||
addKey("\\t", "\\t", '\t', EVENT_NONE, 0); // Send the tab character
|
||||
addKey("space", "\r", ' ', KeyEvent.KEYCODE_SPACE, FLAG_KEY_FONT);
|
||||
addKey("nbsp", "\u237d", '\u00a0', EVENT_NONE, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
|
||||
}
|
||||
}
|
||||
|
@@ -1,73 +1,60 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Typeface;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.text.InputType;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.InputType;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.util.Log;
|
||||
import java.util.HashMap;
|
||||
import android.util.LogPrinter;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Keyboard2 extends InputMethodService
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener
|
||||
{
|
||||
private Keyboard2View _keyboardView;
|
||||
static private final String TAG = "Keyboard2";
|
||||
|
||||
private Keyboard2View _keyboardView;
|
||||
private int _currentTextLayout;
|
||||
private ViewGroup _emojiPane = null;
|
||||
private Typeface _specialKeyFont = null;
|
||||
private ViewGroup _emojiPane = null;
|
||||
|
||||
private Config _config;
|
||||
private Config _config;
|
||||
|
||||
private Map<Integer, KeyboardData> _layoutCache = new HashMap<Integer, KeyboardData>();
|
||||
private boolean _debug_logs = false;
|
||||
|
||||
private KeyboardData getLayout(int resId)
|
||||
{
|
||||
KeyboardData l = _layoutCache.get(resId);
|
||||
if (l == null)
|
||||
{
|
||||
l = KeyboardData.parse(getResources().getXml(resId));
|
||||
_layoutCache.put(resId, l);
|
||||
}
|
||||
return l;
|
||||
return KeyboardData.load(getResources(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
_specialKeyFont = Typeface.createFromAsset(getAssets(), "fonts/keys.ttf");
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
_config = new Config(this);
|
||||
_keyboardView = (Keyboard2View)getLayoutInflater().inflate(R.layout.keyboard, null);
|
||||
_keyboardView.reset();
|
||||
}
|
||||
|
||||
public Config getConfig()
|
||||
{
|
||||
return (_config);
|
||||
}
|
||||
|
||||
public Typeface getSpecialKeyFont()
|
||||
{
|
||||
return (_specialKeyFont);
|
||||
}
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
Config.initGlobalConfig(this, new KeyEventHandler(this.new Receiver()));
|
||||
_config = Config.globalConfig();
|
||||
_config.refresh(this);
|
||||
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
|
||||
_keyboardView.reset();
|
||||
_debug_logs = getResources().getBoolean(R.bool.debug_logs);
|
||||
}
|
||||
|
||||
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
|
||||
{
|
||||
@@ -80,43 +67,49 @@ public class Keyboard2 extends InputMethodService
|
||||
|
||||
private void refreshSubtypeLayout(InputMethodSubtype subtype)
|
||||
{
|
||||
int l = _config.layout;;
|
||||
int l = _config.layout;
|
||||
if (l == -1)
|
||||
{
|
||||
String s = subtype.getExtraValueOf("default_layout");
|
||||
if (s != null)
|
||||
l = Config.layoutId_of_string(s);
|
||||
else
|
||||
l = R.xml.qwerty;
|
||||
}
|
||||
_currentTextLayout = l;
|
||||
}
|
||||
|
||||
private int accents_of_subtype(InputMethodSubtype subtype)
|
||||
private void extra_keys_of_subtype(Set<String> dst, InputMethodSubtype subtype)
|
||||
{
|
||||
String accents_option = subtype.getExtraValueOf("accents");
|
||||
int flags = 0;
|
||||
if (accents_option != null)
|
||||
for (String acc : accents_option.split("\\|"))
|
||||
flags |= Config.accentFlag_of_name(acc);
|
||||
return flags;
|
||||
String extra_keys = subtype.getExtraValueOf("extra_keys");
|
||||
if (extra_keys == null)
|
||||
return;
|
||||
String[] ks = extra_keys.split("\\|");
|
||||
for (int i = 0; i < ks.length; i++)
|
||||
dst.add(ks[i]);
|
||||
}
|
||||
|
||||
private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype)
|
||||
{
|
||||
final int DONT_REMOVE = KeyValue.FLAG_ACCENT_SUPERSCRIPT | KeyValue.FLAG_ACCENT_SUBSCRIPT;
|
||||
int to_keep = DONT_REMOVE;
|
||||
HashSet<String> extra_keys = new HashSet<String>();
|
||||
List<InputMethodSubtype> enabled_subtypes = getEnabledSubtypes(imm);
|
||||
switch (_config.accents)
|
||||
{
|
||||
case 1:
|
||||
to_keep |= accents_of_subtype(subtype);
|
||||
for (InputMethodSubtype s : getEnabledSubtypes(imm))
|
||||
to_keep |= accents_of_subtype(s);
|
||||
extra_keys_of_subtype(extra_keys, subtype);
|
||||
for (InputMethodSubtype s : enabled_subtypes)
|
||||
extra_keys_of_subtype(extra_keys, s);
|
||||
break;
|
||||
case 2: to_keep |= accents_of_subtype(subtype); break;
|
||||
case 3: to_keep = KeyValue.FLAGS_ACCENTS; break;
|
||||
case 2:
|
||||
extra_keys_of_subtype(extra_keys, subtype);
|
||||
break;
|
||||
case 3: extra_keys = null; break;
|
||||
case 4: break;
|
||||
default: throw new IllegalArgumentException();
|
||||
}
|
||||
_config.accent_flags_to_remove = ~to_keep & KeyValue.FLAGS_ACCENTS;
|
||||
_config.extra_keys = extra_keys;
|
||||
if (enabled_subtypes.size() > 1)
|
||||
_config.shouldOfferSwitchingToNextInputMethod = true;
|
||||
}
|
||||
|
||||
private void refreshSubtypeLegacyFallback()
|
||||
@@ -124,8 +117,8 @@ public class Keyboard2 extends InputMethodService
|
||||
// Fallback for the accents option: Only respect the "None" case
|
||||
switch (_config.accents)
|
||||
{
|
||||
case 1: case 2: case 3: _config.accent_flags_to_remove = 0; break;
|
||||
case 4: _config.accent_flags_to_remove = KeyValue.FLAGS_ACCENTS; break;
|
||||
case 1: case 2: case 3: _config.extra_keys = null; break;
|
||||
case 4: _config.extra_keys = new HashSet<String>(); break;
|
||||
}
|
||||
// Fallback for the layout option: Use qwerty in the "system settings" case
|
||||
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
|
||||
@@ -146,28 +139,94 @@ public class Keyboard2 extends InputMethodService
|
||||
refreshSubtypeLayout(subtype);
|
||||
refreshAccentsOption(imm, subtype);
|
||||
}
|
||||
_config.shouldOfferSwitchingToProgramming =
|
||||
_config.programming_layout != -1 &&
|
||||
_currentTextLayout != _config.programming_layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateInputView()
|
||||
{
|
||||
ViewGroup parent = (ViewGroup)_keyboardView.getParent();
|
||||
private String actionLabel_of_imeAction(int action)
|
||||
{
|
||||
int res;
|
||||
switch (action)
|
||||
{
|
||||
case EditorInfo.IME_ACTION_NEXT: res = R.string.key_action_next; break;
|
||||
case EditorInfo.IME_ACTION_DONE: res = R.string.key_action_done; break;
|
||||
case EditorInfo.IME_ACTION_GO: res = R.string.key_action_go; break;
|
||||
case EditorInfo.IME_ACTION_PREVIOUS: res = R.string.key_action_prev; break;
|
||||
case EditorInfo.IME_ACTION_SEARCH: res = R.string.key_action_search; break;
|
||||
case EditorInfo.IME_ACTION_SEND: res = R.string.key_action_send; break;
|
||||
case EditorInfo.IME_ACTION_UNSPECIFIED:
|
||||
case EditorInfo.IME_ACTION_NONE:
|
||||
default: return null;
|
||||
}
|
||||
return getResources().getString(res);
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
parent.removeView(_keyboardView);
|
||||
return (_keyboardView);
|
||||
}
|
||||
private void refreshEditorInfo(EditorInfo info)
|
||||
{
|
||||
// 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
|
||||
public void onStartInputView(EditorInfo info, boolean restarting)
|
||||
{
|
||||
private void refreshConfig()
|
||||
{
|
||||
int prev_theme = _config.theme;
|
||||
_config.refresh(this);
|
||||
refreshSubtypeImm();
|
||||
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
|
||||
// Refreshing the theme config requires re-creating the views
|
||||
if (prev_theme != _config.theme)
|
||||
{
|
||||
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
|
||||
_emojiPane = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void log_editor_info(EditorInfo info)
|
||||
{
|
||||
LogPrinter p = new LogPrinter(Log.DEBUG, TAG);
|
||||
info.dump(p, "");
|
||||
if (info.extras != null)
|
||||
Log.d(TAG, "extras: "+info.extras.toString());
|
||||
Log.d(TAG, "swapEnterActionKey: "+_config.swapEnterActionKey);
|
||||
Log.d(TAG, "actionLabel: "+_config.actionLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartInputView(EditorInfo info, boolean restarting)
|
||||
{
|
||||
refreshConfig();
|
||||
refreshEditorInfo(info);
|
||||
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
|
||||
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
|
||||
else
|
||||
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
|
||||
_keyboardView.reset(); // Layout might need to change due to rotation
|
||||
}
|
||||
setInputView(_keyboardView);
|
||||
if (_debug_logs)
|
||||
log_editor_info(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputView(View v)
|
||||
{
|
||||
ViewParent parent = v.getParent();
|
||||
if (parent != null && parent instanceof ViewGroup)
|
||||
((ViewGroup)parent).removeView(v);
|
||||
super.setInputView(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype)
|
||||
@@ -183,95 +242,99 @@ public class Keyboard2 extends InputMethodService
|
||||
_keyboardView.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
_config.refresh();
|
||||
refreshSubtypeImm();
|
||||
_keyboardView.refreshConfig(_config, getLayout(_currentTextLayout));
|
||||
}
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
refreshConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig)
|
||||
{
|
||||
_keyboardView.reset();
|
||||
}
|
||||
/** Not static */
|
||||
public class Receiver implements KeyEventHandler.IReceiver
|
||||
{
|
||||
public void switchToNextInputMethod()
|
||||
{
|
||||
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.showInputMethodPicker();
|
||||
// deprecated in version 28: imm.switchToNextInputMethod(getConnectionToken(), false);
|
||||
// added in version 28: switchToNextInputMethod(false);
|
||||
}
|
||||
|
||||
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);
|
||||
imm.switchToNextInputMethod(getConnectionToken(), false);
|
||||
}
|
||||
else if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT)) != 0)
|
||||
handleMetaKeyUp(key, flags);
|
||||
// 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)
|
||||
handleMetaKeyUp(key, flags);
|
||||
else
|
||||
getCurrentInputConnection().commitText(key.symbol, 1);
|
||||
}
|
||||
else
|
||||
sendKeyChar(key.char_);
|
||||
}
|
||||
public void setPane_emoji()
|
||||
{
|
||||
if (_emojiPane == null)
|
||||
_emojiPane = (ViewGroup)inflate_view(R.layout.emoji_pane);
|
||||
setInputView(_emojiPane);
|
||||
}
|
||||
|
||||
// private void handleDelKey(int before, int after)
|
||||
// {
|
||||
// CharSequence selection = getCurrentInputConnection().getSelectedText(0);
|
||||
public void setPane_normal()
|
||||
{
|
||||
setInputView(_keyboardView);
|
||||
}
|
||||
|
||||
// if (selection != null && selection.length() > 0)
|
||||
// getCurrentInputConnection().commitText("", 1);
|
||||
// else
|
||||
// getCurrentInputConnection().deleteSurroundingText(before, after);
|
||||
// }
|
||||
public void performAction()
|
||||
{
|
||||
InputConnection conn = getCurrentInputConnection();
|
||||
if (conn == null)
|
||||
return;
|
||||
conn.performEditorAction(_config.actionId);
|
||||
}
|
||||
|
||||
private void handleMetaKeyUp(KeyValue key, int flags)
|
||||
{
|
||||
int metaState = 0;
|
||||
KeyEvent event;
|
||||
public void switchMain()
|
||||
{
|
||||
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
|
||||
}
|
||||
|
||||
if (key.eventCode == KeyValue.EVENT_NONE)
|
||||
return ;
|
||||
if ((flags & KeyValue.FLAG_CTRL) != 0)
|
||||
metaState |= KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON;
|
||||
if ((flags & KeyValue.FLAG_ALT) != 0)
|
||||
metaState |= KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON;
|
||||
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, 1, metaState);
|
||||
getCurrentInputConnection().sendKeyEvent(event);
|
||||
getCurrentInputConnection().sendKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
|
||||
}
|
||||
public void switchNumeric()
|
||||
{
|
||||
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
|
||||
}
|
||||
|
||||
public void switchProgramming()
|
||||
{
|
||||
if (_config.programming_layout == -1)
|
||||
return;
|
||||
KeyboardData layout =
|
||||
getLayout(_config.programming_layout).replaceKeys(key -> {
|
||||
if (key != null && key.eventCode == KeyValue.EVENT_SWITCH_PROGRAMMING)
|
||||
return KeyValue.getKeyByName("switch_text");
|
||||
return key;
|
||||
});
|
||||
_keyboardView.setKeyboard(layout);
|
||||
}
|
||||
|
||||
public void sendKeyEvent(int eventAction, int eventCode, int meta)
|
||||
{
|
||||
InputConnection conn = getCurrentInputConnection();
|
||||
if (conn == null)
|
||||
return;
|
||||
conn.sendKeyEvent(new KeyEvent(1, 1, eventAction, eventCode, 0, meta));
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return getWindow().getWindow().getAttributes().token;
|
||||
}
|
||||
|
||||
private View inflate_view(int layout)
|
||||
{
|
||||
return View.inflate(new ContextThemeWrapper(this, _config.theme), layout, null);
|
||||
}
|
||||
}
|
||||
|
@@ -1,482 +1,301 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Vibrator;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.PopupWindow;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Keyboard2View extends View
|
||||
implements View.OnTouchListener, Handler.Callback
|
||||
implements View.OnTouchListener, Pointers.IPointerEventHandler
|
||||
{
|
||||
private static final long VIBRATE_MIN_INTERVAL = 100;
|
||||
private static final long VIBRATE_MIN_INTERVAL = 100;
|
||||
|
||||
private KeyboardData _keyboard;
|
||||
private KeyboardData _keyboard;
|
||||
|
||||
private ArrayList<KeyDown> _downKeys = new ArrayList<KeyDown>();
|
||||
private Pointers _pointers;
|
||||
|
||||
private int _flags = 0;
|
||||
private int _flags = 0;
|
||||
|
||||
private Vibrator _vibratorService;
|
||||
private long _lastVibration = 0;
|
||||
private Vibrator _vibratorService;
|
||||
private long _lastVibration = 0;
|
||||
|
||||
private Handler _handler;
|
||||
private static int _currentWhat = 0;
|
||||
private static int _currentWhat = 0;
|
||||
|
||||
private Config _config;
|
||||
private Config _config;
|
||||
|
||||
private float _keyWidth;
|
||||
private float _keyWidth;
|
||||
|
||||
private Paint _keyBgPaint = new Paint();
|
||||
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 Theme _theme;
|
||||
|
||||
private static RectF _tmpRect = new RectF();
|
||||
private static RectF _tmpRect = new RectF();
|
||||
|
||||
public Keyboard2View(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
_handler = new Handler(this);
|
||||
refreshConfig(((Keyboard2)context).getConfig(), null);
|
||||
setOnTouchListener(this);
|
||||
}
|
||||
|
||||
/* Internally calls [reset()]. */
|
||||
public void refreshConfig(Config config, KeyboardData kw)
|
||||
enum Vertical
|
||||
{
|
||||
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)
|
||||
setKeyboard(kw); // handle layout options then calls reset().
|
||||
TOP,
|
||||
CENTER,
|
||||
BOTTOM
|
||||
}
|
||||
|
||||
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 Keyboard2View(Context context, AttributeSet attrs)
|
||||
{
|
||||
if (!_config.shouldOfferSwitchingToNextInputMethod)
|
||||
kw = kw.removeKeys(new KeyboardData.RemoveKeysByEvent(KeyValue.EVENT_CHANGE_METHOD));
|
||||
if (_config.accent_flags_to_remove != 0)
|
||||
kw = kw.removeKeys(new KeyboardData.RemoveKeysByFlags(_config.accent_flags_to_remove));
|
||||
_keyboard = kw;
|
||||
super(context, attrs);
|
||||
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
_theme = new Theme(getContext(), attrs);
|
||||
_config = Config.globalConfig();
|
||||
_pointers = new Pointers(this, _config);
|
||||
setOnTouchListener(this);
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_flags = 0;
|
||||
_downKeys.clear();
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event)
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float keyW;
|
||||
int p;
|
||||
|
||||
switch (event.getActionMasked())
|
||||
{
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
onTouchUp(event.getPointerId(event.getActionIndex()));
|
||||
break ;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
p = event.getActionIndex();
|
||||
onTouchDown(event.getX(p), event.getY(p), event.getPointerId(p));
|
||||
break ;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
for (p = 0; p < event.getPointerCount(); p++)
|
||||
onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
|
||||
break ;
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
private KeyDown getKeyDown(int pointerId)
|
||||
{
|
||||
for (KeyDown k : _downKeys)
|
||||
{
|
||||
if (k.pointerId == pointerId)
|
||||
return (k);
|
||||
}
|
||||
return (null);
|
||||
}
|
||||
|
||||
private KeyDown getKeyDown(KeyboardData.Key key)
|
||||
{
|
||||
for (KeyDown k : _downKeys)
|
||||
{
|
||||
if (k.key == key)
|
||||
return (k);
|
||||
}
|
||||
return (null);
|
||||
}
|
||||
|
||||
private KeyDown getKeyDown(KeyValue kv)
|
||||
{
|
||||
for (KeyDown k : _downKeys)
|
||||
{
|
||||
if (k.value == kv)
|
||||
return (k);
|
||||
}
|
||||
return (null);
|
||||
}
|
||||
|
||||
private void onTouchMove(float moveX, float moveY, int pointerId)
|
||||
{
|
||||
KeyDown key = getKeyDown(pointerId);
|
||||
KeyValue newValue;
|
||||
|
||||
if (key != null)
|
||||
{
|
||||
moveX -= key.downX;
|
||||
moveY -= key.downY;
|
||||
float absDist = Math.abs(moveX) + Math.abs(moveY);
|
||||
key.ptrDist = absDist;
|
||||
if (absDist < _config.subValueDist)
|
||||
newValue = key.key.key0;
|
||||
else if (moveX < 0)
|
||||
newValue = (moveY < 0) ? key.key.key1 : key.key.key3;
|
||||
else if (moveY < 0)
|
||||
newValue = key.key.key2;
|
||||
else
|
||||
newValue = key.key.key4;
|
||||
if (newValue != null && newValue != key.value)
|
||||
{
|
||||
if (key.timeoutWhat != -1)
|
||||
{
|
||||
_handler.removeMessages(key.timeoutWhat);
|
||||
if ((newValue.flags & KeyValue.FLAG_NOREPEAT) == 0)
|
||||
_handler.sendEmptyMessageDelayed(key.timeoutWhat, _config.longPressTimeout);
|
||||
}
|
||||
key.value = newValue;
|
||||
key.flags = newValue.flags;
|
||||
updateFlags();
|
||||
invalidate();
|
||||
handleKeyDown(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onTouchDown(float touchX, float touchY, int pointerId)
|
||||
{
|
||||
float y = _config.marginTop - _config.keyHeight;
|
||||
for (KeyboardData.Row row : _keyboard.rows)
|
||||
{
|
||||
y += _config.keyHeight;
|
||||
if (touchY < y || touchY >= (y + _config.keyHeight))
|
||||
continue ;
|
||||
float x = _config.horizontalMargin;
|
||||
for (KeyboardData.Key key : row.keys)
|
||||
{
|
||||
x += key.shift * _keyWidth;
|
||||
float keyW = _keyWidth * key.width;
|
||||
if (touchX >= x && touchX < (x + keyW))
|
||||
{
|
||||
int what = _currentWhat++;
|
||||
if (key.key0 != null && (key.key0.flags & KeyValue.FLAG_NOREPEAT) == 0)
|
||||
_handler.sendEmptyMessageDelayed(what, _config.longPressTimeout);
|
||||
_downKeys.add(new KeyDown(pointerId, key, touchX, touchY, what));
|
||||
handleKeyDown(key.key0);
|
||||
updateFlags();
|
||||
invalidate();
|
||||
return ;
|
||||
}
|
||||
x += keyW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether a key is already activated (key down but pointer up)
|
||||
private KeyDown getActivatedKey(KeyValue kv)
|
||||
public void setKeyboard(KeyboardData kw)
|
||||
{
|
||||
for (KeyDown k : _downKeys)
|
||||
{
|
||||
if (k.value == kv && k.pointerId == -1)
|
||||
return (k);
|
||||
}
|
||||
return (null);
|
||||
_keyboard = _config.modify_layout(kw);
|
||||
reset();
|
||||
}
|
||||
|
||||
private void onTouchUp(int pointerId)
|
||||
{
|
||||
KeyDown k = getKeyDown(pointerId);
|
||||
public void reset()
|
||||
{
|
||||
_flags = 0;
|
||||
_pointers.clear();
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
if (k != null)
|
||||
{
|
||||
// Stop key repeat
|
||||
if (k.timeoutWhat != -1)
|
||||
public KeyValue onPointerDown(KeyValue k)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
invalidate();
|
||||
if (k != null)
|
||||
vibrate();
|
||||
return k;
|
||||
}
|
||||
|
||||
public KeyValue onPointerSwipe(KeyValue k)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
invalidate();
|
||||
if (k != null)
|
||||
vibrate();
|
||||
return k;
|
||||
}
|
||||
|
||||
public void onPointerUp(KeyValue k)
|
||||
{
|
||||
_config.handler.handleKeyUp(k, _flags);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void onPointerHold(KeyValue k)
|
||||
{
|
||||
_config.handler.handleKeyUp(k, _flags);
|
||||
}
|
||||
|
||||
public void onPointerFlagsChanged()
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void updateFlags()
|
||||
{
|
||||
_flags = _pointers.getFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event)
|
||||
{
|
||||
int p;
|
||||
switch (event.getActionMasked())
|
||||
{
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
_pointers.onTouchUp(event.getPointerId(event.getActionIndex()));
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
p = event.getActionIndex();
|
||||
float tx = event.getX(p);
|
||||
float ty = event.getY(p);
|
||||
KeyboardData.Key key = getKeyAtPosition(tx, ty);
|
||||
if (key != null)
|
||||
_pointers.onTouchDown(tx, ty, event.getPointerId(p), key);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
for (p = 0; p < event.getPointerCount(); p++)
|
||||
_pointers.onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
_pointers.onTouchCancel(event.getPointerId(event.getActionIndex()));
|
||||
break;
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
private KeyboardData.Row getRowAtPosition(float ty)
|
||||
{
|
||||
float y = _config.marginTop;
|
||||
if (ty < y)
|
||||
return null;
|
||||
for (KeyboardData.Row row : _keyboard.rows)
|
||||
{
|
||||
y += (row.shift + row.height) * _config.keyHeight;
|
||||
if (ty < y)
|
||||
return row;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private KeyboardData.Key getKeyAtPosition(float tx, float ty)
|
||||
{
|
||||
KeyboardData.Row row = getRowAtPosition(ty);
|
||||
float x = _config.horizontalMargin;
|
||||
if (row == null || tx < x)
|
||||
return null;
|
||||
for (KeyboardData.Key key : row.keys)
|
||||
{
|
||||
x += (key.shift + key.width) * _keyWidth;
|
||||
if (tx < x)
|
||||
return key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void vibrate()
|
||||
{
|
||||
if (!_config.vibrateEnabled)
|
||||
return ;
|
||||
long now = System.currentTimeMillis();
|
||||
if ((now - _lastVibration) > VIBRATE_MIN_INTERVAL)
|
||||
{
|
||||
_lastVibration = now;
|
||||
try
|
||||
{
|
||||
_handler.removeMessages(k.timeoutWhat);
|
||||
k.timeoutWhat = -1;
|
||||
_vibratorService.vibrate(_config.vibrateDuration);
|
||||
}
|
||||
KeyDown k_on = getActivatedKey(k.value);
|
||||
if (k_on != null)
|
||||
catch (Exception e)
|
||||
{
|
||||
_downKeys.remove(k); // Remove dupplicate
|
||||
// Same key with FLAG_LOCK is already on, do lock
|
||||
if ((k_on.flags & KeyValue.FLAG_LOCK) != 0)
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasure(int wSpec, int hSpec)
|
||||
{
|
||||
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
|
||||
int width = dm.widthPixels;
|
||||
int height =
|
||||
(int)(_config.keyHeight * _keyboard.keysHeight
|
||||
+ _keyboard.rows.size()
|
||||
+ _config.marginTop + _config.marginBottom);
|
||||
setMeasuredDimension(width, height);
|
||||
_keyWidth = (width - (_config.horizontalMargin * 2)) / _keyboard.keysWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
updateFlags();
|
||||
float y = _config.marginTop + _config.keyVerticalInterval / 2;
|
||||
for (KeyboardData.Row row : _keyboard.rows)
|
||||
{
|
||||
y += row.shift * _config.keyHeight;
|
||||
float x = _config.horizontalMargin + _config.keyHorizontalInterval / 2;
|
||||
float keyH = row.height * _config.keyHeight - _config.keyVerticalInterval;
|
||||
for (KeyboardData.Key k : row.keys)
|
||||
{
|
||||
x += k.shift * _keyWidth;
|
||||
float keyW = _keyWidth * k.width - _config.keyHorizontalInterval;
|
||||
boolean isKeyDown = _pointers.isKeyDown(k);
|
||||
_tmpRect.set(x, y, x + keyW, y + keyH);
|
||||
canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius,
|
||||
isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint);
|
||||
drawLabel(canvas, k.key0, keyW / 2f + x, y, keyH, isKeyDown);
|
||||
if (k.edgekeys)
|
||||
{
|
||||
k_on.flags ^= KeyValue.FLAG_LOCK; // Next time, disable it
|
||||
k_on.flags |= KeyValue.FLAG_LOCKED;
|
||||
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.TOP, isKeyDown);
|
||||
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.CENTER, isKeyDown);
|
||||
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
|
||||
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
|
||||
}
|
||||
// Otherwise, toggle it
|
||||
else
|
||||
{
|
||||
_downKeys.remove(k_on);
|
||||
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.TOP, isKeyDown);
|
||||
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown);
|
||||
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
|
||||
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
|
||||
}
|
||||
x += _keyWidth * k.width;
|
||||
}
|
||||
// Key stay activated
|
||||
else if ((k.flags & KeyValue.FLAG_KEEP_ON) != 0)
|
||||
{
|
||||
k.pointerId = -1; // Set pointer up
|
||||
}
|
||||
else // Regular key up
|
||||
{
|
||||
for (int i = 0; i < _downKeys.size(); i++)
|
||||
{
|
||||
KeyDown downKey = _downKeys.get(i);
|
||||
// Disable other activated keys that aren't locked
|
||||
if (downKey.pointerId == -1 && (downKey.flags & KeyValue.FLAG_LOCKED) == 0)
|
||||
_downKeys.remove(i--);
|
||||
// Other keys currently down won't stay activated
|
||||
else if ((downKey.flags & KeyValue.FLAG_KEEP_ON) != 0)
|
||||
downKey.flags ^= KeyValue.FLAG_KEEP_ON;
|
||||
}
|
||||
_downKeys.remove(k);
|
||||
handleKeyUp(k);
|
||||
}
|
||||
updateFlags();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
y += row.height * _config.keyHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleKeyUp(KeyDown key)
|
||||
{
|
||||
if (key.value != null && (key.flags & (KeyValue.FLAG_LOCKED | KeyValue.FLAG_NOCHAR)) == 0)
|
||||
((Keyboard2)getContext()).handleKeyUp(key.value, _flags);
|
||||
}
|
||||
|
||||
private void handleKeyDown(KeyValue key)
|
||||
{
|
||||
if (key == null)
|
||||
return ;
|
||||
vibrate();
|
||||
}
|
||||
|
||||
private void updateFlags()
|
||||
{
|
||||
_flags = 0;
|
||||
for (KeyDown k : _downKeys)
|
||||
_flags |= k.flags;
|
||||
}
|
||||
|
||||
private void vibrate()
|
||||
{
|
||||
if (!_config.vibrateEnabled)
|
||||
return ;
|
||||
long now = System.currentTimeMillis();
|
||||
if ((now - _lastVibration) > VIBRATE_MIN_INTERVAL)
|
||||
{
|
||||
_lastVibration = now;
|
||||
try
|
||||
{
|
||||
_vibratorService.vibrate(_config.vibrateDuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg)
|
||||
{
|
||||
for (KeyDown key : _downKeys)
|
||||
{
|
||||
if (key.timeoutWhat == msg.what)
|
||||
{
|
||||
long nextInterval = _config.longPressInterval;
|
||||
if (_config.preciseRepeat && (key.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
|
||||
{
|
||||
// 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)));
|
||||
nextInterval = (long)((float)nextInterval / accel);
|
||||
}
|
||||
_handler.sendEmptyMessageDelayed(msg.what, nextInterval);
|
||||
((Keyboard2)getContext()).handleKeyUp(key.value, _flags);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasure(int wSpec, int hSpec)
|
||||
{
|
||||
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
|
||||
int height;
|
||||
height = (int)(_config.keyHeight * _keyboard.keysHeight
|
||||
+ _keyboard.rows.size() * _config.keyVerticalInterval
|
||||
+ _config.marginTop + _config.marginBottom);
|
||||
setMeasuredDimension(dm.widthPixels, height);
|
||||
_keyWidth = (getWidth() - (_config.horizontalMargin * 2)) / _keyboard.keysWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
float y = _config.marginTop;
|
||||
for (KeyboardData.Row row : _keyboard.rows)
|
||||
{
|
||||
y += row.shift * _config.keyHeight;
|
||||
float x = _config.horizontalMargin;
|
||||
float keyH = row.height * _config.keyHeight;
|
||||
for (KeyboardData.Key k : row.keys)
|
||||
{
|
||||
x += k.shift * _keyWidth + _config.keyHorizontalInterval;
|
||||
float keyW = _keyWidth * k.width - _config.keyHorizontalInterval;
|
||||
KeyDown keyDown = getKeyDown(k);
|
||||
_tmpRect.set(x, y, x + keyW, y + keyH);
|
||||
if (keyDown != null)
|
||||
canvas.drawRect(_tmpRect, _keyDownBgPaint);
|
||||
else
|
||||
canvas.drawRoundRect(_tmpRect, _config.keyRound, _config.keyRound, _keyBgPaint);
|
||||
if (k.key0 != null)
|
||||
drawLabel(canvas, k.key0, keyW / 2f + x, (keyH + _labelTextSize) / 2f + y, keyDown);
|
||||
float subPadding = _config.keyPadding;
|
||||
if (k.key1 != null)
|
||||
drawSubLabel(canvas, k.key1, x + subPadding, y + subPadding, false, true, keyDown);
|
||||
if (k.key3 != null)
|
||||
drawSubLabel(canvas, k.key3, x + subPadding, y + keyH - subPadding, false, false, keyDown);
|
||||
if (k.key2 != null)
|
||||
drawSubLabel(canvas, k.key2, x + keyW - subPadding, y + subPadding, true, true, keyDown);
|
||||
if (k.key4 != null)
|
||||
drawSubLabel(canvas, k.key4, x + keyW - subPadding, y + keyH - subPadding, true, false, keyDown);
|
||||
x += keyW;
|
||||
}
|
||||
y += keyH + _config.keyVerticalInterval;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow()
|
||||
{
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
private int labelColor(KeyValue k, KeyDown hasKeyDown, int defaultColor)
|
||||
@Override
|
||||
public void onDetachedFromWindow()
|
||||
{
|
||||
if (hasKeyDown != null)
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
private int labelColor(KeyValue k, boolean isKeyDown, int defaultColor)
|
||||
{
|
||||
if (isKeyDown && (k.flags & KeyValue.FLAG_LATCH) != 0)
|
||||
{
|
||||
KeyDown kd = getKeyDown(k);
|
||||
if (kd != null)
|
||||
int flags = _pointers.getKeyFlags(k);
|
||||
if (flags != -1)
|
||||
{
|
||||
if ((kd.flags & KeyValue.FLAG_LOCKED) != 0)
|
||||
return _lockedColor;
|
||||
if (kd.pointerId == -1)
|
||||
return _activatedColor;
|
||||
if ((flags & KeyValue.FLAG_LOCKED) != 0)
|
||||
return _theme.lockedColor;
|
||||
if ((flags & KeyValue.FLAG_LATCH) == 0)
|
||||
return _theme.activatedColor;
|
||||
}
|
||||
}
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, KeyDown keyDown)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
Paint p = ((k.flags & KeyValue.FLAG_KEY_FONT) != 0) ? _specialKeyLabelPaint : _keyLabelPaint;
|
||||
p.setColor(labelColor(k, keyDown, _labelColor));
|
||||
p.setTextSize(_labelTextSize * scaleTextSize(k));
|
||||
canvas.drawText(k.symbol, x, y, p);
|
||||
}
|
||||
|
||||
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, boolean right, boolean up, KeyDown keyDown)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
Paint p = ((k.flags & KeyValue.FLAG_KEY_FONT) != 0) ? _specialKeySubLabelPaint : _keySubLabelPaint;
|
||||
p.setColor(labelColor(k, keyDown, _subLabelColor));
|
||||
p.setTextAlign(right ? Paint.Align.RIGHT : Paint.Align.LEFT);
|
||||
p.setTextSize(_sublabelTextSize * scaleTextSize(k));
|
||||
y -= up ? p.ascent() : p.descent();
|
||||
canvas.drawText(k.symbol, x, y, p);
|
||||
}
|
||||
|
||||
private float scaleTextSize(KeyValue k)
|
||||
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown)
|
||||
{
|
||||
return (k.symbol.length() < 2) ? 1.f : 0.8f;
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
if (k == null)
|
||||
return;
|
||||
float textSize = scaleTextSize(k, _config.labelTextSize, keyH);
|
||||
Paint p = _theme.labelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0));
|
||||
p.setColor(labelColor(k, isKeyDown, _theme.labelColor));
|
||||
p.setTextSize(textSize);
|
||||
canvas.drawText(k.symbol, x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
|
||||
}
|
||||
|
||||
private static class KeyDown
|
||||
{
|
||||
/* -1 if pointer is up. */
|
||||
public int pointerId;
|
||||
public KeyValue value;
|
||||
public KeyboardData.Key key;
|
||||
public float downX;
|
||||
public float downY;
|
||||
/* Manhattan distance of the pointer to the center of the key */
|
||||
public float ptrDist;
|
||||
public int flags;
|
||||
public int timeoutWhat;
|
||||
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, float keyW, float keyH, Paint.Align a, Vertical v, boolean isKeyDown)
|
||||
{
|
||||
k = KeyModifier.handleFlags(k, _flags);
|
||||
if (k == null)
|
||||
return;
|
||||
float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH);
|
||||
Paint p = _theme.subLabelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0), a);
|
||||
p.setColor(labelColor(k, isKeyDown, _theme.subLabelColor));
|
||||
p.setTextSize(textSize);
|
||||
float subPadding = _config.keyPadding;
|
||||
if (v == Vertical.CENTER)
|
||||
y += (keyH - p.ascent() - p.descent()) / 2f;
|
||||
else
|
||||
y += (v == Vertical.TOP) ? subPadding - p.ascent() : keyH - subPadding - p.descent();
|
||||
if (a == Paint.Align.CENTER)
|
||||
x += keyW / 2f;
|
||||
else
|
||||
x += (a == Paint.Align.LEFT) ? subPadding : keyW - subPadding;
|
||||
canvas.drawText(k.symbol, x, y, p);
|
||||
}
|
||||
|
||||
public KeyDown(int pointerId, KeyboardData.Key key, float x, float y, int what)
|
||||
{
|
||||
this.pointerId = pointerId;
|
||||
value = key.key0;
|
||||
this.key = key;
|
||||
downX = x;
|
||||
downY = y;
|
||||
ptrDist = 0.f;
|
||||
flags = (value == null) ? 0 : value.flags;
|
||||
timeoutWhat = what;
|
||||
}
|
||||
}
|
||||
private float scaleTextSize(KeyValue k, float rel_size, float keyH)
|
||||
{
|
||||
float smaller_font = ((k.flags & KeyValue.FLAG_SMALLER_FONT) == 0) ? 1.f : 0.75f;
|
||||
return keyH * rel_size * smaller_font * _config.characterSize;
|
||||
}
|
||||
}
|
||||
|
@@ -1,81 +1,102 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
class KeyboardData
|
||||
{
|
||||
public final List<Row> rows;
|
||||
public final List<Row> rows;
|
||||
/* Total width of the keyboard. Unit is abstract. */
|
||||
public final float keysWidth;
|
||||
/* Total height of the keyboard. Unit is abstract. */
|
||||
public final float keysHeight;
|
||||
|
||||
public KeyboardData(List<Row> rows_)
|
||||
public KeyboardData replaceKeys(MapKeys f)
|
||||
{
|
||||
ArrayList<Row> rows_ = new ArrayList<Row>();
|
||||
for (Row r : rows)
|
||||
rows_.add(r.replaceKeys(f));
|
||||
return new KeyboardData(rows_, keysWidth);
|
||||
}
|
||||
|
||||
private static Row _bottomRow = null;
|
||||
private static Map<Integer, KeyboardData> _layoutCache = new HashMap<Integer, KeyboardData>();
|
||||
|
||||
public static KeyboardData load(Resources res, int id)
|
||||
{
|
||||
KeyboardData l = _layoutCache.get(id);
|
||||
if (l == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_bottomRow == null)
|
||||
_bottomRow = parse_bottom_row(res.getXml(R.xml.bottom_row));
|
||||
l = parse_keyboard(res.getXml(id));
|
||||
_layoutCache.put(id, l);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
private static KeyboardData parse_keyboard(XmlResourceParser parser) throws Exception
|
||||
{
|
||||
if (!expect_tag(parser, "keyboard"))
|
||||
throw new Exception("Empty layout file");
|
||||
boolean bottom_row = parser.getAttributeBooleanValue(null, "bottom_row", true);
|
||||
ArrayList<Row> rows = new ArrayList<Row>();
|
||||
while (expect_tag(parser, "row"))
|
||||
rows.add(Row.parse(parser));
|
||||
float kw = compute_max_width(rows);
|
||||
if (bottom_row)
|
||||
rows.add(_bottomRow.updateWidth(kw));
|
||||
return new KeyboardData(rows, kw);
|
||||
}
|
||||
|
||||
private static float compute_max_width(List<Row> rows)
|
||||
{
|
||||
float w = 0.f;
|
||||
for (Row r : rows)
|
||||
w = Math.max(w, r.keysWidth);
|
||||
return w;
|
||||
}
|
||||
|
||||
private static Row parse_bottom_row(XmlResourceParser parser) throws Exception
|
||||
{
|
||||
if (!expect_tag(parser, "row"))
|
||||
throw new Exception("Failed to parse bottom row");
|
||||
return Row.parse(parser);
|
||||
}
|
||||
|
||||
protected KeyboardData(List<Row> rows_, float kw)
|
||||
{
|
||||
float kw = 0.f;
|
||||
float kh = 0.f;
|
||||
for (Row r : rows_)
|
||||
{
|
||||
kw = Math.max(kw, r.keysWidth);
|
||||
kh += r.height + r.shift;
|
||||
}
|
||||
rows = rows_;
|
||||
keysWidth = kw;
|
||||
keysHeight = kh;
|
||||
}
|
||||
|
||||
public static KeyboardData parse(XmlResourceParser parser)
|
||||
{
|
||||
ArrayList<Row> rows = new ArrayList<Row>();
|
||||
|
||||
try
|
||||
{
|
||||
int status;
|
||||
|
||||
while (parser.next() != XmlResourceParser.START_TAG)
|
||||
continue ;
|
||||
if (!parser.getName().equals("keyboard"))
|
||||
throw new Exception("Unknow tag: " + parser.getName());
|
||||
while ((status = parser.next()) != XmlResourceParser.END_DOCUMENT)
|
||||
{
|
||||
if (status == XmlResourceParser.START_TAG)
|
||||
{
|
||||
String tag = parser.getName();
|
||||
if (tag.equals("row"))
|
||||
rows.add(Row.parse(parser));
|
||||
else
|
||||
throw new Exception("Unknow keyboard tag: " + tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new KeyboardData(rows);
|
||||
}
|
||||
|
||||
public KeyboardData removeKeys(MapKeys f)
|
||||
public static class Row
|
||||
{
|
||||
ArrayList<Row> rows_ = new ArrayList<Row>();
|
||||
for (Row r : rows)
|
||||
rows_.add(r.removeKeys(f));
|
||||
return new KeyboardData(rows_);
|
||||
}
|
||||
|
||||
public static class Row
|
||||
{
|
||||
public final List<Key> keys;
|
||||
/* Height of the row. Unit is abstract. */
|
||||
/* Height of the row, without 'shift'. Unit is abstract. */
|
||||
public final float height;
|
||||
/* Extra empty space on the top. */
|
||||
public final float shift;
|
||||
/* Total width of very keys. Unit is abstract. */
|
||||
private final float keysWidth;
|
||||
/* Total width of the row. Unit is abstract. */
|
||||
private final float keysWidth;
|
||||
|
||||
public Row(List<Key> keys_, float h, float s)
|
||||
protected Row(List<Key> keys_, float h, float s)
|
||||
{
|
||||
float kw = 0.f;
|
||||
for (Key k : keys_) kw += k.width + k.shift;
|
||||
@@ -85,34 +106,35 @@ class KeyboardData
|
||||
keysWidth = kw;
|
||||
}
|
||||
|
||||
public static Row parse(XmlResourceParser parser) throws Exception
|
||||
{
|
||||
public static Row parse(XmlResourceParser parser) throws Exception
|
||||
{
|
||||
ArrayList<Key> keys = new ArrayList<Key>();
|
||||
int status;
|
||||
int status;
|
||||
float h = parser.getAttributeFloatValue(null, "height", 1f);
|
||||
float shift = parser.getAttributeFloatValue(null, "shift", 0f);
|
||||
while ((status = parser.next()) != XmlResourceParser.END_TAG)
|
||||
{
|
||||
if (status == XmlResourceParser.START_TAG)
|
||||
{
|
||||
String tag = parser.getName();
|
||||
if (tag.equals("key"))
|
||||
keys.add(Key.parse(parser));
|
||||
else
|
||||
throw new Exception("Unknow row tag: " + tag);
|
||||
}
|
||||
}
|
||||
while (expect_tag(parser, "key"))
|
||||
keys.add(Key.parse(parser));
|
||||
return new Row(keys, h, shift);
|
||||
}
|
||||
}
|
||||
|
||||
public Row removeKeys(MapKeys f)
|
||||
public Row replaceKeys(MapKeys f)
|
||||
{
|
||||
ArrayList<Key> keys_ = new ArrayList<Key>();
|
||||
for (Key k : keys)
|
||||
keys_.add(k.removeKeys(f));
|
||||
keys_.add(k.replaceKeys(f));
|
||||
return new Row(keys_, height, shift);
|
||||
}
|
||||
}
|
||||
|
||||
/** Change the width of every keys so that the row is 's' units wide. */
|
||||
public Row updateWidth(float newWidth)
|
||||
{
|
||||
float s = newWidth / keysWidth;
|
||||
ArrayList<Key> keys_ = new ArrayList<Key>();
|
||||
for (Key k : keys)
|
||||
keys_.add(k.scaleWidth(s));
|
||||
return new Row(keys_, height, shift);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Key
|
||||
{
|
||||
@@ -131,8 +153,10 @@ class KeyboardData
|
||||
public final float width;
|
||||
/* Extra empty space on the left of the key. */
|
||||
public final float shift;
|
||||
/* Put keys 1 to 4 on the edges instead of the corners. */
|
||||
public final boolean edgekeys;
|
||||
|
||||
public Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s)
|
||||
protected Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e)
|
||||
{
|
||||
key0 = k0;
|
||||
key1 = k1;
|
||||
@@ -141,6 +165,7 @@ class KeyboardData
|
||||
key4 = k4;
|
||||
width = w;
|
||||
shift = s;
|
||||
edgekeys = e;
|
||||
}
|
||||
|
||||
public static Key parse(XmlResourceParser parser) throws Exception
|
||||
@@ -152,43 +177,54 @@ class KeyboardData
|
||||
KeyValue k4 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key4"));
|
||||
float width = parser.getAttributeFloatValue(null, "width", 1f);
|
||||
float shift = parser.getAttributeFloatValue(null, "shift", 0.f);
|
||||
boolean edgekeys = parser.getAttributeBooleanValue(null, "edgekeys", false);
|
||||
while (parser.next() != XmlResourceParser.END_TAG)
|
||||
continue ;
|
||||
return new Key(k0, k1, k2, k3, k4, width, shift);
|
||||
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
|
||||
}
|
||||
|
||||
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.apply(key0), f.apply(key1), f.apply(key2),
|
||||
f.apply(key3), f.apply(key4), width, shift, edgekeys);
|
||||
}
|
||||
|
||||
/** New key with the width multiplied by 's'. */
|
||||
public Key scaleWidth(float s)
|
||||
{
|
||||
return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys);
|
||||
}
|
||||
|
||||
public KeyValue getValue(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 1: return key1;
|
||||
case 2: return key2;
|
||||
case 3: return key3;
|
||||
case 4: return key4;
|
||||
default: case 0: return key0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract interface MapKeys
|
||||
public static abstract interface MapKeys extends Function<KeyValue, KeyValue> { }
|
||||
|
||||
/** Parsing utils */
|
||||
|
||||
/** Returns [false] on [END_DOCUMENT] or [END_TAG], [true] otherwise. */
|
||||
private static boolean expect_tag(XmlResourceParser parser, String name) throws Exception
|
||||
{
|
||||
public abstract KeyValue map(KeyValue k);
|
||||
}
|
||||
|
||||
public static class RemoveKeysByFlags implements MapKeys
|
||||
{
|
||||
private final int _flags;
|
||||
|
||||
public RemoveKeysByFlags(int flags) { _flags = flags; }
|
||||
|
||||
public KeyValue map(KeyValue k)
|
||||
int status;
|
||||
do
|
||||
{
|
||||
return (k == null || (k.flags & _flags) != 0) ? null : k;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RemoveKeysByEvent implements MapKeys
|
||||
{
|
||||
private final int _eventCode;
|
||||
|
||||
public RemoveKeysByEvent(int ev) { _eventCode = ev; }
|
||||
|
||||
public KeyValue map(KeyValue k)
|
||||
{
|
||||
return (k == null || k.eventCode == _eventCode) ? null : k;
|
||||
status = parser.next();
|
||||
if (status == XmlResourceParser.END_DOCUMENT || status == XmlResourceParser.END_TAG)
|
||||
return false;
|
||||
}
|
||||
while (status != XmlResourceParser.START_TAG);
|
||||
if (!parser.getName().equals(name))
|
||||
throw new Exception("Unknow tag: " + parser.getName());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
333
srcs/juloo.keyboard2/Pointers.java
Normal file
@@ -0,0 +1,333 @@
|
||||
package juloo.keyboard2;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Manage pointers (fingers) on the screen and long presses.
|
||||
* Call back to IPointerEventHandler.
|
||||
*/
|
||||
public final class Pointers implements Handler.Callback
|
||||
{
|
||||
private Handler _keyrepeat_handler;
|
||||
private ArrayList<Pointer> _ptrs = new ArrayList<Pointer>();
|
||||
private IPointerEventHandler _handler;
|
||||
private Config _config;
|
||||
|
||||
public Pointers(IPointerEventHandler h, Config c)
|
||||
{
|
||||
_keyrepeat_handler = new Handler(this);
|
||||
_handler = h;
|
||||
_config = c;
|
||||
}
|
||||
|
||||
public int getFlags()
|
||||
{
|
||||
int flags = 0;
|
||||
for (Pointer p : _ptrs)
|
||||
flags |= p.flags;
|
||||
return flags;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
_ptrs.clear();
|
||||
}
|
||||
|
||||
public boolean isKeyDown(KeyboardData.Key k)
|
||||
{
|
||||
for (Pointer p : _ptrs)
|
||||
if (p.key == k)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* These flags can be different:
|
||||
* FLAG_LOCK Removed when the key is locked
|
||||
* FLAG_LOCKED Added when the key is locked
|
||||
* FLAG_LATCH Removed when the key is latched (released but not consumed yet)
|
||||
* Returns [-1] if not found.
|
||||
*/
|
||||
public int getKeyFlags(KeyValue kv)
|
||||
{
|
||||
// Use physical equality because the key might have been modified.
|
||||
String name = kv.name;
|
||||
for (Pointer p : _ptrs)
|
||||
if (p.value != null && p.value.name == name)
|
||||
return p.flags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Receiving events
|
||||
|
||||
public void onTouchUp(int pointerId)
|
||||
{
|
||||
Pointer ptr = getPtr(pointerId);
|
||||
if (ptr == null)
|
||||
return;
|
||||
stopKeyRepeat(ptr);
|
||||
Pointer latched = getLatched(ptr);
|
||||
if (latched != null) // Already latched
|
||||
{
|
||||
removePtr(ptr); // Remove dupplicate
|
||||
if ((latched.flags & KeyValue.FLAG_LOCK) != 0) // Locking key, toggle lock
|
||||
{
|
||||
latched.flags = (latched.flags & ~KeyValue.FLAG_LOCK) | KeyValue.FLAG_LOCKED;
|
||||
_handler.onPointerFlagsChanged();
|
||||
}
|
||||
else // Otherwise, unlatch
|
||||
{
|
||||
removePtr(latched);
|
||||
_handler.onPointerUp(ptr.value);
|
||||
}
|
||||
}
|
||||
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
|
||||
{
|
||||
ptr.flags &= ~KeyValue.FLAG_LATCH;
|
||||
ptr.pointerId = -1; // Latch
|
||||
_handler.onPointerFlagsChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
clearLatched();
|
||||
removePtr(ptr);
|
||||
_handler.onPointerUp(ptr.value);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchCancel(int pointerId)
|
||||
{
|
||||
Pointer ptr = getPtr(pointerId);
|
||||
if (ptr == null)
|
||||
return;
|
||||
stopKeyRepeat(ptr);
|
||||
removePtr(ptr);
|
||||
_handler.onPointerFlagsChanged();
|
||||
}
|
||||
|
||||
public void onTouchDown(float x, float y, int pointerId, KeyboardData.Key key)
|
||||
{
|
||||
// Ignore new presses while a modulated key is active. On some devices,
|
||||
// ghost touch events can happen while the pointer travels on top of other
|
||||
// keys.
|
||||
if (isModulatedKeyPressed())
|
||||
return;
|
||||
KeyValue value = _handler.onPointerDown(key.key0);
|
||||
Pointer ptr = new Pointer(pointerId, key, 0, value, x, y);
|
||||
_ptrs.add(ptr);
|
||||
if (value != null && (value.flags & KeyValue.FLAG_NOREPEAT) == 0)
|
||||
startKeyRepeat(ptr);
|
||||
}
|
||||
|
||||
public void onTouchMove(float x, float y, int pointerId)
|
||||
{
|
||||
Pointer ptr = getPtr(pointerId);
|
||||
if (ptr == null)
|
||||
return;
|
||||
float dx = x - ptr.downX;
|
||||
float dy = y - ptr.downY;
|
||||
float dist = Math.abs(dx) + Math.abs(dy);
|
||||
ptr.ptrDist = dist;
|
||||
int newIndex;
|
||||
if (dist < _config.swipe_dist_px)
|
||||
{
|
||||
newIndex = 0;
|
||||
}
|
||||
else if (ptr.key.edgekeys)
|
||||
{
|
||||
if (Math.abs(dy) > Math.abs(dx)) // vertical swipe
|
||||
newIndex = (dy < 0) ? 1 : 4;
|
||||
else // horizontal swipe
|
||||
newIndex = (dx < 0) ? 3 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dx < 0) // left side
|
||||
newIndex = (dy < 0) ? 1 : 3;
|
||||
else // right side
|
||||
newIndex = (dy < 0) ? 2 : 4;
|
||||
}
|
||||
if (newIndex != ptr.value_index)
|
||||
{
|
||||
ptr.value_index = newIndex;
|
||||
KeyValue newValue = _handler.onPointerSwipe(ptr.key.getValue(newIndex));
|
||||
if (newValue != null)
|
||||
{
|
||||
int old_flags = ptr.flags;
|
||||
ptr.value = newValue;
|
||||
ptr.flags = newValue.flags;
|
||||
// Keep the keyrepeat going between modulated keys.
|
||||
if ((old_flags & newValue.flags & KeyValue.FLAG_PRECISE_REPEAT) == 0)
|
||||
{
|
||||
stopKeyRepeat(ptr);
|
||||
if ((newValue.flags & KeyValue.FLAG_NOREPEAT) == 0)
|
||||
startKeyRepeat(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pointers management
|
||||
|
||||
private Pointer getPtr(int pointerId)
|
||||
{
|
||||
for (Pointer p : _ptrs)
|
||||
if (p.pointerId == pointerId)
|
||||
return p;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void removePtr(Pointer ptr)
|
||||
{
|
||||
_ptrs.remove(ptr);
|
||||
}
|
||||
|
||||
private Pointer getLatched(Pointer target)
|
||||
{
|
||||
KeyboardData.Key k = target.key;
|
||||
int vi = target.value_index;
|
||||
for (Pointer p : _ptrs)
|
||||
if (p.key == k && p.value_index == vi && p.pointerId == -1)
|
||||
return p;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void clearLatched()
|
||||
{
|
||||
for (int i = _ptrs.size() - 1; i >= 0; i--)
|
||||
{
|
||||
Pointer ptr = _ptrs.get(i);
|
||||
// Latched and not locked, remove
|
||||
if (ptr.pointerId == -1 && (ptr.flags & KeyValue.FLAG_LOCKED) == 0)
|
||||
_ptrs.remove(i);
|
||||
// Not latched but pressed, don't latch once released
|
||||
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
|
||||
ptr.flags &= ~KeyValue.FLAG_LATCH;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isModulatedKeyPressed()
|
||||
{
|
||||
for (Pointer ptr : _ptrs)
|
||||
{
|
||||
if ((ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Key repeat
|
||||
|
||||
/** Message from [_keyrepeat_handler]. */
|
||||
@Override
|
||||
public boolean handleMessage(Message msg)
|
||||
{
|
||||
for (Pointer ptr : _ptrs)
|
||||
{
|
||||
if (ptr.timeoutWhat == msg.what)
|
||||
{
|
||||
long nextInterval = _config.longPressInterval;
|
||||
if (_config.preciseRepeat && (ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
|
||||
{
|
||||
// Slower repeat for modulated keys
|
||||
nextInterval *= 2;
|
||||
// Modulate repeat interval depending on the distance of the pointer
|
||||
nextInterval = (long)((float)nextInterval / modulatePreciseRepeat(ptr));
|
||||
}
|
||||
_keyrepeat_handler.sendEmptyMessageDelayed(msg.what, nextInterval);
|
||||
_handler.onPointerHold(ptr.value);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
private static int uniqueTimeoutWhat = 0;
|
||||
|
||||
private void startKeyRepeat(Pointer ptr)
|
||||
{
|
||||
int what = (uniqueTimeoutWhat++);
|
||||
ptr.timeoutWhat = what;
|
||||
long timeout = _config.longPressTimeout;
|
||||
// Faster repeat timeout for modulated keys
|
||||
if ((ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
|
||||
timeout /= 2;
|
||||
_keyrepeat_handler.sendEmptyMessageDelayed(what, timeout);
|
||||
}
|
||||
|
||||
private void stopKeyRepeat(Pointer ptr)
|
||||
{
|
||||
if (ptr.timeoutWhat != -1)
|
||||
{
|
||||
_keyrepeat_handler.removeMessages(ptr.timeoutWhat);
|
||||
ptr.timeoutWhat = -1;
|
||||
ptr.repeatingPtrDist = -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
private float modulatePreciseRepeat(Pointer ptr)
|
||||
{
|
||||
if (ptr.repeatingPtrDist < 0.f)
|
||||
ptr.repeatingPtrDist = ptr.ptrDist; // First repeat
|
||||
if (ptr.ptrDist > ptr.repeatingPtrDist * 2.f)
|
||||
ptr.repeatingPtrDist = ptr.ptrDist / 2.f; // Large swipe, move the middle point
|
||||
float left = ptr.repeatingPtrDist / 2.f;
|
||||
float accel = (ptr.ptrDist - left) / (ptr.repeatingPtrDist - left);
|
||||
return Math.min(8.f, Math.max(0.1f, accel));
|
||||
}
|
||||
|
||||
private final class Pointer
|
||||
{
|
||||
/** -1 when latched. */
|
||||
public int pointerId;
|
||||
public final KeyboardData.Key key;
|
||||
public int value_index;
|
||||
/** Modified value. Not equal to [key.getValue(value_index)]. */
|
||||
public KeyValue value;
|
||||
public float downX;
|
||||
public float downY;
|
||||
/** Distance of the pointer to the initial press. */
|
||||
public float ptrDist;
|
||||
public int flags;
|
||||
/** Identify timeout messages. */
|
||||
public int timeoutWhat;
|
||||
/** ptrDist at the first repeat, -1 otherwise. */
|
||||
public float repeatingPtrDist;
|
||||
|
||||
public Pointer(int p, KeyboardData.Key k, int vi, KeyValue v, float x, float y)
|
||||
{
|
||||
pointerId = p;
|
||||
key = k;
|
||||
value_index = vi;
|
||||
value = v;
|
||||
downX = x;
|
||||
downY = y;
|
||||
ptrDist = 0.f;
|
||||
flags = (v == null) ? 0 : v.flags;
|
||||
timeoutWhat = -1;
|
||||
repeatingPtrDist = -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPointerEventHandler
|
||||
{
|
||||
/** A key is pressed. Key can be modified or removed by returning [null].
|
||||
[getFlags()] is not uptodate. */
|
||||
public KeyValue onPointerDown(KeyValue k);
|
||||
|
||||
/** Pointer swipes into a corner. Key can be modified or removed. */
|
||||
public KeyValue onPointerSwipe(KeyValue k);
|
||||
|
||||
/** Key is released. [k] is the key that was returned by [onPointerDown] or
|
||||
[onPointerSwipe]. */
|
||||
public void onPointerUp(KeyValue k);
|
||||
|
||||
/** Flags changed because latched or locked keys or cancelled pointers. */
|
||||
public void onPointerFlagsChanged();
|
||||
|
||||
/** Key is repeating. */
|
||||
public void onPointerHold(KeyValue k);
|
||||
}
|
||||
}
|
@@ -5,10 +5,10 @@ import android.preference.PreferenceActivity;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
}
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
}
|
||||
}
|
||||
|
77
srcs/juloo.keyboard2/Theme.java
Normal file
@@ -0,0 +1,77 @@
|
||||
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 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();
|
||||
_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, Paint.Align align)
|
||||
{
|
||||
Paint p = special_font ? _specialKeySubLabelPaint : _keySubLabelPaint;
|
||||
p.setTextAlign(align);
|
||||
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(), "special_font.ttf");
|
||||
}
|
||||
return _specialKeyFont;
|
||||
}
|
||||
}
|
7
srcs/special_font/01.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- IcoMoon-Free 227-smile2 CC BY 4.0 -->
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#000000" d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM11 4c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM5 4c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM8 13c-1.82 0-3.413-0.973-4.288-2.427l1.286-0.772c0.612 1.018 1.727 1.699 3.002 1.699s2.389-0.681 3.002-1.699l1.286 0.772c-0.874 1.454-2.467 2.427-4.288 2.427z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 742 B |
16
srcs/special_font/02.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- IcoMoon-Free 327-move-up CC BY 4.0 -->
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#000000" d="M11 8v6h1v-6h2.5l-3-3-3 3z"></path>
|
||||
<path fill="#000000" d="M1 3h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M3 3h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M5 3h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M1 6.5h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M2.5 7h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M4.5 7h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M1 4.5h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M5 5h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M5 11v3h-3v-3h3zM6 10h-5v5h5v-5z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 921 B |
16
srcs/special_font/03.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- IcoMoon-Free 328-move-down CC BY 4.0 -->
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#000000" d="M12 11v-6h-1v6h-2.5l3 3 3-3z"></path>
|
||||
<path fill="#000000" d="M5 4v3h-3v-3h3zM6 3h-5v5h5v-5z"></path>
|
||||
<path fill="#000000" d="M1 10h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M3 10h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M5 10h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M1 13.5h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M2.5 14h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M4.5 14h1.5v1h-1.5v-1z"></path>
|
||||
<path fill="#000000" d="M1 11.5h1v1.5h-1v-1.5z"></path>
|
||||
<path fill="#000000" d="M5 12h1v1.5h-1v-1.5z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 931 B |
1
srcs/special_font/04.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M495.9 166.6C499.2 175.2 496.4 184.9 489.6 191.2L446.3 230.6C447.4 238.9 448 247.4 448 256C448 264.6 447.4 273.1 446.3 281.4L489.6 320.8C496.4 327.1 499.2 336.8 495.9 345.4C491.5 357.3 486.2 368.8 480.2 379.7L475.5 387.8C468.9 398.8 461.5 409.2 453.4 419.1C447.4 426.2 437.7 428.7 428.9 425.9L373.2 408.1C359.8 418.4 344.1 427 329.2 433.6L316.7 490.7C314.7 499.7 307.7 506.1 298.5 508.5C284.7 510.8 270.5 512 255.1 512C241.5 512 227.3 510.8 213.5 508.5C204.3 506.1 197.3 499.7 195.3 490.7L182.8 433.6C167 427 152.2 418.4 138.8 408.1L83.14 425.9C74.3 428.7 64.55 426.2 58.63 419.1C50.52 409.2 43.12 398.8 36.52 387.8L31.84 379.7C25.77 368.8 20.49 357.3 16.06 345.4C12.82 336.8 15.55 327.1 22.41 320.8L65.67 281.4C64.57 273.1 64 264.6 64 256C64 247.4 64.57 238.9 65.67 230.6L22.41 191.2C15.55 184.9 12.82 175.3 16.06 166.6C20.49 154.7 25.78 143.2 31.84 132.3L36.51 124.2C43.12 113.2 50.52 102.8 58.63 92.95C64.55 85.8 74.3 83.32 83.14 86.14L138.8 103.9C152.2 93.56 167 84.96 182.8 78.43L195.3 21.33C197.3 12.25 204.3 5.04 213.5 3.51C227.3 1.201 241.5 0 256 0C270.5 0 284.7 1.201 298.5 3.51C307.7 5.04 314.7 12.25 316.7 21.33L329.2 78.43C344.1 84.96 359.8 93.56 373.2 103.9L428.9 86.14C437.7 83.32 447.4 85.8 453.4 92.95C461.5 102.8 468.9 113.2 475.5 124.2L480.2 132.3C486.2 143.2 491.5 154.7 495.9 166.6V166.6zM256 336C300.2 336 336 300.2 336 255.1C336 211.8 300.2 175.1 256 175.1C211.8 175.1 176 211.8 176 255.1C176 300.2 211.8 336 256 336z"/></svg>
|
After Width: | Height: | Size: 1.7 KiB |
3
srcs/special_font/05.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- materialdesignicons.com arrow-up-bold -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M15,20H9V12H4.16L12,4.16L19.84,12H15V20Z" /></svg>
|
After Width: | Height: | Size: 384 B |
3
srcs/special_font/06.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- materialdesignicons.com arrow-right-bold -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,15V9H12V4.16L19.84,12L12,19.84V15H4Z" /></svg>
|
After Width: | Height: | Size: 386 B |
3
srcs/special_font/07.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- materialdesignicons.com arrow-down-bold -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M9,4H15V12H19.84L12,19.84L4.16,12H9V4Z" /></svg>
|
After Width: | Height: | Size: 384 B |
3
srcs/special_font/08.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- materialdesignicons.com arrow-left-bold -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M20,9V15H12V19.84L4.16,12L12,4.16V9H20Z" /></svg>
|
After Width: | Height: | Size: 385 B |
6
srcs/special_font/09.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="16" viewBox="0 0 18 16">
|
||||
<path fill="#000000" d="M17 2h-16c-0.55 0-1 0.45-1 1v10c0 0.55 0.45 1 1 1h16c0.55 0 1-0.45 1-1v-10c0-0.55-0.45-1-1-1zM10 4h2v2h-2v-2zM13 7v2h-2v-2h2zM7 4h2v2h-2v-2zM10 7v2h-2v-2h2zM4 4h2v2h-2v-2zM7 7v2h-2v-2h2zM2 4h1v2h-1v-2zM2 7h2v2h-2v-2zM3 12h-1v-2h1v2zM12 12h-8v-2h8v2zM16 12h-3v-2h3v2zM16 9h-2v-2h2v2zM16 6h-3v-2h3v2z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 651 B |