Compare commits

..

116 Commits

Author SHA1 Message Date
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
Jules Aguillon
65cc0c736e Release 1.14.2 (21) 2022-04-16 23:43:25 +02:00
Jules Aguillon
2cce0fed67 Makefile: Pass -r to adb install
Fails to update on some versions of Android without it.
2022-04-16 23:38:16 +02:00
Jules Aguillon
9a8c4f291d Fix compatibility with Android 6
Android 6 uses Java 1.7, the only incompatible feature in use was
lambdas.
2022-04-16 23:36:54 +02:00
marciozomb13
14cc318a0e Update PT strings (#121)
Tiny fixes and improvements.
2022-04-16 23:17:17 +02:00
Jules Aguillon
8d8a58462c Release 1.14.1 (20) 2022-04-06 09:50:33 +02:00
Jules Aguillon
5562ee1391 Fix mismatch layout name
The Korean layout id was not consistent and this caused a crash.
2022-04-06 09:50:33 +02:00
Jules Aguillon
120c0a9d23 Fix compat with older version of Android
Resources.getFloat is new from API 29.
2022-04-06 09:50:33 +02:00
Jules Aguillon
aaff8689e3 Release 1.14.0 (19) 2022-04-03 20:59:42 +02:00
Jules Aguillon
2b348b7a31 Revert "Swap Ctrl and switch_numeric keys"
This reverts commit b85b67c2f0.

The Ctrl key was too hard to use in the new position, especially in
combination with arrows or backspace.

Leave the switching key in the numeric layout however, where the Ctrl
key is not very useful. Put Ctrl on the top-right because bottom-right
is where the switching key is in the other layouts.
2022-04-03 20:27:25 +02:00
Jules Aguillon
19289bec27 Update screenshots
Many things changed since: new keys, better font, sizes and colors
changed, keys moved.
2022-04-03 18:09:23 +02:00
Jules Aguillon
aa78229b2a Add the Programming Layout option
Allow specifying a layout for programming and add a key for switching to
it easily.

The switching key is placed on the top edge of the space bar.

The option has no effect by default because the ergonomic isn't ideal,
it needs to be enabled explicitly.
Users of Latin-script languages certainly prefer to use one layout (for
programming or not). This feature might be removed in favor of a better
language-switching mechanisms in the future.
2022-04-03 17:15:12 +02:00
Jules Aguillon
d62e7647e0 Move keys away from the edges of the screen
These keys are harder to hit as the finger might exit the screen before
traveling enough to hit a corner. It might be particularly harder for
people that use a phone case.

Every layouts are changed, the notable changes are:

- The Escape key is in the bottom-right corner of the first key.
  This position looks weird at first but is a lot easier to type.

- The 0 key is on the top-left of the last key on the first row.
  It is not like the other digits.

- The Tab key is on the top-right. This might be hard to re-learn.

- Some layouts had more changes to accomodate these new positions.

Co-authored-by: Raphael <rapha.a.r@gmail.com>
2022-04-03 13:30:24 +02:00
Jules Aguillon
9411f59ed5 Rename the Meta key
The symbol isn't clear enough.
2022-04-03 12:49:14 +02:00
Jules Aguillon
b85b67c2f0 Swap Ctrl and switch_numeric keys
The switch_numeric key is generally more important, especially in the
numeric pane.
2022-04-03 12:48:29 +02:00
Jules Aguillon
695f5b4371 Swap Fn and Alt
Fn is increasingly more important while Alt is generally not.
2022-04-03 12:42:50 +02:00
Raphael
b995da9985 Update Space Glyph
Revert to previous version, the original google material icon,
which is not rounded, and it looks better with the rest of the keyboard,
also more correct to represent the open box unicode space char,
instead of a smile
2022-04-02 17:36:10 +02:00
Jules Aguillon
5f47beb5b0 Add currency symbols under the Fn key
Fn+e = €
Fn+l = £
Fn+r = ₹
Fn+y = ¥
Fn+c = ¢
Fn+p = ₱
2022-04-02 16:56:40 +02:00
Raphael
2dda39f453 Arrows and Box system (#114)
* Add `Arrows` and `Box` accent system
2022-04-02 16:42:40 +02:00
nickid
fbf8901bdb Add Korean layout (#115)
* Add Korean layout
2022-04-02 16:33:32 +02:00
Raphael
723c7e9aec Upgrade CI workflow (#111)
* Cache dependencies on CI workflow

* Use available fontforge version for CI action
Avoid a dirty OS upgrade to get a newer version of FontForge,
use what is available at Ubuntu 20.04

* Upgrade CI Workflow
By using an appimage of FontForge, it's easier to install the latest version, to cache it, and there is no extra dependencies clashes with  Ubuntu 20.04

* Make paths for fontforge absolute in makefile
It's necessary because fontforge is an AppImage and requires it

* Improve cache step on CI

wget don't download a duplicate if file already exists

* Generate base64 ascii encoded debug keystore

That can be used to transfer the keystore to a Github Secret

* Restore debug.keystore from github secrets

Get the asc encoded keystore from github secrets, 
and decode it back to a bynary file inside the CI run.

* Cleanup redundant lines and add explanation comment

* runs-on  ubuntu-latest

Co-authored-by: Jules Aguillon <jules@j3s.fr>

* add *.keystore.asc to .gitignore

* Clean up lines, adjust documentation

* use CURDIR automatic makefile variable

Co-authored-by: Jules Aguillon <jules@j3s.fr>
2022-04-02 16:33:12 +02:00
Jules Aguillon
2b6c2b98e0 Compute the swipe distance from the physical dpi
The previous computation was very different depending on the device's
screen and accessibility options.
Given that the keyboard is supposed to fill all the space in one
dimension, the dpi unit makes little sense.

The formula doesn't mean anything in particular, it takes into account
both dimensions (x and y) and should be close to the dpi in the
diagonals (which is the direction of swipe).

This changes the actual value, on a 1920x1080 480dpi screen, the value
is increased by 20%.
2022-04-02 16:16:24 +02:00
ArenaL5
281f779121 µ, æ and œ also generated by Fn 2022-03-31 19:05:40 +02:00
ArenaL5
6b3123090c Add arrows
Add simple arrows to the numeric keypad. Using the Fn key with these arrows will
output double arrows.
2022-03-31 19:05:40 +02:00
ArenaL5
363a65223c Add non-breaking space as Fn+Space 2022-03-31 19:05:40 +02:00
ArenaL5
4355225646 Add extra symbols to Fn
Also removed almost all combinations of diacritics and symbols to create extra
symbols.
2022-03-31 19:05:40 +02:00
ArenaL5
21c76b5b41 Add interpunct and move Tab in Spanish keyboard
Added the middle dot (·) to the Spanish keyboard, in order to be able to type
Catalan words and names. Catalan is spoken in Eastern Spain, and the middle top
is therefore included in standard PC Spanish keyboards.

Also changed the Tab key to an upwards-leftwards swipe, as to follow more closely
the programmer's layout qwerty.xml
2022-03-31 19:05:40 +02:00
Jules Aguillon
ed2dea9630 CI: Install fontforge with Nix
And cache the nix store.
2022-03-27 16:26:58 +02:00
Jules Aguillon
67487d0ef0 Fix CI since recent font changes
Requires the latest version of fontforge.
Re-order the steps to improve caching.
2022-03-25 00:51:11 +01:00
Michael Levi
611f2c8111 More reliable CI without Nix 2022-03-25 00:16:40 +01:00
Jules Aguillon
6db57500ee Add glyphs for Tab, Backspace and Delete
Tab is from IcoMoon. Backspace and Delete are from materialdesignicons.
2022-03-25 00:12:41 +01:00
Jules Aguillon
1b6deb7fed Improve glyphs for accents
The accents are taken from the Roboto Regular font (Apache 2.0), added
the dotted circle and exported with FontForge.

The argument to FontForge's Import function are changed, the fifth
argument controls the accuracy and needed to be lowered otherwise the
grave accent wouldn't be rendered at all.
2022-03-24 23:55:20 +01:00
Raphael
94751bae3e Update Home and End glyphs
Revert them to previous version, but now using SVG icons
instead of a ttf font file
2022-03-24 18:54:41 +01:00
Jules Aguillon
0fb7150a06 Revert to the previous CI
The new CI script doesn't work on forks.

This reverts commit f3aa218de4.
This reverts commit 3373c59b90.
2022-03-24 18:43:09 +01:00
Jules Aguillon
f3aa218de4 Improve CI script
Upgrade nixbuild-action to put back spaces in the workflow name.
Improve the script for retrieving the result, thanks to @rickynils.
2022-03-23 16:27:07 +01:00
nickid
c093b45c96 Korean translations 2022-03-23 15:47:14 +01:00
Jules Aguillon
3373c59b90 CI: Use nixbuild.net
The build takes place on the remote, which takes advantage of Nix's
caching.
The previous workflow used a remote cache but in order to build locally,
all the dependencies needed to be downloaded from the cache everytime.
The dependencies are 462M, downloading took most of the time.
2022-03-23 13:02:38 +01:00
six-6
0d1ddcce3f Translate into Chinese-Simplified 2022-03-21 00:44:57 +01:00
ArenaL5
f736a169a4 Update Spanish translation
and fix a couple typos
2022-03-21 00:39:40 +01:00
ArenaL5
743f6cbc91 Add dead macron to Spanish layout
This is only to make this layout more similar to the default English layout.
Macrons are not actually used in any language spoken in Spain, but they
appear to be used in some varieties of Nahuatl?

Also added C-cedilla to the N-tilde key. Even if both C-cedilla and N-tilde
are redundant in this keyboard, both letters are a staple of Spain keyboards,
and Spaniards are used to have a dedicated key for C-cedilla in PC keyboards.
2022-03-21 00:39:40 +01:00
ArenaL5
47f9043096 Correct displayed value when cancelling settings modification
When changing any numeric setting and cancelling this change, the change would not
be persisted, but the summary in the setting screen would show the last position
of the slider instead of the correct unchanged value.

This commit fixes this on the most simple way by resetting the slider position to
the persisted value.
2022-03-21 00:39:40 +01:00
ArenaL5
a516246e52 Increase vibration maximum from 50 ms to 100 ms 2022-03-21 00:39:40 +01:00
Jules Aguillon
ba6d62dee2 Add F11 and F12
These keys are shown only when Fn is activated, "placeholder" keys are
placed in the layouts.
2022-03-19 16:27:57 +01:00
Jules Aguillon
e872c58788 Allow modifiers to hide keys
Modifiers can temporarily remove a key from the layout by returning
'null'.
Make sure pointer handling code handle these modified keys gracefully
and doesn't trigger a key event and a vibration for the removed key.
2022-03-19 15:39:20 +01:00
Jules Aguillon
57c6208b50 Add glyphs for accent keys
The "dotted circle" character combined with the accent was badly
rendered on many devices.
2022-03-18 17:31:23 +01:00
Jules Aguillon
d733f8c78c Build all special glyphs from SVG
Recover the provenance of each glyphs and remove the base_font.ttf file.
2022-03-18 12:55:08 +01:00
Jules Aguillon
e63ff8f837 Stateless build of the special font file
Keep the glyphs in SVG format and build the font using a FontForge
script.
A part of the previous font is kept because the sources is lost.

This adds a new dependency to the build system, fontforge.
2022-03-17 20:23:28 +01:00
Jules Aguillon
fe35d5fd5a Avoid ghost touches while holding modulated keys
On some devices, bogus touch events can be sent while holding a key.
With modulated keys, it can happens on top of other keys.
Ignore every new pointers when a modulated key is pressed.
2022-03-17 11:24:33 +01:00
Jules Aguillon
2eb615dbf6 Show the switching key if there's several languages
Ensure the switching key is shown when there's several subtypes enabled,
even if Android says not to show it.
2022-03-16 13:09:10 +01:00
igorSilCar
2dae2105b2 Brazilian portuguese layout (#91)
* Providing a comprehensible Brazilian Portuguese keyboard layout

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

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

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

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

* Make Locking behaviour optional, configurable in preferences

* Nest the new settings into a different page

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

* Add Fn and Meta

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

* making the swiping option more intelligible

* fix typo on full_description pt-BR translation

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

View File

@@ -9,26 +9,32 @@ jobs:
Build-Apk: Build-Apk:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install nix - uses: actions/setup-java@v2
uses: cachix/install-nix-action@v15
with: with:
nix_path: nixpkgs=channel:nixos-unstable distribution: 'zulu' # See 'Supported distributions' for available options
- uses: cachix/cachix-action@v10 java-version: '11'
with: - name: Checkout repo
name: julow
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
- name: Checkout Repo
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Cache debug certificate - name: Cache debug certificate
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: _build/debug.keystore path: _build/debug.keystore
key: debug-keystore key: debug-keystore
- name: Run nix-shell and Make - name: Restore debug keystore from github Secrets
uses: ZenithalHourlyRate/nix-shell-action@v4 run: |
with: mkdir -p _build
file: shell.nix cd "_build"
script: make # Check if exist and use the secret named DEBUG_KEYSTORE
# The contents of the secret can be obtained -
# from the debug.keystore.asc from you local _build folder
if [[ ! "${{ secrets.DEBUG_KEYSTORE }}" = "" ]]; then
echo "${{ secrets.DEBUG_KEYSTORE }}" > "debug.keystore.asc"
if [[ -s "debug.keystore.asc" ]]; then
gpg -d --passphrase "debug0" --batch "debug.keystore.asc" > "debug.keystore"
fi
fi
- name: Build
run: make
- name: Save debug apk - name: Save debug apk
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:

1
.gitignore vendored
View File

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

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="18" android:versionName="1.13.1" android:hardwareAccelerated="false"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="23" android:versionName="1.16.0" android:hardwareAccelerated="false">
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="30"/> <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"> <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"> <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` - Android SDK: build tools (minimum `28.0.1`), platform `30`
- Make sure to have the `$ANDROID_HOME` environment variable set. - 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: Building the debug apk:
@@ -20,8 +21,25 @@ Building the debug apk:
make make
``` ```
If the build succeed, the debug apk is located in If the build succeed, the debug apk is located in `_build/juloo.keyboard2.debug.apk`.
`_build/juloo.keyboard2.debug.apk`.
## Using the local debug.keystore on the Github CI actions
It's possible to save the local debug.keystore into a github secret, so the same keystore is utilized to build the debug apk in the CI github actions.
Doing this, they wil have the same signature, thus the debug apk can be updated without having to uninstall it first.
After you sucessfully run `make`, (thus a debug.keystore exists) you can use this second command to generate a base64 stringified version of it
```sh
cd _build
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
```
A file will be generated inside the local `_build/` folder, called `debug.keystore.asc`
You can copy the content of this file, and with that, paste it into a new github secret in your repo settings.
The secret must be named `DEBUG_KEYSTORE`
## Debugging on your phone ## Debugging on your phone
@@ -60,26 +78,54 @@ make installd
## Guidelines ## Guidelines
### Add a localized layout ### Adding a programming layout
Localized layouts (a layout specific to a language) are generally accepted. A programming layout must contains every ASCII characters.
The current programming layouts are: QWERTY, Dvorak.
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`.
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). 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. They don't need to contain every ASCII characters (although it's useful in
This is generally done using dead-keys, for example: 0bf7ff5 (Latvian), 573c13f (Swedish). passwords) and dead-keys.
It is also possible to add some characters that are hidden in other languages, for example 93e84ba (ß), though the space is limited.
### Add a programming layout ### Adding support for a language
A programming layout must contains every ASCII characters as well as every dead-keys. Supported locales are defined in `res/xml/method.xml`.
Currently, the only example is QWERTY.
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
Translations are always welcome ! See for example: 1723288 (Latvian), baf867a (French). Translations are always welcome !
The app can be translated by writing `res/values-<language code>/strings.xml` (for example `values-fr`, `values-lv`), based on the default: `res/values/strings.xml` (English).
The store description is found in `metadata/android/<locale>/`, `short_description.txt` and `full_description.txt`. See for example: 1723288 (Latvian), baf867a (French).
The full description changes very infrequently (it was changed once in 6 years). But if it changes too much, outdated translation might be removed. 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

@@ -6,7 +6,6 @@ ANDROID_PLATFORM_VERSION = android-30
JAVA_VERSION = 1.7 JAVA_VERSION = 1.7
SRC_DIR = srcs SRC_DIR = srcs
ASSETS_DIR = assets
RES_DIR = res RES_DIR = res
EXTRA_JARS = EXTRA_JARS =
@@ -17,9 +16,16 @@ debug: _build/$(PACKAGE_NAME).debug.apk
release: _build/$(PACKAGE_NAME).apk release: _build/$(PACKAGE_NAME).apk
installd: _build/$(PACKAGE_NAME).debug.apk installd: _build/$(PACKAGE_NAME).debug.apk
adb install "$<" adb install -r "$<"
.PHONY: release debug installd clean:
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
_build/*.idsig _build/assets
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) $(shell mkdir -p _build)
@@ -42,7 +48,6 @@ JAVAC_FLAGS = -source $(JAVA_VERSION) -target $(JAVA_VERSION) -encoding utf8
MANIFEST_FILE = AndroidManifest.xml MANIFEST_FILE = AndroidManifest.xml
JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java') JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java')
RES_FILES = $(shell find $(RES_DIR) -type f) RES_FILES = $(shell find $(RES_DIR) -type f)
ASSETS_FILES = $(shell find $(ASSETS_DIR) -type f 2>/dev/null)
# Debug signing # Debug signing
@@ -60,7 +65,7 @@ _build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
# Debug apk # Debug apk
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug _build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug --product debug
# Release signing # Release signing
@@ -76,11 +81,17 @@ _build/%.apk: _build/%.unsigned-apk %-keystore.conf
_build/%.unsigned-apk: _build/%.unaligned-apk _build/%.unsigned-apk: _build/%.unaligned-apk
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@" $(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
_build/%.unaligned-apk: _build/classes.dex $(MANIFEST_FILE) $(ASSETS_FILES) APK_EXTRA_FILES = classes.dex assets/special_font.ttf
_build/%.unaligned-apk: $(addprefix _build/,$(APK_EXTRA_FILES)) $(MANIFEST_FILE)
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \ $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS) -I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
[ -z "$(ASSETS_FILES)" ] || $(ANDROID_BUILD_TOOLS)/aapt add "$@" $(ASSETS_FILES) cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) $(APK_EXTRA_FILES)
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) classes.dex
# 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 # R.java

View File

@@ -1,8 +1,9 @@
# Unexpected Keyboard # Unexpected Keyboard
A lightweight virtual keyboard for developers. A lightweight virtual keyboard for developers.
| <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"/> |
![Unexpected Keyboard](metadata/android/en-US/images/featureGraphic.png) | --- | --- | --- |
| <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..). 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

@@ -1,15 +0,0 @@
# Fonts
The glyphs from this font are made by:
- Home and End
Author: @sdrapha
- Cog
Copyright (C) 2016 by Dave Gandy
Author: Dave Gandy
License: SIL ()
- Emoticon, PageUp and PageDown
IcoMoon-Free is a free vector icon pack by Keyamoon.
License: Attribution 4.0 International (CC BY 4.0)

Binary file not shown.

View File

@@ -0,0 +1,21 @@
Translations: Brazilian portuguese (@igorSilCar), Chinese-Simplified (@9-2-1), Korean (@notnickid)
New layouts: Swedish (@thabubble), Korean (@notnickid)
Improved computation of the swipe gesture and fix unstoppable key-repeat on
some devices.
Moved keys away from the edges of the screen and other improvements to the layouts.
Improved rendering of some symbols.
Added more characters to the keyboard:
- New combinations to Fn (@ArenaL5)
- Currency symbols
- Added arrow and box symbols (@sdrapha)
- F11 and F12.
Option for making modifiers lockable. (@sdrapha)
Fixes to the Spanish layout and other fixes. (@ArenaL5)
Many other fixes.
Huge thanks to the contributors: @igorSilCar, @sdrapha, @ArenaL5, @notnickid, @9-2-1, @thabubble

View File

@@ -0,0 +1,25 @@
Quick fix release.
Previously:
Translations: Brazilian portuguese (@igorSilCar), Chinese-Simplified (@9-2-1), Korean (@notnickid)
New layouts: Swedish (@thabubble), Korean (@notnickid)
Improved computation of the swipe gesture and fix unstoppable key-repeat on
some devices.
Moved keys away from the edges of the screen and other improvements to the layouts.
Improved rendering of some symbols.
Added more characters to the keyboard:
- New combinations to Fn (@ArenaL5)
- Currency symbols
- Added arrow and box symbols (@sdrapha)
- F11 and F12.
Option for making modifiers lockable. (@sdrapha)
Fixes to the Spanish layout and other fixes. (@ArenaL5)
Many other fixes.
Huge thanks to the contributors: @igorSilCar, @sdrapha, @ArenaL5, @notnickid, @9-2-1, @thabubble

View File

@@ -0,0 +1,4 @@
Fix compatibility with Android 6.
Translation improvements.
Huge thanks to the contributors: @marciozomb13

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,18 @@
이 앱은 안드로이드용 가상 키보드입니다. 주요 기능은 스와이프 제스처를 사용하여 모든 ASCII 문자를 쉽게 입력할 수 있다는 점과 악센트 및 수정자 키를 위한 데드 키와 특수 키(tab, esc, 방향키 등)이 있다는 것입니다.
키보드는 각 키의 모서리에 최대 4개의 추가 문자를 표시합니다. 이러한 추가 문자는 키에서 손가락을 스와이프하여 적중됩니다.
일부 하이라이트 기능:
- PC 키보드에서 사용할 수 있는 모든 문자 및 특수 키를 사요 가능합니다. 이것은 Termux와 같은 앱을 사용하는 데 효과적입니다.
- 여기에는 Tab, Esc, 방향키 및 function 키뿐만이 아닌 Ctrl 및 Alt 키도 포함되어 있습니다 !
- 악센트 키는 데드 키를 사용하여 액세스할 수 있습니다. 먼저 악센트 키를 활성화한 다음 악센트 문자를 입력합니다.
- 매우 가볍고 빠릅니다. Google 키보드보다 500배, 기본 키보드보다 15배 적은 공간을 사용합니다. 광고와 사용 기록 추적 없음.
- 다중 레이아웃: QWERTY, QWERTZ, AZERTY. 다양한 테마: White, Dark, OLED Black. 또한 다른 많은 옵션들.
다른 가상 키보드와 마찬가지로 시스템 설정에서 활성화해야 합니다. 시스템 설정을 열고 다음으로 이동합니다.
시스템 > 언어 및 입력 > 키보드 > 키보드 관리.

View File

@@ -0,0 +1 @@
개발자들을 위한 가벼운 가상 키보드.

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard - Einstellungen</string> <string name="settings_activity_label">Unexpected Keyboard - Einstellungen</string>
<string name="pref_category_layout">Layout</string> <string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Tastaturlayout ändern</string> <string name="pref_layout_title">Tastaturlayout ändern</string>
@@ -8,19 +7,18 @@
<string name="pref_accents_title">Akzente</string> <string name="pref_accents_title">Akzente</string>
<string name="pref_accents_e_all_installed">Akzente für alle installierten Sprachen anzeigen</string> <string name="pref_accents_e_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_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_accents_e_none">Akzente verbergen</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_category_typing">Tippen</string>
<string name="pref_swipe_dist_title">Länge der Wischgeste</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_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_timeout_title">Zeitüberschreitung bei Tastenwiederholung</string>
<string name="pref_long_interval_title">Intervall der 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_title">Präzise Cursorsteuerung</string>
<string name="pref_precise_repeat_summary">Geschwindigkeit der Tastenwiederholung durch weniger oder mehr Wischen anpassen</string> <string name="pref_precise_repeat_summary">Geschwindigkeit der Tastenwiederholung durch weniger oder mehr Wischen anpassen</string>
<string name="pref_lockable_keys_title">Sperrbare Hilfstasten</string>
<string name="pref_lockable_keys_summary">Hilfstasten, die durch zweimaliges Tippen gesperrt (eingerastet) werden können</string>
<string name="pref_category_style">Design</string> <string name="pref_category_style">Design</string>
<string name="pref_margin_bottom_title">Unterer Abstand</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_title">Höhe der Tastatur</string>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Ajustes de Unexpected Keyboard</string> <string name="settings_activity_label">Ajustes de Unexpected Keyboard</string>
<string name="pref_category_layout">Formato</string> <string name="pref_category_layout">Formato</string>
<string name="pref_layout_title">Cambiar formato de teclado</string> <string name="pref_layout_title">Cambiar formato de teclado</string>
@@ -8,25 +7,22 @@
<string name="pref_accents_title">Acentos</string> <string name="pref_accents_title">Acentos</string>
<string name="pref_accents_e_all_installed">Mostrar acentos para todos los lenguajes instalados</string> <string name="pref_accents_e_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_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_accents_e_none">Ocultar acentos</string>
<string name="pref_category_typing">Escribiendo</string> <string name="pref_category_typing">Escribiendo</string>
<string name="pref_swipe_dist_title">Distancia para deslizar</string> <string name="pref_swipe_dist_title">Distancia para deslizar</string>
<string name="pref_swipe_dist_summary">Distancia de caractéres en las esquinas de las letras (%s)</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_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_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_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_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_category_style">Estilo</string>
<string name="pref_margin_bottom_title">Margen del pie</string> <string name="pref_margin_bottom_title">Margen del pie</string>
<string name="pref_keyboard_height_title">Altura del teclado</string> <string name="pref_keyboard_height_title">Altura del teclado</string>
<string name="pref_horizontal_margin_title">Margen horizontal</string> <string name="pref_horizontal_margin_title">Margen horizontal</string>
<string name="pref_character_size_title">Tamaño de etiqueta</string> <string name="pref_character_size_title">Tamaño de etiqueta</string>
<string name="pref_character_size_summary">Tamaño de caractéres mostrados en el teclado (%.2fx)</string> <string name="pref_character_size_summary">Tamaño de caracteres mostrados en el teclado (%.2fx)</string>
<string name="pref_theme">Tema</string> <string name="pref_theme">Tema</string>
<string name="pref_theme_e_system">Ajustes de sistema</string> <string name="pref_theme_e_system">Ajustes de sistema</string>
<string name="pref_theme_e_dark">Oscuro</string> <string name="pref_theme_e_dark">Oscuro</string>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard Paramètres</string> <string name="settings_activity_label">Unexpected Keyboard Paramètres</string>
<string name="pref_category_layout">Disposition</string> <string name="pref_category_layout">Disposition</string>
<string name="pref_layout_title">Disposition des touches</string> <string name="pref_layout_title">Disposition des touches</string>
@@ -8,22 +7,18 @@
<string name="pref_accents_title">Accents</string> <string name="pref_accents_title">Accents</string>
<string name="pref_accents_e_all_installed">Afficher les accents pour les langues installées</string> <string name="pref_accents_e_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_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_accents_e_none">Cacher les accents</string>
<string name="pref_category_typing">Saisie</string> <string name="pref_category_typing">Saisie</string>
<string name="pref_swipe_dist_title">Distance de swipe</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_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_timeout_title">Délai avant répétition</string>
<string name="pref_long_interval_title">Écart entre répétitions</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_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_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_category_style">Style</string>
<string name="pref_margin_bottom_title">Marge du bas</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_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_horizontal_margin_title">Marge des côtés</string>
<string name="pref_character_size_title">Taille des labels</string> <string name="pref_character_size_title">Taille des labels</string>
<string name="pref_character_size_summary">Taille des caractères affichés sur les touches (%.2fx)</string> <string name="pref_character_size_summary">Taille des caractères affichés sur les touches (%.2fx)</string>

42
res/values-ko/strings.xml Normal file
View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="settings_activity_label">Unexpected Keyboard 설정</string>
<string name="pref_category_layout">레이아웃</string>
<string name="pref_layout_title">키보드 레이아웃 변경</string>
<string name="pref_layout_e_system">시스템 세팅</string>
<string name="pref_accents_title">악센트</string>
<string name="pref_accents_e_all_installed">설치된 모든 언어의 악센트 표시</string>
<string name="pref_accents_e_selected">선택한 언어의 악센트만 표시</string>
<string name="pref_accents_e_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_precise_repeat_title">정확한 커서 움직임</string>
<string name="pref_precise_repeat_summary">더 많거나 적은 스와이프로 키 반복 조절</string>
<string name="pref_category_style">스타일</string>
<string name="pref_margin_bottom_title">아래 넓이</string>
<string name="pref_keyboard_height_title">키보드 높이</string>
<string name="pref_horizontal_margin_title">양 옆 넓이</string>
<string name="pref_character_size_title">폰트 크기</string>
<string name="pref_character_size_summary">키보드의 표시되는 폰트 크기 (%.2fx)</string>
<string name="pref_theme">테마</string>
<string name="pref_theme_e_system">시스템 테마</string>
<string name="pref_theme_e_dark">Dark</string>
<string name="pref_theme_e_light">Light</string>
<string name="pref_theme_e_black">Black</string>
<string name="pref_swipe_dist_e_very_short">매우 짧음</string>
<string name="pref_swipe_dist_e_short">짧음</string>
<string name="pref_swipe_dist_e_default">보통</string>
<string name="pref_swipe_dist_e_far">넓음</string>
<string name="pref_swipe_dist_e_very_far">매우 넓음</string>
<string name="pref_key_horizontal_space">키보드 양 옆 간격</string>
<string name="pref_key_vertical_space">키보드 세로 간격</string>
<string name="key_action_next">다음</string>
<string name="key_action_done">확인</string>
<string name="key_action_go">Go</string>
<string name="key_action_prev">이전</string>
<string name="key_action_search">검색</string>
<string name="key_action_send">보내기</string>
</resources>

View File

@@ -1,11 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <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="emoji_type_button_height">48dp</dimen>
<dimen name="extra_horizontal_margin">20dp</dimen> <dimen name="extra_horizontal_margin">25dp</dimen>
</resources> </resources>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string> <string name="app_name" 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="settings_activity_label">Unexpected Keyboard iestatījumi</string>
<string name="pref_category_layout">Izkārtojums</string> <string name="pref_category_layout">Izkārtojums</string>
<string name="pref_layout_title">Mainīt tastatūras izkārtojumu</string> <string name="pref_layout_title">Mainīt tastatūras izkārtojumu</string>
@@ -8,19 +9,18 @@
<string name="pref_accents_title">Uzsvara zīmes</string> <string name="pref_accents_title">Uzsvara zīmes</string>
<string name="pref_accents_e_all_installed">Rādīt uzsvara zīmes visām uzstādītajām valodām</string> <string name="pref_accents_e_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_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_accents_e_none">Paslēpt uzsvara zīmes</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_category_typing">Rakstīšana</string>
<string name="pref_swipe_dist_title">Pavilkšanas attālums</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_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_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_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_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_precise_repeat_summary">Mainīt taustiņa atkārtošanās ātrumu ar pavilkšanas attālumu</string>
<string name="pref_lockable_keys_title">Slēdzami pārveidotājtaustiņi</string>
<string name="pref_lockable_keys_summary">Pārveidotātjtaustiņi, kas var tikt slēgti ar divkāršu piesitienu</string>
<string name="pref_category_style">Izskata pielāgojumi</string> <string name="pref_category_style">Izskata pielāgojumi</string>
<string name="pref_margin_bottom_title">Apakšējā apmale</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_title">Tastatūras augstums</string>
@@ -37,6 +37,8 @@
<string name="pref_swipe_dist_e_default">Vidējs</string> <string name="pref_swipe_dist_e_default">Vidējs</string>
<string name="pref_swipe_dist_e_far">Tāls</string> <string name="pref_swipe_dist_e_far">Tāls</string>
<string name="pref_swipe_dist_e_very_far">Ļoti 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_next">Nākamais</string>
<string name="key_action_done">Darīts</string> <string name="key_action_done">Darīts</string>
<string name="key_action_go">Aiziet</string> <string name="key_action_go">Aiziet</string>

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

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<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_none">Ocultar acentos</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>
<string name="pref_swipe_dist_title">Distância a deslizar</string>
<string name="pref_swipe_dist_summary">Distância até acionar os cantos das teclas (%s)</string>
<string name="pref_long_timeout_title">Tempo até repetir tecla</string>
<string name="pref_long_interval_title">Intervalo de repetição de tecla</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_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_horizontal_margin_title">Margem horizontal</string>
<string name="pref_character_size_title">Tamanho dos indicadores</string>
<string name="pref_character_size_summary">Tamanho dos caracteres visíveis no teclado (%.2fx)</string>
<string name="pref_theme">Tema</string>
<string name="pref_theme_e_system">Mesmo do sistema</string>
<string name="pref_theme_e_dark">Escuro</string>
<string name="pref_theme_e_light">Claro</string>
<string name="pref_theme_e_black">Preto</string>
<string name="pref_swipe_dist_e_very_short">Muito curto</string>
<string name="pref_swipe_dist_e_short">Curto</string>
<string name="pref_swipe_dist_e_default">Normal</string>
<string name="pref_swipe_dist_e_far">Longo</string>
<string name="pref_swipe_dist_e_very_far">Muito longo</string>
<string name="pref_key_horizontal_space">Distância horizontal entre teclas</string>
<string name="pref_key_vertical_space">Distância vertical entre teclas</string>
<string name="key_action_next">Próximo</string>
<string name="key_action_done">Pronto</string>
<string name="key_action_go">Ir</string>
<string name="key_action_prev">Anterior</string>
<string name="key_action_search">Buscar</string>
<string name="key_action_send">Enviar</string>
</resources>

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_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_lockable_keys_title">Sabitlenebilir değiştiriciler</string>
<string name="pref_lockable_keys_summary">Çift vuruşla sabitlenebilecek değiştirici tuşlar</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

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" product="debug">Unexpected Keyboard (debug)</string>
<string name="app_name" product="default">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard 设置</string>
<string name="pref_category_layout">布局</string>
<string name="pref_layout_title">改变键盘布局</string>
<string name="pref_layout_e_system">系统设置</string>
<string name="pref_accents_title">声调</string>
<string name="pref_accents_e_all_installed">显示所有安装的语言的声调符号</string>
<string name="pref_accents_e_selected">只显示选择的语言的声调符号</string>
<string name="pref_accents_e_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_precise_repeat_title">精确控制光标移速</string>
<string name="pref_precise_repeat_summary">按键重复按下速度由手指滑动的距离决定</string>
<string name="pref_lockable_keys_title">组合键锁定</string>
<string name="pref_lockable_keys_summary">可以通过输入两次锁定任何组合键(Ctrl, Alt, Fn, 声调符号等)</string>
<string name="pref_category_style">样式</string>
<string name="pref_margin_bottom_title">键盘下边距</string>
<string name="pref_keyboard_height_title">键盘高度</string>
<string name="pref_horizontal_margin_title">键盘左右边距</string>
<string name="pref_character_size_title">字符大小</string>
<string name="pref_character_size_summary">按键上显示的字符的大小 (%.2fx)</string>
<string name="pref_theme">主题</string>
<string name="pref_theme_e_system">跟随系统设置</string>
<string name="pref_theme_e_dark">暗色</string>
<string name="pref_theme_e_light">亮色</string>
<string name="pref_theme_e_black">黑色</string>
<string name="pref_swipe_dist_e_very_short">非常短</string>
<string name="pref_swipe_dist_e_short"></string>
<string name="pref_swipe_dist_e_default">中(默认)</string>
<string name="pref_swipe_dist_e_far"></string>
<string name="pref_swipe_dist_e_very_far">非常长</string>
<string name="pref_key_horizontal_space">按键的左右边距</string>
<string name="pref_key_vertical_space">按键的上下边距</string>
<string name="key_action_next">下一项</string>
<string name="key_action_done">完成</string>
<string name="key_action_go">前往</string>
<string name="key_action_prev">前一项</string>
<string name="key_action_search">搜索</string>
<string name="key_action_send">发送</string>
</resources>

View File

@@ -4,34 +4,60 @@
<item>system</item> <item>system</item>
<item>azerty</item> <item>azerty</item>
<item>qwerty</item> <item>qwerty</item>
<item>qwerty_pt</item>
<item>qwerty_es</item> <item>qwerty_es</item>
<item>qwerty_ko</item>
<item>qwerty_lv</item> <item>qwerty_lv</item>
<item>qwerty_sv_se</item>
<item>qwerty_hu</item>
<item>qwerty_tr</item>
<item>ru_jcuken</item> <item>ru_jcuken</item>
<item>qwertz</item> <item>qwertz</item>
<item>qwertz_hu</item>
<item>bgph1</item> <item>bgph1</item>
<item>dvorak</item> <item>dvorak</item>
<item>colemak</item>
<item>neo2</item>
</string-array> </string-array>
<string-array name="pref_layout_entries"> <string-array name="pref_layout_entries">
<item>@string/pref_layout_e_system</item> <item>@string/pref_layout_e_system</item>
<item>AZERTY</item> <item>AZERTY</item>
<item>QWERTY</item> <item>QWERTY</item>
<item>QWERTY (Brasileiro)</item>
<item>QWERTY (Español)</item> <item>QWERTY (Español)</item>
<item>QWERTY (Korean)</item>
<item>QWERTY (Latvian)</item> <item>QWERTY (Latvian)</item>
<item>QWERTY (Swedish)</item>
<item>QWERTY (Hungarian)</item>
<item>QWERTY (Türkçe)</item>
<item>ЙЦУКЕН (Русский)</item> <item>ЙЦУКЕН (Русский)</item>
<item>QWERTZ</item> <item>QWERTZ</item>
<item>QWERTZ (Hungarian)</item>
<item>Bulgarian (Phonetic Traditional)</item> <item>Bulgarian (Phonetic Traditional)</item>
<item>Dvorak</item> <item>Dvorak</item>
<item>Colemak</item>
<item>Neo 2</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>
<string-array name="pref_accents_entries"> <string-array name="pref_accents_entries">
<item>@string/pref_accents_e_all_installed</item> <item>@string/pref_accents_e_all_installed</item>
<item>@string/pref_accents_e_selected</item> <item>@string/pref_accents_e_selected</item>
<item>@string/pref_accents_e_all</item>
<item>@string/pref_accents_e_none</item> <item>@string/pref_accents_e_none</item>
</string-array> </string-array>
<string-array name="pref_accents_values"> <string-array name="pref_accents_values">
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>
<item>3</item>
<item>4</item> <item>4</item>
</string-array> </string-array>
<string-array name="pref_theme_entries"> <string-array name="pref_theme_entries">

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Unexpected Keyboard</string> <string name="app_name" product="debug">Unexpected Keyboard (debug)</string>
<string name="app_name" product="default">Unexpected Keyboard</string>
<string name="settings_activity_label">Unexpected Keyboard Settings</string> <string name="settings_activity_label">Unexpected Keyboard Settings</string>
<string name="pref_category_layout">Layout</string> <string name="pref_category_layout">Layout</string>
<string name="pref_layout_title">Change keyboard layout</string> <string name="pref_layout_title">Change keyboard layout</string>
@@ -8,22 +9,22 @@
<string name="pref_accents_title">Accents</string> <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_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_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_accents_e_none">Hide accents</string>
<string name="pref_programming_layout_title">Keyboard layout for programming</string>
<string name="pref_programming_layout_none">None</string>
<string name="pref_category_typing">Typing</string> <string name="pref_category_typing">Typing</string>
<string name="pref_swipe_dist_title">Swiping distance</string> <string name="pref_swipe_dist_title">Swiping distance</string>
<string name="pref_swipe_dist_summary">Distance of characters in the corners of the keys (%s)</string> <string name="pref_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_timeout_title">Key repeat timeout</string>
<string name="pref_long_interval_title">Key repeat interval</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_title">Precise cursor movements</string>
<string name="pref_precise_repeat_summary">Modulate key repeat speed by swiping more or less</string> <string name="pref_precise_repeat_summary">Modulate key repeat speed by swiping more or less</string>
<string name="pref_lockable_keys_title">Lockable modifiers</string>
<string name="pref_lockable_keys_summary">Modifiers that can be locked by typing them twice</string>
<string name="pref_category_style">Style</string> <string name="pref_category_style">Style</string>
<string name="pref_margin_bottom_title">Margin bottom</string> <string name="pref_margin_bottom_title">Margin bottom</string>
<string name="pref_keyboard_height_title">Keyboard height</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_horizontal_margin_title">Horizontal margin</string>
<string name="pref_character_size_title">Label size</string> <string name="pref_character_size_title">Label size</string>
<string name="pref_character_size_summary">Size of characters displayed on the keyboard (%.2fx)</string> <string name="pref_character_size_summary">Size of characters displayed on the keyboard (%.2fx)</string>

View File

@@ -20,10 +20,20 @@
<attr name="emoji_color" type="color" format="color"/> <attr name="emoji_color" type="color" format="color"/>
<attr name="emoji_key_bg" type="color" format="color"/> <attr name="emoji_key_bg" type="color" format="color"/>
<attr name="emoji_key_text" 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> </declare-styleable>
<style name="Dark"> <style name="BaseTheme">
<item name="android:isLightTheme">false</item>
<item name="android:forceDarkAllowed">false</item> <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="colorKeyboard">#1b1b1b</item>
<item name="colorKey">#333333</item> <item name="colorKey">#333333</item>
<item name="colorKeyActivated">#1b1b1b</item> <item name="colorKeyActivated">#1b1b1b</item>
@@ -31,15 +41,11 @@
<item name="colorLabelActivated">#3399ff</item> <item name="colorLabelActivated">#3399ff</item>
<item name="colorLabelLocked">#33cc33</item> <item name="colorLabelLocked">#33cc33</item>
<item name="colorSubLabel">#cccccc</item> <item name="colorSubLabel">#cccccc</item>
<item name="keyBorderRadius">5dp</item>
<item name="emoji_button_bg" type="color">#202020</item> <item name="emoji_button_bg" type="color">#202020</item>
<item name="emoji_color" type="color">#ffffff</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>
<style name="Light"> <style name="Light" parent="BaseTheme">
<item name="android:isLightTheme">true</item> <item name="android:isLightTheme">true</item>
<item name="android:forceDarkAllowed">false</item>
<item name="colorKeyboard">#e3e3e3</item> <item name="colorKeyboard">#e3e3e3</item>
<item name="colorKey">#cccccc</item> <item name="colorKey">#cccccc</item>
<item name="colorKeyActivated">#e3e3e3</item> <item name="colorKeyActivated">#e3e3e3</item>
@@ -47,15 +53,11 @@
<item name="colorLabelActivated">#0066cc</item> <item name="colorLabelActivated">#0066cc</item>
<item name="colorLabelLocked">#33cc33</item> <item name="colorLabelLocked">#33cc33</item>
<item name="colorSubLabel">#333333</item> <item name="colorSubLabel">#333333</item>
<item name="keyBorderRadius">5dp</item> <item name="emoji_button_bg">#dedede</item>
<item name="emoji_button_bg" type="color">#dedede</item> <item name="emoji_color">#000000</item>
<item name="emoji_color" type="color">#000000</item>
<item name="emoji_key_bg" type="color">?attr/emoji_button_bg</item>
<item name="emoji_key_text" type="color">?attr/colorLabel</item>
</style> </style>
<style name="Black"> <style name="Black" parent="BaseTheme">
<item name="android:isLightTheme">false</item> <item name="android:isLightTheme">false</item>
<item name="android:forceDarkAllowed">false</item>
<item name="colorKeyboard">#000000</item> <item name="colorKeyboard">#000000</item>
<item name="colorKey">#000000</item> <item name="colorKey">#000000</item>
<item name="colorKeyActivated">#333333</item> <item name="colorKeyActivated">#333333</item>
@@ -64,9 +66,7 @@
<item name="colorLabelLocked">#00ff26</item> <item name="colorLabelLocked">#00ff26</item>
<item name="colorSubLabel">#bbbbbb</item> <item name="colorSubLabel">#bbbbbb</item>
<item name="keyBorderRadius">1dp</item> <item name="keyBorderRadius">1dp</item>
<item name="emoji_button_bg" type="color">#000000</item> <item name="emoji_button_bg">#000000</item>
<item name="emoji_color" type="color">#ffffff</item> <item name="emoji_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>
</resources> </resources>

View File

@@ -7,10 +7,10 @@
<dimen name="key_vertical_interval">2dp</dimen> <dimen name="key_vertical_interval">2dp</dimen>
<dimen name="key_horizontal_interval">2dp</dimen> <dimen name="key_horizontal_interval">2dp</dimen>
<dimen name="key_height">51dp</dimen> <dimen name="key_height">51dp</dimen>
<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_type_button_height">56dp</dimen>
<dimen name="emoji_grid_height">250dp</dimen> <dimen name="emoji_grid_height">250dp</dimen>
<dimen name="emoji_text_size">28dp</dimen> <dimen name="emoji_text_size">28dp</dimen>
<dimen name="extra_horizontal_margin">0dp</dimen> <dimen name="extra_horizontal_margin">0dp</dimen>
<bool name="debug_logs" product="debug">true</bool>
<bool name="debug_logs" product="default">false</bool>
</resources> </resources>

View File

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

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<row height="0.95"> <row height="0.95">
<key width="1.8" key0="ctrl" key2="meta" key3="switch_numeric"/> <key width="1.8" key0="ctrl" key2="meta" key4="switch_numeric"/>
<key width="1.2" key0="alt" key1="fn" key2="change_method" key3="switch_emoji" key4="config"/> <key width="1.2" key0="fn" key1="alt" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/> <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.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/> <key width="1.8" key0="enter" key2="action"/>
</row> </row>

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

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

View File

@@ -1,36 +1,36 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="я" key1="esc" key2="1" key3=" key4="!"/> <key key0="я" key2="1" key4="esc"/>
<key key0="в" key2="2" key3="\@"/> <key key0="в" key1="!" key2="2" key3="\@" key4="ч"/>
<key key0="е" key2="3" key3="\#" key4="№"/> <key key0="е" key2="3" key3="\#" key4="№"/>
<key key0="р" key2="4" key3="$"/> <key key0="р" key2="4" key3="$"/>
<key key0="т" key2="5" key3="%"/> <key key0="т" key2="5" key3="%"/>
<key key0="ъ" key2="6" key3="^" key4="€"/> <key key0="ъ" key2="6" key3="^" key4="€"/>
<key key0="у" key2="7" key3="&amp;" key4="§"/> <key key0="у" key2="7" key3="&amp;" key4="§"/>
<key key0="и" key2="8" key3="*"/> <key key0="и" key2="8" key3="*"/>
<key key0="о" key1="accent_macron" key2="9" key3="(" key4=")"/> <key key0="о" key2="9" key3="(" key4=")"/>
<key key0="п" key2="0" key3="ш" key4="/> <key key0="п" key2="0" key3="f11_placeholder" key4="f12_placeholder"/>
</row> </row>
<row> <row>
<key shift="0.5" key0="а" key1="tab" key2="`"/> <key shift="0.5" key0="а" key1="tab" key2="`"/>
<key key0="с" key2="£"/> <key key0="с"/>
<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="х" key2="=" key3="+"/>
<key key0="й" key1="accent_trema" key2="accent_circonflexe" key4="}" key3="{"/> <key key0="й" key4="}" key3="{"/>
<key key0="к" key3="[" key4="]"/> <key key0="к" key2="ш" key3="[" key4="]"/>
<key key0="л" key2="|" key3="\\" key4="ю"/> <key key0="л" key1="щ" key2="|" key3="\\" key4="ю"/>
</row> </row>
<row> <row>
<key width="1.5" key0="shift"/> <key width="1.5" key0="shift"/>
<key key0="з"/> <key key0="з"/>
<key key0="ь" key1="accent_ring" key3="ѝ"/> <key key0="ь" key3="ѝ"/>
<key key0="ц" key1="accent_cedille" key2="&lt;" key3="."/> <key key0="ц" key2="&lt;" key3="."/>
<key key0="ж" key2="&gt;" key3=","/> <key key0="ж" key2="&gt;" key3=","/>
<key key0="б" key2="\?" key3="/"/> <key key0="б" key2="\?" key3="/"/>
<key key0="н" key1="accent_tilde" key2=":" key3=";"/> <key key0="н" key2=":" key3=";"/>
<key key0="м" key2="&quot;" key3="'"/> <key key0="м" key2="&quot;" key3="'"/>
<key width="1.5" key0="backspace" key2="delete"/> <key width="1.5" key0="backspace" key2="delete"/>
</row> </row>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="й" key1="esc" key2="1" key3="~" key4="!"/> <key key0="й" key2="1" key4="esc"/>
<key key0="ц" key2="2" key3="\@"/> <key key0="ц" key2="2" key3="\@" key4="~"/>
<key key0="у" key2="3" key3="\#"/> <key key0="у" key2="3" key3="\#" key4="!"/>
<key key0="к" key2="4" key3="$"/> <key key0="к" key2="4" key3="$"/>
<key key0="е" key1="ё" key2="5" key3="%"/> <key key0="е" key1="ё" key2="5" key3="%"/>
<key key0="н" key2="6" key3="^"/> <key key0="н" key2="6" key3="^"/>
@@ -11,8 +11,8 @@
<key key0="ш" key2="8" key3="*"/> <key key0="ш" key2="8" key3="*"/>
<key key0="щ" key2="9" key3="(" key4=")"/> <key key0="щ" key2="9" key3="(" key4=")"/>
<key key0="з" key2="0"/> <key key0="з" key2="0"/>
<key key0="х" key1="{" key2="}"/> <key key0="х" key1="{" key2="}" key4="f11_placeholder"/>
<key key0="ъ" key1="[" key2="]" /> <key key0="ъ" key1="[" key2="]" key4="f12_placeholder"/>
</row> </row>
<row> <row>
<key shift="0.5" key0="ф" key1="tab" key2="`"/> <key shift="0.5" key0="ф" key1="tab" key2="`"/>

View File

@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true"> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys=euro"/> <subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=bgph1,extra_keys="/>
<subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz,extra_keys=trema|szlig|euro"/> <subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwertz,extra_keys=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=pound|euro"/> <subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=£|€"/>
<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="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty"/>
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_es,extra_keys=grave|aigu|tilde|trema|euro"/> <subtype android:label="%s" android:languageTag="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=grave|aigu|circonflexe|cedille|trema|euro"/> <subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=azerty,extra_keys=accent_grave|accent_aigu|accent_circonflexe|accent_cedille|accent_trema|"/>
<subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=grave|aigu|euro"/> <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="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_lv,extra_keys=caron|cedille|macron|euro"/> <subtype android:label="%s" android:languageTag="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="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=aigu|cedille|circonflexe|grave|tilde|euro"/> <subtype android:label="%s" android:languageTag="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="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="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=ru_jcuken"/>
<subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty,extra_keys=aigu|trema|ring|euro"/> <subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=qwerty_sv_se,extra_keys=accent_aigu|accent_trema|accent_ring|"/>
<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|₺|ı|ğ"/>
</input-method> </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="meta" key4="switch_numeric"/>
<key width="1.2" key0="fn" key1="alt" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space" key1="switch_programming" edgekeys="true"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key key0="j" key4=";"/>
<key width="1.8" key0="enter" key2="action"/>
</row>
</keyboard>

View File

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

View File

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

View File

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

37
res/xml/qwerty_ko.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="\#"/>
<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="ㅔ" key2="0" key3="f11_placeholder" key4="f12_placeholder"/>
</row>
<row>
<key shift="0.5" key0="ㅁ" key1="tab" key2="`"/>
<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.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

@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="q" key1="esc" key2="1" key3="~" key4="!"/> <key key0="q" key2="1" key4="esc"/>
<key key0="w" key2="2" key3="\@"/> <key key0="w" key1="~" key2="2" key3="\@" key4="!"/>
<key key0="e" key1="ē" key2="3" key3="\#" key4="€"/> <key key0="e" key1="ē" key2="3" key3="\#" key4="€"/>
<key key0="r" key1="ŗ" key2="4" key3="$"/> <key key0="r" key1="ŗ" key2="4" key3="$" key4="f11_placeholder"/>
<key key0="t" key2="5" key3="%"/> <key key0="t" key2="5" key3="%" key4="f12_placeholder"/>
<key key0="y" key2="6" key3="^"/> <key key0="y" key2="6" key3="^"/>
<key key0="u" key1="ū" key2="7" key3="&amp;"/> <key key0="u" key1="ū" key2="7" key3="&amp;" key4="*"/>
<key key0="i" key1="ī" key2="8" key3="*"/> <key key0="i" key1="ī" key2="8" key3="(" key4=")"/>
<key key0="o" key1="ō" key2="9" key3="(" key4=")"/> <key key0="o" key1="ō" key2="9" key3="{" key4="}"/>
<key key0="p" key2="0" key3="{" key4="}"/> <key key0="p" key2="0"/>
</row> </row>
<row> <row>
<key shift="0.5" key0="a" key1="ā"/> <key shift="0.5" key0="a" key1="ā" key2="tab"/>
<key key0="s" key1="š" key3="ß"/> <key key0="s" key1="š" key3="loc ß" key4="loc accent_ogonek"/>
<key key0="d" key2="£"/> <key key0="d"/>
<key key0="f"/> <key key0="f" key1="loc accent_dot_above"/>
<key key0="g" key1="ģ"/> <key key0="g" key1="ģ"/>
<key key0="h" key2="accent_macron" key3="accent_caron" key4="accent_cedille"/> <key key0="h" key2="accent_macron" key3="accent_caron" key4="accent_cedille"/>
<key key0="j" key1="+" key2="=" key3="-" key4="_"/> <key key0="j" key1="+" key2="=" key3="-" key4="_"/>
@@ -24,7 +24,7 @@
<key key0="l" key1="ļ" key2="|" key3="/" key4="\\"/> <key key0="l" key1="ļ" key2="|" key3="/" key4="\\"/>
</row> </row>
<row> <row>
<key width="1.5" key0="shift" key1="tab"/> <key width="1.5" key0="shift"/>
<key key0="z" key1="ž"/> <key key0="z" key1="ž"/>
<key key0="x"/> <key key0="x"/>
<key key0="c" key1="č"/> <key key0="c" key1="č"/>

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

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key2="1" key4="esc"/>
<key key0="w" key1="~" key2="2" 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" 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" key2="0" key3="\\"/>
</row>
<row>
<key key0="a" key2="tab" key4="`"/>
<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="_"/>
<key key0="k" key1="accent_grave" key2="accent_aigu" key3="accent_tilde" key4="accent_circonflexe"/>
<key key0="l" key1="[" key2="]" key3="{" key4="}"/>
<key key0="ç" key1="|"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="z"/>
<key key0="x"/>
<key key0="c"/>
<key key0="v"/>
<key key0="b"/>
<key key0="n" key1="&lt;" key2="&gt;" key3="," key4="."/>
<key key0="m" key1=":" key2=";" key3="/" key4="\?"/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

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

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<keyboard>
<row>
<key key0="q" key4="esc" key2="1"/>
<key key0="w" key2="2" key3="`" key4="\@"/>
<key key0="e" key2="3" key4="\#" key3="€"/>
<key key0="r" key2="4" key4="$"/>
<key key0="t" key2="5" key3="&amp;" key4="|"/>
<key key0="y" key2="6" key3="^" key4="%"/>
<key key0="u" key2="7" key3="~" key4="\\"/>
<key key0="i" key2="8" key3="*" key4="/"/>
<key key0="o" key2="9" key3="+" key4="-"/>
<key key0="p" key2="0" key3="=" key4="f11_placeholder"/>
<key key0="å" key1="\?" key3="!" key4="f12_placeholder"/>
</row>
<row>
<key key0="a" key2="tab"/>
<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="}"/>
<key key0="k" key1="[" key4="]"/>
<key key0="l" key1="(" key4=")"/>
<key key0="ö" key1="&lt;" key4="&gt;"/>
<key key0="ä" key1="'" key3="&quot;"/>
</row>
<row>
<key width="1.5" key0="shift"/>
<key key0="z"/>
<key key0="x"/>
<key key0="c"/>
<key key0="v"/>
<key key0="b" key2=";" key4=","/>
<key key0="n" key2=":" key4="."/>
<key key0="m" key2="-" key4="_"/>
<key width="1.0" key0="." key1="!" key2="\?" key3="'" key4=","/>
<key width="1.5" key0="backspace" key2="delete"/>
</row>
</keyboard>

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

@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard> <keyboard>
<row> <row>
<key key0="q" key1="esc" key2="1" key3="\@" key4="!"/> <key key0="q" key2="1" key4="esc"/>
<key key0="w" key1="^" key2="2" key3="&quot;"/> <key key0="w" key1="^" key2="2" key3="&quot;" key4="\@"/>
<key key0="e" key1="§" key2="3" key4="€"/> <key key0="e" key1="§" key2="3" key3="!" key4="€"/>
<key key0="r" key2="4" key3="$"/> <key key0="r" key2="4" key3="$" key4="f11_placeholder"/>
<key key0="t" key2="5" key3="%"/> <key key0="t" key2="5" key3="%" key4="f12_placeholder"/>
<key key0="z" key2="6" key3="&amp;" key4="{"/> <key key0="z" key2="6" key3="&amp;" key4="{"/>
<key key0="u" key2="7" key3="ü" key4="}"/> <key key0="u" key2="7" key3="ü" key4="}"/>
<key key0="i" key1="(" key2="8" key4="["/> <key key0="i" key1="(" key2="8" key3="[" key4="]"/>
<key key0="o" key1=")" key2="9" key3="ö" key4="]"/> <key key0="o" key1=")" key2="9" key3="ö" key4="="/>
<key key0="p" key1="=" key2="0" key3="\?"/> <key key0="p" key2="0" key3="\?"/>
</row> </row>
<row> <row>
<key shift="0.5" key0="a" key1="tab" key2="`" key3="ä"/> <key shift="0.5" key0="a" key1="tab" key2="`" key3="ä"/>
<key key0="s" key3="ß"/> <key key0="s" key3="ß"/>
<key key0="d" key2="£"/> <key key0="d"/>
<key key0="f" key1="~"/> <key key0="f" key1="~"/>
<key key0="g" key3="-"/> <key key0="g" key3="-"/>
<key key0="h" key3="+"/> <key key0="h" key3="+"/>

37
res/xml/qwertz_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" 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" 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

@@ -3,21 +3,29 @@
<PreferenceCategory android:title="@string/pref_category_layout"> <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="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="accents" android:title="@string/pref_accents_title" android:summary="%s" android:defaultValue="1" android:entries="@array/pref_accents_entries" android:entryValues="@array/pref_accents_values"/>
<ListPreference android:key="programming_layout" android:title="@string/pref_programming_layout_title" android:summary="%s" android:defaultValue="none" android:entries="@array/pref_programming_layout_entries" android:entryValues="@array/pref_programming_layout_values"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_typing"> <PreferenceCategory android:title="@string/pref_category_typing">
<ListPreference android:key="swipe_dist" android:title="@string/pref_swipe_dist_title" android:summary="@string/pref_swipe_dist_summary" android:defaultValue="15" android:entries="@array/pref_swipe_dist_entries" android:entryValues="@array/pref_swipe_dist_values"/> <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_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"/> <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="precise_repeat" android:title="@string/pref_precise_repeat_title" android:summary="@string/pref_precise_repeat_summary" android:defaultValue="true"/>
</PreferenceCategory> <PreferenceScreen android:title="@string/pref_lockable_keys_title" android:summary="@string/pref_lockable_keys_summary">
<PreferenceCategory android:title="@string/pref_category_vibrate"> <CheckBoxPreference android:key="lockable_shift" android:title="Shift" android:defaultValue="true"/>
<CheckBoxPreference android:key="vibrate_enabled" android:title="@string/pref_vibrate_title" android:summary="@string/pref_vibrate_summary" android:defaultValue="true"/> <CheckBoxPreference android:key="lockable_ctrl" android:title="Ctrl" android:defaultValue="false"/>
<juloo.common.IntSlideBarPreference android:key="vibrate_duration" android:title="@string/pref_vibrate_duration_title" android:summary="%sms" android:defaultValue="20" min="5" max="50"/> <CheckBoxPreference android:key="lockable_alt" android:title="Alt" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_fn" android:title="Fn" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_meta" android:title="Meta" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_sup" android:title="Sup" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_sub" android:title="Sub" android:defaultValue="false"/>
<CheckBoxPreference android:key="lockable_box" android:title="Box" android:defaultValue="false"/>
</PreferenceScreen>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_style"> <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"/> <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="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" 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.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.SlideBarPreference android:key="character_size" android:title="@string/pref_character_size_title" android:summary="@string/pref_character_size_summary" android:defaultValue="1.0" min="0.8" max="1.2"/>
<juloo.common.IntSlideBarPreference android:key="key_vertical_space" android:title="@string/pref_key_vertical_space" android:summary="%sdp" android:defaultValue="2" min="0" max="8"/> <juloo.common.IntSlideBarPreference android:key="key_vertical_space" android:title="@string/pref_key_vertical_space" android:summary="%sdp" android:defaultValue="2" min="0" max="8"/>

View File

@@ -14,6 +14,6 @@ let
in in
pkgs.mkShell { pkgs.mkShell {
buildInputs = [ pkgs.findutils jdk android.androidsdk ]; buildInputs = [ pkgs.findutils jdk android.androidsdk pkgs.fontforge ];
ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk"; ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk";
} }

View File

@@ -95,6 +95,10 @@ public class IntSlideBarPreference extends DialogPreference
{ {
if (positiveResult) if (positiveResult)
persistInt(_seekBar.getProgress() + _min); persistInt(_seekBar.getProgress() + _min);
else
_seekBar.setProgress(getPersistedInt(_min) - _min);
updateText();
} }
protected View onCreateDialogView() protected View onCreateDialogView()

View File

@@ -99,6 +99,10 @@ public class SlideBarPreference extends DialogPreference
{ {
if (positiveResult) if (positiveResult)
persistFloat(_value); persistFloat(_value);
else
_seekBar.setProgress((int)((getPersistedFloat(_min) - _min) * STEPS / (_max - _min)));
updateText();
} }
protected View onCreateDialogView() protected View onCreateDialogView()

View File

@@ -8,6 +8,10 @@ import android.os.Build;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.KeyEvent;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
final class Config final class Config
{ {
@@ -20,10 +24,8 @@ final class Config
// From preferences // From preferences
public int layout; // Or '-1' for the system defaults public int layout; // Or '-1' for the system defaults
private float swipe_dist_dp; public int programming_layout; // Or '-1' for none
public float swipe_dist_px; public float swipe_dist_px;
public boolean vibrateEnabled;
public long vibrateDuration;
public long longPressTimeout; public long longPressTimeout;
public long longPressInterval; public long longPressInterval;
public float marginBottom; public float marginBottom;
@@ -32,16 +34,18 @@ final class Config
public float keyVerticalInterval; public float keyVerticalInterval;
public float keyHorizontalInterval; public float keyHorizontalInterval;
public boolean preciseRepeat; public boolean preciseRepeat;
public Set<KeyValue.Modifier> lockable_modifiers = new HashSet<KeyValue.Modifier>();
public float characterSize; // Ratio public float characterSize; // Ratio
public int accents; // Values are R.values.pref_accents_v_* public int accents; // Values are R.values.pref_accents_v_*
public int theme; // Values are R.style.* public int theme; // Values are R.style.*
// Dynamically set // Dynamically set
public boolean shouldOfferSwitchingToNextInputMethod; public boolean shouldOfferSwitchingToNextInputMethod;
public int key_flags_to_remove; public boolean shouldOfferSwitchingToProgramming;
public String actionLabel; // Might be 'null' public String actionLabel; // Might be 'null'
public int actionId; // Meaningful only when 'actionLabel' isn't 'null' public int actionId; // Meaningful only when 'actionLabel' isn't 'null'
public boolean swapEnterActionKey; // Swap the "enter" and "action" keys public boolean swapEnterActionKey; // Swap the "enter" and "action" keys
public Set<KeyValue> extra_keys; // 'null' means all the keys
public final IKeyEventHandler handler; public final IKeyEventHandler handler;
@@ -51,12 +55,11 @@ final class Config
// static values // static values
marginTop = res.getDimension(R.dimen.margin_top); marginTop = res.getDimension(R.dimen.margin_top);
keyPadding = res.getDimension(R.dimen.key_padding); keyPadding = res.getDimension(R.dimen.key_padding);
labelTextSize = res.getFloat(R.integer.label_text_size); labelTextSize = 0.33f;
sublabelTextSize = res.getFloat(R.integer.sublabel_text_size); sublabelTextSize = 0.22f;
// default values // default values
layout = -1; layout = -1;
vibrateEnabled = true; programming_layout = -1;
vibrateDuration = 20;
longPressTimeout = 600; longPressTimeout = 600;
longPressInterval = 65; longPressInterval = 65;
marginBottom = res.getDimension(R.dimen.margin_bottom); marginBottom = res.getDimension(R.dimen.margin_bottom);
@@ -71,10 +74,11 @@ final class Config
refresh(context); refresh(context);
// initialized later // initialized later
shouldOfferSwitchingToNextInputMethod = false; shouldOfferSwitchingToNextInputMethod = false;
key_flags_to_remove = 0; shouldOfferSwitchingToProgramming = false;
actionLabel = null; actionLabel = null;
actionId = 0; actionId = 0;
swapEnterActionKey = false; swapEnterActionKey = false;
extra_keys = null;
handler = h; handler = h;
} }
@@ -86,38 +90,120 @@ final class Config
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Resources res = context.getResources(); Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics(); DisplayMetrics dm = res.getDisplayMetrics();
// The height of the keyboard is relative to the height of the screen. This // The height of the keyboard is relative to the height of the screen.
// is not the actual size of the keyboard, which will be bigger if the // This is the height of the keyboard if it have 4 rows.
// layout has a fifth row.
int keyboardHeightPercent; 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 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 else
{ {
keyboardHeightPercent = prefs.getInt("keyboard_height", 35); keyboardHeightPercent = prefs.getInt("keyboard_height", 35);
} }
layout = layoutId_of_string(prefs.getString("layout", "system")); String layout_s = prefs.getString("layout", "system");
swipe_dist_dp = Float.valueOf(prefs.getString("swipe_dist", "15")); layout = layout_s.equals("system") ? -1 : layoutId_of_string(layout_s);
swipe_dist_px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, swipe_dist_dp, dm); String prog_layout_s = prefs.getString("programming_layout", "none");
vibrateEnabled = prefs.getBoolean("vibrate_enabled", vibrateEnabled); programming_layout = prog_layout_s.equals("none") ? -1 : layoutId_of_string(prog_layout_s);
vibrateDuration = prefs.getInt("vibrate_duration", (int)vibrateDuration); // The swipe distance is defined relatively to the "exact physical pixels
// per inch of the screen", which isn't affected by the scaling settings.
// Take the mean of both dimensions as an approximation of the diagonal.
float physical_scaling = (dm.widthPixels + dm.heightPixels) / (dm.xdpi + dm.ydpi);
swipe_dist_px = Float.valueOf(prefs.getString("swipe_dist", "15")) * physical_scaling;;
longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout); longPressTimeout = prefs.getInt("longpress_timeout", (int)longPressTimeout);
longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval); longPressInterval = prefs.getInt("longpress_interval", (int)longPressInterval);
marginBottom = getDipPref(dm, prefs, "margin_bottom", marginBottom); marginBottom = getDipPref(dm, prefs, "margin_bottom", marginBottom);
keyVerticalInterval = getDipPref(dm, prefs, "key_vertical_space", keyVerticalInterval); 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 // Do not substract keyVerticalInterval from keyHeight because this is done
// during rendered. // during rendered.
keyHeight = dm.heightPixels * keyboardHeightPercent / 100 / 4; 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); preciseRepeat = prefs.getBoolean("precise_repeat", preciseRepeat);
characterSize = prefs.getFloat("character_size", characterSize); lockable_modifiers.clear();
if (prefs.getBoolean("lockable_shift", true)) 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")); accents = Integer.valueOf(prefs.getString("accents", "1"));
theme = getThemeId(res, prefs.getString("theme", "")); theme = getThemeId(res, prefs.getString("theme", ""));
} }
/** Update the layout according to the configuration.
* - Remove the switching key if it isn't needed
* - 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 original_kw)
{
// Update the name to avoid caching in KeyModifier
final KeyValue action_key = (actionLabel == null) ? null :
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>(this.extra_keys);
KeyboardData kw = original_kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key)
{
if (key == null)
return null;
boolean is_extra_key = extra_keys.contains(key);
if (is_extra_key)
extra_keys.remove(key);
int flags = key.getFlags();
if ((flags & KeyValue.FLAG_LOCALIZED) != 0 && !is_extra_key)
return null;
switch (key.getKind())
{
case Event:
switch (key.getEvent())
{
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;
}
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(flags | 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) private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
{ {
float value; float value;
@@ -152,35 +238,22 @@ final class Config
switch (name) switch (name)
{ {
case "azerty": return R.xml.azerty; case "azerty": return R.xml.azerty;
case "qwerty": return R.xml.qwerty;
case "qwerty_lv": return R.xml.qwerty_lv;
case "qwerty_es": return R.xml.qwerty_es;
case "ru_jcuken": return R.xml.local_ru_jcuken;
case "qwertz": return R.xml.qwertz;
case "bgph1": return R.xml.local_bgph1; case "bgph1": return R.xml.local_bgph1;
case "colemak": return R.xml.colemak;
case "dvorak": return R.xml.dvorak; case "dvorak": return R.xml.dvorak;
case "system": default: return -1; case "neo2": return R.xml.neo2;
} case "qwerty_es": return R.xml.qwerty_es;
} case "qwerty_hu": return R.xml.qwerty_hu;
case "qwerty_ko": return R.xml.qwerty_ko;
/* Used for the accents option. */ case "qwerty_lv": return R.xml.qwerty_lv;
public static int extra_key_flag_of_name(String name) case "qwerty_pt": return R.xml.qwerty_pt;
{ case "qwerty_tr": return R.xml.qwerty_tr;
switch (name) case "qwerty": return R.xml.qwerty;
{ case "qwerty_sv_se": return R.xml.qwerty_sv_se;
case "aigu": return KeyValue.FLAG_ACCENT2; case "qwertz_hu": return R.xml.qwertz_hu;
case "caron": return KeyValue.FLAG_ACCENT_CARON; case "qwertz": return R.xml.qwertz;
case "cedille": return KeyValue.FLAG_ACCENT5; case "ru_jcuken": return R.xml.local_ru_jcuken;
case "circonflexe": return KeyValue.FLAG_ACCENT3; default: return R.xml.qwerty; // The config might store an invalid layout, don't crash
case "grave": return KeyValue.FLAG_ACCENT1;
case "macron": return KeyValue.FLAG_ACCENT_MACRON;
case "ring": return KeyValue.FLAG_ACCENT_RING;
case "szlig": return KeyValue.FLAG_LANG_SZLIG;
case "euro": return KeyValue.FLAG_LANG_EURO;
case "pound": return KeyValue.FLAG_LANG_POUND;
case "tilde": return KeyValue.FLAG_ACCENT4;
case "trema": return KeyValue.FLAG_ACCENT6;
default: throw new RuntimeException(name);
} }
} }
@@ -208,6 +281,6 @@ final class Config
public static interface IKeyEventHandler 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.ArrayList;
import java.util.HashMap; 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 final String _desc;
private static HashMap<String, Emoji> emojis_by_name = new HashMap<String, Emoji>(); private static HashMap<String, Emoji> emojis_by_name = new HashMap<String, Emoji>();
protected Emoji(String name, String bytecode, String desc) 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; _desc = desc;
emojis_by_name.put(name, this); emojis_by_name.put(name, this);
} }
public String name()
{
return _name;
}
public KeyValue kv()
{
return _kv;
}
public String getDescription() public String getDescription()
{ {
return (_desc); return (_desc);

View File

@@ -55,7 +55,7 @@ public class EmojiGridView extends GridView
Config config = Config.globalConfig(); Config config = Config.globalConfig();
Integer used = _lastUsed.get(_emojiArray[pos]); Integer used = _lastUsed.get(_emojiArray[pos]);
_lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1); _lastUsed.put(_emojiArray[pos], (used == null) ? 1 : used.intValue() + 1);
config.handler.handleKeyUp(_emojiArray[pos], 0); config.handler.handleKeyUp(_emojiArray[pos].kv(), Pointers.Modifiers.EMPTY);
saveLastUsed(); // TODO: opti saveLastUsed(); // TODO: opti
} }
@@ -88,7 +88,7 @@ public class EmojiGridView extends GridView
HashSet<String> set = new HashSet<String>(); HashSet<String> set = new HashSet<String>();
for (Emoji emoji : _lastUsed.keySet()) 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.putStringSet(LAST_USE_PREF, set);
edit.apply(); edit.apply();
} }
@@ -126,7 +126,7 @@ public class EmojiGridView extends GridView
public void setEmoji(Emoji emoji) 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++) for (int i = 0; i < Emoji.num_groups; i++)
{ {
Emoji first = Emoji.getEmojisByGroup(i)[0]; Emoji first = Emoji.getEmojisByGroup(i)[0];
add_group(i, first.symbol); add_group(i, first.kv().getString());
} }
} }

