Fix: Crash when click context menu too fast.
This commit is contained in:
@ -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 {
|
||||
|
@ -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>
|
@ -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:
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
})
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
5
app/src/main/res/xml/backup_config.xml
Normal file
5
app/src/main/res/xml/backup_config.xml
Normal 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>
|
Reference in New Issue
Block a user