XSession: implement screen keyboard

This commit is contained in:
zt515 2017-11-30 00:09:11 +08:00
parent aa31446121
commit 48dfac4c77
17 changed files with 326 additions and 34 deletions

View File

@ -10,4 +10,8 @@ public class NeoGLView extends DemoGLSurfaceView {
public NeoGLView(NeoXorgViewClient client) {
super(client);
}
public void callNativeScreenKeyboardShown(int shown) {
nativeScreenKeyboardShown(shown);
}
}

View File

@ -0,0 +1,15 @@
package io.neoterm;
/**
* @author kiva
*/
public class NeoRenderer {
public static void callNativeTextInputFinished() {
DemoRenderer.nativeTextInputFinished();
}
public static void callNativeTextInput(int ascii, int unicode) {
DemoRenderer.nativeTextInput(ascii, unicode);
}
}

View File

@ -0,0 +1,17 @@
package io.neoterm;
import io.neoterm.xorg.R;
/**
* @author kiva
*/
public class NeoTextInput {
public static int TextInputKeyboardList[][] =
{
{0, R.xml.qwerty, R.xml.c64, R.xml.amiga, R.xml.atari800},
{0, R.xml.qwerty_shift, R.xml.c64, R.xml.amiga_shift, R.xml.atari800},
{0, R.xml.qwerty_alt, R.xml.c64, R.xml.amiga_alt, R.xml.atari800},
{0, R.xml.qwerty_alt_shift, R.xml.c64, R.xml.amiga_alt_shift, R.xml.atari800}
};
}

View File

@ -38,19 +38,19 @@
<string name="controls_question">What kind of navigation keys does your device have?</string>
<string name="controls_additional">Additional controls</string>
<string name="controls_screenkb">On-screen keyboard</string>
<string name="controls_screenkb">On-screen screenKeyboard</string>
<string name="controls_accelnav">Accelerometer</string>
<string name="controls_screenkb_size">On-screen keyboard size</string>
<string name="controls_screenkb_size">On-screen screenKeyboard size</string>
<string name="controls_screenkb_drawsize">Size of button images</string>
<string name="controls_screenkb_large">Large</string>
<string name="controls_screenkb_medium">Medium</string>
<string name="controls_screenkb_small">Small</string>
<string name="controls_screenkb_tiny">Tiny</string>
<string name="controls_screenkb_custom">Custom</string>
<string name="controls_screenkb_theme">On-screen keyboard theme</string>
<string name="controls_screenkb_theme">On-screen screenKeyboard theme</string>
<string name="controls_screenkb_by">%1$s by %2$s</string>
<string name="controls_screenkb_transparency">On-screen keyboard transparency</string>
<string name="controls_screenkb_transparency">On-screen screenKeyboard transparency</string>
<string name="controls_screenkb_trans_0">Invisible</string>
<string name="controls_screenkb_trans_1">Almost invisible</string>
<string name="controls_screenkb_trans_2">Transparent</string>
@ -145,7 +145,7 @@
<string name="remap_screenkb_button_rotateleft">Rotate left two-finger gesture</string>
<string name="remap_screenkb_button_rotateright">Rotate right two-finger gesture</string>
<string name="screenkb_custom_layout">Customize on-screen keyboard layout</string>
<string name="screenkb_custom_layout">Customize on-screen screenKeyboard layout</string>
<string name="screenkb_custom_layout_help">Press BACK when done. Resize buttons by sliding on empty space.</string>
<string name="screenkb_floating_joystick">Floating joystick</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- When creating new keyboard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<!-- When creating screenKeyboardoard layout, add it to TextInputKeyboardList array in project/java/MainActivity.java -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:horizontalGap="0px"

View File