View File

@@ -15,14 +15,14 @@ public class EmojiKeyButton extends Button
super(context, attrs); super(context, attrs);
setOnClickListener(this); setOnClickListener(this);
_key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key")); _key = KeyValue.getKeyByName(attrs.getAttributeValue(null, "key"));
setText(_key.symbol); setText(_key.getString());
if ((_key.flags & KeyValue.FLAG_KEY_FONT) != 0) if (_key.hasFlags(KeyValue.FLAG_KEY_FONT))
setTypeface(Theme.getSpecialKeyFont(context)); setTypeface(Theme.getSpecialKeyFont(context));
} }
public void onClick(View v) public void onClick(View v)
{ {
Config config = Config.globalConfig(); Config config = Config.globalConfig();
config.handler.handleKeyUp(_key, 0); config.handler.handleKeyUp(_key, Pointers.Modifiers.EMPTY);
} }
} }

View File

@@ -11,27 +11,36 @@ class KeyEventHandler implements Config.IKeyEventHandler
_recv = recv; _recv = recv;
} }
public void handleKeyUp(KeyValue key, int flags) public void handleKeyUp(KeyValue key, Pointers.Modifiers mods)
{ {
key = KeyModifier.handleFlags(key, flags); if (key == null)
switch (key.eventCode) return;
switch (key.getKind())
{ {
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return; case Char:
case KeyValue.EVENT_SWITCH_TEXT: _recv.setLayout(-1); return; _recv.commitChar(key.getChar());
case KeyValue.EVENT_SWITCH_NUMERIC: _recv.setLayout(R.xml.numeric); return; break;
case KeyValue.EVENT_SWITCH_EMOJI: _recv.setPane_emoji(); return; case String:
case KeyValue.EVENT_SWITCH_BACK_EMOJI: _recv.setPane_normal(); return; _recv.commitText(key.getString());
case KeyValue.EVENT_CHANGE_METHOD: _recv.switchToNextInputMethod(); return; break;
case KeyValue.EVENT_ACTION: _recv.performAction(); return; case Event:
default: switch (key.getEvent())
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT | KeyValue.FLAG_META)) != 0) {
handleKeyUpWithModifier(key, flags); case CONFIG: _recv.showKeyboardConfig(); break;
else if (key.char_ != KeyValue.CHAR_NONE) case SWITCH_TEXT: _recv.switchMain(); break;
_recv.commitChar(key.char_); case SWITCH_NUMERIC: _recv.switchNumeric(); break;
else if (key.eventCode != KeyValue.EVENT_NONE) case SWITCH_EMOJI: _recv.setPane_emoji(); break;
handleKeyUpWithModifier(key, flags); case SWITCH_BACK_EMOJI: _recv.setPane_normal(); break;
else case CHANGE_METHOD: _recv.switchToNextInputMethod(); break;
_recv.commitText(key.symbol); case ACTION: _recv.performAction(); break;
case SWITCH_PROGRAMMING: _recv.switchProgramming(); break;
}
break;
case Keyevent:
handleKeyUpWithModifier(key.getKeyevent(), mods);
break;
case Modifier:
break;
} }
} }
@@ -55,31 +64,34 @@ class KeyEventHandler implements Config.IKeyEventHandler
return updatedMetaState; return updatedMetaState;
} }
/* Send key events corresponding to pressed modifier keys. */ private int sendMetaKeyForModifier(KeyValue.Modifier mod, int metaState, boolean down)
private int sendMetaKeys(int flags, int metaState, boolean down)
{ {
if ((flags & KeyValue.FLAG_CTRL) != 0) switch (mod)
metaState = sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down); {
if ((flags & KeyValue.FLAG_ALT) != 0) case CTRL:
metaState = sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down); return sendMetaKey(KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON, metaState, down);
if ((flags & KeyValue.FLAG_SHIFT) != 0) case ALT:
metaState = sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down); return sendMetaKey(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON, metaState, down);
if ((flags & KeyValue.FLAG_META) != 0) case SHIFT:
metaState = sendMetaKey(KeyEvent.KEYCODE_META_LEFT, KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_ON, metaState, down); return sendMetaKey(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON, metaState, down);
return metaState; 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. * 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) int metaState = 0;
return ; for (int i = 0; i < mods.size(); i++)
int metaState = sendMetaKeys(flags, 0, true); metaState = sendMetaKeyForModifier(mods.get(i), metaState, true);
_recv.sendKeyEvent(KeyEvent.ACTION_DOWN, key.eventCode, metaState); _recv.sendKeyEvent(KeyEvent.ACTION_DOWN, keyCode, metaState);
_recv.sendKeyEvent(KeyEvent.ACTION_UP, key.eventCode, metaState); _recv.sendKeyEvent(KeyEvent.ACTION_UP, keyCode, metaState);
sendMetaKeys(flags, metaState, false); for (int i = mods.size() - 1; i >= 0; i--)
metaState = sendMetaKeyForModifier(mods.get(i), metaState, false);
} }
public static interface IReceiver public static interface IReceiver
@@ -90,8 +102,9 @@ class KeyEventHandler implements Config.IKeyEventHandler
public void showKeyboardConfig(); public void showKeyboardConfig();
public void performAction(); public void performAction();
/** 'res_id' is '-1' for the currently selected layout. */ public void switchMain();
public void setLayout(int res_id); public void switchNumeric();
public void switchProgramming();
public void sendKeyEvent(int eventAction, int eventCode, int meta); public void sendKeyEvent(int eventAction, int eventCode, int meta);

