mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-19 06:47:41 +00:00
Merge pull request #341 from keymanapp/android-modifier-chirality
Android modifier chirality
This commit is contained in:
commit
52b94d6d77
38 changed files with 851 additions and 46 deletions
2
android/.gitignore
vendored
2
android/.gitignore
vendored
|
|
@ -20,7 +20,7 @@
|
|||
**/.DS_Store
|
||||
|
||||
# This is the file output from KMEA; it's part of our build process.
|
||||
**/libs/keyman-engine.aar
|
||||
**/keyman-engine.aar
|
||||
|
||||
# keymanweb dependencies
|
||||
KMEA/app/src/main/assets/
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@
|
|||
kmw['getOskHeight'] = getOskHeight;
|
||||
kmw['getOskWidth'] = getOskWidth;
|
||||
kmw['setActiveElement']('ta');
|
||||
|
||||
ta.readOnly = false;
|
||||
|
||||
kmw.addEventListener('keyboardloaded', setIsChiral);
|
||||
kmw.addEventListener('keyboardchange', setIsChiral);
|
||||
}
|
||||
|
||||
function setOskHeight(h) {
|
||||
|
|
@ -56,6 +60,17 @@
|
|||
return oskWidth;
|
||||
}
|
||||
|
||||
// Query KMW if a given keyboard uses chiral modifiers.
|
||||
function setIsChiral(keyboardProperties) {
|
||||
var name = typeof(keyboardProperties.internalName) == "undefined" ? keyboardProperties.keyboardName : keyboardProperties.internalName;
|
||||
var isChiral = tavultesoft.keymanweb.isChiral(name);
|
||||
window.console.log('For keyboard "' + name + '"');
|
||||
window.console.log('setIsChiral = ' + isChiral);
|
||||
|
||||
window.jsInterface.setIsChiral(isChiral);
|
||||
return true;
|
||||
}
|
||||
|
||||
function setKeymanLanguage(keyboardName, internalName, languageName, langId, version, font, oskFont) {
|
||||
//oskFont.files = ['NotoSansSyriacWestern-Regular.svg#NotoSansSyriacWesternRegular'];
|
||||
//window.console.log('oskFonts = '+JSON.stringify(oskFont));
|
||||
|
|
@ -172,11 +187,11 @@
|
|||
kmw['executePopupKey'](keyID, keyText);
|
||||
}
|
||||
|
||||
function executeHardwareKeystroke(code, shift) {
|
||||
function executeHardwareKeystroke(code, shift, lstates) {
|
||||
var kmw=window['tavultesoft']['keymanweb'];
|
||||
window.console.log('executeHardwareKeystroke:('+code+', ' + shift + ');');
|
||||
window.console.log('executeHardwareKeystroke:('+code+', ' + shift + ', ' + lstates + ');');
|
||||
try {
|
||||
var r = kmw['executeHardwareKeystroke'](code, shift);
|
||||
var r = kmw['executeHardwareKeystroke'](code, shift, lstates);
|
||||
window.console.log('executeHardwareKeystroke completed with '+r);
|
||||
} catch(e) {
|
||||
window.console.log('oops: '+e);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
package com.tavultesoft.kmea;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
|
|
@ -114,18 +112,46 @@ public class KMHardwareKeyboardInterpreter implements KeyEvent.Callback {
|
|||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode > 84 || keyCode < 0) {
|
||||
// The key is outside the range of keys we understand
|
||||
return false;
|
||||
}
|
||||
|
||||
int androidModifiers = event.getModifiers(), keymanModifiers = 0;
|
||||
if ((androidModifiers & KeyEvent.META_SHIFT_ON) != 0) keymanModifiers |= 0x10;
|
||||
if ((androidModifiers & KeyEvent.META_CTRL_ON) != 0) keymanModifiers |= 0x20;
|
||||
if ((androidModifiers & KeyEvent.META_ALT_ON) != 0) keymanModifiers |= 0x40;
|
||||
boolean isChiral = KMManager.getKMKeyboard(this.keyboardType).getChirality();
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_TAB && keymanModifiers == 0x20) {
|
||||
// Trigger the Keyman language menu
|
||||
// States of modifier keys
|
||||
// KeyEvent.getModifiers() specifically masks out lock keys (KeyEvent.META_CAPS_LOCK_ON,
|
||||
// KeyEvent.META_SCROLL_LOCK_ON, KeyEvent.META_NUM_LOCK_ON), so get their states separately
|
||||
int androidModifiers = event.getModifiers(), keymanModifiers = 0;
|
||||
boolean capsOn = event.isCapsLockOn();
|
||||
boolean numOn = event.isNumLockOn();
|
||||
boolean scrollOn = event.isScrollLockOn();
|
||||
|
||||
// By design, SHIFT is non-chiral
|
||||
if ((androidModifiers & KeyEvent.META_SHIFT_ON) != 0) {
|
||||
keymanModifiers |= KMModifierCodes.get("SHIFT");
|
||||
}
|
||||
if ((androidModifiers & KeyEvent.META_CTRL_LEFT_ON) != 0) {
|
||||
keymanModifiers |= isChiral ? KMModifierCodes.get("LCTRL") : KMModifierCodes.get("CTRL");
|
||||
}
|
||||
if ((androidModifiers & KeyEvent.META_CTRL_RIGHT_ON) != 0) {
|
||||
keymanModifiers |= isChiral ? KMModifierCodes.get("RCTRL") : KMModifierCodes.get("CTRL");
|
||||
}
|
||||
if ((androidModifiers & KeyEvent.META_ALT_LEFT_ON) != 0) {
|
||||
keymanModifiers |= isChiral ? KMModifierCodes.get("LALT") : KMModifierCodes.get("ALT");
|
||||
}
|
||||
if ((androidModifiers & KeyEvent.META_ALT_RIGHT_ON) != 0) {
|
||||
keymanModifiers |= isChiral ? KMModifierCodes.get("RALT") : KMModifierCodes.get("ALT");
|
||||
}
|
||||
|
||||
int Lstates = 0;
|
||||
Lstates |= capsOn ? KMModifierCodes.get("CAPS") : KMModifierCodes.get("NO_CAPS");
|
||||
Lstates |= numOn ? KMModifierCodes.get("NUM_LOCK") : KMModifierCodes.get("NO_NUM_LOCK");
|
||||
Lstates |= scrollOn ? KMModifierCodes.get("SCROLL_LOCK") : KMModifierCodes.get("NO_SCROLL_LOCK");
|
||||
|
||||
// CTRL-Tab triggers the Keyman language menu
|
||||
if (keyCode == KeyEvent.KEYCODE_TAB && ((androidModifiers & KeyEvent.META_CTRL_ON) != 0)) {
|
||||
KMManager.showKeyboardPicker(context, keyboardType);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -136,7 +162,7 @@ public class KMHardwareKeyboardInterpreter implements KeyEvent.Callback {
|
|||
}
|
||||
|
||||
// Send keystroke to KeymanWeb for processing: will return true to swallow the keystroke
|
||||
return KMManager.executeHardwareKeystroke(keyCodeMap[keyCode], keymanModifiers, keyboardType);
|
||||
return KMManager.executeHardwareKeystroke(keyCodeMap[keyCode], keymanModifiers, keyboardType, Lstates);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ final class KMKeyboard extends WebView {
|
|||
private GestureDetector gestureDetector;
|
||||
private static ArrayList<OnKeyboardEventListener> kbEventListeners = null;
|
||||
private boolean ShouldShowHelpBubble = false;
|
||||
private boolean isChiral = false;
|
||||
|
||||
protected boolean keyboardSet = false;
|
||||
protected boolean keyboardPickerEnabled = true;
|
||||
|
|
@ -138,9 +139,9 @@ final class KMKeyboard extends WebView {
|
|||
setBackgroundColor(0);
|
||||
}
|
||||
|
||||
public void executeHardwareKeystroke(int code, int shift) {
|
||||
String jsFormat = "javascript:executeHardwareKeystroke(%d,%d)";
|
||||
String jsString = String.format(jsFormat, code, shift);
|
||||
public void executeHardwareKeystroke(int code, int shift, int lstates) {
|
||||
String jsFormat = "javascript:executeHardwareKeystroke(%d,%d, %d)";
|
||||
String jsString = String.format(jsFormat, code, shift, lstates);
|
||||
loadUrl(jsString);
|
||||
}
|
||||
|
||||
|
|
@ -406,6 +407,16 @@ final class KMKeyboard extends WebView {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public void setChirality(boolean flag) {
|
||||
this.isChiral = flag;
|
||||
}
|
||||
|
||||
public boolean getChirality() {
|
||||
|
||||
return this.isChiral;
|
||||
|
||||
}
|
||||
|
||||
private void saveCurrentKeyboardIndex() {
|
||||
SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
|
|
|||
|
|
@ -178,22 +178,23 @@ public final class KMManager {
|
|||
IMService = service;
|
||||
}
|
||||
|
||||
public static boolean executeHardwareKeystroke(int code, int shift) {
|
||||
public static boolean executeHardwareKeystroke(int code, int shift, int lstates) {
|
||||
if (SystemKeyboard != null) {
|
||||
return executeHardwareKeystroke(code, shift, KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
return executeHardwareKeystroke(code, shift, KeyboardType.KEYBOARD_TYPE_SYSTEM, lstates);
|
||||
} else if (InAppKeyboard != null) {
|
||||
return executeHardwareKeystroke(code, shift, KeyboardType.KEYBOARD_TYPE_INAPP);
|
||||
return executeHardwareKeystroke(code, shift, KeyboardType.KEYBOARD_TYPE_INAPP, lstates);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean executeHardwareKeystroke(int code, int shift, KeyboardType keyboard) {
|
||||
public static boolean executeHardwareKeystroke(
|
||||
int code, int shift, KeyboardType keyboard, int lstates) {
|
||||
if (keyboard == KeyboardType.KEYBOARD_TYPE_INAPP) {
|
||||
InAppKeyboard.executeHardwareKeystroke(code, shift);
|
||||
InAppKeyboard.executeHardwareKeystroke(code, shift, lstates);
|
||||
return true;
|
||||
} else if (keyboard == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
|
||||
SystemKeyboard.executeHardwareKeystroke(code, shift);
|
||||
SystemKeyboard.executeHardwareKeystroke(code, shift, lstates);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +455,8 @@ public final class KMManager {
|
|||
newKbInfo.put(KMManager.KMKey_LanguageID, KMManager.KMDefault_LanguageID);
|
||||
newKbInfo.put(KMManager.KMKey_KeyboardName, KMManager.KMDefault_KeyboardName);
|
||||
newKbInfo.put(KMManager.KMKey_LanguageName, KMManager.KMDefault_LanguageName);
|
||||
newKbInfo.put(KMManager.KMKey_KeyboardVersion, getLatestKeyboardFileVersion(context, KMManager.KMDefault_KeyboardID));
|
||||
newKbInfo.put(KMManager.KMKey_KeyboardVersion,
|
||||
getLatestKeyboardFileVersion(context, KMManager.KMDefault_KeyboardID));
|
||||
newKbInfo.put(KMManager.KMKey_CustomKeyboard, "N");
|
||||
newKbInfo.put(KMManager.KMKey_Font, KMManager.KMDefault_KeyboardFont);
|
||||
kbList.set(0, newKbInfo);
|
||||
|
|
@ -1158,10 +1160,12 @@ public final class KMManager {
|
|||
}
|
||||
|
||||
if (result > 0) {
|
||||
if (KMManager.InAppKeyboard != null)
|
||||
KMManager.InAppKeyboard.loadKeyboard();
|
||||
if (KMManager.SystemKeyboard != null)
|
||||
KMManager.SystemKeyboard.loadKeyboard();
|
||||
if (KMManager.InAppKeyboard != null) {
|
||||
InAppKeyboard.loadKeyboard();
|
||||
}
|
||||
if ( KMManager.SystemKeyboard != null) {
|
||||
SystemKeyboard.loadKeyboard();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
|
@ -1376,10 +1380,25 @@ public final class KMManager {
|
|||
String langName = kbInfo.get(KMManager.KMKey_LanguageName);
|
||||
String kFont = kbInfo.get(KMManager.KMKey_Font);
|
||||
String kOskFont = kbInfo.get(KMManager.KMKey_OskFont);
|
||||
if (InAppKeyboard != null)
|
||||
if (InAppKeyboard != null) {
|
||||
InAppKeyboard.setKeyboard(kbId, langId, kbName, langName, kFont, kOskFont);
|
||||
if (SystemKeyboard != null)
|
||||
}
|
||||
if (SystemKeyboard != null) {
|
||||
SystemKeyboard.setKeyboard(kbId, langId, kbName, langName, kFont, kOskFont);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Refactor InAppKeyboard / SystemKeyboard logic
|
||||
public static KMKeyboard getKMKeyboard(KeyboardType keyboard) {
|
||||
if (keyboard == KeyboardType.KEYBOARD_TYPE_INAPP) {
|
||||
return InAppKeyboard;
|
||||
} else if (keyboard == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
|
||||
return SystemKeyboard;
|
||||
} else {
|
||||
// What should we do if KeyboardType.KEYBOARD_TYPE_UNDEFINED?
|
||||
Log.w("KMManager", "Invalid keyboard");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKeyboardTextFontFilename() {
|
||||
|
|
@ -2031,7 +2050,6 @@ public final class KMManager {
|
|||
InAppKeyboard.subKeysList.add(hashMap);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2256,6 +2274,15 @@ public final class KMManager {
|
|||
return kbWidth;
|
||||
}
|
||||
|
||||
// Store the current keyboard chirality status from KMW in InAppKeyboard
|
||||
@JavascriptInterface
|
||||
public void setIsChiral(boolean isChiral) {
|
||||
if (isDebugMode()) {
|
||||
Log.d("KMManager", "InAppKeyboard chirality: " + String.valueOf(isChiral));
|
||||
}
|
||||
InAppKeyboard.setChirality(isChiral);
|
||||
}
|
||||
|
||||
// This annotation is required in Jelly Bean and later:
|
||||
@JavascriptInterface
|
||||
public void insertText(final int dn, final String s) {
|
||||
|
|
@ -2361,6 +2388,15 @@ public final class KMManager {
|
|||
return kbWidth;
|
||||
}
|
||||
|
||||
// Store the current keyboard chirality status from KMW in SystemKeyboard
|
||||
@JavascriptInterface
|
||||
public void setIsChiral(boolean isChiral) {
|
||||
if (isDebugMode()) {
|
||||
Log.d("KMManager", "SystemKeyboard chirality: " + String.valueOf(isChiral));
|
||||
}
|
||||
SystemKeyboard.setChirality(isChiral);
|
||||
}
|
||||
|
||||
// This annotation is required in Jelly Bean and later:
|
||||
@JavascriptInterface
|
||||
public void insertText(final int dn, final String s) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tavultesoft.kmea;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public final class KMModifierCodes {
|
||||
|
||||
// Note: Keep this table in sync with web/source/kmwosk.js osk.modifierCodes
|
||||
final static HashMap<String, Integer> codes = new HashMap<String, Integer>() {{
|
||||
put("LCTRL", 0x0001);
|
||||
put("RCTRL", 0x0002);
|
||||
put("LALT", 0x0004);
|
||||
put("RALT", 0x0008);
|
||||
put("SHIFT", 0x0010);
|
||||
put("CTRL", 0x0020);
|
||||
put("ALT", 0x0040);
|
||||
put("CAPS", 0x0100);
|
||||
put("NO_CAPS", 0x0200);
|
||||
put("NUM_LOCK", 0x0400);
|
||||
put("NO_NUM_LOCK", 0x0800);
|
||||
put("SCROLL_LOCK", 0x1000);
|
||||
put("NO_SCROLL_LOCK", 0x2000);
|
||||
put("VIRTUAL_KEY", 0x4000);
|
||||
}};
|
||||
|
||||
public static Integer get(String key) {
|
||||
Integer bitflag = codes.get(key);
|
||||
if (bitflag == null) {
|
||||
bitflag = 0x0;
|
||||
}
|
||||
return bitflag;
|
||||
};
|
||||
}
|
||||
|
|
@ -113,9 +113,10 @@ if [ $? -ne 0 ]; then
|
|||
die "ERROR: Build of KMEA failed"
|
||||
fi
|
||||
|
||||
echo "Copying Keyman Engine for Android to KMAPro and Sample apps"
|
||||
echo "Copying Keyman Engine for Android to KMAPro, Sample apps, and Tests"
|
||||
mv $KMA_ROOT/KMEA/app/build/outputs/aar/app-release.aar $KMA_ROOT/KMAPro/kMAPro/libs/keyman-engine.aar
|
||||
cp $KMA_ROOT/KMAPro/kMAPro/libs/keyman-engine.aar $KMA_ROOT/Samples/KMSample1/app/libs/keyman-engine.aar
|
||||
cp $KMA_ROOT/KMAPro/kMAPro/libs/keyman-engine.aar $KMA_ROOT/Samples/KMSample2/app/libs/keyman-engine.aar
|
||||
cp $KMA_ROOT/KMAPro/kMAPro/libs/keyman-engine.aar $KMA_ROOT/Tests/keyman-engine.aar
|
||||
|
||||
cd ..\
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package com.keyman.kmsample2;
|
||||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KMManager.KeyboardType;
|
||||
import com.tavultesoft.kmea.KMHardwareKeyboardInterpreter;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardEventListener;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import java.util.HashMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
|
@ -12,15 +19,10 @@ import android.view.inputmethod.ExtractedText;
|
|||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KMManager.KeyboardType;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SystemKeyboard extends InputMethodService implements KeyboardEventHandler.OnKeyboardEventListener {
|
||||
public class SystemKeyboard extends InputMethodService implements OnKeyboardEventListener {
|
||||
|
||||
private static View inputView = null;
|
||||
private KMHardwareKeyboardInterpreter interpreter = null;
|
||||
|
||||
/**
|
||||
* Main initialization of the input method component. Be sure to call
|
||||
|
|
@ -32,6 +34,7 @@ public class SystemKeyboard extends InputMethodService implements KeyboardEventH
|
|||
KMManager.setDebugMode(true);
|
||||
KMManager.addKeyboardEventListener(this);
|
||||
KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
interpreter = new KMHardwareKeyboardInterpreter(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
|
||||
// Add a custom keyboard
|
||||
HashMap<String, String> kbInfo = new HashMap<String, String>();
|
||||
|
|
@ -48,6 +51,7 @@ public class SystemKeyboard extends InputMethodService implements KeyboardEventH
|
|||
public void onDestroy() {
|
||||
inputView = null;
|
||||
KMManager.removeKeyboardEventListener(this);
|
||||
interpreter = null; // Throw it away, since we're losing our application's context.
|
||||
KMManager.onDestroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
|
@ -103,7 +107,7 @@ public class SystemKeyboard extends InputMethodService implements KeyboardEventH
|
|||
attribute.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
||||
super.onStartInput(attribute, restarting);
|
||||
KMManager.onStartInput(attribute, restarting);
|
||||
|
||||
KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
// User switched to a new input field so we should extract the text from input field
|
||||
// and pass it to Keyman Engine together with selection range
|
||||
InputConnection ic = getCurrentInputConnection();
|
||||
|
|
@ -175,4 +179,24 @@ public class SystemKeyboard extends InputMethodService implements KeyboardEventH
|
|||
public void onKeyboardDismissed() {
|
||||
// Handle Keyman keyboard dismissed event here if needed
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return interpreter.onKeyDown(keyCode, event); // if false, will revert to default handling.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return interpreter.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
|
||||
return interpreter.onKeyMultiple(keyCode, count, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
return interpreter.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
}
|
||||
1
android/Tests/KeyboardHarness/app/.gitignore
vendored
Normal file
1
android/Tests/KeyboardHarness/app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
33
android/Tests/KeyboardHarness/app/build.gradle
Normal file
33
android/Tests/KeyboardHarness/app/build.gradle
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.keyman.android.tests.keyboardHarness"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:25.1.0'
|
||||
compile(name:'keyman-engine', ext:'aar')
|
||||
}
|
||||
0
android/Tests/KeyboardHarness/app/libs/.gitkeep
Normal file
0
android/Tests/KeyboardHarness/app/libs/.gitkeep
Normal file
17
android/Tests/KeyboardHarness/app/proguard-rules.pro
vendored
Normal file
17
android/Tests/KeyboardHarness/app/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/serkankurt/Desktop/Android Development/adt-bundle-mac-x86_64-20140624/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.keyman.android.tests.keyboardHarness;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.keyman.android.tests.keyboardHarness" >
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
KeymanWeb.KR(new Keyboard_chirality());
|
||||
|
||||
/**
|
||||
* Please note that this is an experimental handwritten keyboard designed for initial testing of modifier chirality support for KeymanWeb.
|
||||
* As it is handcoded, it uses multiple codesize optimization techniques that Keyman Developer simply does not and will not employ, and it
|
||||
* will only work with KeymanWeb based implementations. (Not supported for Keyman Desktop or Keyman for Mac.)
|
||||
*
|
||||
* (This keyboard was written before Developer's implementation of chirality support and was used to bootstrap KeymanWeb chirality, serving
|
||||
* as the initial wave of testing.)
|
||||
*/
|
||||
|
||||
function Keyboard_chirality() {
|
||||
this.KI = "Keyboard_chirality";
|
||||
this.KN = "Development Chirality Test Keyboard";
|
||||
this.KV = {
|
||||
KMBM: 0x001F,
|
||||
F: ' 1em "Arial"',
|
||||
K102: 0,
|
||||
KLS: { 'default': new Array("`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "", "", "", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\", "", "", "", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "", "", "", "", "", "", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "", "", "", "", "", ""),
|
||||
'shift': new Array("~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "", "", "", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}", "|", "", "", "", "A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\"", "", "", "", "", "", "", "Z", "X", "C", "V", "B", "N", "M", "<", ">", "?", "", "", "", "", "", ""),
|
||||
'leftctrl': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ʍ", "ə", "ɹ", "ð", "ʏ", "ʉ", "ɨ", "ɵ", "ʘ", "", "", "", "", "", "", "ɑ", "ʃ", "", "ɸ", "ɣ", "ɥ", "ɟ", "", "ɬ", "ː", "", "", "", "", "", "", "", "ʒ", "χ", "ç", "ʋ", "β", "ɲ", "", "", "", "", "", "", "", "", "", ""),
|
||||
'leftctrl-shift': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ʡ", "", "ɘ", "ʀ", "θ", "", "ɯ", "ɪ", "", "", "", "", "", "", "", "", "ɒ", "ᶘ", "", "", "ɢ", "ʜ", "", "", "ʟ", "ː", "", "", "", "", "", "", "", "ᶚ", "", "", "", "ʙ", "ɴ", "", "", "", "ʔ", "", "", "", "", "", ""),
|
||||
'leftalt': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ɛ", "ɽ", "ʈ", "ɥ", "ʊ", "", "ɔ", "", "", "", "", "", "", "", "æ", "", "ɖ", "", "", "ɦ", "ʝ", "", "ɭ", "", "", "", "", "", "", "", "", "ʐ", "", "ɕ", "", "", "ɳ", "", "", "", "", "", "", "", "", "", ""),
|
||||
'rightalt': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ʠ", "ɰ", "ɜ", "ɾ", "ƭ", "", "ʌ", "", "ø", "ƥ", "", "", "", "", "", "", "ɐ", "σ", "ɗ", "", "ɠ", "ħ", "ʄ", "ƙ", "ɮ", "", "", "", "", "", "", "", "", "ʑ", "", "ƈ", "", "ɓ", "ŋ", "ɱ", "", "", "", "", "", "", "", "", ""),
|
||||
'leftalt-shift': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ʢ", "", "œ", "ɻ", "", "", "", "ᵻ", "ɞ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ʎ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""),
|
||||
'rightalt-shift': new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ɶ", "ʁ", "", "", "ᵾ", "ᵼ", "ɤ", "", "", "", "", "", "", "", "ᴂ", "", "", "", "ʛ", "ɧ", "", "", "ɺ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "")
|
||||
}
|
||||
};
|
||||
this.KH = '';
|
||||
this.KM = 0;
|
||||
|
||||
this.dfltCodes = ["K_BKQUOTE","K_1","K_2","K_3","K_4","K_5","K_6","K_7","K_8","K_9","K_0",
|
||||
"K_HYPHEN","K_EQUAL","K_*","K_*","K_*","K_Q","K_W","K_E","K_R","K_T",
|
||||
"K_Y","K_U","K_I","K_O","K_P","K_LBRKT","K_RBRKT","K_BKSLASH","K_*",
|
||||
"K_*","K_*","K_A","K_S","K_D","K_F","K_G","K_H","K_J","K_K","K_L",
|
||||
"K_COLON","K_QUOTE","K_*","K_*","K_*","K_*","K_*","K_oE2",
|
||||
"K_Z","K_X","K_C","K_V","K_B","K_N","K_M","K_COMMA","K_PERIOD",
|
||||
"K_SLASH","K_*","K_*","K_*","K_*","K_*","K_SPACE"];
|
||||
|
||||
this.gs = function (t, e) {
|
||||
return this.g0(t, e);
|
||||
};
|
||||
this.g0 = function (t, e) {
|
||||
var k = KeymanWeb, r = 0, m = 0;
|
||||
|
||||
// Handwritten time!
|
||||
var kls = this.KV.KLS;
|
||||
|
||||
var layers = ['default', 'shift', 'leftctrl', 'leftctrl-shift', 'leftalt', 'rightalt', 'leftalt-shift', 'rightalt-shift'];
|
||||
|
||||
// Maps keystrokes by base key-codes and array into the key symbols displayed in KLS.
|
||||
for(var i = 0; i < layers.length; i++) {
|
||||
// Obtain the modifier code to match for the selected layer.
|
||||
// The following uses a non-public property potentially subject to change in the future.
|
||||
var modCode = k.osk.modifierCodes['VIRTUAL_KEY'] | k.osk.getModifierState(layers[i]);
|
||||
var layer = layers[i];
|
||||
|
||||
for(var key=0; key < kls[layer].length; key++) {
|
||||
var keySymbol = this.dfltCodes[key];
|
||||
|
||||
if(keySymbol == "K_*") {
|
||||
continue;
|
||||
} else if(kls[layer][key] != '') {
|
||||
if (k.KKM(e, modCode, k.osk.keyCodes[keySymbol])) {
|
||||
r = m = 1;
|
||||
if(k.KSM(e, k.osk.modifierCodes['CAPS'])) {
|
||||
k.KO(0, t, kls[layer][key].toUpperCase());
|
||||
} else {
|
||||
k.KO(0, t, kls[layer][key]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
package com.keyman.android.tests.keyboardHarness;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.tavultesoft.kmea.KMManager;
|
||||
import com.tavultesoft.kmea.KMTextView;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardEventListener;
|
||||
import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardDownloadEventListener;
|
||||
import com.tavultesoft.kmea.KMManager.KeyboardType;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MainActivity extends Activity implements OnKeyboardEventListener, OnKeyboardDownloadEventListener {
|
||||
|
||||
private KMTextView textView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
KMManager.setDebugMode(true);
|
||||
KMManager.initialize(this, KeyboardType.KEYBOARD_TYPE_INAPP);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
textView = (KMTextView) findViewById(R.id.kmTextView);
|
||||
|
||||
// Add a custom keyboard
|
||||
HashMap<String, String> kbInfo = new HashMap<String, String>();
|
||||
final String Chirality_KeyboardFont = "{\"family\":\"LatinWeb\",\"source\":[\"DejaVuSans.ttf\"]}";
|
||||
|
||||
kbInfo.put(KMManager.KMKey_KeyboardID, "chirality");
|
||||
kbInfo.put(KMManager.KMKey_LanguageID, "eng");
|
||||
kbInfo.put(KMManager.KMKey_KeyboardName, "Chirality Keyboard");
|
||||
kbInfo.put(KMManager.KMKey_LanguageName, "English");
|
||||
kbInfo.put(KMManager.KMKey_KeyboardVersion, "1.0");
|
||||
kbInfo.put(KMManager.KMKey_Font, Chirality_KeyboardFont);
|
||||
KMManager.addKeyboard(this, kbInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
KMManager.onResume();
|
||||
KMManager.addKeyboardEventListener(this);
|
||||
KMManager.addKeyboardDownloadEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
KMManager.onPause();
|
||||
KMManager.removeKeyboardEventListener(this);
|
||||
KMManager.removeKeyboardDownloadEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardLoaded(KeyboardType keyboardType) {
|
||||
// Handle Keyman keyboard loaded event here if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardChanged(String newKeyboard) {
|
||||
// Handle Keyman keyboard changed event here if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardShown() {
|
||||
// Handle Keyman keyboard shown event here if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardDismissed() {
|
||||
// Handle Keyman keyboard dismissed event here if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardDownloadStarted(HashMap<String, String> keyboardInfo) {
|
||||
// Handle Keyman keyboard download started event here if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardDownloadFinished(HashMap<String, String> keyboardInfo, int result) {
|
||||
// Handle Keyman keyboard download finished event here if needed
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.tavultesoft.kmea.KMTextView
|
||||
android:id="@+id/kmTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:ems="10"
|
||||
android:inputType="textMultiLine"
|
||||
android:gravity="top"
|
||||
android:scrollbars="vertical" >
|
||||
|
||||
<requestFocus />
|
||||
</com.tavultesoft.kmea.KMTextView>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
||||
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
||||
android:orderInCategory="100" app:showAsAction="never" />
|
||||
</menu>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">Keyboard Harness</string>
|
||||
|
||||
<string name="hello_world">Hello world!</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="android:Theme.Light">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
19
android/Tests/KeyboardHarness/build.gradle
Normal file
19
android/Tests/KeyboardHarness/build.gradle
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
11
android/Tests/KeyboardHarness/build.sh
Normal file
11
android/Tests/KeyboardHarness/build.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
# Build KeyboardHarness test app
|
||||
|
||||
echo Build KMEA
|
||||
cd ../../KMEA
|
||||
./build.sh
|
||||
cd ../Tests/KeyboardHarness
|
||||
cp ../keyman-engine.aar app/libs/
|
||||
|
||||
echo Build KeyboardHarness test app
|
||||
./gradlew clean build
|
||||
18
android/Tests/KeyboardHarness/gradle.properties
Normal file
18
android/Tests/KeyboardHarness/gradle.properties
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
BIN
android/Tests/KeyboardHarness/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/Tests/KeyboardHarness/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/Tests/KeyboardHarness/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/Tests/KeyboardHarness/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#Wed Apr 10 15:27:10 PDT 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
164
android/Tests/KeyboardHarness/gradlew
vendored
Normal file
164
android/Tests/KeyboardHarness/gradlew
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
android/Tests/KeyboardHarness/gradlew.bat
vendored
Normal file
90
android/Tests/KeyboardHarness/gradlew.bat
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
9
android/Tests/KeyboardHarness/readme.md
Normal file
9
android/Tests/KeyboardHarness/readme.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# KeyboardHarness Test App #
|
||||
|
||||
This app is is based on Samples/KMSample1 and targets keyboard functionality and reproducing bugs with keyboards rather than integration functionality. Use as system keyboard is currently not supported.
|
||||
|
||||
## Version History ##
|
||||
|
||||
## 2017-09-26 1.0
|
||||
* Initial creation
|
||||
|
||||
1
android/Tests/KeyboardHarness/settings.gradle
Normal file
1
android/Tests/KeyboardHarness/settings.gradle
Normal file
|
|
@ -0,0 +1 @@
|
|||
include ':app'
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# Keyman for Android
|
||||
|
||||
## 10.0 alpha
|
||||
* Added support for L/R Alt and Ctrl and Caps Lock modifiers for keyboards if specified by a keyboard designer
|
||||
* Add feature to reset keyboard to default layer when new input field focused (keymanapp/keyman#288)
|
||||
* Removed "Share to Facebook" feature (keymanapp/keyman#156)
|
||||
* Fix dual keyboards that appear when closing Keyman Browser (keymanapp/keyman#220)
|
||||
|
|
|
|||
|
|
@ -3627,11 +3627,15 @@ if(!window['tavultesoft']['keymanweb']['initialized']) {
|
|||
/**
|
||||
* Function isChiral
|
||||
* Scope Public
|
||||
* @param {Object=} k0
|
||||
* @param {string|Object=} k0
|
||||
* @return {boolean}
|
||||
* Description Tests if the active keyboard (or optional argument) uses chiral modifiers.
|
||||
*/
|
||||
keymanweb.isChiral = keymanweb['isChiral'] = function(k0) {
|
||||
if(typeof(k0) == "string") {
|
||||
k0 = keymanweb._getKeyboardByID(k0);
|
||||
}
|
||||
|
||||
return !!(keymanweb.getKeyboardModifierBitmask(k0) & keymanweb['osk'].modifierBitmasks.IS_CHIRAL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -455,9 +455,11 @@
|
|||
* API endpoint for hardware keystroke events from Android external keyboards
|
||||
*
|
||||
* @param {number} code key identifier
|
||||
* @param {number} shift shift state (0x10=shift 0x20=ctrl 0x40=alt)
|
||||
* @param {number} shift shift state (0x01=left ctrl 0x02=right ctrl 0x04=left alt 0x08=right alt
|
||||
* 0x10=shift 0x20=ctrl 0x40=alt)
|
||||
* @param {number} lstates lock state (0x0200=no caps 0x0400=num 0x0800=no num 0x1000=scroll 0x2000=no scroll locks)
|
||||
**/
|
||||
keymanweb['executeHardwareKeystroke'] = function(code, shift) {
|
||||
keymanweb['executeHardwareKeystroke'] = function(code, shift, lstates = 0) {
|
||||
if(!keymanweb._ActiveKeyboard || code == 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -466,7 +468,7 @@
|
|||
device.touchable = false;
|
||||
device.formFactor = 'desktop';
|
||||
try {
|
||||
result = keymanweb.executeHardwareKeystrokeInternal(code, shift);
|
||||
result = keymanweb.executeHardwareKeystrokeInternal(code, shift, lstates);
|
||||
} catch (err) {
|
||||
console.error(err.message, err);
|
||||
}
|
||||
|
|
@ -479,9 +481,11 @@
|
|||
* Process the hardware key to the keyboard mapping
|
||||
*
|
||||
* @param {number} code key identifier
|
||||
* @param {number} shift shift state (0x10=shift 0x20=ctrl 0x40=alt)
|
||||
* @param {number} shift shift state (0x01=left ctrl 0x02=right ctrl 0x04=left alt 0x08=right alt
|
||||
* 0x10=shift 0x20=ctrl 0x40=alt)
|
||||
* @param {number} lstates lock state (0x0200=no caps 0x0400=num 0x0800=no num 0x1000=scroll 0x2000=no scroll locks)
|
||||
**/
|
||||
keymanweb.executeHardwareKeystrokeInternal = function(code, shift) {
|
||||
keymanweb.executeHardwareKeystrokeInternal = function(code, shift, lstates) {
|
||||
|
||||
// Clear any pending (non-popup) key
|
||||
osk.keyPending = null;
|
||||
|
|
@ -498,6 +502,7 @@
|
|||
Lmodifiers: shift,
|
||||
vkCode: code,
|
||||
Lcode: code,
|
||||
Lstates: lstates,
|
||||
LisVirtualKey: true,
|
||||
LisVirtualKeyCode: false
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue