diff --git a/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt b/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt index 587df86..8a59e4c 100644 --- a/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt +++ b/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt @@ -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) } } diff --git a/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt b/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt index 6b36438..1421ed0 100644 --- a/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt +++ b/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt @@ -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 = "" diff --git a/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt b/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt index b03ca74..08ce026 100644 --- a/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt +++ b/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt @@ -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 diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt b/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt index 2a0d482..301ba94 100644 --- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt +++ b/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt @@ -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 diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt b/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt index 80e5e01..1a9bb19 100644 --- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt +++ b/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt @@ -14,7 +14,7 @@ import java.io.File open class ShellTermSession private constructor(shellPath: String, cwd: String, args: Array, env: Array, changeCallback: SessionChangedCallback, - val initialCommand: String?, + private val initialCommand: String?, val shellProfile: ShellProfile) : TerminalSession(shellPath, cwd, args, env, changeCallback) { diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt index 3509b48..17e27c4 100644 --- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt +++ b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt @@ -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() } diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermDataHolder.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt similarity index 72% rename from app/src/main/java/io/neoterm/frontend/session/shell/client/TermDataHolder.kt rename to app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt index dd8963a..01fcb8a 100644 --- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermDataHolder.kt +++ b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt @@ -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?) { diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt index 0136318..5eec632 100644 --- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt +++ b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt @@ -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) diff --git a/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java b/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java index 83150a9..c1f7175 100755 --- a/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java +++ b/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java @@ -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; + } } diff --git a/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt b/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt index 6508422..e515aef 100644 --- a/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt +++ b/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt @@ -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 } } \ No newline at end of file diff --git a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt b/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt index 71ae776..2f4787b 100644 --- a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt +++ b/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt @@ -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() { diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 142475c..0f6f9fc 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -22,6 +22,8 @@ 音量下为 Ctrl\n音量上为 FN 使用自定义的 execve() 接管 execve() 来兼容 linux 风格的 shebang + 启用基于单词的输入法 + 输入单位为单词而不是字母(谷歌输入法无法输入中文可以勾选此选项) 软件源 向下切换窗口 关闭当前窗口时切换到下一个窗口而不是上一个 diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index feeb0c0..0f98016 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -8,6 +8,7 @@ neoterm_general_auto_completion neoterm_general_volume_as_control neoterm_general_use_execve_wrapper + neoterm_general_enable_word_based_ime neoterm_ui_fullscreen neoterm_ui_hide_toolbar diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 85d8b4f..c904098 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,6 +89,8 @@ Volume Down as Ctrl\nVolume Up as FN Use execve() wrapper Hook execve() to avoid incorrect shebang + Enable word based IME + Word based or char based IME Full Screen Hide Toolbar Hide toolbar when keyboard is showing diff --git a/app/src/main/res/xml/setting_general.xml b/app/src/main/res/xml/setting_general.xml index 4580cac..8361ce1 100644 --- a/app/src/main/res/xml/setting_general.xml +++ b/app/src/main/res/xml/setting_general.xml @@ -43,6 +43,12 @@ android:summary="@string/pref_general_use_execve_wrapper_desc" android:title="@string/pref_general_use_execve_wrapper" /> + +