View File

@@ -1,119 +1,341 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.util.SparseArray;
import android.view.KeyCharacterMap; import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import java.util.HashMap; import java.util.HashMap;
class KeyModifier class KeyModifier
{ {
/* Cache key is KeyValue's name */ /** Cache key is KeyValue's name */
private static HashMap<String, SparseArray<KeyValue>> _cache = private static HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>> _cache =
new HashMap<String, SparseArray<KeyValue>>(); new HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>>();
/* Modify a key according to modifiers. */ /** Modify a key according to modifiers. */
public static KeyValue handleFlags(KeyValue k, int flags) public static KeyValue modify(KeyValue k, Pointers.Modifiers mods)
{ {
if (flags == 0) // No modifier if (k == null)
return k; return null;
SparseArray<KeyValue> ks = cacheEntry(k); int n_mods = mods.size();
KeyValue r = ks.get(flags); HashMap<Pointers.Modifiers, KeyValue> ks = cacheEntry(k);
if (r != null) // Found in cache KeyValue r = ks.get(mods);
return r; if (r == null)
r = k;
r = handleFn(r, flags);
r = handleShift(r, flags);
r = handleAccents(r, flags);
ks.put(flags, r);
return r;
}
private static KeyValue handleAccents(KeyValue k, int flags)
{
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_) // More rules if toUpperCase() did nothing
switch (k.symbol)
{
case "": c = '⇒'; break;
case "": c = '⇐'; break;
case "<": c = '«'; break;
case ">": c = '»'; break;
case "": c = '”'; break;
default: return k;
}
return k.withCharAndSymbol(c);
}
private static char handleAccentChar(char c, int flags)
{
switch ((flags & KeyValue.FLAGS_ACCENTS))
{ {
case KeyValue.FLAG_ACCENT1: r = k;
return (char)KeyCharacterMap.getDeadChar('\u02CB', c); /* Order: Fn, Shift, accents */
case KeyValue.FLAG_ACCENT2: for (int i = 0; i < n_mods; i++)
r = modify(r, mods.get(i));
ks.put(mods, r);
}
/* Keys with an empty string are placeholder keys. */
return (r.getString().length() == 0) ? null : r;
}
public static KeyValue modify(KeyValue k, KeyValue.Modifier mod)
{
switch (mod)
{
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 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 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";
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 "¿";
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
case '\t': return "\\t";
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 '║';
default: return c;
}
}
private static final Map_char map_char_double_aigu =
new Map_char() {
public char apply(char c)
{
switch (c) switch (c)
{ {
case '`': return '´'; // Composite characters: a̋ e̋ i̋ m̋ ӳ
case '<': return ''; case 'o': return 'ő';
case '>': return ''; case 'u': return 'ű';
default: return (char)KeyCharacterMap.getDeadChar('\u00B4', c); case ' ': return '˝';
default: return c;
} }
case KeyValue.FLAG_ACCENT3: }
return (char)KeyCharacterMap.getDeadChar('\u02C6', c); };
case KeyValue.FLAG_ACCENT4:
switch (c) private static final Map_char map_char_ordinal =
{ new Map_char() {
case '?': return '¿'; public char apply(char c)
case '!': return '¡'; {
default: return (char)KeyCharacterMap.getDeadChar('\u02DC', c);
}
case KeyValue.FLAG_ACCENT5:
switch (c)
{
case 'u': return 'µ';
case '"': return '„';
case '\'': return '';
case '-': return '¬';
case 'a': return 'æ';
case 'o': return 'œ';
default: return (char)KeyCharacterMap.getDeadChar('\u00B8', c);
}
case KeyValue.FLAG_ACCENT6:
switch (c)
{
case '-': return '÷';
default: return (char)KeyCharacterMap.getDeadChar('\u00A8', c);
}
case KeyValue.FLAG_ACCENT_CARON:
switch (c)
{
default: return (char)KeyCharacterMap.getDeadChar('\u02C7', c);
}
case KeyValue.FLAG_ACCENT_RING:
switch (c)
{
default: return (char)KeyCharacterMap.getDeadChar('\u02DA', c);
}
case KeyValue.FLAG_ACCENT_MACRON:
switch (c)
{
default: return (char)KeyCharacterMap.getDeadChar('\u00AF', c);
}
case KeyValue.FLAG_ACCENT_ORDINAL:
switch (c) switch (c)
{ {
case 'a': return 'ª'; case 'a': return 'ª';
@@ -130,7 +352,13 @@ class KeyModifier
case '*': return '°'; case '*': return '°';
default: return c; 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) switch (c)
{ {
case '1': return '¹'; case '1': return '¹';
@@ -152,7 +380,13 @@ class KeyModifier
case 'n': return 'ⁿ'; case 'n': return 'ⁿ';
default: return c; 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) switch (c)
{ {
case '1': return '₁'; case '1': return '₁';
@@ -176,55 +410,66 @@ class KeyModifier
case 'o': return 'ₒ'; case 'o': return 'ₒ';
default: return c; default: return c;
} }
default: return c; // Can't happen }
} };
}
private static KeyValue handleFn(KeyValue k, int flags) private static final Map_char map_char_arrows =
{ new Map_char() {
if ((flags & KeyValue.FLAG_FN) == 0) public char apply(char c)
return k; {
String name; switch (c)
switch (k.name) {
{ case '1': return '↙';
case "1": name = "f1"; break; case '2': return '↓';
case "2": name = "f2"; break; case '3': return '↘';
case "3": name = "f3"; break; case '4': return '←';
case "4": name = "f4"; break; case '6': return '→';
case "5": name = "f5"; break; case '7': return '↖';
case "6": name = "f6"; break; case '8': return '↑';
case "7": name = "f7"; break; case '9': return '↗';
case "8": name = "f8"; break; default: return c;
case "9": name = "f9"; break; }
case "0": name = "f10"; 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 "esc": name = "insert"; break;
case "$": name = ""; break;
case "#": name = "£"; break;
case "*": name = "°"; break;
case "tab": name = "\\t"; break;
default: return k;
}
return KeyValue.getKeyByName(name);
}
/* Lookup the cache entry for a key. Create it needed. */ private static final Map_char map_char_box =
private static SparseArray<KeyValue> cacheEntry(KeyValue k) new Map_char() {
{ public char apply(char c)
SparseArray<KeyValue> ks = _cache.get(k.name); {
if (ks == null) switch (c)
{ {
ks = new SparseArray<KeyValue>(); case '1': return '└';
_cache.put(k.name, ks); case '2': return '┴';
} case '3': return '┘';
return ks; 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,99 +4,204 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import java.util.HashMap; import java.util.HashMap;
class KeyValue final class KeyValue
{ {
public static final int EVENT_NONE = -1; public static enum Event
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 char CHAR_NONE = '\0';
// 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);
// Rendering flags
public static final int FLAG_KEY_FONT = (1 << 5);
public static final int FLAG_SMALLER_FONT = (1 << 6);
// Internal flags
public static final int FLAG_LOCKED = (1 << 8);
// 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);
// 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 FLAGS_ACCENTS = FLAG_ACCENT1 | FLAG_ACCENT2 |
FLAG_ACCENT3 | FLAG_ACCENT4 | FLAG_ACCENT5 | FLAG_ACCENT6 |
FLAG_ACCENT_CARON | FLAG_ACCENT_MACRON | FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL | FLAG_ACCENT_RING;
// Language specific keys
public static final int FLAG_LANG_SZLIG = (1 << 25);
public static final int FLAG_LANG_EURO = (1 << 29);
public static final int FLAG_LANG_POUND = (1 << 30);
public static final int FLAGS_LANGS = FLAG_LANG_SZLIG | FLAG_LANG_EURO |
FLAG_LANG_POUND;
public static final int FLAGS_NOT_HIDDEN_ACCENTS = FLAG_ACCENT_SUPERSCRIPT |
FLAG_ACCENT_SUBSCRIPT | FLAG_ACCENT_ORDINAL;
// Keys that have to be enabled per language
public static final int FLAGS_HIDDEN_KEYS =
(FLAGS_ACCENTS & ~FLAGS_NOT_HIDDEN_ACCENTS) | FLAGS_LANGS;
public final String name;
public final String symbol;
public final char char_;
public final int eventCode;
public final int flags;
/* Update the char and the symbol. */
public KeyValue withCharAndSymbol(char c)
{ {
return withCharAndSymbol(String.valueOf(c), c); CONFIG,
SWITCH_TEXT,
SWITCH_NUMERIC,
SWITCH_EMOJI,
SWITCH_BACK_EMOJI,
CHANGE_METHOD,
ACTION,
SWITCH_PROGRAMMING
} }
public KeyValue withCharAndSymbol(String s, char c) // Must be evaluated in the reverse order of their values.
public static enum Modifier
{ {
return new KeyValue(name, s, c, eventCode, flags); 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
}
// 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);
// Language specific keys that are removed from the keyboard by default.
public static final int FLAG_LOCALIZED = (1 << 27);
// 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);
// 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
}
private final String _symbol;
/** This field encodes three things:
- The kind
- The flags
- The value for Char, Event and Modifier keys.
*/
private final int _code;
public static enum Kind
{
Char, String, Keyevent, Event, Modifier
}
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 withChar(char c)
{
return new KeyValue(String.valueOf(c), KIND_CHAR, c, getFlags());
}
public KeyValue withString(String s)
{
return new KeyValue(s, KIND_STRING, 0, getFlags());
}
public KeyValue withSymbol(String s)
{
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(_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>(); 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; check((kind & ~KIND_BITS) == 0);
symbol = s; check((flags & ~FLAGS_BITS) == 0);
char_ = c; check((value & ~VALUE_BITS) == 0);
eventCode = e; _symbol = s;
flags = f; _code = kind | flags | value;
}
private static String stripPrefix(String s, String prefix)
{
if (s.startsWith(prefix))
return s.substring(prefix.length());
else
return null;
} }
public static KeyValue getKeyByName(String name) public static KeyValue getKeyByName(String name)
@@ -106,164 +211,127 @@ class KeyValue
KeyValue kv = KeyValue.keys.get(name); KeyValue kv = KeyValue.keys.get(name);
if (kv != null) if (kv != null)
return kv; return kv;
char c = (name.length() == 1) ? name.charAt(0) : CHAR_NONE; String localized = stripPrefix(name, "loc ");
return new KeyValue(name, name, c, EVENT_NONE, 0); if (localized != null)
{
kv = getKeyByName(localized);
return kv.withFlags(kv.getFlags() | FLAG_LOCALIZED);
}
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, symbol, KIND_CHAR, c, flags);
addKey(name, name, c, event, 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 addEventKey(String name, String symbol, Event e, int flags)
{ {
addKey(name, symbol, CHAR_NONE, EVENT_NONE, addKey(name, symbol, KIND_EVENT, e.ordinal(), flags | FLAG_SPECIAL);
FLAG_LATCH | FLAG_NOCHAR | FLAG_NOREPEAT | extra_flags);
} }
private static void addSpecialKey(String name, String symbol, int event) private static void addKeyeventKey(String name, String symbol, int code, int flags)
{ {
addSpecialKey(name, symbol, event, 0); addKey(name, symbol, KIND_KEYEVENT, code, flags);
} }
private static void addSpecialKey(String name, String symbol, int event, int flags) private static void addPlaceholderKey(String name)
{ {
addKey(name, symbol, CHAR_NONE, event, flags | FLAG_NOREPEAT); addKey(name, "", KIND_STRING, 0, 0);
}
private static void addEventKey(String name, String symbol, int event)
{
addEventKey(name, symbol, event, 0);
}
private static void addEventKey(String name, String symbol, int event, int flags)
{
addKey(name, symbol, CHAR_NONE, event, flags);
} }
static static
{ {
addModifierKey("shift", "\uE808", addModifierKey("shift", "\n", // Can't write u000A because Java is stupid
FLAG_LOCK | FLAG_SHIFT | FLAG_KEY_FONT | FLAG_SMALLER_FONT); Modifier.SHIFT, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addModifierKey("ctrl", "Ctrl", FLAG_CTRL | FLAG_SMALLER_FONT); addModifierKey("ctrl", "Ctrl", Modifier.CTRL, FLAG_SMALLER_FONT);
addModifierKey("alt", "Alt", FLAG_ALT | FLAG_SMALLER_FONT); addModifierKey("alt", "Alt", Modifier.ALT, FLAG_SMALLER_FONT);
addModifierKey("accent_aigu", "◌́", FLAG_ACCENT2); addModifierKey("accent_aigu", "\u0050", Modifier.AIGU, FLAG_KEY_FONT);
addModifierKey("accent_caron", "◌̌", FLAG_ACCENT_CARON); addModifierKey("accent_caron", "\u0051", Modifier.CARON, FLAG_KEY_FONT);
addModifierKey("accent_cedille", "◌̧", FLAG_ACCENT5); addModifierKey("accent_cedille", "\u0052", Modifier.CEDILLE, FLAG_KEY_FONT);
addModifierKey("accent_circonflexe", "◌̂", FLAG_ACCENT3); addModifierKey("accent_circonflexe", "\u0053", Modifier.CIRCONFLEXE, FLAG_KEY_FONT);
addModifierKey("accent_grave", "◌̀", FLAG_ACCENT1); addModifierKey("accent_grave", "\u0054", Modifier.GRAVE, FLAG_KEY_FONT);
addModifierKey("accent_macron", "◌̄", FLAG_ACCENT_MACRON); addModifierKey("accent_macron", "\u0055", Modifier.MACRON, FLAG_KEY_FONT);
addModifierKey("accent_tilde", "◌̃", FLAG_ACCENT4); addModifierKey("accent_ring", "\u0056", Modifier.RING, FLAG_KEY_FONT);
addModifierKey("accent_trema", "◌̈", FLAG_ACCENT6); addModifierKey("accent_tilde", "\u0057", Modifier.TILDE, FLAG_KEY_FONT);
addModifierKey("accent_ring", "◌̊", FLAG_ACCENT_RING); addModifierKey("accent_trema", "\u0058", Modifier.TREMA, FLAG_KEY_FONT);
addModifierKey("superscript", "◌͆", FLAG_ACCENT_SUPERSCRIPT); addModifierKey("accent_ogonek", "\u0059", Modifier.OGONEK, FLAG_KEY_FONT);
addModifierKey("subscript", "◌̺", FLAG_ACCENT_SUBSCRIPT); addModifierKey("accent_dot_above", "\u005a", Modifier.DOT_ABOVE, FLAG_KEY_FONT);
addModifierKey("ordinal", "ºʳᵈ", FLAG_ACCENT_ORDINAL | FLAG_SMALLER_FONT); addModifierKey("accent_double_aigu", "\u005b", Modifier.DOUBLE_AIGU, FLAG_KEY_FONT);
addModifierKey("fn", "Fn", FLAG_FN | FLAG_SMALLER_FONT); addModifierKey("accent_slash", "\134", // Can't write u005c
addModifierKey("meta", "", FLAG_META); Modifier.SLASH, FLAG_KEY_FONT);
addModifierKey("accent_arrow_right", "\u005d", Modifier.ARROW_RIGHT, FLAG_KEY_FONT);
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); addEventKey("config", "\u0004", Event.CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addCharKey('b', KeyEvent.KEYCODE_B); addEventKey("switch_text", "ABC", Event.SWITCH_TEXT, FLAG_SMALLER_FONT);
addCharKey('c', KeyEvent.KEYCODE_C); addEventKey("switch_numeric", "123+", Event.SWITCH_NUMERIC, FLAG_SMALLER_FONT);
addCharKey('d', KeyEvent.KEYCODE_D); addEventKey("switch_emoji", "\u0001" , Event.SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addCharKey('e', KeyEvent.KEYCODE_E); addEventKey("switch_back_emoji", "ABC", Event.SWITCH_BACK_EMOJI, 0);
addCharKey('f', KeyEvent.KEYCODE_F); addEventKey("switch_programming", "Prog", Event.SWITCH_PROGRAMMING, FLAG_SMALLER_FONT);
addCharKey('g', KeyEvent.KEYCODE_G); addEventKey("change_method", "\u0009", Event.CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addCharKey('h', KeyEvent.KEYCODE_H); addEventKey("action", "Action", Event.ACTION, FLAG_SMALLER_FONT); // Will always be replaced
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_LANG_SZLIG);
addCharKey('€', EVENT_NONE, FLAG_LANG_EURO);
addCharKey('£', EVENT_NONE, FLAG_LANG_POUND);
addSpecialKey("config", "\uE806", EVENT_CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT); addKeyeventKey("esc", "Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT); addKeyeventKey("enter", "\u000E", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT);
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC); addKeyeventKey("up", "\u0005", KeyEvent.KEYCODE_DPAD_UP, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addSpecialKey("switch_emoji", "\uE812" , EVENT_SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT); addKeyeventKey("right", "\u0006", KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI); addKeyeventKey("down", "\u0007", KeyEvent.KEYCODE_DPAD_DOWN, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addSpecialKey("change_method", "\ue807", EVENT_CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT); addKeyeventKey("left", "\u0008", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addSpecialKey("action", "Action", EVENT_ACTION); // Will always be replaced 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); addCharKey("\\t", "\\t", '\t', 0); // Send the tab character
addEventKey("enter", "\ue800", KeyEvent.KEYCODE_ENTER, FLAG_KEY_FONT); addCharKey("space", "\r", ' ', FLAG_KEY_FONT);
addEventKey("up", "\uE80B", KeyEvent.KEYCODE_DPAD_UP, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT); addCharKey("nbsp", "\u237d", '\u00a0', FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addEventKey("right", "\uE80C", KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addEventKey("down", "\uE809", KeyEvent.KEYCODE_DPAD_DOWN, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addEventKey("left", "\uE80A", KeyEvent.KEYCODE_DPAD_LEFT, FLAG_KEY_FONT | FLAG_PRECISE_REPEAT);
addEventKey("page_up", "\uE810", KeyEvent.KEYCODE_PAGE_UP, FLAG_KEY_FONT);
addEventKey("page_down", "\uE811", KeyEvent.KEYCODE_PAGE_DOWN, FLAG_KEY_FONT);
addEventKey("home", "\uE80E", KeyEvent.KEYCODE_MOVE_HOME, FLAG_KEY_FONT);
addEventKey("end", "\uE80F", KeyEvent.KEYCODE_MOVE_END, FLAG_KEY_FONT);
addEventKey("backspace", "", KeyEvent.KEYCODE_DEL, FLAG_SMALLER_FONT);
addEventKey("delete", "", KeyEvent.KEYCODE_FORWARD_DEL, FLAG_SMALLER_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("tab", "", KeyEvent.KEYCODE_TAB);
addKey("\\t", "\\t", '\t', EVENT_NONE, 0); // Send the tab character addPlaceholderKey("removed");
addKey("space", "\ue80d", ' ', KeyEvent.KEYCODE_SPACE, FLAG_KEY_FONT | FLAG_SMALLER_FONT); 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

@@ -18,17 +18,26 @@ import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.util.Log;
import android.util.LogPrinter;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.HashSet;
import java.util.Set;
public class Keyboard2 extends InputMethodService public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener implements SharedPreferences.OnSharedPreferenceChangeListener
{ {
static private final String TAG = "Keyboard2";
private Keyboard2View _keyboardView; private Keyboard2View _keyboardView;
private int _currentTextLayout; private int _currentTextLayout;
private ViewGroup _emojiPane = null; private ViewGroup _emojiPane = null;
private Config _config; private Config _config;
private boolean _debug_logs = false;
private KeyboardData getLayout(int resId) private KeyboardData getLayout(int resId)
{ {
return KeyboardData.load(getResources(), resId); return KeyboardData.load(getResources(), resId);
@@ -45,6 +54,7 @@ public class Keyboard2 extends InputMethodService
_config.refresh(this); _config.refresh(this);
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard); _keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_keyboardView.reset(); _keyboardView.reset();
_debug_logs = getResources().getBoolean(R.bool.debug_logs);
} }
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm) private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
@@ -53,7 +63,7 @@ public class Keyboard2 extends InputMethodService
for (InputMethodInfo imi : imm.getEnabledInputMethodList()) for (InputMethodInfo imi : imm.getEnabledInputMethodList())
if (imi.getPackageName().equals(pkg)) if (imi.getPackageName().equals(pkg))
return imm.getEnabledInputMethodSubtypeList(imi, true); return imm.getEnabledInputMethodSubtypeList(imi, true);
return null; return Arrays.asList();
} }
private void refreshSubtypeLayout(InputMethodSubtype subtype) private void refreshSubtypeLayout(InputMethodSubtype subtype)
@@ -70,32 +80,37 @@ public class Keyboard2 extends InputMethodService
_currentTextLayout = l; _currentTextLayout = l;
} }
private int extra_keys_of_subtype(InputMethodSubtype subtype) private void extra_keys_of_subtype(Set<KeyValue> dst, InputMethodSubtype subtype)
{ {
String extra_keys = subtype.getExtraValueOf("extra_keys"); String extra_keys = subtype.getExtraValueOf("extra_keys");
int flags = 0; if (extra_keys == null)
if (extra_keys != null) return;
for (String acc : extra_keys.split("\\|")) String[] ks = extra_keys.split("\\|");
flags |= Config.extra_key_flag_of_name(acc); for (int i = 0; i < ks.length; i++)
return flags; dst.add(KeyValue.getKeyByName(ks[i]));
} }
private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype) private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype)
{ {
int to_keep = 0; HashSet<KeyValue> extra_keys = new HashSet<KeyValue>();
List<InputMethodSubtype> enabled_subtypes = getEnabledSubtypes(imm);
switch (_config.accents) switch (_config.accents)
{ {
case 1: // '3' was "all accents", now unused
to_keep |= extra_keys_of_subtype(subtype); case 1: case 3:
for (InputMethodSubtype s : getEnabledSubtypes(imm)) extra_keys_of_subtype(extra_keys, subtype);
to_keep |= extra_keys_of_subtype(s); for (InputMethodSubtype s : enabled_subtypes)
extra_keys_of_subtype(extra_keys, s);
break;
case 2:
extra_keys_of_subtype(extra_keys, subtype);
break; break;
case 2: to_keep |= extra_keys_of_subtype(subtype); break;
case 3: to_keep = KeyValue.FLAGS_HIDDEN_KEYS; break;
case 4: break; case 4: break;
default: throw new IllegalArgumentException(); default: throw new IllegalArgumentException();
} }
_config.key_flags_to_remove = ~to_keep & KeyValue.FLAGS_HIDDEN_KEYS; _config.extra_keys = extra_keys;
if (enabled_subtypes.size() > 1)
_config.shouldOfferSwitchingToNextInputMethod = true;
} }
private void refreshSubtypeLegacyFallback() private void refreshSubtypeLegacyFallback()
@@ -103,8 +118,8 @@ public class Keyboard2 extends InputMethodService
// Fallback for the accents option: Only respect the "None" case // Fallback for the accents option: Only respect the "None" case
switch (_config.accents) switch (_config.accents)
{ {
case 1: case 2: case 3: _config.key_flags_to_remove = 0; break; case 1: case 2: case 3: _config.extra_keys = null; break;
case 4: _config.key_flags_to_remove = KeyValue.FLAGS_HIDDEN_KEYS; break; case 4: _config.extra_keys = new HashSet<KeyValue>(); break;
} }
// Fallback for the layout option: Use qwerty in the "system settings" case // Fallback for the layout option: Use qwerty in the "system settings" case
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout; _currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
@@ -125,6 +140,9 @@ public class Keyboard2 extends InputMethodService
refreshSubtypeLayout(subtype); refreshSubtypeLayout(subtype);
refreshAccentsOption(imm, subtype); refreshAccentsOption(imm, subtype);
} }
_config.shouldOfferSwitchingToProgramming =
_config.programming_layout != -1 &&
_currentTextLayout != _config.programming_layout;
} }
private String actionLabel_of_imeAction(int action) private String actionLabel_of_imeAction(int action)
@@ -176,7 +194,16 @@ public class Keyboard2 extends InputMethodService
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard); _keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_emojiPane = null; _emojiPane = null;
} }
_keyboardView.setKeyboard(getLayout(_currentTextLayout)); }
private void log_editor_info(EditorInfo info)
{
LogPrinter p = new LogPrinter(Log.DEBUG, TAG);
info.dump(p, "");
if (info.extras != null)
Log.d(TAG, "extras: "+info.extras.toString());
Log.d(TAG, "swapEnterActionKey: "+_config.swapEnterActionKey);
Log.d(TAG, "actionLabel: "+_config.actionLabel);
} }
@Override @Override
@@ -186,7 +213,11 @@ public class Keyboard2 extends InputMethodService
refreshEditorInfo(info); refreshEditorInfo(info);
if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0) if ((info.inputType & InputType.TYPE_CLASS_NUMBER) != 0)
_keyboardView.setKeyboard(getLayout(R.xml.numeric)); _keyboardView.setKeyboard(getLayout(R.xml.numeric));
else
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
setInputView(_keyboardView); setInputView(_keyboardView);
if (_debug_logs)
log_editor_info(info);
} }
@Override @Override
@@ -249,11 +280,32 @@ public class Keyboard2 extends InputMethodService
conn.performEditorAction(_config.actionId); conn.performEditorAction(_config.actionId);
} }
public void setLayout(int res_id) public void switchMain()
{ {
if (res_id == -1) _keyboardView.setKeyboard(getLayout(_currentTextLayout));
res_id = _currentTextLayout; }
_keyboardView.setKeyboard(getLayout(res_id));
public void switchNumeric()
{
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
}
public void switchProgramming()
{
if (_config.programming_layout == -1)
return;
KeyboardData layout =
getLayout(_config.programming_layout).mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key)
{
if (key != null
&& key.getKind() == KeyValue.Kind.Event
&& key.getEvent() == KeyValue.Event.SWITCH_PROGRAMMING)
return KeyValue.getKeyByName("switch_text");
return key;
}
});
_keyboardView.setKeyboard(layout);
} }
public void sendKeyEvent(int eventAction, int eventCode, int meta) public void sendKeyEvent(int eventAction, int eventCode, int meta)

