Compare commits

..

105 Commits

Author SHA1 Message Date
Jules Aguillon
167c63ee25 Release 1.18.0 2022-10-16 22:42:14 +02:00
Jules Aguillon
f56b926857 Autocapitalisation: Avoid trigerring when Ctrl+Del
Autocapitalisation could trigger while repeatedly typing Ctrl+Del to
remove several words.
2022-10-16 22:34:21 +02:00
Jules Aguillon
75df3afda6 Allow to disable Alt and Meta keys
The keys are marked "loc" in the layouts and are handled like the other
extra keys.
The only difference is that they are enabled by default (for now).
2022-10-16 01:07:24 +02:00
Rapha
7fb5c992b6 Rename resulting CI artifact (#180)
* Rename resulting CI artifact
Add details to the name of the artifact, to distiguish downloads of it between multiple branches while testing

* Update CI to nodejs16 and improve artifact naming
2022-10-16 00:53:04 +02:00
Jules Aguillon
158a3577be Disable fullscreen mode
This mode is annoying to some users and is disabled in most text views.

The keyboard has a fixed sized relative to the height of the screen in
landscape mode. The keyboard can't take more space than expected,
currently.

This might cause problems in the future and might be hidden behind an
option if one is found. Every text views so far seemed to behave fine.
2022-10-16 00:42:28 +02:00
Jules Aguillon
138e59f13a Fix literal tab key
Broken since 31d6a70d.
2022-10-16 00:04:06 +02:00
Jules Aguillon
db347c665c Add the breve diacritic 2022-10-15 23:28:36 +02:00
lpv
8be80eecd4 Basic greek layout. (#207)
* Basic greek layout.
2022-10-15 23:22:19 +02:00
Jules Aguillon
d9a8688237 Fix crash due to auto capitalisation
It is unclear how _autocap.started is not called first but nothing is
preventing to initialize things earlier.
2022-10-15 16:19:27 +02:00
Jules Aguillon
7f51cf001a Mention long press in lockable modifiers option
More documentation about this feature would be appropriate.
2022-10-15 15:55:48 +02:00
Raj9039852537
1909f2fcb4 Added Hindi language layout (#211)
* Hindi Keyboard Layout

Hindi keyboard layout added
Basic symbols like brackets, colons etc are useful. This includes ( ) { } [ ] \ / ÷ - + = ! % : ; . , ?
2022-10-11 22:13:40 +02:00
Jules Aguillon
fc8bb3a539 Allow to type İ on the Turkish layout
In Turkish, upper case of 'iı' is 'İI' but Java's toUpperCase will
return 'II'.
To make 'İ' accessible, make it the shift of 'ı'. This has the
inconvenient of swapping i and ı on the keyboard.
2022-10-04 10:12:22 +02:00
Jules Aguillon
dda8f0314d Contributing: clarify layouts 2022-10-04 10:12:22 +02:00
polyctena
5873b7315d German translation (#208)
Co-authored-by: Benjamin <f.weiss@stud.uni-goettingen.de>
2022-10-04 09:56:15 +02:00
Jules Aguillon
64e263a1af Fix an unexplained crash encountered in the wild
For some reason, 'subtype' can be null. Perhaps because the keyboard is
started before the IMM is ready.
2022-09-24 23:34:50 +02:00
Jules Aguillon
90b9b0e399 Release 1.17.0 2022-09-24 23:07:02 +02:00
Validbit
5169472dfc Added Czech translation and layout (#198)
* Added Czech translation and layout

Translated keyboard and created Czech multilingual "practical" layout for faster typing and typing in commonly used languages (German, Slovak + French w/accents)

* Update (Rephrase) full_description.txt

... to better suit the language and naturally promote keyboard's features and possibilities to a wider audience.
2022-09-24 22:44:10 +02:00
Jules Aguillon
3081af5190 Improve the auto capitalisation
- Detect when the input box is cleared
- Avoid looking up keys on the keyboard every time the shift state needs
  to change.
2022-09-24 22:36:06 +02:00
Jules Aguillon
c778b4e8a2 Fix autocapitalisation randomly not triggered
The autocapitalisation is asking the editor about whether to enable
shift and must make sure to ask after the editor is done processing the
events.
2022-09-24 18:53:37 +02:00
Quantenzitrone
65210fb14f Bone keyboard layout (#155) 2022-09-24 16:17:10 +02:00
Jules Aguillon
d8882c87ae Add support for Polish 2022-09-24 16:08:24 +02:00
Jules Aguillon
2fc40512c6 Add switch_greekmath to the extra keys
The Fn+switch_numeric shortcut might be hard to discover or too slow for
heavy users.

A location is allocated for the key so it has a consistent placement.
2022-09-24 16:02:54 +02:00
Jules Aguillon
5811643562 Add more possible locations for extra keys
Avoid dropping some keys on crowded layouts.
2022-09-24 16:02:54 +02:00
Piotrek Marciniak
a365fdc6a3 Add white e-ink oriented theme (#193)
* Add white e-ing oriented theme

Co-authored-by: Jules Aguillon <jules@j3s.fr>
2022-09-24 13:13:51 +02:00
Edgars
9fc1565065 Add missing Latvian translations (#203) 2022-09-24 11:45:24 +02:00
ChristianGynnild
b0a2298899 Added Norwegian keyboard layout (#202) 2022-09-24 11:44:01 +02:00
Md Rasel Hossain
81f07b427f Bengali Keyboard Layout (#201)
* Bangla Layout
2022-09-24 11:40:10 +02:00
Jules Aguillon
0b388b93c7 Add translations for Russian
Co-authored-by: @94KONG
2022-09-24 11:31:25 +02:00
Jules Aguillon
25a6e71ee8 Add the Extra Keys option
Allows to add more keys to the keyboard from a predefined list.
The implementation doesn't use MultiSelectListPreference because it
doesn't seem possible to change the item layout to properly show the
rendered symbols.
2022-09-19 11:41:18 +02:00
castix
617f0878bc italian translation 2022-09-03 17:33:35 +02:00
igorSilCar
773194ca4a Brazilian portuguese translations (#187)
* Translations for new setting, lockable modifier keys

Co-authored-by: Igor da Silva de Carvalho <igu@coiso.meanhouse>
2022-09-03 12:06:47 +02:00
Jules Aguillon
bc8bcce82a Fix crash when auto-capitalisation runs too soon
This is unexpected but happens once.
2022-07-30 18:19:28 +02:00
Jules Aguillon
4f5ce66347 Fix auto-capitalisation interfering with caps lock
Add a flag to recognize fake pointers and avoid clearing the
intentionally locked shift key.
2022-07-30 18:14:05 +02:00
Jules Aguillon
85d798299e Standard auto-capitalisation only after space
Change the capitalisation algorithm to use Android's
'getCursorCapsMode'. This requires a bit of cursor calculations but
should feel more standard.

The auto completion only triggers after a space is typed or backspace is
pressed.
2022-07-30 17:56:31 +02:00
Jules Aguillon
dec0a7471b Option "Lockable modifiers" is deprecated
Mark that it is planned to be removed, remove corresponding translations.
2022-07-24 23:57:32 +02:00
Jules Aguillon
53b9afa973 Hold any modifier to lock
Modifiers can be locked with a long press. The key repeat mechanism is re-used
and the press timeout is the same.
Every modifiers can be locked that way, not only the "lockable" ones.

The previous behavior can be enabled in the settings (for shift only)
but the default is changed.
2022-07-24 23:55:00 +02:00
Jules Aguillon
081e9a6e53 Add an option to control auto capitalisation 2022-07-24 23:44:37 +02:00
Jules Aguillon
bfde31da6e Avoid automatic capitalisation when using arrows
Disable capitalisation just after an arrow kind is pressed to avoid
interrupting navigation.
2022-07-24 23:32:14 +02:00
Jules Aguillon
324756535e Automatic capitalisation at beginning of sentences
Keep track of end-of-sentence characters while typing and automatically
enable shift when appropriate.

The last few characters just before the cursor need to be queried in
some cases: Begin of input, cursor has moved or text is deleted.
This might have a performance cost.

This normally only enable shift but it also needs to disable shift when
the cursor moves.
2022-07-24 20:02:48 +02:00
Jules Aguillon
2d8ed2d858 Add missing ascii characters to the Hungarian layouts
Was missing '~' and '$'.
2022-07-09 17:55:58 +02:00
Jules Aguillon
929b30f723 Add '#' to the numeric pane
On the bottom-left of the '*' key.
2022-07-09 17:50:13 +02:00
quantenzitrone
3033091f9d Add alternative greek and math symbols 2022-07-09 17:40:20 +02:00
Quantenzitrone
fdd640ef09 added uppercase ẞ of ß 2022-07-09 17:35:17 +02:00
Jules Aguillon
13a13ecbb6 Switch to greekmath with Fn+switch_numeric
Add a shortcut to switch to the greekmath pane directly from the main
layout.
2022-07-09 17:31:44 +02:00
Jules Aguillon
d5836ebb97 Add key for switching to the greekmath pane
The key is placed on the 3rd row of the numeric pane, by taking some
space from the shift key.
2022-07-09 17:30:26 +02:00
quantenzitrone
db8ebc2f4d Add the greekmath pane
The greek and math symbols from the Bone keyboard layout.
2022-07-09 17:27:23 +02:00
Andrew Cat
1d406e948f Add ukrainian layout (#172) 2022-07-03 23:07:06 +02:00
Jules Aguillon
1ddd089166 Compatibility with API level < 24
The Math.floorMod method was added on API level 24.
2022-07-03 22:59:05 +02:00
Jules Aguillon
1951448f9e Release 1.16.1 2022-06-24 22:11:53 +02:00
Jules Aguillon
ff01678ba6 Revert "Remove the vibration settings"
Bring back the "Vibration" option.

The duration option isn't added back because the vibration settings are
still handled by Android. In fact, the option has no effect if the
vibration are disabled in the system settings.

This partially reverts commit ef03dfed5c.
2022-06-24 22:00:23 +02:00
Jules Aguillon
d74e8f3b08 Fix F12 being turned into F11
The "f11_placeholder" and "f12_placeholder" keys were equals since
31d6a70.

Add an incrementing id into the unused key value to differentiate
placeholder values.
2022-06-24 20:56:04 +02:00
Jules Aguillon
ab987c776c Fix localized key not in predefined position
The "loc " prefix for predefining a place for an "extra key" was broken
since 31d6a70.

The FLAG_LOCALIZED flag cannot be used anymore, as adding it to any key
would turn it into a different key that wouldn't be recognized by parts
of the code comparing the keys (placing the extra keys).

Add an other layer in KeyboardData to store such informations.
2022-06-24 20:26:27 +02:00
Thunder-Squirrel
6e5be63e25 Move 'ъ' where it belongs and increase the width of the keys (#160) 2022-06-19 23:04:06 +02:00
Jules Aguillon
402bf4990e Remove the interval between vibrations
This is no longer necessary since repeating key no longer cause a
vibration.
2022-06-06 20:40:53 +02:00
Jules Aguillon
fda53e3952 Release 1.16.0 2022-06-06 20:23:09 +02:00
Jules Aguillon
ef03dfed5c Remove the vibration settings
Instead of using the vibrator directly, use performHapticFeedback, which
will integrate better with the system settings.
2022-06-06 17:04:50 +02:00
Jules Aguillon
e0131fa6b0 Fix inconsistent text size in landscape mode
Dimens weren't refreshed when the orientation changed. Dimens are not
the right solution anyway, use scaling factors instead.
2022-06-06 16:17:43 +02:00
Jules Aguillon
b236a74b64 Increase horizontal spacing in landscape mode
Space between the keys and margin on the left and right edges of the
screen.
2022-06-06 16:15:35 +02:00
Jules Aguillon
f6338a652b New setting: Keyboard height in landscape mode
The previous fixed value of 55% was too high. The new default value is
50% and it is customizable.
2022-06-06 15:33:39 +02:00
Jules Aguillon
9a42fa4dca Don't add extra keys to the numeric pane 2022-06-06 01:02:30 +02:00
Jules Aguillon
4d104eacf3 Remove the option "Show every accents"
This option cannot be implemented easily now that the set of "accents"
(localized keys) isn't defined.
2022-06-06 00:55:16 +02:00
Jules Aguillon
31d6a70dfb Refactor: Remove KeyValue.name
This makes KeyValue objects smaller. 'equals' and 'hashCode' are now
implemented too. Key names are still used to recognise keys with special
meaning, but not for comparing keys anymore.
2022-06-06 00:23:45 +02:00
Jules Aguillon
7462955507 Fix "REMOVED" key appearing when typing Fn and Shift
Since cc571ea
2022-06-05 20:15:11 +02:00
Jules Aguillon
9aac7900c0 Refactor: Make KeyValue final
The class has a complicated internal logic, it is no longer reasonable
to extend it.
2022-06-05 20:14:16 +02:00
Jules Aguillon
088d46d6e6 Refactor: Merge KeyValue._code and _flags fields
With a small number of flags now, it's possible to remove one more
field.
2022-06-05 19:55:55 +02:00
Jules Aguillon
5cc7fdf6d7 Refactor: Separate Events and Keyevents and use enums
Negative values for internal events are preventing further refactoring.

Add a new kind of key and split internal events (now Event) and
Android's key events (now Keyevent).

Use enums events and modifiers outside of the KeyValue class.
Internally, they are converted to and from integer.
2022-06-05 19:30:53 +02:00
Jules Aguillon
cc571ea1ca Refactor: Merge KeyValue.char and code fields
These two fields couldn't have an interesting value at the same time.

As we can no longer rely on a special value to distinguish between
what's the kind, the kind of the key is explicitly encoded in the two
most significative bits of the _flags field.

Extra nice thing: This removes the special values 'EVENT_NONE' and 'CHAR_NONE'.
2022-06-05 18:14:50 +02:00
Jules Aguillon
c1a816d3d4 Refactor: Associate key events in KeyModifier
Two advantages:
- No need to distinguish modifiers in KeyEventHandler. The KeyValue is
  enough to decide what action to do.
- Keys are never a Char and Event at the same time, fields can be
  merged.
2022-06-05 17:46:28 +02:00
Jules Aguillon
e10c587dc5 Refactor: Abstract KeyValue fields
The meaning of the public fields of KeyValue was quite complicated and
not handled consistently accross the app.

Make these fields private and add a more abstract API on top.

The meaning of these fields changed recently and it wasn't an easy
change. I plan on making more changes in the future.
2022-06-05 17:46:22 +02:00
erqan
d03e96da3e Turkish layout & translation (#151)
* Turkish layout & translation
2022-06-05 15:04:54 +02:00
draxaris1010
b3b7877a3b Added support for Dutch(Belgium) (#156) 2022-06-05 14:47:10 +02:00
Jules Aguillon
02124dd71f Add combining 'accent_arrow_right'
It's the first modifier that uses combining diacritics. Whether it
should be represented as a modifier or a new kind of key can be
reconsidered later.
2022-06-05 13:51:09 +02:00
Jules Aguillon
e4e54628b7 Add the 'accent_slash' modifier
Might be useful for some math characters.
2022-06-05 12:02:35 +02:00
Jules Aguillon
4127aa6f03 Stop using flags for modifiers
There was no free bits left to add new modifiers. Instead of increasing
the width of the 'flags' field, refactor the way modifiers are
represented and used.

Modifers are now represented as independent values and stored in the
'code' field. A flag is added to distinguish between modifiers and keys
with a key event.

The most notable change is that modifiers can no longer be or-ed into a
single value but have to be represented as an array.
2022-06-05 01:43:58 +02:00
Jules Aguillon
4f9375373e Colemak: Don't show uncessary dead keys
Hide the dead keys that don't correspond to installed languages.
2022-06-04 16:03:24 +02:00
Djuric
9b154a2495 Add colemak layout (#135) 2022-06-04 15:23:52 +02:00
Jules Aguillon
646ff4834d Move the '0' back to where it was
The '0' has been moved because it was hard to type due to being close to
the edge of the screen.
This is fixed in a more elegant way in a27c644, there's no reason to
keep the '0' in an inconsistent place anymore.
2022-05-29 17:39:48 +02:00
Jules Aguillon
815025aaa9 Add layout: QWERTY (Hungarian) 2022-05-29 17:31:12 +02:00
Jules Aguillon
d9f2fdf8bf Remove some localized keys from the layouts
These keys are not placed in a particular way, the automatic placement
will do a better job.
2022-05-29 12:34:10 +02:00
Jules Aguillon
2e81cb5cf7 Automatically place localized keys on the layouts
Layouts no longer need to mention every localized keys and dead keys.
They are now placed automatically starting from the second row on the
bottom-right corner.

The "loc " prefix is not removed to still be able to define a more
optimal and consistent placement for some extra keys (eg. 'ß' near 's').

Programming layouts no longer need to place every dead keys.
2022-05-29 12:27:46 +02:00
Anindra
89dfc782a7 Update readme (#146)
* add screenshots
2022-05-11 14:45:51 +02:00
Jules Aguillon
eb42943327 Specify localized keys in each layouts
Each layouts can chose which key are localized instead of specifying it
globally for each key.

Important keys are no longer removed from layouts if the 'extra_keys'
mechanism is not working properly. This can happen if language tags
specified in method.xml don't match the user's language.

Removed some currency symbols from some layouts. They are all in the Fn
layer.
2022-05-08 17:35:24 +02:00
Jules Aguillon
121a2ba76f Find closest key further
The previous limit was checking d-1 and d+1, the new limit also tries
d-2 and d+2.
2022-05-08 16:56:34 +02:00
Jules Aguillon
82d3290c6a Fix vibration when pointer move slightly
Fix the bug introduced in the parent commit.
2022-05-08 16:55:03 +02:00
Jules Aguillon
b15ca662c2 Better handling of removed keys and swipe geture
The "closest key" logic must be careful not to reveal keys removed by a
modifier.

Must check [_handler.onPointerSwipe] for every candidate values.
[selected_value] is changed back to [selected_direction].

This adds a new bug: When the direction change, the selected value might
not change but a vibration will be triggered anyway.
2022-05-08 16:55:03 +02:00
Jules Aguillon
9a48acfe3e Improve nearest key computation
getAtDirection was too hard to maintain and might contain bugs.
Change slightly the meaning of directions and implement a the nearest
key calculation as a loop.
2022-05-08 16:55:03 +02:00
Rodrigo Batista de Moraes
bce0a98f62 only vibrate when the swipe key changes 2022-05-08 16:55:03 +02:00
Rodrigo Batista de Moraes
a27c64479f use the closest swipe key on swipe
fix a direction
2022-05-08 16:55:03 +02:00
Jules Aguillon
7da7a5082d Set the color of the navigation bar
Since SDK 21, applications can set the background color of the
navigation bar. This is normally simply an item in a theme but it is
more complicated for keyboards.
2022-05-07 23:51:00 +02:00
Edgars
80600ed659 Add missing LV translations (#136) 2022-05-07 18:57:25 +02:00
Jules Aguillon
3b1c652370 Release 1.15.0 (22) 2022-05-01 23:06:18 +02:00
Tibor Billes
8cb1789eeb Add support for Hungarian layout (#127) 2022-05-01 22:51:11 +02:00
Jules Aguillon
04a7ec4bb8 Fix latched pointers accumulating on the same key
It was possible to latch and lock the same modifier several time at the
same time independently. Remove that.
2022-05-01 00:11:52 +02:00
Jules Aguillon
8e0d38c257 Fix crash when IME not enabled
This is unexpected but happened to a user. Perhaps because the OS
returned bogus or fake results in imm.getEnabledInputMethodList ?
2022-05-01 00:00:15 +02:00
Jules Aguillon
b72635b887 Fix modifiers not cleared when presses overlap
When typing fast, a second key might be pressed before the first is
released.

Clearing modifiers earlier would prevent this but would break modifiers
placed in corners (especially the accent keys). Instead, don't take
latched modifiers into account when registering the second press.

A new flag is needed to not interfere with holding modifers, which is
merged with the norepeat flag.
2022-04-30 23:47:09 +02:00
Jules Aguillon
84af72c222 Record activated modifiers on key down
The View no longer keeps flags for something other than rendering.
2022-04-30 23:17:20 +02:00
marciozomb13
2df4764557 Strings PT: App partially renamed to improve globalization (#134) 2022-04-30 11:01:03 +02:00
Jules Aguillon
39952f8bdf Remove build dependency on Fontforge
The required version of fontforge (from 2020!) is not available in many
distros. This is an annoying for contributors and greatly complicated
the CI and F-Droid scripts.

The generated font file is now included in the sources. Fontforge is
still needed when adding new glyphs but this is not a common operation.
2022-04-24 20:52:36 +02:00
Djuric
ab4c73f9f3 Add build instructions to the contributing page (#130) 2022-04-24 19:59:36 +02:00
matthiakl
e52e537fd7 Added neo 2 layout (#125)
* Added neo 2 layout

* Move accents away from screen edge into second row
2022-04-24 19:58:33 +02:00
Jules Aguillon
2900e8d197 Add Double acute diacritic
Will be used by the Hungarian language.
2022-04-24 01:15:41 +02:00
Jules Aguillon
d8e475467a Fix cedilla glyph is inverted 2022-04-24 00:49:48 +02:00
Jules Aguillon
fec3f109c9 Add support for Lithuanian
Requires two new diacritics: ogonek and dot_above.

The new accents are also added to the Latvian layout as the two language
can be close but not to the other localized layouts. A new mechanism is
needed to reproducibly add extra keys to layouts without manual
placement.
2022-04-24 00:41:49 +02:00
Jules Aguillon
f9f44fbd7d Update contributing guidelines
- Improve layout guidelines
- Adding a locale
- Mention character close to the edges of the screen
- Allow partially translating the app title
2022-04-24 00:41:49 +02:00
Benjamin
914599f16a German translation update 2022-04-23 20:12:52 +02:00
84 changed files with 2923 additions and 949 deletions

View File

@@ -9,38 +9,25 @@ 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
- uses: actions/setup-java@v3
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'
- name: Checkout repo
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Cache debug certificate
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: _build/debug.keystore
key: debug-keystore
- name: Restore debug keystore from github Secrets
run: |
mkdir -p _build
cd "$GITHUB_WORKSPACE/_build"
cd "_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
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"
@@ -48,8 +35,13 @@ jobs:
fi
- name: Build
run: make
- name: Artifact naming
run: |
artifact="${{github.repository_owner}} ${{github.ref_name}}"
artifact="${artifact//\//-}" # replace slashes
echo "artifact=${artifact}" >> $GITHUB_ENV
- name: Save debug apk
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: debug apk
name: "${{env.artifact}} debug_apk"
path: _build/*.apk

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="21" android:versionName="1.14.2" android:hardwareAccelerated="false">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="26" android:versionName="1.18.0" 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">

View File

@@ -12,7 +12,8 @@ Fortunately, there's not many dependencies:
- 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.
For Nix users, the right environment can be obtained with `nix-shell ./shell.nix`.
Instructions to install Nix are [here](https://nixos.wiki/wiki/Nix_Installation_Guide).
Building the debug apk:
@@ -20,8 +21,7 @@ Building the debug apk:
make
```
If the build succeed, the debug apk is located in
`_build/juloo.keyboard2.debug.apk`.
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
@@ -78,26 +78,59 @@ make installd
## Guidelines
### Add a localized layout
### Adding a layout
Localized layouts (a layout specific to a language) are generally accepted.
Layouts are defined in XML, see `res/xml/qwerty.xml`.
An entry must be added to the layout option in `res/values/arrays.xml`, to both
`pref_layout_values` (correspond to the file name) and `pref_layout_entries`
(display name).
The layout must also be referenced in `srcs/juloo.keyboard2/Config.java` in
`layoutId_of_string`.
#### Adding a programming layout
A programming layout must contains every ASCII characters.
The current programming layouts are: QWERTY, Dvorak and Colemak.
Keys with a name starting in `loc ` are hidden unless they are configured for
the user's installed languages in `res/xml/method.xml`. These keys are optional
and will be added automatically when necessary.
Some users cannot easily type the characters close the the edges of the screen
due to a bulky phone case. It is best to avoid placing important characters
there (such as the digits or punctuation).
#### Adding a localized layout
Localized layouts (a layout specific to a language) are gladly 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.
They don't need to contain every ASCII characters (although it's useful in
passwords) and dead-keys.
### Add a programming layout
### Adding support for a language
A programming layout must contains every ASCII characters as well as every dead-keys.
Currently, the only example is QWERTY.
Supported locales are defined in `res/xml/method.xml`.
The attributes `languageTag` and `imeSubtypeLocale` define a locale, the
attribute `imeSubtypeExtraValue` defines the default layout and the dead-keys
and other extra keys to show.
### 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).
Translations are always welcome !
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.
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).
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.
The store description is found in `metadata/android/<locale>/`,
`short_description.txt` and `full_description.txt`.
Translating changelogs is not useful. Changelogs are written quickly just
before a release and older ones are never shown to anyone currently.
The app name might be partially translated, the "unexpected" word should remain
untranslated.

View File

@@ -22,7 +22,10 @@ clean:
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
_build/*.idsig _build/assets
.PHONY: release debug installd clean
rebuild_special_font:
cd srcs/special_font && fontforge -lang=ff -script build.pe *.svg
.PHONY: release debug installd clean rebuild_special_font
$(shell mkdir -p _build)
@@ -85,6 +88,11 @@ _build/%.unaligned-apk: $(addprefix _build/,$(APK_EXTRA_FILES)) $(MANIFEST_FILE)
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) $(APK_EXTRA_FILES)
# Copy the special font file into _build because aapt requires relative paths
_build/assets/special_font.ttf: srcs/special_font/result.ttf
mkdir -p $(@D)
cp "$<" "$@"
# R.java
GEN_DIR = _build/gen
@@ -95,15 +103,6 @@ $(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

View File

@@ -1,8 +1,9 @@
# Unexpected Keyboard
A lightweight virtual keyboard for developers.
![Unexpected Keyboard](metadata/android/en-US/images/featureGraphic.png)
| <img src="/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Screenshot-1" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot-2"/> | <img src="/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot-3"/> |
| --- | --- | --- |
| <img src="/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
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..).

View File

@@ -0,0 +1,18 @@
Tato aplikace je virtuální klávesnící pro Android. Umožňuje rychlejší a plynulejší psaní písmen i symbolů (vč. diakritiky), a to ve vícero jazycích a vlastních rozloženích. To vše zdarma, bez reklam a bez plýtvání vašeho uložiště. Můžete psát libovolné znaky pomocí gest (ASCII i Unicode), používat mrtvé (univerzální) klávesy pro diakritická znaménka a mnohem více.
Klávesnice zobrazuje až 4 další znaky v rozích každé klávesy. Tyto znaky jsou vyvolány přejetím prstu do vybraného rohu.
No zkrátka...:
- Obsahuje každý znak a speciální klávesu, která je běžnou součástí počítačové klávesnice. To přijde vhod obzvláště při používání aplikací jako např. Termux
- Můžete používat modifikační klávesy, obohaceny o speciální klávesy (např. Tab, Esc, šipky, F klávesy, ale také Ctrl nebo Alt !)
- Můžete psát vícero jazyky rychleji a bez chyb. Diakritická znaménka mohou být vyvolána i za pomocí mrtvých kláves. Nejdříve zvolte diakritické znaménko a pak znak, který chcete obohatit o toto znaménko.
- Je vysoce nenáročná a rychlá. Zabere 500x méně místa než klávesnice od Googlu (Gboard) a 15x méně než výchozí klávesnice systému. Bez reklam, bez sledování.
- Má vícero rozložení: QWERTY, QWERTZ, AZERTY. Motivy: Bílá, Tmavá, OLED Černá. A mnoho dalších které si s drobnou znalostí programování můžete upravovat dle libosti.
Nezapomeňte... Jako každá virtuální klávesnice, i tato musí být aktivována v nastavení systému (zařízení). Otevřte (Systémové) Nastavení a přejděte na:
(Další nastavení NEBO Nastavení systému) > Jazyk & způsob zadávání > Spravovat klávesnice.

View File

@@ -0,0 +1 @@
Nenáročná virtuální klávesnice pro vývojáře.

View File

@@ -0,0 +1 @@
Klávesnice Unexpected

View File

@@ -0,0 +1,7 @@
Support languages: Lithuanian, Hungarian (@tbilles)
New layouts: Neo2 (@matthiakl)
Translation improvements (@polyctena, @marciozomb13)
Fix modifiers applied twice when typing quickly. Some other fixes.
Many thanks to the contributors: @matthiakl, @polyctena, @marciozomb13, @dircsem

View File

@@ -0,0 +1,9 @@
New languages: Turkish (@erqan), Dutch (Belgium) (@draxaris1010)
New layouts: Turkish (@erqan), Colemak (@dircsem), Hungarian QWERTY
Less typos: Select the closest key on swipe (@Rodrigodd)
Removed settings: Vibration, Show every accents
More tweaks to the layouts
Fixes to landscape mode, updated translations and more tweaks.
Thanks to the contributors: @erqan, @draxaris1010, @dircsem, @Rodrigodd, @meanindra

View File

@@ -0,0 +1,5 @@
Add back the vibration option.
Fix localized keys not in predefined positions.
Improvements to layouts.
Thanks to the contributors: @Thunder-Squirrel

View File

@@ -0,0 +1,12 @@
New supported languages: Polish, Ukrainian, Bengali, Norwegian
New layouts: Ukrainian, Bengali, Norwegian, Bone, Czech
New translations: Brazilian Portuguese, Italian, Russian, Czech
Hold modifiers to lock, double tap on shift disabled by default.
Option to add more keys to the keyboard.
Automatic capitalisation at beginning of sentences.
Added e-ink oriented theme.
New pane for greek letters and mathematical symbols.
Improvements to the layouts and various bug fixes.
Thanks to the contributors: @nanno, @Quantenzitrone, @eandersons, @iamrasel, @ChristianGynnild, @igorSilCar, @CastixGitHub, @94KONG, @ptrm, @Validbit

View File

@@ -0,0 +1,7 @@
New supported languages: Hindi, Greek
Disable fullscreen mode.
Improvements to layouts and translations.
Various fixes and improvements.
Thanks to the contributors: @sdrapha, @lpv11, @Raj9039852537, @polyctena

View File

@@ -0,0 +1 @@
Una Tastiera Virtuale Leggera Per La Programmazione

View File

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

55
res/values-cs/strings.xml Normal file
View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" product="debug">Klávesnice Unexpected (pro ladění)</string>
<string name="app_name" product="default">Klávesnice Unexpected</string>
<string name="settings_activity_label">Nastavení Klávesnice Unexpected</string>
<string name="pref_category_layout">Rozvržení</string>
<string name="pref_layout_title">Změnit rozvržení klávesnice</string>
<string name="pref_layout_e_system">V nastavení systému</string>
<string name="pref_accents_title">(Univerzální) Diakritická znaménka</string>
<string name="pref_accents_e_all_installed">Zobrazovat znaménka pro všechny instalované systémové jazyky</string>
<string name="pref_accents_e_selected">Zobrazovat znaménka pouze pro současně zvolený jazyk</string>
<string name="pref_accents_e_none">Skrýt (univerzální) diakritická znaménka</string>
<string name="pref_autocapitalisation_title">Automatická kapitalizace</string>
<string name="pref_autocapitalisation_summary">Stiskne Shift na začátku věty</string>
<string name="pref_programming_layout_title">Rozložení klávesnice pro programování</string>
<string name="pref_programming_layout_none">Žádné</string>
<string name="pref_category_typing">Psaní</string>
<string name="pref_swipe_dist_title">Vzdálenost posunutí prstem</string>
<string name="pref_swipe_dist_summary">Jak daleko je třeba posunout prst pro napsaní znaku/diakritiky v rozích klávey (%s)</string>
<string name="pref_long_timeout_title">Časová prodleva opakování znaků</string>
<string name="pref_long_interval_title">Interval opakování znaků</string>
<string name="pref_vibrate_title">Vibrace</string>
<string name="pref_vibrate_summary">Zapnout/Vypnout vibrace při stisku klávesy</string>
<string name="pref_precise_repeat_title">Precizní posun kurzoru</string>
<string name="pref_precise_repeat_summary">Zda-li posun prstem ovlivňuje rychlost kurzoru</string>
<string name="pref_lockable_keys_title">Zastaralé: Zamykatelné modifikační klávesy</string>
<string name="pref_lockable_keys_summary">Tato možnost bude v budoucnu odebrána</string>
<string name="pref_lock_double_tap_title">Dvojklik pro aktivaci caps lock(u)</string>
<string name="pref_lock_double_tap_summary">Dvojklik namísto držení modifikačních kláves po nějakou dobu</string>
<string name="pref_category_style">Styl</string>
<string name="pref_margin_bottom_title">Spodní odsazení</string>
<string name="pref_keyboard_height_title">Výška klávesnice</string>
<string name="pref_keyboard_height_landscape_title">Výška klávesnice v režimu na šířku</string>
<string name="pref_horizontal_margin_title">Boční odsazení</string>
<string name="pref_character_size_title">Velikost znaků</string>
<string name="pref_character_size_summary">Velikost znaků zobrazených na klávesnici (%.2fx)</string>
<string name="pref_theme">Motiv</string>
<string name="pref_theme_e_system">Dle systému</string>
<string name="pref_theme_e_dark">Tmavý</string>
<string name="pref_theme_e_light">Světlý</string>
<string name="pref_theme_e_black">Černý</string>
<string name="pref_swipe_dist_e_very_short">Velmi krátká</string>
<string name="pref_swipe_dist_e_short">Krátká</string>
<string name="pref_swipe_dist_e_default">Běžná</string>
<string name="pref_swipe_dist_e_far">Dlouhá</string>
<string name="pref_swipe_dist_e_very_far">Velmi dlouhá</string>
<string name="pref_key_horizontal_space">Horizontální mezery mezi klávesami</string>
<string name="pref_key_vertical_space">Vertikální mezery mezi klávesami</string>
<string name="key_action_next">Další</string>
<string name="key_action_done">Dokončit</string>
<string name="key_action_go">Spustit</string>
<string name="key_action_prev">Předchozí</string>
<string name="key_action_search">Hledat</string>
<string name="key_action_send">Odeslat</string>
</resources>

View File

@@ -1,5 +1,7 @@
<?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 - Einstellungen</string>
<string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Tastaturlayout ändern</string>
@@ -7,22 +9,29 @@
<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_autocapitalisation_title">Automatische Großschreibung</string>
<string name="pref_autocapitalisation_summary">Umschalttaste am Satzanfang aktivieren</string>
<string name="pref_extra_keys_title">Tasten hinzufügen</string>
<string name="pref_programming_layout_title">Tastaturlayout zum Programmieren</string>
<string name="pref_programming_layout_none">Keines</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_lockable_keys_title">Veraltet: Sperrbare Hilfstasten</string>
<string name="pref_lockable_keys_summary">Wird entfernt. (Hilfstasten, die durch zweimaliges Tippen gesperrt (eingerastet) werden können)</string>
<string name="pref_lock_double_tap_title">Umschalttaste mit Doppeltippen einrasten</string>
<string name="pref_lock_double_tap_summary">Anstatt Taste längere Zeit gedrückt zu halten</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_keyboard_height_landscape_title">Höhe der Tastatur im Querformat</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>
@@ -31,6 +40,7 @@
<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_theme_e_white">Weiß</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>

View File

@@ -7,21 +7,16 @@
<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>

View File

@@ -7,22 +7,22 @@
<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_autocapitalisation_title">Majuscule automatique</string>
<string name="pref_autocapitalisation_summary">Active Shift au début des phrases</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_keyboard_height_landscape_title">Hauteur du clavier en mode paysage</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>
@@ -31,6 +31,7 @@
<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_theme_e_white">Blanc</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>

54
res/values-it/strings.xml Normal file
View File

@@ -0,0 +1,54 @@
<?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">Impostazioni di Unexpected Keyboard</string>
<string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Cambia layout tastiera</string>
<string name="pref_layout_e_system">Impostazioni di sistema</string>
<string name="pref_accents_title">Accenti</string>
<string name="pref_accents_e_all_installed">Mostra accenti per tutte le lingue installate</string>
<string name="pref_accents_e_selected">Mostra accenti solo per le lingue selezionate</string>
<string name="pref_accents_e_none">Nascondi accenti</string>
<string name="pref_autocapitalisation_title">Maiuscole Automatiche</string>
<string name="pref_autocapitalisation_summary">Premi Shift all\'inizio di una frase</string>
<string name="pref_programming_layout_title">Layout tastiera per programmare</string>
<string name="pref_programming_layout_none">Nessuno</string>
<string name="pref_category_typing">Digitando</string>
<string name="pref_swipe_dist_title">Distanza swipe</string>
<string name="pref_swipe_dist_summary">Distanza dei caratteri negli angoli dei tasti (%s)</string>
<string name="pref_long_timeout_title">Timeout ripetizione tasto</string>
<string name="pref_long_interval_title">Intervallo ripetizione tasto</string>
<string name="pref_vibrate_title">Vibrazione</string>
<string name="pref_vibrate_summary">Abilita/Disabilita Vibrazione alla pressione dei tasti</string>
<string name="pref_precise_repeat_title">Movimento puntatore preciso</string>
<string name="pref_precise_repeat_summary">Modula la veocità della ripetizione con lo swipe</string>
<string name="pref_lockable_keys_title">Deprecato: Modificatori bloccabili</string>
<string name="pref_lock_double_tap_title">Doppio tocco su Shift per attivare CapsLock</string>
<string name="pref_lock_double_tap_summary">Invece di premere i modificatori a lungo</string>
<string name="pref_category_style">Stile</string>
<string name="pref_margin_bottom_title">Margine inferiore</string>
<string name="pref_keyboard_height_title">Altezza tastiera</string>
<string name="pref_keyboard_height_landscape_title">Altezza tastiera in modalità orizzontale</string>
<string name="pref_horizontal_margin_title">Margine orizzontale</string>
<string name="pref_character_size_title">Dimensione Caratteri</string>
<string name="pref_character_size_summary">Dimensione dei caratteri mostrati sulla tastiera (%.2fx)</string>
<string name="pref_theme">Tema</string>
<string name="pref_theme_e_system">Impostazioni di sistema</string>
<string name="pref_theme_e_dark">Scuro</string>
<string name="pref_theme_e_light">Chiaro</string>
<string name="pref_theme_e_black">Nero</string>
<string name="pref_swipe_dist_e_very_short">Veramente breve</string>
<string name="pref_swipe_dist_e_short">Breve</string>
<string name="pref_swipe_dist_e_default">Normale</string>
<string name="pref_swipe_dist_e_far">Distante</string>
<string name="pref_swipe_dist_e_very_far">Molto distante</string>
<string name="pref_key_horizontal_space">Spazio orizzontale tra i tasti</string>
<string name="pref_key_vertical_space">Spazio verticale tra i tasti</string>
<string name="key_action_next">Prossimo</string>
<string name="key_action_done">Fatto</string>
<string name="key_action_go">Vai</string>
<string name="key_action_prev">Precedente</string>
<string name="key_action_search">Cerca</string>
<string name="key_action_send">Invia</string>
</resources>

View File

@@ -7,17 +7,14 @@
<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>

View File

@@ -1,11 +1,5 @@
<?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>
<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>
<dimen name="extra_horizontal_margin">25dp</dimen>
</resources>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" product="debug">Unexpected Keyboard (atkļūdošana)</string>
<string name="app_name" product="default">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard iestatījumi</string>
<string name="pref_category_layout">Izkārtojums</string>
<string name="pref_layout_title">Mainīt tastatūras izkārtojumu</string>
@@ -7,22 +9,29 @@
<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_autocapitalisation_title">Automātiski lielie burti</string>
<string name="pref_autocapitalisation_summary">Piespiest Shift teikuma sākumā</string>
<string name="pref_extra_keys_title">Pievienot tastatūrai taustiņus</string>
<string name="pref_programming_layout_title">Tastatūras izkārtojums programmēšanai</string>
<string name="pref_programming_layout_none">Neviens</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_lockable_keys_title">Novecojis: Slēdzami pārveidotāji</string>
<string name="pref_lockable_keys_summary">Šī iespēja tiks noņemta</string>
<string name="pref_lock_double_tap_title">Divkāršs piesitiens burtslēgam</string>
<string name="pref_lock_double_tap_summary">Tā vietā, lai ilstoši piespiestu pārveidotāju</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_keyboard_height_landscape_title">Tastatūras augstums guleniski</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>
@@ -36,6 +45,8 @@
<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="pref_key_horizontal_space">Līmeniskais attālums starp taustiņiem</string>
<string name="pref_key_vertical_space">Stateniskais attālums starp taustiņiem</string>
<string name="key_action_next">Nākamais</string>
<string name="key_action_done">Darīts</string>
<string name="key_action_go">Aiziet</string>

View File

@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" product="debug">Unexpected Keyboard</string>
<string name="app_name" product="default">Unexpected Keyboard</string>
<string name="settings_activity_label">Configurações Unexpected Keyboard</string>
<string name="app_name" product="debug">Teclado Unexpected</string>
<string name="app_name" product="default">Teclado Unexpected</string>
<string name="settings_activity_label">Configurar Teclado Unexpected</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 os 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">Ocultar acentos</string>
<string name="pref_autocapitalisation_title">Maiusculização automática</string>
<string name="pref_autocapitalisation_summary">Aciona o shift no início de cada frase</string>
<string name="pref_programming_layout_title">Layout do teclado para programação</string>
<string name="pref_programming_layout_none">Nenhum</string>
<string name="pref_category_typing">Digitação</string>
@@ -18,17 +19,18 @@
<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 de repetição de 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 a depender do quanto deslizar</string>
<string name="pref_lockable_keys_title">Teclas traváveis</string>
<string name="pref_lockable_keys_summary">Teclas que podem ficar seguradas ao teclar duas vezes</string>
<string name="pref_lockable_keys_title">Descontinuado: Modificadores fixáveis</string>
<string name="pref_lockable_keys_summary">Essa opção será removida</string>
<string name="pref_lock_double_tap_title">Tecle duas vezes no shift para caixa alta</string>
<string name="pref_lock_double_tap_summary">Ao invés de apertar e segurar por um tempo</string>
<string name="pref_category_style">Estilo</string>
<string name="pref_margin_bottom_title">Margem inferior</string>
<string name="pref_keyboard_height_title">Altura do teclado</string>
<string name="pref_keyboard_height_landscape_title">Altura do teclado em modo paisagem</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>

50
res/values-ru/strings.xml Normal file
View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">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_none">Скрыть акценты</string>
<string name="pref_programming_layout_title">Раскладка клавиатуры для программирования</string>
<string name="pref_programming_layout_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_vibrate_title">Вибрация</string>
<string name="pref_vibrate_summary">Включение/выключение вибрации при нажатии клавиши</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">Модификаторы, которые можно заблокировать, введя их дважды</string>
<string name="pref_category_style">Стиль</string>
<string name="pref_margin_bottom_title">Нижняя граница поля</string>
<string name="pref_keyboard_height_title">Высота клавиатуры</string>
<string name="pref_keyboard_height_landscape_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">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">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>

48
res/values-tr/strings.xml Normal file
View File

@@ -0,0 +1,48 @@
<?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 Ayarları</string>
<string name="pref_category_layout">Düzen</string>
<string name="pref_layout_title">Klavye Düzenini Değiştir</string>
<string name="pref_layout_e_system">Sistem Ayarları</string>
<string name="pref_accents_title">Aksanlar</string>
<string name="pref_accents_e_all_installed">Yüklü tüm dillerin aksanlarını göster</string>
<string name="pref_accents_e_selected">Sadece seçili dilin aksanlarını göster</string>
<string name="pref_accents_e_none">Aksanları gizle</string>
<string name="pref_programming_layout_title">Programlama için klavye düzeni</string>
<string name="pref_programming_layout_none">Hiçbiri</string>
<string name="pref_category_typing">Yazma</string>
<string name="pref_swipe_dist_title">Kaydırma mesafesi</string>
<string name="pref_swipe_dist_summary">Tuşların köşelerindeki karakterlerin uzaklıkları (%s)</string>
<string name="pref_long_timeout_title">Tuş tekrarlama beklemesi</string>
<string name="pref_long_interval_title">Tuş tekrarlama aralığı</string>
<string name="pref_vibrate_title">Titreşim</string>
<string name="pref_vibrate_summary">Tuşa basıldığında titreşimi etkinleştir</string>
<string name="pref_precise_repeat_title">İmleç hareketini ayarla</string>
<string name="pref_precise_repeat_summary">Tuş tekrar hızını az ya da çok kaydırarak ayarla</string>
<string name="pref_category_style">Stil</string>
<string name="pref_margin_bottom_title">Alt boşluk</string>
<string name="pref_keyboard_height_title">Klavye yüksekliği</string>
<string name="pref_horizontal_margin_title">Yatay boşluk</string>
<string name="pref_character_size_title">Etiket boyutu</string>
<string name="pref_character_size_summary">Klavye üzerinde gösterilecek karakter boyutu (%.2fx)</string>
<string name="pref_theme">Tema</string>
<string name="pref_theme_e_system">Sistem Ayarları</string>
<string name="pref_theme_e_dark">Koyu</string>
<string name="pref_theme_e_light">ık</string>
<string name="pref_theme_e_black">Siyah</string>
<string name="pref_swipe_dist_e_very_short">Çok kısa</string>
<string name="pref_swipe_dist_e_short">Kısa</string>
<string name="pref_swipe_dist_e_default">Normal</string>
<string name="pref_swipe_dist_e_far">Uzun</string>
<string name="pref_swipe_dist_e_very_far">Çok uzun</string>
<string name="pref_key_horizontal_space">Tuşlar arasındaki yatay boşluk</string>
<string name="pref_key_vertical_space">Tuşlar arasındaki dikey boşluk</string>
<string name="key_action_next">İleri</string>
<string name="key_action_done">Bitti</string>
<string name="key_action_go">İlerle</string>
<string name="key_action_prev">Geri</string>
<string name="key_action_search">Ara</string>
<string name="key_action_send">Gönder</string>
</resources>

View File

@@ -9,21 +9,16 @@
<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>

View File

@@ -6,13 +6,24 @@
<item>qwerty</item>
<item>qwerty_pt</item>
<item>qwerty_es</item>
<item>qwerty_el</item>
<item>qwerty_ko</item>
<item>qwerty_lv</item>
<item>qwerty_no</item>
<item>qwerty_sv_se</item>
<item>qwerty_hu</item>
<item>qwerty_tr</item>
<item>ru_jcuken</item>
<item>qwertz</item>
<item>qwertz_hu</item>
<item>bgph1</item>
<item>dvorak</item>
<item>colemak</item>
<item>neo2</item>
<item>bone</item>
<item>jcuken_ua</item>
<item>bangla</item>
<item>hindi</item>
</string-array>
<string-array name="pref_layout_entries">
<item>@string/pref_layout_e_system</item>
@@ -20,34 +31,45 @@
<item>QWERTY</item>
<item>QWERTY (Brasileiro)</item>
<item>QWERTY (Español)</item>
<item>QWERTY (Greek)</item>
<item>QWERTY (Korean)</item>
<item>QWERTY (Latvian)</item>
<item>QWERTY (Norwegian)</item>
<item>QWERTY (Swedish)</item>
<item>QWERTY (Hungarian)</item>
<item>QWERTY (Türkçe)</item>
<item>ЙЦУКЕН (Русский)</item>
<item>QWERTZ</item>
<item>QWERTZ (Hungarian)</item>
<item>Bulgarian (Phonetic Traditional)</item>
<item>Dvorak</item>
<item>Colemak</item>
<item>Neo 2</item>
<item>Bone</item>
<item>ЙЦУКЕН (Українська)</item>
<item>বাংলা</item>
<item>हिन्दी</item>
</string-array>
<string-array name="pref_programming_layout_values">
<item>none</item>
<item>qwerty</item>
<item>dvorak</item>
<item>colemak</item>
</string-array>
<string-array name="pref_programming_layout_entries">
<item>@string/pref_programming_layout_none</item>
<item>QWERTY</item>
<item>Dvorak</item>
<item>Colemak</item>
</string-array>
<string-array name="pref_accents_entries">
<item>@string/pref_accents_e_all_installed</item>
<item>@string/pref_accents_e_selected</item>
<item>@string/pref_accents_e_all</item>
<item>@string/pref_accents_e_none</item>
</string-array>
<string-array name="pref_accents_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</string-array>
<string-array name="pref_theme_entries">
@@ -55,12 +77,14 @@
<item>@string/pref_theme_e_dark</item>
<item>@string/pref_theme_e_light</item>
<item>@string/pref_theme_e_black</item>
<item>@string/pref_theme_e_white</item>
</string-array>
<string-array name="pref_theme_values">
<item>system</item>
<item>dark</item>
<item>light</item>
<item>black</item>
<item>white</item>
</string-array>
<string-array name="pref_swipe_dist_entries">
<item>@string/pref_swipe_dist_e_very_short</item>

6
res/values/attrs.xml Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ExtraKeyCheckBoxPreference">
<attr name="index" format="integer"/>
</declare-styleable>
</resources>

View File

@@ -9,8 +9,10 @@
<string name="pref_accents_title">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_autocapitalisation_title">Automatic capitalisation</string>
<string name="pref_autocapitalisation_summary">Press Shift at the beginning of a sentence</string>
<string name="pref_extra_keys_title">Add keys to the keyboard</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>
@@ -18,17 +20,18 @@
<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 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_lockable_keys_title">Deprecated: Lockable modifiers</string>
<string name="pref_lockable_keys_summary">Every modifiers can be locked with a long press</string>
<string name="pref_lock_double_tap_title">Double tap on shift for caps lock</string>
<string name="pref_lock_double_tap_summary">Instead of holding modifiers for a time</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_keyboard_height_landscape_title">Keyboard height in landscape mode</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>
@@ -37,6 +40,7 @@
<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_theme_e_white">White</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>

View File

@@ -20,10 +20,20 @@
<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"/>
<!-- System integration -->
<attr name="navigationBarColor" format="color"/>
<attr name="windowLightNavigationBar" format="boolean"/>
</declare-styleable>
<style name="Dark">
<item name="android:isLightTheme">false</item>
<style name="BaseTheme">
<item name="android:forceDarkAllowed">false</item>
<item name="navigationBarColor">?attr/colorKeyboard</item>
<item name="windowLightNavigationBar">?attr/android:isLightTheme</item>
<item name="keyBorderRadius">5dp</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="Dark" parent="BaseTheme">
<item name="android:isLightTheme">false</item>
<item name="colorKeyboard">#1b1b1b</item>
<item name="colorKey">#333333</item>
<item name="colorKeyActivated">#1b1b1b</item>
@@ -31,15 +41,11 @@
<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">
<style name="Light" parent="BaseTheme">
<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>
@@ -47,15 +53,11 @@
<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>
<item name="emoji_button_bg">#dedede</item>
<item name="emoji_color">#000000</item>
</style>
<style name="Black">
<style name="Black" parent="BaseTheme">
<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>
@@ -64,9 +66,19 @@
<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>
<item name="emoji_button_bg">#000000</item>
<item name="emoji_color">#ffffff</item>
</style>
<style name="White" parent="BaseTheme">
<item name="android:isLightTheme">true</item>
<item name="colorKeyboard">#ffffff</item>
<item name="colorKey">#ffffff</item>
<item name="colorKeyActivated">#cccccc</item>
<item name="colorLabel">#000000</item>
<item name="colorLabelActivated">#0066cc</item>
<item name="colorLabelLocked">#33cc33</item>
<item name="colorSubLabel">#333333</item>
<item name="emoji_button_bg">#ffffff</item>
<item name="emoji_color">#000000</item>
</style>
</resources>

View File

@@ -7,8 +7,6 @@
<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>

View File

@@ -10,17 +10,17 @@
<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"/>
<key key0="p" key2="0" key3="f12_placeholder"/>
</row>
<row>
<key key0="q" key2="tab"/>
<key key0="s" key1="accent_ring" key3="ß"/>
<key key0="s" key3="loc ß"/>
<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="k" key2="€" key3="$"/>
<key key0="l" key2="%"/>
<key key0="m" key3="*"/>
</row>
@@ -31,7 +31,7 @@
<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 key0="n" key1="loc accent_tilde" key2="§" key4="!"/>
<key width="2.0" key0="backspace" key2="delete"/>
</row>
</keyboard>

37
res/xml/bangla.xml Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="ঙ" key2="ং" key3="esc" key4="১"/>
<key key0="য" key2="য়" key3="¶" key4="২"/>
<key key0="ড" key2="ঢ" key3="π" key4="৩"/>
<key key0="প" key2="ফ" key3="√" key4=""/>
<key key0="ট" key2="ঠ" key3="^" key4="৫"/>
<key key0="চ" key2="ছ" key3="÷" key4="৬"/>
<key key0="জ" key2="ঝ" key3="×" key4=""/>
<key key0="হ" key2="ঞ" key3="=" key4="৮"/>
<key key0="গ" key2="ঘ" key3="+" key4="৯"/>
<key key0="ড়" key2="ঢ়" key3="-" key4=""/>
</row>
<row>
<key shift="0.5" key0="ৃ" key1="ৠ" key2="ঋ" key3="tab" key4="র্"/>
<key key0="ু" key1="ঊ" key2="উ" key3="~" key4="ূ"/>
<key key0="ি" key1="ঈ" key2="ই" key3="•" key4="ী"/>
<key key0="া" key1="ৄ" key2="আ" key3="°" key4="অ"/>
<key key0="্" key1="ৗ" key2="ঁ" key3="\\" key4="/"/>
<key key0="ব" key1="`" key2="ভ" key3="&lt;" key4="&gt;"/>
<key key0="ক" key1="|" key2="খ" key3="[" key4="]"/>
<key key0="ত" key1="ৎ" key2="থ" key3="{" key4="}"/>
<key key0="দ" key1="_" key2="ধ" key3="(" key4=")"/>
</row>
<row>
<key width="1.4" key0="shift"/>
<key shift="0.1" key0="্র" key2="্য" key3="\#" key4="*"/>
<key key0="ো" key1="ৌ" key2="ও" key3="ঔ" key4="\@"/>
<key key0="ে" key1="ৈ" key2="এ" key3="ঐ" key4="%"/>
<key key0="র" key1="ঃ" key2="ল" key3=":" key4="&amp;"/>
<key key0="ন" key1="৳" key2="ণ" key3=";" key4="."/>
<key key0="স" key1="&quot;" key2="ষ" key3="!" key4=","/>
<key key0="ম" key1="'" key2="শ" key3="\?" key4="।"/>
<key shift="0.1" width="1.4" key0="backspace" key2="delete"/>
</row>
</keyboard>

45
res/xml/bone.xml Normal file
View File

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

View File

@@ -1,7 +1,7 @@
<?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="1.8" key0="ctrl" key1="loc switch_greekmath" key2="loc meta" key4="switch_numeric"/>
<key width="1.2" key0="fn" key1="loc 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"/>

40
res/xml/colemak.xml Normal file
View File

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

View File

@@ -2,32 +2,32 @@
<keyboard>
<row>
<key key0="shift" width="1.5" key2="esc" key4="tab"/>
<key key0="p" key1="accent_ring" key2="." key3="&lt;" key4="f11_placeholder"/>
<key key0="y" key1="accent_grave" key2="," key3="&gt;" key4="f12_placeholder"/>
<key key0="f" key4="€"/>
<key key0="p" key1="loc accent_ring" key2="." key3="&lt;" key4="f11_placeholder"/>
<key key0="y" key1="loc accent_grave" key2="," key3="&gt;" key4="f12_placeholder"/>
<key key0="f" key4="loc €"/>
<key key0="g" key2="\\" key3="|"/>
<key key0="c" key1="accent_trema" key2="accent_circonflexe" key3="{" key4="}"/>
<key key0="c" key1="loc accent_trema" key2="loc accent_circonflexe" key3="{" key4="}"/>
<key key0="r" key3="[" key4="]"/>
<key key0="l" key2="=" key3="+" key4="£"/>
<key key0="l" key2="=" key3="+" key4="loc £"/>
<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="o" key1="loc accent_macron" key2="2" key3="\@" key4="loc accent_ogonek"/>
<key key0="e" key1="loc accent_caron" key2="3" key3="\#" key4="loc accent_dot_above"/>
<key key0="u" key2="4" key3="$" key4="loc accent_double_aigu"/>
<key key0="i" key2="5" key3="%"/>
<key key0="d" key2="6" key3="^"/>
<key key0="h" key2="7" key3="&amp;"/>
<key key0="t" key2="8" key3="*"/>
<key key0="n" key2="9" key3="(" key4=")"/>
<key key0="s" key1="0" key3="ß"/>
<key key0="s" key2="0" key3="loc ß"/>
</row>
<row>
<key key0="q" shift="0.5" key1="accent_tilde" key2="`" key3="~"/>
<key key0="j" key1="accent_aigu" key2="'" key3="&quot;"/>
<key key0="q" shift="0.5" key1="loc accent_tilde" key2="`" key3="~"/>
<key key0="j" key1="loc accent_aigu" key2="'" key3="&quot;"/>
<key key0="k" key2=";" key3=":"/>
<key key0="x" key1="accent_cedille"/>
<key key0="x" key1="loc accent_cedille"/>
<key key0="b"/>
<key key0="m" key2="/" key3="\?"/>
<key key0="w"/>

47
res/xml/greekmath.xml Normal file
View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard bottom_row="false" extra_keys="false">
<row>
<key key0="θ" key2="^"/>
<key key0="δ" key1="⌊" key2="" key3="↔" key4="⊂"/>
<key key0="ϛ" key1="⌋" key2="∧" key3="↑" key4="⊃"/>
<key key0="α" key1="⌈" key2="⊥" key3="↕" key4="∀"/>
<key key0="ξ" key1="⌉" key2="∡" key4="⊷"/>
<key key0="π" key1="∥" key3="≪" key4="7"/>
<key key0="ψ" key1="⌀" key2="⟨" key3="≡" key4="8"/>
<key key0="λ" key1="∞" key2="⟩" key3="≫" key4="9"/>
<key key0="μ" key1="∝" key3="□" key4="f11_placeholder"/>
<key key0="ω" key1="∅" key3="∘" key4="f12_placeholder"/>
</row>
<row>
<key key0="χ" key4=""/>
<key key0="τ" key3="←" key4="∂"/>
<key key0="ι" key3="↓" key4="∫"/>
<key key0="ε" key3="→" key4="∃"/>
<key key0="ο" key4="∈"/>
<key key0="β" key1="⊕" key4="4"/>
<key key0="ν" key1="⊖" key3="" key4="5"/>
<key key0="ρ" key1="⊙" key3="" key4="6"/>
<key key0="σ" key1="⊗"/>
<key key0="γ" key1="⌀"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="φ" key3="⇌" key4="√"/>
<key key0="η" key3="accent_arrow_right" key4=""/>
<key key0="ϡ" key4="∩"/>
<key key0="υ" key3="∇" key4="ℵ"/>
<key key0="ζ" key1="≤" key3="" key4="1"/>
<key key0="Ϟ" key1="≠" key3="" key4="2"/>
<key key0="κ" key1="≥" key3="×" key4="3"/>
<key width="1.5" key0="backspace" key3="delete"/>
</row>
<row height="0.95">
<key width="1.2" key0="switch_text" key2="esc"/>
<key width="1.2" key0="switch_numeric" key2="tab"/>
<key width="1.2" key0="fn"/>
<key width="2.8" key0="space" key1="superscript" key3="subscript"/>
<key width="1.2" key0="0" key2="."/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.2" key0="enter" key1="=" key2="action"/>
</row>
</keyboard>

37
res/xml/hindi.xml Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="ौ" key1="औ" key2="₨" key3="esc" key4="१"/>
<key key0="ै" key1="ऐ" key2="ऍ" key3="¶" key4="२"/>
<key key0="ा" key1="आ" key2="ॅ" key3="ग़" key4="३"/>
<key key0="ी" key1="ई" key2="ज्ञ" key3="ज़" key4="४"/>
<key key0="ू" key1="ऊ" key2="त्र" key3="ऩ" key4="५"/>
<key key0="ब" key1="भ" key2="क्ष" key3="÷" key4="६"/>
<key key0="ह" key1="ङ" key2="श्र" key3="×" key4="७"/>
<key key0="ग" key1="घ" key2="" key3="=" key4="८"/>
<key key0="द" key1="ध" key2="ऋ" key3="+" key4="९"/>
<key key0="ज" key1="झ" key2="ृ" key3="-" key4=""/>
</row>
<row>
<key shift="0.5" key0="ो" key1="ओ" key2="ॉ" key3="tab" key4="ऑ"/>
<key key0="े" key1="ए" key2="ञ" key3="~" key4="॰"/>
<key key0="्" key1="अ" key2="़" key3="ऽ" key4="ऺ"/>
<key key0="ि" key1="इ" key2="ढ" key3="॥" key4="ॄ"/>
<key key0="ु" key1="उ" key2="ड" key3="\\" key4="/"/>
<key key0="प" key1="फ" key2="छ" key3="&lt;" key4="&gt;"/>
<key key0="र" key1="ऱ" key2="च" key3="[" key4="]"/>
<key key0="क" key1="ख" key2="क़" key3="{" key4="}"/>
<key key0="त" key1="थ" key2="ख़" key3="(" key4=")"/>
</row>
<row>
<key width="1.4" key0="shift"/>
<key shift="0.1" key0="ट" key1="ठ" key2="ड़" key3="\#" key4="*"/>
<key key0="ं" key1="ँ" key2="।" key3="ॐ" key4="\@"/>
<key key0="म" key1="ण" key2="य" key3="य़" key4="%"/>
<key key0="न" key1="" key2="।" key3=":" key4="&amp;"/>
<key key0="व" key1="" key2="ढ़" key3=";" key4="."/>
<key key0="ल" key1="ळ" key2="फ़" key3="!" key4=","/>
<key key0="स" key1="श" key2="ष" key3="\?" key4="।"/>
<key shift="0.1" width="1.4" key0="backspace" key2="delete"/>
</row>
</keyboard>

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

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key shift="0.1 " key0="й" key2="1" key4="esc"/>
<key key0="ц" key1="~" key2="2" key3="\@"/>
<key key0="у" key1="!" key2="3" key3="\#" key4="loc €"/>
<key key0="к" key2="4" key3="$"/>
<key key0="е" key2="5" key3="%"/>
<key key0="н" key2="6" key3="^"/>
<key key0="г" key1="ґ" key2="7" key3="&amp;"/>
<key key0="ш" key2="8" key3="*"/>
<key key0="щ" key2="9" key3="(" key4=")"/>
<key key0="з" key2="0" key3="f11_placeholder" key4="f12_placeholder"/>
<key key0="х"/>
</row>
<row>
<key shift="0.1" key0="ф" key1="tab" key2="`"/>
<key key0="і" key2="ї"/>
<key key0="в" />
<key key0="а" />
<key key0="п" />
<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.1" key0="shift"/>
<key key0="я"/>
<key key0="ч" />
<key key0="с" />
<key key0="м" key2="&lt;" key3="."/>
<key key0="и" key2="&gt;" key3=","/>
<key key0="т" key2="\?" key3="/"/>
<key key0="ь" key2=":" key3=";"/>
<key key0="б" key2="&quot;" key3="'"/>
<key key0="ю" key1="«" key2="»"/>
<key width="1.1" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -9,28 +9,28 @@
<key key0="ъ" key2="6" key3="^" key4="€"/>
<key key0="у" key2="7" key3="&amp;" 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"/>
<key key0="о" key2="9" key3="(" key4=")"/>
<key key0="п" key2="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="д"/>
<key key0="ф"/>
<key key0="г" key1="accent_caron" key2="-" key3="_"/>
<key key0="г" key2="-" key3="_"/>
<key key0="х" key2="=" key3="+"/>
<key key0="й" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
<key key0="й" 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="&lt;" key3="."/>
<key key0="ь" key3="ѝ"/>
<key key0="ц" key2="&lt;" key3="."/>
<key key0="ж" key2="&gt;" key3=","/>
<key key0="б" key2="\?" key3="/"/>
<key key0="н" key1="accent_tilde" key2=":" key3=";"/>
<key key0="н" key2=":" key3=";"/>
<key key0="м" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>

View File

@@ -10,12 +10,12 @@
<key key0="г" key2="7" key3="&amp;"/>
<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"/>
<key key0="з" key2="0" key3="{" key4="}" />
<key key0="х" key3="[" key4="]" key1="f11_placeholder" key2="f12_placeholder"/>
</row>
<row>
<key shift="0.5" key0="ф" key1="tab" key2="`"/>
<key key0="ф" key1="tab" key2="`"/>
<key key0="ы"/>
<key key0="в"/>
<key key0="а"/>
@@ -28,16 +28,16 @@
<key key0="э" key2="|" key3="\\"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="я"/>
<key key0="ч"/>
<key key0="с"/>
<key key0="м"/>
<key key0="и" key2="&lt;" key3="."/>
<key key0="т" key2="&gt;" key3=","/>
<key key0=" key2="\?" key3="/"/>
<key key0="б" key2=":" key3=";"/>
<key key0="ю" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
<key width="1.18" key0="shift"/>
<key width="0.96" key0="я"/>
<key width="0.96" key0="ч"/>
<key width="0.96" key0="с"/>
<key width="0.96" key0="м"/>
<key width="0.96" key0="и" key2="&lt;" key3="."/>
<key width="0.96" key0="т" key2="&gt;" key3=","/>
<key width="0.96" key0="ь" key1=" key2="\?" key3="/"/>
<key width="0.96" key0="б" key2=":" key3=";"/>
<key width="0.96" key0="ю" key2="&quot;" key3="'"/>
<key width="1.18" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -1,15 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys=€"/>
<subtype android:label="%s" android:languageTag="bn" android:imeSubtypeLocale="bn_BD" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=৳"/>
<subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=hindi,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="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz_hu,extra_keys=accent_aigu|accent_trema|accent_ogonek|€"/>
<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="lt" android:imeSubtypeLocale="lt_LT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=accent_ogonek|accent_caron|accent_dot_above|accent_macron|€"/>
<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="nl-BE" android:imeSubtypeLocale="nl_BE" 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="no" android:imeSubtypeLocale="no_NO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_no,extra_keys=accent_aigu|€"/>
<subtype android:label="%s" android:languageTag="pl" android:imeSubtypeLocale="pl_PL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=accent_aigu|accent_ogonek|accent_dot_above|ł"/>
<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|€"/>
<subtype android:label="%s" android:languageTag="tr" android:imeSubtypeLocale="tr_TR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_tr,extra_keys=accent_cedille|accent_trema|₺|ı|ğ"/>
<subtype android:label="%s" android:languageTag="uk" android:imeSubtypeLocale="uk_UA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=jcuken_ua"/>
<subtype android:label="%s" android:languageTag="cs" android:imeSubtypeLocale="cs_CZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz_cs,extra_keys=a|accent_cedille|accent_circonflexe"/>
<subtype android:label="%s" android:languageTag="el" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_el,extra_keys=£|€"/>
</input-method>

49
res/xml/neo2.xml Normal file
View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard bottom_row="false">
<row>
<key key0="x" key1="°" key2="1" key4="…"/>
<key key0="v" key1="§" key2="2" key4="_"/>
<key key0="l" key2="3" key4="["/>
<key key0="c" key2="4" key4="]"/>
<key key0="w" key2="5" key4="^"/>
<key key0="k" key2="6" key4="!"/>
<key key0="h" key2="7" key4="&lt;"/>
<key key0="g" key2="8" key4="&gt;"/>
<key key0="f" key2="9" key3="f11_placeholder" key4="="/>
<key key0="q" key2="0" key3="f12_placeholder" key4="&amp;"/>
<key key0="ß" key1="-"/>
</row>
<row>
<key key0="u" key1="tab" key4="\\"/>
<key key0="i" key4="/"/>
<key key0="a" key4="{"/>
<key key0="e" key4="}"/>
<key key0="o" key4="*"/>
<key key0="s" key4="\?"/>
<key key0="n" key4="("/>
<key key0="r" key4=")"/>
<key key0="t" key4="-"/>
<key key0="d" key4=":"/>
<key key0="y" key3="\@"/>
</row>
<row>
<key width="1.5" key0="shift" key1="esc"/>
<key key0="ü" key4="\#"/>
<key key0="ö" key4="$"/>
<key key0="ä" key4="|"/>
<key key0="p" key4="~"/>
<key key0="z" key4="`"/>
<key key0="b" key4="+"/>
<key key0="m" key4="%"/>
<key key0="." key1="," key3="&quot;" key4="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
<row height="0.95">
<key width="1.8" key0="ctrl" key2="loc meta" key4="switch_numeric"/>
<key width="1.2" key0="fn" key1="loc 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 key0="j" key4=";"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard bottom_row="false">
<keyboard bottom_row="false" extra_keys="false">
<row>
<key width="0.75" key0="esc" key2="~" key4="!"/>
<key width="0.75" key0="(" key2="[" key4="{"/>
<key key0="7" key1="&lt;" key2="&gt;"/>
<key key0="8" key2="∞"/>
<key key0="9" key2="π"/>
<key width="0.75" key0="*" key1="√" key2="×"/>
<key width="0.75" key0="*" key1="√" key2="×" key3="\#"/>
<key width="0.75" key0="/" key1="%" key3="÷"/>
</row>
<row>
@@ -19,11 +19,12 @@
<key width="0.75" key0="-" key1="^"/>
</row>
<row>
<key shift="0.35" width="1.15" key0="shift" key2="fn" key4="alt"/>
<key width="0.75" key0="switch_greekmath"/>
<key width="0.75" key0="shift" key2="fn" key4="loc alt"/>
<key key0="1" key1="superscript" key2="ordinal" key3="subscript"/>
<key key0="2"/>
<key key0="3"/>
<key width="1.15" key0="backspace" key2="delete"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
<row height="0.95">
<key width="1.5" key0="switch_text" key2="ctrl"/>

View File

@@ -3,34 +3,34 @@
<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="e" key1="!" key2="3" key3="\#" key4="loc €"/>
<key key0="r" key2="4" key3="$"/>
<key key0="t" key2="5" key3="%"/>
<key key0="y" key2="6" key3="^"/>
<key key0="u" key2="7" key3="&amp;"/>
<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"/>
<key key0="o" key1="loc accent_macron" key2="9" key3="(" key4=")"/>
<key key0="p" key2="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="s" key1="loc accent_ring" key3="loc ß" key4="loc accent_ogonek"/>
<key key0="d" key1="loc accent_grave" key2="loc £" key3="loc accent_aigu"/>
<key key0="f" key1="loc accent_dot_above"/>
<key key0="g" key1="loc 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="j" key1="loc accent_trema" key2="loc accent_circonflexe" key4="}" key3="{"/>
<key key0="k" key1="loc accent_double_aigu" 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="&lt;" key3="."/>
<key key0="c" key1="loc accent_cedille" key2="&lt;" key3="."/>
<key key0="v" key2="&gt;" key3=","/>
<key key0="b" key2="\?" key3="/"/>
<key key0="n" key1="accent_tilde" key2=":" key3=";"/>
<key key0="n" key1="loc accent_tilde" key2=":" key3=";"/>
<key key0="m" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>

37
res/xml/qwerty_el.xml Normal file
View 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="loc €"/>
<key key0="ρ" key2="4" key3="$"/>
<key key0="τ" key2="5" key3="%"/>
<key key0="υ" key2="6" key3="^"/>
<key key0="θ" key2="7" key3="&amp;"/>
<key key0="ι" key1="accent_trema" key2="8" key3="*"/>
<key key0="ο" key2="9" key3="(" key4=")"/>
<key key0="π" key2="0" key3="f11_placeholder" key4="f12_placeholder"/>
</row>
<row>
<key shift="0.5" key0="α" key1="tab" key2="`"/>
<key key0="σ"/>
<key key0="δ" key2="loc £"/>
<key key0="φ"/>
<key key0="γ" key2="-" key3="_"/>
<key key0="η" key2="=" key3="+"/>
<key key0="ξ" key2="accent_aigu" key3="{" key4="}"/>
<key key0="κ" key2="accent_grave" key3="[" key4="]"/>
<key key0="λ" key2="|" key3="\\"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="ζ"/>
<key key0="χ"/>
<key key0="ψ" key2="&lt;" key3="."/>
<key key0="ω" key2="&gt;" key3=","/>
<key key0="β" key2="\?" key3="/"/>
<key key0="ν" key2=":" key3=";"/>
<key key0="μ" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -9,17 +9,17 @@
<key key0="y" key2="6" key3="^"/>
<key key0="u" key2="7" key3="&amp;"/>
<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"/>
<key key0="o" key2="9" key3="(" key4=")"/>
<key key0="p" key2="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="s" key2="¡" key3="loc ß"/>
<key key0="d" key1="accent_grave" key3="accent_aigu"/>
<key key0="f"/>
<key key0="g" key1="accent_caron" key2="-" key3="_"/>
<key key0="g" key2="-" key3="_"/>
<key key0="h" key2="=" key3="+"/>
<key key0="j" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/>
<key key0="j" key1="accent_trema" key4="}" key3="{"/>
<key key0="k" key3="[" key4="]"/>
<key key0="l" key2="|" key3="\\"/>
<key key0="ñ" key1="·" key3="ç" />
@@ -28,7 +28,7 @@
<key width="1.5" key0="shift"/>
<key key0="z"/>
<key key0="x"/>
<key key0="c" key1="accent_cedille" key2="&lt;" key3="."/>
<key key0="c" key1="loc accent_cedille" key2="&lt;" key3="."/>
<key key0="v" key2="&gt;" key3=","/>
<key key0="b" key2="\?" key3="/" key4="¿"/>
<key key0="n" key1="accent_tilde" key2=":" key3=";"/>

37
res/xml/qwerty_hu.xml Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key2="0" key4="esc"/>
<key key0="w" key1="'" key2="1" key3="~" key4="|"/>
<key key0="e" key1="&quot;" key2="2" key4="é"/>
<key key0="r" key2="3" key4="^"/>
<key key0="t" key1="!" key2="4" key4="f11_placeholder"/>
<key key0="y" key1="%" key2="5" key3="°" key4="f12_placeholder"/>
<key key0="u" key1="ű" key2="6" key3="ü" key4="ú"/>
<key key0="i" key1="=" key2="7" key3="`" key4="í"/>
<key key0="o" key1="ő" key2="8" key3="ö" key4="ó"/>
<key key0="p" key2="9"/>
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key4="á"/>
<key key0="s" key1="§" key2="\\" key3="[" key4="]"/>
<key key0="d" key3="{" key4="}"/>
<key key0="f" key3="+"/>
<key key0="g" key3="*"/>
<key key0="h"/>
<key key0="j"/>
<key key0="k" key3="(" key4=")"/>
<key key0="l" key1="$" key3="/"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="z" key3="&lt;" key4="&gt;"/>
<key key0="x" key4="\#"/>
<key key0="c" key4="&amp;"/>
<key key0="v" key4="\@"/>
<key key0="b" key1="\?" key3="," key4=";"/>
<key key0="n" key1=":" key3="."/>
<key key0="m" key1="_" key3="-"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -3,19 +3,19 @@
<row>
<key key0="ㅂ" key2="1" key4="esc"/>
<key key0="ㅈ" key1="~" key2="2" key3="\@"/>
<key key0="ㄷ" key1="!" key2="3" key3="\#" key4="€"/>
<key key0="ㄷ" key1="!" key2="3" key3="\#"/>
<key key0="ㄱ" key2="4" key3="$"/>
<key key0="ㅅ" key2="5" key3="%"/>
<key key0="ㅛ" key2="6" key3="^"/>
<key key0="ㅕ" key2="7" key3="&amp;"/>
<key key0="ㅑ" key2="8" key3="*"/>
<key key0="ㅐ" key2="9" key3="(" key4=")"/>
<key key0="ㅔ" key1="0" key3="f11_placeholder" key4="f12_placeholder"/>
<key key0="ㅔ" key2="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="ㅇ"/>
<key key0="ㄹ"/>
<key key0="ㅎ" key2="-" key3="_"/>
<key key0="ㅗ" key2="=" key3="+"/>

View File

@@ -10,13 +10,13 @@
<key key0="u" key1="ū" key2="7" key3="&amp;" key4="*"/>
<key key0="i" key1="ī" key2="8" key3="(" key4=")"/>
<key key0="o" key1="ō" key2="9" key3="{" key4="}"/>
<key key0="p" key1="0"/>
<key key0="p" key2="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="s" key1="š" key3="loc ß" key4="loc accent_ogonek"/>
<key key0="d"/>
<key key0="f" key1="loc accent_dot_above"/>
<key key0="g" key1="ģ"/>
<key key0="h" key2="accent_macron" key3="accent_caron" key4="accent_cedille"/>
<key key0="j" key1="+" key2="=" key3="-" key4="_"/>

37
res/xml/qwerty_no.xml Normal file
View 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="\@"/>
<key key0="e" key1="!" key2="3" key3="\#" key4="loc €"/>
<key key0="r" key2="4" key3="$"/>
<key key0="t" key2="5" key3="%"/>
<key key0="y" key2="6" key3="^"/>
<key key0="u" key2="7" key3="&amp;"/>
<key key0="i" key2="8" key3="*"/>
<key key0="o" key1="ø" key2="9" key3="(" key4=")"/>
<key key0="p" key2="0" key3="f11_placeholder" key4="f12_placeholder"/>
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key2="`" key3="æ" key4="å"/>
<key key0="s" key1="loc accent_ring" key3="loc ß" key4="loc accent_ogonek"/>
<key key0="d" key1="loc accent_grave" key2="loc £" key3="loc accent_aigu"/>
<key key0="f" key1="loc accent_dot_above"/>
<key key0="g" key1="loc accent_caron" key2="-" key3="_"/>
<key key0="h" key2="=" key3="+"/>
<key key0="j" key1="loc accent_trema" key2="loc accent_circonflexe" key4="}" key3="{"/>
<key key0="k" key1="loc accent_double_aigu" 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="loc accent_cedille" key2="&lt;" key3="."/>
<key key0="v" key2="&gt;" key3=","/>
<key key0="b" key2="\?" key3="/"/>
<key key0="n" key1="loc accent_tilde" key2=":" key3=";"/>
<key key0="m" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -3,20 +3,20 @@
<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="e" 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="y" key2="6" key3="^" key4="loc accent_trema"/>
<key key0="u" key2="7" key3="&amp;"/>
<key key0="i" key2="8" key3="*"/>
<key key0="o" key2="9" key3="(" key4=")"/>
<key key0="p" key1="0" key3="\\"/>
<key key0="p" key2="0" key3="\\"/>
</row>
<row>
<key key0="a" key2="tab" key4="`"/>
<key key0="s" key1="'" key3="ß" key4="accent_cedille"/>
<key key0="d" key1="&quot;" key2="accent_ring"/>
<key key0="f" key2="accent_caron"/>
<key key0="s" key1="'" key3="loc ß" key4="accent_cedille"/>
<key key0="d" key1="&quot;"/>
<key key0="f"/>
<key key0="g"/>
<key key0="h"/>
<key key0="j" key1="-" key2="=" key4="+" key3="_"/>

View File

@@ -15,9 +15,9 @@
</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="s" key1="accent_ring" key3="loc ß"/>
<key key0="d" key3="accent_aigu"/>
<key key0="f" key1="accent_trema"/>
<key key0="g"/>
<key key0="h"/>
<key key0="j" key1="{" key4="}"/>

37
res/xml/qwerty_tr.xml Normal file
View 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="\@"/>
<key key0="e" key1="!" key2="3" key3="\#" key4="€"/>
<key key0="r" key2="4" key3="$"/>
<key key0="t" key2="5" key3="%" key4="₺"/>
<key key0="y" key2="6" key3="^"/>
<key key0="u" key1="ü" key2="7" key3="&amp;"/>
<key key0="i" key1="ı" key2="8" key3="*"/>
<key key0="o" key1="ö" key2="9" key3="(" key4=")"/>
<key key0="p" key1="0" />
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key2="`"/>
<key key0="s" key1="ş"/>
<key key0="d"/>
<key key0="f"/>
<key key0="g" key1="ğ" key2="-" key3="_"/>
<key key0="h" key2="=" key3="+"/>
<key key0="j" key3="{" key4="}"/>
<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="ç" key2="&lt;" key3="."/>
<key key0="v" key2="&gt;" key3=","/>
<key key0="b" key2="\?" key3="/"/>
<key key0="n" key2=":" key3=";"/>
<key key0="m" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -10,12 +10,12 @@
<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="\?"/>
<key key0="p" key2="0" key3="\?"/>
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key2="`" key3="ä"/>
<key key0="s" key3="ß"/>
<key key0="d" key2="£"/>
<key key0="d"/>
<key key0="f" key1="~"/>
<key key0="g" key3="-"/>
<key key0="h" key3="+"/>

37
res/xml/qwertz_cs.xml Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key1="1" key4="esc"/>
<key key0="w" key1="2" key3="~"/>
<key key0="e" key1="3" key2="é" key3="ë" key4="ě"/>
<key key0="r" key1="4" key2="ŕ" key3="°" key4="ř"/>
<key key0="t" key1="5" key3="%" key4="ť"/>
<key key0="z" key1="6" key3="^" key4="ž"/>
<key key0="u" key1="7" key2="ú" key3="ü" key4="ů"/>
<key key0="i" key1="8" key2="í" key3="ï" key4="*"/>
<key key0="o" key1="9" key2="ó" key3="ö" key4="ô"/>
<key key0="p" key1="0" key2="=" key3="/" key4="π"/>
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key2="á" key3="ä" key4="α"/>
<key key0="s" key1="{" key2="&lt;" key3="§" key4="š"/>
<key key0="d" key1="$" key2="δ" key3="Δ" key4="ď"/>
<key key0="f" key1="&gt;" key2="}" key3="ѳ" key4="φ"/>
<key key0="g" key1="»" key2="«" key3="" key4="_"/>
<key key0="h" key1="[" key2="("/>
<key key0="j" key1="+" key2="\?" key3="!" key4="-"/>
<key key0="k" key1=")" key2="]"/>
<key key0="l" key2="ľ" key3="\\" key4="ĺ"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="y" key1="÷" key2="ý"/>
<key key0="x" key1="∙" key3="×"/>
<key key0="c" key1="\#" key2="γ" key3="&amp;" key4="č"/>
<key key0="v" key1="|" key3="\@"/>
<key key0="b" key1=";" key2="♭" key3=":" key4="β"/>
<key key0="n" key1="," key3="." key4="ň"/>
<key key0="m" key1="&quot;" key3="\'"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

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

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key2="0" key4="esc"/>
<key key0="w" key1="'" key2="1" key3="~" key4="|"/>
<key key0="e" key1="&quot;" key2="2" key4="é"/>
<key key0="r" key2="3" key4="^"/>
<key key0="t" key1="!" key2="4" key4="f11_placeholder"/>
<key key0="z" key1="%" key2="5" key3="°" key4="f12_placeholder"/>
<key key0="u" key1="ű" key2="6" key3="ü" key4="ú"/>
<key key0="i" key1="=" key2="7" key3="`" key4="í"/>
<key key0="o" key1="ő" key2="8" key3="ö" key4="ó"/>
<key key0="p" key2="9"/>
</row>
<row>
<key shift="0.5" key0="a" key1="tab" key4="á"/>
<key key0="s" key1="§" key2="\\" key3="[" key4="]"/>
<key key0="d" key3="{" key4="}"/>
<key key0="f" key3="+"/>
<key key0="g" key3="*"/>
<key key0="h"/>
<key key0="j"/>
<key key0="k" key3="(" key4=")"/>
<key key0="l" key1="$" key3="/"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="y" key3="&lt;" key4="&gt;"/>
<key key0="x" key4="\#"/>
<key key0="c" key4="&amp;"/>
<key key0="v" key4="\@"/>
<key key0="b" key1="\?" key3="," key4=";"/>
<key key0="n" key1=":" key3="."/>
<key key0="m" key1="_" key3="-"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

View File

@@ -1,17 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<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"/>
<PreferenceScreen android:title="@string/pref_extra_keys_title">
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="0"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="1"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="2"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="3"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="4"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="5"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="6"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="7"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="8"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="9"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="10"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="11"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="12"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="13"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="14"/>
<juloo.keyboard2.ExtraKeyCheckBoxPreference app:index="15"/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_typing">
<CheckBoxPreference android:key="autocapitalisation" android:title="@string/pref_autocapitalisation_title" android:summary="@string/pref_autocapitalisation_summary" android:defaultValue="true"/>
<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"/>
<CheckBoxPreference android:key="lock_double_tap" android:title="@string/pref_lock_double_tap_title" android:summary="@string/pref_lock_double_tap_summary" android:defaultValue="false"/>
<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"/>
@@ -20,15 +39,13 @@
<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="keyboard_height_landscape" android:title="@string/pref_keyboard_height_landscape_title" android:summary="%s%%" android:defaultValue="50" min="35" max="65"/>
<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"/>

View File

@@ -0,0 +1,148 @@
package juloo.keyboard2;
import android.os.Handler;
import android.os.Looper;
import android.text.InputType;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.KeyEvent;
final class Autocapitalisation
{
boolean _enabled = false;
boolean _should_enable_shift = false;
boolean _should_disable_shift = false;
boolean _should_update_caps_mode = false;
Handler _handler;
InputConnection _ic;
Callback _callback;
int _caps_mode;
/** Keep track of the cursor to recognize cursor movements from typing. */
int _cursor;
static int SUPPORTED_CAPS_MODES =
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
InputType.TYPE_TEXT_FLAG_CAP_WORDS;
public Autocapitalisation(Looper looper, Callback cb)
{
_handler = new Handler(looper);
_callback = cb;
}
/**
* The events are: started, typed, event sent, selection updated
* [started] does initialisation work and must be called before any other
* event.
*/
public void started(EditorInfo info, InputConnection ic)
{
_ic = ic;
_caps_mode = info.inputType & TextUtils.CAP_MODE_SENTENCES;
if (!Config.globalConfig().autocapitalisation || _caps_mode == 0)
{
_enabled = false;
return;
}
_enabled = true;
_should_enable_shift = (info.initialCapsMode != 0);
_callback.update_shift_state(_should_enable_shift, true);
}
public void typed(CharSequence c)
{
for (int i = 0; i < c.length(); i++)
type_one_char(c.charAt(i));
callback(false);
}
public void typed(char c)
{
type_one_char(c);
callback(false);
}
public void event_sent(int code, int meta)
{
if (meta != 0)
{
_should_enable_shift = false;
_should_update_caps_mode = false;
return;
}
switch (code)
{
case KeyEvent.KEYCODE_DEL:
if (_cursor > 0) _cursor--;
_should_update_caps_mode = true;
break;
}
callback(true);
}
public static interface Callback
{
public void update_shift_state(boolean should_enable, boolean should_disable);
}
/** Returns [true] if shift might be disabled. */
public void selection_updated(int old_cursor, int new_cursor)
{
if (new_cursor == _cursor) // Just typing
return;
if (new_cursor == 0 && _ic != null)
{
// Detect whether the input box has been cleared
CharSequence t = _ic.getTextAfterCursor(1, 0);
if (t != null && t.equals(""))
_should_update_caps_mode = true;
}
_cursor = new_cursor;
_should_enable_shift = false;
callback(true);
}
Runnable delayed_callback = new Runnable()
{
public void run()
{
if (_should_update_caps_mode && _ic != null)
{
_should_enable_shift = _enabled && (_ic.getCursorCapsMode(_caps_mode) != 0);
_should_update_caps_mode = false;
}
_callback.update_shift_state(_should_enable_shift, _should_disable_shift);
}
};
void callback(final boolean might_disable)
{
_should_disable_shift = might_disable;
// The callback must be delayed because [getCursorCapsMode] would sometimes
// be called before the editor finished handling the previous event.
_handler.postDelayed(delayed_callback, 1);
}
void type_one_char(char c)
{
_cursor++;
if (is_trigger_character(c))
_should_update_caps_mode = true;
else
_should_enable_shift = false;
}
boolean is_trigger_character(char c)
{
switch (c)
{
case ' ':
return true;
default:
return false;
}
}
}

View File

@@ -9,6 +9,7 @@ import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.KeyEvent;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
@@ -26,7 +27,6 @@ final class Config
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;
@@ -35,10 +35,11 @@ final class Config
public float keyVerticalInterval;
public float keyHorizontalInterval;
public boolean preciseRepeat;
public int lockable_modifiers;
public Set<KeyValue.Modifier> lockable_modifiers = new HashSet<KeyValue.Modifier>();
public float characterSize; // Ratio
public int accents; // Values are R.values.pref_accents_v_*
public int theme; // Values are R.style.*
public boolean autocapitalisation;
// Dynamically set
public boolean shouldOfferSwitchingToNextInputMethod;
@@ -46,7 +47,8 @@ final class Config
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 Set<KeyValue> extra_keys_subtype;
public Set<KeyValue> extra_keys_param;
public final IKeyEventHandler handler;
@@ -56,13 +58,12 @@ final class Config
// 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));
labelTextSize = 0.33f;
sublabelTextSize = 0.22f;
// default values
layout = -1;
programming_layout = -1;
vibrateEnabled = true;
vibrateDuration = 20;
longPressTimeout = 600;
longPressInterval = 65;
marginBottom = res.getDimension(R.dimen.margin_bottom);
@@ -81,7 +82,7 @@ final class Config
actionLabel = null;
actionId = 0;
swapEnterActionKey = false;
extra_keys = null;
extra_keys_subtype = null;
handler = h;
}
@@ -93,13 +94,17 @@ final class Config
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.
// The height of the keyboard is relative to the height of the screen.
// This is the height of the keyboard if it have 4 rows.
int keyboardHeightPercent;
// Scale some dimensions depending on orientation
float horizontalIntervalScale = 1.f;
float characterSizeScale = 1.f;
if (res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) // Landscape mode
{
keyboardHeightPercent = 55;
keyboardHeightPercent = prefs.getInt("keyboard_height_landscape", 50);
horizontalIntervalScale = 2.f;
characterSizeScale = 1.25f;
}
else
{
@@ -115,72 +120,95 @@ final class Config
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);
keyHorizontalInterval =
getDipPref(dm, prefs, "key_horizontal_space", keyHorizontalInterval)
* horizontalIntervalScale;
// 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);
horizontalMargin =
getDipPref(dm, prefs, "horizontal_margin", horizontalMargin)
+ res.getDimension(R.dimen.extra_horizontal_margin);
preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
lockable_modifiers =
(prefs.getBoolean("lockable_shift", true) ? KeyValue.FLAG_SHIFT : 0)
| (prefs.getBoolean("lockable_ctrl", false) ? KeyValue.FLAG_CTRL : 0)
| (prefs.getBoolean("lockable_alt", false) ? KeyValue.FLAG_ALT : 0)
| (prefs.getBoolean("lockable_fn", false) ? KeyValue.FLAG_FN : 0)
| (prefs.getBoolean("lockable_meta", false) ? KeyValue.FLAG_META : 0)
| (prefs.getBoolean("lockable_sup", false) ? KeyValue.FLAG_ACCENT_SUPERSCRIPT : 0)
| (prefs.getBoolean("lockable_sub", false) ? KeyValue.FLAG_ACCENT_SUBSCRIPT : 0)
| (prefs.getBoolean("lockable_box", false) ? KeyValue.FLAG_ACCENT_BOX : 0);
characterSize = prefs.getFloat("character_size", characterSize);
lockable_modifiers.clear();
if (prefs.getBoolean("lock_double_tap", false))
lockable_modifiers.add(KeyValue.Modifier.SHIFT);
if (prefs.getBoolean("lockable_ctrl", false)) lockable_modifiers.add(KeyValue.Modifier.CTRL);
if (prefs.getBoolean("lockable_alt", false)) lockable_modifiers.add(KeyValue.Modifier.ALT);
if (prefs.getBoolean("lockable_fn", false)) lockable_modifiers.add(KeyValue.Modifier.FN);
if (prefs.getBoolean("lockable_meta", false)) lockable_modifiers.add(KeyValue.Modifier.META);
if (prefs.getBoolean("lockable_sup", false)) lockable_modifiers.add(KeyValue.Modifier.SUPERSCRIPT);
if (prefs.getBoolean("lockable_sub", false)) lockable_modifiers.add(KeyValue.Modifier.SUBSCRIPT);
if (prefs.getBoolean("lockable_box", false)) lockable_modifiers.add(KeyValue.Modifier.BOX);
characterSize =
prefs.getFloat("character_size", characterSize)
* characterSizeScale;
accents = Integer.valueOf(prefs.getString("accents", "1"));
theme = getThemeId(res, prefs.getString("theme", ""));
autocapitalisation = prefs.getBoolean("autocapitalisation", true);
extra_keys_param = ExtraKeyCheckBoxPreference.get_extra_keys(prefs);
}
/** 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')
* - Remove "localized" 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)
public KeyboardData modify_layout(KeyboardData original_kw)
{
// Update the name to avoid caching in KeyModifier
final KeyValue action_key = (actionLabel == null) ? null :
KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel);
return kw.replaceKeys(new KeyboardData.MapKeys() {
public KeyValue apply(KeyValue key)
KeyValue.getKeyByName("action").withSymbol(actionLabel);
// Extra keys are removed from the set as they are encountered during the
// first iteration then automatically added.
final Set<KeyValue> extra_keys = new HashSet<KeyValue>();
extra_keys.addAll(extra_keys_subtype);
extra_keys.addAll(extra_keys_param);
KeyboardData kw = original_kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
if (key == null)
boolean is_extra_key = extra_keys.contains(key);
if (is_extra_key)
extra_keys.remove(key);
if (localized && !is_extra_key)
return null;
switch (key.eventCode)
switch (key.getKind())
{
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)
case Event:
switch (key.getEvent())
{
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);
case CHANGE_METHOD:
return shouldOfferSwitchingToNextInputMethod ? key : null;
case ACTION:
return (swapEnterActionKey && action_key != null) ?
KeyValue.getKeyByName("enter") : action_key;
case SWITCH_PROGRAMMING:
return shouldOfferSwitchingToProgramming ? key : null;
}
return key;
break;
case Keyevent:
switch (key.getKeyevent())
{
case KeyEvent.KEYCODE_ENTER:
return (swapEnterActionKey && action_key != null) ? action_key : key;
}
break;
case Modifier:
if (lockable_modifiers.contains(key.getModifier()))
return key.withFlags(key.getFlags() | KeyValue.FLAG_LOCK);
break;
}
return key;
}
});
if (extra_keys.size() > 0)
kw = kw.addExtraKeys(extra_keys.iterator());
return kw;
}
private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
@@ -200,6 +228,7 @@ final class Config
case "light": return R.style.Light;
case "black": return R.style.Black;
case "dark": return R.style.Dark;
case "white": return R.style.White;
default:
case "system":
if (Build.VERSION.SDK_INT >= 8)
@@ -217,30 +246,32 @@ final class Config
switch (name)
{
case "azerty": return R.xml.azerty;
case "bangla": return R.xml.bangla;
case "hindi": return R.xml.hindi;
case "bgph1": return R.xml.local_bgph1;
case "bone": return R.xml.bone;
case "colemak": return R.xml.colemak;
case "dvorak": return R.xml.dvorak;
case "neo2": return R.xml.neo2;
case "qwerty_es": return R.xml.qwerty_es;
case "qwerty_el": return R.xml.qwerty_el;
case "qwerty_hu": return R.xml.qwerty_hu;
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_tr": return R.xml.qwerty_tr;
case "qwerty": return R.xml.qwerty;
case "qwerty_no": return R.xml.qwerty_no;
case "qwerty_sv_se": return R.xml.qwerty_sv_se;
case "qwertz_hu": return R.xml.qwertz_hu;
case "qwertz_cs": return R.xml.qwertz_cs;
case "qwertz": return R.xml.qwertz;
case "ru_jcuken": return R.xml.local_ru_jcuken;
case "jcuken_ua": return R.xml.jcuken_ua;
default: return R.xml.qwerty; // The config might store an invalid layout, don't crash
}
}
public static int themeId_of_string(String name)
{
switch (name)
{
case "light": return R.style.Light;
case "black": return R.style.Black;
default: case "dark": return R.style.Dark;
}
}
private static Config _globalConfig = null;
public static void initGlobalConfig(Context context, IKeyEventHandler handler)
@@ -255,6 +286,6 @@ final class Config
public static interface IKeyEventHandler
{
public void handleKeyUp(KeyValue value, int flags);
public void handleKeyUp(KeyValue value, Pointers.Modifiers flags);
}
}

View File

@@ -8,19 +8,32 @@ import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.HashMap;
public class Emoji extends KeyValue
public class Emoji
{
private final String _name;
private final KeyValue _kv;
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);
_name = name;
_kv = new KeyValue(bytecode, KeyValue.KIND_STRING, 0, 0);
_desc = desc;
emojis_by_name.put(name, this);
}
public String name()
{
return _name;
}
public KeyValue kv()
{
return _kv;
}
public String getDescription()
{
return (_desc);

View File

@@ -55,7 +55,7 @@ public class EmojiGridView extends GridView
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);
config.handler.handleKeyUp(_emojiArray[pos].kv(), Pointers.Modifiers.EMPTY);
saveLastUsed(); // TODO: opti
}
@@ -88,7 +88,7 @@ public class EmojiGridView extends GridView
HashSet<String> set = new HashSet<String>();
for (Emoji emoji : _lastUsed.keySet())
set.add(String.valueOf(_lastUsed.get(emoji)) + "-" + emoji.name);
set.add(String.valueOf(_lastUsed.get(emoji)) + "-" + emoji.name());
edit.putStringSet(LAST_USE_PREF, set);
edit.apply();
}
@@ -126,7 +126,7 @@ public class EmojiGridView extends GridView
public void setEmoji(Emoji emoji)
{
setText(emoji.symbol);
setText(emoji.kv().getString());
}
}

View File

@@ -15,7 +15,7 @@ public class EmojiGroupButtonsBar extends LinearLayout
for (int i = 0; i < Emoji.num_groups; i++)
{
Emoji first = Emoji.getEmojisByGroup(i)[0];
add_group(i, first.symbol);
add_group(i, first.kv().getString());
}
}

View File

@@ -14,15 +14,16 @@ public class EmojiKeyButton extends Button
{
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));
String key_name = attrs.getAttributeValue(null, "key");
_key = (key_name == null) ? null : KeyValue.getKeyByName(key_name);
setText(_key.getString());
if (_key.hasFlags(KeyValue.FLAG_KEY_FONT))
setTypeface(Theme.getKeyFont(context));
}
public void onClick(View v)
{
Config config = Config.globalConfig();
config.handler.handleKeyUp(_key, 0);
config.handler.handleKeyUp(_key, Pointers.Modifiers.EMPTY);
}
}

View File

@@ -0,0 +1,89 @@
package juloo.keyboard2;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.SharedPreferences;
import android.preference.CheckBoxPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import java.util.HashSet;
import java.util.Set;
public class ExtraKeyCheckBoxPreference extends CheckBoxPreference
{
public static String[] extra_keys = new String[]
{
"alt",
"meta",
"accent_aigu",
"accent_grave",
"accent_double_aigu",
"accent_dot_above",
"accent_circonflexe",
"accent_tilde",
"accent_cedille",
"accent_trema",
"accent_ring",
"accent_caron",
"accent_macron",
"accent_ogonek",
"accent_breve",
"",
"ß",
"£",
"switch_greekmath",
};
public static boolean default_checked(String name)
{
switch (name)
{
case "alt":
case "meta":
return true;
default:
return false;
}
}
boolean _key_font;
public ExtraKeyCheckBoxPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ExtraKeyCheckBoxPreference);
int index = a.getInteger(R.styleable.ExtraKeyCheckBoxPreference_index, 0);
a.recycle();
String key_name = extra_keys[index];
setKey(pref_key_of_key_name(key_name));
setDefaultValue(default_checked(key_name));
KeyValue kv = KeyValue.getKeyByName(key_name);
setTitle(kv.getString());
_key_font = kv.hasFlags(KeyValue.FLAG_KEY_FONT);
}
@Override
protected void onBindView(View view)
{
super.onBindView(view);
TextView title = (TextView)view.findViewById(android.R.id.title);
title.setTypeface(_key_font ? Theme.getKeyFont(getContext()) : null);
}
static String pref_key_of_key_name(String key_name)
{
return "extra_key_" + key_name;
}
public static Set<KeyValue> get_extra_keys(SharedPreferences prefs)
{
HashSet<KeyValue> ks = new HashSet<KeyValue>();
for (String key_name : extra_keys)
{
if (prefs.getBoolean(pref_key_of_key_name(key_name), default_checked(key_name)))
ks.add(KeyValue.getKeyByName(key_name));
}
return ks;
}
}

View File

@@ -11,29 +11,37 @@ class KeyEventHandler implements Config.IKeyEventHandler
_recv = recv;
}
public void handleKeyUp(KeyValue key, int flags)
public void handleKeyUp(KeyValue key, Pointers.Modifiers mods)
{
if (key == null || (key.flags & KeyValue.FLAG_NOCHAR) != 0)
if (key == null)
return;
switch (key.eventCode)
switch (key.getKind())
{
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);
case Char:
_recv.commitChar(key.getChar());
break;
case String:
_recv.commitText(key.getString());
break;
case Event:
switch (key.getEvent())
{
case CONFIG: _recv.showKeyboardConfig(); break;
case SWITCH_TEXT: _recv.switchMain(); break;
case SWITCH_NUMERIC: _recv.switchNumeric(); break;
case SWITCH_EMOJI: _recv.setPane_emoji(); break;
case SWITCH_BACK_EMOJI: _recv.setPane_normal(); break;
case CHANGE_METHOD: _recv.switchToNextInputMethod(); break;
case ACTION: _recv.performAction(); break;
case SWITCH_PROGRAMMING: _recv.switchProgramming(); break;
case SWITCH_GREEKMATH: _recv.switchGreekmath(); break;
}
break;
case Keyevent:
handleKeyUpWithModifier(key.getKeyevent(), mods);
break;
case Modifier:
break;
}
}
@@ -57,31 +65,34 @@ class KeyEventHandler implements Config.IKeyEventHandler
return updatedMetaState;
}
/* Send key events corresponding to pressed modifier keys. */
private int sendMetaKeys(int flags, int metaState, boolean down)
private int sendMetaKeyForModifier(KeyValue.Modifier mod, 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;
switch (mod)
{
case CTRL:
return sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down);
case ALT:
return sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down);
case SHIFT:
return sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down);
case META:
return sendMetaKey(KeyEvent.KEYCODE_META_LEFT, KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_ON, metaState, down);
default: return metaState;
}
}
/*
* Don't set KeyEvent.FLAG_SOFT_KEYBOARD.
*/
private void handleKeyUpWithModifier(KeyValue key, int flags)
private void handleKeyUpWithModifier(int keyCode, Pointers.Modifiers mods)
{
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);
int metaState = 0;
for (int i = 0; i < mods.size(); i++)
metaState = sendMetaKeyForModifier(mods.get(i), metaState, true);
_recv.sendKeyEvent(KeyEvent.ACTION_DOWN, keyCode, metaState);
_recv.sendKeyEvent(KeyEvent.ACTION_UP, keyCode, metaState);
for (int i = mods.size() - 1; i >= 0; i--)
metaState = sendMetaKeyForModifier(mods.get(i), metaState, false);
}
public static interface IReceiver
@@ -95,6 +106,7 @@ class KeyEventHandler implements Config.IKeyEventHandler
public void switchMain();
public void switchNumeric();
public void switchProgramming();
public void switchGreekmath();
public void sendKeyEvent(int eventAction, int eventCode, int meta);

View File

@@ -1,6 +1,5 @@
package juloo.keyboard2;
import android.util.SparseArray;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import java.util.HashMap;
@@ -8,75 +7,381 @@ import java.util.HashMap;
class KeyModifier
{
/** Cache key is KeyValue's name */
private static HashMap<String, SparseArray<KeyValue>> _cache =
new HashMap<String, SparseArray<KeyValue>>();
/** Represents a removed key, because a cache entry can't be [null]. */
private static final KeyValue removed_key = KeyValue.getKeyByName("removed");
private static HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>> _cache =
new HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>>();
/** Modify a key according to modifiers. */
public static KeyValue handleFlags(KeyValue k, int flags)
public static KeyValue modify(KeyValue k, Pointers.Modifiers mods)
{
if (k == null)
return null;
SparseArray<KeyValue> ks = cacheEntry(k);
KeyValue r = ks.get(flags);
if (r == null) // Cold cache
int n_mods = mods.size();
HashMap<Pointers.Modifiers, KeyValue> ks = cacheEntry(k);
KeyValue r = ks.get(mods);
if (r == null)
{
r = k;
r = handleFn(r, flags);
r = handleShift(r, flags);
r = handleAccents(r, flags);
ks.put(flags, r);
/* Order: Fn, Shift, accents */
for (int i = 0; i < n_mods; i++)
r = modify(r, mods.get(i));
ks.put(mods, r);
}
return (r == removed_key) ? null : r;
/* Keys with an empty string are placeholder keys. */
return (r.getString().length() == 0) ? null : r;
}
private static KeyValue handleAccents(KeyValue k, int flags)
public static KeyValue modify(KeyValue k, KeyValue.Modifier mod)
{
if (k.char_ == KeyValue.CHAR_NONE || (flags & KeyValue.FLAGS_ACCENTS) == 0)
return k;
char c = handleAccentChar(k.char_, flags);
if (c == 0 || c == k.char_)
return k;
return k.withCharAndSymbol(c);
}
private static KeyValue handleShift(KeyValue k, int flags)
{
if ((flags & KeyValue.FLAG_SHIFT) == 0)
return k;
char c = k.char_;
if (k.char_ != KeyValue.CHAR_NONE)
c = Character.toUpperCase(c);
if (c == k.char_) // Used to have more rules if toUpperCase() did nothing
return k;
return k.withCharAndSymbol(c);
}
private static char handleAccentChar(char c, int flags)
{
switch ((flags & KeyValue.FLAGS_ACCENTS))
switch (mod)
{
case KeyValue.FLAG_ACCENT1:
return (char)KeyCharacterMap.getDeadChar('\u02CB', c);
case KeyValue.FLAG_ACCENT2:
return (char)KeyCharacterMap.getDeadChar('\u00B4', c);
case KeyValue.FLAG_ACCENT3:
return (char)KeyCharacterMap.getDeadChar('\u02C6', c);
case KeyValue.FLAG_ACCENT4:
return (char)KeyCharacterMap.getDeadChar('\u02DC', c);
case KeyValue.FLAG_ACCENT5:
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:
case CTRL:
case ALT:
case META: return turn_into_keyevent(k);
case FN: return apply_fn(k);
case SHIFT: return apply_shift(k);
case GRAVE: return apply_dead_char(k, '\u02CB');
case AIGU: return apply_dead_char(k, '\u00B4');
case CIRCONFLEXE: return apply_dead_char(k, '\u02C6');
case TILDE: return apply_dead_char(k, '\u02DC');
case CEDILLE: return apply_dead_char(k, '\u00B8');
case TREMA: return apply_dead_char(k, '\u00A8');
case CARON: return apply_dead_char(k, '\u02C7');
case RING: return apply_dead_char(k, '\u02DA');
case MACRON: return apply_dead_char(k, '\u00AF');
case OGONEK: return apply_dead_char(k, '\u02DB');
case DOT_ABOVE: return apply_dead_char(k, '\u02D9');
case BREVE: return apply_dead_char(k, '\u02D8');
case DOUBLE_AIGU: return apply_map_char(k, map_char_double_aigu);
case ORDINAL: return apply_map_char(k, map_char_ordinal);
case SUPERSCRIPT: return apply_map_char(k, map_char_superscript);
case SUBSCRIPT: return apply_map_char(k, map_char_subscript);
case ARROWS: return apply_map_char(k, map_char_arrows);
case BOX: return apply_map_char(k, map_char_box);
case SLASH: return apply_map_char(k, map_char_slash);
case ARROW_RIGHT: return apply_combining(k, "\u20D7");
default: return k;
}
}
private static KeyValue apply_map_char(KeyValue k, Map_char map)
{
switch (k.getKind())
{
case Char:
char kc = k.getChar();
char c = map.apply(kc);
return (kc == c) ? k : k.withChar(c);
default: return k;
}
}
private static KeyValue apply_dead_char(KeyValue k, char dead_char)
{
switch (k.getKind())
{
case Char:
char kc = k.getChar();
char c = (char)KeyCharacterMap.getDeadChar(dead_char, kc);
return (c == 0 || kc == c) ? k : k.withChar(c);
default: return k;
}
}
private static KeyValue apply_combining(KeyValue k, String combining)
{
switch (k.getKind())
{
case Char:
return k.withString(String.valueOf(k.getChar()) + combining);
default: return k;
}
}
private static KeyValue apply_shift(KeyValue k)
{
switch (k.getKind())
{
case Char:
char kc = k.getChar();
char c = map_char_shift(kc);
if (kc == c)
c = Character.toUpperCase(kc);
return (kc == c) ? k : k.withChar(c);
case String:
return k.withString(k.getString().toUpperCase());
default: return k;
}
}
private static KeyValue apply_fn(KeyValue k)
{
String name = null;
switch (k.getKind())
{
case Char: name = apply_fn_char(k.getChar()); break;
case Keyevent: name = apply_fn_keyevent(k.getKeyevent()); break;
case Event: name = apply_fn_event(k.getEvent()); break;
case String:
switch (k.getString())
{
case "":
if (k == KeyValue.getKeyByName("f11_placeholder"))
name = "f11";
else if (k == KeyValue.getKeyByName("f12_placeholder"))
name = "f12";
break;
}
break;
}
return (name == null) ? k : KeyValue.getKeyByName(name);
}
private static String apply_fn_keyevent(int code)
{
switch (code)
{
case KeyEvent.KEYCODE_DPAD_UP: return "page_up";
case KeyEvent.KEYCODE_DPAD_DOWN: return "page_down";
case KeyEvent.KEYCODE_DPAD_LEFT: return "home";
case KeyEvent.KEYCODE_DPAD_RIGHT: return "end";
case KeyEvent.KEYCODE_ESCAPE: return "insert";
case KeyEvent.KEYCODE_TAB: return "\\t";
default: return null;
}
}
private static String apply_fn_event(KeyValue.Event ev)
{
switch (ev)
{
case SWITCH_NUMERIC: return "switch_greekmath";
default: return null;
}
}
/** Return the name of modified key, or [null]. */
private static String apply_fn_char(char c)
{
switch (c)
{
case '1': return "f1";
case '2': return "f2";
case '3': return "f3";
case '4': return "f4";
case '5': return "f5";
case '6': return "f6";
case '7': return "f7";
case '8': return "f8";
case '9': return "f9";
case '0': return "f10";
case '<': return "«";
case '>': return "»";
case '{': return "";
case '}': return "";
case '[': return "";
case ']': return "";
case '(': return "";
case ')': return "";
case '\'': return "";
case '"': return "";
case '-': return "";
case '_': return "";
case '^': return "¬";
case '%': return "";
case '=': return "";
case 'u': return "µ";
case 'a': return "æ";
case 'o': return "œ";
case '*': return "°";
case '.': return "";
case ',': return "·";
case '!': return "¡";
case '?': return "¿";
// arrows
case '↖': return "";
case '↑': return "";
case '↗': return "";
case '←': return "";
case '→': return "";
case '↙': return "";
case '↓': return "";
case '↘': return "";
case '↔': return "";
case '↕': return "";
// Currency symbols
case 'e': return "";
case 'l': return "£";
case 'r': return "";
case 'y': return "¥";
case 'c': return "¢";
case 'p': return "";
case '€': case '£': return "removed"; // Avoid showing these twice
// alternating greek letters
case 'π': return "ϖ";
case 'θ': return "ϑ";
case 'Θ': return "ϴ";
case 'ε': return "ϵ";
case 'β': return "ϐ";
case 'ρ': return "ϱ";
case 'σ': return "ς";
case 'γ': return "ɣ";
case 'φ': return "ϕ";
case 'υ': return "ϒ";
case 'κ': return "ϰ";
// alternating math characters
case '': return "";
case '∩': return "";
case '∃': return "";
case '∈': return "";
case '∫': return "";
case 'Π': return "";
case 'Σ': return "";
case '': return "";
case '∧': return "";
case '⊷': return "";
case '⊂': return "";
case '⊃': return "";
case '±': return "";
// other
case ' ': return "nbsp";
default: return null;
}
}
private static KeyValue turn_into_keyevent(KeyValue k)
{
if (k.getKind() != KeyValue.Kind.Char)
return k;
int e;
switch (k.getChar())
{
case 'a': e = KeyEvent.KEYCODE_A; break;
case 'b': e = KeyEvent.KEYCODE_B; break;
case 'c': e = KeyEvent.KEYCODE_C; break;
case 'd': e = KeyEvent.KEYCODE_D; break;
case 'e': e = KeyEvent.KEYCODE_E; break;
case 'f': e = KeyEvent.KEYCODE_F; break;
case 'g': e = KeyEvent.KEYCODE_G; break;
case 'h': e = KeyEvent.KEYCODE_H; break;
case 'i': e = KeyEvent.KEYCODE_I; break;
case 'j': e = KeyEvent.KEYCODE_J; break;
case 'k': e = KeyEvent.KEYCODE_K; break;
case 'l': e = KeyEvent.KEYCODE_L; break;
case 'm': e = KeyEvent.KEYCODE_M; break;
case 'n': e = KeyEvent.KEYCODE_N; break;
case 'o': e = KeyEvent.KEYCODE_O; break;
case 'p': e = KeyEvent.KEYCODE_P; break;
case 'q': e = KeyEvent.KEYCODE_Q; break;
case 'r': e = KeyEvent.KEYCODE_R; break;
case 's': e = KeyEvent.KEYCODE_S; break;
case 't': e = KeyEvent.KEYCODE_T; break;
case 'u': e = KeyEvent.KEYCODE_U; break;
case 'v': e = KeyEvent.KEYCODE_V; break;
case 'w': e = KeyEvent.KEYCODE_W; break;
case 'x': e = KeyEvent.KEYCODE_X; break;
case 'y': e = KeyEvent.KEYCODE_Y; break;
case 'z': e = KeyEvent.KEYCODE_Z; break;
case '0': e = KeyEvent.KEYCODE_0; break;
case '1': e = KeyEvent.KEYCODE_1; break;
case '2': e = KeyEvent.KEYCODE_2; break;
case '3': e = KeyEvent.KEYCODE_3; break;
case '4': e = KeyEvent.KEYCODE_4; break;
case '5': e = KeyEvent.KEYCODE_5; break;
case '6': e = KeyEvent.KEYCODE_6; break;
case '7': e = KeyEvent.KEYCODE_7; break;
case '8': e = KeyEvent.KEYCODE_8; break;
case '9': e = KeyEvent.KEYCODE_9; break;
case '`': e = KeyEvent.KEYCODE_GRAVE; break;
case '-': e = KeyEvent.KEYCODE_MINUS; break;
case '=': e = KeyEvent.KEYCODE_EQUALS; break;
case '[': e = KeyEvent.KEYCODE_LEFT_BRACKET; break;
case ']': e = KeyEvent.KEYCODE_RIGHT_BRACKET; break;
case '\\': e = KeyEvent.KEYCODE_BACKSLASH; break;
case ';': e = KeyEvent.KEYCODE_SEMICOLON; break;
case '\'': e = KeyEvent.KEYCODE_APOSTROPHE; break;
case '/': e = KeyEvent.KEYCODE_SLASH; break;
case '@': e = KeyEvent.KEYCODE_AT; break;
case '+': e = KeyEvent.KEYCODE_PLUS; break;
case ',': e = KeyEvent.KEYCODE_COMMA; break;
case '.': e = KeyEvent.KEYCODE_PERIOD; break;
case '*': e = KeyEvent.KEYCODE_STAR; break;
case '#': e = KeyEvent.KEYCODE_POUND; break;
case '(': e = KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN; break;
case ')': e = KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN; break;
case ' ': e = KeyEvent.KEYCODE_SPACE; break;
default: return k;
}
return k.withKeyevent(e);
}
/* Lookup the cache entry for a key. Create it needed. */
private static HashMap<Pointers.Modifiers, KeyValue> cacheEntry(KeyValue k)
{
HashMap<Pointers.Modifiers, KeyValue> ks = _cache.get(k);
if (ks == null)
{
ks = new HashMap<Pointers.Modifiers, KeyValue>();
_cache.put(k, ks);
}
return ks;
}
private static abstract class Map_char
{
public abstract char apply(char c);
}
private static char map_char_shift(char c)
{
switch (c)
{
case '↙': return '⇙';
case '↓': return '⇓';
case '↘': return '⇘';
case '←': return '⇐';
case '→': return '⇒';
case '↖': return '⇖';
case '↑': return '⇑';
case '↗': return '⇗';
case '└': return '╚';
case '┴': return '╩';
case '┘': return '╝';
case '├': return '╠';
case '┼': return '╬';
case '┤': return '╣';
case '┌': return '╔';
case '┬': return '╦';
case '┐': return '╗';
case '─': return '═';
case '│': return '║';
case 'ß': return 'ẞ';
/* In Turkish, upper case of 'iı' is 'İI' but Java's toUpperCase will
return 'II'. To make 'İ' accessible, make it the shift of 'ı'. This
has the inconvenient of swapping i and ı on the keyboard. */
case 'ı': return 'İ';
default: return c;
}
}
private static final Map_char map_char_double_aigu =
new Map_char() {
public char apply(char c)
{
switch (c)
{
// Composite characters: a̋ e̋ i̋ m̋ ӳ
case 'o': return 'ő';
case 'u': return 'ű';
case ' ': return '˝';
default: return c;
}
}
};
private static final Map_char map_char_ordinal =
new Map_char() {
public char apply(char c)
{
switch (c)
{
case 'a': return 'ª';
@@ -93,7 +398,13 @@ class KeyModifier
case '*': return '°';
default: return c;
}
case KeyValue.FLAG_ACCENT_SUPERSCRIPT:
}
};
private static final Map_char map_char_superscript =
new Map_char() {
public char apply(char c)
{
switch (c)
{
case '1': return '¹';
@@ -115,7 +426,13 @@ class KeyModifier
case 'n': return 'ⁿ';
default: return c;
}
case KeyValue.FLAG_ACCENT_SUBSCRIPT:
}
};
private static final Map_char map_char_subscript =
new Map_char() {
public char apply(char c)
{
switch (c)
{
case '1': return '₁';
@@ -139,165 +456,66 @@ 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
}
}
private static KeyValue handleFn(KeyValue k, int flags)
{
if ((flags & KeyValue.FLAG_FN) == 0)
{
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)
{
case "1": name = "f1"; break;
case "2": name = "f2"; break;
case "3": name = "f3"; break;
case "4": name = "f4"; break;
case "5": name = "f5"; break;
case "6": name = "f6"; break;
case "7": name = "f7"; break;
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 "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);
}
};
/* Lookup the cache entry for a key. Create it needed. */
private static SparseArray<KeyValue> cacheEntry(KeyValue k)
{
SparseArray<KeyValue> ks = _cache.get(k.name);
if (ks == null)
{
ks = new SparseArray<KeyValue>();
_cache.put(k.name, ks);
}
return ks;
}
private static final Map_char map_char_arrows =
new Map_char() {
public char apply(char c)
{
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;
}
}
};
private static final Map_char map_char_box =
new Map_char() {
public char apply(char c)
{
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;
}
}
};
private static final Map_char map_char_slash =
new Map_char() {
public char apply(char c)
{
switch (c)
{
case 'a': return 'ⱥ';
case 'c': return 'ȼ';
case 'e': return 'ɇ';
case 'g': return 'ꞡ';
case 'l': return 'ł';
case 'n': return 'ꞥ';
case 'o': return 'ø';
case ' ': return '/';
default: return c;
}
}
};
}

View File

@@ -4,274 +4,330 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import java.util.HashMap;
class KeyValue
final 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 int EVENT_ACTION = -8;
public static final int EVENT_SWITCH_PROGRAMMING = -9;
public static final char CHAR_NONE = '\0';
public static enum Event
{
CONFIG,
SWITCH_TEXT,
SWITCH_NUMERIC,
SWITCH_EMOJI,
SWITCH_BACK_EMOJI,
CHANGE_METHOD,
ACTION,
SWITCH_PROGRAMMING,
SWITCH_GREEKMATH
}
// Behavior flags
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);
// Must be evaluated in the reverse order of their values.
public static enum Modifier
{
SHIFT,
FN,
CTRL,
ALT,
META,
DOUBLE_AIGU,
DOT_ABOVE,
GRAVE,
AIGU,
CIRCONFLEXE,
TILDE,
CEDILLE,
TREMA,
SUPERSCRIPT,
SUBSCRIPT,
RING,
CARON,
MACRON,
ORDINAL,
ARROWS,
BOX,
OGONEK,
SLASH,
ARROW_RIGHT,
BREVE
}
// Rendering flags
public static final int FLAG_KEY_FONT = (1 << 5);
public static final int FLAG_SMALLER_FONT = (1 << 6);
// Behavior flags.
public static final int FLAG_LATCH = (1 << 20);
public static final int FLAG_LOCK = (1 << 21);
// Special keys are not repeated and don't clear latched modifiers.
public static final int FLAG_SPECIAL = (1 << 22);
public static final int FLAG_PRECISE_REPEAT = (1 << 23);
// Rendering flags.
public static final int FLAG_KEY_FONT = (1 << 24);
public static final int FLAG_SMALLER_FONT = (1 << 25);
// Used by [Pointers].
public static final int FLAG_LOCKED = (1 << 26);
public static final int FLAG_FAKE_PTR = (1 << 27);
// Internal flags
public static final int FLAG_LOCKED = (1 << 8);
// Kinds
public static final int KIND_CHAR = (0 << 29);
public static final int KIND_STRING = (1 << 29);
public static final int KIND_KEYEVENT = (2 << 29);
public static final int KIND_EVENT = (3 << 29);
public static final int KIND_MODIFIER = (4 << 29);
// Modifier flags
public static final int FLAG_CTRL = (1 << 10);
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);
// Ranges for the different components
private static final int FLAGS_BITS = (0b111111111 << 20); // 9 bits wide
private static final int KIND_BITS = (0b111 << 29); // 3 bits wide
private static final int VALUE_BITS = ~(FLAGS_BITS | KIND_BITS); // 20 bits wide
static
{
check((FLAGS_BITS & KIND_BITS) == 0); // No overlap
check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes
}
// Accent flags
public static final int FLAG_ACCENT1 = (1 << 16); // Grave
public static final int FLAG_ACCENT2 = (1 << 17); // Aigu
public static final int FLAG_ACCENT3 = (1 << 18); // Circonflexe
public static final int FLAG_ACCENT4 = (1 << 19); // Tilde
public static final int FLAG_ACCENT5 = (1 << 20); // Cédille
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);
private final String _symbol;
public static final int FLAGS_ACCENTS = FLAG_ACCENT1 | FLAG_ACCENT2 |
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
FLAG_ACCENT_CARON | FLAG_ACCENT_MACRON | FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL | FLAG_ACCENT_ARROWS |
FLAG_ACCENT_BOX | FLAG_ACCENT_RING;
/** This field encodes three things:
- The kind
- The flags
- The value for Char, Event and Modifier keys.
*/
private final int _code;
// Language specific keys that are removed from the keyboard by default
public static final int FLAG_LOCALIZED = (1 << 25);
public static enum Kind
{
Char, String, Keyevent, Event, Modifier
}
public final String name;
public final String symbol;
public final char char_;
public final int eventCode;
public final int flags;
public Kind getKind()
{
switch (_code & KIND_BITS)
{
case KIND_CHAR: return Kind.Char;
case KIND_STRING: return Kind.String;
case KIND_KEYEVENT: return Kind.Keyevent;
case KIND_EVENT: return Kind.Event;
case KIND_MODIFIER: return Kind.Modifier;
default: throw new RuntimeException("Corrupted kind flags");
}
}
public int getFlags()
{
return (_code & FLAGS_BITS);
}
public boolean hasFlags(int has)
{
return ((_code & has) == has);
}
/** The string to render on the keyboard.
When [getKind() == Kind.String], also the string to send. */
public String getString()
{
return _symbol;
}
/** Defined only when [getKind() == Kind.Char]. */
public char getChar()
{
return (char)(_code & VALUE_BITS);
}
/** Defined only when [getKind() == Kind.Keyevent]. */
public int getKeyevent()
{
return (_code & VALUE_BITS);
}
/** Defined only when [getKind() == Kind.Event]. */
public Event getEvent()
{
return Event.values()[(_code & VALUE_BITS)];
}
/** Defined only when [getKind() == Kind.Modifier]. */
public Modifier getModifier()
{
return Modifier.values()[(_code & VALUE_BITS)];
}
/* Update the char and the symbol. */
public KeyValue withCharAndSymbol(char c)
public KeyValue withChar(char c)
{
return withCharAndSymbol(String.valueOf(c), c);
return new KeyValue(String.valueOf(c), KIND_CHAR, c, getFlags());
}
public KeyValue withCharAndSymbol(String s, char c)
public KeyValue withString(String s)
{
return new KeyValue(name, s, c, eventCode, flags);
return new KeyValue(s, KIND_STRING, 0, getFlags());
}
public KeyValue withNameAndSymbol(String n, String s)
public KeyValue withSymbol(String s)
{
return new KeyValue(n, s, char_, eventCode, flags);
return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags());
}
public KeyValue withKeyevent(int code)
{
return new KeyValue(_symbol, KIND_KEYEVENT, code, getFlags());
}
public KeyValue withFlags(int f)
{
return new KeyValue(name, symbol, char_, eventCode, f);
return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f);
}
@Override
public boolean equals(Object obj)
{
KeyValue snd = (KeyValue)obj;
return _symbol.equals(snd._symbol) && _code == snd._code;
}
@Override
public int hashCode()
{
return _symbol.hashCode() + _code;
}
private static HashMap<String, KeyValue> keys = new HashMap<String, KeyValue>();
public KeyValue(String n, String s, char c, int e, int f)
public KeyValue(String s, int kind, int value, int flags)
{
name = n;
symbol = s;
char_ = c;
eventCode = e;
flags = f;
check((kind & ~KIND_BITS) == 0);
check((flags & ~FLAGS_BITS) == 0);
check((value & ~VALUE_BITS) == 0);
_symbol = s;
_code = kind | flags | value;
}
public static KeyValue getKeyByName(String name)
{
if (name == null)
return null;
KeyValue kv = KeyValue.keys.get(name);
KeyValue kv = keys.get(name);
if (kv != null)
return kv;
char c = (name.length() == 1) ? name.charAt(0) : CHAR_NONE;
return new KeyValue(name, name, c, EVENT_NONE, 0);
if (name.length() == 1)
return new KeyValue(name, KIND_CHAR, name.charAt(0), 0);
else
return new KeyValue(name, KIND_STRING, 0, 0);
}
private static void addKey(String name, String symbol, char c, int event, int flags)
private static void addKey(String name, String symbol, int kind, int code, int flags)
{
keys.put(name, new KeyValue(name, symbol, c, event, flags));
keys.put(name, new KeyValue(symbol, kind, code, flags));
}
private static void addCharKey(char c, int event, int flags)
private static void addCharKey(String name, String symbol, char c, int flags)
{
String name = String.valueOf(c);
addKey(name, name, c, event, flags);
addKey(name, symbol, KIND_CHAR, c, flags);
}
private static void addCharKey(char c, int event)
private static void addModifierKey(String name, String symbol, Modifier m, int extra_flags)
{
addCharKey(c, event, 0);
addKey(name, symbol, KIND_MODIFIER, m.ordinal(),
FLAG_LATCH | FLAG_SPECIAL | extra_flags);
}
private static void addModifierKey(String name, String symbol, int extra_flags)
private static void addDiacritic(String name, int special_font_symbol, Modifier m)
{
addKey(name, symbol, CHAR_NONE, EVENT_NONE,
FLAG_LATCH | FLAG_NOCHAR | FLAG_NOREPEAT | extra_flags);
addModifierKey(name, String.valueOf((char)special_font_symbol), m, FLAG_KEY_FONT);
}
private static void addSpecialKey(String name, String symbol, int event)
private static void addEventKey(String name, String symbol, Event e, int flags)
{
addSpecialKey(name, symbol, event, 0);
addKey(name, symbol, KIND_EVENT, e.ordinal(), flags | FLAG_SPECIAL);
}
private static void addSpecialKey(String name, String symbol, int event, int flags)
private static void addKeyeventKey(String name, String symbol, int code, int flags)
{
addKey(name, symbol, CHAR_NONE, event, flags | FLAG_NOREPEAT);
addKey(name, symbol, KIND_KEYEVENT, code, flags);
}
private static void addEventKey(String name, String symbol, int event)
{
addEventKey(name, symbol, event, 0);
}
// Within VALUE_BITS
private static int placeholder_unique_id = 0;
private static void addEventKey(String name, String symbol, int event, int flags)
/** Use a unique id as the value because the symbol is shared between every
placeholders (it is the empty string). */
private static void addPlaceholderKey(String name)
{
addKey(name, symbol, CHAR_NONE, event, flags);
addKey(name, "", KIND_STRING, placeholder_unique_id++, 0);
}
static
{
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);
Modifier.SHIFT, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addModifierKey("ctrl", "Ctrl", Modifier.CTRL, FLAG_SMALLER_FONT);
addModifierKey("alt", "Alt", Modifier.ALT, FLAG_SMALLER_FONT);
addDiacritic("accent_aigu", 0x50, Modifier.AIGU);
addDiacritic("accent_caron", 0x51, Modifier.CARON);
addDiacritic("accent_cedille", 0x52, Modifier.CEDILLE);
addDiacritic("accent_circonflexe", 0x53, Modifier.CIRCONFLEXE);
addDiacritic("accent_grave", 0x54, Modifier.GRAVE);
addDiacritic("accent_macron", 0x55, Modifier.MACRON);
addDiacritic("accent_ring", 0x56, Modifier.RING);
addDiacritic("accent_tilde", 0x57, Modifier.TILDE);
addDiacritic("accent_trema", 0x58, Modifier.TREMA);
addDiacritic("accent_ogonek", 0x59, Modifier.OGONEK);
addDiacritic("accent_dot_above", 0x5A, Modifier.DOT_ABOVE);
addDiacritic("accent_double_aigu", 0x5B, Modifier.DOUBLE_AIGU);
addDiacritic("accent_slash", 0x5C, Modifier.SLASH);
addDiacritic("accent_arrow_right", 0x5D, Modifier.ARROW_RIGHT);
addDiacritic("accent_breve", 0x5E, Modifier.BREVE);
addModifierKey("superscript", "Sup", Modifier.SUPERSCRIPT, FLAG_SMALLER_FONT);
addModifierKey("subscript", "Sub", Modifier.SUBSCRIPT, FLAG_SMALLER_FONT);
addModifierKey("ordinal", "Ord", Modifier.ORDINAL, FLAG_SMALLER_FONT);
addModifierKey("arrows", "Arr", Modifier.ARROWS, FLAG_SMALLER_FONT);
addModifierKey("box", "Box", Modifier.BOX, FLAG_SMALLER_FONT);
addModifierKey("fn", "Fn", Modifier.FN, FLAG_SMALLER_FONT);
addModifierKey("meta", "Meta", Modifier.META, FLAG_SMALLER_FONT);
addCharKey('a', KeyEvent.KEYCODE_A);
addCharKey('b', KeyEvent.KEYCODE_B);
addCharKey('c', KeyEvent.KEYCODE_C);
addCharKey('d', KeyEvent.KEYCODE_D);
addCharKey('e', KeyEvent.KEYCODE_E);
addCharKey('f', KeyEvent.KEYCODE_F);
addCharKey('g', KeyEvent.KEYCODE_G);
addCharKey('h', KeyEvent.KEYCODE_H);
addCharKey('i', KeyEvent.KEYCODE_I);
addCharKey('j', KeyEvent.KEYCODE_J);
addCharKey('k', KeyEvent.KEYCODE_K);
addCharKey('l', KeyEvent.KEYCODE_L);
addCharKey('m', KeyEvent.KEYCODE_M);
addCharKey('n', KeyEvent.KEYCODE_N);
addCharKey('o', KeyEvent.KEYCODE_O);
addCharKey('p', KeyEvent.KEYCODE_P);
addCharKey('q', KeyEvent.KEYCODE_Q);
addCharKey('r', KeyEvent.KEYCODE_R);
addCharKey('s', KeyEvent.KEYCODE_S);
addCharKey('t', KeyEvent.KEYCODE_T);
addCharKey('u', KeyEvent.KEYCODE_U);
addCharKey('v', KeyEvent.KEYCODE_V);
addCharKey('w', KeyEvent.KEYCODE_W);
addCharKey('x', KeyEvent.KEYCODE_X);
addCharKey('y', KeyEvent.KEYCODE_Y);
addCharKey('z', KeyEvent.KEYCODE_Z);
addCharKey('0', KeyEvent.KEYCODE_0);
addCharKey('1', KeyEvent.KEYCODE_1);
addCharKey('2', KeyEvent.KEYCODE_2);
addCharKey('3', KeyEvent.KEYCODE_3);
addCharKey('4', KeyEvent.KEYCODE_4);
addCharKey('5', KeyEvent.KEYCODE_5);
addCharKey('6', KeyEvent.KEYCODE_6);
addCharKey('7', KeyEvent.KEYCODE_7);
addCharKey('8', KeyEvent.KEYCODE_8);
addCharKey('9', KeyEvent.KEYCODE_9);
addCharKey('`', KeyEvent.KEYCODE_GRAVE);
addCharKey('-', KeyEvent.KEYCODE_MINUS);
addCharKey('=', KeyEvent.KEYCODE_EQUALS);
addCharKey('[', KeyEvent.KEYCODE_LEFT_BRACKET);
addCharKey(']', KeyEvent.KEYCODE_RIGHT_BRACKET);
addCharKey('\\', KeyEvent.KEYCODE_BACKSLASH);
addCharKey(';', KeyEvent.KEYCODE_SEMICOLON);
addCharKey('\'', KeyEvent.KEYCODE_APOSTROPHE);
addCharKey('/', KeyEvent.KEYCODE_SLASH);
addCharKey('@', KeyEvent.KEYCODE_AT);
addCharKey('+', KeyEvent.KEYCODE_PLUS);
addCharKey(',', KeyEvent.KEYCODE_COMMA);
addCharKey('.', KeyEvent.KEYCODE_PERIOD);
addCharKey('*', KeyEvent.KEYCODE_STAR);
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);
addEventKey("config", "\u0004", Event.CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addEventKey("switch_text", "ABC", Event.SWITCH_TEXT, FLAG_SMALLER_FONT);
addEventKey("switch_numeric", "123+", Event.SWITCH_NUMERIC, FLAG_SMALLER_FONT);
addEventKey("switch_emoji", "\u0001" , Event.SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addEventKey("switch_back_emoji", "ABC", Event.SWITCH_BACK_EMOJI, 0);
addEventKey("switch_programming", "Prog", Event.SWITCH_PROGRAMMING, FLAG_SMALLER_FONT);
addEventKey("switch_greekmath", "πλ∇¬", Event.SWITCH_GREEKMATH, FLAG_SMALLER_FONT);
addEventKey("change_method", "\u0009", Event.CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addEventKey("action", "Action", Event.ACTION, FLAG_SMALLER_FONT); // Will always be replaced
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("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
addKeyeventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
addKeyeventKey("enter", "\u000E", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
addKeyeventKey("up", "\u0005", KeyEvent.KEYCODE_DPAD_UP, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addKeyeventKey("right", "\u0006", KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addKeyeventKey("down", "\u0007", KeyEvent.KEYCODE_DPAD_DOWN, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addKeyeventKey("left", "\u0008", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addKeyeventKey("page_up", "\u0002", KeyEvent.KEYCODE_PAGE_UP, FLAG_KEY_FONT);
addKeyeventKey("page_down", "\u0003", KeyEvent.KEYCODE_PAGE_DOWN, FLAG_KEY_FONT);
addKeyeventKey("home", "\u000B", KeyEvent.KEYCODE_MOVE_HOME, FLAG_KEY_FONT);
addKeyeventKey("end", "\u000C", KeyEvent.KEYCODE_MOVE_END, FLAG_KEY_FONT);
addKeyeventKey("backspace", "\u0011", KeyEvent.KEYCODE_DEL, FLAG_KEY_FONT);
addKeyeventKey("delete", "\u0010", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_KEY_FONT);
addKeyeventKey("insert", "Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT);
addKeyeventKey("f1", "F1", KeyEvent.KEYCODE_F1, 0);
addKeyeventKey("f2", "F2", KeyEvent.KEYCODE_F2, 0);
addKeyeventKey("f3", "F3", KeyEvent.KEYCODE_F3, 0);
addKeyeventKey("f4", "F4", KeyEvent.KEYCODE_F4, 0);
addKeyeventKey("f5", "F5", KeyEvent.KEYCODE_F5, 0);
addKeyeventKey("f6", "F6", KeyEvent.KEYCODE_F6, 0);
addKeyeventKey("f7", "F7", KeyEvent.KEYCODE_F7, 0);
addKeyeventKey("f8", "F8", KeyEvent.KEYCODE_F8, 0);
addKeyeventKey("f9", "F9", KeyEvent.KEYCODE_F9, 0);
addKeyeventKey("f10", "F10", KeyEvent.KEYCODE_F10, 0);
addKeyeventKey("f11", "F11", KeyEvent.KEYCODE_F11, FLAG_SMALLER_FONT);
addKeyeventKey("f12", "F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT);
addKeyeventKey("tab", "\u000F", KeyEvent.KEYCODE_TAB, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
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);
addEventKey("f4", "F4", KeyEvent.KEYCODE_F4);
addEventKey("f5", "F5", KeyEvent.KEYCODE_F5);
addEventKey("f6", "F6", KeyEvent.KEYCODE_F6);
addEventKey("f7", "F7", KeyEvent.KEYCODE_F7);
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);
addCharKey("\\t", "\\t", '\t', 0); // Send the tab character
addCharKey("space", "\r", ' ', FLAG_KEY_FONT);
addCharKey("nbsp", "\u237d", '\u00a0', FLAG_KEY_FONT | FLAG_SMALLER_FONT);
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);
addPlaceholderKey("removed");
addPlaceholderKey("f11_placeholder");
addPlaceholderKey("f12_placeholder");
}
// Substitute for [assert], which has no effect on Android.
private static void check(boolean b)
{
if (!b)
throw new RuntimeException("Assertion failure");
}
}

View File

@@ -20,12 +20,14 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.util.Log;
import android.util.LogPrinter;
import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener
implements SharedPreferences.OnSharedPreferenceChangeListener,
Autocapitalisation.Callback
{
static private final String TAG = "Keyboard2";
@@ -34,6 +36,7 @@ public class Keyboard2 extends InputMethodService
private ViewGroup _emojiPane = null;
private Config _config;
private Autocapitalisation _autocap;
private boolean _debug_logs = false;
@@ -54,6 +57,15 @@ public class Keyboard2 extends InputMethodService
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_keyboardView.reset();
_debug_logs = getResources().getBoolean(R.bool.debug_logs);
_autocap = new Autocapitalisation(getMainLooper(), this);
}
public void update_shift_state(boolean should_enable, boolean should_disable)
{
if (should_enable)
_keyboardView.set_shift_state(true);
else if (should_disable)
_keyboardView.set_shift_state(false);
}
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
@@ -62,7 +74,7 @@ public class Keyboard2 extends InputMethodService
for (InputMethodInfo imi : imm.getEnabledInputMethodList())
if (imi.getPackageName().equals(pkg))
return imm.getEnabledInputMethodSubtypeList(imi, true);
return null;
return Arrays.asList();
}
private void refreshSubtypeLayout(InputMethodSubtype subtype)
@@ -79,23 +91,24 @@ public class Keyboard2 extends InputMethodService
_currentTextLayout = l;
}
private void extra_keys_of_subtype(Set<String> dst, InputMethodSubtype subtype)
private void extra_keys_of_subtype(Set<KeyValue> dst, InputMethodSubtype subtype)
{
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]);
dst.add(KeyValue.getKeyByName(ks[i]));
}
private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype)
{
HashSet<String> extra_keys = new HashSet<String>();
HashSet<KeyValue> extra_keys = new HashSet<KeyValue>();
List<InputMethodSubtype> enabled_subtypes = getEnabledSubtypes(imm);
switch (_config.accents)
{
case 1:
// '3' was "all accents", now unused
case 1: case 3:
extra_keys_of_subtype(extra_keys, subtype);
for (InputMethodSubtype s : enabled_subtypes)
extra_keys_of_subtype(extra_keys, s);
@@ -103,11 +116,10 @@ public class Keyboard2 extends InputMethodService
case 2:
extra_keys_of_subtype(extra_keys, subtype);
break;
case 3: extra_keys = null; break;
case 4: break;
default: throw new IllegalArgumentException();
}
_config.extra_keys = extra_keys;
_config.extra_keys_subtype = extra_keys;
if (enabled_subtypes.size() > 1)
_config.shouldOfferSwitchingToNextInputMethod = true;
}
@@ -117,8 +129,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.extra_keys = null; break;
case 4: _config.extra_keys = new HashSet<String>(); break;
case 1: case 2: case 3: _config.extra_keys_subtype = null; break;
case 4: _config.extra_keys_subtype = new HashSet<KeyValue>(); break;
}
// Fallback for the layout option: Use qwerty in the "system settings" case
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
@@ -136,8 +148,16 @@ public class Keyboard2 extends InputMethodService
else
{
InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
refreshSubtypeLayout(subtype);
refreshAccentsOption(imm, subtype);
if (subtype == null)
{
// On some rare cases, [subtype] is null.
refreshSubtypeLegacyFallback();
}
else
{
refreshSubtypeLayout(subtype);
refreshAccentsOption(imm, subtype);
}
}
_config.shouldOfferSwitchingToProgramming =
_config.programming_layout != -1 &&
@@ -162,7 +182,7 @@ public class Keyboard2 extends InputMethodService
return getResources().getString(res);
}
private void refreshEditorInfo(EditorInfo info)
private void refresh_action_label(EditorInfo info)
{
// First try to look at 'info.actionLabel', if it isn't set, look at
// 'imeOptions'.
@@ -209,11 +229,12 @@ public class Keyboard2 extends InputMethodService
public void onStartInputView(EditorInfo info, boolean restarting)
{
refreshConfig();
refreshEditorInfo(info);
refresh_action_label(info);
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
else
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
_autocap.started(info, getCurrentInputConnection());
setInputView(_keyboardView);
if (_debug_logs)
log_editor_info(info);
@@ -235,6 +256,13 @@ public class Keyboard2 extends InputMethodService
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
}
@Override
public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd)
{
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
_autocap.selection_updated(oldSelStart, newSelStart);
}
@Override
public void onFinishInputView(boolean finishingInput)
{
@@ -248,6 +276,13 @@ public class Keyboard2 extends InputMethodService
refreshConfig();
}
@Override
public boolean onEvaluateFullscreenMode()
{
/* Entirely disable fullscreen mode. */
return false;
}
/** Not static */
public class Receiver implements KeyEventHandler.IReceiver
{
@@ -289,15 +324,21 @@ public class Keyboard2 extends InputMethodService
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
}
public void switchGreekmath()
{
_keyboardView.setKeyboard(getLayout(R.xml.greekmath));
}
public void switchProgramming()
{
if (_config.programming_layout == -1)
return;
KeyboardData layout =
getLayout(_config.programming_layout).replaceKeys(new KeyboardData.MapKeys() {
public KeyValue apply(KeyValue key)
getLayout(_config.programming_layout).mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
if (key != null && key.eventCode == KeyValue.EVENT_SWITCH_PROGRAMMING)
if (key.getKind() == KeyValue.Kind.Event
&& key.getEvent() == KeyValue.Event.SWITCH_PROGRAMMING)
return KeyValue.getKeyByName("switch_text");
return key;
}
@@ -311,6 +352,8 @@ public class Keyboard2 extends InputMethodService
if (conn == null)
return;
conn.sendKeyEvent(new KeyEvent(1, 1, eventAction, eventCode, 0, meta));
if (eventAction == KeyEvent.ACTION_UP)
_autocap.event_sent(eventCode, meta);
}
public void showKeyboardConfig()
@@ -323,11 +366,13 @@ public class Keyboard2 extends InputMethodService
public void commitText(String text)
{
getCurrentInputConnection().commitText(text, 1);
_autocap.typed(text);
}
public void commitChar(char c)
{
sendKeyChar(c);
_autocap.typed(c);
}
}

View File

@@ -1,29 +1,30 @@
package juloo.keyboard2;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Vibrator;
import android.inputmethodservice.InputMethodService;
import android.os.Build.VERSION;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
public class Keyboard2View extends View
implements View.OnTouchListener, Pointers.IPointerEventHandler
{
private static final long VIBRATE_MIN_INTERVAL = 100;
private KeyboardData _keyboard;
private KeyValue _shift_kv;
private KeyboardData.Key _shift_key;
private Pointers _pointers;
private int _flags = 0;
private Vibrator _vibratorService;
private long _lastVibration = 0;
private Pointers.Modifiers _mods;
private static int _currentWhat = 0;
@@ -45,65 +46,103 @@ public class Keyboard2View extends View
public Keyboard2View(Context context, AttributeSet attrs)
{
super(context, attrs);
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
_theme = new Theme(getContext(), attrs);
_config = Config.globalConfig();
_pointers = new Pointers(this, _config);
refresh_navigation_bar(context);
setOnTouchListener(this);
reset();
}
private Window getParentWindow(Context context)
{
if (context instanceof InputMethodService)
return ((InputMethodService)context).getWindow().getWindow();
if (context instanceof ContextWrapper)
return getParentWindow(((ContextWrapper)context).getBaseContext());
return null;
}
public void refresh_navigation_bar(Context context)
{
if (VERSION.SDK_INT < 21)
return;
// The intermediate Window is a [Dialog].
Window w = getParentWindow(context);
int uiFlags = getSystemUiVisibility();
if (_theme.isLightNavBar)
uiFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
else
uiFlags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
w.setNavigationBarColor(_theme.colorNavBar);
setSystemUiVisibility(uiFlags);
}
public void setKeyboard(KeyboardData kw)
{
_keyboard = _config.modify_layout(kw);
_shift_kv = KeyValue.getKeyByName("shift");
_shift_key = _keyboard.findKeyWithValue(_shift_kv);
if (_shift_key == null)
{
_shift_kv = _shift_kv.withFlags(_shift_kv.getFlags() | KeyValue.FLAG_LOCK);
_shift_key = _keyboard.findKeyWithValue(_shift_kv);
}
reset();
}
public void reset()
{
_flags = 0;
_mods = Pointers.Modifiers.EMPTY;
_pointers.clear();
requestLayout();
invalidate();
}
public KeyValue onPointerDown(KeyValue k)
/** Called by auto-capitalisation. */
public void set_shift_state(boolean state)
{
k = KeyModifier.handleFlags(k, _flags);
if (_keyboard == null || _shift_key == null)
return;
if (state)
_pointers.add_fake_pointer(_shift_kv, _shift_key);
else
_pointers.remove_fake_pointer(_shift_kv, _shift_key);
invalidate();
if (k != null)
}
public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods)
{
return KeyModifier.modify(k, mods);
}
public void onPointerDown(boolean isSwipe)
{
invalidate();
vibrate();
}
public void onPointerUp(KeyValue k, Pointers.Modifiers mods)
{
_config.handler.handleKeyUp(k, mods);
invalidate();
}
public void onPointerHold(KeyValue k, Pointers.Modifiers mods)
{
_config.handler.handleKeyUp(k, mods);
}
public void onPointerFlagsChanged(boolean shouldVibrate)
{
invalidate();
if (shouldVibrate)
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();
_mods = _pointers.getModifiers();
}
@Override
@@ -171,18 +210,10 @@ public class Keyboard2View extends View
{
if (!_config.vibrateEnabled)
return ;
long now = System.currentTimeMillis();
if ((now - _lastVibration) > VIBRATE_MIN_INTERVAL)
if (VERSION.SDK_INT >= 5)
{
_lastVibration = now;
try
{
_vibratorService.vibrate(_config.vibrateDuration);
}
catch (Exception e)
{
e.printStackTrace();
}
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
@@ -246,7 +277,7 @@ public class Keyboard2View extends View
private int labelColor(KeyValue k, boolean isKeyDown, int defaultColor)
{
if (isKeyDown && (k.flags & KeyValue.FLAG_LATCH) != 0)
if (isKeyDown && k.hasFlags(KeyValue.FLAG_LATCH))
{
int flags = _pointers.getKeyFlags(k);
if (flags != -1)
@@ -260,26 +291,30 @@ public class Keyboard2View extends View
return defaultColor;
}
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown)
private void drawLabel(Canvas canvas, KeyboardData.Corner k, float x, float y, float keyH, boolean isKeyDown)
{
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));
KeyValue kv = KeyModifier.modify(k.kv, _mods);
if (kv == null)
return;
float textSize = scaleTextSize(kv, _config.labelTextSize, keyH);
Paint p = _theme.labelPaint(kv.hasFlags(KeyValue.FLAG_KEY_FONT));
p.setColor(labelColor(kv, isKeyDown, _theme.labelColor));
p.setTextSize(textSize);
canvas.drawText(k.symbol, x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
canvas.drawText(kv.getString(), x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
}
private void drawSubLabel(Canvas canvas, KeyValue k, float x, float y, float keyW, float keyH, Paint.Align a, Vertical v, boolean isKeyDown)
private void drawSubLabel(Canvas canvas, KeyboardData.Corner 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));
KeyValue kv = KeyModifier.modify(k.kv, _mods);
if (kv == null)
return;
float textSize = scaleTextSize(kv, _config.sublabelTextSize, keyH);
Paint p = _theme.subLabelPaint(kv.hasFlags(KeyValue.FLAG_KEY_FONT), a);
p.setColor(labelColor(kv, isKeyDown, _theme.subLabelColor));
p.setTextSize(textSize);
float subPadding = _config.keyPadding;
if (v == Vertical.CENTER)
@@ -290,12 +325,12 @@ public class Keyboard2View extends View
x += keyW / 2f;
else
x += (a == Paint.Align.LEFT) ? subPadding : keyW - subPadding;
canvas.drawText(k.symbol, x, y, p);
canvas.drawText(kv.getString(), x, y, p);
}
private float scaleTextSize(KeyValue k, float rel_size, float keyH)
{
float smaller_font = ((k.flags & KeyValue.FLAG_SMALLER_FONT) == 0) ? 1.f : 0.75f;
float smaller_font = k.hasFlags(KeyValue.FLAG_SMALLER_FONT) ? 0.75f : 1.f;
return keyH * rel_size * smaller_font * _config.characterSize;
}
}

View File

@@ -3,25 +3,75 @@ package juloo.keyboard2;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import java.util.ArrayList;
import java.util.function.Function;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
class KeyboardData
{
public final List<Row> rows;
/* Total width of the keyboard. Unit is abstract. */
/** Total width of the keyboard. */
public final float keysWidth;
/* Total height of the keyboard. Unit is abstract. */
/** Total height of the keyboard. */
public final float keysHeight;
/** Whether to add extra keys. */
public final boolean extra_keys;
public KeyboardData replaceKeys(MapKeys f)
public KeyboardData mapKeys(MapKey f)
{
ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows)
rows_.add(r.replaceKeys(f));
return new KeyboardData(rows_, keysWidth);
rows_.add(r.mapKeys(f));
return new KeyboardData(rows_, keysWidth, extra_keys);
}
/** Add keys from the given iterator into the keyboard. Extra keys are added
* on the empty key4 corner of the second row, from right to left. If there's
* not enough room, key3 of the second row is tried then key2 and key1 of the
* third row. */
public KeyboardData addExtraKeys(Iterator<KeyValue> k)
{
if (!extra_keys)
return this;
ArrayList<Row> rows = new ArrayList<Row>(this.rows);
addExtraKeys_to_row(rows, k, 1, 4);
addExtraKeys_to_row(rows, k, 1, 3);
addExtraKeys_to_row(rows, k, 2, 2);
addExtraKeys_to_row(rows, k, 2, 1);
if (k.hasNext())
{
for (int r = 0; r < rows.size(); r++)
for (int c = 1; c <= 4; c++)
addExtraKeys_to_row(rows, k, r, c);
}
return new KeyboardData(rows, keysWidth, extra_keys);
}
public Key findKeyWithValue(KeyValue kv)
{
for (Row r : rows)
{
Key k = r.findKeyWithValue(kv);
if (k != null)
return k;
}
return null;
}
private static void addExtraKeys_to_row(ArrayList<Row> rows, final Iterator<KeyValue> extra_keys, int row_i, final int d)
{
if (!extra_keys.hasNext())
return;
rows.set(row_i, rows.get(row_i).mapKeys(new MapKey(){
public Key apply(Key k) {
if (k.getKeyValue(d) == null && extra_keys.hasNext())
return k.withKeyValue(d, extra_keys.next());
else
return k;
}
}));
}
private static Row _bottomRow = null;
@@ -52,13 +102,14 @@ class KeyboardData
if (!expect_tag(parser, "keyboard"))
throw new Exception("Empty layout file");
boolean bottom_row = parser.getAttributeBooleanValue(null, "bottom_row", true);
boolean extra_keys = parser.getAttributeBooleanValue(null, "extra_keys", 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);
return new KeyboardData(rows, kw, extra_keys);
}
private static float compute_max_width(List<Row> rows)
@@ -76,7 +127,7 @@ class KeyboardData
return Row.parse(parser);
}
protected KeyboardData(List<Row> rows_, float kw)
protected KeyboardData(List<Row> rows_, float kw, boolean xk)
{
float kh = 0.f;
for (Row r : rows_)
@@ -84,16 +135,17 @@ class KeyboardData
rows = rows_;
keysWidth = kw;
keysHeight = kh;
extra_keys = xk;
}
public static class Row
{
public final List<Key> keys;
/* Height of the row, without 'shift'. Unit is abstract. */
/** Height of the row, without 'shift'. */
public final float height;
/* Extra empty space on the top. */
/** Extra empty space on the top. */
public final float shift;
/* Total width of the row. Unit is abstract. */
/** Total width of the row. */
private final float keysWidth;
protected Row(List<Key> keys_, float h, float s)
@@ -117,22 +169,29 @@ class KeyboardData
return new Row(keys, h, shift);
}
public Row replaceKeys(MapKeys f)
public Row mapKeys(MapKey f)
{
ArrayList<Key> keys_ = new ArrayList<Key>();
for (Key k : keys)
keys_.add(k.replaceKeys(f));
keys_.add(f.apply(k));
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>();
final float s = newWidth / keysWidth;
return mapKeys(new MapKey(){
public Key apply(Key k) { return k.scaleWidth(s); }
});
}
public Key findKeyWithValue(KeyValue kv)
{
for (Key k : keys)
keys_.add(k.scaleWidth(s));
return new Row(keys_, height, shift);
if (k.hasValue(kv))
return k;
return null;
}
}
@@ -143,20 +202,20 @@ class KeyboardData
** 0
** 3 4
*/
public final KeyValue key0;
public final KeyValue key1;
public final KeyValue key2;
public final KeyValue key3;
public final KeyValue key4;
public final Corner key0;
public final Corner key1;
public final Corner key2;
public final Corner key3;
public final Corner key4;
/* Key width in relative unit. */
/** Key width in relative unit. */
public final float width;
/* Extra empty space on the left of the key. */
/** 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. */
/** Put keys 1 to 4 on the edges instead of the corners. */
public final boolean edgekeys;
protected Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e)
protected Key(Corner k0, Corner k1, Corner k2, Corner k3, Corner k4, float w, float s, boolean e)
{
key0 = k0;
key1 = k1;
@@ -170,11 +229,11 @@ class KeyboardData
public static Key parse(XmlResourceParser parser) throws Exception
{
KeyValue k0 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key0"));
KeyValue k1 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key1"));
KeyValue k2 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key2"));
KeyValue k3 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key3"));
KeyValue k4 = KeyValue.getKeyByName(parser.getAttributeValue(null, "key4"));
Corner k0 = Corner.parse_of_attr(parser, "key0");
Corner k1 = Corner.parse_of_attr(parser, "key1");
Corner k2 = Corner.parse_of_attr(parser, "key2");
Corner k3 = Corner.parse_of_attr(parser, "key3");
Corner k4 = Corner.parse_of_attr(parser, "key4");
float width = parser.getAttributeFloatValue(null, "width", 1f);
float shift = parser.getAttributeFloatValue(null, "shift", 0.f);
boolean edgekeys = parser.getAttributeBooleanValue(null, "edgekeys", false);
@@ -183,34 +242,159 @@ class KeyboardData
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
}
public Key replaceKeys(MapKeys f)
{
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)
public KeyValue getKeyValue(int i)
{
switch (index)
Corner c;
switch (i)
{
case 1: return key1;
case 2: return key2;
case 3: return key3;
case 4: return key4;
default: case 0: return key0;
case 0: c = key0; break;
case 1: c = key1; break;
case 2: c = key2; break;
case 3: c = key3; break;
case 4: c = key4; break;
default: c = null; break;
}
return (c == null) ? null : c.kv;
}
public Key withKeyValue(int i, KeyValue kv)
{
Corner k0 = key0, k1 = key1, k2 = key2, k3 = key3, k4 = key4;
Corner k = Corner.of_kv(kv);
switch (i)
{
case 0: k0 = k; break;
case 1: k1 = k; break;
case 2: k2 = k; break;
case 3: k3 = k; break;
case 4: k4 = k; break;
}
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
}
/**
* See Pointers.onTouchMove() for the represented direction.
*/
public KeyValue getAtDirection(int direction)
{
Corner c = null;
if (edgekeys)
{
// \ 1 /
// \ /
// 3 0 2
// / \
// / 4 \
switch (direction)
{
case 2: case 3: c = key1; break;
case 4: case 5: c = key2; break;
case 6: case 7: c = key4; break;
case 8: case 1: c = key3; break;
}
}
else
{
// 1 | 2
// |
// --0--
// |
// 3 | 4
switch (direction)
{
case 1: case 2: c = key1; break;
case 3: case 4: c = key2; break;
case 5: case 6: c = key4; break;
case 7: case 8: c = key3; break;
}
}
return (c == null) ? null : c.kv;
}
public boolean hasValue(KeyValue kv)
{
return (hasValue(key0, kv) || hasValue(key1, kv) || hasValue(key2, kv) ||
hasValue(key3, kv) || hasValue(key4, kv));
}
private static boolean hasValue(Corner c, KeyValue kv)
{
return (c != null && c.kv.equals(kv));
}
}
public static final class Corner
{
public final KeyValue kv;
/** Whether the kv is marked with the "loc " prefix. To be removed if not
specified in the [extra_keys]. */
public final boolean localized;
protected Corner(KeyValue k, boolean l)
{
kv = k;
localized = l;
}
public static Corner parse_of_attr(XmlResourceParser parser, String attr) throws Exception
{
String name = parser.getAttributeValue(null, attr);
boolean localized = false;
if (name == null)
return null;
String name_loc = stripPrefix(name, "loc ");
if (name_loc != null)
{
localized = true;
name = name_loc;
}
return new Corner(KeyValue.getKeyByName(name), localized);
}
public static Corner of_kv(KeyValue kv)
{
return new Corner(kv, false);
}
private static String stripPrefix(String s, String prefix)
{
if (s.startsWith(prefix))
return s.substring(prefix.length());
else
return null;
}
}
// Not using Function<KeyValue, KeyValue> to keep compatibility with Android 6.
public static abstract interface MapKeys {
public KeyValue apply(KeyValue kv);
public static abstract interface MapKey {
public Key apply(Key k);
}
public static abstract class MapKeyValues implements MapKey {
abstract public KeyValue apply(KeyValue c, boolean localized);
public Key apply(Key k)
{
return new Key(apply(k.key0), apply(k.key1), apply(k.key2),
apply(k.key3), apply(k.key4), k.width, k.shift, k.edgekeys);
}
private Corner apply(Corner c)
{
if (c == null)
return null;
KeyValue kv = apply(c.kv, c.localized);
if (kv == null)
return null;
return Corner.of_kv(kv);
}
}
/** Parsing utils */

View File

@@ -2,6 +2,7 @@ package juloo.keyboard2;
import android.os.Handler;
import android.os.Message;
import java.util.Arrays;
import java.util.ArrayList;
/**
@@ -22,12 +23,27 @@ public final class Pointers implements Handler.Callback
_config = c;
}
public int getFlags()
/** Return the list of modifiers currently activated. */
public Modifiers getModifiers()
{
int flags = 0;
for (Pointer p : _ptrs)
flags |= p.flags;
return flags;
return getModifiers(false);
}
/** When [skip_latched] is true, don't take flags of latched keys into account. */
private Modifiers getModifiers(boolean skip_latched)
{
int n_ptrs = _ptrs.size();
KeyValue.Modifier[] mods = new KeyValue.Modifier[n_ptrs];
int n_mods = 0;
for (int i = 0; i < n_ptrs; i++)
{
Pointer p = _ptrs.get(i);
if (p.value != null && p.value.getKind() == KeyValue.Kind.Modifier
&& !(skip_latched && p.pointerId == -1
&& (p.flags & KeyValue.FLAG_LOCKED) == 0))
mods[n_mods++] = p.value.getModifier();
}
return Modifiers.ofArray(mods, n_mods);
}
public void clear()
@@ -52,14 +68,30 @@ public final class Pointers implements Handler.Callback
*/
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)
if (p.value != null && p.value.equals(kv))
return p.flags;
return -1;
}
/** Fake pointers are latched and not lockable. */
public void add_fake_pointer(KeyValue kv, KeyboardData.Key key)
{
// Avoid adding a fake pointer to a key that is already down.
if (isKeyDown(key))
return;
Pointer ptr = new Pointer(-1, key, kv, 0.f, 0.f, Modifiers.EMPTY);
ptr.flags = ptr.flags & ~(KeyValue.FLAG_LATCH | KeyValue.FLAG_LOCK | KeyValue.FLAG_FAKE_PTR);
_ptrs.add(ptr);
}
public void remove_fake_pointer(KeyValue kv, KeyboardData.Key key)
{
Pointer ptr = getLatched(key, kv);
if (ptr != null && (ptr.flags & KeyValue.FLAG_FAKE_PTR) != 0)
removePtr(ptr);
}
// Receiving events
public void onTouchUp(int pointerId)
@@ -72,28 +104,25 @@ public final class Pointers implements Handler.Callback
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();
}
if ((latched.flags & KeyValue.FLAG_LOCK) != 0) // Toggle lockable key
lockPointer(latched, false);
else // Otherwise, unlatch
{
removePtr(latched);
_handler.onPointerUp(ptr.value);
_handler.onPointerUp(ptr.value, ptr.modifiers);
}
}
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
{
ptr.flags &= ~KeyValue.FLAG_LATCH;
ptr.pointerId = -1; // Latch
_handler.onPointerFlagsChanged();
_handler.onPointerFlagsChanged(false);
}
else
{
clearLatched();
removePtr(ptr);
_handler.onPointerUp(ptr.value);
_handler.onPointerUp(ptr.value, ptr.modifiers);
}
}
@@ -104,7 +133,16 @@ public final class Pointers implements Handler.Callback
return;
stopKeyRepeat(ptr);
removePtr(ptr);
_handler.onPointerFlagsChanged();
_handler.onPointerFlagsChanged(true);
}
/* Whether an other pointer is down on a non-special key. */
private boolean isOtherPointerDown()
{
for (Pointer p : _ptrs)
if (p.pointerId != -1 && (p.flags & KeyValue.FLAG_SPECIAL) == 0)
return true;
return false;
}
public void onTouchDown(float x, float y, int pointerId, KeyboardData.Key key)
@@ -114,11 +152,46 @@ public final class Pointers implements Handler.Callback
// keys.
if (isModulatedKeyPressed())
return;
KeyValue value = _handler.onPointerDown(key.key0);
Pointer ptr = new Pointer(pointerId, key, 0, value, x, y);
// Don't take latched modifiers into account if an other key is pressed.
// The other key already "own" the latched modifiers and will clear them.
Modifiers mods = getModifiers(isOtherPointerDown());
KeyValue value = handleKV(key.key0, mods);
Pointer ptr = new Pointer(pointerId, key, value, x, y, mods);
_ptrs.add(ptr);
if (value != null && (value.flags & KeyValue.FLAG_NOREPEAT) == 0)
startKeyRepeat(ptr);
startKeyRepeat(ptr);
_handler.onPointerDown(false);
}
/*
* Get the KeyValue at the given direction. In case of swipe (!= 0), get the
* nearest KeyValue that is not key0.
* Take care of applying [_handler.onPointerSwipe] to the selected key, this
* must be done at the same time to be sure to treat removed keys correctly.
* Return [null] if no key could be found in the given direction or if the
* selected key didn't change.
*/
private KeyValue getKeyAtDirection(Pointer ptr, int direction)
{
if (direction == 0)
return handleKV(ptr.key.key0, ptr.modifiers);
KeyValue k;
for (int i = 0; i > -3; i = (~i>>31) - i)
{
int d = (direction + i + 8 - 1) % 8 + 1;
// Don't make the difference between a key that doesn't exist and a key
// that is removed by [_handler]. Triggers side effects.
k = _handler.modifyKey(ptr.key.getAtDirection(d), ptr.modifiers);
if (k != null)
return k;
}
return null;
}
private KeyValue handleKV(KeyboardData.Corner c, Modifiers modifiers)
{
if (c == null)
return null;
return _handler.modifyKey(c.kv, modifiers);
}
public void onTouchMove(float x, float y, int pointerId)
@@ -126,45 +199,51 @@ public final class Pointers implements Handler.Callback
Pointer ptr = getPtr(pointerId);
if (ptr == null)
return;
// The position in a IME windows is clampled to view.
// For a better up swipe behaviour, set the y position to a negative value when clamped.
if (y == 0.0) y = -400;
float dx = x - ptr.downX;
float dy = y - ptr.downY;
float dist = Math.abs(dx) + Math.abs(dy);
ptr.ptrDist = dist;
int newIndex;
int direction;
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;
direction = 0;
}
else
{
if (dx < 0) // left side
newIndex = (dy < 0) ? 1 : 3;
else // right side
newIndex = (dy < 0) ? 2 : 4;
// One of the 8 directions:
// |\2|3/|
// |1\|/4|
// |-----|
// |8/|\5|
// |/7|6\|
direction = 1;
if (dx > 0) direction += 2;
if (dx > Math.abs(dy) || (dx < 0 && dx > -Math.abs(dy))) direction += 1;
if (dy > 0) direction = 9 - direction;
}
if (newIndex != ptr.value_index)
if (direction != ptr.selected_direction)
{
ptr.value_index = newIndex;
KeyValue newValue = _handler.onPointerSwipe(ptr.key.getValue(newIndex));
if (newValue != null)
ptr.selected_direction = direction;
KeyValue newValue = getKeyAtDirection(ptr, direction);
if (newValue != null && (ptr.value == null || !newValue.equals(ptr.value)))
{
int old_flags = ptr.flags;
ptr.value = newValue;
ptr.flags = newValue.flags;
ptr.flags = newValue.getFlags();
// Keep the keyrepeat going between modulated keys.
if ((old_flags & newValue.flags & KeyValue.FLAG_PRECISE_REPEAT) == 0)
if ((old_flags & ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) == 0)
{
stopKeyRepeat(ptr);
if ((newValue.flags & KeyValue.FLAG_NOREPEAT) == 0)
startKeyRepeat(ptr);
startKeyRepeat(ptr);
}
_handler.onPointerDown(true);
}
}
}
@@ -186,10 +265,15 @@ public final class Pointers implements Handler.Callback
private Pointer getLatched(Pointer target)
{
KeyboardData.Key k = target.key;
int vi = target.value_index;
return getLatched(target.key, target.value);
}
private Pointer getLatched(KeyboardData.Key k, KeyValue v)
{
if (v == null)
return null;
for (Pointer p : _ptrs)
if (p.key == k && p.value_index == vi && p.pointerId == -1)
if (p.key == k && p.pointerId == -1 && p.value != null && p.value.equals(v))
return p;
return null;
}
@@ -202,12 +286,19 @@ public final class Pointers implements Handler.Callback
// 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
// Not latched but pressed, don't latch once released and stop long press.
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
ptr.flags &= ~KeyValue.FLAG_LATCH;
}
}
/** Make a pointer into the locked state. */
private void lockPointer(Pointer ptr, boolean shouldVibrate)
{
ptr.flags = (ptr.flags & ~KeyValue.FLAG_LOCK) | KeyValue.FLAG_LOCKED;
_handler.onPointerFlagsChanged(shouldVibrate);
}
private boolean isModulatedKeyPressed()
{
for (Pointer ptr : _ptrs)
@@ -228,26 +319,33 @@ public final class Pointers implements Handler.Callback
{
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);
if (handleKeyRepeat(ptr))
_keyrepeat_handler.sendEmptyMessageDelayed(msg.what, nextRepeatInterval(ptr));
else
ptr.timeoutWhat = -1;
return true;
}
}
return (false);
return false;
}
private long nextRepeatInterval(Pointer ptr)
{
long t = _config.longPressInterval;
if (_config.preciseRepeat && (ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
{
// Modulate repeat interval depending on the distance of the pointer
t = (long)((float)t * 2.f / modulatePreciseRepeat(ptr));
}
return t;
}
private static int uniqueTimeoutWhat = 0;
private void startKeyRepeat(Pointer ptr)
{
if (ptr.value == null)
return;
int what = (uniqueTimeoutWhat++);
ptr.timeoutWhat = what;
long timeout = _config.longPressTimeout;
@@ -267,6 +365,22 @@ public final class Pointers implements Handler.Callback
}
}
/** A pointer is repeating. Returns [true] if repeat should continue. */
private boolean handleKeyRepeat(Pointer ptr)
{
// Long press toggle lock on modifiers
if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
{
lockPointer(ptr, true);
return false;
}
// Stop repeating: Latched key, special keys
if (ptr.pointerId == -1 || (ptr.flags & KeyValue.FLAG_SPECIAL) != 0)
return false;
_handler.onPointerHold(ptr.value, ptr.modifiers);
return true;
}
private float modulatePreciseRepeat(Pointer ptr)
{
if (ptr.repeatingPtrDist < 0.f)
@@ -278,56 +392,110 @@ public final class Pointers implements Handler.Callback
return Math.min(8.f, Math.max(0.1f, accel));
}
private final class Pointer
private static final class Pointer
{
/** -1 when latched. */
public int pointerId;
/** The Key pressed by this Pointer */
public final KeyboardData.Key key;
public int value_index;
/** Modified value. Not equal to [key.getValue(value_index)]. */
/** Current direction. */
public int selected_direction;
/** Selected value with [modifiers] applied. */
public KeyValue value;
public float downX;
public float downY;
/** Distance of the pointer to the initial press. */
public float ptrDist;
/** Modifier flags at the time the key was pressed. */
public Modifiers modifiers;
/** Flags of the value. Latch, lock and locked flags are updated. */
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)
public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifiers m)
{
pointerId = p;
key = k;
value_index = vi;
selected_direction = 0;
value = v;
downX = x;
downY = y;
ptrDist = 0.f;
flags = (v == null) ? 0 : v.flags;
modifiers = m;
flags = (v == null) ? 0 : v.getFlags();
timeoutWhat = -1;
repeatingPtrDist = -1.f;
}
}
/** Represent modifiers currently activated.
Sorted in the order they should be evaluated. */
public static final class Modifiers
{
private final KeyValue.Modifier[] _mods;
private final int _size;
private Modifiers(KeyValue.Modifier[] m, int s)
{
_mods = m; _size = s;
}
public KeyValue.Modifier get(int i) { return _mods[_size - 1 - i]; }
public int size() { return _size; }
@Override
public int hashCode() { return Arrays.hashCode(_mods); }
@Override
public boolean equals(Object obj)
{
return Arrays.equals(_mods, ((Modifiers)obj)._mods);
}
public static final Modifiers EMPTY =
new Modifiers(new KeyValue.Modifier[0], 0);
protected static Modifiers ofArray(KeyValue.Modifier[] mods, int size)
{
// Sort and remove duplicates and nulls.
if (size > 1)
{
Arrays.sort(mods, 0, size);
int j = 0;
for (int i = 0; i < size; i++)
{
KeyValue.Modifier m = mods[i];
if (m != null && (i + 1 >= size || m != mods[i + 1]))
{
mods[j] = m;
j++;
}
}
size = j;
}
return new Modifiers(mods, size);
}
}
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);
/** Key can be modified or removed by returning [null]. */
public KeyValue modifyKey(KeyValue k, Modifiers flags);
/** Pointer swipes into a corner. Key can be modified or removed. */
public KeyValue onPointerSwipe(KeyValue k);
/** A key is pressed. [getModifiers()] is uptodate. Might be called after a
press or a swipe to a different value. */
public void onPointerDown(boolean isSwipe);
/** Key is released. [k] is the key that was returned by [onPointerDown] or
[onPointerSwipe]. */
public void onPointerUp(KeyValue k);
/** Key is released. [k] is the key that was returned by
[modifySelectedKey] or [modifySelectedKey]. */
public void onPointerUp(KeyValue k, Modifiers flags);
/** Flags changed because latched or locked keys or cancelled pointers. */
public void onPointerFlagsChanged();
public void onPointerFlagsChanged(boolean shouldVibrate);
/** Key is repeating. */
public void onPointerHold(KeyValue k);
public void onPointerHold(KeyValue k, Modifiers flags);
}
}

