Compare commits

...

59 Commits
0.1 ... 4.3.30

Author SHA1 Message Date
Yuriy Liskov
cb13108a11 fix: home activity not found: update 2 2018-09-18 00:37:14 +03:00
Yuriy Liskov
43ef8324bf fix: home activity not found 2018-09-17 03:33:41 +03:00
Yuriy Liskov
70cfd73ac8 mouse pointer animation fix: update 2 2018-09-17 02:41:00 +03:00
Yuriy Liskov
0a42892d2d mouse pointer animation fix 2018-09-17 01:59:05 +03:00
Yuriy Liskov
c5c88e622d bit refactor 2018-09-17 01:25:26 +03:00
Yuriy Liskov
6e7db94a30 fix issue #7 2018-09-15 03:27:45 +03:00
Yuriy Liskov
80b76e9d1e donation 2018-09-08 00:08:58 +03:00
Yuriy Liskov
8c1c36cf0e update readme 2018-09-04 16:32:26 +03:00
Yuriy Liskov
a4d615bbf2 persian fix 2018-08-29 15:59:25 +03:00
Yuriy Liskov
5e8e68de44 persian fix; enter in editor fix 2018-08-20 16:05:06 +03:00
Yuriy Liskov
48e12a21d1 ESC fix #2 2018-08-10 18:42:20 +03:00
Yuriy Liskov
6a8b9c63e5 ESC and Go fixes (see github > issues) 2018-08-07 20:39:07 +03:00
Yuriy Liskov
95ab858296 bugfixes 2018-08-04 18:19:57 +03:00
Yuriy Liskov
37243e4d11 hide soft kbd on physical key 2018-08-03 19:00:34 +03:00
Yuriy Liskov
0c7052be55 Swedish translate fix 2018-07-19 00:02:24 +03:00
Yuriy Liskov
5bf9563011 Swedish translate fix 2018-07-18 22:25:27 +03:00
Yuriy Liskov
abe60af6a6 add bunch of the new translations 2018-07-18 21:31:24 +03:00
Yuriy Liskov
13bc09cfcd Swedish translation (early phase) 2018-07-18 18:18:50 +03:00
Yuriy Liskov
e53316842c fix2: remember selected kbd 2018-07-18 17:34:47 +03:00
Yuriy Liskov
c16cc2525a fix: remember selected kbd 2018-07-18 14:29:08 +03:00
Yuriy Liskov
a1f7c7959a add Swedish kbd 2018-07-08 23:13:43 +03:00
Yuriy Liskov
2cdfd6a2a3 improve rus translation 2018-05-25 22:58:41 +03:00
Yuriy Liskov
f54e9826f1 ru translation 2018-05-14 20:36:17 +03:00
Yuriy Liskov
2dc84de557 ru fix 2018-05-14 06:03:31 +03:00
Yuriy Liskov
643301a02a update readme 2018-05-05 01:21:50 +03:00
Yuriy Liskov
ef8339e351 update readme 2018-05-05 01:20:26 +03:00
Yuriy Liskov
aa5656998c meet new contributor - aglt 2018-05-05 00:54:17 +03:00
Yuriy Liskov
53e7a4958f bump to 4.3.10 2018-05-05 00:48:08 +03:00
Yuriy Liskov
f2e1a39931 Icelandic lang: final 2018-05-05 00:45:02 +03:00
Yuriy Liskov
375a96c8aa Merge branch 'aglt-master' 2018-05-05 00:30:17 +03:00
aglt
c061884771 Merge branch 'master' into icelandic 2018-05-04 20:03:31 +00:00
aglt
7ad28440ba icelandic language support 2018-05-04 20:02:58 +00:00
Yuriy Liskov
a90f40dc95 update 2018-05-04 11:52:21 +03:00
Yuriy Liskov
7cf2e00f6e fix 2018-05-04 11:40:18 +03:00
Yuriy Liskov
aeb54d90bc wiki link 2018-05-04 11:25:19 +03:00
Yuriy Liskov
67a682269e readme fix 2018-05-04 11:10:39 +03:00
Yuriy Liskov
301833ff90 contributors 2018-05-04 11:06:34 +03:00
Yuriy Liskov
a57eeff2ae bump to 4.3.9 2018-04-27 17:40:40 +03:00
Yuriy Liskov
63b5f290e3 Merge branch 'rabin111-master' 2018-04-27 17:20:11 +03:00
rabin
acc035d8ba correct Thai keyboard layout 2018-04-26 10:58:01 +07:00
Yuriy Liskov
0757a82e2b refactor last commit 2018-04-23 02:30:59 +03:00
Yuriy Liskov
d05415fb65 fixes for previous commit 2018-04-23 00:04:11 +03:00
Yuriy Liskov
b3afc8e7f2 store up to two chars in one key label (Thai fix) 2018-04-22 15:48:25 +03:00
Yuriy Liskov
5d94ae66ac FireTV fix (update2) 2018-03-26 00:02:20 +03:00
Yuriy Liskov
0ed1761b8e FireTV fix (update1) 2018-03-25 18:28:27 +03:00
Yuriy Liskov
e9cc575c31 FireTV fix (possible) 2018-03-25 16:46:58 +03:00
Yuriy Liskov
4262862a1b spell fix 2018-03-24 21:07:14 +02:00
Yuriy Liskov
1313101d70 img fix 2018-03-24 21:04:31 +02:00
Yuriy Liskov
643b7e5443 add Thai kbd (final?) 2018-03-22 23:56:08 +02:00
Yuriy Liskov
524b371c63 add Thai kbd (pre-final) 2018-03-22 23:46:16 +02:00
Yuriy Liskov
aebdadb0fa add Thai lang (update 1) 2018-03-21 23:59:05 +02:00
Yuriy Liskov
f54ec3e5b0 rename to Pro 2018-03-20 23:15:01 +02:00
Yuriy Liskov
231c384db3 release naming 2018-03-20 22:50:30 +02:00
Yuriy Liskov
0d8a86cadd release naming 2018-03-20 22:47:59 +02:00
Yuriy Liskov
f948ba3bd4 keyboard chooser (bugfixes) 2018-03-20 22:31:30 +02:00
Yuriy Liskov
1c65d017fb add keyboard chooser dialog 2018-03-20 15:48:41 +02:00
Yuriy Liskov
a7598c27eb donate address 2018-03-19 23:11:21 +02:00
Yuriy Liskov
ce62e91626 collect all language packs in one app 2018-03-19 22:51:26 +02:00
Yuriy Liskov
171d314230 add lang switch key; bit refactoring 2018-03-19 13:55:03 +02:00
118 changed files with 3845 additions and 474 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
notes.txt
/other
/files
/misc
tmp/

View File