View File

@@ -1,15 +1,19 @@
package juloo.keyboard2; package juloo.keyboard2;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Vibrator; import android.inputmethodservice.InputMethodService;
import android.os.Build.VERSION;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.Window;
public class Keyboard2View extends View public class Keyboard2View extends View
implements View.OnTouchListener, Pointers.IPointerEventHandler implements View.OnTouchListener, Pointers.IPointerEventHandler
@@ -20,9 +24,8 @@ public class Keyboard2View extends View
private Pointers _pointers; private Pointers _pointers;
private int _flags = 0; private Pointers.Modifiers _mods;
private Vibrator _vibratorService;
private long _lastVibration = 0; private long _lastVibration = 0;
private static int _currentWhat = 0; private static int _currentWhat = 0;
@@ -45,88 +48,82 @@ public class Keyboard2View extends View
public Keyboard2View(Context context, AttributeSet attrs) public Keyboard2View(Context context, AttributeSet attrs)
{ {
super(context, attrs); super(context, attrs);
_vibratorService = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
_theme = new Theme(getContext(), attrs); _theme = new Theme(getContext(), attrs);
_config = Config.globalConfig(); _config = Config.globalConfig();
_pointers = new Pointers(this, _config); _pointers = new Pointers(this, _config);
refresh_navigation_bar(context);
setOnTouchListener(this); setOnTouchListener(this);
reset(); 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) public void setKeyboard(KeyboardData kw)
{ {
if (!_config.shouldOfferSwitchingToNextInputMethod) _keyboard = _config.modify_layout(kw);
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_CHANGE_METHOD, null));
if (_config.key_flags_to_remove != 0)
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByFlags(_config.key_flags_to_remove, null));
// Replace the action key to show the right label.
KeyValue action_key = null;
if (_config.actionLabel != null)
{
action_key = new KeyValue(_config.actionLabel, _config.actionLabel,
KeyValue.CHAR_NONE, KeyValue.EVENT_ACTION, KeyValue.FLAG_NOREPEAT);
}
if (_config.swapEnterActionKey && action_key != null)
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent2(KeyEvent.KEYCODE_ENTER,
action_key, KeyValue.EVENT_ACTION,
KeyValue.getKeyByName("enter")));
else
kw = kw.replaceKeys(
new KeyboardData.ReplaceKeysByEvent(KeyValue.EVENT_ACTION, action_key));
_keyboard = kw;
reset(); reset();
} }
public void reset() public void reset()
{ {
_flags = 0; _mods = Pointers.Modifiers.EMPTY;
_pointers.clear(); _pointers.clear();
requestLayout(); requestLayout();
invalidate(); invalidate();
} }
public void onPointerDown(KeyValue k) public KeyValue modifyKey(KeyValue k, Pointers.Modifiers mods)
{ {
updateFlags(); return KeyModifier.modify(k, mods);
invalidate();
if (k != null)
vibrate();
} }
public void onPointerSwipe(KeyValue k) public void onPointerDown(boolean isSwipe)
{ {
updateFlags();
invalidate(); invalidate();
if (k != null) vibrate();
vibrate();
} }
public void onPointerUp(KeyValue k) public void onPointerUp(KeyValue k, Pointers.Modifiers mods)
{ {
if (k != null && (k.flags & KeyValue.FLAG_NOCHAR) == 0) _config.handler.handleKeyUp(k, mods);
_config.handler.handleKeyUp(k, _flags);
updateFlags();
invalidate(); invalidate();
} }
public void onPointerHold(KeyValue k) public void onPointerHold(KeyValue k, Pointers.Modifiers mods)
{ {
if (k != null) _config.handler.handleKeyUp(k, mods);
_config.handler.handleKeyUp(k, _flags);
} }
public void onPointerFlagsChanged() public void onPointerFlagsChanged()
{ {
updateFlags();
invalidate(); invalidate();
} }
private void updateFlags() private void updateFlags()
{ {
_flags = _pointers.getFlags(); _mods = _pointers.getModifiers();
} }
@Override @Override
@@ -138,7 +135,7 @@ public class Keyboard2View extends View
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_UP:
_pointers.onTouchUp(event.getPointerId(event.getActionIndex())); _pointers.onTouchUp(event.getPointerId(event.getActionIndex()));
break ; break;
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
p = event.getActionIndex(); p = event.getActionIndex();
@@ -147,11 +144,14 @@ public class Keyboard2View extends View
KeyboardData.Key key = getKeyAtPosition(tx, ty); KeyboardData.Key key = getKeyAtPosition(tx, ty);
if (key != null) if (key != null)
_pointers.onTouchDown(tx, ty, event.getPointerId(p), key); _pointers.onTouchDown(tx, ty, event.getPointerId(p), key);
break ; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
for (p = 0; p < event.getPointerCount(); p++) for (p = 0; p < event.getPointerCount(); p++)
_pointers.onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p)); _pointers.onTouchMove(event.getX(p), event.getY(p), event.getPointerId(p));
break ; break;
case MotionEvent.ACTION_CANCEL:
_pointers.onTouchCancel(event.getPointerId(event.getActionIndex()));
break;
default: default:
return (false); return (false);
} }
@@ -189,19 +189,14 @@ public class Keyboard2View extends View
private void vibrate() private void vibrate()
{ {
if (!_config.vibrateEnabled)
return ;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if ((now - _lastVibration) > VIBRATE_MIN_INTERVAL) if ((now - _lastVibration) > VIBRATE_MIN_INTERVAL)
{ {
_lastVibration = now; _lastVibration = now;
try if (VERSION.SDK_INT >= 5)
{ {
_vibratorService.vibrate(_config.vibrateDuration); performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
} HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
catch (Exception e)
{
e.printStackTrace();
} }
} }
} }
@@ -222,6 +217,7 @@ public class Keyboard2View extends View
@Override @Override
protected void onDraw(Canvas canvas) protected void onDraw(Canvas canvas)
{ {
updateFlags();
float y = _config.marginTop + _config.keyVerticalInterval / 2; float y = _config.marginTop + _config.keyVerticalInterval / 2;
for (KeyboardData.Row row : _keyboard.rows) for (KeyboardData.Row row : _keyboard.rows)
{ {
@@ -236,29 +232,20 @@ public class Keyboard2View extends View
_tmpRect.set(x, y, x + keyW, y + keyH); _tmpRect.set(x, y, x + keyW, y + keyH);
canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius, canvas.drawRoundRect(_tmpRect, _theme.keyBorderRadius, _theme.keyBorderRadius,
isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint); isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint);
if (k.key0 != null) drawLabel(canvas, k.key0, keyW / 2f + x, y, keyH, isKeyDown);
drawLabel(canvas, k.key0, keyW / 2f + x, y, keyH, isKeyDown);
if (k.edgekeys) if (k.edgekeys)
{ {
if (k.key1 != null) // top key drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.TOP, isKeyDown);
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.TOP, isKeyDown); drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.CENTER, isKeyDown);
if (k.key3 != null) // left key drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.CENTER, isKeyDown); drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
if (k.key2 != null) // right key
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.CENTER, isKeyDown);
if (k.key4 != null) // bottom key
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.CENTER, Vertical.BOTTOM, isKeyDown);
} }
else else
{ {
if (k.key1 != null) // top left key drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.TOP, isKeyDown);
drawSubLabel(canvas, k.key1, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.TOP, isKeyDown); drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown);
if (k.key3 != null) // bottom left key drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
drawSubLabel(canvas, k.key3, x, y, keyW, keyH, Paint.Align.LEFT, Vertical.BOTTOM, isKeyDown); drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
if (k.key2 != null) // top right key
drawSubLabel(canvas, k.key2, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.TOP, isKeyDown);
if (k.key4 != null) // bottom right key
drawSubLabel(canvas, k.key4, x, y, keyW, keyH, Paint.Align.RIGHT, Vertical.BOTTOM, isKeyDown);
} }
x += _keyWidth * k.width; x += _keyWidth * k.width;
} }
@@ -274,7 +261,7 @@ public class Keyboard2View extends View
private int labelColor(KeyValue k, boolean isKeyDown, int defaultColor) 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); int flags = _pointers.getKeyFlags(k);
if (flags != -1) if (flags != -1)
@@ -290,19 +277,23 @@ public class Keyboard2View extends View
private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown) private void drawLabel(Canvas canvas, KeyValue k, float x, float y, float keyH, boolean isKeyDown)
{ {
k = KeyModifier.modify(k, _mods);
if (k == null)
return;
float textSize = scaleTextSize(k, _config.labelTextSize, keyH); float textSize = scaleTextSize(k, _config.labelTextSize, keyH);
k = KeyModifier.handleFlags(k, _flags); Paint p = _theme.labelPaint(k.hasFlags(KeyValue.FLAG_KEY_FONT));
Paint p = _theme.labelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0));
p.setColor(labelColor(k, isKeyDown, _theme.labelColor)); p.setColor(labelColor(k, isKeyDown, _theme.labelColor));
p.setTextSize(textSize); p.setTextSize(textSize);
canvas.drawText(k.symbol, x, (keyH - p.ascent() - p.descent()) / 2f + y, p); canvas.drawText(k.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, KeyValue k, float x, float y, float keyW, float keyH, Paint.Align a, Vertical v, boolean isKeyDown)
{ {
k = KeyModifier.modify(k, _mods);
if (k == null)
return;
float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH); float textSize = scaleTextSize(k, _config.sublabelTextSize, keyH);
k = KeyModifier.handleFlags(k, _flags); Paint p = _theme.subLabelPaint(k.hasFlags(KeyValue.FLAG_KEY_FONT), a);
Paint p = _theme.subLabelPaint(((k.flags & KeyValue.FLAG_KEY_FONT) != 0), a);
p.setColor(labelColor(k, isKeyDown, _theme.subLabelColor)); p.setColor(labelColor(k, isKeyDown, _theme.subLabelColor));
p.setTextSize(textSize); p.setTextSize(textSize);
float subPadding = _config.keyPadding; float subPadding = _config.keyPadding;
@@ -314,12 +305,12 @@ public class Keyboard2View extends View
x += keyW / 2f; x += keyW / 2f;
else else
x += (a == Paint.Align.LEFT) ? subPadding : keyW - subPadding; x += (a == Paint.Align.LEFT) ? subPadding : keyW - subPadding;
canvas.drawText(k.symbol, x, y, p); canvas.drawText(k.getString(), x, y, p);
} }
private float scaleTextSize(KeyValue k, float rel_size, float keyH) 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; return keyH * rel_size * smaller_font * _config.characterSize;
} }
} }