View File

@@ -18,6 +18,9 @@ public class Theme
public final float keyBorderRadius;
public final int colorNavBar;
public final boolean isLightNavBar;
private final Paint _keyLabelPaint;
private final Paint _specialKeyLabelPaint;
private final Paint _keySubLabelPaint;
@@ -29,6 +32,8 @@ public class Theme
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);
colorNavBar = s.getColor(R.styleable.keyboard_navigationBarColor, 0);
isLightNavBar = s.getBoolean(R.styleable.keyboard_windowLightNavigationBar, false);
labelColor = s.getColor(R.styleable.keyboard_colorLabel, 0);
activatedColor = s.getColor(R.styleable.keyboard_colorLabelActivated, 0);
lockedColor = s.getColor(R.styleable.keyboard_colorLabelLocked, 0);
@@ -37,7 +42,7 @@ public class Theme
s.recycle();
_keyLabelPaint = initLabelPaint(Paint.Align.CENTER, null);
_keySubLabelPaint = initLabelPaint(Paint.Align.LEFT, null);
Typeface specialKeyFont = getSpecialKeyFont(context);
Typeface specialKeyFont = getKeyFont(context);
_specialKeyLabelPaint = initLabelPaint(Paint.Align.CENTER, specialKeyFont);
_specialKeySubLabelPaint = initLabelPaint(Paint.Align.LEFT, specialKeyFont);
}
@@ -64,14 +69,12 @@ public class Theme
return (paint);
}
private static Typeface _specialKeyFont = null;
private static Typeface _key_font = null;
static public Typeface getSpecialKeyFont(Context context)
static public Typeface getKeyFont(Context context)
{
if (_specialKeyFont == null)
{
_specialKeyFont = Typeface.createFromAsset(context.getAssets(), "special_font.ttf");
}
return _specialKeyFont;
if (_key_font == null)
_key_font = Typeface.createFromAsset(context.getAssets(), "special_font.ttf");
return _key_font;
}
}