@@ -1,27 +1,30 @@
![Logo of LeanKeyKeyboard](screenshots/leankeykeyboard-logo_small.png "Logo of LeanKeyKeyboard") LeanKeyKeyboard
![Logo of LeanKeyKeyboard](img/leankeykeyboard_logo_small.png "Logo of LeanKeyKeyboard") LeanKeyKeyboard
=========
[![MPLv2 License](http://img.shields.io/badge/license-MPLv2-blue.svg?style=flat-square)](https://www.mozilla.org/MPL/2.0/)
__LeanKeyKeyboard: An Keyboard for Android-based set-top boxes and TVs:__
__LeanKeyKeyboard: Keyboard for Android-based set-top boxes and TVs:__
Visit Google Play page:
* <a href="https://play.google.com/store/apps/details?id=org.liskovsoft.androidtv.rukeyboard" target="_blank">[APP] LeanKeyKeyboard</a>
### Features:
__NOTE: Google Play release is outdated. So I recommend to obtain new releases [here](https://github.com/yuliskov/LeanKeyKeyboard/releases).__
### Features:
* Designed for TV screens.
* Any remote controller support.
* Support dozens of languages through the language packs.
* Supports dozens of languages.
* Doesn't depend on Google Services.
* __No root required!__
__Switch to other language performed with menu key or with long press of the space bar.__
__Switch to other language performed with 'world' button, menu key or long press on the space bar.__
### Screenshots:
* __[Open screenshots](#screens)__
### Install LeanKeyKeyboard:
__Easy installation in less than 5 minutes with only the FireTV__
* <a href="https://github.com/yuliskov/SmartYouTubeTV/wiki/Install-SmartYouTubeTV-(only-FireTV-needed)">Install LeanKeyKeyboard (only FireTV needed)</a>
__Easy installation in less than 10 minutes with only FireTV__
* <a href="https://github.com/yuliskov/LeanKeyKeyboard/wiki/How-to-Install-LeanKeyKeyboard-on-FireTV">Install LeanKeyKeyboard (only FireTV needed)</a>
__Standard installation via ADB__
* If you don't know how to sideload/install apps via ADB, read a tutorial (e.g. <a href="http://kodi.wiki/view/HOW-TO:Install_Kodi_on_Fire_TV" target="_blank">this one</a>)
@@ -35,15 +38,19 @@ __Standard installation via ADB__
### Changelog:
* [Check releases page for changelog ..](https://github.com/yuliskov/LeanKeyKeyboard/releases)
### Screenshots:
### Contributors:
* __[aglt](https://github.com/aglt)__ (Icelandic lang)
* __[rabin111](https://github.com/rabin111)__ (Thai lang)
![Screenshot of LeanKeyKeyboard](screenshots/leankeykeyboard_screenshot_01.png "Screenshot of LeanKeyKeyboard")
![Screenshot of LeanKeyKeyboard](screenshots/leankeykeyboard_screenshot_02.png "Screenshot of LeanKeyKeyboard")
### Developer:
* __[yuliskov](https://github.com/yuliskov)__ (design & coding)
### Why using it:
* LeanKeyKeyboard provides possibility to enter text with any length.
* LeanKeyKeyboard provides support for the multiple remote controllers which allows you to enter text in a very convenient way.
### Donation:
If you want to support my developments you are welcome to buy me a cup of coffee :)
* coming soon
* [__PrivatBank (Ukraine)__](https://privatbank.ua/ru/sendmoney?payment=5fcdddf53e3d491d63fcb050e6e2e05f2f2678c2)
* __BTC__: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
### Screens:
![Screenshot of LeanKeyKeyboard](img/leankeykeyboard_screenshot_01.png "Screenshot of LeanKeyKeyboard")
![Screenshot of LeanKeyKeyboard](img/leankeykeyboard_screenshot_02.png "Screenshot of LeanKeyKeyboard")
![Screenshot of LeanKeyKeyboard](img/leankeykeyboard_screenshot_03.png "Screenshot of LeanKeyKeyboard")

View File

@@ -14,14 +14,14 @@ buildscript {
// https://stackoverflow.com/questions/20404476/how-to-define-common-android-properties-for-all-modules-using-gradle
// Gradle constants example: https://github.com/google/ExoPlayer
ext {
compileSdkVersion = 27
buildToolsVersion = "27.0.3"
compileSdkVersion = 26
buildToolsVersion = "26.0.2"
minSdkVersion = 14
targetSdkVersion = 27
appCompatVersion = 'com.android.support:appcompat-v7:27.+'
targetSdkVersion = 26
appCompatVersion = 'com.android.support:appcompat-v7:26.+'
espressoCoreVersion = 'com.android.support.test.espresso:espresso-core:2.2.2'
junitVersion = 'junit:junit:4.12'
supportVersion = 'com.android.support:support-v4:27.+'
supportVersion = 'com.android.support:support-v4:26.+'
robolectricVersion = 'org.robolectric:robolectric:3.5.1'
crashlyticsVersion = 'com.crashlytics.sdk.android:crashlytics:2.8.0@aar'
}

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -5,11 +5,11 @@ android {
buildToolsVersion project.properties.buildToolsVersion
defaultConfig {
applicationId "org.liskovsoft.androidtv.rukeyboard"
applicationId "org.liskovsoft.leankeykeyboard.pro"
minSdkVersion project.properties.minSdkVersion
targetSdkVersion project.properties.targetSdkVersion
versionCode 52
versionName "3.2.0"
versionCode 80
versionName "4.3.30"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -20,6 +20,26 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// naming example: SmartYouTubeTV_Xwalk_v6.8.12_r.apk
// https://stackoverflow.com/questions/18332474/how-to-set-versionname-in-apk-filename-using-gradle
applicationVariants.all { variant ->
variant.outputs.each { output ->
def project = "LeanKeyKeyboardPro"
def buildType = variant.variantData.variantConfiguration.buildType.name.take(1)
def version = variant.versionName
def newApkName = sprintf("%s_v%s_%s.apk", [project, version, buildType])
output.outputFile = new File(output.outputFile.parent, newApkName)
}
}
lintOptions {
abortOnError true
disable 'MissingTranslation'
disable 'NewApi'
}
}
dependencies {

View File

@@ -4,10 +4,14 @@
<uses-feature android:name="android.hardware.microphone" android:required="false"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<application android:banner="@drawable/banner_app" android:label="LeanKey Keyboard" android:icon="@drawable/ic_launcher" tools:targetApi="21">
<activity android:launchMode="singleTop" android:name="com.liskovsoft.inputchooser.SettingsActivity">
<application android:banner="@drawable/banner_app" android:label="@string/ime_name" android:icon="@drawable/ic_launcher" tools:targetApi="21">
<activity android:launchMode="singleTop" android:name="com.liskovsoft.other.GenericLaunchActivity">
<meta-data android:name="package" android:value="com.android.settings"/>
<meta-data android:name="class" android:value="com.android.settings.Settings"/>
<meta-data android:name="class" android:value="com.android.settings.Settings$LanguageAndInputSettingsActivity"/>
<!-- "Languages & input" on old api -->
<meta-data android:name="package_alt" android:value="com.android.settings"/>
<meta-data android:name="class_alt" android:value="com.android.settings.Settings$InputMethodAndLanguageSettingsActivity"/>
<!-- Last try (if above not found) -->
<meta-data android:name="intent" android:value="android.settings.INPUT_METHOD_SETTINGS"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -15,13 +19,15 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
<service android:label="LeanKey Keyboard" android:name="com.google.leanback.ime.LeanbackImeService" android:permission="android.permission.BIND_INPUT_METHOD">
<service android:label="@string/ime_service_name"
android:name="com.google.leanback.ime.LeanbackImeService"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
</service>
<receiver android:name="com.liskovsoft.inputchooser.RestartServiceReceiver" android:exported="true" android:enabled="true">
<receiver android:name="com.liskovsoft.other.RestartServiceReceiver" android:exported="true" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />

View File

@@ -36,6 +36,8 @@ import android.widget.RelativeLayout.LayoutParams;
import com.google.android.leanback.ime.voice.RecognizerView;
import com.google.android.leanback.ime.voice.SpeechLevelSource;
import com.google.leanback.ime.LeanbackImeService;
import com.liskovsoft.other.ChooseKeyboardDialog;
import com.liskovsoft.utils.LeanKeyPreferences;
import com.liskovsoft.keyboardaddons.KeyboardManager;
import com.liskovsoft.leankeykeyboard.R;
@@ -59,8 +61,11 @@ public class LeanbackKeyboardContainer {
public static final int TOUCH_STATE_TOUCH_SNAP = 1;
private static final boolean VOICE_SUPPORTED = true;
public static final Interpolator sMovementInterpolator = new DecelerateInterpolator(1.5F);
public static final int DIRECTION_UP = 8;
public static final int DIRECTION_DOWN = 2;
public static final int DIRECTION_LEFT = 1;
public static final int DIRECTION_RIGHT = 4;
private Keyboard mAbcKeyboard;
private Keyboard mAbcKeyboardRU;
private Button mActionButtonView;
private final float mAlphaIn;
private final float mAlphaOut;
@@ -161,7 +166,6 @@ public class LeanbackKeyboardContainer {
mAlphaIn = res.getFraction(R.fraction.alpha_in, 1, 1);
mAlphaOut = res.getFraction(R.fraction.alpha_out, 1, 1);
mVoiceAnimator = new LeanbackKeyboardContainer.VoiceIntroAnimator(mVoiceEnterListener, mVoiceExitListener);
initKeyboards();
mRootView = (RelativeLayout) mContext.getLayoutInflater().inflate(R.layout.root_leanback, null);
mKeyboardsContainer = mRootView.findViewById(R.id.keyboard);
mSuggestionsBg = mRootView.findViewById(R.id.candidate_background);
@@ -203,8 +207,9 @@ public class LeanbackKeyboardContainer {
LeanbackKeyboardContainer.this.cancelVoiceRecording();
}
});
initKeyboards();
}
private void configureFocus(LeanbackKeyboardContainer.KeyFocus focus, Rect rect, int index, int type) {
focus.type = type;
focus.index = index;
@@ -267,10 +272,10 @@ public class LeanbackKeyboardContainer {
}
private void initKeyboards() {
this.mAbcKeyboard = new Keyboard(this.mContext, R.xml.qwerty_us);
this.mSymKeyboard = new Keyboard(this.mContext, R.xml.sym_us);
this.updateAddonKeyboard();
this.mNumKeyboard = new Keyboard(this.mContext, R.xml.number);
mAbcKeyboard = new Keyboard(mContext, R.xml.qwerty_us);
mSymKeyboard = new Keyboard(mContext, R.xml.sym_us);
updateAddonKeyboard();
mNumKeyboard = new Keyboard(mContext, R.xml.number);
}
private boolean isMatch(Locale var1, Locale[] var2) {
@@ -312,11 +317,13 @@ public class LeanbackKeyboardContainer {
}
/**
* All keyboard settings applied here
* @param resources resources (not used)
* Init currently displayed keyboard<br/>
* Note: all keyboard settings applied here<br/>
* Note: this method is called constantly on new field
* @param res resources (not used)
* @param info current ime attributes
*/
private void setImeOptions(Resources resources, EditorInfo info) {
private void setImeOptions(Resources res, EditorInfo info) {
// do not erase last keyboard
if (mInitialMainKeyboard == null) {
mInitialMainKeyboard = mAbcKeyboard;
@@ -439,23 +446,23 @@ public class LeanbackKeyboardContainer {
boolean overestimateHeight = false;
switch (focus.type) {
case KeyFocus.TYPE_MAIN:
boolean showScale = false;
overestimateHeight = true;
if (focus.code != LeanbackKeyboardView.ASCII_SPACE) {
overestimateWidth = true;
} else {
overestimateWidth = false;
showScale = true;
}
LeanbackKeyboardView mainView = mMainKeyboardView;
int index = focus.index;
boolean isClicked = false;
if (mTouchState == TOUCH_STATE_CLICK) {
overestimateHeight = true;
} else {
overestimateHeight = false;
isClicked = true;
}
mainView.setFocus(index, overestimateHeight, overestimateWidth);
mainView.setFocus(index, isClicked, showScale);
mPrevView = mMainKeyboardView;
overestimateHeight = true;
break;
case KeyFocus.TYPE_VOICE:
mVoiceButtonView.setMicFocused(true);
@@ -587,7 +594,12 @@ public class LeanbackKeyboardContainer {
mSelector.setX(translatedX);
mSelector.setY(translatedY);
} else {
mSelector.animate().x(translatedX).y(translatedY).setInterpolator(sMovementInterpolator).setDuration(MOVEMENT_ANIMATION_DURATION).start();
mSelector.animate()
.x(translatedX)
.y(translatedY)
.setInterpolator(sMovementInterpolator)
.setDuration(MOVEMENT_ANIMATION_DURATION)
.start();
}
}
@@ -614,51 +626,58 @@ public class LeanbackKeyboardContainer {
return mAutoEnterSpaceEnabled;
}
/**
* Initialize {@link KeyFocus focus} variable based on supplied coordinates
* @param x x coordinates
* @param y y coordinates
* @param focus result focus
* @return whether focus is found or not
*/
public boolean getBestFocus(final Float x, final Float y, final LeanbackKeyboardContainer.KeyFocus focus) {
this.offsetRect(this.mRect, this.mActionButtonView);
int actionLeft = this.mRect.left;
this.offsetRect(this.mRect, this.mMainKeyboardView);
int keyboardTop = this.mRect.top;
offsetRect(mRect, mActionButtonView);
int actionLeft = mRect.left;
offsetRect(mRect, mMainKeyboardView);
int keyboardTop = mRect.top;
Float newX = x;
if (x == null) {
newX = this.mX;
newX = mX;
}
Float newY = y;
if (y == null) {
newY = this.mY;
newY = mY;
}
int count = this.mSuggestions.getChildCount();
if (newY < (float) keyboardTop && count > 0 && this.mSuggestionsEnabled) {
int count = mSuggestions.getChildCount();
if (newY < (float) keyboardTop && count > 0 && mSuggestionsEnabled) {
for (actionLeft = 0; actionLeft < count; ++actionLeft) {
View view = this.mSuggestions.getChildAt(actionLeft);
this.offsetRect(this.mRect, view);
if (newX < (float) this.mRect.right || actionLeft + 1 == count) {
View view = mSuggestions.getChildAt(actionLeft);
offsetRect(mRect, view);
if (newX < (float) mRect.right || actionLeft + 1 == count) {
view.requestFocus();
LeanbackUtils.sendAccessibilityEvent(view.findViewById(R.id.text), true);
this.configureFocus(focus, this.mRect, actionLeft, 3);
configureFocus(focus, mRect, actionLeft, KeyFocus.TYPE_SUGGESTION);
break;
}
}
return true;
} else if (newY < (float) keyboardTop && this.mEscapeNorthEnabled) {
this.escapeNorth();
} else if (newY < (float) keyboardTop && mEscapeNorthEnabled) {
escapeNorth();
return false;
} else if (newX > (float) actionLeft) {
this.offsetRect(this.mRect, this.mActionButtonView);
this.configureFocus(focus, this.mRect, 0, 2);
offsetRect(mRect, mActionButtonView);
configureFocus(focus, mRect, 0, KeyFocus.TYPE_ACTION);
return true;
} else {
this.mX = newX;
this.mY = newY;
this.offsetRect(this.mRect, this.mMainKeyboardView);
final float left = (float) this.mRect.left;
final float top = (float) this.mRect.top;
actionLeft = this.mMainKeyboardView.getNearestIndex(Float.valueOf(newX - left), Float.valueOf(newY - top));
Key key = this.mMainKeyboardView.getKey(actionLeft);
this.configureFocus(focus, this.mRect, actionLeft, key, 0);
mX = newX;
mY = newY;
offsetRect(mRect, mMainKeyboardView);
final float left = (float) mRect.left;
final float top = (float) mRect.top;
actionLeft = mMainKeyboardView.getNearestIndex(Float.valueOf(newX - left), Float.valueOf(newY - top));
Key key = mMainKeyboardView.getKey(actionLeft);
configureFocus(focus, mRect, actionLeft, key, 0);
return true;
}
}
@@ -688,109 +707,109 @@ public class LeanbackKeyboardContainer {
public boolean getNextFocusInDirection(int direction, LeanbackKeyboardContainer.KeyFocus startFocus, LeanbackKeyboardContainer.KeyFocus nextFocus) {
switch (startFocus.type) {
case KeyFocus.TYPE_MAIN:
Key key = this.getKey(startFocus.type, startFocus.index);
float var5 = (float) startFocus.rect.height() / 2.0F;
float var4 = (float) startFocus.rect.centerX();
float var6 = (float) startFocus.rect.centerY();
Key key = getKey(startFocus.type, startFocus.index);
float centerDelta = (float) startFocus.rect.height() / 2.0F;
float centerX = (float) startFocus.rect.centerX();
float centerY = (float) startFocus.rect.centerY();
if (startFocus.code == 32) {
var4 = this.mX;
centerX = mX;
}
if ((direction & 1) != 0) {
if ((direction & DIRECTION_LEFT) != 0) {
if ((key.edgeFlags & 1) == 0) {
var4 = (float) startFocus.rect.left - var5;
centerX = (float) startFocus.rect.left - centerDelta;
}
} else if ((direction & 4) != 0) {
} else if ((direction & DIRECTION_RIGHT) != 0) {
if ((key.edgeFlags & 2) != 0) {
this.offsetRect(this.mRect, this.mActionButtonView);
var4 = (float) this.mRect.centerX();
offsetRect(mRect, mActionButtonView);
centerX = (float) mRect.centerX();
} else {
var4 = (float) startFocus.rect.right + var5;
centerX = (float) startFocus.rect.right + centerDelta;
}
}
if ((direction & 8) != 0) {
var5 = (float) ((double) var6 - (double) startFocus.rect.height() * DIRECTION_STEP_MULTIPLIER);
if ((direction & DIRECTION_UP) != 0) {
centerDelta = (float) ((double) centerY - (double) startFocus.rect.height() * DIRECTION_STEP_MULTIPLIER);
} else {
var5 = var6;
if ((direction & 2) != 0) {
var5 = (float) ((double) var6 + (double) startFocus.rect.height() * DIRECTION_STEP_MULTIPLIER);
centerDelta = centerY;
if ((direction & DIRECTION_DOWN) != 0) {
centerDelta = (float) ((double) centerY + (double) startFocus.rect.height() * DIRECTION_STEP_MULTIPLIER);
}
}
this.getPhysicalPosition(var4, var5, this.mTempPoint);
return this.getBestFocus(var4, var5, nextFocus);
getPhysicalPosition(centerX, centerDelta, mTempPoint);
return getBestFocus(centerX, centerDelta, nextFocus);
case KeyFocus.TYPE_VOICE:
default:
break;
case KeyFocus.TYPE_ACTION:
this.offsetRect(this.mRect, this.mMainKeyboardView);
if ((direction & 1) != 0) {
return this.getBestFocus((float) this.mRect.right, null, nextFocus);
offsetRect(mRect, mMainKeyboardView);
if ((direction & DIRECTION_LEFT) != 0) {
return getBestFocus((float) mRect.right, null, nextFocus);
}
if ((direction & 8) != 0) {
this.offsetRect(this.mRect, this.mSuggestions);
return this.getBestFocus((float) startFocus.rect.centerX(), (float) this.mRect.centerY(), nextFocus);
if ((direction & DIRECTION_UP) != 0) {
offsetRect(mRect, mSuggestions);
return getBestFocus((float) startFocus.rect.centerX(), (float) mRect.centerY(), nextFocus);
}
break;
case KeyFocus.TYPE_SUGGESTION:
if ((direction & 2) != 0) {
this.offsetRect(this.mRect, this.mMainKeyboardView);
return this.getBestFocus((float) startFocus.rect.centerX(), (float) this.mRect.top, nextFocus);
if ((direction & DIRECTION_DOWN) != 0) {
offsetRect(mRect, mMainKeyboardView);
return getBestFocus((float) startFocus.rect.centerX(), (float) mRect.top, nextFocus);
}
if ((direction & 8) != 0) {
if (this.mEscapeNorthEnabled) {
this.escapeNorth();
if ((direction & DIRECTION_UP) != 0) {
if (mEscapeNorthEnabled) {
escapeNorth();
return true;
}
} else {
boolean var7;
if ((direction & 1) != 0) {
var7 = true;
boolean left;
if ((direction & DIRECTION_LEFT) != 0) {
left = true;
} else {
var7 = false;
left = false;
}
boolean var12;
if ((direction & 4) != 0) {
var12 = true;
boolean right;
if ((direction & DIRECTION_RIGHT) != 0) {
right = true;
} else {
var12 = false;
right = false;
}
if (var7 || var12) {
this.offsetRect(this.mRect, this.mRootView);
MarginLayoutParams var11 = (MarginLayoutParams) this.mSuggestionsContainer.getLayoutParams();
int var8 = this.mRect.left + var11.leftMargin;
int var9 = this.mRect.right - var11.rightMargin;
int var10 = startFocus.index;
byte var13;
if (var7) {
var13 = -1;
if (left || right) {
offsetRect(mRect, mRootView);
MarginLayoutParams params = (MarginLayoutParams) mSuggestionsContainer.getLayoutParams();
int leftCalc = mRect.left + params.leftMargin;
int rightCalc = mRect.right - params.rightMargin;
int focusIdx = startFocus.index;
byte delta;
if (left) {
delta = -1;
} else {
var13 = 1;
delta = 1;
}
direction = var10 + var13;
View var14 = this.mSuggestions.getChildAt(direction);
if (var14 != null) {
this.offsetRect(this.mRect, var14);
if (this.mRect.left < var8 && this.mRect.right > var9) {
this.mRect.left = var8;
this.mRect.right = var9;
} else if (this.mRect.left < var8) {
this.mRect.right = this.mRect.width() + var8;
this.mRect.left = var8;
} else if (this.mRect.right > var9) {
this.mRect.left = var9 - this.mRect.width();
this.mRect.right = var9;
int suggestIdx = focusIdx + delta;
View suggestion = mSuggestions.getChildAt(suggestIdx);
if (suggestion != null) {
offsetRect(mRect, suggestion);
if (mRect.left < leftCalc && mRect.right > rightCalc) {
mRect.left = leftCalc;
mRect.right = rightCalc;
} else if (mRect.left < leftCalc) {
mRect.right = mRect.width() + leftCalc;
mRect.left = leftCalc;
} else if (mRect.right > rightCalc) {
mRect.left = rightCalc - mRect.width();
mRect.right = rightCalc;
}
var14.requestFocus();
LeanbackUtils.sendAccessibilityEvent(var14.findViewById(R.id.text), true);
this.configureFocus(nextFocus, this.mRect, direction, 3);
suggestion.requestFocus();
LeanbackUtils.sendAccessibilityEvent(suggestion.findViewById(R.id.text), true);
configureFocus(nextFocus, mRect, suggestIdx, KeyFocus.TYPE_SUGGESTION);
return true;
}
}
@@ -800,72 +819,73 @@ public class LeanbackKeyboardContainer {
return true;
}
public CharSequence getSuggestionText(int var1) {
Object var3 = null;
CharSequence var2 = (CharSequence) var3;
if (var1 >= 0) {
var2 = (CharSequence) var3;
if (var1 < this.mSuggestions.getChildCount()) {
Button var4 = (Button) this.mSuggestions.getChildAt(var1).findViewById(R.id.text);
var2 = (CharSequence) var3;
if (var4 != null) {
var2 = var4.getText();
public CharSequence getSuggestionText(int idx) {
CharSequence result = null;
if (idx >= 0) {
if (idx < this.mSuggestions.getChildCount()) {
Button btn = (Button) this.mSuggestions.getChildAt(idx).findViewById(R.id.text);
if (btn != null) {
result = btn.getText();
}
}
}
return var2;
return result;
}
public int getTouchState() {
return this.mTouchState;
return mTouchState;
}
public RelativeLayout getView() {
return this.mRootView;
return mRootView;
}
public boolean isCapsLockOn() {
return this.mMainKeyboardView.getShiftState() == 2;
return mMainKeyboardView.getShiftState() == 2;
}
public boolean isCurrKeyShifted() {
return this.mMainKeyboardView.isShifted();
return mMainKeyboardView.isShifted();
}
public boolean isMiniKeyboardOnScreen() {
return this.mMainKeyboardView.isMiniKeyboardOnScreen();
return mMainKeyboardView.isMiniKeyboardOnScreen();
}
public boolean isVoiceEnabled() {
return this.mVoiceEnabled;
return mVoiceEnabled;
}
public boolean isVoiceVisible() {
return this.mVoiceButtonView.getVisibility() == 0;
return mVoiceButtonView.getVisibility() == View.VISIBLE;
}
public void onInitInputView() {
this.resetFocusCursor();
this.mSelector.setVisibility(View.VISIBLE);
resetFocusCursor();
mSelector.setVisibility(View.VISIBLE);
}
public boolean onKeyLongPress() {
int var1 = this.mCurrKeyInfo.code;
if (var1 == -1) {
this.onToggleCapsLock();
this.setTouchState(0);
int keyCode = mCurrKeyInfo.code;
if (keyCode == LeanbackKeyboardView.KEYCODE_SHIFT) {
onToggleCapsLock();
setTouchState(LeanbackKeyboardContainer.TOUCH_STATE_NO_TOUCH);
return true;
} else if (var1 == 32) {
this.switchToNextKeyboard();
this.setTouchState(0);
} else if (keyCode == LeanbackKeyboardView.ASCII_SPACE) {
onLangKeyPress();
setTouchState(LeanbackKeyboardContainer.TOUCH_STATE_NO_TOUCH);
return true;
} else if (keyCode == LeanbackKeyboardView.KEYCODE_LANG_TOGGLE) {
// NOTE: normal constructor cannot be applied here
new ChooseKeyboardDialog(mContext, mMainKeyboardView).run();
return true;
} else {
if (this.mCurrKeyInfo.type == 0) {
this.mMainKeyboardView.onKeyLongPress();
if (this.mMainKeyboardView.isMiniKeyboardOnScreen()) {
this.mMiniKbKeyIndex = this.mCurrKeyInfo.index;
this.moveFocusToIndex(this.mMainKeyboardView.getBaseMiniKbIndex(), 0);
if (mCurrKeyInfo.type == KeyFocus.TYPE_MAIN) {
mMainKeyboardView.onKeyLongPress();
if (mMainKeyboardView.isMiniKeyboardOnScreen()) {
mMiniKbKeyIndex = mCurrKeyInfo.index;
moveFocusToIndex(mMainKeyboardView.getBaseMiniKbIndex(), KeyFocus.TYPE_MAIN);
return true;
}
}
@@ -1016,6 +1036,10 @@ public class LeanbackKeyboardContainer {
setKbFocus(focus, false, true);
}
public void setFocus(LeanbackKeyboardContainer.KeyFocus focus, final boolean animate) {
setKbFocus(focus, false, animate);
}
public void setSelectorToFocus(Rect rect, boolean overestimateWidth, boolean overestimateHeight, boolean animate) {
if (this.mSelector.getWidth() != 0 && this.mSelector.getHeight() != 0 && rect.width() != 0 && rect.height() != 0) {
final float width = (float) rect.width();
@@ -1102,17 +1126,23 @@ public class LeanbackKeyboardContainer {
* Switch to next keyboard (looped).
* {@link KeyboardManager KeyboardManager} is the source behind all keyboard implementations
*/
public void switchToNextKeyboard() {
public void onLangKeyPress() {
switchToNextKeyboard();
showRunOnceDialog();
}
private void switchToNextKeyboard() {
LeanbackKeyboardView keyboardView = mMainKeyboardView;
Keyboard keyboard = mKeyboardManager.getNextKeyboard();
mInitialMainKeyboard = keyboard;
mAbcKeyboard = keyboard;
keyboardView.setKeyboard(keyboard);
}
public void updateAddonKeyboard() {
KeyboardManager manager = new KeyboardManager(mContext, mAbcKeyboard);
mKeyboardManager = manager;
mInitialMainKeyboard = manager.getNextKeyboard();
mKeyboardManager = new KeyboardManager(mContext);
switchToNextKeyboard();
}
public void updateSuggestions(ArrayList<String> suggestions) {
@@ -1139,6 +1169,25 @@ public class LeanbackKeyboardContainer {
}
}
public void onLangKeyClick() {
onLangKeyPress();
// setTouchState(LeanbackKeyboardContainer.TOUCH_STATE_NO_TOUCH);
}
private void showRunOnceDialog() {
LeanKeyPreferences prefs = LeanKeyPreferences.instance(mContext);
boolean runOnce = prefs.isRunOnce();
if (runOnce) {
return;
}
prefs.setRunOnce(true);
// NOTE: normal constructor cannot be applied here
new ChooseKeyboardDialog(mContext, mMainKeyboardView).run();
}
public interface DismissListener {
void onDismiss(boolean var1);
}

View File

@@ -1,10 +1,11 @@
package com.google.android.leanback.ime;
import android.graphics.PointF;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard.Key;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -29,6 +30,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private static final int KEY_CHANGE_HISTORY_SIZE = 10;
private static final long KEY_CHANGE_REVERT_TIME_MS = 100L;
private static final String TAG = "LbKbController";
public static final String TAG_GO = "Go";
private boolean clickConsumed;
private long lastClickTime;
private LeanbackKeyboardContainer mContainer;
@@ -48,7 +50,10 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private LeanbackKeyboardContainer.KeyFocus mTempFocus;
private PointF mTempPoint;
private LeanbackKeyboardController.TouchEventListener mTouchEventListener;
private long prevTime;
private long mPrevTime;
private boolean mShowInput;
private int mLastEditorIdPhysicalKeyboardWasUsed;
private boolean mHideKeyboardWhenPhysicalKeyboardUsed = true;
public LeanbackKeyboardController(final InputMethodService context, final LeanbackKeyboardController.InputListener listener) {
this(context, listener, new TouchNavSpaceTracker(), new LeanbackKeyboardContainer(context));
@@ -106,7 +111,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private boolean applyLETVFixesUp(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
this.mContainer.switchToNextKeyboard();
this.mContainer.onLangKeyPress();
break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
this.fakeKeyIndex(0, 2);
@@ -149,14 +154,19 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
this.commitKey(this.mContainer.getCurrFocus());
}
/**
* NOTE: where all magic happens. Input from virtual kbd is processed here.
* @param focus current key
*/
private void commitKey(LeanbackKeyboardContainer.KeyFocus focus) {
if (mContainer != null && focus != null) {
switch (focus.type) {
case KeyFocus.TYPE_VOICE:
mContainer.onVoiceClick();
return;
case KeyFocus.TYPE_ACTION:
case KeyFocus.TYPE_ACTION: // NOTE: user presses Go, Send, Search etc
mInputListener.onEntry(InputListener.ENTRY_TYPE_ACTION, 0, null);
// mContext.hideWindow(); // SmartYouTubeTV fix: force hide keyboard
return;
case KeyFocus.TYPE_SUGGESTION:
mInputListener.onEntry(InputListener.ENTRY_TYPE_SUGGESTION, 0, mContainer.getSuggestionText(focus.index));
@@ -284,50 +294,57 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private void handleCommitKeyboardKey(int keyCode, CharSequence text) {
switch (keyCode) {
case LeanbackKeyboardView.KEYCODE_DISMISS_MINI_KEYBOARD:
this.mContainer.dismissMiniKeyboard();
mContainer.dismissMiniKeyboard();
return;
case LeanbackKeyboardView.KEYCODE_VOICE:
this.mContainer.startVoiceRecording();
mContainer.startVoiceRecording();
return;
case LeanbackKeyboardView.KEYCODE_CAPS_LOCK:
this.mContainer.onShiftDoubleClick(this.mContainer.isCapsLockOn());
mContainer.onShiftDoubleClick(mContainer.isCapsLockOn());
return;
case LeanbackKeyboardView.KEYCODE_DELETE:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_BACKSPACE, LeanbackKeyboardView.SHIFT_OFF, null);
mInputListener.onEntry(InputListener.ENTRY_TYPE_BACKSPACE, LeanbackKeyboardView.SHIFT_OFF, null);
return;
case LeanbackKeyboardView.KEYCODE_RIGHT:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_RIGHT, LeanbackKeyboardView.SHIFT_OFF, null);
mInputListener.onEntry(InputListener.ENTRY_TYPE_RIGHT, LeanbackKeyboardView.SHIFT_OFF, null);
return;
case LeanbackKeyboardView.KEYCODE_LEFT:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_LEFT, LeanbackKeyboardView.SHIFT_OFF, null);
mInputListener.onEntry(InputListener.ENTRY_TYPE_LEFT, LeanbackKeyboardView.SHIFT_OFF, null);
return;
case LeanbackKeyboardView.KEYCODE_SYM_TOGGLE:
if (Log.isLoggable("LbKbController", Log.DEBUG)) {
Log.d("LbKbController", "mode change");
}
this.mContainer.onModeChangeClick();
mContainer.onModeChangeClick();
return;
case LeanbackKeyboardView.KEYCODE_SHIFT:
if (Log.isLoggable("LbKbController", Log.DEBUG)) {
Log.d("LbKbController", "shift");
}
this.mContainer.onShiftClick();
mContainer.onShiftClick();
return;
case LeanbackKeyboardView.ASCII_SPACE:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, " ");
this.mContainer.onSpaceEntry();
mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, " ");
mContainer.onSpaceEntry();
return;
case LeanbackKeyboardView.ASCII_PERIOD:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, text);
this.mContainer.onPeriodEntry();
mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, text);
mContainer.onPeriodEntry();
return;
case LeanbackKeyboardView.KEYCODE_LANG_TOGGLE:
if (Log.isLoggable("LbKbController", Log.DEBUG)) {
Log.d("LbKbController", "language change");
}
mContainer.onLangKeyClick();
return;
default:
this.mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, text);
this.mContainer.onTextEntry();
if (this.mContainer.isMiniKeyboardOnScreen()) {
this.mContainer.dismissMiniKeyboard();
mInputListener.onEntry(InputListener.ENTRY_TYPE_STRING, keyCode, text);
mContainer.onTextEntry();
if (mContainer.isMiniKeyboardOnScreen()) {
mContainer.dismissMiniKeyboard();
}
}
@@ -349,16 +366,16 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
handled = true;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
handled = onDirectionalMove(8);
handled = onDirectionalMove(LeanbackKeyboardContainer.DIRECTION_UP);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
handled = onDirectionalMove(2);
handled = onDirectionalMove(LeanbackKeyboardContainer.DIRECTION_DOWN);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
handled = onDirectionalMove(1);
handled = onDirectionalMove(LeanbackKeyboardContainer.DIRECTION_LEFT);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
handled = onDirectionalMove(4);
handled = onDirectionalMove(LeanbackKeyboardContainer.DIRECTION_RIGHT);
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
@@ -366,7 +383,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
mMoveCount = 0;
mKeyDownKeyFocus = new LeanbackKeyboardContainer.KeyFocus();
mKeyDownKeyFocus.set(mContainer.getCurrFocus());
} else if (eventRepeatCount == 1 && handleKeyLongPress(keyCode)) {
} else if (eventRepeatCount == 1 && handleKeyLongPress(keyCode)) { // space long press handler and others
mKeyDownKeyFocus = null;
}
@@ -425,7 +442,8 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private boolean handleKeyUpEvent(int keyCode, long currTime) {
keyCode = getSimplifiedKey(keyCode);
boolean handled;
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
handled = false;
} else if (mContainer.isVoiceVisible()) {
handled = true;
@@ -481,15 +499,39 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
updatePositionToCurrentFocus();
}
private boolean isCallAllowed(int periodMillis) {
/**
* Simple throttle routine.
* @param callInterval interval
* @return is allowed
*/
private boolean isCallAllowedOrigin(int callInterval) {
long currTimeMS = System.currentTimeMillis();
if (this.prevTime != 0L && currTimeMS - this.prevTime <= (long) (periodMillis * 3)) {
if (currTimeMS - this.prevTime > (long) periodMillis) {
this.prevTime = 0L;
long timeDelta = currTimeMS - mPrevTime;
if (mPrevTime != 0 && timeDelta <= (callInterval * 3)) {
if (timeDelta > callInterval) {
mPrevTime = 0;
return true;
}
} else {
this.prevTime = currTimeMS;
mPrevTime = currTimeMS;
}
return false;
}
/**
* Simple throttle routine. Simplified comparing to previous. Not tested yet!!!!
* @param interval interval
* @return is allowed
*/
private boolean isCallAllowed2(int interval) {
long currTimeMS = System.currentTimeMillis();
long timeDelta = currTimeMS - mPrevTime;
if (mPrevTime == 0) {
mPrevTime = currTimeMS;
return true;
} else if (timeDelta > interval) {
mPrevTime = 0;
}
return false;
@@ -521,20 +563,17 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
}
private void moveSelectorToPoint(float x, float y) {
LeanbackKeyboardContainer container = this.mContainer;
LeanbackKeyboardContainer.KeyFocus focus = this.mTempFocus;
container.getBestFocus(new Float(x), new Float(y), focus);
this.mContainer.setFocus(this.mTempFocus);
container = this.mContainer;
Rect rect = this.mTempFocus.rect;
container.alignSelector((float) rect.centerX(), (float) rect.centerY(), false);
LeanbackKeyboardContainer container = mContainer;
LeanbackKeyboardContainer.KeyFocus focus = mTempFocus;
container.getBestFocus(x, y, focus);
mContainer.setFocus(mTempFocus, false);
}
private boolean onDirectionalMove(int dir) {
if (this.mContainer.getNextFocusInDirection(dir, this.mDownFocus, this.mTempFocus)) {
this.mContainer.setFocus(this.mTempFocus);
this.mDownFocus.set(this.mTempFocus);
this.clearKeyIfNecessary();
if (mContainer.getNextFocusInDirection(dir, mDownFocus, mTempFocus)) {
mContainer.setFocus(mTempFocus);
mDownFocus.set(mTempFocus);
clearKeyIfNecessary();
}
return true;
@@ -595,7 +634,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
Button button = mContainer.getGoButton();
button.setOnTouchListener(this);
button.setOnHoverListener(this);
button.setTag("Go");
button.setTag(TAG_GO);
return view;
} else {
return null;
@@ -609,27 +648,27 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
mInputListener.onEntry(InputListener.ENTRY_TYPE_DISMISS, LeanbackKeyboardView.SHIFT_OFF, null);
}
}
public boolean onGenericMotionEvent(MotionEvent event) {
return mSpaceTracker != null && mContext != null && mContext.isInputViewShown() && mSpaceTracker.onGenericMotionEvent(event);
}
/**
* Try to handle on hover event
* Control keyboard from the mouse. Movement catching
* @param view active view
* @param event event object
* @return is hover handled
*/
@Override
public boolean onHover(View view, MotionEvent event) {
boolean allowed = isCallAllowed(300);
if (allowed) {
if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
PointF pos = getRelativePosition(mContainer.getView(), event);
moveSelectorToPoint(pos.x, pos.y);
}
boolean handled = false;
if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
PointF pos = getRelativePosition(mContainer.getView(), event);
moveSelectorToPoint(pos.x, pos.y);
handled = true;
}
return allowed;
return handled;
}
/**
@@ -638,86 +677,131 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
* @param event {@link KeyEvent KeyEvent}
* @return is event handled
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
this.mDownFocus.set(this.mContainer.getCurrFocus());
if (this.mSpaceTracker != null && this.mSpaceTracker.onKeyDown(keyCode, event)) {
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
//greater than zero means it is a physical keyboard.
//we also want to hide the view if it's a glyph (for example, not physical volume-up key)
//if (event.getDeviceId() > 0 && event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
if (event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
mDownFocus.set(mContainer.getCurrFocus());
if (mSpaceTracker != null && mSpaceTracker.onKeyDown(keyCode, event)) {
return true;
} else {
if (this.isEnterKey(keyCode)) {
this.mKeyDownReceived = true;
if (isEnterKey(keyCode)) {
mKeyDownReceived = true;
if (event.getRepeatCount() == 0) {
this.mContainer.setTouchState(LeanbackKeyboardContainer.TOUCH_STATE_CLICK);
mContainer.setTouchState(LeanbackKeyboardContainer.TOUCH_STATE_CLICK);
}
}
return this.handleKeyDownEvent(keyCode, event.getRepeatCount());
return handleKeyDownEvent(keyCode, event.getRepeatCount());
}
}
public boolean onKeyUp(int var1, KeyEvent var2) {
if (this.mSpaceTracker != null && this.mSpaceTracker.onKeyUp(var1, var2)) {
private void onPhysicalKeyboardKeyPressed() {
EditorInfo editorInfo = mContext.getCurrentInputEditorInfo();
mLastEditorIdPhysicalKeyboardWasUsed = editorInfo == null ? 0 : editorInfo.fieldId;
if (mHideKeyboardWhenPhysicalKeyboardUsed) {
mContext.hideWindow();
}
// For all other keys, if we want to do transformations on
// text being entered with a hard keyboard, we need to process
// it and do the appropriate action.
// using physical keyboard is more annoying with candidate view in
// the way
// so we disable it.
// stopping any soft-keyboard prediction
//abortCorrectionAndResetPredictionState(false);
}
public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
if (mSpaceTracker != null && mSpaceTracker.onKeyUp(keyCode, keyEvent)) {
return true;
} else {
if (this.isEnterKey(var1)) {
if (!this.mKeyDownReceived || this.mLongPressHandled) {
this.mLongPressHandled = false;
if (isEnterKey(keyCode)) {
if (!mKeyDownReceived || mLongPressHandled) {
mLongPressHandled = false;
return true;
}
this.mKeyDownReceived = false;
if (this.mContainer.getTouchState() == 3) {
this.mContainer.setTouchState(1);
mKeyDownReceived = false;
if (mContainer.getTouchState() == 3) {
mContainer.setTouchState(1);
}
}
return this.handleKeyUpEvent(var1, var2.getEventTime());
return handleKeyUpEvent(keyCode, keyEvent.getEventTime());
}
}
public void onStartInput(EditorInfo var1) {
if (this.mContainer != null) {
this.mContainer.onStartInput(var1);
this.initInputView();
public void onStartInput(EditorInfo info) {
if (mContainer != null) {
mContainer.onStartInput(info);
initInputView();
}
//// prevent accidental kbd pop-up on FireTV devices
//// more info: https://forum.xda-developers.com/fire-tv/general/guide-change-screen-keyboard-to-leankey-t3527675/page2
//int maskAction = info.imeOptions & EditorInfo.IME_MASK_ACTION;
//mShowInput = maskAction != 0;
mShowInput = info.inputType != InputType.TYPE_NULL;
}
public boolean showInputView() {
return mShowInput;
}
private void onHideIme() {
mContext.requestHideSelf(InputMethodService.BACK_DISPOSITION_DEFAULT);
}
public void onStartInputView() {
this.mKeyDownReceived = false;
if (this.mContainer != null) {
this.mContainer.onStartInputView();
mKeyDownReceived = false;
if (mContainer != null) {
mContainer.onStartInputView();
}
this.mDoubleClickDetector.reset();
mDoubleClickDetector.reset();
}
@Override
public boolean onTouch(View view, MotionEvent event) {
Object tag = view.getTag();
if (tag != null && "Go".equals(tag)) {
fakeKeyIndex(0, KeyFocus.TYPE_ACTION);
} else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
moveSelectorToPoint(event.getX(), event.getY());
fakeClickDown();
beginLongClickCountdown();
boolean isEnterKey = TAG_GO.equals(tag);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isEnterKey) {
break;
case MotionEvent.ACTION_UP:
if (!clickConsumed) {
clickConsumed = true;
if (isDoubleClick()) {
mContainer.onKeyLongPress();
break;
}
}
fakeClickUp();
moveSelectorToPoint(event.getX(), event.getY());
fakeClickDown();
beginLongClickCountdown();
break;
case MotionEvent.ACTION_UP:
if (isEnterKey) {
fakeKeyIndex(0, KeyFocus.TYPE_ACTION);
break;
}
if (!clickConsumed) {
clickConsumed = true;
if (isDoubleClick()) {
mContainer.onKeyLongPress();
break;
}
fakeLongClickUp();
break;
default:
return false;
}
fakeClickUp();
}
fakeLongClickUp();
break;
default:
return false;
}
return true;

View File

@@ -24,7 +24,14 @@ import java.util.Iterator;
import java.util.List;
public class LeanbackKeyboardView extends FrameLayout {
public static final int ASCII_PERIOD = 46;
/**
* space key index (important: wrong value will broke navigation)
*/
public static final int ASCII_PERIOD = 47;
/**
* keys count among which space key spans (important: wrong value will broke navigation)
*/
public static final int ASCII_PERIOD_LEN = 6;
public static final int ASCII_SPACE = 32;
private static final boolean DEBUG = false;
public static final int KEYCODE_CAPS_LOCK = -6;
@@ -35,6 +42,7 @@ public class LeanbackKeyboardView extends FrameLayout {
public static final int KEYCODE_SHIFT = -1;
public static final int KEYCODE_SYM_TOGGLE = -2;
public static final int KEYCODE_VOICE = -7;
public static final int KEYCODE_LANG_TOGGLE = -9;
private static final int NOT_A_KEY = -1;
public static final int SHIFT_LOCKED = 2;
public static final int SHIFT_OFF = 0;
@@ -61,6 +69,56 @@ public class LeanbackKeyboardView extends FrameLayout {
private int mRowCount;
private int mShiftState;
private final int mUnfocusStartDelay;
private final KeyConverter mConverter;
private class KeyConverter {
private static final int LOWER_CASE = 0;
private static final int UPPER_CASE = 1;
private void init(KeyHolder keyHolder) {
// store original label
// in case when two characters are stored in one label (e.g. "A|B")
if (keyHolder.key.text == null) {
keyHolder.key.text = keyHolder.key.label;
}
}
public void toLowerCase(KeyHolder keyHolder) {
extractChar(LOWER_CASE, keyHolder);
}
public void toUpperCase(KeyHolder keyHolder) {
extractChar(UPPER_CASE, keyHolder);
}
private void extractChar(int charCase, KeyHolder keyHolder) {
init(keyHolder);
CharSequence result = null;
CharSequence label = keyHolder.key.text;
String[] labels = splitLabels(label);
switch (charCase) {
case LOWER_CASE:
result = labels != null ? labels[0] : label.toString().toLowerCase();
break;
case UPPER_CASE:
result = labels != null ? labels[1] : label.toString().toUpperCase();
break;
}
keyHolder.key.label = result;
}
private String[] splitLabels(CharSequence label) {
String realLabel = label.toString();
String[] labels = realLabel.split("\\|");
return labels.length == 2 ? labels : null; // remember, we encoding two chars
}
}
public LeanbackKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -84,29 +142,24 @@ public class LeanbackKeyboardView extends FrameLayout {
mClickAnimDur = res.getInteger(R.integer.clicked_anim_duration);
mUnfocusStartDelay = res.getInteger(R.integer.unfocused_anim_delay);
mInactiveMiniKbAlpha = res.getInteger(R.integer.inactive_mini_kb_alpha);
mConverter = new KeyConverter();
}
private CharSequence adjustCase(LeanbackKeyboardView.KeyHolder keyHolder) {
CharSequence label = keyHolder.key.label;
CharSequence result = label;
if (label != null && label.length() < 3) {
boolean flag;
if (keyHolder.isInMiniKb && keyHolder.isInvertible) {
flag = true;
} else {
flag = false;
}
private void adjustCase(LeanbackKeyboardView.KeyHolder keyHolder) {
boolean flag;
if (this.mKeyboard.isShifted() ^ flag) {
result = label.toString().toUpperCase();
} else {
result = label.toString().toLowerCase();
}
keyHolder.key.label = result;
if (keyHolder.isInMiniKb && keyHolder.isInvertible) {
flag = true;
} else {
flag = false;
}
return result;
// ^ equals to !=
if (mKeyboard.isShifted() ^ flag) {
mConverter.toUpperCase(keyHolder);
} else {
mConverter.toLowerCase(keyHolder);
}
}
@SuppressLint("NewApi")
@@ -260,6 +313,8 @@ public class LeanbackKeyboardView extends FrameLayout {
/**
* Get index of the key under cursor
* <br/>
* Resulted index depends on the space key position
* @param x x position
* @param y y position
* @return index of the key
@@ -296,16 +351,16 @@ public class LeanbackKeyboardView extends FrameLayout {
indexFull += mColCount * result;
result = indexFull;
if (indexFull > ASCII_PERIOD) {
if (indexFull > ASCII_PERIOD) { // key goes beyond space
result = indexFull;
if (indexFull < 53) {
if (indexFull < (ASCII_PERIOD + ASCII_PERIOD_LEN)) { // key stays within space boundary
result = ASCII_PERIOD;
}
}
indexFull = result;
if (result >= 53) {
indexFull = result - 6;
if (result >= (ASCII_PERIOD + ASCII_PERIOD_LEN)) { // is key position after space?
indexFull = result - ASCII_PERIOD_LEN + 1;
}
if (indexFull < 0) {
@@ -468,8 +523,12 @@ public class LeanbackKeyboardView extends FrameLayout {
}
mCurrentFocusView = mKeyImageViews[indexFull];
mCurrentFocusView.animate().scaleX(scale).scaleY(scale).setInterpolator(LeanbackKeyboardContainer.sMovementInterpolator)
.setDuration((long) mClickAnimDur).start();
mCurrentFocusView.animate()
.scaleX(scale)
.scaleY(scale)
.setInterpolator(LeanbackKeyboardContainer.sMovementInterpolator)
.setDuration((long) mClickAnimDur)
.start();
}
mFocusIndex = indexFull;

View File

@@ -1,6 +1,7 @@
package com.google.leanback.ime;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.os.Handler;
@@ -18,6 +19,7 @@ import com.google.android.leanback.ime.LeanbackKeyboardController.InputListener;
import com.google.android.leanback.ime.LeanbackKeyboardView;
import com.google.android.leanback.ime.LeanbackSuggestionsFactory;
import com.google.android.leanback.ime.LeanbackUtils;
import com.liskovsoft.utils.LangUpdater;
public class LeanbackImeService extends InputMethodService {
private static final boolean DEBUG = false;
@@ -53,10 +55,17 @@ public class LeanbackImeService extends InputMethodService {
@SuppressLint("NewApi")
public LeanbackImeService() {
if (!this.enableHardwareAcceleration()) {
if (!enableHardwareAcceleration()) {
Log.w("LbImeService", "Could not enable hardware acceleration");
}
}
@Override
public void onCreate() {
super.onCreate();
LangUpdater langUpdater = new LangUpdater(this);
langUpdater.update();
}
private void clearSuggestionsDelayed() {
@@ -153,8 +162,15 @@ public class LeanbackImeService extends InputMethodService {
connection.commitText(text, 1);
mEnterSpaceBeforeCommitting = true;
case InputListener.ENTRY_TYPE_ACTION:
sendDefaultEditorAction(false);
case InputListener.ENTRY_TYPE_ACTION: // NOTE: user presses Go, Send, Search etc
boolean result = sendDefaultEditorAction(true);
if (result) {
hideWindow(); // NOTE: SmartYouTubeTV hide kbd on search page fix
} else {
sendEnterKey(connection);
}
updateSuggestions = false;
break;
case InputListener.ENTRY_TYPE_LEFT:
@@ -202,6 +218,10 @@ public class LeanbackImeService extends InputMethodService {
}
}
private void sendEnterKey(InputConnection connection) {
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
}
@Override
public View onCreateInputView() {
mInputView = mKeyboardController.getView();
@@ -225,15 +245,19 @@ public class LeanbackImeService extends InputMethodService {
return false;
}
/**
* At this point, decision whether to show kbd taking place
* @return whether to show kbd
*/
@SuppressLint("MissingSuperCall")
@Override
public boolean onEvaluateInputViewShown() {
return true;
return mKeyboardController.showInputView();
}
@Override
public void onFinishInputView(boolean var1) {
super.onFinishInputView(var1);
public void onFinishInputView(boolean finishingInput) {
super.onFinishInputView(finishingInput);
this.sendBroadcast(new Intent(IME_CLOSE));
this.mSuggestionsFactory.clearSuggestions();
}
@@ -247,7 +271,7 @@ public class LeanbackImeService extends InputMethodService {
}
public void onHideIme() {
this.requestHideSelf(0);
requestHideSelf(InputMethodService.BACK_DISPOSITION_DEFAULT);
}
@Override
@@ -259,19 +283,45 @@ public class LeanbackImeService extends InputMethodService {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// NOTE: hide keyboard on ESC key
// https://github.com/yuliskov/SmartYouTubeTV/issues/142
event = mapEscToBack(event);
keyCode = mapEscToBack(keyCode);
return isInputViewShown() && mKeyboardController.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// NOTE: hide keyboard on ESC key
// https://github.com/yuliskov/SmartYouTubeTV/issues/142
event = mapEscToBack(event);
keyCode = mapEscToBack(keyCode);
return isInputViewShown() && mKeyboardController.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
}
@Override
public boolean onShowInputRequested(int flags, boolean configChange) {
return true;
private KeyEvent mapEscToBack(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE) {
// pay attention, you must pass the same action
event = new KeyEvent(event.getAction(), KeyEvent.KEYCODE_BACK);
}
return event;
}
private int mapEscToBack(int keyCode) {
if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
keyCode = KeyEvent.KEYCODE_BACK;
}
return keyCode;
}
// FireTV fix
//@Override
//public boolean onShowInputRequested(int flags, boolean configChange) {
// return true;
//}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if (intent != null) {
@@ -285,7 +335,7 @@ public class LeanbackImeService extends InputMethodService {
}
}
return 1;
return Service.START_STICKY;
}
@Override
@@ -299,6 +349,15 @@ public class LeanbackImeService extends InputMethodService {
@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
super.onStartInputView(info, restarting);
// FireTV: fix accidental kbd pop-ups
// more info: https://forum.xda-developers.com/fire-tv/general/guide-change-screen-keyboard-to-leankey-t3527675/page2
updateInputViewShown();
if (!mKeyboardController.showInputView()) {
onHideIme();
return;
}
mKeyboardController.onStartInputView();
sendBroadcast(new Intent(IME_OPEN));
if (mKeyboardController.areSuggestionsEnabled()) {

View File

@@ -1,77 +0,0 @@
//
// Decompiled by Procyon v0.5.30
//
package com.liskovsoft.inputchooser;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.widget.Toast;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ActivityInfo;
import android.content.Intent;
import android.app.Activity;
public class SettingsActivity extends Activity
{
@SuppressLint("WrongConstant")
private void addIntentFlags(final Intent intent) {
intent.addFlags(67108864);
intent.addFlags(536870912);
}
@SuppressLint("WrongConstant")
private ActivityInfo getCurrentActivityInfo() {
try {
return this.getPackageManager().getActivityInfo(this.getComponentName(), 129);
}
catch (NameNotFoundException ex) {
ex.printStackTrace();
this.makeLongToast(ex.getLocalizedMessage(), 10);
return null;
}
}
private void launchApp() {
final Intent intent = this.makeIntent(this.getCurrentActivityInfo());
this.addIntentFlags(intent);
this.startIntent(intent);
this.finish();
}
private Intent makeIntent(final ActivityInfo activityInfo) {
final Bundle metaData = activityInfo.metaData;
final Intent intent = new Intent();
if (metaData.getString("intent") != null) {
intent.setAction(metaData.getString("intent"));
return intent;
}
intent.setComponent(new ComponentName(metaData.getString("package"), metaData.getString("class")));
return intent;
}
private void makeLongToast(final String s, int i) {
int n;
for (n = i / 2, i = 0; i < n; ++i) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
private void startIntent(final Intent intent) {
try {
this.startActivity(intent);
}
catch (ActivityNotFoundException ex) {
ex.printStackTrace();
this.makeLongToast(ex.getLocalizedMessage(), 10);
}
}
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
this.launchApp();
}
}

View File

@@ -0,0 +1,9 @@
package com.liskovsoft.keyboardaddons;
import android.inputmethodservice.Keyboard;
import android.support.annotation.Nullable;
public interface KeyboardBuilder {
@Nullable
Keyboard createKeyboard();
}

View File

@@ -0,0 +1,10 @@
package com.liskovsoft.keyboardaddons;
import android.content.Context;
import java.util.List;
public interface KeyboardFactory {
List<? extends KeyboardBuilder> getAllAvailableKeyboards(Context context);
boolean needUpdate();
}

View File

@@ -0,0 +1,10 @@
package com.liskovsoft.keyboardaddons;
public interface KeyboardInfo {
boolean isEnabled();
String getLangCode();
String getLangName();
void setLangName(String langName);
void setLangCode(String langCode);
void setEnabled(boolean enabled);
}

View File

@@ -2,50 +2,59 @@ package com.liskovsoft.keyboardaddons;
import android.content.Context;
import android.inputmethodservice.Keyboard;
import com.liskovsoft.keyboardaddons.apklangfactory.keyboards.KeyboardAddOnAndBuilder;
import com.liskovsoft.keyboardaddons.apklangfactory.keyboards.ApkLangKeyboardFactory;
import com.liskovsoft.keyboardaddons.reskbdfactory.ResKeyboardFactory;
import java.util.ArrayList;
import java.util.List;
public class KeyboardManager {
private final Keyboard mEnglishKeyboard;
private final Context mContext;
private final List<KeyboardAddOnAndBuilder> mKeyboardBuilders;
private final List<Keyboard> mAllKeyboards;
private final ApkLangKeyboardFactory mKeyboardFactory;
private final KeyboardStateManager mStateManager;
private List<? extends KeyboardBuilder> mKeyboardBuilders;
private List<Keyboard> mAllKeyboards;
private KeyboardFactory mKeyboardFactory;
private int mKeyboardIndex = 0;
public KeyboardManager(Context ctx, int keyboardResId) {
this(ctx, new Keyboard(ctx, keyboardResId));
public KeyboardManager(Context ctx) {
mContext = ctx;
mStateManager = new KeyboardStateManager(mContext, this);
mStateManager.restore();
init();
}
public KeyboardManager(Context ctx, Keyboard englishKeyboard) {
mContext = ctx;
mEnglishKeyboard = englishKeyboard;
mKeyboardFactory = new ApkLangKeyboardFactory();
private void init() {
mKeyboardFactory = new ResKeyboardFactory(mContext);
mKeyboardBuilders = mKeyboardFactory.getAllAvailableKeyboards(mContext);
mAllKeyboards = buildAllKeyboards();
}
private List<Keyboard> buildAllKeyboards() {
List<Keyboard> keyboards = new ArrayList<>();
keyboards.add(mEnglishKeyboard);
if (!mKeyboardBuilders.isEmpty()) {
for (KeyboardAddOnAndBuilder builder : mKeyboardBuilders) {
for (KeyboardBuilder builder : mKeyboardBuilders) {
keyboards.add(builder.createKeyboard());
}
}
return keyboards;
}
/**
* Performs callback to event handlers
*/
private void onNextKeyboard() {
mStateManager.onNextKeyboard();
}
/**
* Get next keyboard from internal source (looped)
* @return keyboard
*/
public Keyboard getNextKeyboard() {
++mKeyboardIndex;
if (mKeyboardFactory.needUpdate()) {
init();
}
mKeyboardIndex = mKeyboardIndex < mAllKeyboards.size() ? mKeyboardIndex : 0;
Keyboard kbd = mAllKeyboards.get(mKeyboardIndex);
@@ -53,6 +62,18 @@ public class KeyboardManager {
throw new IllegalStateException(String.format("Keyboard %s not initialized", mKeyboardIndex));
}
onNextKeyboard();
++mKeyboardIndex;
return kbd;
}
public int getKeyboardIndex() {
return mKeyboardIndex;
}
public void setKeyboardIndex(int idx) {
mKeyboardIndex = idx;
}
}

View File

@@ -0,0 +1,25 @@
package com.liskovsoft.keyboardaddons;
import android.content.Context;
import com.liskovsoft.utils.LeanKeyPreferences;
public class KeyboardStateManager {
private final Context mContext;
private final KeyboardManager mManager;
private final LeanKeyPreferences mPrefs;
public KeyboardStateManager(Context context, KeyboardManager manager) {
mContext = context;
mManager = manager;
mPrefs = LeanKeyPreferences.instance(mContext);
}
public void restore() {
int idx = mPrefs.getKeyboardIndex();
mManager.setKeyboardIndex(idx);
}
public void onNextKeyboard() {
mPrefs.setKeyboardIndex(mManager.getKeyboardIndex());
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.addons;
package com.liskovsoft.keyboardaddons.apkkbdfactory.addons;
import android.content.Context;
import android.support.annotation.NonNull;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.addons;
package com.liskovsoft.keyboardaddons.apkkbdfactory.addons;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -23,7 +23,7 @@ import android.support.annotation.Nullable;
import android.support.v4.util.SparseArrayCompat;
import android.util.SparseIntArray;
import com.liskovsoft.keyboardaddons.apklangfactory.utils.Logger;
import com.liskovsoft.keyboardaddons.apkkbdfactory.utils.Logger;
import java.lang.ref.WeakReference;
import java.util.Arrays;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.addons;
package com.liskovsoft.keyboardaddons.apkkbdfactory.addons;
import android.content.Context;
import android.content.Intent;
@@ -27,7 +27,7 @@ import android.util.AttributeSet;
import android.util.Xml;
//import com.liskovsoft.keyboardaddons.apklangfactory.AnySoftKeyboard;
import com.liskovsoft.keyboardaddons.apklangfactory.utils.Logger;
import com.liskovsoft.keyboardaddons.apkkbdfactory.utils.Logger;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -67,24 +67,6 @@ public abstract class AddOnsFactory<E extends AddOn> {
private static final String sTAG = "AddOnsFactory";
//public static void onPackageChanged(final Intent eventIntent, final AnySoftKeyboard ask) {
// boolean cleared = false;
// boolean recreateView = false;
// for (AddOnsFactory<?> factory : mActiveInstances) {
// try {
// if (factory.isEventRequiresCacheRefresh(eventIntent, ask.getApplicationContext())) {
// cleared = true;
// if (factory.isEventRequiresViewReset(eventIntent, ask.getApplicationContext())) recreateView = true;
// Logger.d(sTAG, factory.getClass().getName() + " will handle this package-changed event. Also recreate view? " + recreateView);
// factory.clearAddOnList();
// }
// } catch (NameNotFoundException e) {
// e.printStackTrace();
// }
// }
// if (cleared) ask.resetKeyboardView(recreateView);
//}
public static AddOn locateAddOn(String id, Context askContext) {
for (AddOnsFactory<?> factory : mActiveInstances) {
AddOn addOn = factory.getAddOnById(id, askContext);

View File

@@ -1,11 +1,11 @@
package com.liskovsoft.keyboardaddons.apklangfactory.addons;
package com.liskovsoft.keyboardaddons.apkkbdfactory.addons;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.util.SparseIntArray;
import com.liskovsoft.keyboardaddons.apklangfactory.utils.Logger;
import com.liskovsoft.keyboardaddons.apkkbdfactory.utils.Logger;
import java.util.ArrayList;
import java.util.List;

View File

@@ -14,36 +14,36 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.keyboards;
package com.liskovsoft.keyboardaddons.apkkbdfactory.keyboards;
import android.content.Context;
import android.support.annotation.Nullable;
import com.liskovsoft.keyboardaddons.apklangfactory.addons.AddOn;
import com.liskovsoft.keyboardaddons.apklangfactory.addons.AddOnImpl;
import com.liskovsoft.keyboardaddons.KeyboardBuilder;
import com.liskovsoft.keyboardaddons.apkkbdfactory.addons.AddOn;
import com.liskovsoft.keyboardaddons.apkkbdfactory.addons.AddOnImpl;
public class KeyboardAddOnAndBuilder extends AddOnImpl {
public class ApkKeyboardAddOnAndBuilder extends AddOnImpl implements KeyboardBuilder {
public static final String KEYBOARD_PREF_PREFIX = "keyboard_";
private final int mResId;
private final int mLandscapeResId;
//private final int mIconResId;
private final String mDefaultDictionary;
private final int mQwertyTranslationId;
private final String mAdditionalIsLetterExceptions;
private final String mSentenceSeparators;
private final boolean mKeyboardDefaultEnabled;
public KeyboardAddOnAndBuilder(Context askContext, Context packageContext, String id, int nameResId,
int layoutResId, int landscapeLayoutResId,
String defaultDictionary, int iconResId,
int physicalTranslationResId,
String additionalIsLetterExceptions,
String sentenceSeparators,
String description,
int keyboardIndex,
boolean keyboardDefaultEnabled) {
public ApkKeyboardAddOnAndBuilder(Context askContext, Context packageContext, String id, int nameResId,
int layoutResId, int landscapeLayoutResId,
String defaultDictionary, int iconResId,
int physicalTranslationResId,
String additionalIsLetterExceptions,
String sentenceSeparators,
String description,
int keyboardIndex,
boolean keyboardDefaultEnabled) {
super(askContext, packageContext, KEYBOARD_PREF_PREFIX + id, nameResId, description, keyboardIndex);
mResId = layoutResId;
@@ -74,16 +74,10 @@ public class KeyboardAddOnAndBuilder extends AddOnImpl {
}
@Nullable
@Override
public android.inputmethodservice.Keyboard createKeyboard() {
Context remoteContext = getPackageContext();
if (remoteContext == null) return null;
return new android.inputmethodservice.Keyboard(remoteContext, mLandscapeResId);
}
//@Nullable
//public android.inputmethodservice.Keyboard createKeyboard(Context askContext, @Keyboard.KeyboardRowModeId int mode) {
// Context remoteContext = getPackageContext();
// if (remoteContext == null) return null;
// return new ExternalAnyKeyboard(this, askContext, remoteContext, mResId, mLandscapeResId, getId(), getName(), mIconResId, mQwertyTranslationId, mDefaultDictionary, mAdditionalIsLetterExceptions, mSentenceSeparators, mode);
//}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.keyboards;
package com.liskovsoft.keyboardaddons.apkkbdfactory.keyboards;
import android.content.Context;
import android.content.SharedPreferences;
@@ -23,15 +23,17 @@ import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import com.liskovsoft.keyboardaddons.apklangfactory.addons.AddOn;
import com.liskovsoft.keyboardaddons.apklangfactory.addons.AddOnsFactory;
import com.liskovsoft.keyboardaddons.apklangfactory.utils.Logger;
import com.liskovsoft.keyboardaddons.KeyboardBuilder;
import com.liskovsoft.keyboardaddons.KeyboardFactory;
import com.liskovsoft.keyboardaddons.apkkbdfactory.addons.AddOn;
import com.liskovsoft.keyboardaddons.apkkbdfactory.addons.AddOnsFactory;
import com.liskovsoft.keyboardaddons.apkkbdfactory.utils.Logger;
import java.util.ArrayList;
import java.util.List;
public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilder> {
public class ApkLangKeyboardFactory extends AddOnsFactory<ApkKeyboardAddOnAndBuilder> implements KeyboardFactory {
private static final String TAG = "ASK_KF";
private static final String XML_LAYOUT_RES_ID_ATTRIBUTE = "layoutResId";
@@ -50,20 +52,27 @@ public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilde
0, true);
}
public List<KeyboardAddOnAndBuilder> getAllAvailableKeyboards(Context askContext) {
return getAllAddOns(askContext);
@Override
public List<? extends KeyboardBuilder> getAllAvailableKeyboards(Context context) {
return getAllAddOns(context);
}
public List<KeyboardAddOnAndBuilder> getEnabledKeyboards(Context askContext) {
final List<KeyboardAddOnAndBuilder> allAddOns = getAllAddOns(askContext);
@Override
public boolean needUpdate() {
// TODO: implement need update
return false;
}
public List<ApkKeyboardAddOnAndBuilder> getEnabledKeyboards(Context askContext) {
final List<ApkKeyboardAddOnAndBuilder> allAddOns = getAllAddOns(askContext);
Logger.i(TAG, "Creating enabled addons list. I have a total of " + allAddOns.size() + " addons");
//getting shared prefs to determine which to create.
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(askContext);
final ArrayList<KeyboardAddOnAndBuilder> enabledAddOns = new ArrayList<>();
final ArrayList<ApkKeyboardAddOnAndBuilder> enabledAddOns = new ArrayList<>();
for (int addOnIndex = 0; addOnIndex < allAddOns.size(); addOnIndex++) {
final KeyboardAddOnAndBuilder addOn = allAddOns.get(addOnIndex);
final ApkKeyboardAddOnAndBuilder addOn = allAddOns.get(addOnIndex);
final boolean addOnEnabled = sharedPreferences.getBoolean(addOn.getId(), addOn.getKeyboardDefaultEnabled());
@@ -76,13 +85,13 @@ public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilde
// Check if there is any keyboards created if not, lets create a default english keyboard
if (enabledAddOns.size() == 0) {
final SharedPreferences.Editor editor = sharedPreferences.edit();
final KeyboardAddOnAndBuilder addOn = allAddOns.get(0);
final ApkKeyboardAddOnAndBuilder addOn = allAddOns.get(0);
editor.putBoolean(addOn.getId(), true);
editor.commit();
enabledAddOns.add(addOn);
}
for (final KeyboardAddOnAndBuilder addOn : enabledAddOns) {
for (final ApkKeyboardAddOnAndBuilder addOn : enabledAddOns) {
Logger.d(TAG, "Factory provided addon: %s", addOn.getId());
}
@@ -90,7 +99,7 @@ public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilde
}
@Override
protected KeyboardAddOnAndBuilder createConcreteAddOn(Context askContext, Context context, String prefId, int nameId, String description, int sortIndex, AttributeSet attrs) {
protected ApkKeyboardAddOnAndBuilder createConcreteAddOn(Context askContext, Context context, String prefId, int nameId, String description, int sortIndex, AttributeSet attrs) {
final int layoutResId = attrs.getAttributeResourceValue(null, XML_LAYOUT_RES_ID_ATTRIBUTE, AddOn.INVALID_RES_ID);
final int landscapeLayoutResId = attrs.getAttributeResourceValue(null, XML_LANDSCAPE_LAYOUT_RES_ID_ATTRIBUTE, AddOn.INVALID_RES_ID);
//final int iconResId = attrs.getAttributeResourceValue(null, XML_ICON_RES_ID_ATTRIBUTE, R.drawable.sym_keyboard_notification_icon);
@@ -114,7 +123,7 @@ public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilde
+ " landscapeResId:" + landscapeLayoutResId
+ " iconResId:" + iconResId + " defaultDictionary:"
+ defaultDictionary);
return new KeyboardAddOnAndBuilder(askContext, context,
return new ApkKeyboardAddOnAndBuilder(askContext, context,
prefId, nameId, layoutResId, landscapeLayoutResId,
defaultDictionary, iconResId, physicalTranslationResId,
additionalIsLetterExceptions, sentenceSeparators,
@@ -127,7 +136,7 @@ public class ApkLangKeyboardFactory extends AddOnsFactory<KeyboardAddOnAndBuilde
}
public Keyboard createKeyboard(Context context) {
List<KeyboardAddOnAndBuilder> keyboardBuilders = getAllAvailableKeyboards(context);
List<? extends KeyboardBuilder> keyboardBuilders = getAllAvailableKeyboards(context);
if (keyboardBuilders.size() == 0)
return new Keyboard(context, 0x7f04000c); // ru keyboard resource id
// remember, only one external keyboard supported

View File

@@ -1,4 +1,4 @@
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
public class BuildConfig {
public final static boolean TESTING_BUILD = true;

View File

@@ -1,4 +1,4 @@
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
import android.os.Build;
import android.util.Log;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
public interface LogProvider {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
import android.support.annotation.NonNull;

View File

@@ -1,4 +1,4 @@
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
/**
* Doesn't do anything. For release.

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
import android.util.Xml;

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
package com.liskovsoft.keyboardaddons.apklangfactory.utils;
package com.liskovsoft.keyboardaddons.apkkbdfactory.utils;
import java.io.File;
import java.io.FileWriter;

View File

@@ -0,0 +1,13 @@
package com.liskovsoft.keyboardaddons.reskbdfactory;
import android.inputmethodservice.Keyboard;
import android.support.annotation.Nullable;
import com.liskovsoft.keyboardaddons.KeyboardBuilder;
class ResKeyboardBuilder implements KeyboardBuilder {
@Nullable
@Override
public Keyboard createKeyboard() {
return null;
}
}

View File

@@ -0,0 +1,59 @@
package com.liskovsoft.keyboardaddons.reskbdfactory;
import android.content.Context;
import android.content.res.Resources;
import android.inputmethodservice.Keyboard;
import android.support.annotation.Nullable;
import com.liskovsoft.keyboardaddons.KeyboardBuilder;
import com.liskovsoft.keyboardaddons.KeyboardFactory;
import com.liskovsoft.keyboardaddons.KeyboardInfo;
import java.util.ArrayList;
import java.util.List;
public class ResKeyboardFactory implements KeyboardFactory {
private final Context mContext;
public ResKeyboardFactory(Context ctx) {
mContext = ctx;
}
@Override
public List<? extends KeyboardBuilder> getAllAvailableKeyboards(Context context) {
List<KeyboardBuilder> result = new ArrayList<>();
List<KeyboardInfo> infos = ResKeyboardInfo.getAllKeyboardInfos(context);
for (final KeyboardInfo info : infos) {
if (!info.isEnabled()) {
continue;
}
result.add(createKeyboard(info.getLangCode()));
}
// at least one kbd should be enabled
if (result.isEmpty()) {
KeyboardInfo firstKbd = infos.get(0);
result.add(createKeyboard(firstKbd.getLangCode()));
firstKbd.setEnabled(true);
ResKeyboardInfo.updateAllKeyboardInfos(mContext, infos);
}
return result;
}
private KeyboardBuilder createKeyboard(final String langCode) {
return new KeyboardBuilder() {
@Nullable
@Override
public Keyboard createKeyboard() {
return new Keyboard(mContext, mContext.getResources().getIdentifier("qwerty_" + langCode, "xml", mContext.getPackageName()));
}
};
}
@Override
public boolean needUpdate() {
return ResKeyboardInfo.needUpdate();
}
}

View File

@@ -0,0 +1,91 @@
package com.liskovsoft.keyboardaddons.reskbdfactory;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.liskovsoft.keyboardaddons.KeyboardInfo;
import com.liskovsoft.leankeykeyboard.R;
import java.util.ArrayList;
import java.util.List;
public class ResKeyboardInfo implements KeyboardInfo {
private static boolean sNeedUpdate;
private boolean mEnabled;
private String mLangCode;
private String mLangName;
public static List<KeyboardInfo> getAllKeyboardInfos(Context ctx) {
List<KeyboardInfo> result = new ArrayList<>();
String[] langs = ctx.getResources().getStringArray(R.array.additional_languages);
for (final String langPair : langs) {
String[] pairs = langPair.split("\\|");
final String langName = pairs[0];
final String langCode = pairs[1];
KeyboardInfo info = new ResKeyboardInfo();
info.setLangName(langName);
info.setLangCode(langCode);
// sync with prefs
syncWithPrefs(ctx, info);
result.add(info);
}
sNeedUpdate = false;
return result;
}
public static void updateAllKeyboardInfos(Context ctx, List<KeyboardInfo> infos) {
for (KeyboardInfo info : infos) {
// update prefs
updatePrefs(ctx, info);
}
sNeedUpdate = true;
}
private static void syncWithPrefs(Context ctx, KeyboardInfo info) {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
final boolean kbdEnabled = sharedPreferences.getBoolean(info.getLangCode(), false);
info.setEnabled(kbdEnabled);
}
private static void updatePrefs(Context ctx, KeyboardInfo info) {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
final SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(info.getLangCode(), info.isEnabled());
editor.apply();
}
public static boolean needUpdate() {
return sNeedUpdate;
}
@Override
public boolean isEnabled() {
return mEnabled;
}
@Override
public String getLangCode() {
return mLangCode;
}
@Override
public String getLangName() {
return mLangName;
}
@Override
public void setLangName(String langName) {
mLangName = langName;
}
@Override
public void setLangCode(String langCode) {
mLangCode = langCode;
}
@Override
public void setEnabled(boolean enabled) {
mEnabled = enabled;
}
}

View File

@@ -0,0 +1,11 @@
package com.liskovsoft.keyboardaddons.reskbdfactory;
import com.liskovsoft.keyboardaddons.KeyboardInfo;
import java.util.List;
class ResKeyboardManager {
public List<KeyboardInfo> getAllKeyboardInfos() {
return null;
}
}

View File

@@ -0,0 +1,133 @@
package com.liskovsoft.other;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.res.TypedArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckedTextView;
import com.liskovsoft.keyboardaddons.KeyboardInfo;
import com.liskovsoft.keyboardaddons.reskbdfactory.ResKeyboardInfo;
import com.liskovsoft.leankeykeyboard.R;
import java.util.ArrayList;
import java.util.List;
public class ChooseKeyboardDialog implements OnClickListener {
private final View mInputView;
private final Context mContext;
private final List<KeyboardInfo> mInfos;
private AlertDialog alertDialog;
private ArrayList<CheckedTextView> mLangViews;
/**
* Main constructor. Use it in most of the cases.
* @param ctx context
*/
public ChooseKeyboardDialog(Context ctx) {
this(ctx, null);
}
/**
* Special constructor. Useful when others didn't work. E.g. when running dialog within input method.
* @param ctx context
* @param inputView view to get token
*/
public ChooseKeyboardDialog(Context ctx, View inputView) {
mContext = ctx;
mInfos = ResKeyboardInfo.getAllKeyboardInfos(ctx);
mInputView = inputView;
}
public void run() {
showDialog();
}
@TargetApi(17)
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
View title = LayoutInflater.from(mContext).inflate(R.layout.lang_selection_dialog_title, null);
alertDialog = builder
//.setTitle(R.string.language_dialog_title)
.setCustomTitle(title)
.setView(buildView(builder.getContext()))
.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
ResKeyboardInfo.updateAllKeyboardInfos(mContext, mInfos);
}
})
.create();
if (mInputView != null) {
initDialog(); // prepare to run from IME
}
alertDialog.show();
}
private void initDialog() {
Window window = alertDialog.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.token = mInputView.getWindowToken();
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
window.setAttributes(lp);
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
@SuppressLint("InflateParams")
private View buildView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.lang_selection_dialog, null);
ViewGroup root = view.findViewById(R.id.root);
TypedArray attributeArray = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.selectableItemBackground});
int selectableItemBackgroundResourceId = attributeArray.getResourceId(0, 0);
attributeArray.recycle();
mLangViews = new ArrayList<>();
for (KeyboardInfo info : mInfos) {
CheckedTextView langView = (CheckedTextView) inflater.inflate(android.R.layout.simple_list_item_multiple_choice, root, false);
langView.setBackgroundResource(selectableItemBackgroundResourceId);
langView.setText(info.getLangName());
langView.setFocusable(true);
langView.setTag(info); // our TAG
langView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources().getDimension(R.dimen.text_size_dp));
langView.setOnClickListener(this);
mLangViews.add(langView);
root.addView(langView);
}
updateViews();
return view;
}
private void updateViews() {
for (CheckedTextView view : mLangViews) {
KeyboardInfo kbd = (KeyboardInfo) view.getTag();
if (kbd.isEnabled()) {
view.setChecked(true);
}
}
}
@Override
public void onClick(View view) {
KeyboardInfo kbd = (KeyboardInfo) view.getTag();
// todo
CheckedTextView checkedView = (CheckedTextView) view;
boolean checked = checkedView.isChecked();
kbd.setEnabled(!checked);
checkedView.setChecked(!checked);
}
}

View File

@@ -0,0 +1,130 @@
package com.liskovsoft.other;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.pm.PackageManager;
import android.widget.Toast;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ActivityInfo;
import android.content.Intent;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
public class GenericLaunchActivity extends Activity
{
private static final String META_PACKAGE_NAME = "package";
private static final String META_CLASS_NAME = "class";
private static final String META_PACKAGE_NAME_ALT = "package_alt";
private static final String META_CLASS_NAME_ALT = "class_alt";
private static final String META_INTENT_NAME = "intent";
private List<Intent> mIntents = new ArrayList<>();
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
launchApp();
}
@SuppressLint("WrongConstant")
private void addCommonIntentFlags(final Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
@SuppressLint("WrongConstant")
private ActivityInfo getCurrentActivityInfo() {
try {
return getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA | PackageManager.GET_ACTIVITIES);
}
catch (NameNotFoundException ex) {
ex.printStackTrace();
makeLongToast(ex.getLocalizedMessage());
return null;
}
}
private void launchApp() {
makeIntentList();
startIntents();
finish();
}
private void startIntents() {
for (Intent intent : mIntents) {
boolean result = startIntent(intent);
if (result) { // run until first successful attempt
break;
}
}
}
private void makeIntentList() {
final ActivityInfo activityInfo = getCurrentActivityInfo();
if (activityInfo == null) {
return;
}
final Bundle metaData = activityInfo.metaData;
String metaPackageName = metaData.getString(META_PACKAGE_NAME);
String metaClassName = metaData.getString(META_CLASS_NAME);
mIntents.add(createIntent(metaPackageName, metaClassName));
String metaPackageNameAlt = metaData.getString(META_PACKAGE_NAME_ALT);
String metaClassNameAlt = metaData.getString(META_CLASS_NAME_ALT);
mIntents.add(createIntent(metaPackageNameAlt, metaClassNameAlt));
String metaIntentName = metaData.getString(META_INTENT_NAME);
mIntents.add(createIntent(metaIntentName));
}
private Intent createIntent(String intentName) {
if (intentName == null) {
return null;
}
final Intent intent = new Intent();
intent.setAction(intentName);
addCommonIntentFlags(intent);
return intent;
}
private Intent createIntent(String packageName, String className) {
if (packageName == null || className == null) {
return null;
}
final Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, className));
addCommonIntentFlags(intent);
return intent;
}
private void makeLongToast(final String s) {
makeLongToast(s, 10);
}
private void makeLongToast(final String s, int nums) {
int n;
for (n = nums / 2, nums = 0; nums < n; ++nums) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
private boolean startIntent(final Intent intent) {
if (intent == null) {
return false;
}
try {
startActivity(intent);
}
catch (ActivityNotFoundException ex) {
return false;
}
return true;
}
}

View File

@@ -1,10 +1,8 @@
package com.liskovsoft.inputchooser;
package com.liskovsoft.other;
import android.app.*;
import android.content.*;
import android.content.res.*;
import android.net.*;
import android.util.*;
import android.view.inputmethod.*;
import java.util.*;

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Useful links:
// https://android.googlesource.com/platform/frameworks/base/+/de47f1c358c8186ff3e14b887d5869f69b9a9d6c/core/java/com/android/internal/widget/DialogTitle.java
// com.android.internal.widget.DialogTitle: https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/layout/alert_dialog.xml
// https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/app/AlertController.java
// <declare-styleable name="TextAppearance">: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/res/values/attrs.xml
package com.liskovsoft.other.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.TypedValue;
import com.liskovsoft.leankeykeyboard.R;
/**
* Used by dialogs to change the font size and number of lines to try to fit
* the text to the available space.
*/
public class DialogTitle extends android.support.v7.widget.AppCompatTextView {
public DialogTitle(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public DialogTitle(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DialogTitle(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final Layout layout = getLayout();
if (layout != null) {
final int lineCount = layout.getLineCount();
if (lineCount > 0) {
final int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
if (ellipsisCount > 0) {
setSingleLine(false);
TypedArray a = getContext().obtainStyledAttributes(null,
R.styleable.TextAppearance,
android.R.attr.textAppearanceMedium,
android.R.style.TextAppearance_Medium);
final int textSize = a.getDimensionPixelSize(
R.styleable.TextAppearance_textSize,
(int) (20 * getResources().getDisplayMetrics().density));
final int textColor = a.getColor(
R.styleable.TextAppearance_textColor, 0xffffffff);
// textSize is already expressed in pixels
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
setTextColor(textColor);
setMaxLines(2);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
}
}

View File

@@ -0,0 +1,144 @@
package com.liskovsoft.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Helpers {
/**
* Simple wildcard matching routine. Implemented without regex. So you may expect huge performance boost.
* @param host
* @param mask
* @return
*/
public static boolean matchSubstr(String host, String mask) {
String[] sections = mask.split("\\*");
String text = host;
for (String section : sections) {
int index = text.indexOf(section);
if (index == -1) {
return false;
}
text = text.substring(index + section.length());
}
return true;
}
public static boolean matchSubstrNoCase(String host, String mask) {
return matchSubstr(host.toLowerCase(), mask.toLowerCase());
}
public static InputStream getAsset(Context ctx, String fileName) {
InputStream is = null;
try {
is = ctx.getAssets().open(fileName);
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
public static String encodeURI(byte[] data) {
try {
// make behaviour of java uri-encode the same as javascript's one
return URLEncoder.encode(new String(data, "UTF-8"), "UTF-8").replace("+", "%20");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static boolean floatEquals(float num1, float num2) {
float epsilon = 0.1f;
return Math.abs(num1 - num2) < epsilon;
}
public static String getDeviceName() {
return String.format("%s (%s)", Build.MODEL, Build.PRODUCT);
}
public static boolean deviceMatch(String[] devicesToProcess) {
String thisDeviceName = Helpers.getDeviceName();
for (String deviceName : devicesToProcess) {
boolean match = matchSubstrNoCase(thisDeviceName, deviceName);
if (match) {
return true;
}
}
return false;
}
public static String toString(InputStream inputStream) {
if (inputStream == null) {
return null;
}
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String result = s.hasNext() ? s.next() : "";
return result;
}
public static InputStream toStream(String content) {
return new ByteArrayInputStream(content.getBytes(Charset.forName("UTF8")));
}
public static void postOnUiThread(Runnable runnable) {
new Handler(Looper.getMainLooper()).post(runnable);
}
public static String unixToLocalDate(Context ctx, String timestamp) {
Locale current = ctx.getResources().getConfiguration().locale;
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG, current);
Date date;
if (timestamp == null) {
date = new Date();
} else {
date = new Date((long) Integer.parseInt(timestamp) * 1000);
}
return dateFormat.format(date);
}
public static String runMultiMatcher(String input, String... patterns) {
if (input == null) {
return null;
}
Pattern regex;
Matcher matcher;
String result = null;
for (String pattern : patterns) {
regex = Pattern.compile(pattern);
matcher = regex.matcher(input);
if (matcher.find()) {
result = matcher.group(matcher.groupCount()); // get last group
break;
}
}
return result;
}
public static boolean isCallable(Context ctx, Intent intent) {
List<ResolveInfo> list = ctx.getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
}

View File

@@ -0,0 +1,127 @@
package com.liskovsoft.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
public class LangUpdater {
private static final String LOCALE_EN_US = "en_US";
private static final String LOCALE_RU = "ru_RU";
private Context mContext;
private String[] rusPackages = {"dkc.androidtv.tree", "dkc.video.fsbox", "dkc.video.hdbox", "dkc.video.uatv"};
public LangUpdater(Context ctx) {
mContext = ctx;
}
public void update() {
tryToEnableRussian();
tryToForceEnglishOnDevices();
tryToRestoreLanguage();
}
private void tryToRestoreLanguage() {
String langCode = getPreferredLocale();
if (langCode != null) {
forceLocale(langCode);
}
}
private void tryToForceEnglishOnDevices() {
String deviceName = Helpers.getDeviceName();
switch (deviceName) {
case "ChangHong Android TV (full_mst638)":
forceLocale(LOCALE_EN_US);
}
}
private void tryToBypassChinese() {
String script = LocaleUtility.getScript(Locale.getDefault());
if (isChineseScript(script)) {
forceLocale(LOCALE_EN_US);
}
}
private boolean isChineseScript(String script) {
switch (script) {
case "Hani":
case "Hans":
case "Hant":
return true;
}
return false;
}
private void tryToEnableRussian() {
List<String> installedPackages = getListInstalledPackages();
for (String pkgName : installedPackages) {
if (isRussianPackage(pkgName)) {
forceLocale(LOCALE_RU);
}
}
}
// short lang code. ex: "ru"
private void forceLocale(String langCode) {
if (langCode == null || langCode.isEmpty()) {
return;
}
Locale locale = parseLangCode(langCode);
Locale.setDefault(locale);
Configuration config = mContext.getResources().getConfiguration();
config.locale = locale;
mContext.getResources().updateConfiguration(config,
mContext.getResources().getDisplayMetrics());
}
private boolean isRussianPackage(String pkgName) {
for (String rusPackage : rusPackages) {
if (rusPackage.equals(pkgName)){
return true;
}
}
return false;
}
private List<String> getListInstalledPackages() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> pkgAppsList = mContext.getPackageManager().queryIntentActivities( mainIntent, 0);
List<String> result = new ArrayList<>();
for (ResolveInfo info : pkgAppsList) {
result.add(info.activityInfo.packageName);
}
return result;
}
public String getLocale() {
Configuration config = mContext.getResources().getConfiguration();
return config.locale.getLanguage();
}
/**
* Get locale as lang code (e.g. zh, ru_RU etc)
* @return lang code
*/
public String getPreferredLocale() {
return LeanKeyPreferences.instance(mContext).getPreferredLanguage();
}
public void setPreferredLocale(String langCode) {
LeanKeyPreferences.instance(mContext).setPreferredLanguage(langCode);
}
private Locale parseLangCode(String langCode) {
StringTokenizer tokenizer = new StringTokenizer(langCode, "_");
String lang = tokenizer.nextToken();
String country = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : "";
return new Locale(lang, country);
}
}

View File

@@ -0,0 +1,57 @@
package com.liskovsoft.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public final class LeanKeyPreferences {
private static final String APP_RUN_ONCE = "appRunOnce";
private static final String BOOTSTRAP_SELECTED_LANGUAGE = "bootstrapSelectedLanguage";
private static final String APP_KEYBOARD_INDEX = "appKeyboardIndex";
private static LeanKeyPreferences sInstance;
private final Context mContext;
private SharedPreferences mPrefs;
public static LeanKeyPreferences instance(Context ctx) {
if (sInstance == null)
sInstance = new LeanKeyPreferences(ctx);
return sInstance;
}
public LeanKeyPreferences(Context context) {
mContext = context.getApplicationContext();
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
}
public boolean isRunOnce() {
return mPrefs.getBoolean(APP_RUN_ONCE, false);
}
public void setRunOnce(boolean runOnce) {
mPrefs.edit()
.putBoolean(APP_RUN_ONCE, runOnce)
.apply();
}
public void setPreferredLanguage(String name) {
mPrefs.edit()
.putString(BOOTSTRAP_SELECTED_LANGUAGE, name)
.apply();
}
public String getPreferredLanguage() {
String name = mPrefs.getString(BOOTSTRAP_SELECTED_LANGUAGE, "");
return name;
}
public int getKeyboardIndex() {
int idx = mPrefs.getInt(APP_KEYBOARD_INDEX, 0);
return idx;
}
public void setKeyboardIndex(int idx) {
mPrefs.edit()
.putInt(APP_KEYBOARD_INDEX, idx)
.apply();
}
}

View File

@@ -0,0 +1,768 @@
package com.liskovsoft.utils;
import android.content.Context;
import android.os.Build;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/*
* Copyright 2013 Phil Brown
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* Get Script name by Locale
* <br>
* @author Phil Brown
* @since 9:47:09 AM Dec 20, 2013
*
*/
/*
* Additional info:
* https://en.wikipedia.org/wiki/Writing_system
* https://stackoverflow.com/questions/19153384/how-to-get-the-script-from-a-locale-object-on-android
* https://docs.oracle.com/javase/7/docs/api/java/util/Locale.html#getScript()
* http://unicode.org/iso15924/iso15924-codes.html
*
* Usage:
* String script = LocaleUtilities.getScript(Locale.getDefault());
* String script = LocaleUtilities.getScript(getDefaultLocale(myActivity));
*/
public class LocaleUtility {
public static Map<String, Map<String, String>> scriptsByLocale = new HashMap<String, Map<String, String>>();
public static Map<String, String> getScriptsMap(String... keyValuePairs) {
Map<String, String> languages = new HashMap<String, String>();
for (int i = 0; i < keyValuePairs.length; i += 2) {
languages.put(keyValuePairs[i], keyValuePairs[i + 1]);
}
return languages;
}
static {
scriptsByLocale.put("aa", getScriptsMap("", "Latn"));
scriptsByLocale.put("ab", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("abq", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("abr", getScriptsMap("", ""));
scriptsByLocale.put("ace", getScriptsMap("", "Latn"));
scriptsByLocale.put("ach", getScriptsMap("", "Latn"));
scriptsByLocale.put("ada", getScriptsMap("", "Latn"));
scriptsByLocale.put("ady", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ae", getScriptsMap("", "Avst"));
scriptsByLocale.put("af", getScriptsMap("", "Latn"));
scriptsByLocale.put("agq", getScriptsMap("", "Latn"));
scriptsByLocale.put("aii", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ain", getScriptsMap("", "Kana"));
scriptsByLocale.put("ak", getScriptsMap("", "Latn"));
scriptsByLocale.put("akk", getScriptsMap("", "Xsux"));
scriptsByLocale.put("ale", getScriptsMap("", "Latn"));
scriptsByLocale.put("alt", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("am", getScriptsMap("", "Ethi"));
scriptsByLocale.put("amo", getScriptsMap("", "Latn"));
scriptsByLocale.put("an", getScriptsMap("", "Latn"));
scriptsByLocale.put("anp", getScriptsMap("", "Deva"));
scriptsByLocale.put("aoz", getScriptsMap("", ""));
scriptsByLocale.put("ar", getScriptsMap("", "Arab", "IR", "Syrc"));
scriptsByLocale.put("arc", getScriptsMap("", "Armi"));
scriptsByLocale.put("arn", getScriptsMap("", "Latn"));
scriptsByLocale.put("arp", getScriptsMap("", "Latn"));
scriptsByLocale.put("arw", getScriptsMap("", "Latn"));
scriptsByLocale.put("as", getScriptsMap("", "Beng"));
scriptsByLocale.put("asa", getScriptsMap("", "Latn"));
scriptsByLocale.put("ast", getScriptsMap("", "Latn"));
scriptsByLocale.put("atj", getScriptsMap("", ""));
scriptsByLocale.put("av", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("awa", getScriptsMap("", "Deva"));
scriptsByLocale.put("ay", getScriptsMap("", "Latn"));
scriptsByLocale.put("az", getScriptsMap("", "Latn", "AZ", "Cyrl", "IR", "Arab"));
scriptsByLocale.put("ba", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("bal", getScriptsMap("", "Arab", "IR", "Latn", "PK", "Latn"));
scriptsByLocale.put("ban", getScriptsMap("", "Latn", "ID", "Bali"));
scriptsByLocale.put("bap", getScriptsMap("", ""));
scriptsByLocale.put("bas", getScriptsMap("", "Latn"));
scriptsByLocale.put("bax", getScriptsMap("", "Bamu"));
scriptsByLocale.put("bbc", getScriptsMap("", "Latn", "ID", "Batk"));
scriptsByLocale.put("bbj", getScriptsMap("", ""));
scriptsByLocale.put("bci", getScriptsMap("", ""));
scriptsByLocale.put("be", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("bej", getScriptsMap("", "Arab"));
scriptsByLocale.put("bem", getScriptsMap("", "Latn"));
scriptsByLocale.put("bew", getScriptsMap("", ""));
scriptsByLocale.put("bez", getScriptsMap("", "Latn"));
scriptsByLocale.put("bfd", getScriptsMap("", ""));
scriptsByLocale.put("bfq", getScriptsMap("", "Taml"));
scriptsByLocale.put("bft", getScriptsMap("", "Arab"));
scriptsByLocale.put("bfy", getScriptsMap("", "Deva"));
scriptsByLocale.put("bg", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("bgc", getScriptsMap("", ""));
scriptsByLocale.put("bgx", getScriptsMap("", ""));
scriptsByLocale.put("bh", getScriptsMap("", "Deva"));
scriptsByLocale.put("bhb", getScriptsMap("", "Deva"));
scriptsByLocale.put("bhi", getScriptsMap("", ""));
scriptsByLocale.put("bhk", getScriptsMap("", ""));
scriptsByLocale.put("bho", getScriptsMap("", "Deva"));
scriptsByLocale.put("bi", getScriptsMap("", "Latn"));
scriptsByLocale.put("bik", getScriptsMap("", "Latn"));
scriptsByLocale.put("bin", getScriptsMap("", "Latn"));
scriptsByLocale.put("bjj", getScriptsMap("", "Deva"));
scriptsByLocale.put("bjn", getScriptsMap("", ""));
scriptsByLocale.put("bkm", getScriptsMap("", ""));
scriptsByLocale.put("bku", getScriptsMap("", "Latn"));
scriptsByLocale.put("bla", getScriptsMap("", "Latn"));
scriptsByLocale.put("blt", getScriptsMap("", "Tavt"));
scriptsByLocale.put("bm", getScriptsMap("", "Latn"));
scriptsByLocale.put("bmq", getScriptsMap("", ""));
scriptsByLocale.put("bn", getScriptsMap("", "Beng"));
scriptsByLocale.put("bo", getScriptsMap("", "Tibt"));
scriptsByLocale.put("bqi", getScriptsMap("", ""));
scriptsByLocale.put("bqv", getScriptsMap("", "Latn"));
scriptsByLocale.put("br", getScriptsMap("", "Latn"));
scriptsByLocale.put("bra", getScriptsMap("", "Deva"));
scriptsByLocale.put("brh", getScriptsMap("", ""));
scriptsByLocale.put("brx", getScriptsMap("", "Deva"));
scriptsByLocale.put("bs", getScriptsMap("", "Latn"));
scriptsByLocale.put("bss", getScriptsMap("", ""));
scriptsByLocale.put("bto", getScriptsMap("", ""));
scriptsByLocale.put("btv", getScriptsMap("", "Deva"));
scriptsByLocale.put("bua", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("buc", getScriptsMap("", "Latn"));
scriptsByLocale.put("bug", getScriptsMap("", "Latn", "ID", "Bugi"));
scriptsByLocale.put("bum", getScriptsMap("", ""));
scriptsByLocale.put("bvb", getScriptsMap("", ""));
scriptsByLocale.put("bya", getScriptsMap("", "Latn"));
scriptsByLocale.put("byn", getScriptsMap("", "Ethi"));
scriptsByLocale.put("byv", getScriptsMap("", ""));
scriptsByLocale.put("bze", getScriptsMap("", ""));
scriptsByLocale.put("bzx", getScriptsMap("", ""));
scriptsByLocale.put("ca", getScriptsMap("", "Latn"));
scriptsByLocale.put("cad", getScriptsMap("", "Latn"));
scriptsByLocale.put("car", getScriptsMap("", "Latn"));
scriptsByLocale.put("cay", getScriptsMap("", "Latn"));
scriptsByLocale.put("cch", getScriptsMap("", "Latn"));
scriptsByLocale.put("ccp", getScriptsMap("", "Beng"));
scriptsByLocale.put("ce", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ceb", getScriptsMap("", "Latn"));
scriptsByLocale.put("cgg", getScriptsMap("", "Latn"));
scriptsByLocale.put("ch", getScriptsMap("", "Latn"));
scriptsByLocale.put("chk", getScriptsMap("", "Latn"));
scriptsByLocale.put("chm", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("chn", getScriptsMap("", "Latn"));
scriptsByLocale.put("cho", getScriptsMap("", "Latn"));
scriptsByLocale.put("chp", getScriptsMap("", "Latn"));
scriptsByLocale.put("chr", getScriptsMap("", "Cher"));
scriptsByLocale.put("chy", getScriptsMap("", "Latn"));
scriptsByLocale.put("cja", getScriptsMap("", "Arab"));
scriptsByLocale.put("cjm", getScriptsMap("", "Cham"));
scriptsByLocale.put("cjs", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ckb", getScriptsMap("", "Arab"));
scriptsByLocale.put("ckt", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("co", getScriptsMap("", "Latn"));
scriptsByLocale.put("cop", getScriptsMap("", "Arab"));
scriptsByLocale.put("cpe", getScriptsMap("", "Latn"));
scriptsByLocale.put("cr", getScriptsMap("", "Cans"));
scriptsByLocale.put("crh", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("crj", getScriptsMap("", ""));
scriptsByLocale.put("crk", getScriptsMap("", "Cans"));
scriptsByLocale.put("crl", getScriptsMap("", ""));
scriptsByLocale.put("crm", getScriptsMap("", ""));
scriptsByLocale.put("crs", getScriptsMap("", ""));
scriptsByLocale.put("cs", getScriptsMap("", "Latn"));
scriptsByLocale.put("csb", getScriptsMap("", "Latn"));
scriptsByLocale.put("csw", getScriptsMap("", ""));
scriptsByLocale.put("cu", getScriptsMap("", "Glag"));
scriptsByLocale.put("cv", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("cy", getScriptsMap("", "Latn"));
scriptsByLocale.put("da", getScriptsMap("", "Latn"));
scriptsByLocale.put("daf", getScriptsMap("", ""));
scriptsByLocale.put("dak", getScriptsMap("", "Latn"));
scriptsByLocale.put("dar", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("dav", getScriptsMap("", "Latn"));
scriptsByLocale.put("dcc", getScriptsMap("", ""));
scriptsByLocale.put("de", getScriptsMap("", "Latn", "BR", "Runr", "KZ", "Runr", "US", "Runr"));
scriptsByLocale.put("del", getScriptsMap("", "Latn"));
scriptsByLocale.put("den", getScriptsMap("", "Latn"));
scriptsByLocale.put("dgr", getScriptsMap("", "Latn"));
scriptsByLocale.put("din", getScriptsMap("", "Latn"));
scriptsByLocale.put("dje", getScriptsMap("", "Latn"));
scriptsByLocale.put("dng", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("doi", getScriptsMap("", "Arab"));
scriptsByLocale.put("dsb", getScriptsMap("", "Latn"));
scriptsByLocale.put("dtm", getScriptsMap("", ""));
scriptsByLocale.put("dua", getScriptsMap("", "Latn"));
scriptsByLocale.put("dv", getScriptsMap("", "Thaa"));
scriptsByLocale.put("dyo", getScriptsMap("", "Arab"));
scriptsByLocale.put("dyu", getScriptsMap("", "Latn"));
scriptsByLocale.put("dz", getScriptsMap("", "Tibt"));
scriptsByLocale.put("ebu", getScriptsMap("", "Latn"));
scriptsByLocale.put("ee", getScriptsMap("", "Latn"));
scriptsByLocale.put("efi", getScriptsMap("", "Latn"));
scriptsByLocale.put("egy", getScriptsMap("", "Egyp"));
scriptsByLocale.put("eka", getScriptsMap("", "Latn"));
scriptsByLocale.put("eky", getScriptsMap("", "Kali"));
scriptsByLocale.put("el", getScriptsMap("", "Grek"));
scriptsByLocale.put("en", getScriptsMap("", "Latn"));
scriptsByLocale.put("eo", getScriptsMap("", "Latn"));
scriptsByLocale.put("es", getScriptsMap("", "Latn"));
scriptsByLocale.put("et", getScriptsMap("", "Latn"));
scriptsByLocale.put("ett", getScriptsMap("", "Ital"));
scriptsByLocale.put("eu", getScriptsMap("", "Latn"));
scriptsByLocale.put("evn", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ewo", getScriptsMap("", "Latn"));
scriptsByLocale.put("fa", getScriptsMap("", "Arab"));
scriptsByLocale.put("fan", getScriptsMap("", "Latn"));
scriptsByLocale.put("ff", getScriptsMap("", "Latn"));
scriptsByLocale.put("ffm", getScriptsMap("", ""));
scriptsByLocale.put("fi", getScriptsMap("", "Latn"));
scriptsByLocale.put("fil", getScriptsMap("", "Latn", "US", "Tglg"));
scriptsByLocale.put("fiu", getScriptsMap("", "Latn"));
scriptsByLocale.put("fj", getScriptsMap("", "Latn"));
scriptsByLocale.put("fo", getScriptsMap("", "Latn"));
scriptsByLocale.put("fon", getScriptsMap("", "Latn"));
scriptsByLocale.put("fr", getScriptsMap("", "Latn"));
scriptsByLocale.put("frr", getScriptsMap("", "Latn"));
scriptsByLocale.put("frs", getScriptsMap("", "Latn"));
scriptsByLocale.put("fud", getScriptsMap("", ""));
scriptsByLocale.put("fuq", getScriptsMap("", ""));
scriptsByLocale.put("fur", getScriptsMap("", "Latn"));
scriptsByLocale.put("fuv", getScriptsMap("", ""));
scriptsByLocale.put("fy", getScriptsMap("", "Latn"));
scriptsByLocale.put("ga", getScriptsMap("", "Latn"));
scriptsByLocale.put("gaa", getScriptsMap("", "Latn"));
scriptsByLocale.put("gag", getScriptsMap("", "Latn", "MD", "Cyrl"));
scriptsByLocale.put("gay", getScriptsMap("", "Latn"));
scriptsByLocale.put("gba", getScriptsMap("", "Arab"));
scriptsByLocale.put("gbm", getScriptsMap("", "Deva"));
scriptsByLocale.put("gcr", getScriptsMap("", "Latn"));
scriptsByLocale.put("gd", getScriptsMap("", "Latn"));
scriptsByLocale.put("gez", getScriptsMap("", "Ethi"));
scriptsByLocale.put("ggn", getScriptsMap("", ""));
scriptsByLocale.put("gil", getScriptsMap("", "Latn"));
scriptsByLocale.put("gjk", getScriptsMap("", ""));
scriptsByLocale.put("gju", getScriptsMap("", ""));
scriptsByLocale.put("gl", getScriptsMap("", "Latn"));
scriptsByLocale.put("gld", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("glk", getScriptsMap("", ""));
scriptsByLocale.put("gn", getScriptsMap("", "Latn"));
scriptsByLocale.put("gon", getScriptsMap("", "Telu"));
scriptsByLocale.put("gor", getScriptsMap("", "Latn"));
scriptsByLocale.put("gos", getScriptsMap("", ""));
scriptsByLocale.put("got", getScriptsMap("", "Goth"));
scriptsByLocale.put("grb", getScriptsMap("", "Latn"));
scriptsByLocale.put("grc", getScriptsMap("", "Cprt"));
scriptsByLocale.put("grt", getScriptsMap("", "Beng"));
scriptsByLocale.put("gsw", getScriptsMap("", "Latn"));
scriptsByLocale.put("gu", getScriptsMap("", "Gujr"));
scriptsByLocale.put("gub", getScriptsMap("", ""));
scriptsByLocale.put("guz", getScriptsMap("", "Latn"));
scriptsByLocale.put("gv", getScriptsMap("", "Latn"));
scriptsByLocale.put("gvr", getScriptsMap("", ""));
scriptsByLocale.put("gwi", getScriptsMap("", "Latn"));
scriptsByLocale.put("ha", getScriptsMap("", "Arab", "NE", "Latn", "GH", "Latn"));
scriptsByLocale.put("hai", getScriptsMap("", "Latn"));
scriptsByLocale.put("haw", getScriptsMap("", "Latn"));
scriptsByLocale.put("haz", getScriptsMap("", ""));
scriptsByLocale.put("he", getScriptsMap("", "Hebr"));
scriptsByLocale.put("hi", getScriptsMap("", "Deva"));
scriptsByLocale.put("hil", getScriptsMap("", "Latn"));
scriptsByLocale.put("hit", getScriptsMap("", "Xsux"));
scriptsByLocale.put("hmn", getScriptsMap("", "Latn"));
scriptsByLocale.put("hnd", getScriptsMap("", ""));
scriptsByLocale.put("hne", getScriptsMap("", "Deva"));
scriptsByLocale.put("hnn", getScriptsMap("", "Latn"));
scriptsByLocale.put("hno", getScriptsMap("", ""));
scriptsByLocale.put("ho", getScriptsMap("", "Latn"));
scriptsByLocale.put("hoc", getScriptsMap("", "Deva"));
scriptsByLocale.put("hoj", getScriptsMap("", "Deva"));
scriptsByLocale.put("hop", getScriptsMap("", "Latn"));
scriptsByLocale.put("hr", getScriptsMap("", "Latn"));
scriptsByLocale.put("hsb", getScriptsMap("", "Latn"));
scriptsByLocale.put("ht", getScriptsMap("", "Latn"));
scriptsByLocale.put("hu", getScriptsMap("", "Latn"));
scriptsByLocale.put("hup", getScriptsMap("", "Latn"));
scriptsByLocale.put("hy", getScriptsMap("", "Armn"));
scriptsByLocale.put("hz", getScriptsMap("", "Latn"));
scriptsByLocale.put("ia", getScriptsMap("", "Latn"));
scriptsByLocale.put("iba", getScriptsMap("", "Latn"));
scriptsByLocale.put("ibb", getScriptsMap("", "Latn"));
scriptsByLocale.put("id", getScriptsMap("", "Latn"));
scriptsByLocale.put("ig", getScriptsMap("", "Latn"));
scriptsByLocale.put("ii", getScriptsMap("", "Yiii", "CN", "Latn"));
scriptsByLocale.put("ik", getScriptsMap("", "Latn"));
scriptsByLocale.put("ikt", getScriptsMap("", ""));
scriptsByLocale.put("ilo", getScriptsMap("", "Latn"));
scriptsByLocale.put("inh", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("is", getScriptsMap("", "Latn"));
scriptsByLocale.put("it", getScriptsMap("", "Latn"));
scriptsByLocale.put("iu", getScriptsMap("", "Cans", "CA", "Latn"));
scriptsByLocale.put("ja", getScriptsMap("", "Jpan"));
scriptsByLocale.put("jmc", getScriptsMap("", "Latn"));
scriptsByLocale.put("jml", getScriptsMap("", ""));
scriptsByLocale.put("jpr", getScriptsMap("", "Hebr"));
scriptsByLocale.put("jrb", getScriptsMap("", "Hebr"));
scriptsByLocale.put("jv", getScriptsMap("", "Latn", "ID", "Java"));
scriptsByLocale.put("ka", getScriptsMap("", "Geor"));
scriptsByLocale.put("kaa", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kab", getScriptsMap("", "Latn"));
scriptsByLocale.put("kac", getScriptsMap("", "Latn"));
scriptsByLocale.put("kaj", getScriptsMap("", "Latn"));
scriptsByLocale.put("kam", getScriptsMap("", "Latn"));
scriptsByLocale.put("kao", getScriptsMap("", ""));
scriptsByLocale.put("kbd", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kca", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kcg", getScriptsMap("", "Latn"));
scriptsByLocale.put("kck", getScriptsMap("", ""));
scriptsByLocale.put("kde", getScriptsMap("", "Latn"));
scriptsByLocale.put("kdt", getScriptsMap("", "Thai"));
scriptsByLocale.put("kea", getScriptsMap("", "Latn"));
scriptsByLocale.put("kfo", getScriptsMap("", "Latn"));
scriptsByLocale.put("kfr", getScriptsMap("", "Deva"));
scriptsByLocale.put("kfy", getScriptsMap("", ""));
scriptsByLocale.put("kg", getScriptsMap("", "Latn"));
scriptsByLocale.put("kge", getScriptsMap("", ""));
scriptsByLocale.put("kgp", getScriptsMap("", ""));
scriptsByLocale.put("kha", getScriptsMap("", "Latn", "IN", "Beng"));
scriptsByLocale.put("khb", getScriptsMap("", "Talu"));
scriptsByLocale.put("khn", getScriptsMap("", ""));
scriptsByLocale.put("khq", getScriptsMap("", "Latn"));
scriptsByLocale.put("kht", getScriptsMap("", "Mymr"));
scriptsByLocale.put("khw", getScriptsMap("", ""));
scriptsByLocale.put("ki", getScriptsMap("", "Latn"));
scriptsByLocale.put("kj", getScriptsMap("", "Latn"));
scriptsByLocale.put("kjg", getScriptsMap("", ""));
scriptsByLocale.put("kjh", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kk", getScriptsMap("", "Arab", "KZ", "Cyrl", "TR", "Cyrl"));
scriptsByLocale.put("kkj", getScriptsMap("", ""));
scriptsByLocale.put("kl", getScriptsMap("", "Latn"));
scriptsByLocale.put("kln", getScriptsMap("", "Latn"));
scriptsByLocale.put("km", getScriptsMap("", "Khmr"));
scriptsByLocale.put("kmb", getScriptsMap("", "Latn"));
scriptsByLocale.put("kn", getScriptsMap("", "Knda"));
scriptsByLocale.put("ko", getScriptsMap("", "Kore"));
scriptsByLocale.put("koi", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kok", getScriptsMap("", "Deva"));
scriptsByLocale.put("kos", getScriptsMap("", "Latn"));
scriptsByLocale.put("kpe", getScriptsMap("", "Latn"));
scriptsByLocale.put("kpy", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kr", getScriptsMap("", "Latn"));
scriptsByLocale.put("krc", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kri", getScriptsMap("", "Latn"));
scriptsByLocale.put("krl", getScriptsMap("", "Latn"));
scriptsByLocale.put("kru", getScriptsMap("", "Deva"));
scriptsByLocale.put("ks", getScriptsMap("", "Arab"));
scriptsByLocale.put("ksb", getScriptsMap("", "Latn"));
scriptsByLocale.put("ksf", getScriptsMap("", "Latn"));
scriptsByLocale.put("ksh", getScriptsMap("", "Latn"));
scriptsByLocale.put("ku", getScriptsMap("", "Latn", "LB", "Arab"));
scriptsByLocale.put("kum", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kut", getScriptsMap("", "Latn"));
scriptsByLocale.put("kv", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("kvr", getScriptsMap("", ""));
scriptsByLocale.put("kvx", getScriptsMap("", ""));
scriptsByLocale.put("kw", getScriptsMap("", "Latn"));
scriptsByLocale.put("kxm", getScriptsMap("", ""));
scriptsByLocale.put("kxp", getScriptsMap("", ""));
scriptsByLocale.put("ky", getScriptsMap("", "Cyrl", "CN", "Arab", "TR", "Latn"));
scriptsByLocale.put("kyu", getScriptsMap("", "Kali"));
scriptsByLocale.put("la", getScriptsMap("", "Latn"));
scriptsByLocale.put("lad", getScriptsMap("", "Hebr"));
scriptsByLocale.put("lag", getScriptsMap("", "Latn"));
scriptsByLocale.put("lah", getScriptsMap("", "Arab"));
scriptsByLocale.put("laj", getScriptsMap("", ""));
scriptsByLocale.put("lam", getScriptsMap("", "Latn"));
scriptsByLocale.put("lb", getScriptsMap("", "Latn"));
scriptsByLocale.put("lbe", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("lbw", getScriptsMap("", ""));
scriptsByLocale.put("lcp", getScriptsMap("", "Thai"));
scriptsByLocale.put("lep", getScriptsMap("", "Lepc"));
scriptsByLocale.put("lez", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("lg", getScriptsMap("", "Latn"));
scriptsByLocale.put("li", getScriptsMap("", "Latn"));
scriptsByLocale.put("lif", getScriptsMap("", "Deva"));
scriptsByLocale.put("lis", getScriptsMap("", "Lisu"));
scriptsByLocale.put("ljp", getScriptsMap("", ""));
scriptsByLocale.put("lki", getScriptsMap("", "Arab"));
scriptsByLocale.put("lkt", getScriptsMap("", ""));
scriptsByLocale.put("lmn", getScriptsMap("", "Telu"));
scriptsByLocale.put("lmo", getScriptsMap("", ""));
scriptsByLocale.put("ln", getScriptsMap("", "Latn"));
scriptsByLocale.put("lo", getScriptsMap("", "Laoo"));
scriptsByLocale.put("lol", getScriptsMap("", "Latn"));
scriptsByLocale.put("loz", getScriptsMap("", "Latn"));
scriptsByLocale.put("lrc", getScriptsMap("", ""));
scriptsByLocale.put("lt", getScriptsMap("", "Latn"));
scriptsByLocale.put("lu", getScriptsMap("", "Latn"));
scriptsByLocale.put("lua", getScriptsMap("", "Latn"));
scriptsByLocale.put("lui", getScriptsMap("", "Latn"));
scriptsByLocale.put("lun", getScriptsMap("", "Latn"));
scriptsByLocale.put("luo", getScriptsMap("", "Latn"));
scriptsByLocale.put("lus", getScriptsMap("", "Beng"));
scriptsByLocale.put("lut", getScriptsMap("", "Latn"));
scriptsByLocale.put("luy", getScriptsMap("", "Latn"));
scriptsByLocale.put("luz", getScriptsMap("", ""));
scriptsByLocale.put("lv", getScriptsMap("", "Latn"));
scriptsByLocale.put("lwl", getScriptsMap("", "Thai"));
scriptsByLocale.put("mad", getScriptsMap("", "Latn"));
scriptsByLocale.put("maf", getScriptsMap("", ""));
scriptsByLocale.put("mag", getScriptsMap("", "Deva"));
scriptsByLocale.put("mai", getScriptsMap("", "Deva"));
scriptsByLocale.put("mak", getScriptsMap("", "Latn", "ID", "Bugi"));
scriptsByLocale.put("man", getScriptsMap("", "Latn", "GN", "Nkoo"));
scriptsByLocale.put("mas", getScriptsMap("", "Latn"));
scriptsByLocale.put("maz", getScriptsMap("", ""));
scriptsByLocale.put("mdf", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("mdh", getScriptsMap("", "Latn"));
scriptsByLocale.put("mdr", getScriptsMap("", "Latn"));
scriptsByLocale.put("mdt", getScriptsMap("", ""));
scriptsByLocale.put("men", getScriptsMap("", "Latn"));
scriptsByLocale.put("mer", getScriptsMap("", "Latn"));
scriptsByLocale.put("mfa", getScriptsMap("", ""));
scriptsByLocale.put("mfe", getScriptsMap("", "Latn"));
scriptsByLocale.put("mg", getScriptsMap("", "Latn"));
scriptsByLocale.put("mgh", getScriptsMap("", "Latn"));
scriptsByLocale.put("mgp", getScriptsMap("", ""));
scriptsByLocale.put("mgy", getScriptsMap("", ""));
scriptsByLocale.put("mh", getScriptsMap("", "Latn"));
scriptsByLocale.put("mi", getScriptsMap("", "Latn"));
scriptsByLocale.put("mic", getScriptsMap("", "Latn"));
scriptsByLocale.put("min", getScriptsMap("", "Latn"));
scriptsByLocale.put("mk", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ml", getScriptsMap("", "Mlym"));
scriptsByLocale.put("mn", getScriptsMap("", "Cyrl", "CN", "Mong"));
scriptsByLocale.put("mnc", getScriptsMap("", "Mong"));
scriptsByLocale.put("mni", getScriptsMap("", "Beng", "IN", "Mtei"));
scriptsByLocale.put("mns", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("mnw", getScriptsMap("", "Mymr"));
scriptsByLocale.put("moe", getScriptsMap("", ""));
scriptsByLocale.put("moh", getScriptsMap("", "Latn"));
scriptsByLocale.put("mos", getScriptsMap("", "Latn"));
scriptsByLocale.put("mr", getScriptsMap("", "Deva"));
scriptsByLocale.put("mrd", getScriptsMap("", ""));
scriptsByLocale.put("mrj", getScriptsMap("", ""));
scriptsByLocale.put("ms", getScriptsMap("", "Arab", "MY", "Latn", "SG", "Latn"));
scriptsByLocale.put("mt", getScriptsMap("", "Latn"));
scriptsByLocale.put("mtr", getScriptsMap("", ""));
scriptsByLocale.put("mua", getScriptsMap("", "Latn"));
scriptsByLocale.put("mus", getScriptsMap("", "Latn"));
scriptsByLocale.put("mvy", getScriptsMap("", ""));
scriptsByLocale.put("mwk", getScriptsMap("", ""));
scriptsByLocale.put("mwl", getScriptsMap("", "Latn"));
scriptsByLocale.put("mwr", getScriptsMap("", "Deva"));
scriptsByLocale.put("mxc", getScriptsMap("", ""));
scriptsByLocale.put("my", getScriptsMap("", "Mymr"));
scriptsByLocale.put("myv", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("myx", getScriptsMap("", ""));
scriptsByLocale.put("myz", getScriptsMap("", "Mand"));
scriptsByLocale.put("na", getScriptsMap("", "Latn"));
scriptsByLocale.put("nap", getScriptsMap("", "Latn"));
scriptsByLocale.put("naq", getScriptsMap("", "Latn"));
scriptsByLocale.put("nb", getScriptsMap("", "Latn"));
scriptsByLocale.put("nbf", getScriptsMap("", ""));
scriptsByLocale.put("nch", getScriptsMap("", ""));
scriptsByLocale.put("nd", getScriptsMap("", "Latn"));
scriptsByLocale.put("ndc", getScriptsMap("", ""));
scriptsByLocale.put("nds", getScriptsMap("", "Latn"));
scriptsByLocale.put("ne", getScriptsMap("", "Deva"));
scriptsByLocale.put("new", getScriptsMap("", "Deva"));
scriptsByLocale.put("ng", getScriptsMap("", "Latn"));
scriptsByLocale.put("ngl", getScriptsMap("", ""));
scriptsByLocale.put("nhe", getScriptsMap("", ""));
scriptsByLocale.put("nhw", getScriptsMap("", ""));
scriptsByLocale.put("nia", getScriptsMap("", "Latn"));
scriptsByLocale.put("nij", getScriptsMap("", ""));
scriptsByLocale.put("niu", getScriptsMap("", "Latn"));
scriptsByLocale.put("nl", getScriptsMap("", "Latn"));
scriptsByLocale.put("nmg", getScriptsMap("", "Latn"));
scriptsByLocale.put("nn", getScriptsMap("", "Latn"));
scriptsByLocale.put("nnh", getScriptsMap("", ""));
scriptsByLocale.put("nod", getScriptsMap("", "Lana"));
scriptsByLocale.put("noe", getScriptsMap("", ""));
scriptsByLocale.put("nog", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("nqo", getScriptsMap("", "Nkoo"));
scriptsByLocale.put("nr", getScriptsMap("", "Latn"));
scriptsByLocale.put("nsk", getScriptsMap("", ""));
scriptsByLocale.put("nso", getScriptsMap("", "Latn"));
scriptsByLocale.put("nus", getScriptsMap("", "Latn"));
scriptsByLocale.put("nv", getScriptsMap("", "Latn"));
scriptsByLocale.put("ny", getScriptsMap("", "Latn"));
scriptsByLocale.put("nym", getScriptsMap("", "Latn"));
scriptsByLocale.put("nyn", getScriptsMap("", "Latn"));
scriptsByLocale.put("nyo", getScriptsMap("", "Latn"));
scriptsByLocale.put("nzi", getScriptsMap("", "Latn"));
scriptsByLocale.put("oc", getScriptsMap("", "Latn"));
scriptsByLocale.put("oj", getScriptsMap("", "Cans"));
scriptsByLocale.put("om", getScriptsMap("", "Latn", "ET", "Ethi"));
scriptsByLocale.put("or", getScriptsMap("", "Orya"));
scriptsByLocale.put("os", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("osa", getScriptsMap("", "Latn"));
scriptsByLocale.put("osc", getScriptsMap("", "Ital"));
scriptsByLocale.put("otk", getScriptsMap("", "Orkh"));
scriptsByLocale.put("pa", getScriptsMap("", "Guru", "PK", "Arab"));
scriptsByLocale.put("pag", getScriptsMap("", "Latn"));
scriptsByLocale.put("pal", getScriptsMap("", "Phli"));
scriptsByLocale.put("pam", getScriptsMap("", "Latn"));
scriptsByLocale.put("pap", getScriptsMap("", "Latn"));
scriptsByLocale.put("pau", getScriptsMap("", "Latn"));
scriptsByLocale.put("peo", getScriptsMap("", "Xpeo"));
scriptsByLocale.put("phn", getScriptsMap("", "Phnx"));
scriptsByLocale.put("pi", getScriptsMap("", "Deva"));
scriptsByLocale.put("pko", getScriptsMap("", ""));
scriptsByLocale.put("pl", getScriptsMap("", "Latn"));
scriptsByLocale.put("pon", getScriptsMap("", "Latn"));
scriptsByLocale.put("pra", getScriptsMap("", "Brah"));
scriptsByLocale.put("prd", getScriptsMap("", "Arab"));
scriptsByLocale.put("prg", getScriptsMap("", "Latn"));
scriptsByLocale.put("prs", getScriptsMap("", "Arab"));
scriptsByLocale.put("ps", getScriptsMap("", "Arab"));
scriptsByLocale.put("pt", getScriptsMap("", "Latn"));
scriptsByLocale.put("puu", getScriptsMap("", ""));
scriptsByLocale.put("qu", getScriptsMap("", "Latn"));
scriptsByLocale.put("raj", getScriptsMap("", "Latn"));
scriptsByLocale.put("rap", getScriptsMap("", "Latn"));
scriptsByLocale.put("rar", getScriptsMap("", "Latn"));
scriptsByLocale.put("rcf", getScriptsMap("", "Latn"));
scriptsByLocale.put("rej", getScriptsMap("", "Latn", "ID", "Rjng"));
scriptsByLocale.put("ria", getScriptsMap("", ""));
scriptsByLocale.put("rif", getScriptsMap("", ""));
scriptsByLocale.put("rjs", getScriptsMap("", "Deva"));
scriptsByLocale.put("rkt", getScriptsMap("", "Beng"));
scriptsByLocale.put("rm", getScriptsMap("", "Latn"));
scriptsByLocale.put("rmf", getScriptsMap("", ""));
scriptsByLocale.put("rmo", getScriptsMap("", ""));
scriptsByLocale.put("rmt", getScriptsMap("", ""));
scriptsByLocale.put("rn", getScriptsMap("", "Latn"));
scriptsByLocale.put("rng", getScriptsMap("", ""));
scriptsByLocale.put("ro", getScriptsMap("", "Latn", "RS", "Cyrl"));
scriptsByLocale.put("rob", getScriptsMap("", ""));
scriptsByLocale.put("rof", getScriptsMap("", "Latn"));
scriptsByLocale.put("rom", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ru", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("rue", getScriptsMap("", ""));
scriptsByLocale.put("rup", getScriptsMap("", "Latn"));
scriptsByLocale.put("rw", getScriptsMap("", "Latn"));
scriptsByLocale.put("rwk", getScriptsMap("", "Latn"));
scriptsByLocale.put("ryu", getScriptsMap("", ""));
scriptsByLocale.put("sa", getScriptsMap("", "Deva"));
scriptsByLocale.put("sad", getScriptsMap("", "Latn"));
scriptsByLocale.put("saf", getScriptsMap("", "Latn"));
scriptsByLocale.put("sah", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("sam", getScriptsMap("", "Hebr"));
scriptsByLocale.put("saq", getScriptsMap("", "Latn"));
scriptsByLocale.put("sas", getScriptsMap("", "Latn"));
scriptsByLocale.put("sat", getScriptsMap("", "Latn"));
scriptsByLocale.put("saz", getScriptsMap("", "Saur"));
scriptsByLocale.put("sbp", getScriptsMap("", "Latn"));
scriptsByLocale.put("sc", getScriptsMap("", "Latn"));
scriptsByLocale.put("sck", getScriptsMap("", ""));
scriptsByLocale.put("scn", getScriptsMap("", "Latn"));
scriptsByLocale.put("sco", getScriptsMap("", "Latn"));
scriptsByLocale.put("scs", getScriptsMap("", ""));
scriptsByLocale.put("sd", getScriptsMap("", "Arab", "IN", "Deva"));
scriptsByLocale.put("sdh", getScriptsMap("", "Arab"));
scriptsByLocale.put("se", getScriptsMap("", "Latn", "NO", "Cyrl"));
scriptsByLocale.put("see", getScriptsMap("", "Latn"));
scriptsByLocale.put("sef", getScriptsMap("", ""));
scriptsByLocale.put("seh", getScriptsMap("", "Latn"));
scriptsByLocale.put("sel", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ses", getScriptsMap("", "Latn"));
scriptsByLocale.put("sg", getScriptsMap("", "Latn"));
scriptsByLocale.put("sga", getScriptsMap("", "Latn"));
scriptsByLocale.put("shi", getScriptsMap("", "Tfng"));
scriptsByLocale.put("shn", getScriptsMap("", "Mymr"));
scriptsByLocale.put("si", getScriptsMap("", "Sinh"));
scriptsByLocale.put("sid", getScriptsMap("", "Latn"));
scriptsByLocale.put("sk", getScriptsMap("", "Latn"));
scriptsByLocale.put("skr", getScriptsMap("", ""));
scriptsByLocale.put("sl", getScriptsMap("", "Latn"));
scriptsByLocale.put("sm", getScriptsMap("", "Latn"));
scriptsByLocale.put("sma", getScriptsMap("", "Latn"));
scriptsByLocale.put("smi", getScriptsMap("", "Latn"));
scriptsByLocale.put("smj", getScriptsMap("", "Latn"));
scriptsByLocale.put("smn", getScriptsMap("", "Latn"));
scriptsByLocale.put("sms", getScriptsMap("", "Latn"));
scriptsByLocale.put("sn", getScriptsMap("", "Latn"));
scriptsByLocale.put("snk", getScriptsMap("", "Latn"));
scriptsByLocale.put("so", getScriptsMap("", "Latn"));
scriptsByLocale.put("son", getScriptsMap("", "Latn"));
scriptsByLocale.put("sou", getScriptsMap("", ""));
scriptsByLocale.put("sq", getScriptsMap("", "Latn"));
scriptsByLocale.put("sr", getScriptsMap("", "Latn"));
scriptsByLocale.put("srn", getScriptsMap("", "Latn"));
scriptsByLocale.put("srr", getScriptsMap("", "Latn"));
scriptsByLocale.put("srx", getScriptsMap("", ""));
scriptsByLocale.put("ss", getScriptsMap("", "Latn"));
scriptsByLocale.put("ssy", getScriptsMap("", "Latn"));
scriptsByLocale.put("st", getScriptsMap("", "Latn"));
scriptsByLocale.put("su", getScriptsMap("", "Latn"));
scriptsByLocale.put("suk", getScriptsMap("", "Latn"));
scriptsByLocale.put("sus", getScriptsMap("", "Latn", "GN", "Arab"));
scriptsByLocale.put("sv", getScriptsMap("", "Latn"));
scriptsByLocale.put("sw", getScriptsMap("", "Latn"));
scriptsByLocale.put("swb", getScriptsMap("", "Arab", "YT", "Latn"));
scriptsByLocale.put("swc", getScriptsMap("", "Latn"));
scriptsByLocale.put("swv", getScriptsMap("", ""));
scriptsByLocale.put("sxn", getScriptsMap("", ""));
scriptsByLocale.put("syi", getScriptsMap("", ""));
scriptsByLocale.put("syl", getScriptsMap("", "Beng", "BD", "Sylo"));
scriptsByLocale.put("syr", getScriptsMap("", "Syrc"));
scriptsByLocale.put("ta", getScriptsMap("", "Taml"));
scriptsByLocale.put("tab", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("taj", getScriptsMap("", ""));
scriptsByLocale.put("tbw", getScriptsMap("", "Latn"));
scriptsByLocale.put("tcy", getScriptsMap("", "Knda"));
scriptsByLocale.put("tdd", getScriptsMap("", "Tale"));
scriptsByLocale.put("tdg", getScriptsMap("", ""));
scriptsByLocale.put("tdh", getScriptsMap("", ""));
scriptsByLocale.put("te", getScriptsMap("", "Telu"));
scriptsByLocale.put("tem", getScriptsMap("", "Latn"));
scriptsByLocale.put("teo", getScriptsMap("", "Latn"));
scriptsByLocale.put("ter", getScriptsMap("", "Latn"));
scriptsByLocale.put("tet", getScriptsMap("", "Latn"));
scriptsByLocale.put("tg", getScriptsMap("", "Cyrl", "PK", "Arab"));
scriptsByLocale.put("th", getScriptsMap("", "Thai"));
scriptsByLocale.put("thl", getScriptsMap("", ""));
scriptsByLocale.put("thq", getScriptsMap("", ""));
scriptsByLocale.put("thr", getScriptsMap("", ""));
scriptsByLocale.put("ti", getScriptsMap("", "Ethi"));
scriptsByLocale.put("tig", getScriptsMap("", "Ethi"));
scriptsByLocale.put("tiv", getScriptsMap("", "Latn"));
scriptsByLocale.put("tk", getScriptsMap("", "Latn"));
scriptsByLocale.put("tkl", getScriptsMap("", "Latn"));
scriptsByLocale.put("tkt", getScriptsMap("", ""));
scriptsByLocale.put("tli", getScriptsMap("", "Latn"));
scriptsByLocale.put("tmh", getScriptsMap("", "Latn"));
scriptsByLocale.put("tn", getScriptsMap("", "Latn"));
scriptsByLocale.put("to", getScriptsMap("", "Latn"));
scriptsByLocale.put("tog", getScriptsMap("", "Latn"));
scriptsByLocale.put("tpi", getScriptsMap("", "Latn"));
scriptsByLocale.put("tr", getScriptsMap("", "Latn", "DE", "Arab", "MK", "Arab"));
scriptsByLocale.put("tru", getScriptsMap("", "Latn"));
scriptsByLocale.put("trv", getScriptsMap("", "Latn"));
scriptsByLocale.put("ts", getScriptsMap("", "Latn"));
scriptsByLocale.put("tsf", getScriptsMap("", ""));
scriptsByLocale.put("tsg", getScriptsMap("", "Latn"));
scriptsByLocale.put("tsi", getScriptsMap("", "Latn"));
scriptsByLocale.put("tsj", getScriptsMap("", ""));
scriptsByLocale.put("tt", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("ttj", getScriptsMap("", ""));
scriptsByLocale.put("tts", getScriptsMap("", "Thai"));
scriptsByLocale.put("tum", getScriptsMap("", "Latn"));
scriptsByLocale.put("tut", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("tvl", getScriptsMap("", "Latn"));
scriptsByLocale.put("twq", getScriptsMap("", "Latn"));
scriptsByLocale.put("ty", getScriptsMap("", "Latn"));
scriptsByLocale.put("tyv", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("tzm", getScriptsMap("", "Latn"));
scriptsByLocale.put("ude", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("udm", getScriptsMap("", "Cyrl", "RU", "Latn"));
scriptsByLocale.put("ug", getScriptsMap("", "Arab", "KZ", "Cyrl", "MN", "Cyrl"));
scriptsByLocale.put("uga", getScriptsMap("", "Ugar"));
scriptsByLocale.put("uk", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("uli", getScriptsMap("", "Latn"));
scriptsByLocale.put("umb", getScriptsMap("", "Latn"));
scriptsByLocale.put("und", getScriptsMap("", ""));
scriptsByLocale.put("unr", getScriptsMap("", "Beng", "NP", "Deva"));
scriptsByLocale.put("unx", getScriptsMap("", "Beng"));
scriptsByLocale.put("ur", getScriptsMap("", "Arab"));
scriptsByLocale.put("uz", getScriptsMap("", "Latn", "AF", "Arab", "CN", "Cyrl"));
scriptsByLocale.put("vai", getScriptsMap("", "Vaii"));
scriptsByLocale.put("ve", getScriptsMap("", "Latn"));
scriptsByLocale.put("vi", getScriptsMap("", "Latn", "US", "Hani"));
scriptsByLocale.put("vic", getScriptsMap("", ""));
scriptsByLocale.put("vmw", getScriptsMap("", ""));
scriptsByLocale.put("vo", getScriptsMap("", "Latn"));
scriptsByLocale.put("vot", getScriptsMap("", "Latn"));
scriptsByLocale.put("vun", getScriptsMap("", "Latn"));
scriptsByLocale.put("wa", getScriptsMap("", "Latn"));
scriptsByLocale.put("wae", getScriptsMap("", "Latn"));
scriptsByLocale.put("wak", getScriptsMap("", "Latn"));
scriptsByLocale.put("wal", getScriptsMap("", "Ethi"));
scriptsByLocale.put("war", getScriptsMap("", "Latn"));
scriptsByLocale.put("was", getScriptsMap("", "Latn"));
scriptsByLocale.put("wbq", getScriptsMap("", ""));
scriptsByLocale.put("wbr", getScriptsMap("", ""));
scriptsByLocale.put("wls", getScriptsMap("", ""));
scriptsByLocale.put("wo", getScriptsMap("", "Latn"));
scriptsByLocale.put("wtm", getScriptsMap("", ""));
scriptsByLocale.put("xal", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("xav", getScriptsMap("", ""));
scriptsByLocale.put("xcr", getScriptsMap("", "Cari"));
scriptsByLocale.put("xh", getScriptsMap("", "Latn"));
scriptsByLocale.put("xnr", getScriptsMap("", ""));
scriptsByLocale.put("xog", getScriptsMap("", "Latn"));
scriptsByLocale.put("xpr", getScriptsMap("", "Prti"));
scriptsByLocale.put("xsa", getScriptsMap("", "Sarb"));
scriptsByLocale.put("xsr", getScriptsMap("", "Deva"));
scriptsByLocale.put("xum", getScriptsMap("", "Ital"));
scriptsByLocale.put("yao", getScriptsMap("", "Latn"));
scriptsByLocale.put("yap", getScriptsMap("", "Latn"));
scriptsByLocale.put("yav", getScriptsMap("", "Latn"));
scriptsByLocale.put("ybb", getScriptsMap("", ""));
scriptsByLocale.put("yi", getScriptsMap("", "Hebr"));
scriptsByLocale.put("yo", getScriptsMap("", "Latn"));
scriptsByLocale.put("yrk", getScriptsMap("", "Cyrl"));
scriptsByLocale.put("yua", getScriptsMap("", ""));
scriptsByLocale.put("yue", getScriptsMap("", "Hans"));
scriptsByLocale.put("za", getScriptsMap("", "Latn", "CN", "Hans"));
scriptsByLocale.put("zap", getScriptsMap("", "Latn"));
scriptsByLocale.put("zdj", getScriptsMap("", ""));
scriptsByLocale.put("zea", getScriptsMap("", ""));
scriptsByLocale.put("zen", getScriptsMap("", "Tfng"));
scriptsByLocale.put("zh", getScriptsMap("", "Hant", "CN", "Hans", "HK", "Hans", "MO", "Hans", "SG", "Hans", "MN", "Hans"));
scriptsByLocale.put("zmi", getScriptsMap("", ""));
scriptsByLocale.put("zu", getScriptsMap("", "Latn"));
scriptsByLocale.put("zun", getScriptsMap("", "Latn"));
scriptsByLocale.put("zza", getScriptsMap("", "Arab"));
}
/**
* Gets the script (writing type) for the given locale. For example, if a US citizen uses German Locale,
* and calls this method with Locale.getDefault(), the result would be "Runr"
*
* @param locale
* @return
*/
public static String getScript(Locale locale) {
String localeString = locale.toString();
String language = "";
String country = "";
if (localeString.contains("_")) {
String[] split = localeString.split("_");
language = split[0];
country = split[1];
} else language = localeString;
Map<String, String> scripts = scriptsByLocale.get(language);
String script = scripts.get(country);
return script == null ? scripts.get("") : script;
}
/**
* Obtain right locale even if the user changes their Locale in settings after your application process is running.
* Android N (Api level 24) update (no warnings).
* @param context activity
* @return locale
*/
public static Locale getCurrentLocale(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
return context.getResources().getConfiguration().getLocales().get(0);
} else{
//noinspection deprecation
return context.getResources().getConfiguration().locale;
}
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:id="@+id/root"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Useful links: -->
<!-- com.android.internal.widget.DialogTitle: https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/layout/alert_dialog.xml -->
<!-- <declare-styleable name="TextAppearance">: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/res/values/attrs.xml -->
<!-- https://android.googlesource.com/platform/frameworks/base/+/de47f1c358c8186ff3e14b887d5869f69b9a9d6c/core/java/com/android/internal/widget/DialogTitle.java -->
<!-- https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/app/AlertController.java -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/title_template"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dip">
<!-- Use the same widget as used in AlertDialog -->
<TextView android:id="@+id/alertTitle1"
android:text="@string/language_dialog_title"
style="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"/>
<TextView android:id="@+id/alertTitle2"
android:text="@string/language_dialog_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"/>
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Leanback Keyboard</string>
<string name="ime_service_name">Leanback Keyboard</string>
<string name="word_separators">" .,;:!?
()[]*&amp;@{}/&lt;>_+=|"</string>
<string name="label_go_key">Go</string>
<string name="label_next_key">Next</string>
<string name="label_send_key">Send</string>
<string name="label_search_key">Search</string>
<string name="label_done_key">Done</string>
<string name="settings_title">Keyboard Options</string>
<string name="title_movement_sensitivity">Movement sensitivity</string>
<string name="btn_on">On</string>
<string name="btn_off">Off</string>
<string name="keyboardview_keycode_space">Space</string>
<string name="keyboardview_keycode_delete">Delete</string>
<string name="keyboardview_keycode_mode_change">Mode change</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Left</string>
<string name="keyboardview_keycode_right">Right</string>
<string name="keyboard_headset_required_to_hear_password">Plug in a headset to hear password keys spoken.</string>
<string name="keyboard_password_character_no_headset">Dot.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">لوحة مفاتيح Leanback</string>
<string name="ime_service_name">لوحة مفاتيح Leanback</string>
<string name="label_go_key">انتقال</string>
<string name="label_next_key">التالي</string>
<string name="label_send_key">إرسال</string>
<string name="label_search_key">بحث</string>
<string name="label_done_key">تم</string>
<string name="settings_title">خيارات لوحة المفاتيح</string>
<string name="title_movement_sensitivity">حساسية الحركة</string>
<string name="btn_on">تشغيل</string>
<string name="btn_off">إيقاف</string>
<string name="keyboardview_keycode_space">مسافة</string>
<string name="keyboardview_keycode_delete">حذف</string>
<string name="keyboardview_keycode_mode_change">تغيير الوضع</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">لليسار</string>
<string name="keyboardview_keycode_right">لليمين</string>
<string name="keyboard_headset_required_to_hear_password">يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور عندما يتم نطقها.</string>
<string name="keyboard_password_character_no_headset">نقطة</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Клавиатура за Leanback</string>
<string name="ime_service_name">Клавиатура за Leanback</string>
<string name="label_go_key">Старт</string>
<string name="label_next_key">Напред</string>
<string name="label_send_key">Изпращане</string>
<string name="label_search_key">Търсене</string>
<string name="label_done_key">Готово</string>
<string name="settings_title">Опции за клавиатурата</string>
<string name="title_movement_sensitivity">Чувствителност на движението</string>
<string name="btn_on">Включено</string>
<string name="btn_off">Изключено</string>
<string name="keyboardview_keycode_space">Space</string>
<string name="keyboardview_keycode_delete">Изтриване</string>
<string name="keyboardview_keycode_mode_change">Промяна на режима</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Left</string>
<string name="keyboardview_keycode_right">Right</string>
<string name="keyboard_headset_required_to_hear_password">Включете слушалки, за да чуете изговарянето на клавишите за паролата.</string>
<string name="keyboard_password_character_no_headset">Точка.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Leanback-Tastatur</string>
<string name="ime_service_name">Leanback-Tastatur</string>
<string name="label_go_key">Los</string>
<string name="label_next_key">Weiter</string>
<string name="label_send_key">Senden</string>
<string name="label_search_key">Suchen</string>
<string name="label_done_key">Fertig</string>
<string name="settings_title">Tastaturoptionen</string>
<string name="title_movement_sensitivity">Bewegungsempfindlichkeit</string>
<string name="btn_on">An</string>
<string name="btn_off">Aus</string>
<string name="keyboardview_keycode_space">Leertaste</string>
<string name="keyboardview_keycode_delete">Löschen</string>
<string name="keyboardview_keycode_mode_change">Modusänderung</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Feststelltaste</string>
<string name="keyboardview_keycode_left">Nach links</string>
<string name="keyboardview_keycode_right">Nach rechts</string>
<string name="keyboard_headset_required_to_hear_password">Schließen Sie ein Headset an, um das Passwort gesprochen zu hören.</string>
<string name="keyboard_password_character_no_headset">Punkt.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Πληκτρολόγιο Leanback</string>
<string name="ime_service_name">Πληκτρολόγιο Leanback</string>
<string name="label_go_key">Μετάβαση</string>
<string name="label_next_key">Επόμενο</string>
<string name="label_send_key">Αποστολή</string>
<string name="label_search_key">Αναζήτηση</string>
<string name="label_done_key">Τέλος</string>
<string name="settings_title">Επιλογές πληκτρολογίου</string>
<string name="title_movement_sensitivity">Ευαισθησία κίνησης</string>
<string name="btn_on">Ενεργοποίηση</string>
<string name="btn_off">Απενεργοποίηση</string>
<string name="keyboardview_keycode_space">Πλήκτρο διαστήματος</string>
<string name="keyboardview_keycode_delete">Διαγραφή</string>
<string name="keyboardview_keycode_mode_change">Αλλαγή τρόπου</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Αριστερά</string>
<string name="keyboardview_keycode_right">Δεξιά</string>
<string name="keyboard_headset_required_to_hear_password">Συνδέστε ακουστικά για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται.</string>
<string name="keyboard_password_character_no_headset">Τελεία.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">صفحه‌کلید Leanback</string>
<string name="ime_service_name">صفحه‌کلید Leanback</string>
<string name="label_go_key">برو</string>
<string name="label_next_key">بعدی</string>
<string name="label_send_key">ارسال</string>
<string name="label_search_key">جستجو</string>
<string name="label_done_key">انجام شد</string>
<string name="settings_title">گزینه‌های صفحه‌کلید</string>
<string name="title_movement_sensitivity">حساسیت حرکت</string>
<string name="btn_on">فعال</string>
<string name="btn_off">خاموش</string>
<string name="keyboardview_keycode_space">فاصله</string>
<string name="keyboardview_keycode_delete">حذف</string>
<string name="keyboardview_keycode_mode_change">تغییر حالت</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">چپ</string>
<string name="keyboardview_keycode_right">راست</string>
<string name="keyboard_headset_required_to_hear_password">هدست را برای شنیدن کلیدهای گذرواژه که خوانده می‌شوند، وصل کنید.</string>
<string name="keyboard_password_character_no_headset">نقطه.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Clavier Leanback</string>
<string name="ime_service_name">Clavier Leanback</string>
<string name="label_go_key">OK</string>
<string name="label_next_key">Suivant</string>
<string name="label_send_key">Envoyer</string>
<string name="label_search_key">Rechercher</string>
<string name="label_done_key">OK</string>
<string name="settings_title">Options de clavier</string>
<string name="title_movement_sensitivity">Sensibilité du déplacement</string>
<string name="btn_on">Activer</string>
<string name="btn_off">Désactiver</string>
<string name="keyboardview_keycode_space">Espace</string>
<string name="keyboardview_keycode_delete">Supprimer</string>
<string name="keyboardview_keycode_mode_change">Changement de mode</string>
<string name="keyboardview_keycode_shift">Maj</string>
<string name="keyboardview_keycode_caps">Verrouillage des majuscules</string>
<string name="keyboardview_keycode_left">Gauche</string>
<string name="keyboardview_keycode_right">Droite</string>
<string name="keyboard_headset_required_to_hear_password">"Branchez un casque pour entendre l'énoncé des touches lors de la saisie du mot de passe."</string>
<string name="keyboard_password_character_no_headset">Point.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Leanback lyklaborð</string>
<string name="ime_service_name">Leanback lyklaborð</string>
<string name="label_go_key">Áfram</string>
<string name="label_next_key">Næsta</string>
<string name="label_send_key">Senda</string>
<string name="label_search_key">Leita</string>
<string name="label_done_key">Lokið</string>
<string name="settings_title">Valkostir lyklaborðs</string>
<string name="title_movement_sensitivity">Hreyfinæmi</string>
<string name="btn_on">Kveikt</string>
<string name="btn_off">Slökkt</string>
<string name="keyboardview_keycode_space">Bil</string>
<string name="keyboardview_keycode_delete">Eyða</string>
<string name="keyboardview_keycode_mode_change">Breyta stillingu</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Hástafalás</string>
<string name="keyboardview_keycode_left">Vinstri</string>
<string name="keyboardview_keycode_right">Hægri</string>
<string name="keyboard_headset_required_to_hear_password">Tengdu heyrnartól til að heyra stafi aðgangsorðsins lesna upphátt.</string>
<string name="keyboard_password_character_no_headset">Punktur.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Tastiera Leanback</string>
<string name="ime_service_name">Tastiera Leanback</string>
<string name="label_go_key">Vai</string>
<string name="label_next_key">Avanti</string>
<string name="label_send_key">Invia</string>
<string name="label_search_key">Cerca</string>
<string name="label_done_key">Fine</string>
<string name="settings_title">Opzioni tastiera</string>
<string name="title_movement_sensitivity">Sensibilità movimento</string>
<string name="btn_on">Attiva</string>
<string name="btn_off">Disattiva</string>
<string name="keyboardview_keycode_space">Spazio</string>
<string name="keyboardview_keycode_delete">Elimina</string>
<string name="keyboardview_keycode_mode_change">Cambio modalità</string>
<string name="keyboardview_keycode_shift">Maiusc</string>
<string name="keyboardview_keycode_caps">Bloc Maiusc</string>
<string name="keyboardview_keycode_left">Sinistra</string>
<string name="keyboardview_keycode_right">Destra</string>
<string name="keyboard_headset_required_to_hear_password">Collega gli auricolari per ascoltare la pronuncia dei tasti premuti per la password.</string>
<string name="keyboard_password_character_no_headset">Punto.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Toetsenbord voor Leanback</string>
<string name="ime_service_name">Toetsenbord voor Leanback</string>
<string name="label_go_key">Gaan</string>
<string name="label_next_key">Volgende</string>
<string name="label_send_key">Verzenden</string>
<string name="label_search_key">Zoeken</string>
<string name="label_done_key">Gereed</string>
<string name="settings_title">Toetsenbordopties</string>
<string name="title_movement_sensitivity">Gevoeligheid beweging</string>
<string name="btn_on">Aan</string>
<string name="btn_off">Uit</string>
<string name="keyboardview_keycode_space">Spatiebalk</string>
<string name="keyboardview_keycode_delete">Verwijderen</string>
<string name="keyboardview_keycode_mode_change">Modus wijzigen</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Links</string>
<string name="keyboardview_keycode_right">Rechts</string>
<string name="keyboard_headset_required_to_hear_password">Sluit een headset aan om wachtwoordtoetsen te laten voorlezen.</string>
<string name="keyboard_password_character_no_headset">Stip.</string>
</resources>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Клавиатура Leanback</string>
<string name="ime_service_name">Клавиатура Leanback</string>
<string name="label_go_key">ОК</string>
<string name="label_next_key">Далее</string>
<string name="label_send_key">Отправить</string>
<string name="label_search_key">Поиск</string>
<string name="label_done_key">Готово</string>
<string name="settings_title">Настройки клавиатуры</string>
<string name="title_movement_sensitivity">Обработка движений</string>
<string name="btn_on">ВКЛ</string>
<string name="btn_off">ВЫКЛ</string>
<string name="keyboardview_keycode_space">Пробел.</string>
<string name="keyboardview_keycode_delete">Удалить</string>
<string name="keyboardview_keycode_mode_change">Смена режима</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Стрелка влево</string>
<string name="keyboardview_keycode_right">Стрелка вправо</string>
<string name="keyboard_headset_required_to_hear_password">Подключите гарнитуру, чтобы услышать пароль.</string>
<string name="keyboard_password_character_no_headset">Точка</string>
<string name="language_dialog_title">Выберите дополнительные раскладки</string>
<string name="language_dialog_subtitle">Чтобы открыть этот диалог, зажмите кнопку \'земной шар\'</string>
</resources>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Tangentbord för Leanback</string>
<string name="ime_service_name">Tangentbord för Leanback</string>
<string name="label_go_key">Kör</string>
<string name="label_next_key">Nästa</string>
<string name="label_send_key">Skicka</string>
<string name="label_search_key">Sök</string>
<string name="label_done_key">Klar</string>
<string name="settings_title">Tangentbordsinställningar</string>
<string name="title_movement_sensitivity">Rörelsekänslighet</string>
<string name="btn_on"></string>
<string name="btn_off">Av</string>
<string name="keyboardview_keycode_space">Blanksteg</string>
<string name="keyboardview_keycode_delete">Ta bort</string>
<string name="keyboardview_keycode_mode_change">Funktionsändring</string>
<string name="keyboardview_keycode_shift">Skift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Vänster</string>
<string name="keyboardview_keycode_right">Höger</string>
<string name="keyboard_headset_required_to_hear_password">Anslut hörlurar om du vill höra lösenordet tecken för tecken.</string>
<string name="keyboard_password_character_no_headset">Punkt.</string>
<string name="keyboardview_keycode_lang">Språk</string>
<string name="language_dialog_title">Välj layouter</string>
<string name="language_dialog_subtitle">"För att öppna dialogen nästa gång, tryck länge på knappen med världsikonen</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">แป้นพิมพ์ Leanback</string>
<string name="ime_service_name">แป้นพิมพ์ Leanback</string>
<string name="label_go_key">ไป</string>
<string name="label_next_key">ถัดไป</string>
<string name="label_send_key">ส่ง</string>
<string name="label_search_key">ค้นหา</string>
<string name="label_done_key">เสร็จสิ้น</string>
<string name="settings_title">ตัวเลือกแป้นพิมพ์</string>
<string name="title_movement_sensitivity">ความไวในการเคลื่อนที่</string>
<string name="btn_on">เปิด</string>
<string name="btn_off">ปิด</string>
<string name="keyboardview_keycode_space">วรรค</string>
<string name="keyboardview_keycode_delete">ลบ</string>
<string name="keyboardview_keycode_mode_change">เปลี่ยนโหมด</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">ซ้าย</string>
<string name="keyboardview_keycode_right">ขวา</string>
<string name="keyboard_headset_required_to_hear_password">เสียบชุดหูฟังเพื่อฟังเสียงรหัสผ่าน</string>
<string name="keyboard_password_character_no_headset">เครื่องหมายจุด</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Leanback Klavyesi</string>
<string name="ime_service_name">Leanback Klavyesi</string>
<string name="label_go_key">Git</string>
<string name="label_next_key">İleri</string>
<string name="label_send_key">Gönder</string>
<string name="label_search_key">Ara</string>
<string name="label_done_key">Bitti</string>
<string name="settings_title">Klavye Seçenekleri</string>
<string name="title_movement_sensitivity">Hareket duyarlılığı</string>
<string name="btn_on"></string>
<string name="btn_off">Kapat</string>
<string name="keyboardview_keycode_space">Boşluk</string>
<string name="keyboardview_keycode_delete">Sil</string>
<string name="keyboardview_keycode_mode_change">Mod değiştir</string>
<string name="keyboardview_keycode_shift">ÜstKrktr</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Sol</string>
<string name="keyboardview_keycode_right">Sağ</string>
<string name="keyboard_headset_required_to_hear_password">Şifre tuşlarının sesli okunmasını dinlemek için mikrofonlu kulaklık takın.</string>
<string name="keyboard_password_character_no_headset">Nokta.</string>
</resources>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">Клавіатура додатка Leanback</string>
<string name="ime_service_name">Клавіатура додатка Leanback</string>
<string name="label_go_key">ОК</string>
<string name="label_next_key">Далі</string>
<string name="label_send_key">Надіслати</string>
<string name="label_search_key">Пошук</string>
<string name="label_done_key">Готово</string>
<string name="settings_title">Параметри клавіатури</string>
<string name="title_movement_sensitivity">Чутливість руху</string>
<string name="btn_on">Увімкнути</string>
<string name="btn_off">Вимкнути</string>
<string name="keyboardview_keycode_space">Пробіл</string>
<string name="keyboardview_keycode_delete">Видалити</string>
<string name="keyboardview_keycode_mode_change">Зміна режиму</string>
<string name="keyboardview_keycode_shift">Клавіша Shift</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Ліворуч</string>
<string name="keyboardview_keycode_right">Праворуч</string>
<string name="keyboard_headset_required_to_hear_password">Підключіть гарнітуру, щоб почути символи пароля.</string>
<string name="keyboard_password_character_no_headset">Крапка.</string>
</resources>

View File

@@ -2,7 +2,12 @@
<resources>
<dimen name="key_height">28.0dip</dimen>
<dimen name="key_width">28.0dip</dimen>
<dimen name="space_key_width">268.0dip</dimen>
<!--
NOTE: don't change space size unless you've setup constants here:
LeanbackKeyboardView.ASCII_PERIOD, LeanbackKeyboardView.ASCII_PERIOD_LEN
Old space width: 268.0dip
-->
<dimen name="space_key_width">230.0dip</dimen>
<dimen name="keyboard_horizontal_gap">12.0dip</dimen>
<dimen name="keyboard_vertical_gap">8.0dip</dimen>
<dimen name="recognizer_size">96.0dip</dimen>
@@ -22,4 +27,6 @@
<dimen name="key_font_size">18.0sp</dimen>
<dimen name="function_key_mode_change_font_size">16.0sp</dimen>
<dimen name="resize_move_distance">12.0dip</dimen>
<dimen name="text_size_dp">15dp</dimen>
<dimen name="text_size_big_dp">25dp</dimen>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="additional_languages">
<item>English|us</item>
<item>Arabic|ar</item>
<item>Bulgarian|bg</item>
<item>Dutch|nl</item>
<item>French|fr</item>
<item>German|de</item>
<item>Greek|el</item>
<item>Hebrew|he</item>
<item>Icelandic|is</item>
<item>Italian|it</item>
<item>Persian|fa</item>
<item>Russian|ru</item>
<item>Swedish|sv</item>
<item>Thai|th</item>
<item>Turkish|tr</item>
<item>Ukrainian|uk</item>
</string-array>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ime_name">LeanKey Keyboard</string>
<string name="ime_service_name">LeanKey Keyboard</string>
<string name="ime_name">LeanKey Keyboard Pro</string>
<string name="ime_service_name">LeanKey Keyboard Pro</string>
<string name="word_separators">" .,;:!?
()[]*&amp;@{}/&lt;>_+=|"</string>
<string name="label_go_key">Go</string>
@@ -18,9 +18,12 @@
<string name="keyboardview_keycode_delete">Delete</string>
<string name="keyboardview_keycode_mode_change">Mode change</string>
<string name="keyboardview_keycode_shift">Shift</string>
<string name="keyboardview_keycode_lang">Language</string>
<string name="keyboardview_keycode_caps">Caps Lock</string>
<string name="keyboardview_keycode_left">Left</string>
<string name="keyboardview_keycode_right">Right</string>
<string name="keyboard_headset_required_to_hear_password">Plug in a headset to hear password keys spoken.</string>
<string name="keyboard_password_character_no_headset">Dot.</string>
<string name="language_dialog_title">Select additional layouts</string>
<string name="language_dialog_subtitle">To open dialog next time, long press on \'world\' button</string>
</resources>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextAppearance">
<!-- Text color. -->
<attr name="textColor" format="color" />
<!-- Size of the text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp). -->
<attr name="textSize" format="dimension" />
<!-- Style (bold, italic, bolditalic) for the text. -->
<attr name="textStyle" format="reference" />
<!-- Typeface (normal, sans, serif, monospace) for the text. -->
<attr name="typeface" format="string" />
<!-- Font family (named by string) for the text. -->
<attr name="fontFamily" format="string" />
<!-- Color of the text selection highlight. -->
<attr name="textColorHighlight" format="color" />
<!-- Color of the hint text. -->
<attr name="textColorHint" format="color" />
<!-- Color of the links. -->
<attr name="textColorLink" format="color" />
<!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
<attr name="textAllCaps" format="boolean" />
<!-- Place a blurred shadow of text underneath the text, drawn with the
specified color. The text shadow produced does not interact with
properties on View that are responsible for real time shadows,
{@link android.R.styleable#View_elevation elevation} and
{@link android.R.styleable#View_translationZ translationZ}. -->
<attr name="shadowColor" format="color" />
<!-- Horizontal offset of the text shadow. -->
<attr name="shadowDx" format="float" />
<!-- Vertical offset of the text shadow. -->
<attr name="shadowDy" format="float" />
<!-- Blur radius of the text shadow. -->
<attr name="shadowRadius" format="float" />
<!-- Elegant text height, especially for less compacted complex script text. -->
<attr name="elegantTextHeight" format="boolean" />
<!-- Text letter-spacing. -->
<attr name="letterSpacing" format="float" />
<!-- Font feature settings. -->
<attr name="fontFeatureSettings" format="string" />
</declare-styleable>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:keyLabel="آ" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="97" android:keyLabel="a" />
<Key android:codes="225" android:keyLabel="á" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="101" android:keyLabel="e" />
<Key android:codes="233" android:keyLabel="é" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="105" android:keyLabel="i" />
<Key android:codes="237" android:keyLabel="í" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="111" android:keyLabel="o" />
<Key android:codes="243" android:keyLabel="ó" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="117" android:keyLabel="u" />
<Key android:codes="250" android:keyLabel="ú" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:codes="121" android:keyLabel="y" />
<Key android:codes="236" android:keyLabel="ý" />
</Row>
</Keyboard>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:keyEdgeFlags="left" android:keyIcon="@drawable/ic_ime_accent_close" />
<Key android:codes="1573" android:keyLabel="إ" />
</Row>
</Keyboard>

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