View File

@@ -3,24 +3,58 @@ package juloo.keyboard2;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Function;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
class KeyboardData class KeyboardData
{ {
public final List<Row> rows; public final List<Row> rows;
/* Total width of the keyboard. Unit is abstract. */ /** Total width of the keyboard. */
public final float keysWidth; public final float keysWidth;
/* Total height of the keyboard. Unit is abstract. */ /** Total height of the keyboard. */
public final float keysHeight; 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>(); ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows) for (Row r : rows)
rows_.add(r.replaceKeys(f)); rows_.add(r.mapKeys(f));
return new KeyboardData(rows_, keysWidth); 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);
return new KeyboardData(rows, keysWidth, extra_keys);
}
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; private static Row _bottomRow = null;
@@ -51,13 +85,14 @@ class KeyboardData
if (!expect_tag(parser, "keyboard")) if (!expect_tag(parser, "keyboard"))
throw new Exception("Empty layout file"); throw new Exception("Empty layout file");
boolean bottom_row = parser.getAttributeBooleanValue(null, "bottom_row", true); boolean bottom_row = parser.getAttributeBooleanValue(null, "bottom_row", true);
boolean extra_keys = parser.getAttributeBooleanValue(null, "extra_keys", true);
ArrayList<Row> rows = new ArrayList<Row>(); ArrayList<Row> rows = new ArrayList<Row>();
while (expect_tag(parser, "row")) while (expect_tag(parser, "row"))
rows.add(Row.parse(parser)); rows.add(Row.parse(parser));
float kw = compute_max_width(rows); float kw = compute_max_width(rows);
if (bottom_row) if (bottom_row)
rows.add(_bottomRow.updateWidth(kw)); 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) private static float compute_max_width(List<Row> rows)
@@ -75,7 +110,7 @@ class KeyboardData
return Row.parse(parser); return Row.parse(parser);
} }
protected KeyboardData(List<Row> rows_, float kw) protected KeyboardData(List<Row> rows_, float kw, boolean xk)
{ {
float kh = 0.f; float kh = 0.f;
for (Row r : rows_) for (Row r : rows_)
@@ -83,16 +118,17 @@ class KeyboardData
rows = rows_; rows = rows_;
keysWidth = kw; keysWidth = kw;
keysHeight = kh; keysHeight = kh;
extra_keys = xk;
} }
public static class Row public static class Row
{ {
public final List<Key> keys; public final List<Key> keys;
/* Height of the row, without 'shift'. Unit is abstract. */ /** Height of the row, without 'shift'. */
public final float height; public final float height;
/* Extra empty space on the top. */ /** Extra empty space on the top. */
public final float shift; public final float shift;
/* Total width of the row. Unit is abstract. */ /** Total width of the row. */
private final float keysWidth; private final float keysWidth;
protected Row(List<Key> keys_, float h, float s) protected Row(List<Key> keys_, float h, float s)
@@ -116,22 +152,21 @@ class KeyboardData
return new Row(keys, h, shift); return new Row(keys, h, shift);
} }
public Row replaceKeys(MapKeys f) public Row mapKeys(MapKey f)
{ {
ArrayList<Key> keys_ = new ArrayList<Key>(); ArrayList<Key> keys_ = new ArrayList<Key>();
for (Key k : keys) for (Key k : keys)
keys_.add(k.replaceKeys(f)); keys_.add(f.apply(k));
return new Row(keys_, height, shift); return new Row(keys_, height, shift);
} }
/** Change the width of every keys so that the row is 's' units wide. */ /** Change the width of every keys so that the row is 's' units wide. */
public Row updateWidth(float newWidth) public Row updateWidth(float newWidth)
{ {
float s = newWidth / keysWidth; final float s = newWidth / keysWidth;
ArrayList<Key> keys_ = new ArrayList<Key>(); return mapKeys(new MapKey(){
for (Key k : keys) public Key apply(Key k) { return k.scaleWidth(s); }
keys_.add(k.scaleWidth(s)); });
return new Row(keys_, height, shift);
} }
} }
@@ -148,11 +183,11 @@ class KeyboardData
public final KeyValue key3; public final KeyValue key3;
public final KeyValue key4; public final KeyValue key4;
/* Key width in relative unit. */ /** Key width in relative unit. */
public final float width; 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; 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; public final boolean edgekeys;
protected Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e) protected Key(KeyValue k0, KeyValue k1, KeyValue k2, KeyValue k3, KeyValue k4, float w, float s, boolean e)
@@ -182,80 +217,90 @@ class KeyboardData
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys); return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
} }
public Key replaceKeys(MapKeys f)
{
return new Key(f.map(key0), f.map(key1), f.map(key2), f.map(key3), f.map(key4), width, shift, edgekeys);
}
/** New key with the width multiplied by 's'. */ /** New key with the width multiplied by 's'. */
public Key scaleWidth(float s) public Key scaleWidth(float s)
{ {
return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys); return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys);
} }
}
public static abstract interface MapKeys public KeyValue getKeyValue(int i)
{
public abstract KeyValue map(KeyValue k);
}
public static class ReplaceKeysByFlags implements MapKeys
{
private final int _flags;
private final KeyValue _replacement;
public ReplaceKeysByFlags(int flags, KeyValue r)
{ {
_flags = flags; switch (i)
_replacement = r; {
case 0: return key0;
case 1: return key1;
case 2: return key2;
case 3: return key3;
case 4: return key4;
default: return null;
}
} }
public KeyValue map(KeyValue k) public Key withKeyValue(int i, KeyValue kv)
{ {
return (k != null && (k.flags & _flags) != 0) ? _replacement : k; KeyValue k0 = key0, k1 = key1, k2 = key2, k3 = key3, k4 = key4;
switch (i)
{
case 0: k0 = kv; break;
case 1: k1 = kv; break;
case 2: k2 = kv; break;
case 3: k3 = kv; break;
case 4: k4 = kv; break;
}
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
}
/**
* See Pointers.onTouchMove() for the represented direction.
*/
public KeyValue getAtDirection(int direction)
{
if (edgekeys)
{
// \ 1 /
// \ /
// 3 0 2
// / \
// / 4 \
switch (direction)
{
case 2: case 3: return key1;
case 4: case 5: return key2;
case 6: case 7: return key4;
case 8: case 1: return key3;
}
}
else
{
// 1 | 2
// |
// --0--
// |
// 3 | 4
switch (direction)
{
case 1: case 2: return key1;
case 3: case 4: return key2;
case 5: case 6: return key4;
case 7: case 8: return key3;
}
}
return null;
} }
} }
public static class ReplaceKeysByEvent implements MapKeys // Not using Function<KeyValue, KeyValue> to keep compatibility with Android 6.
{ public static abstract interface MapKey {
private final int _eventCode; public Key apply(Key k);
private final KeyValue _replacement;
public ReplaceKeysByEvent(int ev, KeyValue r)
{
_eventCode = ev;
_replacement = r;
}
public KeyValue map(KeyValue k)
{
return (k != null && k.eventCode == _eventCode) ? _replacement : k;
}
} }
/* Replace two keys at the same time. Used for swaping keys. */ public static abstract class MapKeyValues implements MapKey {
public static class ReplaceKeysByEvent2 implements MapKeys abstract public KeyValue apply(KeyValue kv);
{
private final int _e1;
private final KeyValue _r1;
private final int _e2;
private final KeyValue _r2;
public ReplaceKeysByEvent2(int e1, KeyValue r1, int e2, KeyValue r2) public Key apply(Key k)
{ {
_e1 = e1; return new Key(apply(k.key0), apply(k.key1), apply(k.key2),
_r1 = r1; apply(k.key3), apply(k.key4), k.width, k.shift, k.edgekeys);
_e2 = e2;
_r2 = r2;
}
public KeyValue map(KeyValue k)
{
if (k == null)
return null;
if (k.eventCode == _e1) return _r1;
if (k.eventCode == _e2) return _r2;
return k;
} }
} }