@ -6,18 +6,24 @@ import android.content.Context
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.view.Surface
import android.view.WindowManager
import io.neoterm.Globals
import io.neoterm.NeoAccelerometerReader
import io.neoterm.NeoAudioThread
import android.inputmethodservice.Keyboard
import android.inputmethodservice.KeyboardView
import android.os.SystemClock
import android.text.InputType
import android.view.*
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.FrameLayout
import io.neoterm.*
import io.neoterm.xorg.NeoXorgViewClient
import io.neoterm.xorg.R
import java.util.*
/**
* @author kiva
*/
class XSession private constructor(val mActivity: Activity, val sessionData: XSessionData) : NeoXorgViewClient {
class XSession private constructor(private val mActivity: Activity, private val sessionData: XSessionData) : NeoXorgViewClient {
companion object {
fun createSession(activity: Activity, parameter: XParameter): XSession {
return XSession(activity, XSessionData())
@ -51,24 +57,206 @@ class XSession private constructor(val mActivity: Activity, val sessionData: XSe
override fun getWindowManager() = mActivity.windowManager!!
override fun showScreenKeyboardWithoutTextInputField(flags: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
override fun showScreenKeyboardWithoutTextInputField(keyboard: Int) {
val inputManager = mActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (!isKeyboardWithoutTextInputShown) {
sessionData.keyboardWithoutTextInputShown = true
runOnUiThread(Runnable {
if (keyboard == 0) {
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
inputManager.showSoftInput(glView, InputMethodManager.SHOW_FORCED)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
} else {
if (sessionData.screenKeyboard != null)
return@Runnable
val builtinKeyboard = BuiltInKeyboardView(mActivity, null)
builtinKeyboard.alpha = 0.7f
builtinKeyboard.changeKeyboard(keyboard)
builtinKeyboard.setOnKeyboardActionListener(object : KeyboardView.OnKeyboardActionListener {
override fun onPress(key: Int) {
var key = key
if (key == KeyEvent.KEYCODE_BACK)
return
if (key < 0)
return
for (k in builtinKeyboard.keyboard.keys) {
if (k.sticky && key == k.codes[0])
return
}
if (key > 100000) {
key -= 100000
mActivity.onKeyDown(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT))
}
mActivity.onKeyDown(key, KeyEvent(KeyEvent.ACTION_DOWN, key))
}
override fun onRelease(key: Int) {
var key = key
if (key == KeyEvent.KEYCODE_BACK) {
builtinKeyboard.setOnKeyboardActionListener(null)
showScreenKeyboardWithoutTextInputField(0) // Hide keyboard
return
}
if (key == Keyboard.KEYCODE_SHIFT) {
builtinKeyboard.shift = !builtinKeyboard.shift
if (builtinKeyboard.shift && !builtinKeyboard.alt)
mActivity.onKeyDown(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT))
else
mActivity.onKeyUp(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT))
builtinKeyboard.changeKeyboard(keyboard)
return
}
if (key == Keyboard.KEYCODE_ALT) {
builtinKeyboard.alt = !builtinKeyboard.alt
if (builtinKeyboard.alt)
mActivity.onKeyUp(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT))
else
builtinKeyboard.shift = false
builtinKeyboard.changeKeyboard(keyboard)
return
}
if (key < 0)
return
for (k in builtinKeyboard.keyboard.keys) {
if (k.sticky && key == k.codes[0]) {
if (k.on) {
builtinKeyboard.stickyKeys.add(key)
mActivity.onKeyDown(key, KeyEvent(KeyEvent.ACTION_DOWN, key))
} else {
builtinKeyboard.stickyKeys.remove(key)
mActivity.onKeyUp(key, KeyEvent(KeyEvent.ACTION_UP, key))
}
return
}
}
var shifted = false
if (key > 100000) {
key -= 100000
shifted = true
}
mActivity.onKeyUp(key, KeyEvent(KeyEvent.ACTION_UP, key))
if (shifted) {
mActivity.onKeyUp(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT))
builtinKeyboard.stickyKeys.remove(KeyEvent.KEYCODE_SHIFT_LEFT)
for (k in builtinKeyboard.keyboard.keys) {
if (k.sticky && k.codes[0] == KeyEvent.KEYCODE_SHIFT_LEFT && k.on) {
k.on = false
builtinKeyboard.invalidateAllKeys()
}
}
}
}
override fun onText(p1: CharSequence) {}
override fun swipeLeft() {}
override fun swipeRight() {}
override fun swipeDown() {}
override fun swipeUp() {}
override fun onKey(p1: Int, p2: IntArray) {}
})
sessionData.screenKeyboard = builtinKeyboard
val layout = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM)
sessionData.videoLayout!!.addView(sessionData.screenKeyboard, layout)
}
})
} else {
sessionData.keyboardWithoutTextInputShown = false
runOnUiThread {
if (sessionData.screenKeyboard != null) {
sessionData.videoLayout!!.removeView(sessionData.screenKeyboard)
sessionData.screenKeyboard = null
}
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
inputManager.hideSoftInputFromWindow(glView!!.windowToken, 0)
}
}
glView!!.callNativeScreenKeyboardShown(if (isKeyboardWithoutTextInputShown) 1 else 0)
}
override fun setScreenKeyboardHintMessage(hideMessage: String?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
sessionData.screenKeyboardHintMessage = hideMessage
if (sessionData.screenKeyboard is EditText) {
runOnUiThread {
val editText = sessionData.screenKeyboard as EditText?
editText?.hint = hideMessage ?: mActivity.getString(R.string.text_edit_click_here)
}
}
}
override fun isScreenKeyboardShown(): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun isScreenKeyboardShown() = sessionData.screenKeyboard != null
override fun showScreenKeyboard(message: String?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
override fun showScreenKeyboard(oldText: String?) {
if (Globals.CompatibilityHacksTextInputEmulatesHwKeyboard) {
showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard)
return
}
if (sessionData.screenKeyboard != null)
return
val screenKeyboard = EditText(mActivity, null,
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
android.R.style.TextAppearance_Material_Widget_EditText
else android.R.style.TextAppearance_Widget_EditText)
val hint = sessionData.screenKeyboardHintMessage
screenKeyboard.hint = hint ?: mActivity.getString(R.string.text_edit_click_here)
screenKeyboard.setText(oldText)
screenKeyboard.setSelection(screenKeyboard.text.length)
screenKeyboard.setOnKeyListener(SimpleKeyListener(this))
screenKeyboard.setBackgroundColor(mActivity.resources.getColor(android.R.color.primary_text_light))
screenKeyboard.setTextColor(mActivity.resources.getColor(android.R.color.background_light))
if (isRunningOnOUYA && Globals.TvBorders)
screenKeyboard.setPadding(100, 100, 100, 100) // Bad bad HDMI TVs all have cropped borders
sessionData.screenKeyboard = screenKeyboard
sessionData.videoLayout!!.addView(sessionData.screenKeyboard)
screenKeyboard.inputType = InputType.TYPE_CLASS_TEXT
screenKeyboard.isFocusableInTouchMode = true
screenKeyboard.isFocusable = true
screenKeyboard.postDelayed({
screenKeyboard.requestFocus()
screenKeyboard.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0f, 0f, 0))
screenKeyboard.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0f, 0f, 0))
screenKeyboard.postDelayed({
screenKeyboard.requestFocus()
screenKeyboard.setSelection(screenKeyboard.text.length)
}, 100)
}, 300)
}
override fun hideScreenKeyboard() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
val inputManager = mActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (isKeyboardWithoutTextInputShown)
showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard)
if (sessionData.screenKeyboard == null || sessionData.screenKeyboard !is EditText)
return
synchronized(sessionData.textInput) {
val text = (sessionData.screenKeyboard as EditText).text.toString()
for (i in 0 until text.length) {
NeoRenderer.callNativeTextInput(text[i].toInt(), text.codePointAt(i))
}
}
NeoRenderer.callNativeTextInputFinished()
inputManager.hideSoftInputFromWindow(sessionData.screenKeyboard!!.windowToken, 0)
sessionData.videoLayout!!.removeView(sessionData.screenKeyboard)
sessionData.screenKeyboard = null
glView!!.isFocusableInTouchMode = true
glView!!.isFocusable = true
glView!!.requestFocus()
}
override fun updateScreenOrientation() {
@ -106,4 +294,64 @@ class XSession private constructor(val mActivity: Activity, val sessionData: XSe
else android.view.PointerIcon.TYPE_DEFAULT)
}
}
class SimpleKeyListener(var client: NeoXorgViewClient) : View.OnKeyListener {
override fun onKey(v: View, keyCode: Int, event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_UP && (keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_BACK ||
keyCode == KeyEvent.KEYCODE_MENU ||
keyCode == KeyEvent.KEYCODE_BUTTON_A ||
keyCode == KeyEvent.KEYCODE_BUTTON_B ||
keyCode == KeyEvent.KEYCODE_BUTTON_X ||
keyCode == KeyEvent.KEYCODE_BUTTON_Y ||
keyCode == KeyEvent.KEYCODE_BUTTON_1 ||
keyCode == KeyEvent.KEYCODE_BUTTON_2 ||
keyCode == KeyEvent.KEYCODE_BUTTON_3 ||
keyCode == KeyEvent.KEYCODE_BUTTON_4)) {
client.hideScreenKeyboard()
return true
}
return false
}
}
class BuiltInKeyboardView(context: Context, attrs: android.util.AttributeSet?) : KeyboardView(context, attrs) {
var shift = false
var alt = false
var stickyKeys = TreeSet<Int>()
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if (ev.y < top)
return false
if (ev.action == MotionEvent.ACTION_DOWN || ev.action == MotionEvent.ACTION_UP || ev.action == MotionEvent.ACTION_MOVE) {
// Convert pointer coords, this will lose multitiouch data, however KeyboardView does not support multitouch anyway
val converted = MotionEvent.obtain(ev.downTime, ev.eventTime, ev.action, ev.x, ev.y - top.toFloat(), ev.metaState)
return super.dispatchTouchEvent(converted)
}
return false
}
override fun onKeyDown(key: Int, event: KeyEvent): Boolean {
return false
}
override fun onKeyUp(key: Int, event: KeyEvent): Boolean {
return false
}
fun changeKeyboard(keyboardIndex: Int) {
val idx = (if (shift) 1 else 0) + if (alt) 2 else 0
val keyboard = Keyboard(context, NeoTextInput.TextInputKeyboardList[idx][keyboardIndex])
isPreviewEnabled = false
isProximityCorrectionEnabled = false
for (k in keyboard.keys) {
if (stickyKeys.contains(k.codes[0])) {
k.on = true
invalidateAllKeys()
}
}
}
}
}

