Compare commits

...

305 Commits

Author SHA1 Message Date
Jules Aguillon
997b7be4c0 launcher: Animated vector describing swipe gesture
Replace the short video with an animated vector image that shows the
swipe gesture.

This is much lighter and reliable than the mp4 video, which failed to
play on many devices.

Source for the image of the key is in inkscape SVG format in srcs/res
and is converted to an android drawable when needed. The swipe animation
is hand-written.
2024-11-18 00:13:08 +01:00
Jules Aguillon
23097921cf Disable automatic Shift when pressing Compose 2024-11-17 11:10:21 +01:00
Jules Aguillon
237c4e2cc2 Automatic Shift should be disabled when pressing Ctrl
This was caused by a programming error.
2024-11-17 11:09:24 +01:00
Jules Aguillon
9bf0a20226 method.xml: Add Australia 2024-11-17 10:38:33 +01:00
Jules Aguillon
354c0a6f1c compose: Add digits to accent_dot_above 2024-11-16 12:23:25 +01:00
Jules Aguillon
46408572bc font: Use standard symbols for home and end
The glyphs are taken from DejaVuSans, the lines are thickened to improve
readability.
2024-11-16 12:08:36 +01:00
Jules Aguillon
0d51f7ea1e Don't apply Fn to space bar left and right
"home" and "end" on the spacebar slider are not useful.
2024-11-16 11:46:43 +01:00
DocJr90
fcbaa23ccf
Add "scroll_lock" key (#800)
Added "scroll_lock" equates to KeyEvent.KEYCODE_SCROLL_LOCK
2024-11-11 16:28:59 +01:00
Jules Aguillon
70365b48d4 Readme: Update link and status for Calculator++ 2024-10-27 11:12:34 +01:00
Jules Aguillon
3c30e8248e Stable extra keys position when number row is added
Add the extra keys to the keyboard before the number row is added, as
that interferes with the "preferred pos" system.
2024-10-27 11:04:05 +01:00
Kalan Walmsley
73742a853f
Rosé Pine Theme (#788) 2024-10-26 00:54:25 +02:00
solokot
24a6dd0f2c
Update Russian translation (#784) 2024-10-19 11:39:40 +02:00
Anastázius Kaejatídarján
2233250e4d
Slavonictajiki (#776)
new layouts for old slavonic and tajik languages
2024-10-05 23:58:42 +02:00
Jules Aguillon
c4a88e4d5b Update compose sequences for Cyrillic
Mainly add sequences for the combining diacritics.

Co-authored-by: Anastazius Kaejatidarjan <zdarian@asu.edu>
2024-10-05 11:39:11 +02:00
Jules Aguillon
cd2932bde1 Add slavonic combining diacritics
Co-authored-by: Anastazius Kaejatidarjan <zdarian@asu.edu>
2024-10-05 11:28:14 +02:00
Zitrone
6fae23a432
compose/accent_*.json: improvements (more accents) (#770)
compose/accent_*.json: improve/complete implementation
compose/shift.json: uppercase for superscript letters & characters without preapplied uppercase versions
2024-10-05 11:06:24 +02:00
Sergiy Stupar
6e2494ca0b
Update Ukrainian translation (#781) 2024-10-05 10:31:39 +02:00
Jules Aguillon
8a6dc34b2c Add combining diacritics keys
Co-authored-by: Anastazius Kaejatidarjan <zdarian@asu.edu>
2024-10-04 01:09:51 +02:00
Jules Aguillon
9f0cf15d2e Add Fn layer and Compose sequences for Cyrillic 2024-09-29 22:47:57 +02:00
Jules Aguillon
700ec23bd4 Improve Ctrl key labels for Serbian Cyrillic layout
Add the ':char' syntax for defining character keys with a different
symbol.
This new kind of keys is used to implement Ctrl combinations in the
Serbian Cyrillic layout without showing latin letters while the Ctrl
modifier is activated.
2024-09-29 22:05:54 +02:00
Jules Aguillon
fb93d841a5 refactoring: safer KeyboardData.load 2024-09-29 22:05:09 +02:00
Jules Aguillon
a1be402638 Fix crash with complex keys 2024-09-29 21:59:07 +02:00
Jules Aguillon
9f22e53a3b
Add complex keys (#774)
This allows to add new kinds of keys that need more data without making
KeyValue's footprint bigger for common keys.

This changes the [_symbol] field into [_payload], which holds the same
as the previous field for more common keys but can hold bigger objects
for keys of the new "Complex" kind.

This also adds a complex key: String keys with a symbol different than
the outputted string.

Unit tests are added as the Java language is not helpful in making
robust code.
2024-09-29 21:58:22 +02:00
bokidori
e309b76c0a
Increase default label size (#747)
Change default label size to 1.15
2024-09-21 23:30:01 +02:00
Mostafa Khorashadi Zadeh
4d686a8836
Change the place of چ and ژ in Persian Keyboard Layout (#757)
* Change place of "چ" and "ژ"

* rollback unexpected changes
2024-09-21 11:33:59 +02:00
Zitrone
b21bf3fffd
Improve bone layout (#748)
* shell.nix: fix gradle error

error was:
> \> Task :compileDebugJavaWithJavac FAILED
> error: Source option 7 is no longer supported. Use 8 or later.
> error: Target option 7 is no longer supported. Use 8 or later.

fixed by overriding the jdk version for gradle to openjdk17

* layouts/latn_bone: fix layout

- fix alignment with tabs mess
- make like actual bone layout, instead of trying to fit it into a 10 key
  wide keyboard
  - fixes missing üäö
  - fix missing $
  - moves q and ß where they belong
  - remove all of the diacritic keys (they can be added through the
    settings as extra keys)
  - kept the number row extra keys integration into top row
  - kept the idea of compressing , and . into the swipe actions of the
    bottom row
  - kept the number keys as key4 in the layer4 positions (instead of
    moving them to a number row, which i also considered)
2024-09-19 23:57:26 +02:00
Spike
7454389f48
doc: Point to code for built-in bottom row and number row for use as starting points (#756) 2024-09-19 23:48:56 +02:00
Jules Aguillon
b61e9db21e compose: Deduplicate end states
Make compose sequences ending in the same character to share the ending
state.
This reduce the compiled compose key data size from 33kB to 27kB.
2024-09-14 15:13:04 +02:00
Jules Aguillon
24d6b96ad7 Add Serbian to method.xml 2024-09-14 14:28:56 +02:00
Jules Aguillon
13ad05c0b0 doc: Mention switch_clipboard 2024-09-14 14:26:34 +02:00
Jules Aguillon
a8e331c322 Define the Shift modifier using the compose mechanism 2024-09-10 22:50:39 +02:00
Jules Aguillon
b600332595 Define the Fn modifier using the compose mechanism
This removes 100Kb from the app.
2024-09-10 22:43:40 +02:00
Jules Aguillon
e734d1d0e2 compose: Allow c-style comments in json files
Useful to manager growing the collection of sequences.
2024-09-10 22:43:05 +02:00
Jules Aguillon
c57ae83bfa Compose sequences can end in internal key names
This adds the '\n' and '\t' sequences to showcase the new feature.
2024-09-10 22:16:49 +02:00
Jules Aguillon
c886a89b11 Update autocapitalisation on Enter 2024-09-10 21:53:52 +02:00
cknight828
231c08eb97
Add Japanese translation and layout (#743) 2024-09-08 15:46:38 +02:00
IYO-OYI
4eca9caec1
Update Korean translations (#737) 2024-08-24 23:43:42 +02:00
Spike
bc8fef11f1
Modmap: Reorganize (#730)
Put new example in Examples section; put all overview material at start; use "modmap" for the modmap tag but "mapping" for the various subtags; set out each subtag separately; stop illustrating example mappings as complete modmap.
2024-08-18 21:49:30 +02:00
Jules Aguillon
4d0598a011 Fix crash when clipboard contains an image 2024-08-18 21:24:32 +02:00
Jules Aguillon
038f693cae Update target SDK version to 35 2024-07-28 23:07:05 +02:00
bokidori
72d88a5298
Map Fn+Cursor_move to home/end (#728)
Fn modifier switches cursor_left to home key, cursor_right to end key
2024-07-28 21:29:50 +02:00
Jules Aguillon
bd50964651 Release 1.29.1 (42) 2024-07-27 12:35:59 +02:00
Adrian
105a5a2f33
Added supported key for avoiding the pain of auto-caps (#725) 2024-07-27 12:27:05 +02:00
bokidori
62530e98b9
Update cyrl_lynyertz_sr.xml (#727)
Include comprehensive ctrl modmap, enabling the use of ctrl modifier with Serbian Cyrillic keys. Remove clunky fn modmap previously used for just a few actions such as cut/copy/paste/etc.
2024-07-27 12:17:40 +02:00
Nils Brederlow
b3d1a3fc1a
Add new keyevent "menu" (#726)
* Update ExtraKeysPreference.java

add "menu" to array of extra keys

* Update KeyValue.java

add menu keyevent
2024-07-27 12:00:20 +02:00
Jules Aguillon
50a3c0f5bc Fix scaling for layouts with few columns
This was causing a slight padding on the right of 4 columns layouts,
which turned into a large padding when the number row was added.
2024-07-27 00:48:18 +02:00
Jules Aguillon
d8fc4e80e3 Fix crash on Android 6
The call to getLanguageTag() introduced in 4629410 requires API 24.
2024-07-27 00:25:33 +02:00
Jules Aguillon
9d76227982 check_layout.py: Handle compass-point attributes 2024-07-26 00:10:54 +02:00
Jules Aguillon
3967fb8a9f doc: Document the <ctrl /> modmap 2024-07-26 00:04:57 +02:00
Jules Aguillon
29b4b665dc Allow Ctrl modmaps in layouts
The 'ctrl' modmap is different from the other modmaps as it also applies
the built-in Ctrl modifier to the resulting character, even if it was
first modified by the custom modmap.

For example, this will map Ctrl+в to Ctrl+V (not to v):

    <ctrl a="в" b="v"/>

This is intended to add keyboard shortcuts in non-latin layouts.

A caveat is that the latin character appears on the keyboard while Ctrl
is activated.
2024-07-25 23:40:58 +02:00
Jules Aguillon
35f35b27be Update ComposeKeyData
Outdated since 6c786f2
2024-07-25 23:23:53 +02:00
asivery
bf2bec0d4b
Revert "latn_qwerty_pl: Consistent placement for ó" (#714)
This reverts commit c5e9e3ff5c.
2024-07-25 23:22:38 +02:00
bokidori
6e1364b5c2
Add Serbian Latin QWERTY layout (#720)
Adds Serbian Latin QWERTY layout. Serbian language uses both Latin and Cyrillic as its official scripts, and this variant should cover anyone from Serbo-Croatian speaking group that uses Latin script.
2024-07-25 23:21:39 +02:00
bokidori
acddd70435
Add Serbian Cyrillic layout (#718)
Adds Serbian Cyrillic layout. Modmap of Fn key allows for desktop-like easier access to actions such as selectAll, copy, paste, etc. This is because, unlike desktop systems, on mobile ctrl does not combine with cyrillic keys to perform actions.
2024-07-25 23:14:30 +02:00
bokidori
6c786f2a1a
Update accent_circonflexe.json (#719)
Allow combining circumflex \u0302 for Cyrillic vowels, enabling users to express themselves accurately.

ја сам са̂м = I am alone
ја сам сам = I am am

да = yes
да̂ = give

код = at
ко̂д = code

Similar to #437 for aigo.
2024-07-25 23:12:55 +02:00
Jules Aguillon
2696f42144
Allow extending the compose key (#713)
This allows adding more compose sequences without modifying
en_US_UTF_8_Compose.pre.

This is done by grouping sequences files that should be merged together
into a directory. This also allows moving keysymdef.h into that
directory.
2024-07-21 23:37:07 +02:00
Reza Hosseinzadeh
84e10e0470
Improve zwnj/halfspace symbol and Persian layout (#711)
* Fix persian's half-space invisibility
* Add a 0.5 space before ظ in persian
* Change the place of چ in persian
* Change the width of backspace in persian
* Rename zwnj to halfspace in KeyValue.java and beng_provat layout
2024-07-21 13:37:01 +02:00
Jules Aguillon
65f4ffd15b method.xml: Remove overridesImplicitlyEnabledSubtype
This was hoped to fix a random layouts to be shown by default to users
of unsupported languages. This breaks language switching using the
system dialog.
2024-07-20 12:20:24 +02:00
Jules Aguillon
deb611a0d2 Release 1.29.0 (41) 2024-07-15 00:21:59 +02:00
solokot
29f03d0e96
Update Russian translation (#702) 2024-07-14 16:55:34 +02:00
Jules Aguillon
4629410230 Fix unintended layout used for unsupported languages
The arabic layout was used as the default on devices where all the
installed languages are not supported by the keyboard. This is not
intended.
This is probably caused by 'getCurrentInputMethodSubtype' returning the
first layout in the list of disabled subtypes in alphabetical or
language tag order.
Re-ordering the subtypes in method.xml had no effect.

Setting 'overridesImplicitlyEnabledSubtype' in method.xml has no
measured effect.
2024-07-14 16:15:18 +02:00
Jules Aguillon
b9526d918d Fix crash when using a different script layout
This might happen when using a layout of a different script than the
installed languages.
2024-07-14 15:52:24 +02:00
Mehmet Ali
db3b021bfc
Update Turkish Translations (#699) 2024-07-13 11:16:06 +02:00
Spike
3862f4d6ba
doc: Re-add text for better overview (#697) 2024-07-10 22:47:58 +02:00
Edgars
555ede0fee
Add missing Latvian translations (#698) 2024-07-09 19:36:05 +02:00
Spike
7b90294b57
Clerical edits related to locale_extra_keys (#696)
* Post-edit on Metadata

① Tell reader exactly what to type to disable locale_extra_keys, as with prev. bullet
② Values should be quoted
③ Rephrase one passive

* locale_extra_keys obviates 2nd example under modmap
2024-07-08 22:45:11 +02:00
Spike
69881e75c7
Update Spanish translations (#695) 2024-07-08 00:17:16 +02:00
Chasm Solacer
533e22ab4f
Update Polish translation (#691) 2024-07-07 14:21:35 +02:00
Sergiy Stupar
46c86a05bd
Update Ukrainian translation (#692) 2024-07-07 14:21:03 +02:00
Validbit
e053d4b20c
Update Czech strings.xml (#693) 2024-07-07 14:20:13 +02:00
polyctena
c1e19a21d0
Update values-de/strings.xml (#694) 2024-07-07 14:19:33 +02:00
Jules Aguillon
3164215879 Add locale_extra_keys keyboard attribute
This attribute can be used to disable adding the extra keys from
method.xml.
2024-07-06 23:09:51 +02:00
Jules Aguillon
99367a9ec6 Update French translations 2024-07-06 22:42:56 +02:00
TadaCZE
cd0f61da74
Add support for Android 12+ dynamic colors (#647) 2024-07-06 22:32:01 +02:00
Jules Aguillon
ce57b5a4a2 Make the emoji and clipboard bottom rows consistent 2024-07-06 22:19:34 +02:00
Jules Aguillon
bf3b9c374e
Clipboard pane (#681)
This adds the clipboard pane, which allows to save an arbitrary number of
clipboards and to paste them later. The key can be disabled in settings.

Checking the "Recently copied text" checkbox will cause the keyboard to keep a
temporary history of copied text. This history can only contain 3 elements
which expire after 5 minutes.
If this is unchecked, no history is collected.

History entries can be pinned into the persisted list of pins.
2024-07-06 22:16:37 +02:00
Jules Aguillon
6021a0b83c Fix crash with narrow layouts
The PreferredPos mechanism cause an out of bound access since 773147a.
2024-07-06 13:34:08 +02:00
solokot
89d0e6c063
Update Russian translation (#689) 2024-07-06 11:15:49 +02:00
Jules Aguillon
a2eea76e70 doc: Clarify the possible key values 2024-07-03 00:35:25 +02:00
Sergiy Stupar
2cb5e67d1f
Update Ukrainian translation (#682) 2024-06-30 14:02:56 +02:00
Jules Aguillon
3a371c354b doc: Correct mentions of gestures 2024-06-30 00:46:25 +02:00
Jules Aguillon
bdb080657d Option to disable key repeat
Internally "key repeat" is reword into "long press" when the same
mechanism was used for both features.

The constraint that 'timeoutWhat' must be set to '-1' when no message is
expected has been lifted to simplify the code.
2024-06-30 00:24:39 +02:00
Jules Aguillon
bf33230c26 settings: Reword "Key repeat" into "Long press"
The long press timeout is used for long press on keys that do not
repeat, for example the keyboard switching key.

This must be detached from the key repeat as it might be disableable in
the future and more keys might be longpressable.
2024-06-30 00:06:17 +02:00
Jules Aguillon
45fc18576e Validate more fields in custom layouts
This adds some errors:

- 'script' or 'numpad_script' is set an empty string.
- Multiple '<modmap>' elements.
- 'shift', 'width' and 'height' on every nodes that support them are
  clamped to a valid value.
2024-06-29 22:48:47 +02:00
Jules Aguillon
b432f1d773 Set preferred position for Norwegian extra keys
This should make the QWERTY (US) layout look the same to Norwegian users
as the current latn_qwerty_no layout, allowing it to be changed.
2024-06-24 00:14:26 +02:00
Jules Aguillon
66cf643574 Remove 'loc' keys from latn_qwerty_us
Use the "preferred position" feature to place the removed keys
approximately where they were.
2024-06-24 00:07:56 +02:00
Spike
ada3b5f3b7
doc: Where to put <modmap> (#666)
* Modmap: Where to put it; cancelling built-in mods (#665)

* Correct per Julow: not only Euro layouts

* Post-edit: Doesn't depend on "built-in" layout

* P-vs-L: Change "That is to say", sentence is not a restatement

* Discussion with Julow: Swipe graphic to HTML; at most one modmap

* Swipes: Center tables
2024-06-22 23:27:29 +02:00
Jules Aguillon
6405e5e8be Don't stop keyrepeat after a circle gesture
This was inconsistent with the anticircle and roundtrip gestures.
2024-06-22 23:10:43 +02:00
Sergiy Stupar
460f25317f
Update Ukrainian translation (#670) 2024-06-16 22:39:44 +02:00
alotbsol555
81d1a1a831
Update German translations (#667) 2024-06-16 22:39:26 +02:00
Jules Aguillon
c01b289eaf Don't change input view when configuration changes
This doesn't seem necessary and won't play well with eventual keys that
change the configuration.
2024-06-16 22:20:14 +02:00
Jules Aguillon
a7b79022e5 Launcher activity: Don't consume events in text field
Allow the keybindings to have an effect in the "Try here" text field.
2024-06-16 22:19:27 +02:00
Jules Aguillon
bad2e8c237 Refactor: Remove unecessary view in emoji pane 2024-06-16 22:19:20 +02:00
solokot
b7be19dc1f
Update Russian translation (#656) 2024-06-11 00:54:19 +02:00
Jules Aguillon
b5a96dc4dc Option to tweak or disable the circle gesture 2024-06-09 14:25:19 +02:00
Jules Aguillon
944ed32a37 Use preferred dir when placing a key next to an other 2024-06-09 14:03:02 +02:00
Jules Aguillon
773147ab9c Automatic placement of f11/f12 placeholders 2024-06-09 13:55:27 +02:00
Jules Aguillon
52805d9745 Allow to remove keys Tab and Esc 2024-06-09 13:18:25 +02:00
Jules Aguillon
8d793da6b6 Refactor: Remove the KeyModifier cache 2024-06-09 12:49:23 +02:00
Jules Aguillon
91ace060bc Move diacritics mapping to the compose state machine
This replaces the switch cases in KeyModifier.java with JSON files, one
for each diacritic.

The number of states increases from 6727 to 7377. The apk size slightly
decreases (around 3kb).
2024-06-09 11:53:17 +02:00
Jules Aguillon
ecac6a77f8 compose: Compile several starting states
Sequences from several files are no longer merged but compiled to
separate starting states.

The plan is to use that to represent the diacritics.
2024-06-09 11:52:17 +02:00
Jules Aguillon
a886f6eede compose: Fix misbehaving due to encoding errors
Encoding errors in the compose data compiler due to:
- 'UTF-16' adds a BOM, use 'UTF-16-LE' instead
- 'str.encode' returns a byte array, use 'array' to have a 16-bit char
  array.
2024-06-09 10:35:38 +02:00
Jules Aguillon
1197ce36b4 Update check_layout.output 2024-06-08 22:47:55 +02:00
Spike
8b99c04a21
Flesh out custom layout doc (#651) 2024-06-08 22:22:46 +02:00
Jules Aguillon
6ac973cfda Don't cap indication length
This was inadvertently changed when the anti-circle gesture was
introduced, which use the same rendering logic.
2024-06-06 00:30:22 +02:00
Jules Aguillon
c5e9e3ff5c latn_qwerty_pl: Consistent placement for ó
Co-authored-by: @ZX-Commodore-ST
2024-06-05 23:45:03 +02:00
Jules Aguillon
cf1aaa3bdf Add compose sequences for Greek, Cyrillic, Hebrew and more
Parse key names from keysymdef.h, which is distributed with Xorg. The
Greek, Cyrillic and Hebrew sequences referenced these keysyms.

This increases the number of sequences from 2043 to 2668.
2024-05-29 15:56:08 +02:00
Jules Aguillon
39b3f50aa3 Allow compose sequence ending with more symbols
Change the compose state machine definition to allow final states that
are wider than 16-bits.

This increases the number of sequences that can be used from
en_US_UTF_8_Compose.pre from 2013 to 2043 (of 3201).
2024-05-29 15:02:08 +02:00
Jules Aguillon
f7f1d85f80 Release 1.28.0 2024-05-29 14:08:27 +02:00
Jules Aguillon
5d2eb35574 Increase target SDK to 34 2024-05-29 14:04:14 +02:00
Jules Aguillon
93d58571cc
Fix overflow due to navigation on the right and cutouts (#641)
Take display cutouts and navigation bars when computing the keyboard
width on SDK >= 30.
2024-05-29 12:00:41 +02:00
Jules Aguillon
1a290f96f2
Configure anticircle gesture per-key (#644)
This adds the new 'anticircle' attribute to layouts '<key>' elements
that configure the key to send when doing a anti-clockwise circle
gesture on it.

Labels are drawn the same way as indication.

Updated docs.
2024-05-29 11:59:54 +02:00
Jules Aguillon
304375268d Fix uninitialized bottom_row when editing custom layout
This happen when opening the settings from the launcher activity without
ever opening the keyboard.

To remove this bug entirely, the KeyboardData.init method is removed,
the pieces needing initialization are now cached in Config.
2024-05-29 11:56:26 +02:00
Jules Aguillon
9d89297c15 Fix off-by-one error in 1-row layouts 2024-05-27 23:59:09 +02:00
Jules Aguillon
46f3b41393 Support the nnbsp character 2024-05-26 00:49:15 +02:00
Jules Aguillon
bea2e6cd1f Update check_layout.output
Was outdated since previous commit
2024-05-26 00:20:36 +02:00
Jules Aguillon
abf36e5d56 Add missing characters to hang_dubeolsik_kr 2024-05-25 23:56:35 +02:00
JapanYoshi
c9b6380ed0
Add custom layout documentation in doc/ (#643) 2024-05-25 22:22:42 +02:00
Jules Aguillon
4906f8105f
Circle and round trip gestures (#640)
This implements clockwise/anticlockwise circle and round trip gestures
inspired by Messagease.

The circle gestures start after a small threshold to avoid making the
regular swipe too hard to aim.

The gestures do:

- circle: The center symbol with Shift applied, with a fallback on Fn
- round trip: Same as the circle gesture but applied to a side symbol
- anticlockwise circle: Nothing currently. It is intended to be made
  configurable per-layout in the future.

The new Gesture class keeps track of what the pointer is doing while it moves
on a key. It replaces the 'selected_direction' integer.
2024-05-25 21:19:44 +02:00
NACAMURA Mitsuhiro
96fc4003f1
Update NixOS wiki link (#633) 2024-05-12 10:53:04 +02:00
Quinn Cypher
a91332a903
Pull the emoji list from unicode.org (#612)
- Removing unused information (names and descriptions) from the Emoji class
- Creating a Gradle task that generates a more efficient res/raw/emojis.txt file from the most recent Unicode standard
- Saving recently used emoji preferences as emoji values rather than names
- Migrating old user preferences to the new system
2024-05-08 13:02:19 +02:00
Spike
53e04d5784
Compass-point synonyms for edge keys in layouts (#628) 2024-05-08 12:51:11 +02:00
alotbsol555
c7d33356bc
Add settings button to launcher app (#629) 2024-05-05 11:22:34 +02:00
Jules Aguillon
69ab869079
Hangul support (#595)
* Hangul support

This works with two new kinds of keys (Hangul_initial and Hangul_medial)
that carry a precomposed hangul syllable and act as modifiers.

The hangul syllables are composed algorithmically.

* Add shift layer to Dubeolsik layout
2024-05-02 20:52:18 +02:00
Jules Aguillon
d96414c6c6 Allow the newline character '\n' in layouts 2024-05-02 19:37:18 +02:00
Jules Aguillon
0f11a88418
More precise and faster spacebar slider (#593)
* Make slider speed independent from swipe distance

Swipe distances other than the default resulted in a slider that were
not easy to control.

* refactor: Add class Pointers.Sliding

It holds the states and the code needed to make the slider work.
'Pointer.sliding' is set to [null] when sliding is not in progress.

The implementation is changed not to depend on [downX] and [dx] but
instead use the pointer's [x] coordinate directly.

* Move the cursor further for faster slides

In sliding mode, compute the speed of the pointer and use it to increase
at which the cursor moves.

* refactor: Separate kind for cursor movement keys

This allows to define a key that moves the cursor more than one position
at a time.

This will be used to avoid lag during fast slider movements.

* Reduce lag when sliding quickly on the spacebar

Avoid sending key events in a loop while sliding quickly in a cursor
movement key. Key of kind Cursor_move are "multiplied", meaning a single
key event represents a movement of more than one position, reducing the
number of key events sent.
This is only for cursor move keys.
2024-05-02 19:31:48 +02:00
alotbsol555
82e0840568
allow for <fn ...> in <modmap> (#626) 2024-05-02 12:09:39 +02:00
Jules Aguillon
c7ed2bcae9 Clear cache when changing layout
Due to the modmap, the cache must be cleared when switching layout to or
from a layout that contain a modmap.

This is broken since 3f6b6fd23, which moves the modmap handling into
KeyModifier.
2024-05-02 12:06:15 +02:00
JapanYoshi
5386541db3
Add more accented characters to KeyModifier.java (#622) 2024-04-25 13:24:52 +02:00
复予
94b2ded843
Update Simplified Chinese translation (#617) 2024-04-24 13:31:29 +02:00
JapanYoshi
2684d1f041
Turkish: Correct shift behavior for ı and i (#615) 2024-04-19 14:38:35 +02:00
Jules Aguillon
78f85e52a2 Fix space key without a symbol
The symbol on the space key was accidentally lost in be97364 when the
string "\r" (Java's only way to write "\x0D") was not replaced by
"\xE00D".
2024-04-03 23:59:18 +02:00
Tomasz Cielecki
5e3a3f894b
Add Danish layout (#606) 2024-04-03 23:46:39 +02:00
Jules Aguillon
3f6b6fd232 refactor: Apply the modmap in KeyModifier
This makes possible to apply other modifiers to mapped keys and ensures
that the modmap really override the shift key behavior.
2024-04-01 23:01:21 +02:00
Jules Aguillon
f17afba7be sync_translations: Fix store descrs not updated 2024-03-24 21:37:41 +01:00
marciozomb13
7e9d8c73df
Update pt-BR translations (#598) 2024-03-24 21:36:55 +01:00
Benson Muite
b22b49d3e6
launcher: Grammar fixes (#599) 2024-03-24 21:36:18 +01:00
Lev Brekalov
7c3286078b
Add Shaw Imperial layout (#592) 2024-03-23 00:06:23 +01:00
Jules Aguillon
e604f6fd57 refactor: Implement Compose without global state
Thanks to the previous commit, a modifier key can now be more complex
than just a KeyValue.Modifier. This allows a more elegant implementation
of the compose key, that could be taken as a base for other features
(eg. unicode hex entry, hangul)

The COMPOSE_PENDING modifier is removed as keys of kind Compose_pending
can act as a modifier. This has the advantage of highlighting the key
that was last pressed in the sequence.

Rules are added to Pointers: Non-special but latchable keys must clear
latches and cannot be locked with a long press. These rules were not
needed before but were intended.
2024-03-18 01:00:22 +01:00
Jules Aguillon
dc3a303af1 refactor: Allow modifier of other key kinds
Allow keys of a kind other than Modifier to be a modifier.

This requires writing a compareTo function for KeyValue. Fields are
compared in this order: Kind, value, flags, symbol.
2024-03-18 00:40:15 +01:00
Jules Aguillon
ec8e78d5cc refactor: Use Pointers.Modifiers.has less
The performance characteristics of this function will change in future
plans.
2024-03-18 00:09:32 +01:00
Jules Aguillon
0549c6c8a1 Fix potential out of bounds access
The preferred pos mechanism could cause an out of bounds access on 1 row
layouts.
2024-03-16 23:42:37 +01:00
Jules Aguillon
e74b45c2d6 Move fastlane metadata into fastlane/metadata/android 2024-03-16 23:37:38 +01:00
solokot
1cbaa7106c
Update Russian translation (#588) 2024-03-14 00:37:37 +01:00
Jules Aguillon
fe0f82436a Improve the QWERTY (Slovak) layout
The grid layout was not likeable.
2024-03-11 20:21:26 +01:00
Jules Aguillon
5c19140609 refactor: Pointers: Flag for sliding state 2024-03-11 00:38:37 +01:00
Jules Aguillon
47e2009da4 refactor: Add latched flag to Pointers 2024-03-11 00:29:12 +01:00
Jules Aguillon
b33bcd8865 refactor: Use internal flags in Pointers
'FLAG_LOCKED' and 'FLAG_FAKE_PTR' are only used within Pointers.
Define new flags in Pointers and remove these from KeyValue. Also allows
to define new flags.
2024-03-11 00:24:25 +01:00
Spike
c41a098924
Update Spanish translations (#586) 2024-03-10 19:31:58 +01:00
Quinn Cypher
8cd868ba76
Update to Unicode Emoji v15.1 (#583) 2024-03-09 11:37:15 +01:00
Validbit
07f9c1ffaa
Update cs strings.xml (#582) 2024-03-07 19:36:48 +01:00
Edgars
9a07149efc
Update Latvian translations (#580) 2024-03-04 19:35:28 +01:00
Jules Aguillon
0594127575 metadata: Remove metedata without a short_description
It is mandatory for Google Play.
2024-03-04 00:57:23 +01:00
Jules Aguillon
a9f9bbec19 Revert renaming metadata locale directories
Metadata directories were renamed while adding store descriptions into
strings files for simplicity.

This interferes with releases so is released.
An hardcoded lookup table is used instead.
2024-03-04 00:57:23 +01:00
polyctena
35d1ebeab5
Update German strings.xml (#579) 2024-03-03 23:25:54 +01:00
Jules Aguillon
0739c6bd2c Release 1.27.0 (39) 2024-03-03 23:19:02 +01:00
Yogesh-B
a1de69bcc4
Gujarati phonetic layout (#562)
added shift modifier characters
Add support for gujarati numerals

Co-authored-by: yogesh-b <yogesh@improwised.com>
2024-03-03 23:12:52 +01:00
Jules Aguillon
5e5937b0f4 Fix auto-capitalisation disabling locked shift
Shift locked via the "caps lock" key use the "fake pointer" mechanism
that is also used by auto-capitalisation.

Make sure that unlatching a fake pointer do not disabled a locked
modifier.

The implementation is moved into the Pointers class for a safer API and
easier implementation.
2024-03-03 17:14:01 +01:00
Chasm Solacer
ce38a4f151
Update pl/strings.xml (#578) 2024-03-03 01:06:07 +01:00
Jules Aguillon
0e0c761a92 Add QWERTY (Slovak) layout
The original author is @sejkm in https://github.com/Julow/Unexpected-Keyboard/issues/573
2024-03-02 20:39:22 +01:00
Jules Aguillon
940cf0deb8 compose: Parse json files and fix edge cases
There's no json file yet, this was part of an experiment.

Add a missing escape rule and detect colliding sequences.
2024-03-02 19:12:37 +01:00
Jules Aguillon
c2d5b14261 compose: Add a README.md
Mention the source of the sequences files.
2024-03-02 19:11:41 +01:00
Jules Aguillon
ebda7b2c3e Improve the AZERTY layout
Add éèàç directly to the layout, which removes the corresponding dead
keys.

Remove the requirement for ù and ÿ from method.xml, which are extremely
rare and can be typed via the compose key.
2024-03-02 17:42:57 +01:00
Jules Aguillon
39f6d294fb translations: Remove outdated store descriptions 2024-03-02 17:22:22 +01:00
Jules Aguillon
8b5d971fb5 Modify the number row according to the numpad script
The same way as the numpad is modified.
2024-02-28 23:19:50 +01:00
Jules Aguillon
8c7559d8f6 Fix localized numpad outputing wester arabic numbers
The number keys were constructed in the wrong way: the rendered symbol
was correct but not the underlying character that is typed.
2024-02-28 20:42:52 +01:00
Jules Aguillon
d7e5040873 method.xml: Add en-CA and fr-CA
Without this, the system might choose en-GB and fr-CH.
This makes them more similar to en-US and fr-FR (without € in extra keys).
2024-02-24 11:54:46 +01:00
Jules Aguillon
b29a344cd0 Remove € from en-GB extra keys 2024-02-22 19:34:23 +01:00
Jules Aguillon
b8e673b614 Ensure the layout contain the config key
Without the config key, the user risk being locked in a custom layout
that lacks an escape key like 'switch_numpad', 'change_method', etc..
2024-02-22 19:10:31 +01:00
Jules Aguillon
bae82d6ed8 Add FUNDING.yml
Thanks to everyone considering funding the development of the app.
2024-02-21 19:07:34 +01:00
Jules Aguillon
f913051dca
Relicense layout definitions under CC0 (#528)
* Relicense layouts under CC0

Layout definitions are licensed differently from the rest of the
application source code to allow use in other projects related or
unrelated to Unexpected Keyboard.

Some layouts are not re-licensed and their original copyright continues
to apply. The copyright notice is added at the top of the files.

* Contributing: Mention layout licensing
2024-02-18 23:37:26 +01:00
Jules Aguillon
dac702ad0b
CI: Improve layout and store description checks (#565)
* CI: Run 'check_layout.py'

Ensures that 'check_layout.output' is not outdated.
Also, update it.

* CI: Check new store descriptions

When a store description is added, 'python3 sync_translations.py' leaves
an untracked file that is not checked.

This makes sure that untracked store descriptions are noticed in CI.
2024-02-18 17:55:41 +01:00
matthiakl
f2f6ef0627
neo2: Update bottom row (#560) 2024-02-18 17:10:46 +01:00
Sergiy Stupar
6389d58553
Update Ukrainian translation (#561) 2024-02-18 17:08:56 +01:00
Jules Aguillon
e40558677e Allow to remove the compose key in the settings 2024-02-17 23:28:31 +01:00
Jules Aguillon
ae270b36f4 Add the compose key on alternate layouts
Though it is not useful in the greek-math layout, it could give ideas
for new sequences.
2024-02-17 23:28:31 +01:00
Jules Aguillon
146d520325 compose: Grey out keys that are not in sequence
Keys that are not in the pending compose sequence are greyed out with
the new 'FLAG_GREYED' flag.
2024-02-17 23:28:31 +01:00
Jules Aguillon
065d9520e5 Dim secondary keys in every themes
Themes do not dim secondary keys the same way due to the "offset"
mechanism. Instead, use a ratio that is the same for every themes.

It's still possible to override this ratio per theme.
2024-02-17 23:28:31 +01:00
Jules Aguillon
bb60ed9b13 Fix KeyValue flags layout
The kind field wasn't large enough to hold the new Compose_pending kind.
The flags field is reduced in size by removing a free spot.

The FLAGS_BITS mask is defined in a safer way.
2024-02-17 23:28:31 +01:00
Jules Aguillon
d56e4d129e compose: Add glyph 2024-02-17 23:28:31 +01:00
Jules Aguillon
e9f734b6cc compose: Don't remove keys not in sequence
Keys that are not part of any possible sequences are now dimmed and
still usable instead of being removed, which felt weird.
2024-02-17 23:28:31 +01:00
Jules Aguillon
63e7ac2e94 compose: Add X11 compose sequences
compile.py implements a parser for X11's Compose.pre files. A lot of
code is necessary to interpret character names but thanksfully, the name
of most characters is contained in the file.

The state machine is compiled into two char arrays which unfortunately
requires an expensive initialisation and allocation.
2024-02-17 23:28:31 +01:00
Jules Aguillon
8c29073260 Compose key
The COMPOSE_PENDING modifier indicate whether a compose sequence is in
progress. The new key of kind Compose_pending sets the current state of
the sequence.

The compose sequences are compiled into a state machine by a python
script into a compact encoding.

The state of the pending compose is determined by the index of a state.
2024-02-17 23:28:31 +01:00
Ryan Gibb
38deb810f9
Add QWERTY GB layout (#557)
Adapted from latn_qwerty_us

* Make it the default layout for en-GB
2024-02-16 21:09:28 +01:00
vedamanavi
d8beda411d
Improve latn_qwerty_tly.xml (#549)
Removing "g" as it was used two times as a main key.
shift="0.5" added
2024-02-14 22:55:56 +01:00
Jules Aguillon
d96577963e Don't invert the pin entry layout
The pin entry layout shouldn't be inverted as the letter indications
would be meaningless and the order would be opposite to what the option
specifies.

The enter and action key are swapped as the automatic swapping is also
removed.
2024-02-14 22:52:25 +01:00
BogdanLata
f369b5d90b
Update README.md (#553)
I made more clearer how to use the keys
2024-02-11 20:54:35 +01:00
Jules Aguillon
f4d88cc087 Fix various linter warnings
Among others:
- Use `apply` instead of `commit` when saving shared preferences.
- Avoid inlined Api
- Remove unused resources
2024-02-10 18:10:49 +01:00
Jules Aguillon
d5676d683f Fix compatibility with Android 3.0
Incompatible APIs were used in the custom layouts and the extra keys
options.

Add @TargetApi annotations to help catch similar issues in the future
with the help of 'gradle lint'.
2024-02-10 17:33:42 +01:00
Jules Aguillon
332413ed3c Drop support for Android versions below 3.0
Android 3.0 (API level 11) was released in Feb 2011.

These versions were already unsupported due to unavoidable calls to:
- MotionEvent.getActionMasked() (API 8)

And avoidable calls to:
- SharedPreferences.Editor.putStringSet() (API 11)
2024-02-10 17:24:15 +01:00
RetrogisusDEV
93d8af4505
Custom border settings (#524) 2024-02-10 11:38:46 +01:00
Mehmet Ali
f74e5a9f73
Update Turkish translations (#550) 2024-02-10 00:43:34 +01:00
ErrrorMaxx
6513c21144
contributing: Fix typo (#551) 2024-02-10 00:42:35 +01:00
Rapha
79aec5b9bc
CI: Update to node.js-20 (#546) 2024-02-07 00:01:54 +01:00
Jules Aguillon
be053b082c Add more Russian vowels combined with acute accent 2024-02-06 23:32:58 +01:00
Jules Aguillon
5ce89d1b4b Move store descriptions into strings files
This makes translation easier as there's a single file to edit at.
Existing short and full descriptions are conserved.

sync_translations.py takes care of updating the metadata files.

The metadata directories are renamed to match the language codes used in `res/`.

Contributing guidelines are updated accordingly.
2024-02-06 23:11:14 +01:00
vedamanavi
82a9774f5a
Update method.xml to support arab_hamvaj_tly (#547) 2024-02-06 22:24:43 +01:00
Jules Aguillon
5d1a503210 Release 1.26.0 (38) 2024-02-04 23:24:34 +01:00
vedamanavi
d1aa59768d
Create layout arabic-hamvaj-tly (#542) 2024-02-04 23:18:33 +01:00
Jules Aguillon
2c52e94e0b Workaround cursor slider bug in Acode
Moving the cursor with setSelection has no effect on Acode, for which
the fallback must be used.
2024-02-04 00:29:07 +01:00
vedamanavi
3adf95a4c9
Add language support for Talysh New Latin (#534) 2024-01-31 01:06:47 +01:00
vedamanavi
44f39059e4
Add layout QWERTY (Talysh New Latin) (#529) 2024-01-28 23:49:27 +01:00
Jules Aguillon
bbc6226839 Redefined the key margin options in percent
Define the key margin options relative to the baseline dimensions of
keys. This removes the doubling of the horizontal margin in landscape
mode.
2024-01-28 19:38:29 +01:00
Jules Aguillon
c5f2c0b727 Send down event for modifiers on time
This allows to use modifiers in combination with other inputs like a
mouse click, for example under termux-x11.

The key down event and notification about modifiers changing are sent
down to KeyEventHandler. A mutable state remember for which modifier
down events have been sent.

When pressing down a modifier with one finger and typing with the
other, it might appear that the modifier is released after the first
time an other key is pressed and then pressed and released for the
following keys.
This prevents unintentionally type two modified keys instead of one
when the second key is pressed while the other is not yet released.
2024-01-26 00:17:51 +01:00
Jules Aguillon
fb27f8d36f check_layout: Warn against whitespaces and "loc" 2024-01-22 20:55:36 +01:00
Jules Aguillon
5beacf32b7 Add Russian vowels combined with the acute accent 2024-01-21 19:47:03 +01:00
Jules Aguillon
ad7314a016 Move layout definitions into srcs/layouts
This separates the layout definitions from the special layouts
(bottom_row, greekmath) and other unrelated files (method, settings).

This is also a more intuitive location for layouts and make the resource
directory easier to navigate.

Under the hood, layouts are copied back into
build/generated-resources/xml.
2024-01-21 16:34:49 +01:00
marciozomb13
bef29da3de
Update pt-br translation (#527)
Update translation pt-br
2024-01-21 16:10:26 +01:00
RetrogisusDEV
a55506e607 Light and dark themes for the launcher and settings 2024-01-20 22:37:51 +01:00
abb128
b3dcd61c28
Add <queries> element for detecting IMEs (#526)
To detect voice IMEs, Unexpected Keyboard calls InputMethodManager.getEnabledInputMethodList

Internally, this method eventually calls a method that returns a filtered list of packages that may not include the installed voice IME, and thus Unexpected Keyboard unexpectedly claims no voice input is installed because it can't see it.

The fix is to explicitly state in the manifest that we want to query for other IMEs, based on https://developer.android.com/training/package-visibility/declaring

This is not an issue with Google's voice input or other preinstalled voice inputs because they usually have android:forceQueryable=true, but this is an issue with third-party voice inputs such as FUTO Voice Input. Launching the voice input app after activating the keyboard also usually makes the package visible, so a consistent way to replicate this issue on modern Android is to reboot the device and try triggering voice input from the keyboard
2024-01-18 23:42:29 +01:00
Sergiy Stupar
9257bf7392
Add Ukrainian translation (#525) 2024-01-18 22:44:22 +01:00
Jules Aguillon
95bd9312a7 Allow hidding the keyboard switching key
The keyboard switching key is now selected by default in the Extra Keys
option and can be deselected.
2024-01-15 23:26:40 +01:00
Jules Aguillon
0a86f9ab01 Always show the keyboard switching key
Android's shouldOfferSwitchingToNextInputMethod() method might return
false when an other IME is installed, perhaps when the other IME doesn't
specify android:supportsSwitchingToNextInputMethod="true".
2024-01-15 23:15:16 +01:00
Jules Aguillon
70d777253c Use switchToNextInputMethod instead of switchToPreviousInputMethod
This is warranted by the API.
2024-01-15 22:10:11 +01:00
Jules Aguillon
d7fa5ffa9a Refactor: Clearer names for CHANGE_METHOD* events
The keys are not renamed to retain compatibility.
2024-01-15 22:09:15 +01:00
Jules Aguillon
b114c78bf1 Refactor: Keyboard2View: Take layout id attr
Removes EmojiBottomRow.
2024-01-13 23:22:26 +01:00
Jules Aguillon
eddf9c6c11 Refactor: New namespace for preference classes 2024-01-13 20:59:05 +01:00
Jules Aguillon
148f3dfc05 prefs: Show custom layout names if provided
Show the name of custom layouts in the list if it's provided using the
`name` attribute.
This should make managing several custom layouts easier.
2024-01-10 23:39:19 +01:00
Jules Aguillon
6725d3057b check_layout: Stronger bottom row key check 2024-01-10 23:00:40 +01:00
Jules Aguillon
cf9fd3a0db CI: Fix debug build due to missing release keystore 2024-01-10 00:34:19 +01:00
Jules Aguillon
329a35e7d3 Fix layouts containing empty keys
This results in a key being the empty string and do not trigger an
error:

    key1="\"

Layouts are fixed and check_layout now checks for this case.
2024-01-10 00:28:21 +01:00
Jules Aguillon
b319356a08 Fix crash on shift with empty keys
Tapping shift might call `Utils.capitalize_string` on some symbols
(notably custom keys), which crashes on empty string.

This also happens on builtin layouts with `key1="\"`.
2024-01-10 00:17:09 +01:00
Jules Aguillon
73267d68fb Revert "Remove the vibration settings"
This reverts commits ef03dfed5c and
ff01678ba6.

The "vibration duration" slider is bought back.
The "vibration enabled" option is replaced by "custom vibration", which switch between the system haptic feedback or the custom vibration.

The slider is greyed when "custom vibration" is unchecked and is
allowed to have a value of 0 to disable vibrations within the app.

The intermediate values "light", "medium" and "strong" are removed and
no migration of the setting is made.
2024-01-09 00:43:28 +01:00
Jules Aguillon
3f2f3177da gradle: Enforce release build is signed 2024-01-08 22:49:59 +01:00
Jules Aguillon
e26e1d112c gradle: Name outputs after the application ID 2024-01-08 22:47:21 +01:00
Diego Puma
0005eb2dd5
Update Spanish translations (#517) 2024-01-07 02:18:40 +01:00
Jules Aguillon
8b2c7d9337 Release 1.25.0 (37) 2024-01-03 01:07:22 +01:00
Jules Aguillon
409362ddb4 launcher: Remove intro video when not supported
Previously, this would trigger an error popup and make the activity
unresponsive.
2024-01-03 00:48:26 +01:00
Jules Aguillon
c524caa6f1 Remove unsupported API readAllBytes 2024-01-01 21:04:54 +01:00
Jules Aguillon
7caf60c93b
README: Display the intro video 2023-12-31 20:19:58 +01:00
Jules Aguillon
49a6a30773 Add an introduction video in the launcher activity
A video is more intuitive than a written description and doesn't need
translations.
2023-12-31 13:18:15 +01:00
Jules Aguillon
4a5a125aea Bring the voice IME chooser with a long press 2023-12-30 01:24:21 +01:00
Jules Aguillon
51a41ec90a Voice IME chooser popup
Bring a popup for choosing the voice IME when the voice key is pressed
for the first time or the list of voice IMEs installed on the device
change.

A preference stores the last selected IME and the last seen list of
IMEs.
2023-12-30 00:56:55 +01:00
Jules Aguillon
7e7a5e4425 Separate arabic layouts with hindu or arabic numerals
This reverts the Tusinian layout (1af4e45) and instead introduce a new
arabic PC layout with arabic numbers.

Layouts are renamed:
- arab_pc => arab_pc_hindu
- arab_pc_tn => arab_pc
2023-12-26 17:16:29 +01:00
Jules Aguillon
9ff8179d49 Add layout attribute 'numpad_script'
This new attribute is now used instead of 'script' for modifying the
numpad according to the selected layout's script.
If not provided, it defaults to the value of 'script'.
2023-12-26 17:05:51 +01:00
Jules Aguillon
1af4e45117 Add Tunisian layout
It is a copy of the 'arab_pc' layout with arabic digits.
Also, fix the default layout for arabic.
2023-12-21 21:45:56 +01:00
Jules Aguillon
2db4ae3730 Fix the number row showing up on top of pinentry
This wasn't intended and was caused by the "current_layout_unmodified"
optimisation.
2023-12-21 20:59:30 +01:00
polyctena
2aecbca9ac
Update strings.xml (#505) 2023-12-20 21:27:19 +01:00
Validbit
dce7e2b9d9
Update strings.xml (cz_CS) (#506) 2023-12-20 21:26:46 +01:00
1
7c12aa610c
Update Turkish translations (#501)
Turkish translate update
2023-12-18 19:38:06 +01:00
Chasm Solacer
294ebee6f1
Update Polish translations (#502) 2023-12-18 19:35:56 +01:00
Edgars
bd1afd2c3c
Update Latvian translations (#503) 2023-12-18 19:34:15 +01:00
Jules Aguillon
44f6908411 Update French translation 2023-12-17 20:25:43 +01:00
RetrogisusDEV
df04eae85f Launcher activity: Add "Select keyboard" button 2023-12-17 20:10:39 +01:00
Jules Aguillon
d7c230e173 prefs: Use QWERTY (US) as the default custom layout
This layout definition contains some documentation and is a better
default than no text.
2023-12-17 12:41:19 +01:00
Jules Aguillon
478d8082f4 Improve layout parsing errors
Add location information to all error and improve "expected tag" errors.
2023-12-17 12:12:23 +01:00
Jules Aguillon
7af6adcf11 prefs: Report errors while editing custom layouts
Errors are obtained by running the parser, validation is throttle to
when the user stops editing for a second.
2023-12-17 11:58:41 +01:00
Jules Aguillon
dd327cc812 prefs: Render line numbers in custom layout input box
Line numbers will help reporting errors. Also, disable line breaking to
improve readability.
2023-12-10 19:44:50 +01:00
Jules Aguillon
d073523125 shell.nix: Update dependencies and add Gradle
Update OpenJDK to version 17, Android build tools to 33.0.1 and platform to 33.
These are required to build with Gradle.

Add Gradle to the environment, which must be wrapped to fix a
permissions issue. Setting `GRADLE_OPTS` has no effect as it seems not
to be passed down to the daemon.
2023-11-25 20:13:24 +01:00
deftkHD
684d5c7b70
Use Gradle (#452) 2023-11-25 20:11:12 +01:00
deftk
851d22da6e Make check_layout.py independent from dir structure 2023-11-25 19:08:24 +01:00
Jules Aguillon
44adb55544 Separately persisted current layout in landscape mode
Remember the selected layout in portrait and landscape mode
independently.
This allows to define a layout specific to landscape without having to
switch manually.
2023-11-19 20:10:45 +01:00
Jules Aguillon
15de829138 Persist current selected layout 2023-11-19 19:07:54 +01:00
Jules Aguillon
c57d896d8d Update translations
Was missing from the previous commit.
2023-11-19 12:03:39 +01:00
RetrogisusDEV
80c6f97767 Add Desert and Jungle themes 2023-11-19 11:33:39 +01:00
Diego Puma
b0cf9a52b5
Update Spanish translations (#489) 2023-11-13 00:06:43 +01:00
Jules Aguillon
f696452c59 method.xml: Add Armenian 2023-11-13 00:04:31 +01:00
Jules Aguillon
70500ba6f8 Update check_layout.output 2023-11-13 00:03:45 +01:00
Rafael Grigorian
474c693427
Add Armenian layout (#490) 2023-11-13 00:00:25 +01:00
RetrogisusDEV
73060bfc00 Adaptive launcher icon
Existing icons are kept for API < 26.
2023-11-06 20:52:35 +01:00
Reza Hosseinzadeh
60134effdc
Remove extra paranthesis in persian layout (#485) 2023-11-01 16:30:01 +01:00
1
838fbc8ef8
Update Turkish translation (#486) 2023-10-31 20:57:42 +01:00
Jules Aguillon
148bed769a Add left/right slider to the emoji pane
This entirely changes the implementation of the bottom row in the emoji
pane.
2023-10-28 20:14:32 +02:00
deftk
3d36ecb34d Make special font glyphs pass linting 2023-10-28 18:48:25 +02:00
Jules Aguillon
2d164ca64f Add '₽' to Russian layout and to the Fn layer
Other currencies are moved on the Fn layer for consistency with the
compose key.
2023-10-21 11:56:56 +02:00
matthiakl
d594242a53
Update the neo2 layout (#477) 2023-10-20 21:06:21 +02:00
Lyubomir Vasilev
bd886a24eb
Add Bulgarian BDS layout (#479) 2023-10-20 14:21:14 +02:00
Luke Videckis
7b7202ec1b
Add * and @ to Hindi layout (#480) 2023-10-20 12:59:19 +02:00
Jules Aguillon
33653a94cb Add page_up, page_down, home, end to extra keys
The new keys are placed on the corner of the arrow keys. Key
descriptions are added.

They are removed from the Fn layer to avoid showing up twice.
2023-10-20 12:20:25 +02:00
Ojas Bhagavath
5b4345088d
Use standard Greek layout in greekmath.xml (#474) 2023-09-24 16:59:47 +02:00
Jules Aguillon
d5cbcb37e3 Preferred position for locale extra_keys
`method.xml` is now able to specify a preferred position for each extra
keys in term of an other key to which it should be placed nearby.

It's implemented for French as an example.
2023-09-24 16:35:24 +02:00
Jules Aguillon
66b1bdc9c9 Refactor: Preferred positions for extra keys
The new PreferredPos class represents where an extra key should be
placed
Currently used to place keys at the same positions they were placed
before.
2023-09-15 18:00:27 +02:00
Jules Aguillon
d771e9d2c7 Refactor: Compute key positions in layouts
`KeyboardData.getKeys()` now returns a map of the keys present on the
layout to their position. Positions are the row, column and swipe
direction.

The computed map is cached in the KeyboardData object as it might be
accessed later by `findKeyWithValue`, which now do less work.
2023-09-10 11:43:56 +02:00
Jules Aguillon
44e2e86f19 Capitalize the first letter of custom keys
This is more useful than turning the entire string full caps.
2023-09-09 14:32:03 +02:00
Jules Aguillon
92a8db5e93 Update auto-capitalisation state when input starts
The initial capitalisation state given by the editor
(`info.initialCapsMode`) is always 0 in many editors.

For some text input types, update the state when typing starts,
disregarding the value given by `info.initialCapsMode`.
2023-09-09 14:15:44 +02:00
Jules Aguillon
687d88f4f7 Per-script numpad
The numeric layout and the optional right hand side numpad are modified
to show the digits belonging to the script used in the current layout.

The numpads are still defined as it was before. The digits are changed
in `modify_numpad` if needed.
2023-09-03 23:38:55 +02:00
Jules Aguillon
b079e5cf43 Consistent layout for optional numpad
Modify the optional right hand numpad the same way as the numeric
layout.
2023-09-03 23:36:49 +02:00
Jules Aguillon
86038ef512 check_layout.py: Deterministic output order 2023-09-03 20:15:31 +02:00
Jules Aguillon
816269aed0 Remove unused editing keys from the settings
These keys don't seem to have a purpose, which is confusing.
2023-09-03 15:05:23 +02:00
Ben Slusky
234986817f
Change Greek math koppa to lowercase (#457)
Uppercase koppa can still be entered as shift+koppa.
2023-08-30 09:33:36 +02:00
pharook
f4a995e2bd
Add Czech QWERTY layout (#455) 2023-08-28 19:16:39 +02:00
Jules Aguillon
f07fbaff3b CONTRIBUTING: Fix typos 2023-08-27 17:44:13 +02:00
Jules Aguillon
3530263083 CONTRIBUTING: Improve translation guidelines 2023-08-27 17:39:04 +02:00
Jules Aguillon
9b917e79b1 Fix regression on Ctrl on space bar slider
This makes Ctrl+move_cursor the same as before 5123ce5.
2023-08-26 23:44:41 +02:00
Jules Aguillon
f4c11d99ed Disable automatically Shift when pressing Ctrl
Automatic capitalisation might interferes with keyboard shortcuts.
2023-08-26 23:37:22 +02:00
Jules Aguillon
cf76118548 Add missing combining accents
Implement the combinations that were previously not possible and were
commented out.

Also remove `apply_dead_char` and `apply_combining` and make all
dead-keys definitions uniform.
2023-08-20 01:03:14 +02:00
Jules Aguillon
40498e7b4c Refactor: Allow combining diacritics modifiers
Change the API of `KeyModifier.Map_char` to allow returning a string
instead of a single 16 bits char.

This allows to return combining diacritics.

This also gets rid of `apply_map_or_dead_char`, maps can have their own
fallback.
2023-08-20 00:44:22 +02:00
Jules Aguillon
cd5ca56226 Release 1.24.0 (36) 2023-08-18 12:29:17 +02:00
Shareef101
491e72f247
Add urdu phonetic layout (#413) 2023-08-18 12:20:41 +02:00
Dimethylebutane
c3a5dc63f2
Added french bépo layout (adapted) (#402) 2023-08-18 12:15:43 +02:00
Eluc
6cb6f2541b
Add Bitcoin symbol to Fn+b (#434) 2023-08-18 12:14:20 +02:00
Jules Aguillon
5123ce5417 Fix slider movements changing input focus
The slider was repeatedly sending arrow keys, which change the focused
input when the end of a text box is hit.

A new key is added that implements cursor movements using the
`InputConnection` API.
The new keys are defined as `KeyValue.Editing`, which are no longer only
context menu actions.

The behavior when a selection has started is changed. The selection is
modified instead of cleared even when shift isn't pressed or the
selection would become empty.

Fallbacks to sending arrow keys for editors that do not support the API,
like Termux.
2023-08-17 12:47:44 +02:00
Jules Aguillon
2dc0ce066d Fix inconsistent initial spacing between keys
Settings defined with `get_dip_pref` had a wrong default value on first
launch.

The "right" default value was used after the shared preferences are
populated.
2023-08-16 18:25:20 +02:00
Eluc
ab05d8314b
Create latn_qwertz_fr_CH.xml (#390)
Adapted from qwertz DE to match qwertz fr_CH layout.

Added all missing characters with accents needed in French while leaving the most common Swiss German characters as it is on the Swiss layout PC keyboard.
Re-organized some special characters to be in a similar position than the PC layout.

* Add locale fr-CH
2023-08-16 16:14:38 +02:00
Validbit
405e63d5c2
Move voice input key (#433)
Move the voice input key to the top-left corner of the return key to reduce accidentally entering voice input, which is disrupting.
2023-08-16 12:27:00 +02:00
Jules Aguillon
5822f98bbb Migrate layouts preferences
The new `layouts` preference replaces three previous preferences:

    layout
    second_layout
    custom_layout

Add a preference migration function, which first migration is to
migrate layouts into the new preference.

The migration must also be called from the SettingsActivity as it might
use a different preference store due to the boot-aware preference copy.
2023-08-16 12:21:40 +02:00
Jules Aguillon
613aa283bd LayoutsPreference: Remove cross button for custom layouts
Remove the cross button on the right of custom layouts to reduce
accidental removal.
A remove button is added in the dialog for modifying the layout.
2023-08-16 12:21:38 +02:00
Jules Aguillon
ddceb69d4e LayoutsPreference: Modify custom layout
Clicking on a custom layout opens a dialog for modifying the layout
description instead of the dialog for selecting a layout.
2023-08-16 12:21:25 +02:00
Jules Aguillon
4584e8289b Remove unused class LayoutListPreference
This class is not used since the introduction of [LayoutsPreference].
2023-08-16 12:21:25 +02:00
Jules Aguillon
febc23776f ListGroupPreference: Fix change items
[Preference.onClick] is apparently not called on [Item]s, though it is
on [AddButton].

Workaround this by listening on click events on the view.
2023-08-16 12:21:25 +02:00
Jules Aguillon
500f4e41d3 Allow multiple custom layouts
This merges the "Layouts" option with the "Custom layout" option.
A custom layout becomes an item in the "Layouts" list among the other
layouts. It's possible to add several custom layouts.

Selecting the "Custom layout" item in the list opens a second dialog for
entering the layout description.

Layouts are serialized as JSON object and are decoded solely in the
LayoutsPreference class.
2023-08-16 12:21:23 +02:00
Jules Aguillon
8611dbcfa0 CustomExtraKeysPreference: Reusable edit text layout
This layout is generically used by CustomExtraKeysPreference and
LayoutsPreference.
2023-08-16 12:20:40 +02:00
Jules Aguillon
03f2b8df70 ListGroupPreference.Serializer: Allow exceptions
(De)serializing might raise exceptions, which are handled by dropping
the failing item.
2023-08-16 12:20:40 +02:00
Jules Aguillon
0269cd65ea ListGroupPreference: Make items abstract
Allow items to be of any class instead of strings.

Item serialization and deserialization methods are in a separate class
because they are also used in a static context.
2023-08-16 12:20:40 +02:00
polyctena
20ab3915e8
Update German Strings (#430)
Co-authored-by: Benjamin <f.weiss@stud.uni-goettingen.de>
2023-08-15 20:18:35 +02:00
374 changed files with 23182 additions and 5825 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
srcs/juloo.keyboard2/ComposeKeyData.java -diff

View File

@ -1,19 +1,26 @@
name: Check layouts
# Runs 'gen_layouts.py' and checks that the generated file were uptodate.
# This doesn't run 'check_layout.py'.
on:
workflow_dispatch:
push:
pull_request:
jobs:
check-layouts:
gen-layouts:
name: Generated files
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- run: python3 gen_layouts.py
- name: Check that the generated layouts.xml is uptodate, run python3 gen_layouts.py otherwise
- name: "Check that the generated 'layouts.xml' is uptodate, otherwise run 'python3 gen_layouts.py'"
run: git diff --exit-code
check-layouts:
name: check_layout.output
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- run: python3 check_layout.py
- name: "Check that the generated 'check_layout.output' is uptodate, otherwise run 'python3 check_layout.py'"
run: git diff --exit-code

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- run: python3 sync_translations.py
- name: Check that strings files are uptodate, run python3 sync_translations.py otherwise
run: git diff --exit-code
- name: "Check that strings files are uptodate, otherwise run 'python3 sync_translations.py'"
run: git add -N . && git diff --exit-code

View File

@ -9,39 +9,41 @@ jobs:
Build-Apk:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'
java-version: '17'
- name: Checkout repo
uses: actions/checkout@v3
- name: Cache debug certificate
uses: actions/cache@v3
with:
path: _build/debug.keystore
key: debug-keystore
- name: Restore debug keystore from github Secrets
uses: actions/checkout@v4
- name: Restore debug keystore from GitHub Secrets
run: |
mkdir -p _build
cd "_build"
# Check if exist and use the secret named DEBUG_KEYSTORE
# The contents of the secret can be obtained -
# from the debug.keystore.asc from you local _build folder
# from the debug.keystore.asc from you local folder
# (refer to CONTRIBUTING.md Using the local debug.keystore on the Github CI actions)
if [[ ! "${{ secrets.DEBUG_KEYSTORE }}" = "" ]]; then
echo "${{ secrets.DEBUG_KEYSTORE }}" > "debug.keystore.asc"
if [[ -s "debug.keystore.asc" ]]; then
echo "Restoring debug keystore from GitHub secrets"
gpg -d --passphrase "debug0" --batch "debug.keystore.asc" > "debug.keystore"
fi
fi
- name: Build
run: make
- name: Build debug APK
uses: gradle/gradle-build-action@v3
env:
DEBUG_KEYSTORE: "debug.keystore"
DEBUG_KEYSTORE_PASSWORD: debug0
DEBUG_KEY_ALIAS: debug
DEBUG_KEY_PASSWORD: debug0
with:
arguments: assembleDebug
- name: Artifact naming
run: |
artifact="${{github.repository_owner}} ${{github.ref_name}}"
artifact="${artifact//\//-}" # replace slashes
echo "artifact=${artifact}" >> $GITHUB_ENV
- name: Save debug apk
uses: actions/upload-artifact@v3
- name: Upload debug APK
uses: actions/upload-artifact@v4
with:
name: "${{env.artifact}} debug_apk"
path: _build/*.apk
path: build/outputs/apk/debug/*.apk

10
.gitignore vendored
View File

@ -1,4 +1,12 @@
*.keystore
*.keystore.asc
_build
/*-keystore.conf
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/captures
/build
# Directory _build is not used anymore
/_build

View File

@ -1,25 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="35" android:versionName="1.23.0" android:hardwareAccelerated="false">
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="33"/>
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:hardwareAccelerated="false">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:hardwareAccelerated="false">
<service android:name="juloo.keyboard2.Keyboard2" android:label="@string/app_name" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true" android:directBootAware="true">
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
</service>
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@drawable/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/android:Theme.DeviceDefault" android:exported="true" android:directBootAware="true">
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/android:Theme.DeviceDefault" android:exported="true" android:directBootAware="true">
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- To query enabled input methods for voice IME detection -->
<queries>
<intent>
<action android:name="android.view.InputMethod" />
</intent>
</queries>
</manifest>

View File

@ -4,52 +4,46 @@ Thanks for contributing :)
## Building the app
The application doesn't use Gradle and it might be hard to use some features of
Android Studio.
Fortunately, there's not many dependencies:
- OpenJDK 8
The application uses Gradle and can be used with Android Studio, but using
Android Studio is not required. The build dependencies are:
- OpenJDK 17
- Android SDK: build tools (minimum `28.0.1`), platform `30`
- Make sure to have the `$ANDROID_HOME` environment variable set.
Python 3 is required to update generated files but not to build the app.
For Android Studio users, no more setup is needed.
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).
Instructions to install Nix are [here](https://wiki.nixos.org/wiki/Nix_Installation_Guide).
If you don't use Android Studio or Nix, you have to inform Gradle about the
location of your Android SDK by either:
- Setting the `ANDROID_HOME` environment variable to point to the android sdk or
- Creating the file `local.properties` and writing
`sdk.dir=<location_of_android_home>` into it.
Building the debug apk:
```sh
make
./gradlew assembleDebug
```
If the build succeed, the debug apk is located in `_build/juloo.keyboard2.debug.apk`.
Nix users can call gradle directly: `gradle assembleDebug`.
## 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`
If the build succeeds, the debug apk is located in `build/outputs/apk/debug/app-debug.apk`.
## Debugging on your phone
First [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb#Enabling).
Then connect your phone to your computer using an USB cable or wireless
Then connect your phone to your computer using an USB cable or via wireless
debugging.
If you use Android Studio, this process will be automatic and you don't have to
follow this guide anymore.
And finally, install the application with:
```sh
make installd
./gradlew installDebug
```
The released version of the application won't be removed, both versions will
@ -57,11 +51,13 @@ be installed at the same time.
## Debugging the application: INSTALL_FAILED_UPDATE_INCOMPATIBLE
`make installd` can fail with the following error message:
`./gradlew installDebug` can fail with the following error message:
```
adb: failed to install _build/juloo.keyboard2.debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package juloo.keyboard2.debug signatures do not match previously installed version; ignoring!]
make: *** [Makefile:20: installd] Error 1
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':installDebug'.
> java.util.concurrent.ExecutionException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package juloo.keyboard2.debug signatures do not match newer version; ignoring!
```
The application can't be "updated" because the temporary certificate has been
@ -70,36 +66,57 @@ The application must be enabled again in the settings.
```sh
adb uninstall juloo.keyboard2.debug
make installd
./gradlew installDebug
```
## Specifying a debug signing certificate on Github Actions
It's possible to specify the signing certificate that the automated build
should use.
After you successfully run `./gradlew asssembleDebug`, (thus a debug.keystore
exists) you can use this second command to generate a base64 stringified
version of it:
```sh
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
```
This will create the file `debug.keystore.asc`, paste its content into a new
Github secret named `DEBUG_KEYSTORE`.
## Guidelines
### Adding a layout
Layouts are defined in XML, see `res/xml/latn_qwerty_us.xml`.
Layouts are defined in XML, see `srcs/layouts/latn_qwerty_us.xml`.
An online tool for editing layout files written by @Lixquid is available
[here](https://unexpected-keyboard-layout-editor.lixquid.com/).
Makes sure to specify the `name` attribute like in `latn_qwerty_us.xml`,
otherwise the layout won't be added to the app.
The layout file must be placed in the `res/xml/` directory and named according to:
The layout file must be placed in the `srcs/layouts` directory and named
according to:
- script (`latn` for latin, etc..)
- layout name (eg. the name of a standard)
- country code (or language code if more adequate)
Then, run `make gen_layouts` to add the layout to the app.
Then, run `./gradlew genLayoutsList` to add the layout to the app.
The last step will update the file `res/values/layouts.xml`, that you should
not edit directly.
Run `make check_layouts` to check some properties about your layout. This will
change the file `check_layout.output`, which you should commit.
Run `./gradlew checkKeyboardLayouts` to check some properties about your
layout. This will change the file `check_layout.output`, which you should
commit.
Layouts are CC0 licensed by default. If you do not want your layout to be
released into the public domain, add a copyright notice at the top of the file
and a mention in `srcs/layouts/LICENSE`.
#### Adding a programming layout
A programming layout must contains every ASCII characters.
A programming layout must contain all ASCII characters.
The current programming layouts are: QWERTY, Dvorak and Colemak.
See for example, Dvorak, added in https://github.com/Julow/Unexpected-Keyboard/pull/16
@ -133,32 +150,52 @@ and other extra keys to show.
The list of language tags (generally two letters)
and locales (generally of the form `xx_XX`)
can be found in this stackoverflow answer: https://stackoverflow.com/a/7989085
can be found in this [stackoverflow answer](https://stackoverflow.com/a/7989085)
### Translations
### Updating translations
Translations are always welcome !
The text used in the app is written in `res/values-<language_tag>/strings.xml`.
See for example: 1723288 (Latvian), baf867a (French).
The app can be translated by writing `res/values-<language code>/strings.xml`
(for example `values-fr`, `values-lv`), based on the default:
`res/values/strings.xml` (English).
The list of language tags can be found in this
[stackoverflow answer](https://stackoverflow.com/a/7989085)
The first part before the `_` is used, for example,
`res/values-fr/strings.xml` for French,
`res/values-lv/strings.xml` for Latvian.
Commented-out lines indicate missing translations:
```xml
<!-- <string name="pref_layouts_add">Add an alternate layout</string> -->
```
Remove the `<!--` and `-->` parts and change the text.
### Adding a translation
The `res/values-<language_tag>/strings.xml` file must be created by copying the
default translation in `res/values/strings.xml`, which contain the structure of
the file and the English strings.
To check that `strings.xml` is formatted correctly, run
`python sync_translations.py`. This will modify your files.
The store description is found in `metadata/android/<locale>/`,
`short_description.txt` and `full_description.txt`.
The short description must not exceed 80 characters.
Store descriptions in `fastlane/metadata/android/` are updated automatically.
Translating changelogs is not useful.
The app name might be partially translated, the "unexpected" word should remain
untranslated.
The app name might be partially translated, the "Unexpected" word should remain
untranslated if possible.
As translations need to be updated regularly, you can subscribe to this issue
to receive a notification when an update is needed:
https://github.com/Julow/Unexpected-Keyboard/issues/373
### Adding Compose key sequences
New Compose sequences can be added into `srcs/compose/compose/extra.json`.
If a entirely new family of sequences were to be added, a new `.json` file can
be created in the same directory to host them.
### Adding key combinations
Key combinations are defined in `srcs/juloo.keyboard2/KeyModifier.java`.

3
FUNDING.yml Normal file
View File

@ -0,0 +1,3 @@
github: [ Julow ]
liberapay: Julow
custom: [ "https://paypal.me/JulesAguillon" ]

139
Makefile
View File

@ -1,139 +0,0 @@
# Configuration
PACKAGE_NAME = juloo.keyboard2
ANDROID_PLATFORM_VERSION = android-30
JAVA_VERSION = 1.7
SRC_DIR = srcs
RES_DIR = res
EXTRA_JARS =
# /
debug: _build/$(PACKAGE_NAME).debug.apk
release: _build/$(PACKAGE_NAME).apk
installd: _build/$(PACKAGE_NAME).debug.apk
adb install -r "$<"
clean:
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
_build/*.idsig _build/assets
rebuild_special_font: _build/special_font.ttf
cp "$<" srcs/special_font/result.ttf
sync_translations:
python sync_translations.py
check_layouts:
python check_layout.py $(wildcard res/xml/*.xml) > check_layout.output
gen_layouts:
python gen_layouts.py
# Will modify the source tree.
runtest: rebuild_special_font sync_translations check_layouts gen_layouts
.PHONY: release debug installd clean rebuild_special_font check_layouts \
sync_translations runtest gen_layouts
$(shell mkdir -p _build)
ifndef ANDROID_HOME
$(error ANDROID_HOME not set)
endif
ANDROID_BUILD_TOOLS = $(lastword $(sort $(wildcard $(ANDROID_HOME)/build-tools/*)))
ANDROID_PLATFORM = $(ANDROID_HOME)/platforms/$(ANDROID_PLATFORM_VERSION)
ifeq ($(shell [ -d "$(ANDROID_PLATFORM)" ] && echo ok),)
$(error Android platform not found. Want $(ANDROID_PLATFORM_VERSION), \
found $(notdir $(wildcard $(ANDROID_HOME)/platforms/*)))
endif
JAVAC_FLAGS = -source $(JAVA_VERSION) -target $(JAVA_VERSION) -encoding utf8
# Source files
MANIFEST_FILE = AndroidManifest.xml
JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java')
RES_FILES = $(shell find $(RES_DIR) -type f)
# Debug signing
DEBUG_KEYSTORE = _build/debug.keystore
DEBUG_PASSWD = debug0
$(DEBUG_KEYSTORE):
echo y | keytool -genkeypair -dname "cn=d, ou=e, o=b, c=ug" \
-alias debug -keypass $(DEBUG_PASSWD) -keystore "$@" \
-keyalg rsa -storepass $(DEBUG_PASSWD) -validity 10000
_build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
--ks $(DEBUG_KEYSTORE) --ks-key-alias debug --ks-pass "pass:$(DEBUG_PASSWD)"
# Debug apk
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug --product debug
# Release signing
# %-keystore.conf should declare KEYSTORE, KEYNAME and KEYSTOREPASS
# it is interpreted as a shell script
_build/%.apk: _build/%.unsigned-apk %-keystore.conf
eval `cat $(word 2,$^)` && \
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
--ks "$$KEYSTORE" --ks-key-alias "$$KEYNAME" --ks-pass "pass:$$KEYSTOREPASS"
# Package
_build/%.unsigned-apk: _build/%.unaligned-apk
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
APK_EXTRA_FILES = classes.dex assets/special_font.ttf
_build/%.unaligned-apk: $(addprefix _build/,$(APK_EXTRA_FILES)) $(MANIFEST_FILE)
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) $(APK_EXTRA_FILES)
# Copy the special font file into _build because aapt requires relative paths
_build/assets/special_font.ttf: srcs/special_font/result.ttf
mkdir -p $(@D)
cp "$<" "$@"
# R.java
GEN_DIR = _build/gen
R_FILE = $(GEN_DIR)/$(subst .,/,$(PACKAGE_NAME))/R.java
$(R_FILE): $(RES_FILES) $(MANIFEST_FILE)
mkdir -p "$(@D)"
$(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(RES_DIR) -J $(GEN_DIR) \
-M $(MANIFEST_FILE) -I $(ANDROID_PLATFORM)/android.jar
# Compile java classes and build classes.dex
OBJ_DIR = _build/class
# A$B.class files are ignored
# CLASS_FILES = $(JAVA_FILES:$(SRC_DIR)/%.java=$(OBJ_DIR)/%.class) \
# $(R_FILE:$(GEN_DIR)/%.java=$(OBJ_DIR)/%.class)
_build/classes.dex: $(JAVA_FILES) $(R_FILE)
mkdir -p $(OBJ_DIR)
javac -d $(OBJ_DIR) $(JAVAC_FLAGS) \
-classpath $(ANDROID_PLATFORM)/android.jar:$(EXTRA_JARS) \
-sourcepath $(SRC_DIR):$(GEN_DIR) \
$^
$(ANDROID_BUILD_TOOLS)/d8 --output $(@D) $(OBJ_DIR)/*/*/* $(subst :, ,$(EXTRA_JARS))
# Font file
FONT_GLYPHS = $(wildcard srcs/special_font/*.svg)
_build/special_font.ttf: srcs/special_font/build.pe $(FONT_GLYPHS)
fontforge -lang=ff -script $< "$@" $(FONT_GLYPHS)

View File

@ -9,9 +9,7 @@
Lightweight and privacy-conscious virtual keyboard for Android.
| <img src="/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Screenshot-1" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot-2"/> | <img src="/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot-3"/> |
| --- | --- | --- |
| <img src="/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
https://github.com/Julow/Unexpected-Keyboard/assets/2310568/28f8f6fe-ac13-46f3-8c5e-d62443e16d0d
The main feature is that you can type more characters by swiping the keys towards the corners.
@ -20,8 +18,14 @@ Now perfect for everyday use.
This application contains no ads, doesn't make any network requests and is Open Source.
Usage: to apply the symbols located in the corners of each key, slide your finger in the direction of the symbols. For example, the Settings are opened by sliding in the left down corner.
| <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Screenshot-1" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot-2"/> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot-3"/> |
| --- | --- | --- |
| <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
## Similar apps
* [Calculator++](https://github.com/Bubu/android-calculatorpp) - Calculator with a similar UX, swipe to corners for advanced math symbols and operators. Works up to Android 13 but maybe unmaintained.
* [Calculator++](https://git.bubu1.eu/Bubu/android-calculatorpp) - Calculator with a similar UX, swipe to corners for advanced math symbols and operators.
## Contributing

BIN
assets/special_font.ttf Normal file

Binary file not shown.

199
build.gradle Normal file
View File

@ -0,0 +1,199 @@
plugins {
id 'com.android.application' version '8.1.1'
}
dependencies {
testImplementation "junit:junit:4.13.2"
}
android {
namespace 'juloo.keyboard2'
compileSdk 34
defaultConfig {
applicationId "juloo.keyboard2"
minSdk 11
targetSdkVersion 35
versionCode 42
versionName "1.29.1"
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['srcs/juloo.keyboard2']
res.srcDirs = ['res', 'build/generated-resources']
assets.srcDirs = ['assets']
}
test {
java.srcDirs = ['test']
}
}
signingConfigs {
// Debug builds will always be signed. If no environment variables are set, a default
// keystore will be initialized by the task initDebugKeystore and used. This keystore
// can be uploaded to GitHub secrets by following instructions in CONTRIBUTING.md
// in order to always receive correctly signed debug APKs from the CI.
debug {
storeFile(System.env.DEBUG_KEYSTORE ? file(System.env.DEBUG_KEYSTORE) : file("debug.keystore"))
storePassword(System.env.DEBUG_KEYSTORE_PASSWORD ? "$System.env.DEBUG_KEYSTORE_PASSWORD" : "debug0")
keyAlias(System.env.DEBUG_KEY_ALIAS ? "$System.env.DEBUG_KEY_ALIAS" : "debug")
keyPassword(System.env.DEBUG_KEY_PASSWORD ? "$System.env.DEBUG_KEY_PASSWORD" : "debug0")
}
release {
if (System.env.RELEASE_KEYSTORE) {
storeFile file(System.env.RELEASE_KEYSTORE)
storePassword "$System.env.RELEASE_KEYSTORE_PASSWORD"
keyAlias "$System.env.RELEASE_KEY_ALIAS"
keyPassword "$System.env.RELEASE_KEY_PASSWORD"
}
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
resValue "string", "app_name", "@string/app_name_release"
signingConfig signingConfigs.release
}
debug {
minifyEnabled false
shrinkResources false
debuggable true
applicationIdSuffix ".debug"
resValue "string", "app_name", "@string/app_name_debug"
resValue "bool", "debug_logs", "true"
signingConfig signingConfigs.debug
}
}
// Name outputs after the application ID.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${applicationId}.apk"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
lintOptions {
// Translation are already checked by 'syncTranslations'
disable 'MissingTranslation'
}
}
tasks.register('buildKeyboardFont') {
println "\nBuilding assets/special_font.ttf"
mkdir "$buildDir"
exec {
workingDir "$projectDir/srcs/special_font"
def svgFiles = workingDir.listFiles().findAll {
it.isFile() && it.name.endsWith(".svg")
}
commandLine("fontforge", "-lang=ff", "-script", "build.pe", "$buildDir/special_font.ttf", *svgFiles)
}
copy {
from "$buildDir/special_font.ttf"
into "assets"
}
}
tasks.register('genEmojis') {
println "\nGenerating res/raw/emojis.txt"
exec {
workingDir = projectDir
commandLine "python", "gen_emoji.py"
}
}
tasks.withType(Test).configureEach {
dependsOn 'genLayoutsList'
dependsOn 'checkKeyboardLayouts'
dependsOn 'syncTranslations'
dependsOn 'compileComposeSequences'
}
tasks.register('genLayoutsList') {
println "\nGenerating res/values/layouts.xml"
exec {
workingDir = projectDir
commandLine "python", "gen_layouts.py"
}
}
tasks.register('checkKeyboardLayouts') {
println "\nChecking layouts"
exec {
def layouts = new File(projectDir, "srcs/layouts").listFiles().findAll {
it.name.endsWith(".xml")
}
workingDir = projectDir
commandLine("python", "check_layout.py", *layouts)
standardOutput = new FileOutputStream("${projectDir}/check_layout.output")
}
}
tasks.register('syncTranslations') {
println "\nUpdating translations"
exec {
workingDir = projectDir
commandLine "python", "sync_translations.py"
}
}
tasks.register('compileComposeSequences') {
def out = "srcs/juloo.keyboard2/ComposeKeyData.java"
println "\nGenerating ${out}"
exec {
def sequences = new File(projectDir, "srcs/compose").listFiles().findAll {
!it.name.endsWith(".py") && !it.name.endsWith(".md")
}
workingDir = projectDir
commandLine("python", "srcs/compose/compile.py", *sequences)
standardOutput = new FileOutputStream("${projectDir}/${out}")
}
}
tasks.named("preBuild") {
dependsOn += "initDebugKeystore"
dependsOn += "copyRawQwertyUS"
dependsOn += "copyLayoutDefinitions"
}
tasks.register('initDebugKeystore') {
if (!file("debug.keystore").exists()) {
println "Initializing default debug keystore"
exec {
// A shell script might be needed if this line requires input from the user
commandLine "keytool", "-genkeypair", "-dname", "cn=d, ou=e, o=b, c=ug", "-alias", "debug", "-keypass", "debug0", "-keystore", "debug.keystore", "-keyalg", "rsa", "-storepass", "debug0", "-validity", "10000"
}
}
}
// latn_qwerty_us is used as a raw resource by the custom layout option.
tasks.register('copyRawQwertyUS')
{
copy {
from "srcs/layouts/latn_qwerty_us.xml"
into "build/generated-resources/raw"
}
}
tasks.register('copyLayoutDefinitions')
{
copy {
from "srcs/layouts"
include "*.xml"
into "build/generated-resources/xml"
}
}

View File

@ -1,107 +1,148 @@
# res/xml/arab_alt.xml
# arab_alt
Layout includes some ASCII punctuation but not all, missing: !, ", ', +, -, /, :, ;, <, =, >, ?, [, \, ], _, |, ~
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
2 warnings
# res/xml/arab_pc_ckb.xml
Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ., :, ;, <, =, >, ?, `, |, ~
1 warnings
# res/xml/arab_pc_ir.xml
Duplicate keys: (, )
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, }
# arab_hamvaj_tly
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], _, `, {, |, }
Layout doesn't define some important keys, missing: loc esc
2 warnings
# res/xml/arab_pc.xml
# arab_pc
Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
1 warnings
# res/xml/beng_national.xml
# arab_pc_ckb
Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ., :, ;, <, =, >, ?, `, |, ~
1 warnings
# arab_pc_hindu
Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
1 warnings
# arab_pc_ir
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, }
1 warnings
# armenian_ph_am
0 warnings
# beng_national
Layout includes some ASCII punctuation but not all, missing: $
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
Layout doesn't specify a script.
3 warnings
# res/xml/beng_provat.xml
1 warnings
# beng_provat
Layout includes some ASCII punctuation but not all, missing: $, &, *, ., /, <, >, [, \, ], `, {, |, }
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
Layout doesn't specify a script.
3 warnings
# res/xml/cyrl_jcuken_ru.xml
1 warnings
# cyrl_jcuken_ru
0 warnings
# res/xml/cyrl_jcuken_uk.xml
# cyrl_jcuken_uk
0 warnings
# res/xml/cyrl_yaverti.xml
# cyrl_lynyertz_sr
0 warnings
# cyrl_ueishsht
0 warnings
# cyrl_yaverti
Layout includes some ASCII punctuation but not all, missing: ~
1 warnings
# res/xml/deva_alt.xml
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), *, +, ., /, :, <, =, >, @, [, \, ], ^, _, `, {, |, }, ~
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
# cyrl_yqukeng_tj
Layout doesn't define some important keys, missing: loc esc, loc tab
These keys are now added automatically, unexpected: f11_placeholder, f12_placeholder
2 warnings
# res/xml/deva_inscript.xml
Duplicate keys: , ।
Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, |
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
# cyrl_yxukeng_os
Layout includes some ASCII punctuation but not all, missing: ", #, $, &, ', @, [, ], ~
Layout doesn't define some important keys, missing: loc esc, loc tab
These keys are now added automatically, unexpected: f11_placeholder, f12_placeholder
3 warnings
# res/xml/grek_qwerty.xml
# deva_alt
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), +, ., /, :, <, =, >, [, \, ], ^, _, `, {, |, }, ~
Layout doesn't define some important keys, missing: loc esc, loc tab
2 warnings
# deva_inscript
Duplicate keys: ।
Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, |
2 warnings
# grek_qwerty
Duplicate keys: ;
1 warnings
# res/xml/hang_dubeolsik_kr.xml
0 warnings
# res/xml/hebr_1_il.xml
# guj_phonetic_in
Duplicate keys: ટ, ડ
1 warnings
# hang_dubeolsik_kr
Layout doesn't define some important keys, missing: loc esc, loc tab
1 warnings
# hebr_1_il
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# res/xml/hebr_2_il.xml
# hebr_2_il
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# res/xml/latn_azerty_fr.xml
# latn_azerty_fr
0 warnings
# res/xml/latn_bone.xml
Layout includes some ASCII punctuation but not all, missing: $
Layout redefines the bottom row but some important keys are missing, missing: switch_backward
# latn_bepo_fr
0 warnings
# latn_bone
Layout doesn't define some important keys, missing: loc esc, loc tab
Layout redefines the bottom row but some important keys are missing, missing: cursor_left, cursor_right, loc compose, loc end, loc home, loc page_down, loc page_up, loc switch_clipboard, loc switch_greekmath, loc voice_typing, switch_backward
2 warnings
# res/xml/latn_colemak.xml
# latn_colemak
Some keys contain whitespaces, unexpected: ́
1 warnings
# latn_dvorak
0 warnings
# res/xml/latn_dvorak.xml
# latn_neo2
Layout redefines the bottom row but some important keys are missing, missing: loc switch_clipboard
1 warnings
# latn_qwerty_br
0 warnings
# res/xml/latn_neo2.xml
Duplicate keys: -
Layout redefines the bottom row but some important keys are missing, missing: switch_forward
2 warnings
# res/xml/latn_qwerty_br.xml
# latn_qwerty_cz
0 warnings
# res/xml/latn_qwerty_es.xml
# latn_qwerty_da
0 warnings
# res/xml/latn_qwerty_hu.xml
# latn_qwerty_es
0 warnings
# res/xml/latn_qwerty_lv.xml
# latn_qwerty_gb
0 warnings
# res/xml/latn_qwerty_no.xml
# latn_qwerty_hu
0 warnings
# res/xml/latn_qwerty_pl.xml
# latn_qwerty_jp
0 warnings
# res/xml/latn_qwerty_ro.xml
# latn_qwerty_lv
0 warnings
# res/xml/latn_qwerty_se.xml
# latn_qwerty_no
0 warnings
# latn_qwerty_pl
0 warnings
# latn_qwerty_ro
0 warnings
# latn_qwerty_se
Duplicate keys: !, ', ,, -, ., ?
1 warnings
# res/xml/latn_qwerty_tr.xml
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
1 warnings
# res/xml/latn_qwerty_us.xml
# latn_qwerty_sk
0 warnings
# res/xml/latn_qwerty_vi.xml
Layout includes some ASCII punctuation but not all, missing: \
1 warnings
# res/xml/latn_qwertz_cz_multifunctional.xml
# latn_qwerty_sr
0 warnings
# latn_qwerty_tly
Duplicate keys: a, c, j, q
Layout doesn't define some important keys, missing: loc esc, loc tab
2 warnings
# latn_qwerty_tr
0 warnings
# latn_qwerty_us
0 warnings
# latn_qwerty_vi
0 warnings
# latn_qwertz
0 warnings
# latn_qwertz_cz
0 warnings
# latn_qwertz_cz_multifunctional
Layout includes some ASCII punctuation but not all, missing: `
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
2 warnings
# res/xml/latn_qwertz_cz.xml
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
1 warnings
# res/xml/latn_qwertz_de.xml
# latn_qwertz_de
0 warnings
# res/xml/latn_qwertz_hu.xml
# latn_qwertz_fr_ch
0 warnings
# res/xml/latn_qwertz_sk.xml
Layout includes some ASCII punctuation but not all, missing: \, `
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
2 warnings
# res/xml/latn_qwertz.xml
# latn_qwertz_hu
0 warnings
# latn_qwertz_sk
Layout includes some ASCII punctuation but not all, missing: `
1 warnings
# shaw_imperial_en
0 warnings
# urdu_phonetic_ur
Duplicate keys:
Layout includes some ASCII punctuation but not all, missing: <, >, ?, `, |, ~
Some keys contain whitespaces, unexpected:
3 warnings

View File

@ -1,12 +1,19 @@
import xml.etree.ElementTree as ET
import sys
import sys, os
warning_count = 0
KNOWN_NOT_LAYOUT = set([
"res/xml/number_row.xml", "res/xml/numpad.xml", "res/xml/pin.xml",
"res/xml/bottom_row.xml", "res/xml/settings.xml", "res/xml/method.xml",
"res/xml/greekmath.xml", "res/xml/numeric.xml" ])
"number_row", "numpad", "pin",
"bottom_row", "settings", "method",
"greekmath", "numeric", "emoji_bottom_row",
"clipboard_bottom_row" ])
KEY_ATTRIBUTES = set([
"key0",
"key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8",
"nw", "ne", "sw", "se", "w", "e", "n", "s"
])
def warn(msg):
global warning_count
@ -34,6 +41,15 @@ def unexpected_keys(keys, symbols, msg):
if len(unexpected) > 0:
warn("%s, unexpected: %s" % (msg, key_list_str(unexpected)))
# Write to [keys] and [dup].
def parse_row_from_et(row, keys, dup):
for key in row:
for attr in key.keys():
if attr in KEY_ATTRIBUTES:
k = key.get(attr).removeprefix("\\")
if k in keys: dup.add(k)
keys.add(k)
def parse_layout(fname):
keys = set()
dup = set()
@ -41,12 +57,16 @@ def parse_layout(fname):
if root.tag != "keyboard":
return None
for row in root:
for key in row:
for attr in key.keys():
if attr.startswith("key"):
k = key.get(attr).removeprefix("\\")
if k in keys: dup.add(k)
keys.add(k)
parse_row_from_et(row, keys, dup)
return root, keys, dup
def parse_row(fname):
keys = set()
dup = set()
root = ET.parse(fname).getroot()
if root.tag != "row":
return None
parse_row_from_et(root, keys, dup)
return root, keys, dup
def check_layout(layout):
@ -55,24 +75,22 @@ def check_layout(layout):
missing_some_of(keys, "~!@#$%^&*(){}`[]=\\-_;:/.,?<>'\"+|", "ASCII punctuation")
missing_some_of(keys, "0123456789", "digits")
missing_required(keys,
["esc", "tab", "backspace", "delete",
"f11_placeholder", "f12_placeholder"],
["loc esc", "loc tab", "backspace", "delete"],
"Layout doesn't define some important keys")
unexpected_keys(keys,
["copy", "paste", "cut", "selectAll", "shareText",
"pasteAsPlainText", "undo", "redo", "replaceText",
"textAssist", "autofill" ],
"pasteAsPlainText", "undo", "redo" ],
"Layout contains editing keys")
unexpected_keys(keys,
[ "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
"f10", "f11", "f12" ],
"Layout contains function keys")
unexpected_keys(keys, [""], "Layout contains empty strings")
unexpected_keys(keys, ["loc"], "Special keyword cannot be a symbol")
unexpected_keys(keys, filter(lambda k: k.strip()!=k, keys), "Some keys contain whitespaces")
unexpected_keys(keys, ["f11_placeholder", "f12_placeholder"], "These keys are now added automatically")
bottom_row_keys = [
"ctrl", "fn", "switch_numeric", "change_method", "switch_emoji",
"config", "switch_forward", "switch_backward", "enter", "action",
"left", "up", "right", "down", "space"
]
_, bottom_row_keys, _ = parse_row("res/xml/bottom_row.xml")
if root.get("bottom_row") == "false":
missing_required(keys, bottom_row_keys,
@ -84,14 +102,15 @@ def check_layout(layout):
if root.get("script") == None:
warn("Layout doesn't specify a script.")
for fname in sys.argv[1:]:
if fname in KNOWN_NOT_LAYOUT:
for fname in sorted(sys.argv[1:]):
layout_id, _ = os.path.splitext(os.path.basename(fname))
if layout_id in KNOWN_NOT_LAYOUT:
continue
layout = parse_layout(fname)
if layout == None:
print("Not a layout file: %s" % fname)
print("Not a layout file: %s" % layout_id)
else:
print("# %s" % fname)
print("# %s" % layout_id)
warning_count = 0
check_layout(layout)
print("%d warnings" % warning_count)

155
doc/Custom-layouts.md Normal file
View File

@ -0,0 +1,155 @@
# Custom layouts
You select a key layout for Unexpected Keyboard by calling up the Settings page (swipe the gear icon) and, at the top of the page, either tapping an existing layout or tapping _Add an alternate layout_. This displays a menu of available layouts. You can define your own layout by choosing _Custom layout_ at the bottom of this menu. Unexpected Keyboard now displays code in the XML format. You make changes by replacing this with different code and tapping OK.
We recommend you keep your work in a file outside Unexpected Keyboard (named something like `MyChanges.xml`). If you installed a new version of Unexpected from a different website (with a different signature), then the work you did solely by editing the XML inside Unexpected would be lost.
Put initial contents into your file in one of these ways:
* Copypaste the code Unexpected displays for _Custom layout_.
* Make a copy of one of the built-in layouts found in [`/srcs/layouts`](https://github.com/Julow/Unexpected-Keyboard/tree/master/srcs/layouts).
* Use the [web-based editor](https://unexpected-keyboard-layout-editor.lixquid.com/). Interact with this web page to define keys and swipes and move keys to desired positions, and it will write the XML code for you. You can make the web page put the XML in a text file or copy it to the clipboard.
When you have prepared suitable XML code in one of these ways, copy it to the clipboard and paste it into Unexpected Keyboard.
## XML language overview
A layout XML file comprises tags that start with `<` and end with `>`.
* Every layout file starts with this declaration:
`<?xml version="1.0" encoding="utf-8"?>`
* Certain tags come in pairs—an opening tag and a closing tag—and apply to everything between them.
* The `<keyboard>`...`</keyboard>` pair says that the material between them is the definition of your keyboard. There can be only one of these.
* The `<row>`...`</row>` pair encloses the definition of a single row.
* An optional `<modmap>`...`</modmap>` pair contains instructions if you want to change the behavior of a modifier key such as Shift.
* Stand-alone tags include `<key`...`/>`, which defines a single key.
A tag can have properties, defined using an equals sign and a pair of ASCII double quotes. For example, `<key key0="a" />` defines the "a" key. The `key0` property of the `key` tag says which key you are defining, and the tag's location inside `<row>`...`</row>` specifies where it will go in the row.
### Example
Here is a complete keyboard file with a single row containing an "a" key on the left and a "b" key on the right:
<?xml version="1.0" encoding="utf-8"?>
<keyboard name="Simple example" script="latin">
<row>
<key key0="a" />
<key key0="b" />
</row>
</keyboard>
## Keyboard metadata
The `<keyboard>`...`</keyboard>` pair follows the declaration tag and encloses the whole keyboard. The following properties may be used (The first two appear in the example above):
* `name`: The name of the keyboard. The name you specify will appear in the Settings menu. If not present, the layout will just appear as “Custom layout”.
* `script`: The (main) writing system that the keyboard supports. The possible values are `arabic`, `armenian`, `bengali`, `cyrillic`, `devanagari`, `gujarati`, `hangul`, `hebrew`, `latin`, `persian`, `shavian`, and `urdu`. It defaults to `latin`.
* `numpad_script`: The script to use for the numpad. This is useful for scripts where a different, non-ASCII set of numerals is used, like Devanagari and Arabic. It defaults to the same as `script`.
* `bottom_row`: Whether or not to show the built-in bottom row. It accepts `true` or `false`, and defaults to `true`. If your custom layout defines the bottom row, then specify `bottom_row="false"` to disable the built-in bottom row.
+ We recommend your layout use the built-in bottom row, because it is still evolving and your layout will incorporate innovations in future versions. However, to define your own, the current definition of the bottom row is in [bottom_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/bottom_row.xml). You can copypaste this XML into your custom layout as a starting point.
+ Likewise, the current definition of the top (number) row is in [number_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/number_row.xml).
* `locale_extra_keys`: Whether Unexpected should add language-dependent extra keys from [method.xml](../res/xml/method.xml) to this layout. It accepts `true` or `false`, and defaults to `true`. To disable these automatic additions, specify `locale_extra_keys="false"`.
## Row
The `<row>`...`</row>` pair encloses one row on the keyboard. It has only one optional property:
* `height`: The height of the row: a positive floating-point value.
A row's default height is 1.0 (one quarter of the keyboard height specified on the Settings menu). The `height` property makes the row taller or shorter than this. For example, if you define a 5-row keyboard but one row has `height="0.7"`, then the keyboard's total height is 4.7 units. If the total is different from 4.0, the keyboard will be taller or shorter than that specified in Settings.
## Key
The `<key />` tag defines a key on the keyboard. Its position in the sequence of keys inside `<row>`...`</row>` indicates its position in the row from left to right. What the key does is defined by optional properties.
### Taps
What the key does when tapped is defined by the optional `key0` property. For example, `<key key0="a" />` defines the "a" key. Unexpected Keyboard provides a legend in the middle of the key.
When the Shift modifier is tapped, the "a" key becomes the "A" key and the legend temporarily changes. The Fn modifier makes a different change. You can override this behavior with a modmap (see below).
### Swipes
The following optional properties define the effects of swipes:
* `n`, `ne`, `e`, `se`, `s`, `sw`, `w`, `nw`: What the key should do when it is swiped in the direction of that compass point. ("North" means upward and "East" is to the right.)
<TABLE ALIGN=CENTER>
<TR>
<TD STYLE="width: 6em;">nw</TD><TD>n</TD><TD>ne</TD>
</TR>
<TR ALIGN=CENTER>
<TD>w</TD><TD>&nbsp;</TD><TD>e</TD>
</TR>
<TR>
<TD>sw</TD><TD>s</TD><TD>se</TD>
</TR>
</TABLE>
* `key1` through `key8` is an older way to achieve the same effects. The directions are ordered as follows:
<TABLE ALIGN=CENTER>
<TR>
<TD>key1</TD><TD>key7</TD><TD>key2</TD>
</TR>
<TR>
<TD>key5</TD><TD>&nbsp;</TD><TD>key6</TD>
</TR>
<TR>
<TD>key3</TD><TD>key8</TD><TD>key4</TD>
</TR>
</TABLE>
You can define a swipe only once with either compass-point or numeric notation. Unexpected Keyboard automatically puts a small legend in that direction from the center of the key.
* `slider`: If `slider="true"`, and the key also has `w` and `e` properties, then the key tracks horizontal finger motion precisely and sends the `w` and `e` keystrokes repeatedly. In built-in layouts, this makes the space bar send left and right characters as the user slides on the space bar.
* `anticircle`: The key value to send when doing an anti-clockwise gesture on the key.
### Layout
A key may have the following properties to control the row's layout:
* `width`: The width of the key, a positive floating-point value. It defaults to 1.0
* `shift`: How much empty space to add to the left of this key, a non-negative floating-point value. It defaults to 0.0
Normally, a key's width is 1.0 unit. Unexpected Keyboard occupies the full width of the screen, and the row defining the highest number of units (in widths plus shifts) is as wide as the screen. A row whose width is a smaller number of units has empty space on the right.
### Extra legend
* `indication`: An optional extra legend to show under the main label. For example, `<key key0="2" indication="ABC" />` displays ABC at the bottom of the 2 key, as on a pinpad or some telephones. If the key also defines a downward swipe with `s` or `key8`, the legends overlap.
### Possible key values
Built-in strings that assign a special function to a key are described in [this page](Possible-key-values.md). For example, `se="copy"` means a southeasterly swipe produces the Copy key. If a key value does not match any of the built-in strings, it outputs that text _verbatim_. For example, `key0="a"` simply outputs the letter a.
In a layout, a key value can also start with the `loc` prefix. These are place-holders; the tap or swipe does nothing unless enabled through the "Add keys to keyboard" option in the Settings menu, or implicitly enabled by the language the device is set to use. For example, `ne="loc accent_aigu"` says that a northeast swipe produces the acute accent combinatorial key—if enabled.
## Modmap
The `<modmap>`...`</modmap>` pair encloses custom mappings for modifier keys. The modmap is placed inside the `<keyboard>`...`</keyboard>` pair, but outside any row. A layout can have at most one modmap. It can contain any number of mappings. Each mapping has an `a` property and a `b` property and maps the `a` key to the `b` key. Valid values are listed in [Possible key values](Possible-key-values.md).
The following mappings are supported:
```xml
<shift a="before" b="after" />
```
This means that when the Shift modifier is on, the key `before` is changed into `after`.
```xml
<fn a="before" b="after" />
```
This means that when the Fn modifier is on, the key `before` is changed into `after`.
```xml
<ctrl a="before" b="after" />
```
This means that when the Ctrl modifier is on, the key `before` is changed into `after`. The `<ctrl />` mapping is special in that the Ctrl modifier is applied to `after` after the mapping.
The clockwise circle and the round-trip gestures are affected by both `<shift />` and `<fn />` mappings. The Shift mappings are used first and if that did not modify the key, the Fn mappings are used instead.
### Examples
① Turkish keyboards use the Latin alphabet, but when "i" is shifted, it should produce "İ". This is achieved with the following mapping:
```xml
<shift a="i" b="İ" />
```
② Cyrillic layouts have no V key. A layout can define Ctrl-V with the following mapping:
```xml
<ctrl a="в" b="v" />
```
This maps Ctrl+в to Ctrl+V—not to v.
## Portrait vs. landscape
Unexpected Keyboard remembers *separately* which layout has last been used in portrait and landscape orientation. So you may have one custom layout for portrait orientation, but another custom layout for landscape orientation, and Unexpected Keyboard will switch between them without your intervention.
## Contributing your layout
The Unexpected Keyboard project enthusiastically accepts user contributions, including custom layouts. (See the guidance for layouts at [CONTRIBUTING.md](https://github.com/Julow/Unexpected-Keyboard/blob/master/CONTRIBUTING.md#Adding-a-layout)).
* Submit a layout that has innovations of possible interest to other users at [Unexpected-Keyboard-layouts](https://github.com/Julow/Unexpected-Keyboard-layouts).
* Propose that your layout be included in the set of built-in layouts by making a Pull Request for an addition to [srcs/layouts](https://github.com/Julow/Unexpected-Keyboard/tree/master/srcs/layouts). Please show that such a layout is standard in your locale or has a substantial number of users.

190
doc/Possible-key-values.md Normal file
View File

@ -0,0 +1,190 @@
# Key values
This is an exhaustive list of special values accepted for the `key0` through `key8` or `nw` through `se` attributes on a key.
Any string that does not exactly match these will be printed verbatim.
A key can output multiple characters, but cannot combine multiple built-in key values.
## Escape codes
Value | Escape code for
:---- | :------
`\?` | `?`
`\#` | `#`
`\@` | `@`
`\n` | Literal newline character. This is different from `enter` and `action` in certain apps.
`\t` | Literal tab character. This is different from `tab` in certain apps.
`\\` | `\`
XML escape codes also work, including:
Value | Escape code for
:------- | :------
`&amp;` | `&`
`&lt;` | `<`
`&gt;` | `>`
`&quot;` | `"`
## Modifiers
System modifiers are sent to the app, which is free to do whatever they want in response.
The other modifiers only exist within the keyboard.
Value | Meaning
:---------- | :------
`shift` | System modifier.
`ctrl` | System modifier.
`alt` | System modifier.
`meta` | System modifier. Equivalent to the Windows key.
`fn` | Activates Fn mode, which assigns letters and symbols to special characters. e.g. `fn` `!` = `¡`
`compose` | Compose key. Enables composing characters using Linux-like shortcuts; e.g. `Compose` `A` `single quote` types `Á` (A with acute accent).
`capslock` | Actives and locks Shift
## Special keys
These keys are sent to apps, which are free to ignore them. The keyboard does not perform editing in response to these keys.
`esc`, `enter`,
`up`, `right`,
`down`, `left`,
`page_up`, `page_down`,
`home`, `end`,
`backspace`, `delete`,
`insert`, `scroll_lock`,
`f1`-`f12`,
`tab`, `copy`,
`paste`, `cut`,
`selectAll`, `pasteAsPlainText`,
`undo`, `redo`
## Whitespace
Value | Meaning
:------ | :------
`space` | Space bar.
`nbsp` | Non-breaking space.
`nnbsp` | Narrow non-breaking space.
`zwj` | Zero-width joiner.
`zwnj` | Zero-width non-joiner.
## Keyboard editing actions
These keys perform editing on the text without sending keys that the app can interpret differently or ignore.
Value | Meaning
:----------------- | :------
`cursor_left` | Moves the cursor position to the left directly, without sending a `left` key event.
`cursor_right` | Moves the cursor position to the right directly, without sending a `right` key event.
## Other modifiers and diacritics
Value | Meaning
:------------------- | :------
`accent_aigu` | Acute accent. `á`
`accent_caron` | Háček. `č`
`accent_cedille` | Cedilla. `ç`
`accent_circonflexe` | Circumflex. `â`
`accent_grave` | Grave accent. `à`
`accent_macron` | Macron. `ā`
`accent_ring` | Ring accent. `å`
`accent_tilde` | Tilde. `ã`
`accent_trema` | Dieresis/umlaut. `ä`
`accent_ogonek` | Ogonek. `ą`
`accent_dot_above` | Dot accent. `ż` If applied to the lowercase `i`, removes the dot instead for Turkish. `ı`
`accent_double_aigu` | Double acute accent. `ő`
`accent_slash` | Slash through. `ø`
`accent_arrow_right` | Right arrow above, used to denote a vector. `a⃗`
`accent_breve` | Breve. `ă`
`accent_bar` | Bar/strikethrough. `ɨ`
`accent_dot_below` | Dot below. `ạ`
`accent_horn` | Horn accent. `ơ`
`accent_hook_above` | Hook accent. `ả`
`superscript` | Superscript. `ᵃ`
`subscript` | Subscript. `ₐ`
`ordinal` | Turns `a` and `o` into `ª` and `º`.
`arrows` | Turns `1`-`4` and `6`-`9` into arrows.
`box` | Turns `1`-`9`, `0`, and `.` into single-line, thin box-drawing characters.
## Bidirectional
Value | Meaning
:------ | :------
`lrm` | Left-to-right mark.
`rlm` | Right-to-left mark.
`b(`, `b)`, `b[`, `b]`, `b{`, `b}`, `blt`, `bgt` | Sends the bracket characters, but with mirrored key legends for right-to-left languages. (`blt` and `bgt` print `<` and `>` respectively.)
## Hebrew
Keys ending in `_placeholder` are normally hidden unless the Fn key is pressed.
`qamats`, `patah`,
`sheva`, `dagesh`,
`hiriq`, `segol`,
`tsere`, `holam`,
`qubuts`, `hataf_patah`,
`hataf_qamats`, `hataf_segol`,
`shindot`, `shindot_placeholder`,
`sindot`, `sindot_placeholder`,
`geresh`, `gershayim`,
`maqaf`, `rafe`,
`ole`, `ole_placeholder`,
`meteg`, `meteg_placeholder`
## Keyboard behavior keys
Value | Meaning
:--------------------- | :------
`config` | Gear icon; opens Unexpected Keyboard settings.
`switch_text` | Switch to the text layer (main layer).
`switch_numeric` | Switch to the numeric layer.
`switch_emoji` | Switch to the emoji layer.
`switch_back_emoji` | Switch to the text layer from the emoji layer.
`switch_forward` | Change the keyboard layout, as long as Unexpected Keyboard has multiple keyboard layouts enabled in the settings.
`switch_backward` | Change the keyboard layout to the previous one in the list.
`switch_greekmath` | Switch to the Greek & Math Symbols layer.
`switch_clipboard` | Switch to the clipboard pane.
`change_method` | Open the input method picker dialog.
`change_method_prev` | Switch to the previously used input method.
`action` | Performs a special context-sensitive operation related to the Enter key. For example, in the Twitter (X) app, `enter` adds a new line, while `action` posts.
`voice_typing` | Begin voice typing.
`voice_typing_chooser` | Shows a menu where you can choose which voice typing provider to use, then begins voice typing when you make a selection.
`shareText` | Emit a share Intent for the selected text. **Oddity:** This is in CamelCase.
## Unused
These keys are known to do nothing.
`replaceText`, `textAssist`,
`autofill`, `removed`
## Placeholders
These keys are normally hidden unless the Fn modifier is activated.
`f11_placeholder` | `f12_placeholder`
## Complex keys
More complex keys are of this form:
```
:<kind> <attributes>:<payload>
```
Where `<kind>` is one of the kinds documented below and `<attributes>` is a
space separated list of attributes. `<payload>` depends on the `<kind>`.
Attributes are:
- `symbol='Sym'` specifies the symbol to be shown on the keyboard.
- `flags='<flags>'` changes the behavior of the key.
`<flags>` is a coma separated list of:
+ `dim`: Make the symbol dimmer.
+ `small`: Make the symbol smaller.
### Kind `str`
Defines a key that outputs an arbitrary string. `<payload>` is a string wrapped
in single-quotes (`'`), escaping of other single quotes is allowed with `\'`.
For example:
- `:str:'Arbitrary string with a \' inside'`
- `:str symbol='Symbol':'Output string'`
### Kind `char`
Defines a key that outputs a single character. `<payload>` is the character to
output, unquoted.
This kind of key can be used to define a character key with a different symbol
on it. `char` keys can be modified by `ctrl` and other modifiers, unlike `str`
keys.
For example:
- `:char symbol='q':љ`, which is used to implement `ctrl` shortcuts in cyrillic
layouts.

View File

@ -0,0 +1,6 @@
Hlavní funkcí je možnost psát více znaků posunutím kláves směrem k rohům.
Tato aplikace byla původně navržena pro programátory používající Termux.
Nyní je ideální pro každodenní použití.
Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je Open Source.

View File

@ -0,0 +1,9 @@
Allow selecting any number of standard and custom layouts.
Allow adding custom keys to the keyboard.
Changed behavior of auto-added keys (often dead-keys).
New layouts.
Improved layouts and language support.
Improved the space bar slider, and many more.
Updated translations.
Thanks to the contributors: @ChasmSolacer, @ElucGeek, @GoRaN909, @RZHSSNZDH, @Shareef101, @Validbit, @eandersons, @nitsvga, @polyctena, @sdrapha, @syskill

View File

@ -0,0 +1,8 @@
Improved custom layout option.
Allow selecting voice typing app with a long press.
The numpad can work with other numeral systems.
New and updated layouts.
New themes.
Many small improvements.
Thanks to the contributors: @pharook, @syskill, @ojas-bhagavath, @lrvideckis, @lyubomirv, @matthiakl, @deftkHD, @V6lhost, @RZHSSNZDH, @RetrogisusDEV, @rafasaurus, @krtsgnr7230, @eandersons, @ChasmSolacer, @Validbit, @polyctena

View File

@ -0,0 +1,7 @@
The custom vibration setting is back.
Allow to hide the keyboard switching key.
Fixed modifier keys in some development apps.
Updated translations.
Bug fixes and general improvements.
Many thanks to the contributors: @abb128, @marciozomb13, @RetrogisusDEV, @Sestowner, @vedamanavi, @krtsgnr7230

View File

@ -0,0 +1,6 @@
New layouts: QWERTY (Slovak), Gujarati phonetic
Add Linux Compose key to type a variety of characters using known combinations.
Fixed localized numpad and number row.
Many improvements and bug fixes.
Huge thanks to the contributors: @Yogesh-B, @ChasmSolacer, @matthiakl, @Sestowner, @RyanGibb, @BogdanLata, @RetrogisusDEV, @V6lhost, @ErrrorMaxx, @sdrapha, @vedamanavi

View File

@ -0,0 +1,11 @@
MessagEase and Thumb-Key inspired gestures with the anti-clockwise circle being
completely configurable.
Updated emojis.
Improved Hangul (Korean) support.
Added Danish support.
Improved spacebar slider.
Updated translations.
Various improvements and fixes to the app and layouts.
Many thanks to the contributors: @alotbsol555 @bkmgit @Cheesebaron @CloneWith @eandersons @JapanYoshi @Julow @la-ninpre @m15a @marciozomb13 @polyctena @solokot @Spike-from-NH @tmqCypher @Validbit

View File

@ -0,0 +1,8 @@
Clipboard pane
New Monet theme
Improvements to custom layouts
Options to disable key repeat and the circle gesture
Options to disable the Tab and Esc keys
Many thanks to the contributors: @alotbsol555 @ChasmSolacer @eandersons @polyctena @Sestowner @solokot @Spike-from-NH @TadaCZE @V6lhost @Validbit

View File

@ -0,0 +1,6 @@
Fix crash on Android 6.
Fix scaling issues for layouts with few columns.
Added Serbian layouts.
Layout and compose key tweaks. Improvements to custom layouts. Added Menu key.
Many thanks to the contributors: @adrian4096 @asivery @bokidori @dingodoppelt @RZHSSNZDH

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1 @@
https://www.youtube.com/watch?v=rwGvWesPFX8

View File

@ -3,4 +3,4 @@ La característica principal es que hay acceso a más caractéres deslizando hac
Esta aplicación fue originalmente diseñada para programadores que usaran Termux.
Ahora es perfecta para uso cotidiano.
La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y es de Fuente Abierta.
La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y es de Fuente Abierta.

View File

@ -0,0 +1,7 @@
このキーボードは、キーの角をスワイプすることで様々なキーを入力できます。
このアプリは元々はTermuxでのプログラミング用に設計されました。
しかし、今では普段の入力にも適しています。
PCキーボードでの半角入力を再現しています。日本語入力、変換は出来ません。
このアプリは広告を含まず、インターネットに接続せず、そしてオープンソースです。

View File

@ -0,0 +1 @@
軽量でプライバシーに配慮したAndroid用仮想キーボード

View File

@ -0,0 +1,6 @@
주요 기능은 모서리 방향으로 키를 스와이프하여 더 많은 문자를 입력할 수 있다는 것입니다.
이 앱은 처음에는 Termux를 사용하는 프로그래머들을 위한 것으로 개발되었습니다.
지금은 일상적인 용도로도 완벽합니다.
이 응용 프로그램에는 광고가 없으며 네트워크 요청을 하지 않고 오픈 소스입니다.

View File

@ -0,0 +1 @@
Unexpected Keyboard

View File

@ -0,0 +1,6 @@
A principal característica é que você pode digitar mais caracteres deslizando as teclas para os cantos.
O app foi criado originalmente para desenvolvedores que usam Termux.
Agora aperfeiçoado para o uso diário.
Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e é Open Source.

View File

@ -0,0 +1 @@
Unexpected Keyboard

View File

@ -0,0 +1,6 @@
Главная особенность клавиатуры — это возможность легко напечатать любой ASCII-символ жестами в углы клавиш.
Приложение изначально было разработано для использования с Termux.
На данный момент оно также удобно в повседневном использовании.
Приложение не содержит рекламы, не осуществляет никаких запросов в сеть и имеет открытый исходный код.

View File

@ -0,0 +1 @@
Unexpected Keyboard

View File

@ -0,0 +1,6 @@
Bu uygulama özünde tuşların kenarlarından kaydırarak daha fazla karakter yazabilmek amacıyla geliştirildi.
Bu uygulama aslında Termux kullanıcıları için geliştirildi.
Artık gündelik kullanım için de uygun.
Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz.

View File

@ -0,0 +1 @@
Android için hafif ve güvenlik odaklı bir sanal klavye uygulaması.

View File

@ -0,0 +1 @@
Unexpected Keyboard

View File

@ -0,0 +1,6 @@
Головна особливість полягає в тому, що ви можете вводити більше символів, проводячи клавіші до кутів.
Ця програма спочатку була розроблена для програмістів, які використовують Termux.
Тепер ідеально підходить для щоденного використання.
Ця програма не містить реклами, не надсилає жодних мережевих запитів і має відкритий код.

View File

@ -0,0 +1 @@
Легка та конфіденційна віртуальна клавіатура для Android.

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