View File

@@ -2,6 +2,7 @@ package juloo.keyboard2;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
/** /**
@@ -22,12 +23,27 @@ public final class Pointers implements Handler.Callback
_config = c; _config = c;
} }
public int getFlags() /** Return the list of modifiers currently activated. */
public Modifiers getModifiers()
{ {
int flags = 0; return getModifiers(false);
for (Pointer p : _ptrs) }
flags |= p.flags;
return flags; /** 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() public void clear()
@@ -53,7 +69,7 @@ public final class Pointers implements Handler.Callback
public int getKeyFlags(KeyValue kv) public int getKeyFlags(KeyValue kv)
{ {
for (Pointer p : _ptrs) for (Pointer p : _ptrs)
if (p.value == kv) if (p.value != null && p.value.equals(kv))
return p.flags; return p.flags;
return -1; return -1;
} }
@@ -66,7 +82,7 @@ public final class Pointers implements Handler.Callback
if (ptr == null) if (ptr == null)
return; return;
stopKeyRepeat(ptr); stopKeyRepeat(ptr);
Pointer latched = getLatched(ptr.value); Pointer latched = getLatched(ptr);
if (latched != null) // Already latched if (latched != null) // Already latched
{ {
removePtr(ptr); // Remove dupplicate removePtr(ptr); // Remove dupplicate
@@ -78,7 +94,7 @@ public final class Pointers implements Handler.Callback
else // Otherwise, unlatch else // Otherwise, unlatch
{ {
removePtr(latched); removePtr(latched);
_handler.onPointerUp(ptr.value); _handler.onPointerUp(ptr.value, ptr.modifiers);
} }
} }
else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0) else if ((ptr.flags & KeyValue.FLAG_LATCH) != 0)
@@ -91,18 +107,70 @@ public final class Pointers implements Handler.Callback
{ {
clearLatched(); clearLatched();
removePtr(ptr); removePtr(ptr);
_handler.onPointerUp(ptr.value); _handler.onPointerUp(ptr.value, ptr.modifiers);
} }
} }
public void onTouchCancel(int pointerId)
{
Pointer ptr = getPtr(pointerId);
if (ptr == null)
return;
stopKeyRepeat(ptr);
removePtr(ptr);
_handler.onPointerFlagsChanged();
}
/* 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) public void onTouchDown(float x, float y, int pointerId, KeyboardData.Key key)
{ {
KeyValue value = key.key0; // Ignore new presses while a modulated key is active. On some devices,
Pointer ptr = new Pointer(pointerId, key, value, x, y); // ghost touch events can happen while the pointer travels on top of other
// keys.
if (isModulatedKeyPressed())
return;
// 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 = _handler.modifyKey(key.key0, mods);
Pointer ptr = new Pointer(pointerId, key, value, x, y, mods);
_ptrs.add(ptr); _ptrs.add(ptr);
if (value != null && (value.flags & KeyValue.FLAG_NOREPEAT) == 0) if (value != null && !value.hasFlags(KeyValue.FLAG_SPECIAL))
startKeyRepeat(ptr); startKeyRepeat(ptr);
_handler.onPointerDown(value); _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 _handler.modifyKey(ptr.key.key0, ptr.modifiers);
KeyValue k;
for (int i = 0; i > -3; i = (~i>>31) - i)
{
int d = Math.floorMod(direction + i - 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;
} }
public void onTouchMove(float x, float y, int pointerId) public void onTouchMove(float x, float y, int pointerId)
@@ -110,44 +178,52 @@ public final class Pointers implements Handler.Callback
Pointer ptr = getPtr(pointerId); Pointer ptr = getPtr(pointerId);
if (ptr == null) if (ptr == null)
return; 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 dx = x - ptr.downX;
float dy = y - ptr.downY; float dy = y - ptr.downY;
float dist = Math.abs(dx) + Math.abs(dy); float dist = Math.abs(dx) + Math.abs(dy);
ptr.ptrDist = dist; ptr.ptrDist = dist;
KeyValue newValue;
int direction;
if (dist < _config.swipe_dist_px) if (dist < _config.swipe_dist_px)
{ {
newValue = ptr.key.key0; direction = 0;
}
else if (ptr.key.edgekeys)
{
if (Math.abs(dy) > Math.abs(dx)) // vertical swipe
newValue = (dy < 0) ? ptr.key.key1 : ptr.key.key4;
else // horizontal swipe
newValue = (dx < 0) ? ptr.key.key3 : ptr.key.key2;
} }
else else
{ {
if (dx < 0) // left side // One of the 8 directions:
newValue = (dy < 0) ? ptr.key.key1 : ptr.key.key3; // |\2|3/|
else // right side // |1\|/4|
newValue = (dy < 0) ? ptr.key.key2 : ptr.key.key4; // |-----|
// |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 (newValue != null && newValue != ptr.value)
if (direction != ptr.selected_direction)
{ {
int old_flags = (ptr.value != null) ? ptr.value.flags : 0; ptr.selected_direction = direction;
ptr.value = newValue; KeyValue newValue = getKeyAtDirection(ptr, direction);
ptr.flags = newValue.flags; if (newValue != null && (ptr.value == null || !newValue.equals(ptr.value)))
if ((old_flags & newValue.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
{ {
int old_flags = ptr.flags;
ptr.value = newValue;
ptr.flags = newValue.getFlags();
// Keep the keyrepeat going between modulated keys. // Keep the keyrepeat going between modulated keys.
} if ((old_flags & ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) == 0)
else {
{ stopKeyRepeat(ptr);
stopKeyRepeat(ptr); if ((ptr.flags & KeyValue.FLAG_SPECIAL) == 0)
if ((newValue.flags & KeyValue.FLAG_NOREPEAT) == 0) startKeyRepeat(ptr);
startKeyRepeat(ptr); }
_handler.onPointerSwipe(newValue); _handler.onPointerDown(true);
} }
} }
} }
@@ -167,10 +243,14 @@ public final class Pointers implements Handler.Callback
_ptrs.remove(ptr); _ptrs.remove(ptr);
} }
private Pointer getLatched(KeyValue kv) private Pointer getLatched(Pointer target)
{ {
KeyboardData.Key k = target.key;
KeyValue v = target.value;
if (v == null)
return null;
for (Pointer p : _ptrs) for (Pointer p : _ptrs)
if (p.value == kv && p.pointerId == -1) if (p.key == k && p.pointerId == -1 && p.value != null && p.value.equals(v))
return p; return p;
return null; return null;
} }
@@ -189,6 +269,16 @@ public final class Pointers implements Handler.Callback
} }
} }
private boolean isModulatedKeyPressed()
{
for (Pointer ptr : _ptrs)
{
if ((ptr.flags & KeyValue.FLAG_PRECISE_REPEAT) != 0)
return true;
}
return false;
}
// Key repeat // Key repeat
/** Message from [_keyrepeat_handler]. */ /** Message from [_keyrepeat_handler]. */
@@ -208,7 +298,7 @@ public final class Pointers implements Handler.Callback
nextInterval = (long)((float)nextInterval / modulatePreciseRepeat(ptr)); nextInterval = (long)((float)nextInterval / modulatePreciseRepeat(ptr));
} }
_keyrepeat_handler.sendEmptyMessageDelayed(msg.what, nextInterval); _keyrepeat_handler.sendEmptyMessageDelayed(msg.what, nextInterval);
_handler.onPointerHold(ptr.value); _handler.onPointerHold(ptr.value, ptr.modifiers);
return (true); return (true);
} }
} }
@@ -249,42 +339,110 @@ public final class Pointers implements Handler.Callback
return Math.min(8.f, Math.max(0.1f, accel)); return Math.min(8.f, Math.max(0.1f, accel));
} }
private final class Pointer private static final class Pointer
{ {
/** -1 when latched. */ /** -1 when latched. */
public int pointerId; public int pointerId;
public KeyboardData.Key key; /** The Key pressed by this Pointer */
public final KeyboardData.Key key;
/** Current direction. */
public int selected_direction;
/** Selected value with [modifiers] applied. */
public KeyValue value; public KeyValue value;
public float downX; public float downX;
public float downY; public float downY;
/** Distance of the pointer to the initial press. */ /** Distance of the pointer to the initial press. */
public float ptrDist; 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; public int flags;
/** Identify timeout messages. */ /** Identify timeout messages. */
public int timeoutWhat; public int timeoutWhat;
/** ptrDist at the first repeat, -1 otherwise. */ /** ptrDist at the first repeat, -1 otherwise. */
public float repeatingPtrDist; public float repeatingPtrDist;
public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y) public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifiers m)
{ {
pointerId = p; pointerId = p;
key = k; key = k;
selected_direction = 0;
value = v; value = v;
downX = x; downX = x;
downY = y; downY = y;
ptrDist = 0.f; ptrDist = 0.f;
flags = (v == null) ? 0 : v.flags; modifiers = m;
flags = (v == null) ? 0 : v.getFlags();
timeoutWhat = -1; timeoutWhat = -1;
repeatingPtrDist = -1.f; 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 public interface IPointerEventHandler
{ {
public void onPointerDown(KeyValue k); /** Key can be modified or removed by returning [null]. */
public void onPointerSwipe(KeyValue k); public KeyValue modifyKey(KeyValue k, Modifiers flags);
public void onPointerUp(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
[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();
public void onPointerHold(KeyValue k);
/** Key is repeating. */
public void onPointerHold(KeyValue k, Modifiers flags);
} }
} }

View File

@@ -18,6 +18,9 @@ public class Theme
public final float keyBorderRadius; public final float keyBorderRadius;
public final int colorNavBar;
public final boolean isLightNavBar;
private final Paint _keyLabelPaint; private final Paint _keyLabelPaint;
private final Paint _specialKeyLabelPaint; private final Paint _specialKeyLabelPaint;
private final Paint _keySubLabelPaint; private final Paint _keySubLabelPaint;
@@ -29,6 +32,8 @@ public class Theme
keyBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKey, 0)); keyBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKey, 0));
keyDownBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKeyActivated, 0)); keyDownBgPaint.setColor(s.getColor(R.styleable.keyboard_colorKeyActivated, 0));
// colorKeyboard = s.getColor(R.styleable.keyboard_colorKeyboard, 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); labelColor = s.getColor(R.styleable.keyboard_colorLabel, 0);
activatedColor = s.getColor(R.styleable.keyboard_colorLabelActivated, 0); activatedColor = s.getColor(R.styleable.keyboard_colorLabelActivated, 0);
lockedColor = s.getColor(R.styleable.keyboard_colorLabelLocked, 0); lockedColor = s.getColor(R.styleable.keyboard_colorLabelLocked, 0);
@@ -70,7 +75,7 @@ public class Theme
{ {
if (_specialKeyFont == null) if (_specialKeyFont == null)
{ {
_specialKeyFont = Typeface.createFromAsset(context.getAssets(), "fonts/keys.ttf"); _specialKeyFont = Typeface.createFromAsset(context.getAssets(), "special_font.ttf");
} }
return _specialKeyFont; return _specialKeyFont;
} }

