Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a09b6d2a6 | ||
|
|
9d3f7734a1 | ||
|
|
61f766b59f | ||
|
|
3f08376881 | ||
|
|
cf06e70429 | ||
|
|
0714e435cb | ||
|
|
c26315185f | ||
|
|
adc43c40c5 | ||
|
|
779b1ca1f8 | ||
|
|
e375f99b0c | ||
|
|
0ac55cd77a | ||
|
|
4aefa5049b | ||
|
|
5b14124258 | ||
|
|
1a9c38374c | ||
|
|
eefd504f08 | ||
|
|
19f838e3d1 | ||
|
|
63adb2b132 | ||
|
|
7d3a988d2f | ||
|
|
5cd705d6d1 | ||
|
|
af8b269b51 | ||
|
|
8c220eaaea | ||
|
|
0142e1ed0e | ||
|
|
ac0a349ed9 | ||
|
|
548b0916b6 | ||
|
|
009de5a3ee | ||
|
|
41d0d60017 | ||
|
|
12ac0fa73c | ||
|
|
835dfc0276 | ||
|
|
f60316835f | ||
|
|
f74a091be6 | ||
|
|
dd6cb5221d | ||
|
|
cab6df5c0e | ||
|
|
f6f0809558 | ||
|
|
11ed7e45d8 |
2
.idea/gradle.xml
generated
@@ -10,6 +10,8 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
<option value="$PROJECT_DIR$/terminal-emulator" />
|
||||||
|
<option value="$PROJECT_DIR$/terminal-view" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ android:
|
|||||||
components:
|
components:
|
||||||
- platform-tools
|
- platform-tools
|
||||||
- tools
|
- tools
|
||||||
- build-tools-25.0.2
|
- build-tools-25.0.3
|
||||||
- android-25
|
- android-25
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
|
|
||||||
|
|||||||
3
LICENSE.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html).
|
||||||
|
|
||||||
|
Contains code from `Terminal Emulator for Android` by which is released under [the Apache License 2.0](https://www.apache.org/licenses/).
|
||||||
@@ -12,10 +12,6 @@ Termux app
|
|||||||
|
|
||||||
Note that this repository is for the app itself (the user interface and the terminal emulation). For the packages installable inside the app, see [termux/termux-packages](https://github.com/termux/termux-packages)
|
Note that this repository is for the app itself (the user interface and the terminal emulation). For the packages installable inside the app, see [termux/termux-packages](https://github.com/termux/termux-packages)
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). Contains code from `Terminal Emulator for Android` which is released under [the Apache License 2.0](https://www.apache.org/licenses/).
|
|
||||||
|
|
||||||
Terminal resources
|
Terminal resources
|
||||||
==================
|
==================
|
||||||
* [XTerm control sequences](http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
|
* [XTerm control sequences](http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
|
||||||
|
|||||||
@@ -2,29 +2,20 @@ apply plugin: 'com.android.application'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 25
|
||||||
buildToolsVersion "25.0.2"
|
buildToolsVersion "25.0.3"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:support-annotations:25.1.0'
|
compile 'com.android.support:support-annotations:25.3.1'
|
||||||
compile "com.android.support:support-v4:25.1.0"
|
compile "com.android.support:support-v4:25.3.1"
|
||||||
|
compile project(":terminal-view")
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 47
|
versionCode 50
|
||||||
versionName "0.47"
|
versionName "0.50"
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
ndkBuild {
|
|
||||||
cFlags "-std=c11", "-Wall", "-Wextra", "-Werror", "-Os", "-fno-stack-protector", "-Wl,--gc-sections"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ndk {
|
|
||||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -34,12 +25,6 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
ndkBuild {
|
|
||||||
path "src/main/jni/Android.mk"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.termux;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.test.ApplicationTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
|
||||||
*/
|
|
||||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
|
||||||
public ApplicationTest() {
|
|
||||||
super(Application.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:extractNativeLibs="true"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:fullBackupContent="@xml/backupscheme"
|
android:fullBackupContent="@xml/backupscheme"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|||||||
@@ -116,8 +116,9 @@ public final class BackgroundJob {
|
|||||||
final String langEnv = "LANG=en_US.UTF-8";
|
final String langEnv = "LANG=en_US.UTF-8";
|
||||||
final String pathEnv = "PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets";
|
final String pathEnv = "PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets";
|
||||||
final String pwdEnv = "PWD=" + cwd;
|
final String pwdEnv = "PWD=" + cwd;
|
||||||
|
final String tmpdirEnv = "TMPDIR=" + TermuxService.PREFIX_PATH + "/tmp";
|
||||||
|
|
||||||
return new String[]{termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv};
|
return new String[]{termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv, tmpdirEnv};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +159,6 @@ public final class BackgroundJob {
|
|||||||
if (c == ' ' || c == '\n') {
|
if (c == ' ' || c == '\n') {
|
||||||
if (builder.length() == 0) {
|
if (builder.length() == 0) {
|
||||||
// Skip whitespace after shebang.
|
// Skip whitespace after shebang.
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
// End of shebang.
|
// End of shebang.
|
||||||
String executable = builder.toString();
|
String executable = builder.toString();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.termux.app;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -144,6 +145,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
button.setOnClickListener(new OnClickListener() {
|
button.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
finalButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
||||||
View root = getRootView();
|
View root = getRootView();
|
||||||
switch (buttonText) {
|
switch (buttonText) {
|
||||||
case "CTRL":
|
case "CTRL":
|
||||||
|
|||||||
@@ -49,8 +49,6 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.View.OnLongClickListener;
|
import android.view.View.OnLongClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
@@ -215,7 +213,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
|
|
||||||
setContentView(R.layout.drawer_layout);
|
setContentView(R.layout.drawer_layout);
|
||||||
mTerminalView = (TerminalView) findViewById(R.id.terminal_view);
|
mTerminalView = (TerminalView) findViewById(R.id.terminal_view);
|
||||||
mTerminalView.setOnKeyListener(new TermuxKeyListener(this));
|
mTerminalView.setOnKeyListener(new TermuxViewClient(this));
|
||||||
|
|
||||||
mTerminalView.setTextSize(mSettings.getFontSize());
|
mTerminalView.setTextSize(mSettings.getFontSize());
|
||||||
mFullScreenHelper.setImmersive(mSettings.isFullScreen());
|
mFullScreenHelper.setImmersive(mSettings.isFullScreen());
|
||||||
@@ -399,7 +397,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
@Override
|
@Override
|
||||||
public void onClipboardText(TerminalSession session, String text) {
|
public void onClipboardText(TerminalSession session, String text) {
|
||||||
if (!mIsVisible) return;
|
if (!mIsVisible) return;
|
||||||
showToast("Clipboard:\n\"" + text + "\"", false);
|
|
||||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
clipboard.setPrimaryClip(new ClipData(null, new String[]{"text/plain"}, new ClipData.Item(text)));
|
clipboard.setPrimaryClip(new ClipData(null, new String[]{"text/plain"}, new ClipData.Item(text)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.database.MatrixCursor;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
@@ -28,22 +29,10 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean isExternalUrl = data.getScheme() != null && !data.getScheme().equals("file");
|
|
||||||
if (isExternalUrl) {
|
|
||||||
Intent viewIntent = new Intent(Intent.ACTION_VIEW, data);
|
|
||||||
try {
|
|
||||||
context.startActivity(viewIntent);
|
|
||||||
} catch (ActivityNotFoundException e) {
|
|
||||||
Log.e(EmulatorDebug.LOG_TAG, "termux-open: No app handles the url " + data);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String filePath = data.getPath();
|
final String filePath = data.getPath();
|
||||||
final String contentTypeExtra = intent.getStringExtra("content-type");
|
final String contentTypeExtra = intent.getStringExtra("content-type");
|
||||||
final boolean useChooser = intent.getBooleanExtra("chooser", false);
|
final boolean useChooser = intent.getBooleanExtra("chooser", false);
|
||||||
final String intentAction = intent.getAction() == null ? Intent.ACTION_VIEW : intent.getAction();
|
final String intentAction = intent.getAction() == null ? Intent.ACTION_VIEW : intent.getAction();
|
||||||
|
|
||||||
switch (intentAction) {
|
switch (intentAction) {
|
||||||
case Intent.ACTION_SEND:
|
case Intent.ACTION_SEND:
|
||||||
case Intent.ACTION_VIEW:
|
case Intent.ACTION_VIEW:
|
||||||
@@ -54,6 +43,24 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean isExternalUrl = data.getScheme() != null && !data.getScheme().equals("file");
|
||||||
|
if (isExternalUrl) {
|
||||||
|
Intent urlIntent = new Intent(intentAction, data);
|
||||||
|
if (intentAction.equals(Intent.ACTION_SEND)) {
|
||||||
|
urlIntent.putExtra(Intent.EXTRA_TEXT, data.toString());
|
||||||
|
urlIntent.setData(null);
|
||||||
|
} else if (contentTypeExtra != null) {
|
||||||
|
urlIntent.setDataAndType(data, contentTypeExtra);
|
||||||
|
}
|
||||||
|
urlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
try {
|
||||||
|
context.startActivity(urlIntent);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.e(EmulatorDebug.LOG_TAG, "termux-open: No app handles the url " + data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final File fileToShare = new File(filePath);
|
final File fileToShare = new File(filePath);
|
||||||
if (!(fileToShare.isFile() && fileToShare.canRead())) {
|
if (!(fileToShare.isFile() && fileToShare.canRead())) {
|
||||||
Log.e(EmulatorDebug.LOG_TAG, "termux-open: Not a readable file: '" + fileToShare.getAbsolutePath() + "'");
|
Log.e(EmulatorDebug.LOG_TAG, "termux-open: Not a readable file: '" + fileToShare.getAbsolutePath() + "'");
|
||||||
@@ -105,7 +112,7 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
File file = new File(uri.getPath());
|
File file = new File(uri.getPath());
|
||||||
|
|
||||||
if (projection == null) {
|
if (projection == null) {
|
||||||
@@ -142,27 +149,27 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType(Uri uri) {
|
public String getType(@NonNull Uri uri) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(Uri uri, ContentValues values) {
|
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||||
File file = new File(uri.getPath());
|
File file = new File(uri.getPath());
|
||||||
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,8 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG);
|
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG);
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
|
|
||||||
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
|
// http://tools.android.com/tech-docs/lint-in-studio-2-3#TOC-WifiManager-Leak
|
||||||
|
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||||
mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, EmulatorDebug.LOG_TAG);
|
mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, EmulatorDebug.LOG_TAG);
|
||||||
mWifiLock.acquire();
|
mWifiLock.acquire();
|
||||||
|
|
||||||
@@ -173,7 +174,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Update the shown foreground service notification after making any changes that affect it. */
|
/** Update the shown foreground service notification after making any changes that affect it. */
|
||||||
private void updateNotification() {
|
void updateNotification() {
|
||||||
if (mWakeLock == null && mTerminalSessions.isEmpty() && mBackgroundTasks.isEmpty()) {
|
if (mWakeLock == null && mTerminalSessions.isEmpty() && mBackgroundTasks.isEmpty()) {
|
||||||
// Exit if we are updating after the user disabled all locks with no sessions or tasks running.
|
// Exit if we are updating after the user disabled all locks with no sessions or tasks running.
|
||||||
stopSelf();
|
stopSelf();
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ import android.view.inputmethod.InputMethodManager;
|
|||||||
import com.termux.terminal.KeyHandler;
|
import com.termux.terminal.KeyHandler;
|
||||||
import com.termux.terminal.TerminalEmulator;
|
import com.termux.terminal.TerminalEmulator;
|
||||||
import com.termux.terminal.TerminalSession;
|
import com.termux.terminal.TerminalSession;
|
||||||
import com.termux.view.TerminalKeyListener;
|
import com.termux.view.TerminalViewClient;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class TermuxKeyListener implements TerminalKeyListener {
|
public final class TermuxViewClient implements TerminalViewClient {
|
||||||
|
|
||||||
final TermuxActivity mActivity;
|
final TermuxActivity mActivity;
|
||||||
|
|
||||||
/** Keeping track of the special keys acting as Ctrl and Fn for the soft keyboard and other hardware keys. */
|
/** Keeping track of the special keys acting as Ctrl and Fn for the soft keyboard and other hardware keys. */
|
||||||
boolean mVirtualControlKeyDown, mVirtualFnKeyDown;
|
boolean mVirtualControlKeyDown, mVirtualFnKeyDown;
|
||||||
|
|
||||||
public TermuxKeyListener(TermuxActivity activity) {
|
public TermuxViewClient(TermuxActivity activity) {
|
||||||
this.mActivity = activity;
|
this.mActivity = activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +256,11 @@ public final class TermuxKeyListener implements TerminalKeyListener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongPress(MotionEvent event) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Handle dedicated volume buttons as virtual keys if applicable. */
|
/** Handle dedicated volume buttons as virtual keys if applicable. */
|
||||||
private boolean handleVirtualKeys(int keyCode, KeyEvent event, boolean down) {
|
private boolean handleVirtualKeys(int keyCode, KeyEvent event, boolean down) {
|
||||||
InputDevice inputDevice = event.getDevice();
|
InputDevice inputDevice = event.getDevice();
|
||||||
@@ -30,10 +30,6 @@
|
|||||||
<string name="select_url_copied_to_clipboard">URL copied to clipboard</string>
|
<string name="select_url_copied_to_clipboard">URL copied to clipboard</string>
|
||||||
<string name="share_transcript_chooser_title">Send text to:</string>
|
<string name="share_transcript_chooser_title">Send text to:</string>
|
||||||
|
|
||||||
<string name="paste_text">Paste</string>
|
|
||||||
<string name="copy_text">Copy</string>
|
|
||||||
<string name="text_selection_more">More…</string>
|
|
||||||
|
|
||||||
<string name="kill_process">Kill process (%d)</string>
|
<string name="kill_process">Kill process (%d)</string>
|
||||||
<string name="confirm_kill_process">Really kill this session?</string>
|
<string name="confirm_kill_process">Really kill this session?</string>
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
- If adding text, use large font sizes.
|
- If adding text, use large font sizes.
|
||||||
- Your graphic may be displayed alone without the app icon.
|
- Your graphic may be displayed alone without the app icon.
|
||||||
-->
|
-->
|
||||||
<svg xmlns:svg="http://www.w3.org/2000/svg"
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 1024 500">
|
viewBox="0 0 1024 500">
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 962 B |
@@ -7,8 +7,7 @@
|
|||||||
- Text must be included in the image. If your app is available in more
|
- Text must be included in the image. If your app is available in more
|
||||||
than one language, you must provide versions of the banner image for each supported language.
|
than one language, you must provide versions of the banner image for each supported language.
|
||||||
-->
|
-->
|
||||||
<svg xmlns:svg="http://www.w3.org/2000/svg"
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
version="1.1"
|
||||||
viewBox="0 0 1280 720">
|
viewBox="0 0 1280 720">
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 736 B |
@@ -5,7 +5,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
classpath 'com.android.tools.build:gradle:2.3.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Sun Dec 04 17:26:05 CET 2016
|
#Mon Mar 06 01:34:12 CET 2017
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
|
||||||
|
|||||||
78
scripts/bintray-publish.gradle
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Start https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle
|
||||||
|
apply plugin: 'com.github.dcendents.android-maven'
|
||||||
|
group = publishedGroupId // Maven Group ID for the artifact
|
||||||
|
install {
|
||||||
|
repositories.mavenInstaller {
|
||||||
|
pom {
|
||||||
|
project {
|
||||||
|
packaging 'aar'
|
||||||
|
groupId publishedGroupId
|
||||||
|
artifactId artifact
|
||||||
|
|
||||||
|
name libraryName
|
||||||
|
description libraryDescription
|
||||||
|
url siteUrl
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name 'GNU General Public License version 3'
|
||||||
|
url 'https://opensource.org/licenses/gpl-3.0.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id 'fornwall'
|
||||||
|
name 'Fredrik Fornwall'
|
||||||
|
email 'fredrik@fornwall.net'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection gitUrl
|
||||||
|
developerConnection gitUrl
|
||||||
|
url siteUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle
|
||||||
|
|
||||||
|
// Start https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle
|
||||||
|
apply plugin: 'com.jfrog.bintray'
|
||||||
|
|
||||||
|
version = libraryVersion
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar) {
|
||||||
|
classifier = 'sources'
|
||||||
|
from android.sourceSets.main.java.srcDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives sourcesJar
|
||||||
|
}
|
||||||
|
|
||||||
|
bintray {
|
||||||
|
user = System.getenv('BINTRAY_USER')
|
||||||
|
key = System.getenv('BINTRAY_API_KEY')
|
||||||
|
|
||||||
|
configurations = ['archives']
|
||||||
|
pkg {
|
||||||
|
repo = 'maven'
|
||||||
|
name = bintrayName
|
||||||
|
userOrg = 'termux'
|
||||||
|
desc = libraryDescription
|
||||||
|
websiteUrl = siteUrl
|
||||||
|
vcsUrl = gitUrl
|
||||||
|
licenses = ['GPL-3.0']
|
||||||
|
publish = true
|
||||||
|
publicDownloadNumbers = true
|
||||||
|
version {
|
||||||
|
desc = libraryDescription
|
||||||
|
gpg {
|
||||||
|
sign = false //Determines whether to GPG sign the files. The default is false
|
||||||
|
// passphrase = properties.getProperty("bintray.gpg.password")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
include ':app'
|
include ':app', ':terminal-emulator', ':terminal-view'
|
||||||
|
|||||||
62
terminal-emulator/build.gradle
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.jfrog.bintray" version "1.7"
|
||||||
|
id "com.github.dcendents.android-maven" version "1.5"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
ext {
|
||||||
|
bintrayName = 'terminal-emulator'
|
||||||
|
publishedGroupId = 'com.termux'
|
||||||
|
libraryName = 'TerminalEmulator'
|
||||||
|
artifact = 'terminal-emulator'
|
||||||
|
libraryDescription = 'The terminal emulator used in Termux'
|
||||||
|
siteUrl = 'https://github.com/termux/termux'
|
||||||
|
gitUrl = 'https://github.com/termux/termux.git'
|
||||||
|
libraryVersion = '0.49'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 25
|
||||||
|
buildToolsVersion "25.0.3"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 25
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
cFlags "-std=c11", "-Wall", "-Wextra", "-Werror", "-Os", "-fno-stack-protector", "-Wl,--gc-sections"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk {
|
||||||
|
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
path "src/main/jni/Android.mk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test) {
|
||||||
|
testLogging {
|
||||||
|
events "started", "passed", "skipped", "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: '../scripts/bintray-publish.gradle'
|
||||||
25
terminal-emulator/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/fornwall/lib/android-sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
3
terminal-emulator/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.termux.terminal">
|
||||||
|
</manifest>
|
||||||
@@ -3,7 +3,7 @@ package com.termux.terminal;
|
|||||||
/**
|
/**
|
||||||
* A circular buffer of {@link TerminalRow}:s which keeps notes about what is visible on a logical screen and the scroll
|
* A circular buffer of {@link TerminalRow}:s which keeps notes about what is visible on a logical screen and the scroll
|
||||||
* history.
|
* history.
|
||||||
* <p/>
|
* <p>
|
||||||
* See {@link #externalToInternalRow(int)} for how to map from logical screen rows to array indices.
|
* See {@link #externalToInternalRow(int)} for how to map from logical screen rows to array indices.
|
||||||
*/
|
*/
|
||||||
public final class TerminalBuffer {
|
public final class TerminalBuffer {
|
||||||
@@ -92,22 +92,20 @@ public final class TerminalBuffer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a row value from the public external coordinate system to our internal private coordinate system.
|
* Convert a row value from the public external coordinate system to our internal private coordinate system.
|
||||||
* <p/>
|
*
|
||||||
* <ul>
|
|
||||||
* <li>External coordinate system: -mActiveTranscriptRows to mScreenRows-1, with the screen being 0..mScreenRows-1.
|
|
||||||
* <li>Internal coordinate system: the mScreenRows lines starting at mScreenFirstRow comprise the screen, while the
|
|
||||||
* mActiveTranscriptRows lines ending at mScreenFirstRow-1 form the transcript (as a circular buffer).
|
|
||||||
* </ul>
|
|
||||||
* <p/>
|
|
||||||
* External <---> Internal:
|
|
||||||
* <p/>
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* [ ... ] [ ... ]
|
* - External coordinate system: -mActiveTranscriptRows to mScreenRows-1, with the screen being 0..mScreenRows-1.
|
||||||
* [ -mActiveTranscriptRows ] [ mScreenFirstRow - mActiveTranscriptRows ]
|
* - Internal coordinate system: the mScreenRows lines starting at mScreenFirstRow comprise the screen, while the
|
||||||
* [ ... ] [ ... ]
|
* mActiveTranscriptRows lines ending at mScreenFirstRow-1 form the transcript (as a circular buffer).
|
||||||
* [ 0 (visible screen starts here) ] <-----> [ mScreenFirstRow ]
|
*
|
||||||
* [ ... ] [ ... ]
|
* External ↔ Internal:
|
||||||
* [ mScreenRows-1 ] [ mScreenFirstRow + mScreenRows-1 ]
|
*
|
||||||
|
* [ ... ] [ ... ]
|
||||||
|
* [ -mActiveTranscriptRows ] [ mScreenFirstRow - mActiveTranscriptRows ]
|
||||||
|
* [ ... ] [ ... ]
|
||||||
|
* [ 0 (visible screen starts here) ] ↔ [ mScreenFirstRow ]
|
||||||
|
* [ ... ] [ ... ]
|
||||||
|
* [ mScreenRows-1 ] [ mScreenFirstRow + mScreenRows-1 ]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param externalRow a row in the external coordinate system.
|
* @param externalRow a row in the external coordinate system.
|
||||||
@@ -56,8 +56,6 @@ public final class TerminalEmulator {
|
|||||||
private static final int ESC_SELECT_LEFT_PAREN = 3;
|
private static final int ESC_SELECT_LEFT_PAREN = 3;
|
||||||
/** Escape processing: Have seen ESC and a character-set-select ) char */
|
/** Escape processing: Have seen ESC and a character-set-select ) char */
|
||||||
private static final int ESC_SELECT_RIGHT_PAREN = 4;
|
private static final int ESC_SELECT_RIGHT_PAREN = 4;
|
||||||
/** Escape processing: Have seen ESC and a character-set-select + char */
|
|
||||||
// private static final int ESC_SELECT_PLUS = 5;
|
|
||||||
/** Escape processing: "ESC [" or CSI (Control Sequence Introducer). */
|
/** Escape processing: "ESC [" or CSI (Control Sequence Introducer). */
|
||||||
private static final int ESC_CSI = 6;
|
private static final int ESC_CSI = 6;
|
||||||
/** Escape processing: ESC [ ? */
|
/** Escape processing: ESC [ ? */
|
||||||
@@ -4,7 +4,7 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A row in a terminal, composed of a fixed number of cells.
|
* A row in a terminal, composed of a fixed number of cells.
|
||||||
* <p/>
|
* <p>
|
||||||
* The text in the row is stored in a char[] array, {@link #mText}, for quick access during rendering.
|
* The text in the row is stored in a char[] array, {@link #mText}, for quick access during rendering.
|
||||||
*/
|
*/
|
||||||
public final class TerminalRow {
|
public final class TerminalRow {
|
||||||
@@ -19,13 +19,13 @@ import java.util.UUID;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A terminal session, consisting of a process coupled to a terminal interface.
|
* A terminal session, consisting of a process coupled to a terminal interface.
|
||||||
* <p/>
|
* <p>
|
||||||
* The subprocess will be executed by the constructor, and when the size is made known by a call to
|
* The subprocess will be executed by the constructor, and when the size is made known by a call to
|
||||||
* {@link #updateSize(int, int)} terminal emulation will begin and threads will be spawned to handle the subprocess I/O.
|
* {@link #updateSize(int, int)} terminal emulation will begin and threads will be spawned to handle the subprocess I/O.
|
||||||
* All terminal emulation and callback methods will be performed on the main thread.
|
* All terminal emulation and callback methods will be performed on the main thread.
|
||||||
* <p/>
|
* <p>
|
||||||
* The child process may be exited forcefully by using the {@link #finishIfRunning()} method.
|
* The child process may be exited forcefully by using the {@link #finishIfRunning()} method.
|
||||||
* <p/>
|
* <p>
|
||||||
* NOTE: The terminal session may outlive the EmulatorView, so be careful with callbacks!
|
* NOTE: The terminal session may outlive the EmulatorView, so be careful with callbacks!
|
||||||
*/
|
*/
|
||||||
public final class TerminalSession extends TerminalOutput {
|
public final class TerminalSession extends TerminalOutput {
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
* Encodes effects, foreground and background colors into a 64 bit long, which are stored for each cell in a terminal
|
* Encodes effects, foreground and background colors into a 64 bit long, which are stored for each cell in a terminal
|
||||||
* row in {@link TerminalRow#mStyle}.
|
* row in {@link TerminalRow#mStyle}.
|
||||||
* <p/>
|
* </p>
|
||||||
|
* <p>
|
||||||
* The bit layout is:
|
* The bit layout is:
|
||||||
|
* </p>
|
||||||
* - 16 flags (11 currently used).
|
* - 16 flags (11 currently used).
|
||||||
* - 24 for foreground color (only 9 first bits if a color index).
|
* - 24 for foreground color (only 9 first bits if a color index).
|
||||||
* - 24 for background color (only 9 first bits if a color index).
|
* - 24 for background color (only 9 first bits if a color index).
|
||||||
@@ -20,9 +23,10 @@ public final class TextStyle {
|
|||||||
public final static int CHARACTER_ATTRIBUTE_STRIKETHROUGH = 1 << 6;
|
public final static int CHARACTER_ATTRIBUTE_STRIKETHROUGH = 1 << 6;
|
||||||
/**
|
/**
|
||||||
* The selective erase control functions (DECSED and DECSEL) can only erase characters defined as erasable.
|
* The selective erase control functions (DECSED and DECSEL) can only erase characters defined as erasable.
|
||||||
* <p/>
|
* <p>
|
||||||
* This bit is set if DECSCA (Select Character Protection Attribute) has been used to define the characters that
|
* This bit is set if DECSCA (Select Character Protection Attribute) has been used to define the characters that
|
||||||
* come after it as erasable from the screen.
|
* come after it as erasable from the screen.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public final static int CHARACTER_ATTRIBUTE_PROTECTED = 1 << 7;
|
public final static int CHARACTER_ATTRIBUTE_PROTECTED = 1 << 7;
|
||||||
/** Dim colors. Also known as faint or half intensity. */
|
/** Dim colors. Also known as faint or half intensity. */
|
||||||
46
terminal-view/build.gradle
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.jfrog.bintray" version "1.7"
|
||||||
|
id "com.github.dcendents.android-maven" version "1.5"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
ext {
|
||||||
|
bintrayName = 'terminal-view'
|
||||||
|
publishedGroupId = 'com.termux'
|
||||||
|
libraryName = 'TerminalView'
|
||||||
|
artifact = 'terminal-view'
|
||||||
|
libraryDescription = 'The terminal view used in Termux'
|
||||||
|
siteUrl = 'https://github.com/termux/termux'
|
||||||
|
gitUrl = 'https://github.com/termux/termux.git'
|
||||||
|
libraryVersion = '0.49'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 25
|
||||||
|
buildToolsVersion "25.0.3"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'com.android.support:support-annotations:25.3.1'
|
||||||
|
compile project(":terminal-emulator")
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 25
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: '../scripts/bintray-publish.gradle'
|
||||||
25
terminal-view/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/fornwall/lib/android-sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
3
terminal-view/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.termux.view">
|
||||||
|
</manifest>
|
||||||
@@ -6,7 +6,7 @@ import android.view.MotionEvent;
|
|||||||
import android.view.ScaleGestureDetector;
|
import android.view.ScaleGestureDetector;
|
||||||
|
|
||||||
/** A combination of {@link GestureDetector} and {@link ScaleGestureDetector}. */
|
/** A combination of {@link GestureDetector} and {@link ScaleGestureDetector}. */
|
||||||
public final class GestureAndScaleRecognizer {
|
final class GestureAndScaleRecognizer {
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
boolean onSingleTapUp(MotionEvent e);
|
boolean onSingleTapUp(MotionEvent e);
|
||||||
@@ -29,7 +29,6 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
import com.termux.R;
|
|
||||||
import com.termux.terminal.EmulatorDebug;
|
import com.termux.terminal.EmulatorDebug;
|
||||||
import com.termux.terminal.KeyHandler;
|
import com.termux.terminal.KeyHandler;
|
||||||
import com.termux.terminal.TerminalBuffer;
|
import com.termux.terminal.TerminalBuffer;
|
||||||
@@ -49,7 +48,7 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
TerminalRenderer mRenderer;
|
TerminalRenderer mRenderer;
|
||||||
|
|
||||||
TerminalKeyListener mOnKeyListener;
|
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;
|
int mTopRow;
|
||||||
@@ -106,7 +105,7 @@ public final class TerminalView extends View {
|
|||||||
requestFocus();
|
requestFocus();
|
||||||
if (!mEmulator.isMouseTrackingActive()) {
|
if (!mEmulator.isMouseTrackingActive()) {
|
||||||
if (!e.isFromSource(InputDevice.SOURCE_MOUSE)) {
|
if (!e.isFromSource(InputDevice.SOURCE_MOUSE)) {
|
||||||
mOnKeyListener.onSingleTapUp(e);
|
mClient.onSingleTapUp(e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +135,7 @@ public final class TerminalView extends View {
|
|||||||
public boolean onScale(float focusX, float focusY, float scale) {
|
public boolean onScale(float focusX, float focusY, float scale) {
|
||||||
if (mEmulator == null || mIsSelectingText) return true;
|
if (mEmulator == null || mIsSelectingText) return true;
|
||||||
mScaleFactor *= scale;
|
mScaleFactor *= scale;
|
||||||
mScaleFactor = mOnKeyListener.onScale(mScaleFactor);
|
mScaleFactor = mClient.onScale(mScaleFactor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +188,9 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLongPress(MotionEvent e) {
|
public void onLongPress(MotionEvent e) {
|
||||||
if (!mGestureRecognizer.isInProgress() && !mIsSelectingText) {
|
if (mGestureRecognizer.isInProgress()) return;
|
||||||
|
if (mClient.onLongPress(e)) return;
|
||||||
|
if (!mIsSelectingText) {
|
||||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
toggleSelectingText(e);
|
toggleSelectingText(e);
|
||||||
}
|
}
|
||||||
@@ -202,8 +203,8 @@ public final class TerminalView extends View {
|
|||||||
* @param onKeyListener Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
* @param onKeyListener Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
||||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||||
*/
|
*/
|
||||||
public void setOnKeyListener(TerminalKeyListener onKeyListener) {
|
public void setOnKeyListener(TerminalViewClient onKeyListener) {
|
||||||
this.mOnKeyListener = onKeyListener;
|
this.mClient = onKeyListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -555,7 +556,7 @@ public final class TerminalView extends View {
|
|||||||
if (mIsSelectingText) {
|
if (mIsSelectingText) {
|
||||||
toggleSelectingText(null);
|
toggleSelectingText(null);
|
||||||
return true;
|
return true;
|
||||||
} else if (mOnKeyListener.shouldBackButtonBeMappedToEscape()) {
|
} else if (mClient.shouldBackButtonBeMappedToEscape()) {
|
||||||
// Intercept back button to treat it as escape:
|
// Intercept back button to treat it as escape:
|
||||||
switch (event.getAction()) {
|
switch (event.getAction()) {
|
||||||
case KeyEvent.ACTION_DOWN:
|
case KeyEvent.ACTION_DOWN:
|
||||||
@@ -574,10 +575,10 @@ public final class TerminalView extends View {
|
|||||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
Log.i(EmulatorDebug.LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
||||||
if (mEmulator == null) return true;
|
if (mEmulator == null) return true;
|
||||||
|
|
||||||
if (mOnKeyListener.onKeyDown(keyCode, event, mTermSession)) {
|
if (mClient.onKeyDown(keyCode, event, mTermSession)) {
|
||||||
invalidate();
|
invalidate();
|
||||||
return true;
|
return true;
|
||||||
} else if (event.isSystem() && (!mOnKeyListener.shouldBackButtonBeMappedToEscape() || keyCode != KeyEvent.KEYCODE_BACK)) {
|
} else if (event.isSystem() && (!mClient.shouldBackButtonBeMappedToEscape() || keyCode != KeyEvent.KEYCODE_BACK)) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return super.onKeyDown(keyCode, event);
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_MULTIPLE && keyCode == KeyEvent.KEYCODE_UNKNOWN) {
|
} else if (event.getAction() == KeyEvent.ACTION_MULTIPLE && keyCode == KeyEvent.KEYCODE_UNKNOWN) {
|
||||||
mTermSession.write(event.getCharacters());
|
mTermSession.write(event.getCharacters());
|
||||||
@@ -641,10 +642,10 @@ public final class TerminalView extends View {
|
|||||||
+ leftAltDownFromEvent + ")");
|
+ leftAltDownFromEvent + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean controlDown = controlDownFromEvent || mOnKeyListener.readControlKey();
|
final boolean controlDown = controlDownFromEvent || mClient.readControlKey();
|
||||||
final boolean altDown = leftAltDownFromEvent || mOnKeyListener.readAltKey();
|
final boolean altDown = leftAltDownFromEvent || mClient.readAltKey();
|
||||||
|
|
||||||
if (mOnKeyListener.onCodePoint(codePoint, controlDown, mTermSession)) return;
|
if (mClient.onCodePoint(codePoint, controlDown, mTermSession)) return;
|
||||||
|
|
||||||
if (controlDown) {
|
if (controlDown) {
|
||||||
if (codePoint >= 'a' && codePoint <= 'z') {
|
if (codePoint >= 'a' && codePoint <= 'z') {
|
||||||
@@ -713,7 +714,7 @@ public final class TerminalView extends View {
|
|||||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
Log.i(EmulatorDebug.LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
||||||
if (mEmulator == null) return true;
|
if (mEmulator == null) return true;
|
||||||
|
|
||||||
if (mOnKeyListener.onKeyUp(keyCode, event)) {
|
if (mClient.onKeyUp(keyCode, event)) {
|
||||||
invalidate();
|
invalidate();
|
||||||
return true;
|
return true;
|
||||||
} else if (event.isSystem()) {
|
} else if (event.isSystem()) {
|
||||||
@@ -781,7 +782,7 @@ public final class TerminalView extends View {
|
|||||||
@TargetApi(23)
|
@TargetApi(23)
|
||||||
public void toggleSelectingText(MotionEvent ev) {
|
public void toggleSelectingText(MotionEvent ev) {
|
||||||
mIsSelectingText = !mIsSelectingText;
|
mIsSelectingText = !mIsSelectingText;
|
||||||
mOnKeyListener.copyModeChanged(mIsSelectingText);
|
mClient.copyModeChanged(mIsSelectingText);
|
||||||
|
|
||||||
if (mIsSelectingText) {
|
if (mIsSelectingText) {
|
||||||
if (mLeftSelectionHandle == null) {
|
if (mLeftSelectionHandle == null) {
|
||||||
@@ -8,16 +8,19 @@ import com.termux.terminal.TerminalSession;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Input and scale listener which may be set on a {@link TerminalView} through
|
* Input and scale listener which may be set on a {@link TerminalView} through
|
||||||
* {@link TerminalView#setOnKeyListener(TerminalKeyListener)}.
|
* {@link TerminalView#setOnKeyListener(TerminalViewClient)}.
|
||||||
* <p/>
|
* <p/>
|
||||||
* TODO: Rename to TerminalViewClient.
|
|
||||||
*/
|
*/
|
||||||
public interface TerminalKeyListener {
|
public interface TerminalViewClient {
|
||||||
|
|
||||||
/** Callback function on scale events according to {@link ScaleGestureDetector#getScaleFactor()}. */
|
/**
|
||||||
|
* Callback function on scale events according to {@link ScaleGestureDetector#getScaleFactor()}.
|
||||||
|
*/
|
||||||
float onScale(float scale);
|
float onScale(float scale);
|
||||||
|
|
||||||
/** On a single tap on the terminal if terminal mouse reporting not enabled. */
|
/**
|
||||||
|
* On a single tap on the terminal if terminal mouse reporting not enabled.
|
||||||
|
*/
|
||||||
void onSingleTapUp(MotionEvent e);
|
void onSingleTapUp(MotionEvent e);
|
||||||
|
|
||||||
boolean shouldBackButtonBeMappedToEscape();
|
boolean shouldBackButtonBeMappedToEscape();
|
||||||
@@ -34,4 +37,6 @@ public interface TerminalKeyListener {
|
|||||||
|
|
||||||
boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession session);
|
boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession session);
|
||||||
|
|
||||||
|
boolean onLongPress(MotionEvent event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
5
terminal-view/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="paste_text">Paste</string>
|
||||||
|
<string name="copy_text">Copy</string>
|
||||||
|
<string name="text_selection_more">More…</string>
|
||||||
|
</resources>
|
||||||