View File

@ -1,17 +1,25 @@
package io.neoterm.frontend.xorg
import android.view.View
import android.widget.FrameLayout
import io.neoterm.NeoAudioThread
import io.neoterm.NeoGLView
import io.neoterm.xorg.NeoXorgViewClient
import java.util.*
/**
* @author kiva
*/
class XSessionData {
var videoLayout: FrameLayout? = null
var audioThread: NeoAudioThread? = null
var screenKeyboard: View? = null
var glView: NeoGLView? = null
var isPaused = false
var client: NeoXorgViewClient? = null
var keyboardWithoutTextInputShown = false
var isPaused = false
var screenKeyboardHintMessage: String? = null
var textInput = LinkedList<Int>()
}

View File

@ -18,7 +18,7 @@ class FullScreenHelper private constructor(activity: Activity, var fullScreen: B
* @param isShow true is show else hidden
* *
* @param keyboardHeight keyboard height
* @param keyboardHeight screenKeyboard height
*/
fun onKeyboardChange(isShow: Boolean, keyboardHeight: Int)
}
@ -93,10 +93,10 @@ class FullScreenHelper private constructor(activity: Activity, var fullScreen: B
val usableHeightSansKeyboard = mChildOfContent.rootView.height
val heightDifference = usableHeightSansKeyboard - usableHeightNow
if (heightDifference > usableHeightSansKeyboard / 4) {
// keyboard probably just became visible
// screenKeyboard probably just became visible
currentHeightLayoutHeight = usableHeightSansKeyboard - heightDifference
} else {
// keyboard probably just became hidden
// screenKeyboard probably just became hidden
currentHeightLayoutHeight = usableHeightSansKeyboard
}
frameLayoutParams.height = currentHeightLayoutHeight