7
srcs/special_font/01.svg Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- IcoMoon-Free 227-smile2 CC BY 4.0 -->
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<path fill="#000000" d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM11 4c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM5 4c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM8 13c-1.82 0-3.413-0.973-4.288-2.427l1.286-0.772c0.612 1.018 1.727 1.699 3.002 1.699s2.389-0.681 3.002-1.699l1.286 0.772c-0.874 1.454-2.467 2.427-4.288 2.427z"></path>
</svg>

After

Width:  |  Height:  |  Size: 742 B

16
srcs/special_font/02.svg Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- IcoMoon-Free 327-move-up CC BY 4.0 -->
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<path fill="#000000" d="M11 8v6h1v-6h2.5l-3-3-3 3z"></path>
<path fill="#000000" d="M1 3h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M3 3h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M5 3h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M1 6.5h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M2.5 7h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M4.5 7h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M1 4.5h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M5 5h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M5 11v3h-3v-3h3zM6 10h-5v5h5v-5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 921 B

16
srcs/special_font/03.svg Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- IcoMoon-Free 328-move-down CC BY 4.0 -->
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<path fill="#000000" d="M12 11v-6h-1v6h-2.5l3 3 3-3z"></path>
<path fill="#000000" d="M5 4v3h-3v-3h3zM6 3h-5v5h5v-5z"></path>
<path fill="#000000" d="M1 10h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M3 10h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M5 10h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M1 13.5h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M2.5 14h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M4.5 14h1.5v1h-1.5v-1z"></path>
<path fill="#000000" d="M1 11.5h1v1.5h-1v-1.5z"></path>
<path fill="#000000" d="M5 12h1v1.5h-1v-1.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 931 B