View File

@@ -1,12 +1,14 @@
<?xml version="1.0" standalone="no"?>
<!-- Accent from Roboto font family (Regular). Apache License, Version 2.0. -->
<!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" viewBox="-19 0 1167 2048">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="-20 0 1168 2048">
<g transform="matrix(1 0 0 -1 0 1536)">
<path fill="currentColor"
d="M931 1003l-69 -70q-112 86 -250 99v99q176 -12 319 -128zM517 1032q-133 -10 -250 -101q0 1 -72 74l3 -2q143 116 319 128v-99zM198 860q-90 -103 -108 -246h-99q17 182 137 319l-6 6l4 -3l41 -43q31 -32 31 -33zM1138 614h-100q-17 141 -107 249l70 70
q120 -137 137 -319zM1138 518q-14 -190 -130 -327l-69 70q86 111 99 257h100zM190 264q-76 -77 -75 -77l4 4q-115 137 -128 327h99q14 -147 100 -254zM939 121q-146 -124 -327 -136v100q140 12 258 106zM517 -15q-180 12 -327 136l69 70q118 -90 258 -106v-100zM687 0
q-70 -52 -109.5 -99.5t-39.5 -101.5q0 -42 22.5 -66t73.5 -24q27 0 50 7.5t49 18.5l33 -123q-36 -19 -79.5 -31.5t-103.5 -12.5q-95 0 -155.5 55t-60.5 154q0 80 60.5 152t187.5 128z" />
d="M931.256 1002.78l-69.3145 -69.3145q-112.472 86.3154 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166v0zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30859 -71.9297 74.5449l2.61523 -2.61523q142.554 116.396 319.106 128.166v-99.3945
v0zM197.572 860.229q-90.2393 -103.316 -107.24 -245.867h-99.3936q17.001 181.786 137.32 319.104l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3867 30.0791 -32.6953v0zM1137.89 614.361h-99.3936q-17.001 141.242 -107.239 248.483
l69.3135 70.6211q120.318 -137.319 137.319 -319.104v0zM1137.89 517.583q-14.3857 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3154 111.164 99.3936 256.331h99.3936v0zM189.726 263.867h0.000976562q-86.3154 107.239 -99.3936 253.716h-99.3945
q13.0781 -189.633 128.165 -326.953l-3.92285 -3.92383q-1.30762 0 74.5449 77.1611zM939.103 121.315q-146.476 -124.242 -326.952 -136.014v99.3945q139.935 11.7705 257.639 105.934zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145
q117.703 -90.2383 257.64 -105.933v-99.3945h-0.000976562zM623 -9l-12 -52q65 -11 108 -52t43 -121q0 -96 -79 -153t-226 -57l-7 109q72 0 116 24.5t44 73.5q0 48 -36 67t-123 26l32 135h140z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

