Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android modifier chirality #341

Merged
merged 19 commits into from
Oct 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
21 changes: 18 additions & 3 deletions android/KMEA/app/src/main/assets/keyboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

package com.tavultesoft.kmea;

import android.util.Log;

import android.content.Context;
import android.view.KeyEvent;

Expand Down Expand Up @@ -114,18 +112,46 @@ public KMHardwareKeyboardInterpreter(Context context, KMManager.KeyboardType key

@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;
}

boolean isChiral = KMManager.getKMKeyboard(this.keyboardType).getChirality();

// 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;
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 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");

if (keyCode == KeyEvent.KEYCODE_TAB && keymanModifiers == 0x20) {
// Trigger the Keyman language menu
// CTRL-Tab triggers the Keyman language menu
if (keyCode == KeyEvent.KEYCODE_TAB && ((androidModifiers & KeyEvent.META_CTRL_ON) != 0)) {
KMManager.showKeyboardPicker(context, keyboardType);
return false;
}
Expand All @@ -136,7 +162,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
}

// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -138,9 +139,9 @@ public void loadKeyboard() {
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);
}

Expand Down Expand Up @@ -406,6 +407,16 @@ public void run() {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,23 @@ public static void setInputMethodService(InputMethodService service) {
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;
}

Expand Down Expand Up @@ -454,7 +455,8 @@ public static void updateOldKeyboardsList(Context context) {
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);
Expand Down Expand Up @@ -1158,10 +1160,12 @@ protected void onPostExecute(Integer result) {
}

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();
Expand Down Expand Up @@ -1376,10 +1380,25 @@ public static void switchToNextKeyboard(Context context) {
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() {
Expand Down Expand Up @@ -2031,7 +2050,6 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
InAppKeyboard.subKeysList.add(hashMap);
}
}

return false;
}
}
Expand Down Expand Up @@ -2256,6 +2274,15 @@ public int getKeyboardWidth() {
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) {
Expand Down Expand Up @@ -2361,6 +2388,15 @@ public int getKeyboardWidth() {
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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
};
}
3 changes: 2 additions & 1 deletion android/KMEA/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 ..\
Loading