1
srcs/special_font/04.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M495.9 166.6C499.2 175.2 496.4 184.9 489.6 191.2L446.3 230.6C447.4 238.9 448 247.4 448 256C448 264.6 447.4 273.1 446.3 281.4L489.6 320.8C496.4 327.1 499.2 336.8 495.9 345.4C491.5 357.3 486.2 368.8 480.2 379.7L475.5 387.8C468.9 398.8 461.5 409.2 453.4 419.1C447.4 426.2 437.7 428.7 428.9 425.9L373.2 408.1C359.8 418.4 344.1 427 329.2 433.6L316.7 490.7C314.7 499.7 307.7 506.1 298.5 508.5C284.7 510.8 270.5 512 255.1 512C241.5 512 227.3 510.8 213.5 508.5C204.3 506.1 197.3 499.7 195.3 490.7L182.8 433.6C167 427 152.2 418.4 138.8 408.1L83.14 425.9C74.3 428.7 64.55 426.2 58.63 419.1C50.52 409.2 43.12 398.8 36.52 387.8L31.84 379.7C25.77 368.8 20.49 357.3 16.06 345.4C12.82 336.8 15.55 327.1 22.41 320.8L65.67 281.4C64.57 273.1 64 264.6 64 256C64 247.4 64.57 238.9 65.67 230.6L22.41 191.2C15.55 184.9 12.82 175.3 16.06 166.6C20.49 154.7 25.78 143.2 31.84 132.3L36.51 124.2C43.12 113.2 50.52 102.8 58.63 92.95C64.55 85.8 74.3 83.32 83.14 86.14L138.8 103.9C152.2 93.56 167 84.96 182.8 78.43L195.3 21.33C197.3 12.25 204.3 5.04 213.5 3.51C227.3 1.201 241.5 0 256 0C270.5 0 284.7 1.201 298.5 3.51C307.7 5.04 314.7 12.25 316.7 21.33L329.2 78.43C344.1 84.96 359.8 93.56 373.2 103.9L428.9 86.14C437.7 83.32 447.4 85.8 453.4 92.95C461.5 102.8 468.9 113.2 475.5 124.2L480.2 132.3C486.2 143.2 491.5 154.7 495.9 166.6V166.6zM256 336C300.2 336 336 300.2 336 255.1C336 211.8 300.2 175.1 256 175.1C211.8 175.1 176 211.8 176 255.1C176 300.2 211.8 336 256 336z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

3
srcs/special_font/05.svg Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com arrow-up-bold -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M15,20H9V12H4.16L12,4.16L19.84,12H15V20Z" /></svg>

After

Width:  |  Height:  |  Size: 384 B

3
srcs/special_font/06.svg Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com arrow-right-bold -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,15V9H12V4.16L19.84,12L12,19.84V15H4Z" /></svg>

After

Width:  |  Height:  |  Size: 386 B

3
srcs/special_font/07.svg Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com arrow-down-bold -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M9,4H15V12H19.84L12,19.84L4.16,12H9V4Z" /></svg>

After

Width:  |  Height:  |  Size: 384 B

3
srcs/special_font/08.svg Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com arrow-left-bold -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M20,9V15H12V19.84L4.16,12L12,4.16V9H20Z" /></svg>

After

Width:  |  Height:  |  Size: 385 B

6
srcs/special_font/09.svg Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="16" viewBox="0 0 18 16">
<path fill="#000000" d="M17 2h-16c-0.55 0-1 0.45-1 1v10c0 0.55 0.45 1 1 1h16c0.55 0 1-0.45 1-1v-10c0-0.55-0.45-1-1-1zM10 4h2v2h-2v-2zM13 7v2h-2v-2h2zM7 4h2v2h-2v-2zM10 7v2h-2v-2h2zM4 4h2v2h-2v-2zM7 7v2h-2v-2h2zM2 4h1v2h-1v-2zM2 7h2v2h-2v-2zM3 12h-1v-2h1v2zM12 12h-8v-2h8v2zM16 12h-3v-2h3v2zM16 9h-2v-2h2v2zM16 6h-3v-2h3v2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 651 B

6
srcs/special_font/0A.svg Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<path fill="#000000" d="M10.5 14h-5c-0.276 0-0.5-0.224-0.5-0.5v-5.5h-2c-0.202 0-0.385-0.122-0.462-0.309s-0.035-0.402 0.108-0.545l5-5c0.195-0.195 0.512-0.195 0.707 0l5 5c0.143 0.143 0.186 0.358 0.108 0.545s-0.26 0.309-0.462 0.309h-2v5.5c0 0.276-0.224 0.5-0.5 0.5zM6 13h4v-5.5c0-0.276 0.224-0.5 0.5-0.5h1.293l-3.793-3.793-3.793 3.793h1.293c0.276 0 0.5 0.224 0.5 0.5v5.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 697 B

9
srcs/special_font/0B.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="-10 0 750 1000"
fill="currentColor">
<!-- created by @sdrapha - https://github.com/sdrapha/IconFontSVG
License - LICENSE: CC BY-SA 4.0 -->
<!-- derived from Entypo+ arrow-left-bold by Daniel Bruce -->
<title>arrow-home</title>
<path d="M0 165h50v669h-50v-669zM378 830l-328 -330l328 -330v190h352v278h-352v192z" />
</svg>

After

Width:  |  Height:  |  Size: 381 B

9
srcs/special_font/0C.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="-10 0 750 1000"
fill="currentColor">
<!-- created by @sdrapha - https://github.com/sdrapha/IconFontSVG
License - LICENSE: CC BY-SA 4.0 -->
<!-- derived from Entypo+ arrow-right-bold by Daniel Bruce -->
<title>arrow-end</title>
<path d="M680 170h50v660h-50v-660zM350 170l330 330l-330 330v-192h-350v-278h350v-190z" />
</svg>

After

Width:  |  Height:  |  Size: 384 B

8
srcs/special_font/0D.svg Normal file
View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<!-- Material Icons by @google - https://github.com/google/material-design-icons
License - Apache-2.0 License -->
<title>space-bar</title>
<path d="M18 9v4H6V9H4v6h16V9h-2z"/>
</svg>

After

Width:  |  Height:  |  Size: 274 B

9
srcs/special_font/0E.svg Normal file
View File

@@ -0,0 +1,9 @@
<?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="-10 0 870 1000">
<g transform="matrix(1 0 0 -1 0 850)">
<path fill="currentColor"
d="M200 390h510v240h140v-280q0 -42 -30 -71t-70 -29h-550v-100l-200 170l200 170v-100z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 434 B

9
srcs/special_font/0F.svg Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
<path fill="#000000" d="M15 0h1v8h-1v-8z"></path>
<path fill="#000000" d="M0 8h1v8h-1v-8z"></path>
<path fill="#000000" d="M5 11h11v2h-11v2.5l-3.5-3.5 3.5-3.5v2.5z"></path>
<path fill="#000000" d="M11 5h-11v-2h11v-2.5l3.5 3.5-3.5 3.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 563 B

4
srcs/special_font/10.svg Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com backspace-reverse-outline -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M5,15.59L6.41,17L10,13.41L13.59,17L15,15.59L11.41,12L15,8.41L13.59,7L10,10.59L6.41,7L5,8.41L8.59,12L5,15.59M2,3A2,2 0 0,0 0,5V19A2,2 0 0,0 2,21H17C17.69,21 18.23,20.64 18.59,20.11L24,12L18.59,3.88C18.23,3.35 17.69,3 17,3H2M2,5H17L21.72,12L17,19H2V5Z" /></svg>

After

Width:  |  Height:  |  Size: 606 B

4
srcs/special_font/11.svg Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- materialdesignicons.com backspace-outline -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,15.59L17.59,17L14,13.41L10.41,17L9,15.59L12.59,12L9,8.41L10.41,7L14,10.59L17.59,7L19,8.41L15.41,12L19,15.59M22,3A2,2 0 0,1 24,5V19A2,2 0 0,1 22,21H7C6.31,21 5.77,20.64 5.41,20.11L0,12L5.41,3.88C5.77,3.35 6.31,3 7,3H22M22,5H7L2.28,12L7,19H22V5Z" /></svg>

After

Width:  |  Height:  |  Size: 596 B

14
srcs/special_font/50.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM650 1541h230
l2 -6l-269 -260h-148z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

14
srcs/special_font/51.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM553 1395l147 148
h170v-18l-257 -245h-119l-254 243v20h166z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

14
srcs/special_font/52.svg Normal file
View File

@@ -0,0 +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="-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.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>

After

Width:  |  Height:  |  Size: 1.5 KiB

14
srcs/special_font/53.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM863 1304v-25
h-161l-147 148l-146 -148h-160v26l246 237h120z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

14
srcs/special_font/54.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM638 1279h-158
l-250 260l3 6h230zM638 1279h-158l-250 260l3 6h230z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

14
srcs/special_font/55.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM925.5 1318h-721
v146h721v-146z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

14
srcs/special_font/56.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM378 1412
q0 72 51.5 120.5t124.5 48.5q72 0 122.5 -48.5t50.5 -120.5q0 -73 -50.5 -118.5t-122.5 -45.5q-74 0 -125 46t-51 118zM478 1412q0 -31 22.5 -52.5t53.5 -21.5q30 0 51.5 21t21.5 53t-21.5 54.5t-51.5 22.5q-32 0 -54 -22.5t-22 -54.5z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

14
srcs/special_font/57.svg Normal file
View File

@@ -0,0 +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="-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.3159 -249.792 98.0859v99.3945q176.555 -11.7715 319.106 -128.166zM516.679 1031.55q-133.396 -10.4619 -249.792 -100.701q0 1.30811 -71.9297 74.5449l2.61523 -2.61523q142.553 116.395 319.106 128.166v-99.3945z
M197.572 860.229q-90.2388 -103.317 -107.24 -245.868h-99.3936q17.001 181.786 137.32 319.105l-6.53906 5.23145l3.92285 -2.61523l41.8506 -43.1582q30.0791 -31.3872 30.0791 -32.6953zM1137.89 614.361h-99.3936q-17.001 141.243 -107.24 248.484l69.3135 70.6211
q120.319 -137.32 137.32 -319.105zM1137.89 517.583q-14.3862 -189.633 -129.474 -326.953l-69.3135 70.6221q86.3159 111.164 99.3936 256.331h99.3936zM189.726 263.867q-75.8525 -77.1606 -74.5449 -77.1611l3.92285 3.92383q-115.087 137.32 -128.165 326.953h99.3936
q13.0781 -146.476 99.3936 -253.716zM939.103 121.315q-146.476 -124.242 -326.953 -136.013v99.3945q139.935 11.77 257.639 105.933zM516.679 -14.6973q-180.478 11.7715 -326.953 136.013l69.3145 69.3145q117.703 -90.2388 257.639 -105.933v-99.3945zM902 1522
q0 -94 -59.5 -159t-149.5 -65q-71 0 -148 46.5t-128 46.5q-43 0 -72 -32.5t-29 -78.5l-108 26q0 93 59 161.5t150 68.5q56 0 140 -47t136 -47q41 0 71 32.5t30 79.5z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Some files were not shown because too many files have changed in this diff Show More