13
srcs/special_font/59.svg Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 1168 2048">
<g transform="matrix(1 0 0 -1 0 1536)">
<path fill="currentColor"
d="M931.256 1002.78l-69.3145 -69.3145q-112.472 86.3154 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166v0zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30859 -71.9297 74.5449l2.61523 -2.61523q142.554 116.396 319.106 128.166v-99.3945
v0zM197.572 860.229q-90.2393 -103.316 -107.24 -245.867h-99.3936q17.001 181.786 137.32 319.104l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3867 30.0791 -32.6953v0zM1137.89 614.361h-99.3936q-17.001 141.242 -107.239 248.483
l69.3135 70.6211q120.318 -137.319 137.319 -319.104v0zM1137.89 517.583q-14.3857 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3154 111.164 99.3936 256.331h99.3936v0zM189.726 263.867h0.000976562q-86.3154 107.239 -99.3936 253.716h-99.3945
q13.0781 -189.633 128.165 -326.953l-3.92285 -3.92383q-1.30762 0 74.5449 77.1611zM939.103 121.315q-146.476 -124.242 -326.952 -136.014v99.3945q139.935 11.7705 257.639 105.934zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145
q117.703 -90.2383 257.64 -105.933v-99.3945h-0.000976562zM987 0q-70 -52 -109.5 -99.5t-39.5 -101.5q0 -42 22.5 -66t73.5 -24q27 0 50 7.5t49 18.5l33 -123q-36 -19 -79.5 -31.5t-103.5 -12.5q-95 0 -155.5 55t-60.5 154q0 80 60.5 152t187.5 128z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

13
srcs/special_font/5A.svg Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 1168 2048">
<g transform="matrix(1 0 0 -1 0 1536)">
<path fill="currentColor"
d="M931.256 1002.78l-69.3145 -69.3145q-112.472 86.3154 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166v0zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30859 -71.9297 74.5449l2.61523 -2.61523q142.554 116.396 319.106 128.166v-99.3945
v0zM197.572 860.229q-90.2393 -103.316 -107.24 -245.867h-99.3936q17.001 181.786 137.32 319.104l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3867 30.0791 -32.6953v0zM1137.89 614.361h-99.3936q-17.001 141.242 -107.239 248.483
l69.3135 70.6211q120.318 -137.319 137.319 -319.104v0zM1137.89 517.583q-14.3857 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3154 111.164 99.3936 256.331h99.3936v0zM189.726 263.867h0.000976562q-86.3154 107.239 -99.3936 253.716h-99.3945
q13.0781 -189.633 128.165 -326.953l-3.92285 -3.92383q-1.30762 0 74.5449 77.1611zM939.103 121.315q-146.476 -124.242 -326.952 -136.014v99.3945q139.935 11.7705 257.639 105.934zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145
q117.703 -90.2383 257.64 -105.933v-99.3945h-0.000976562zM648 1283h-218v201h218v-201z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

