mirror of
https://github.com/yuliskov/LeanKeyboard.git
synced 2026-05-03 05:12:36 -04:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e7db94a30 | ||
|
|
80b76e9d1e | ||
|
|
8c1c36cf0e | ||
|
|
a4d615bbf2 | ||
|
|
5e8e68de44 | ||
|
|
48e12a21d1 | ||
|
|
6a8b9c63e5 | ||
|
|
95ab858296 |
@@ -47,9 +47,8 @@ __Standard installation via ADB__
|
||||
|
||||
### Donation:
|
||||
If you want to support my developments you are welcome to buy me a cup of coffee :)
|
||||
* BTC: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
|
||||
* WMZ: Z375157140784
|
||||
* WMU: U449339012933
|
||||
* [__PrivatBank (Ukraine)__](https://privatbank.ua/ru/sendmoney?payment=5fcdddf53e3d491d63fcb050e6e2e05f2f2678c2)
|
||||
* __BTC__: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
|
||||
|
||||
### Screens:
|
||||

|
||||
|
||||
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "org.liskovsoft.leankeykeyboard.pro"
|
||||
minSdkVersion project.properties.minSdkVersion
|
||||
targetSdkVersion project.properties.targetSdkVersion
|
||||
versionCode 71
|
||||
versionName "4.3.21"
|
||||
versionCode 77
|
||||
versionName "4.3.27"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -320,10 +320,10 @@ public class LeanbackKeyboardContainer {
|
||||
* Init currently displayed keyboard<br/>
|
||||
* Note: all keyboard settings applied here<br/>
|
||||
* Note: this method is called constantly on new field
|
||||
* @param resources resources (not used)
|
||||
* @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;
|
||||
@@ -1132,7 +1132,7 @@ public class LeanbackKeyboardContainer {
|
||||
}
|
||||
|
||||
public void updateAddonKeyboard() {
|
||||
mKeyboardManager = new KeyboardManager(mContext, mAbcKeyboard);
|
||||
mKeyboardManager = new KeyboardManager(mContext);
|
||||
switchToNextKeyboard();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,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;
|
||||
@@ -154,14 +155,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));
|
||||
@@ -437,7 +443,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;
|
||||
@@ -607,7 +614,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;
|
||||
@@ -653,7 +660,8 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
|
||||
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.getDeviceId() > 0 && event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
|
||||
if (event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
|
||||
|
||||
mDownFocus.set(mContainer.getCurrFocus());
|
||||
if (mSpaceTracker != null && mSpaceTracker.onKeyDown(keyCode, event)) {
|
||||
@@ -743,31 +751,37 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
|
||||
@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;
|
||||
|
||||
@@ -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;
|
||||
@@ -161,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:
|
||||
@@ -210,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();
|
||||
@@ -271,14 +283,39 @@ 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -298,7 +335,7 @@ public class LeanbackImeService extends InputMethodService {
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class KeyboardManager {
|
||||
private final Keyboard mEnglishKeyboard;
|
||||
private final Context mContext;
|
||||
private final KeyboardStateManager mStateManager;
|
||||
private List<? extends KeyboardBuilder> mKeyboardBuilders;
|
||||
@@ -17,13 +16,8 @@ public class KeyboardManager {
|
||||
|
||||
private int mKeyboardIndex = 0;
|
||||
|
||||
public KeyboardManager(Context ctx, int keyboardResId) {
|
||||
this(ctx, new Keyboard(ctx, keyboardResId));
|
||||
}
|
||||
|
||||
public KeyboardManager(Context ctx, Keyboard englishKeyboard) {
|
||||
public KeyboardManager(Context ctx) {
|
||||
mContext = ctx;
|
||||
mEnglishKeyboard = englishKeyboard;
|
||||
mStateManager = new KeyboardStateManager(mContext, this);
|
||||
mStateManager.restore();
|
||||
init();
|
||||
@@ -37,7 +31,6 @@ public class KeyboardManager {
|
||||
|
||||
private List<Keyboard> buildAllKeyboards() {
|
||||
List<Keyboard> keyboards = new ArrayList<>();
|
||||
keyboards.add(mEnglishKeyboard);
|
||||
if (!mKeyboardBuilders.isEmpty()) {
|
||||
for (KeyboardBuilder builder : mKeyboardBuilders) {
|
||||
keyboards.add(builder.createKeyboard());
|
||||
|
||||
@@ -21,26 +21,37 @@ public class ResKeyboardFactory implements KeyboardFactory {
|
||||
@Override
|
||||
public List<? extends KeyboardBuilder> getAllAvailableKeyboards(Context context) {
|
||||
List<KeyboardBuilder> result = new ArrayList<>();
|
||||
|
||||
List<KeyboardInfo> infos = ResKeyboardInfo.getAllKeyboardInfos(context);
|
||||
final Resources resources = mContext.getResources();
|
||||
|
||||
for (final KeyboardInfo info : infos) {
|
||||
if (!info.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(new KeyboardBuilder() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Keyboard createKeyboard() {
|
||||
return new Keyboard(mContext, resources.getIdentifier("qwerty_" + info.getLangCode(), "xml", mContext.getPackageName()));
|
||||
}
|
||||
});
|
||||
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();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="additional_languages">
|
||||
<item>Swedish|sv</item>
|
||||
<item>English|us</item>
|
||||
<item>Arabic|ar</item>
|
||||
<item>Bulgarian|bg</item>
|
||||
<item>Dutch|nl</item>
|
||||
@@ -13,6 +13,7 @@
|
||||
<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>
|
||||
|
||||
7
leankeykeyboard/src/main/res/xml/accent_fa_a.xml
Normal file
7
leankeykeyboard/src/main/res/xml/accent_fa_a.xml
Normal 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>
|
||||
@@ -37,7 +37,8 @@
|
||||
<Key android:keyLabel="ی" />
|
||||
<Key android:keyLabel="ب" />
|
||||
<Key android:keyLabel="ل" />
|
||||
<Key android:keyLabel="ا" />
|
||||
<!-- fix from Shobair Mohammadi <shobairmohammadi@gmail.com> -->
|
||||
<Key android:keyLabel="ا|آ" android:popupKeyboard="@xml/accent_fa_a" />
|
||||
<Key android:keyLabel="ت" />
|
||||
<Key android:keyLabel="ن" />
|
||||
<Key android:keyLabel="م" />
|
||||
|
||||
Reference in New Issue
Block a user