Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f24628fd2 | ||
|
|
debbe44809 | ||
|
|
b2ff0e4051 | ||
|
|
9e7029b76a | ||
|
|
51370799c7 | ||
|
|
0910844896 | ||
|
|
f33ebf810f | ||
|
|
930029b5d2 | ||
|
|
33def928cf | ||
|
|
fc04a93990 | ||
|
|
8d302aa9fe |
@@ -17,8 +17,8 @@ android {
|
|||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 95
|
versionCode 96
|
||||||
versionName "0.95"
|
versionName "0.96"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
ndkBuild {
|
ndkBuild {
|
||||||
@@ -133,11 +133,11 @@ clean {
|
|||||||
|
|
||||||
task downloadBootstraps(){
|
task downloadBootstraps(){
|
||||||
doLast {
|
doLast {
|
||||||
def version = 25
|
def version = 26
|
||||||
downloadBootstrap("aarch64", "633baa1f7edfd81f6064338a68d1149aa203d4b24cbc4f7c64283aaca109609e", version)
|
downloadBootstrap("aarch64", "c7830de73aa437933aef1957bdea29640afa34ca292fd7e27a6bdd1c9271bfe3", version)
|
||||||
downloadBootstrap("arm", "a581a22e0d79a0e8cef9395b1bd951ba066ac2d688522e17cca0b3e1c0649daa", version)
|
downloadBootstrap("arm", "d6c250d853ef235da6f64ee946018cfaca1ca5a416d2ce0bdd82d97c35972bc5", version)
|
||||||
downloadBootstrap("i686", "8288e13f0a6ddeb2ff9406d8f968a8930a58e9318d09fadb2b7c8970a034cfdc", version)
|
downloadBootstrap("i686", "d1b272e022a6bbee9d6bff024f1e42d26c58d0d3dfe64ca68846b94b40db352d", version)
|
||||||
downloadBootstrap("x86_64", "c99b80a18d6bbb64c24c5a64d6ee6b8d4306729ebd172662b807bcb4a46dd39a", version)
|
downloadBootstrap("x86_64", "866793074541aa1ead0927affc8f1b5279a2cf9d683688a8379e6090754e077e", version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ public final class BackgroundJob {
|
|||||||
List<String> environment = new ArrayList<>();
|
List<String> environment = new ArrayList<>();
|
||||||
|
|
||||||
environment.add("TERM=xterm-256color");
|
environment.add("TERM=xterm-256color");
|
||||||
|
environment.add("COLORTERM=truecolor");
|
||||||
environment.add("HOME=" + TermuxService.HOME_PATH);
|
environment.add("HOME=" + TermuxService.HOME_PATH);
|
||||||
environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
|
environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
|
||||||
environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH"));
|
environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH"));
|
||||||
@@ -147,16 +148,18 @@ public final class BackgroundJob {
|
|||||||
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
||||||
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
||||||
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
||||||
// ANDROID_RUNTIME_ROOT and ANDROID_TZDATA_ROOT are required for `am` to run on Android Q
|
|
||||||
|
// These variables are needed if running on Android 10 and higher.
|
||||||
|
addToEnvIfPresent(environment, "ANDROID_ART_ROOT");
|
||||||
|
addToEnvIfPresent(environment, "DEX2OATBOOTCLASSPATH");
|
||||||
|
addToEnvIfPresent(environment, "ANDROID_I18N_ROOT");
|
||||||
addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT");
|
addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT");
|
||||||
addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT");
|
addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT");
|
||||||
|
|
||||||
if (failSafe) {
|
if (failSafe) {
|
||||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||||
environment.add("PATH= " + System.getenv("PATH"));
|
environment.add("PATH= " + System.getenv("PATH"));
|
||||||
} else {
|
} else {
|
||||||
if (shouldAddLdLibraryPath()) {
|
|
||||||
environment.add("LD_LIBRARY_PATH=" + TermuxService.PREFIX_PATH + "/lib");
|
|
||||||
}
|
|
||||||
environment.add("LANG=en_US.UTF-8");
|
environment.add("LANG=en_US.UTF-8");
|
||||||
environment.add("PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets");
|
environment.add("PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets");
|
||||||
environment.add("PWD=" + cwd);
|
environment.add("PWD=" + cwd);
|
||||||
@@ -166,20 +169,6 @@ public final class BackgroundJob {
|
|||||||
return environment.toArray(new String[0]);
|
return environment.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldAddLdLibraryPath() {
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(TermuxService.PREFIX_PATH + "/etc/apt/sources.list")))) {
|
|
||||||
String line;
|
|
||||||
while ((line = in.readLine()) != null) {
|
|
||||||
if (!line.startsWith("#") && line.contains("//termux.net stable")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(LOG_TAG, "Error trying to read sources.list", e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getPid(Process p) {
|
public static int getPid(Process p) {
|
||||||
try {
|
try {
|
||||||
Field f = p.getClass().getDeclaredField("pid");
|
Field f = p.getClass().getDeclaredField("pid");
|
||||||
|
|||||||
@@ -15,18 +15,32 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When allow-external-apps property is set to "true", Termux is able to process execute intents
|
* When allow-external-apps property is set to "true" in ~/.termux/termux.properties, Termux
|
||||||
* sent by third-party applications.
|
* is able to process execute intents sent by third-party applications.
|
||||||
*
|
*
|
||||||
* Third-party program must declare com.termux.permission.RUN_COMMAND permission and it should be
|
* Third-party program must declare com.termux.permission.RUN_COMMAND permission and it should be
|
||||||
* granted by user.
|
* granted by user.
|
||||||
|
* Full path of command or script must be given in "RUN_COMMAND_PATH" extra.
|
||||||
|
* The "RUN_COMMAND_ARGUMENTS", "RUN_COMMAND_WORKDIR" and "RUN_COMMAND_BACKGROUND" extras are
|
||||||
|
* optional. The background mode defaults to false.
|
||||||
*
|
*
|
||||||
* Sample code to run command "top":
|
* Sample code to run command "top" with java:
|
||||||
* Intent intent = new Intent();
|
* Intent intent = new Intent();
|
||||||
* intent.setClassName("com.termux", "com.termux.app.RunCommandService");
|
* intent.setClassName("com.termux", "com.termux.app.RunCommandService");
|
||||||
* intent.setAction("com.termux.RUN_COMMAND");
|
* intent.setAction("com.termux.RUN_COMMAND");
|
||||||
* intent.putExtra("com.termux.RUN_COMMAND_PATH", "/data/data/com.termux/files/usr/bin/top");
|
* intent.putExtra("com.termux.RUN_COMMAND_PATH", "/data/data/com.termux/files/usr/bin/top");
|
||||||
|
* intent.putExtra("com.termux.RUN_COMMAND_ARGUMENTS", new String[]{"-n", "5"});
|
||||||
|
* intent.putExtra("com.termux.RUN_COMMAND_WORKDIR", "/data/data/com.termux/files/home");
|
||||||
|
* intent.putExtra("com.termux.RUN_COMMAND_BACKGROUND", false);
|
||||||
* startService(intent);
|
* startService(intent);
|
||||||
|
*
|
||||||
|
* Sample code to run command "top" with "am startservice" command:
|
||||||
|
* am startservice --user 0 -n com.termux/com.termux.app.RunCommandService
|
||||||
|
* -a com.termux.RUN_COMMAND
|
||||||
|
* --es com.termux.RUN_COMMAND_PATH '/data/data/com.termux/files/usr/bin/top'
|
||||||
|
* --esa com.termux.RUN_COMMAND_ARGUMENTS '-n,5'
|
||||||
|
* --es com.termux.RUN_COMMAND_WORKDIR '/data/data/com.termux/files/home'
|
||||||
|
* --ez com.termux.RUN_COMMAND_BACKGROUND 'false'
|
||||||
*/
|
*/
|
||||||
public class RunCommandService extends Service {
|
public class RunCommandService extends Service {
|
||||||
|
|
||||||
@@ -34,6 +48,7 @@ public class RunCommandService extends Service {
|
|||||||
public static final String RUN_COMMAND_PATH = "com.termux.RUN_COMMAND_PATH";
|
public static final String RUN_COMMAND_PATH = "com.termux.RUN_COMMAND_PATH";
|
||||||
public static final String RUN_COMMAND_ARGUMENTS = "com.termux.RUN_COMMAND_ARGUMENTS";
|
public static final String RUN_COMMAND_ARGUMENTS = "com.termux.RUN_COMMAND_ARGUMENTS";
|
||||||
public static final String RUN_COMMAND_WORKDIR = "com.termux.RUN_COMMAND_WORKDIR";
|
public static final String RUN_COMMAND_WORKDIR = "com.termux.RUN_COMMAND_WORKDIR";
|
||||||
|
public static final String RUN_COMMAND_BACKGROUND = "com.termux.RUN_COMMAND_BACKGROUND";
|
||||||
|
|
||||||
class LocalBinder extends Binder {
|
class LocalBinder extends Binder {
|
||||||
public final RunCommandService service = RunCommandService.this;
|
public final RunCommandService service = RunCommandService.this;
|
||||||
@@ -52,8 +67,9 @@ public class RunCommandService extends Service {
|
|||||||
|
|
||||||
Intent execIntent = new Intent(TermuxService.ACTION_EXECUTE, programUri);
|
Intent execIntent = new Intent(TermuxService.ACTION_EXECUTE, programUri);
|
||||||
execIntent.setClass(this, TermuxService.class);
|
execIntent.setClass(this, TermuxService.class);
|
||||||
execIntent.putExtra(TermuxService.EXTRA_ARGUMENTS, intent.getStringExtra(RUN_COMMAND_ARGUMENTS));
|
execIntent.putExtra(TermuxService.EXTRA_ARGUMENTS, intent.getStringArrayExtra(RUN_COMMAND_ARGUMENTS));
|
||||||
execIntent.putExtra(TermuxService.EXTRA_CURRENT_WORKING_DIRECTORY, intent.getStringExtra(RUN_COMMAND_WORKDIR));
|
execIntent.putExtra(TermuxService.EXTRA_CURRENT_WORKING_DIRECTORY, intent.getStringExtra(RUN_COMMAND_WORKDIR));
|
||||||
|
execIntent.putExtra(TermuxService.EXTRA_EXECUTE_IN_BACKGROUND, intent.getBooleanExtra(RUN_COMMAND_BACKGROUND, false));
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
this.startForegroundService(execIntent);
|
this.startForegroundService(execIntent);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
public static final String EXTRA_ARGUMENTS = "com.termux.execute.arguments";
|
public static final String EXTRA_ARGUMENTS = "com.termux.execute.arguments";
|
||||||
|
|
||||||
public static final String EXTRA_CURRENT_WORKING_DIRECTORY = "com.termux.execute.cwd";
|
public static final String EXTRA_CURRENT_WORKING_DIRECTORY = "com.termux.execute.cwd";
|
||||||
private static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background";
|
public static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background";
|
||||||
|
|
||||||
/** This service is only bound from inside the same process and never uses IPC. */
|
/** This service is only bound from inside the same process and never uses IPC. */
|
||||||
class LocalBinder extends Binder {
|
class LocalBinder extends Binder {
|
||||||
|
|||||||
@@ -1,40 +1,24 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:height="108dp"
|
android:width="24dp"
|
||||||
android:width="108dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="24">
|
||||||
<!--
|
<!--
|
||||||
https://material.google.com/style/icons.html
|
Updated notification icon compliant with system icons guidelines
|
||||||
|
https://material.io/design/iconography/system-icons.html
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- A circle as the icon border. -->
|
<group>
|
||||||
<path
|
<clip-path
|
||||||
android:fillColor="#00000000"
|
android:pathData="M0,0h24v24h-24z"/>
|
||||||
android:strokeColor="#FFF"
|
|
||||||
android:strokeWidth="3"
|
|
||||||
android:pathData="M18,54
|
|
||||||
A36,36 0 1,1 90,54
|
|
||||||
A36,36 0 1,1 18,54 Z" />
|
|
||||||
|
|
||||||
<!-- Keep in sync with ic_foreground.xml: -->
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M34,38
|
|
||||||
h6
|
|
||||||
l12,16
|
|
||||||
l-12,16
|
|
||||||
h-6
|
|
||||||
l12,-16
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFF"
|
android:pathData="M5,4H2L8,12L2,20H5L11,12L5,4Z"
|
||||||
android:pathData="M56,66
|
android:fillColor="#ffffff"/>
|
||||||
h18
|
|
||||||
v4
|
|
||||||
h-18
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:pathData="M13,18H22V20H13V18Z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ public final class TerminalRenderer {
|
|||||||
|
|
||||||
long lastRunStyle = 0;
|
long lastRunStyle = 0;
|
||||||
boolean lastRunInsideCursor = false;
|
boolean lastRunInsideCursor = false;
|
||||||
|
boolean lastRunInsideSelection = false;
|
||||||
int lastRunStartColumn = -1;
|
int lastRunStartColumn = -1;
|
||||||
int lastRunStartIndex = 0;
|
int lastRunStartIndex = 0;
|
||||||
boolean lastRunFontWidthMismatch = false;
|
boolean lastRunFontWidthMismatch = false;
|
||||||
@@ -98,7 +99,8 @@ public final class TerminalRenderer {
|
|||||||
final int charsForCodePoint = charIsHighsurrogate ? 2 : 1;
|
final int charsForCodePoint = charIsHighsurrogate ? 2 : 1;
|
||||||
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
|
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
|
||||||
final int codePointWcWidth = WcWidth.width(codePoint);
|
final int codePointWcWidth = WcWidth.width(codePoint);
|
||||||
final boolean insideCursor = (column >= selx1 && column <= selx2) || (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1));
|
final boolean insideCursor = (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1));
|
||||||
|
final boolean insideSelection = column >= selx1 && column <= selx2;
|
||||||
final long style = lineObject.getStyle(column);
|
final long style = lineObject.getStyle(column);
|
||||||
|
|
||||||
// Check if the measured text width for this code point is not the same as that expected by wcwidth().
|
// Check if the measured text width for this code point is not the same as that expected by wcwidth().
|
||||||
@@ -109,7 +111,7 @@ public final class TerminalRenderer {
|
|||||||
currentCharIndex, charsForCodePoint);
|
currentCharIndex, charsForCodePoint);
|
||||||
final boolean fontWidthMismatch = Math.abs(measuredCodePointWidth / mFontWidth - codePointWcWidth) > 0.01;
|
final boolean fontWidthMismatch = Math.abs(measuredCodePointWidth / mFontWidth - codePointWcWidth) > 0.01;
|
||||||
|
|
||||||
if (style != lastRunStyle || insideCursor != lastRunInsideCursor || fontWidthMismatch || lastRunFontWidthMismatch) {
|
if (style != lastRunStyle || insideCursor != lastRunInsideCursor || insideSelection != lastRunInsideSelection || fontWidthMismatch || lastRunFontWidthMismatch) {
|
||||||
if (column == 0) {
|
if (column == 0) {
|
||||||
// Skip first column as there is nothing to draw, just record the current style.
|
// Skip first column as there is nothing to draw, just record the current style.
|
||||||
} else {
|
} else {
|
||||||
@@ -118,11 +120,12 @@ public final class TerminalRenderer {
|
|||||||
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
|
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
|
||||||
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun,
|
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun,
|
||||||
lastRunStartIndex, charsSinceLastRun, measuredWidthForRun,
|
lastRunStartIndex, charsSinceLastRun, measuredWidthForRun,
|
||||||
cursorColor, cursorShape, lastRunStyle, reverseVideo);
|
cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
|
||||||
}
|
}
|
||||||
measuredWidthForRun = 0.f;
|
measuredWidthForRun = 0.f;
|
||||||
lastRunStyle = style;
|
lastRunStyle = style;
|
||||||
lastRunInsideCursor = insideCursor;
|
lastRunInsideCursor = insideCursor;
|
||||||
|
lastRunInsideSelection = insideSelection;
|
||||||
lastRunStartColumn = column;
|
lastRunStartColumn = column;
|
||||||
lastRunStartIndex = currentCharIndex;
|
lastRunStartIndex = currentCharIndex;
|
||||||
lastRunFontWidthMismatch = fontWidthMismatch;
|
lastRunFontWidthMismatch = fontWidthMismatch;
|
||||||
@@ -141,7 +144,7 @@ public final class TerminalRenderer {
|
|||||||
final int charsSinceLastRun = currentCharIndex - lastRunStartIndex;
|
final int charsSinceLastRun = currentCharIndex - lastRunStartIndex;
|
||||||
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
|
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
|
||||||
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun,
|
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun,
|
||||||
measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo);
|
measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user