Fix: Crash when click context menu too fast.

This commit is contained in:
zt515
2017-07-08 00:23:43 +08:00
parent 1812d348df
commit c9de9541bf
10 changed files with 121 additions and 35 deletions

View File

@ -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 {

View File

@ -10,14 +10,12 @@
<application
android:name=".App"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_config"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.setup.SetupActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ui.NeoTermActivity"
android:configChanges="orientation|keyboardHidden"
@ -31,6 +29,9 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.setup.SetupActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ui.pm.PackageManagerActivity"
android:label="@string/package_settings"
@ -50,9 +51,21 @@
android:name=".ui.settings.UISettingsActivity"
android:theme="@style/Theme.AppCompat" />
<activity-alias
android:name=".NeoLotMainActivity"
android:targetActivity="io.neoterm.ui.NeoTermActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity-alias>
<service
android:name=".services.NeoTermService"
android:enabled="true" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
</application>
</manifest>

View File

@ -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:

View File

@ -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()
}

View File

@ -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()
}
})

View File

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

View File

@ -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 {
.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!!)
}
finish()
} else {
dialog.setTitle(getString(R.string.error))
}
}
})
.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))
}
}
})

View File

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

View File

@ -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) {
@ -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();

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<!-- See https://developer.android.com/training/backup/autosyncapi.html -->
<include domain="file" path="home/auto_backup" />
</full-backup-content>