13
srcs/special_font/5B.svg Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 1184 2048">
<g transform="matrix(1 0 0 -1 0 1536)">
<path fill="currentColor"
d="M931.256 1002.78l-69.3145 -69.3145q-112.472 86.3154 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166v0zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30859 -71.9297 74.5449l2.61523 -2.61523q142.554 116.396 319.106 128.166v-99.3945
v0zM197.572 860.229q-90.2393 -103.316 -107.24 -245.867h-99.3936q17.001 181.786 137.32 319.104l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3867 30.0791 -32.6953v0zM1137.89 614.361h-99.3936q-17.001 141.242 -107.239 248.483
l69.3135 70.6211q120.318 -137.319 137.319 -319.104v0zM1137.89 517.583q-14.3857 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3154 111.164 99.3936 256.331h99.3936v0zM189.726 263.867h0.000976562q-86.3154 107.239 -99.3936 253.716h-99.3945
q13.0781 -189.633 128.165 -326.953l-3.92285 -3.92383q-1.30762 0 74.5449 77.1611zM939.103 121.315q-146.476 -124.242 -326.952 -136.014v99.3945q139.935 11.7705 257.639 105.934zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145
q117.703 -90.2383 257.64 -105.933v-99.3945h-0.000976562zM856 1545h229l3 -6l-300 -260h-171l-2 5zM530 1545h211l2 -5l-240 -261h-157z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

