TerminalView: Use word based ime

This commit is contained in:
zt515 2017-12-19 23:39:10 +08:00
parent 9963c649b8
commit aa7d28ba95
15 changed files with 83 additions and 59 deletions

View File

@ -46,8 +46,8 @@ class CandidatePopupWindow(val context: Context) {
}
popWindow.showAtLocation(terminalView, Gravity.BOTTOM.and(Gravity.START),
terminalView.cursorAbsX,
terminalView.cursorAbsY)
terminalView.cursorAbsoluteX,
terminalView.cursorAbsoluteY)
}
}

View File

@ -19,6 +19,7 @@ object DefaultValues {
const val enableExplicitExtraKeysWeight = false
const val enableBackButtonBeMappedToEscape = false
const val enableSpecialVolumeKeys = false
const val enableWordBasedIme = false
const val loginShell = "sh"
const val initialCommand = ""

View File

@ -25,15 +25,8 @@ object NeoPreference {
const val KEY_CURRENT_SESSION = "neoterm_service_current_session"
const val KEY_SYSTEM_SHELL = "neoterm_core_system_shell"
const val KEY_SOURCES = "neoterm_source_source_list"
// const val KEY_FLOATING_WINDOW_X = "neoterm_floating_window_x"
// const val KEY_FLOATING_WINDOW_Y = "neoterm_floating_window_y"
// const val KEY_FLOATING_WIDTH = "neoterm_floating_window_width"
// const val KEY_FLOATING_HEIGHT = "neoterm_floating_window_height"
const val VALUE_HAPPY_EGG_TRIGGER = 8
const val VALUE_NEOTERM_ONLY = "NeoTermOnly"
const val VALUE_NEOTERM_FIRST = "NeoTermFirst"
const val VALUE_SYSTEM_FIRST = "SystemFirst"
var MIN_FONT_SIZE: Int = 0
private set
@ -243,22 +236,10 @@ object NeoPreference {
DefaultValues.enableSwitchNextTab)
}
// fun storeWindowSize(context: Context, width: Int, height: Int) {
// store(KEY_FLOATING_WIDTH, width)
// store(KEY_FLOATING_HEIGHT, height)
// }
//
// fun storeWindowLocation(context: Context, x: Int, y: Int) {
// store(KEY_FLOATING_WINDOW_X, x)
// store(KEY_FLOATING_WINDOW_Y, y)Se
// }
//
// fun applySavedWindowParameter(context: Context, layout: WindowManager.LayoutParams) {
// layout.x = loadInt(KEY_FLOATING_WINDOW_X, 200)
// layout.y = loadInt(KEY_FLOATING_WINDOW_Y, 200)
// layout.width = loadInt(KEY_FLOATING_WIDTH, 500)
// layout.height = loadInt(KEY_FLOATING_HEIGHT, 800)
// }
fun isWordBasedImeEnabled() : Boolean {
return loadBoolean(R.string.key_general_enable_word_based_ime,
DefaultValues.enableWordBasedIme)
}
/**
* TODO

View File

@ -26,6 +26,7 @@ class ShellProfile : NeoProfile() {
private const val EXTRA_KEYS = "extra-keys"
private const val FONT = "font"
private const val COLOR_SCHEME = "color-scheme"
private const val WORD_BASED_IME = "word-based-ime"
private val PROFILE_META_PATH = arrayOf(PROFILE_META_NAME)
}
@ -42,6 +43,7 @@ class ShellProfile : NeoProfile() {
var enableAutoCompletion = DefaultValues.enableAutoCompletion
var enableBackKeyToEscape = DefaultValues.enableBackButtonBeMappedToEscape
var enableExtraKeys = DefaultValues.enableExtraKeys
var enableWordBasedIme = DefaultValues.enableWordBasedIme
var profileFont: String
var profileColorScheme: String
@ -62,6 +64,7 @@ class ShellProfile : NeoProfile() {
enableAutoCompletion = NeoPreference.isAutoCompletionEnabled()
enableBackKeyToEscape = NeoPreference.isBackButtonBeMappedToEscapeEnabled()
enableExtraKeys = NeoPreference.isExtraKeysEnabled()
enableWordBasedIme = NeoPreference.isWordBasedImeEnabled()
}
override fun onProfileLoaded(visitor: ConfigVisitor): Boolean {
@ -74,6 +77,7 @@ class ShellProfile : NeoProfile() {
enableAutoCompletion = visitor.getProfileBoolean(AUTO_COMPLETION, enableAutoCompletion)
enableBackKeyToEscape = visitor.getProfileBoolean(BACK_KEY_TO_ESC, enableBackKeyToEscape)
enableExtraKeys = visitor.getProfileBoolean(EXTRA_KEYS, enableExtraKeys)
enableWordBasedIme = visitor.getProfileBoolean(WORD_BASED_IME, enableWordBasedIme)
profileFont = visitor.getProfileString(FONT, profileFont)
profileColorScheme = visitor.getProfileString(COLOR_SCHEME, profileColorScheme)
return true

View File

@ -14,7 +14,7 @@ import java.io.File
open class ShellTermSession private constructor(shellPath: String, cwd: String,
args: Array<String>, env: Array<String>,
changeCallback: SessionChangedCallback,
val initialCommand: String?,
private val initialCommand: String?,
val shellProfile: ShellProfile)
: TerminalSession(shellPath, cwd, args, env, changeCallback) {

View File

@ -10,26 +10,26 @@ import io.neoterm.frontend.session.shell.ShellTermSession
* @author kiva
*/
class TermSessionCallback : TerminalSession.SessionChangedCallback {
var termData: TermDataHolder? = null
var termSessionData: TermSessionData? = null
var bellController: BellController? = null
override fun onTextChanged(changedSession: TerminalSession?) {
termData?.termView?.onScreenUpdated()
termSessionData?.termView?.onScreenUpdated()
}
override fun onTitleChanged(changedSession: TerminalSession?) {
if (changedSession?.title != null) {
termData?.termUI?.requireUpdateTitle(changedSession.title)
termSessionData?.termUI?.requireUpdateTitle(changedSession.title)
}
}
override fun onSessionFinished(finishedSession: TerminalSession?) {
termData?.termUI?.requireOnSessionFinished()
termSessionData?.termUI?.requireOnSessionFinished()
}
override fun onClipboardText(session: TerminalSession?, text: String?) {
val termView = termData?.termView
val termView = termSessionData?.termView
if (termView != null) {
val clipboard = termView.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText("", text)
@ -37,7 +37,7 @@ class TermSessionCallback : TerminalSession.SessionChangedCallback {
}
override fun onBell(session: TerminalSession?) {
val termView = termData?.termView ?: return
val termView = termSessionData?.termView ?: return
val shellSession = session as ShellTermSession
if (bellController == null) {
@ -48,7 +48,7 @@ class TermSessionCallback : TerminalSession.SessionChangedCallback {
}
override fun onColorsChanged(session: TerminalSession?) {
val termView = termData?.termView
val termView = termSessionData?.termView
if (session != null && termView != null) {
termView.onScreenUpdated()
}

View File

@ -2,13 +2,15 @@ package io.neoterm.frontend.session.shell.client
import io.neoterm.backend.TerminalSession
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
import io.neoterm.frontend.session.shell.ShellProfile
import io.neoterm.frontend.session.shell.ShellTermSession
import io.neoterm.frontend.terminal.TerminalView
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
/**
* @author kiva
*/
class TermDataHolder {
class TermSessionData {
var termSession: TerminalSession? = null
var sessionCallback: TermSessionCallback? = null
var viewClient: TermViewClient? = null
@ -18,25 +20,33 @@ class TermDataHolder {
var termView: TerminalView? = null
var extraKeysView: ExtraKeysView? = null
var profile: ShellProfile? = null
fun cleanup() {
onAutoCompleteListener?.onCleanUp()
onAutoCompleteListener = null
sessionCallback?.termData = null
viewClient?.termData = null
sessionCallback?.termSessionData = null
viewClient?.termSessionData = null
termUI = null
termView = null
extraKeysView = null
termSession = null
profile = null
}
fun initializeSessionWith(session: TerminalSession, sessionCallback: TermSessionCallback?, viewClient: TermViewClient?) {
this.termSession = session
this.sessionCallback = sessionCallback
this.viewClient = viewClient
this.sessionCallback?.termData = this
this.viewClient?.termData = this
this.sessionCallback?.termSessionData = this
this.viewClient?.termSessionData = this
if (session is ShellTermSession) {
profile = session.shellProfile
}
}
fun initializeViewWith(termUI: TermUiPresenter?, termView: TerminalView?, eks: ExtraKeysView?) {

View File

@ -24,7 +24,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
private var mVirtualFnKeyDown: Boolean = false
private var lastTitle: String = ""
var termData: TermDataHolder? = null
var termSessionData: TermSessionData? = null
override fun onScale(scale: Float): Float {
if (scale < 0.9f || scale > 1.1f) {
@ -36,13 +36,13 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
override fun onSingleTapUp(e: MotionEvent?) {
val termView = termData?.termView ?: return
val termView = termSessionData?.termView ?: return
(context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
.showSoftInput(termView, InputMethodManager.SHOW_IMPLICIT)
}
override fun shouldBackButtonBeMappedToEscape(): Boolean {
val shellSession = termData?.termSession as ShellTermSession? ?: return false
val shellSession = termSessionData?.termSession as ShellTermSession? ?: return false
return shellSession.shellProfile.enableBackKeyToEscape
}
@ -55,7 +55,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
return true
}
val termUI = termData?.termUI
val termUI = termSessionData?.termUI
when (keyCode) {
KeyEvent.KEYCODE_ENTER -> {
@ -112,12 +112,12 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
override fun readControlKey(): Boolean {
val extraKeysView = termData?.extraKeysView
val extraKeysView = termSessionData?.extraKeysView
return (extraKeysView != null && extraKeysView.readControlButton()) || mVirtualControlKeyDown
}
override fun readAltKey(): Boolean {
val extraKeysView = termData?.extraKeysView
val extraKeysView = termSessionData?.extraKeysView
return (extraKeysView != null && extraKeysView.readAltButton()) || mVirtualFnKeyDown
}
@ -194,7 +194,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
return false
}
val shellSession = termData?.termSession as ShellTermSession? ?: return false
val shellSession = termSessionData?.termSession as ShellTermSession? ?: return false
// Volume keys as special keys
val volumeAsSpecialKeys = shellSession.shellProfile.enableSpecialVolumeKeys
@ -213,7 +213,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
fun updateExtraKeys(title: String?, force: Boolean = false) {
val extraKeysView = termData?.extraKeysView
val extraKeysView = termSessionData?.extraKeysView
if (extraKeysView == null || title == null || title.isEmpty()) {
return
@ -229,8 +229,8 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
private fun updateExtraKeysVisibility(): Boolean {
val extraKeysView = termData?.extraKeysView ?: return false
val shellSession = termData?.termSession as ShellTermSession? ?: return false
val extraKeysView = termSessionData?.extraKeysView ?: return false
val shellSession = termSessionData?.termSession as ShellTermSession? ?: return false
return if (shellSession.shellProfile.enableExtraKeys) {
extraKeysView.visibility = View.VISIBLE
@ -242,12 +242,12 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
private fun removeExtraKeys() {
val extraKeysView = termData?.extraKeysView
val extraKeysView = termSessionData?.extraKeysView
extraKeysView?.clearUserKeys()
}
private fun changeFontSize(increase: Boolean) {
val termView = termData?.termView
val termView = termSessionData?.termView
if (termView != null) {
val changedSize = (if (increase) 1 else -1) * 2
val fontSize = NeoPreference.validateFontSize(termView.textSize + changedSize)

View File

@ -97,6 +97,11 @@ public final class TerminalView extends View {
int mCombiningAccent;
int mTextSize;
/**
* If true, IME will be word based instead of char based.
*/
private boolean mEnableWordBasedIme = false;
public TerminalView(Context context) {
super(context);
commonInit(context);
@ -325,7 +330,12 @@ public final class TerminalView extends View {
// https://github.com/termux/termux-app/issues/87.
// https://github.com/termux/termux-app/issues/126.
// https://github.com/termux/termux-app/issues/137 (japanese chars and TYPE_NULL).
outAttrs.inputType = InputType.TYPE_NULL;
if (mEnableWordBasedIme) {
// Workaround for Google Pinying cannot input Chinese
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
} else {
outAttrs.inputType = InputType.TYPE_NULL;
}
// Note that IME_ACTION_NONE cannot be used as that makes it impossible to input newlines using the on-screen
// keyboard on Android TV (see https://github.com/termux/termux-app/issues/221).
@ -1089,13 +1099,17 @@ public final class TerminalView extends View {
this.onAutoCompleteListener = onAutoCompleteListener;
}
public int getCursorAbsX() {
public int getCursorAbsoluteX() {
return (int) mRenderer.getCursorX();
}
public int getCursorAbsY() {
public int getCursorAbsoluteY() {
int[] locations = new int[2];
getLocationOnScreen(locations);
return (int) (mRenderer.getCursorY() + locations[1]);
}
public void setEnableWordBasedIme(boolean mEnableWordBasedIme) {
this.mEnableWordBasedIme = mEnableWordBasedIme;
}
}

View File

@ -16,6 +16,7 @@ import io.neoterm.NeoGLView
import io.neoterm.R
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.frontend.config.DefaultValues
import io.neoterm.frontend.terminal.TerminalView
import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
import io.neoterm.ui.term.NeoTermActivity
@ -26,8 +27,9 @@ import io.neoterm.utils.TerminalUtils
*/
class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
companion object {
private val VIEW_TYPE_TERM = 1
private val VIEW_TYPE_X = 2
private var VIEW_TYPE_COUNT = 0
private val VIEW_TYPE_TERM = VIEW_TYPE_COUNT++
private val VIEW_TYPE_X = VIEW_TYPE_COUNT++
}
private fun setViewLayerType(view: View?) = view?.setLayerType(View.LAYER_TYPE_NONE, null)
@ -146,6 +148,7 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
val termData = tab.termData
termData.initializeViewWith(tab, termView, extraKeysView)
termView.setEnableWordBasedIme(termData.profile?.enableWordBasedIme ?: DefaultValues.enableWordBasedIme)
termView.setTerminalViewClient(termData.viewClient)
termView.attachSession(termData.termSession)
@ -155,7 +158,7 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
}
override fun getViewTypeCount(): Int {
return 2
return VIEW_TYPE_COUNT
}
override fun getViewType(tab: Tab, index: Int): Int {
@ -164,6 +167,6 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
} else if (tab is XSessionTab) {
return VIEW_TYPE_X
}
return 0
return -1
}
}

View File

@ -4,7 +4,7 @@ import android.content.Context
import android.support.v7.widget.Toolbar
import android.view.inputmethod.InputMethodManager
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.session.shell.client.TermDataHolder
import io.neoterm.frontend.session.shell.client.TermSessionData
import io.neoterm.frontend.session.shell.client.TermUiPresenter
import io.neoterm.frontend.session.shell.client.event.*
import io.neoterm.frontend.component.ComponentManager
@ -19,7 +19,7 @@ class TermTab(title: CharSequence) : NeoTab(title), TermUiPresenter {
val PARAMETER_SHOW_EKS = "show_eks"
}
var termData = TermDataHolder()
var termData = TermSessionData()
var toolbar: Toolbar? = null
fun updateColorScheme() {

View File

@ -22,6 +22,8 @@
<string name="pref_general_volume_as_control_desc">音量下为 Ctrl\n音量上为 FN</string>
<string name="pref_general_use_execve_wrapper">使用自定义的 execve()</string>
<string name="pref_general_use_execve_wrapper_desc">接管 execve() 来兼容 linux 风格的 shebang</string>
<string name="pref_general_enable_word_based_ime">启用基于单词的输入法</string>
<string name="pref_general_enable_word_based_ime_desc">输入单位为单词而不是字母(谷歌输入法无法输入中文可以勾选此选项)</string>
<string name="pref_package_source">软件源</string>
<string name="pref_ui_close_tab_anim_next_tab">向下切换窗口</string>
<string name="pref_ui_close_tab_anim_next_tab_desc">关闭当前窗口时切换到下一个窗口而不是上一个</string>

View File

@ -8,6 +8,7 @@
<string name="key_general_auto_completion" translatable="false">neoterm_general_auto_completion</string>
<string name="key_general_volume_as_control" translatable="false">neoterm_general_volume_as_control</string>
<string name="key_general_use_execve_wrapper" translatable="false">neoterm_general_use_execve_wrapper</string>
<string name="key_general_enable_word_based_ime" translatable="false">neoterm_general_enable_word_based_ime</string>
<string name="key_ui_fullscreen" translatable="false">neoterm_ui_fullscreen</string>
<string name="key_ui_hide_toolbar" translatable="false">neoterm_ui_hide_toolbar</string>

View File

@ -89,6 +89,8 @@
<string name="pref_general_volume_as_control_desc">Volume Down as Ctrl\nVolume Up as FN</string>
<string name="pref_general_use_execve_wrapper">Use execve() wrapper</string>
<string name="pref_general_use_execve_wrapper_desc">Hook execve() to avoid incorrect shebang</string>
<string name="pref_general_enable_word_based_ime">Enable word based IME</string>
<string name="pref_general_enable_word_based_ime_desc">Word based or char based IME</string>
<string name="pref_ui_fullscreen">Full Screen</string>
<string name="pref_ui_hide_toolbar">Hide Toolbar</string>
<string name="pref_ui_hide_toolbar_desc">Hide toolbar when keyboard is showing</string>

View File

@ -43,6 +43,12 @@
android:summary="@string/pref_general_use_execve_wrapper_desc"
android:title="@string/pref_general_use_execve_wrapper" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_general_enable_word_based_ime"
android:summary="@string/pref_general_enable_word_based_ime_desc"
android:title="@string/pref_general_enable_word_based_ime" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_general_auto_completion"