diff --git a/app/build.gradle b/app/build.gradle
index da71a2b..a798251 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,8 +17,8 @@ android {
applicationId "io.neoterm"
minSdkVersion 21
targetSdkVersion 25
- versionCode 5
- versionName "1.1.3"
+ versionCode 6
+ versionName "1.1.4"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resConfigs "zh"
externalNativeBuild {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ffb2263..f5c6cae 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,14 +10,12 @@
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/backend/TerminalEmulator.java b/app/src/main/java/io/neoterm/backend/TerminalEmulator.java
index a73f87a..32e3ef1 100755
--- a/app/src/main/java/io/neoterm/backend/TerminalEmulator.java
+++ b/app/src/main/java/io/neoterm/backend/TerminalEmulator.java
@@ -421,8 +421,14 @@ public final class TerminalEmulator {
if (codePoint >= 0x80 && codePoint <= 0x9F) {
// Sequence decoded to a C1 control character which is the same as escape followed by
// ((code & 0x7F) + 0x40).
- processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27);
- processCodePoint((codePoint & 0x7F) + 0x40);
+ // processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27);
+ // processCodePoint((codePoint & 0x7F) + 0x40);
+
+ // Sequence decoded to a C1 control character which we ignore. They are
+ // not used nowadays and increases the risk of messing up the terminal state
+ // on binary input. XTerm does not allow them in utf-8:
+ // "It is not possible to use a C1 control obtained from decoding the
+ // UTF-8 text" - http://invisible-island.net/xterm/ctlseqs/ctlseqs.htm
} else {
switch (Character.getType(codePoint)) {
case Character.UNASSIGNED:
diff --git a/app/src/main/java/io/neoterm/ui/NeoTermActivity.kt b/app/src/main/java/io/neoterm/ui/NeoTermActivity.kt
index d79dd15..3d696f8 100644
--- a/app/src/main/java/io/neoterm/ui/NeoTermActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/NeoTermActivity.kt
@@ -114,7 +114,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
TabSwitcher.setupWithMenu(tabSwitcher, toolbar.menu, View.OnClickListener {
val imm = this@NeoTermActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (!tabSwitcher.isSwitcherShown) {
- if (imm.isActive) {
+ if (imm.isActive && tabSwitcher.selectedTab is TermTab) {
val tab = tabSwitcher.selectedTab as TermTab
tab.hideIme()
}
diff --git a/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt b/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
index 924c090..b85fc84 100644
--- a/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
@@ -68,10 +68,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
.setTitle(model.packageInfo.packageName)
.setMessage(model.getPackageDetails(this@PackageManagerActivity))
.setPositiveButton(R.string.install, { _, _ ->
- TerminalDialog(this@PackageManagerActivity)
- .execute(NeoTermPath.APT_BIN_PATH,
- arrayOf("apt", "install", "-y", model.packageInfo.packageName!!))
- .show("Installing ${model.packageInfo.packageName}")
+ installPackage(model.packageInfo.packageName)
})
.setNegativeButton(android.R.string.no, null)
.show()
@@ -89,6 +86,20 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
refreshPackageList()
}
+ private fun installPackage(packageName: String?) {
+ if (packageName != null) {
+ TerminalDialog(this@PackageManagerActivity)
+ .execute(NeoTermPath.APT_BIN_PATH,
+ arrayOf("apt", "install", "-y", packageName))
+ .onFinish(object : TerminalDialog.SessionFinishedCallback {
+ override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
+ dialog.setTitle(getString(R.string.done))
+ }
+ })
+ .show("Installing $packageName")
+ }
+ }
+
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_pm, menu)
val searchItem = menu!!.findItem(R.id.action_search)
@@ -170,6 +181,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
TerminalDialog(this@PackageManagerActivity)
.onFinish(object : TerminalDialog.SessionFinishedCallback {
override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
+ dialog.dismiss()
refreshPackageList()
}
})
diff --git a/app/src/main/java/io/neoterm/ui/settings/UISettingsActivity.kt b/app/src/main/java/io/neoterm/ui/settings/UISettingsActivity.kt
index 0778722..dcbcfd1 100644
--- a/app/src/main/java/io/neoterm/ui/settings/UISettingsActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/settings/UISettingsActivity.kt
@@ -4,6 +4,7 @@ import android.app.AlertDialog
import android.os.Bundle
import android.support.v7.app.AppCompatPreferenceActivity
import android.view.MenuItem
+import android.widget.Toast
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.preference.NeoPreference
@@ -39,9 +40,11 @@ class UISettingsActivity : AppCompatPreferenceActivity() {
TerminalDialog(this)
.onFinish(object : TerminalDialog.SessionFinishedCallback {
override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
- dialog.dismiss()
if (finishedSession?.exitStatus == 0) {
+ dialog.dismiss()
NeoPreference.store(R.string.key_general_shell, "zsh")
+ } else {
+ dialog.setTitle(getString(R.string.error))
}
}
})
diff --git a/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt b/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt
index 60940fb..899a395 100644
--- a/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt
@@ -1,7 +1,6 @@
package io.neoterm.ui.setup
import android.app.Activity
-import android.content.DialogInterface
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog
@@ -63,11 +62,17 @@ class SetupActivity : AppCompatActivity() {
}
TerminalDialog(this@SetupActivity)
- .onDismiss(DialogInterface.OnCancelListener {
- if (withShell != null) {
- NeoPreference.store(R.string.key_general_shell, withShell!!)
+ .onFinish(object : TerminalDialog.SessionFinishedCallback {
+ override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
+ if (finishedSession?.exitStatus == 0) {
+ dialog.dismiss()
+ if (withShell != null) {
+ NeoPreference.store(R.string.key_general_shell, withShell!!)
+ }
+ } else {
+ dialog.setTitle(getString(R.string.error))
+ }
}
- finish()
})
.execute(NeoTermPath.APT_BIN_PATH, packageList.toTypedArray())
.show(getString(R.string.installer_message))
@@ -106,11 +111,13 @@ class SetupActivity : AppCompatActivity() {
TerminalDialog(this)
.onFinish(object : TerminalDialog.SessionFinishedCallback {
override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
- dialog.dismiss()
nextButton.visibility = View.VISIBLE
val exit = finishedSession?.exitStatus ?: 1
if (exit == 0) {
+ dialog.dismiss()
aptUpdated = true
+ } else {
+ dialog.setTitle(getString(R.string.error))
}
}
})
diff --git a/app/src/main/java/io/neoterm/view/TerminalDialog.kt b/app/src/main/java/io/neoterm/view/TerminalDialog.kt
index 6977e78..d8f1065 100644
--- a/app/src/main/java/io/neoterm/view/TerminalDialog.kt
+++ b/app/src/main/java/io/neoterm/view/TerminalDialog.kt
@@ -66,6 +66,11 @@ class TerminalDialog(val context: Context) {
return this
}
+ fun setTitle(title: String?) : TerminalDialog {
+ dialog?.setTitle(title)
+ return this
+ }
+
fun onFinish(finishedCallback: SessionFinishedCallback):TerminalDialog {
this.sessionFinishedCallback = finishedCallback
return this
diff --git a/app/src/main/java/io/neoterm/view/TerminalView.java b/app/src/main/java/io/neoterm/view/TerminalView.java
index c266253..95a7f6c 100755
--- a/app/src/main/java/io/neoterm/view/TerminalView.java
+++ b/app/src/main/java/io/neoterm/view/TerminalView.java
@@ -36,22 +36,32 @@ import io.neoterm.backend.TerminalBuffer;
import io.neoterm.backend.TerminalEmulator;
import io.neoterm.backend.TerminalSession;
-/** View displaying and interacting with a {@link TerminalSession}. */
+/**
+ * View displaying and interacting with a {@link TerminalSession}.
+ */
public final class TerminalView extends View {
- /** Log view key and IME events. */
+ /**
+ * Log view key and IME events.
+ */
private static final boolean LOG_KEY_EVENTS = false;
- /** The currently displayed terminal session, whose emulator is {@link #mEmulator}. */
+ /**
+ * The currently displayed terminal session, whose emulator is {@link #mEmulator}.
+ */
TerminalSession mTermSession;
- /** Our terminal emulator whose session is {@link #mTermSession}. */
+ /**
+ * Our terminal emulator whose session is {@link #mTermSession}.
+ */
TerminalEmulator mEmulator;
TerminalRenderer mRenderer;
TerminalViewClient mClient;
- /** The top row of text to display. Ranges from -activeTranscriptRows to 0. */
+ /**
+ * The top row of text to display. Ranges from -activeTranscriptRows to 0.
+ */
int mTopRow;
boolean mIsSelectingText = false, mIsDraggingLeftSelection, mInitialTextSelection;
@@ -63,17 +73,25 @@ public final class TerminalView extends View {
float mScaleFactor = 1.f;
/* final */ GestureAndScaleRecognizer mGestureRecognizer;
- /** Keep track of where mouse touch event started which we report as mouse scroll. */
+ /**
+ * Keep track of where mouse touch event started which we report as mouse scroll.
+ */
private int mMouseScrollStartX = -1, mMouseScrollStartY = -1;
- /** Keep track of the time when a touch event leading to sending mouse scroll events started. */
+ /**
+ * Keep track of the time when a touch event leading to sending mouse scroll events started.
+ */
private long mMouseStartDownTime = -1;
/* final */ Scroller mScroller;
- /** What was left in from scrolling movement. */
+ /**
+ * What was left in from scrolling movement.
+ */
float mScrollRemainder;
- /** If non-zero, this is the last unicode code point received if that was a combining character. */
+ /**
+ * If non-zero, this is the last unicode code point received if that was a combining character.
+ */
int mCombiningAccent;
int mTextSize;
@@ -429,7 +447,9 @@ public final class TerminalView extends View {
return true;
}
- /** Send a single mouse event code to the terminal. */
+ /**
+ * Send a single mouse event code to the terminal.
+ */
void sendMouseEventCode(MotionEvent e, int button, boolean pressed) {
int x = (int) (e.getX() / mRenderer.mFontWidth) + 1;
int y = (int) ((e.getY() - mRenderer.mFontLineSpacingAndAscent) / mRenderer.mFontLineSpacing) + 1;
@@ -446,7 +466,9 @@ public final class TerminalView extends View {
mEmulator.sendMouseEvent(button, x, y, pressed);
}
- /** Perform a scroll, either from dragging the screen or by scrolling a mouse wheel. */
+ /**
+ * Perform a scroll, either from dragging the screen or by scrolling a mouse wheel.
+ */
void doScroll(MotionEvent event, int rowsDown) {
boolean up = rowsDown < 0;
int amount = Math.abs(rowsDown);
@@ -464,7 +486,9 @@ public final class TerminalView extends View {
}
}
- /** Overriding {@link View#onGenericMotionEvent(MotionEvent)}. */
+ /**
+ * Overriding {@link View#onGenericMotionEvent(MotionEvent)}.
+ */
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mEmulator != null && event.isFromSource(InputDevice.SOURCE_MOUSE) && event.getAction() == MotionEvent.ACTION_SCROLL) {
@@ -656,7 +680,7 @@ public final class TerminalView extends View {
void inputCodePoint(int codePoint, boolean controlDownFromEvent, boolean leftAltDownFromEvent) {
if (LOG_KEY_EVENTS) {
Log.i(EmulatorDebug.LOG_TAG, "inputCodePoint(codePoint=" + codePoint + ", controlDownFromEvent=" + controlDownFromEvent + ", leftAltDownFromEvent="
- + leftAltDownFromEvent + ")");
+ + leftAltDownFromEvent + ")");
}
final boolean controlDown = controlDownFromEvent || mClient.readControlKey();
@@ -709,7 +733,9 @@ public final class TerminalView extends View {
}
}
- /** Input the specified keyCode if applicable and return if the input was consumed. */
+ /**
+ * Input the specified keyCode if applicable and return if the input was consumed.
+ */
public boolean handleKeyCode(int keyCode, int keyMod) {
TerminalEmulator term = mTermSession.getEmulator();
String code = KeyHandler.getCode(keyCode, keyMod, term.isCursorKeysApplicationMode(), term.isKeypadApplicationMode());
@@ -751,7 +777,9 @@ public final class TerminalView extends View {
updateSize();
}
- /** Check if the terminal size in rows and columns should be updated. */
+ /**
+ * Check if the terminal size in rows and columns should be updated.
+ */
public void updateSize() {
int viewWidth = getWidth();
int viewHeight = getHeight();
@@ -795,7 +823,9 @@ public final class TerminalView extends View {
}
}
- /** Toggle text selection mode in the view. */
+ /**
+ * Toggle text selection mode in the view.
+ */
@TargetApi(23)
public void toggleSelectingText(MotionEvent ev) {
mIsSelectingText = !mIsSelectingText;
@@ -851,6 +881,11 @@ public final class TerminalView extends View {
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ if (!mIsSelectingText) {
+ // Fix issue where the dialog is pressed while being dismissed.
+ return true;
+ }
+
switch (item.getItemId()) {
case 1:
String selectedText = mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2).trim();
diff --git a/app/src/main/res/xml/backup_config.xml b/app/src/main/res/xml/backup_config.xml
new file mode 100644
index 0000000..400d2ee
--- /dev/null
+++ b/app/src/main/res/xml/backup_config.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file