10
srcs/special_font/5C.svg Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 2068 2048">
<path fill="currentColor"
d="M931.256 533.22l-69.3145 69.3145q-112.472 -86.3154 -249.792 -98.0859v-99.3945q176.555 11.7715 319.106 128.166v0zM516.679 504.45q-133.396 10.4619 -249.792 100.701q0 -1.30859 -71.9297 -74.5449l2.61523 2.61523q142.554 -116.396 319.106 -128.166v99.3945v0z
M197.572 675.771q-90.2393 103.316 -107.24 245.867h-99.3936q17.001 -181.786 137.32 -319.104l-6.53906 -5.23145l3.92285 2.61523l41.8506 43.1582q30.0791 31.3867 30.0791 32.6953v0zM1137.89 921.639h-99.3936q-17.001 -141.242 -107.239 -248.483l69.3135 -70.6211
q120.318 137.319 137.319 319.104v0zM1137.89 1018.42q-14.3857 189.633 -129.474 326.953l-69.3135 -70.6221q86.3154 -111.164 99.3936 -256.331h99.3936v0zM189.726 1272.13h0.000976562q-86.3154 -107.239 -99.3936 -253.716h-99.3945q13.0781 189.633 128.165 326.953
l-3.92285 3.92383q-1.30762 0 74.5449 -77.1611zM939.103 1414.68q-146.476 124.242 -326.952 136.014v-99.3945q139.935 -11.7705 257.639 -105.934zM516.679 1550.7q-180.478 -11.7715 -326.953 -136.013l69.3145 -69.3145q117.703 90.2383 257.64 105.933v99.3945
h-0.000976562zM198 1670l661 -1343h129zM990 330l-665 1341h-129z" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

15
srcs/special_font/5D.svg Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 2068 2048">
<path fill="currentColor"
d="M197.832 205.612h538.118q-61.2705 -48.0928 -87.4463 -102.807h38.8799q75.3359 77.7539 209.951 112.332v18.6455q-134.406 34.6621 -209.951 112.332h-38.8799q26.4688 -54.8193 87.4463 -103.197h-538.118v-37.3057zM931.256 533.22l-69.3145 69.3145
q-112.472 -86.3154 -249.792 -98.0859v-99.3945q176.555 11.7715 319.106 128.166v0zM516.679 504.45q-133.396 10.4619 -249.792 100.701q0 -1.30859 -71.9297 -74.5449l2.61523 2.61523q142.554 -116.396 319.106 -128.166v99.3945v0zM197.572 675.771
q-90.2393 103.316 -107.24 245.867h-99.3936q17.001 -181.786 137.32 -319.104l-6.53906 -5.23145l3.92285 2.61523l41.8506 43.1582q30.0791 31.3867 30.0791 32.6953v0zM1137.89 921.639h-99.3936q-17.001 -141.242 -107.239 -248.483l69.3135 -70.6211
q120.318 137.319 137.319 319.104v0zM1137.89 1018.42q-14.3857 189.633 -129.474 326.953l-69.3135 -70.6221q86.3154 -111.164 99.3936 -256.331h99.3936v0zM189.726 1272.13h0.000976562q-86.3154 -107.239 -99.3936 -253.716h-99.3945q13.0781 189.633 128.165 326.953
l-3.92285 3.92383q-1.30762 0 74.5449 -77.1611zM939.103 1414.68q-146.476 124.242 -326.952 136.014v-99.3945q139.935 -11.7705 257.639 -105.934zM516.679 1550.7q-180.478 -11.7715 -326.953 -136.013l69.3145 -69.3145q117.703 90.2383 257.64 105.933v99.3945
h-0.000976562zM931.256 533.22l-69.3145 69.3145q-112.472 -86.3154 -249.792 -98.0859v-99.3945q176.555 11.7715 319.106 128.166v0zM516.679 504.45q-133.396 10.4619 -249.792 100.701q0 -1.30859 -71.9297 -74.5449l2.61523 2.61523q142.554 -116.396 319.106 -128.166
v99.3945v0zM197.572 675.771q-90.2393 103.316 -107.24 245.867h-99.3936q17.001 -181.786 137.32 -319.104l-6.53906 -5.23145l3.92285 2.61523l41.8506 43.1582q30.0791 31.3867 30.0791 32.6953v0zM1137.89 921.639h-99.3936q-17.001 -141.242 -107.239 -248.483
l69.3135 -70.6211q120.318 137.319 137.319 319.104v0zM1137.89 1018.42q-14.3857 189.633 -129.474 326.953l-69.3135 -70.6221q86.3154 -111.164 99.3936 -256.331h99.3936v0zM189.726 1272.13h0.000976562q-86.3154 -107.239 -99.3936 -253.716h-99.3945
q13.0781 189.633 128.165 326.953l-3.92285 3.92383q-1.30762 0 74.5449 -77.1611zM939.103 1414.68q-146.476 124.242 -326.952 136.014v-99.3945q139.935 -11.7705 257.639 -105.934zM516.679 1550.7q-180.478 -11.7715 -326.953 -136.013l69.3145 -69.3145
q117.703 90.2383 257.64 105.933v99.3945h-0.000976562z" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

13
srcs/special_font/5E.svg Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!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" viewBox="-20 0 1168 2048">
<g transform="matrix(1 0 0 -1 0 1536)">
<path fill="currentColor"
d="M931.256 1002.78l-69.3145 -69.3145q-112.472 86.3154 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166v0zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30859 -71.9297 74.5449l2.61523 -2.61523q142.554 116.396 319.106 128.166v-99.3945
v0zM197.572 860.229q-90.2393 -103.316 -107.24 -245.867h-99.3936q17.001 181.786 137.32 319.104l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3867 30.0791 -32.6953v0zM1137.89 614.361h-99.3936q-17.001 141.242 -107.239 248.483
l69.3135 70.6211q120.318 -137.319 137.319 -319.104v0zM1137.89 517.583q-14.3857 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3154 111.164 99.3936 256.331h99.3936v0zM189.726 263.867h0.000976562q-86.3154 107.239 -99.3936 253.716h-99.3945
q13.0781 -189.633 128.165 -326.953l-3.92285 -3.92383q-1.30762 0 74.5449 77.1611zM939.103 121.315q-146.476 -124.242 -326.952 -136.014v99.3945q139.935 11.7705 257.639 105.934zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145
q117.703 -90.2383 257.64 -105.933v-99.3945h-0.000976562zM881 1496q0 -121 -82.5 -194.5t-216.5 -73.5t-217 74t-83 194h151q0 -70 38 -109.5t111 -39.5q70 0 109.5 39t39.5 110h150z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -3,7 +3,7 @@
New()
# Imports glyphs, file name is position in the font.
i = 2
i = 1
while (i < $argc)
Select(Strtol($argv[i]:t:r, 16))
Import($argv[i], 0, 0, 4.0, 0.1)
@@ -11,4 +11,4 @@ while (i < $argc)
i++
endloop
Generate($1)
Generate("result.ttf")

Binary file not shown.