Compare commits

..

11 Commits
v0.95 ... v0.96

Author SHA1 Message Date
Leonid Pliushch
6f24628fd2 version 0.96 2020-07-30 23:56:27 +03:00
Leonid Pliushch
debbe44809 update bootstrap archives 2020-07-30 23:47:26 +03:00
Agnostic Apollo
b2ff0e4051 Changed static string "EXTRA_EXECUTE_IN_BACKGROUND" access to public 2020-07-30 21:39:41 +03:00
Agnostic Apollo
9e7029b76a Receive "RUN_COMMAND_ARGUMENTS" extra for "RUN_COMMAND_ACTION" intent
as a string array extra instead of a string extra since TermuxService expects it that way.

Added "RUN_COMMAND_BACKGROUND" boolean extra so that Termux session can be started in background
when running a command.

Updated usage docs.

Check #1029 for details.
2020-07-30 21:39:41 +03:00
Egor Zhdanov
51370799c7 update notification icon 2020-07-14 12:36:56 +03:00
Danny Lin
0910844896 Invert selected text instead of highlighting
Highlighting text in the terminal often makes it hard to read, which
can be problematic for users who want to adjust or review selections
before copying them. For example, the default theme makes white and
green text hard to read on its light gray selection background, and
there are plenty of other themes where the choice of text and cursor
colors would hinder selection readability.

To fix this issue and make selected text more legible in nearly all
combinations of colors, invert selected text instead of highlighting it.
This is more common among terminal emulators anyway:
    Invert:    xterm, fbcon, kitty, Konsole, Alacritty, Tilix,
               gnome-terminal (7)
    Highlight: Termux, Terminal.app, iTerm2, Windows Terminal (4)
2020-07-12 17:54:47 +03:00
Danny Lin
f33ebf810f Fix selection rendering with alternate cursor styles
There is currently a bug where selection rendering is broken if the
active cursor shape is anything other than the default solid box.
Selected text is normally highlighted by effectively rendering a cursor
over all of the characters in the selection region, but if the cursor is
a bar, the resulting selection highlight is too narrow to cover the full
width of the selection. Similarly, if the cursor is an underline, all of
the selected text will be underlined instead of highlighted.

To fix this issue, treat selections different from cursors in the
rendering logic and force the renderer to always use the block cursor
style for rendering selections. That way, we get correct behavior
regardless of what the current cursor shape is.
2020-07-04 15:31:45 +03:00
Felix C. Stegerman
930029b5d2 export COLORTERM=truecolor 2020-06-22 02:07:20 +03:00
Leonid Pliushch
33def928cf add DEX2OATBOOTCLASSPATH environment variable 2020-06-19 22:25:51 +03:00
Leonid Pliushch
fc04a93990 get rid of Android 5 legacy stuff
We don't need LD_LIBRARY_PATH as of Android 7.0.
2020-06-19 22:18:28 +03:00
Leonid Pliushch
8d302aa9fe fix am on Android R 2020-06-19 22:18:21 +03:00
6 changed files with 58 additions and 66 deletions

View File

@@ -17,8 +17,8 @@ android {
applicationId "com.termux"
minSdkVersion 24
targetSdkVersion 28
versionCode 95
versionName "0.95"
versionCode 96
versionName "0.96"
externalNativeBuild {
ndkBuild {
@@ -133,11 +133,11 @@ clean {
task downloadBootstraps(){
doLast {
def version = 25
downloadBootstrap("aarch64", "633baa1f7edfd81f6064338a68d1149aa203d4b24cbc4f7c64283aaca109609e", version)
downloadBootstrap("arm", "a581a22e0d79a0e8cef9395b1bd951ba066ac2d688522e17cca0b3e1c0649daa", version)
downloadBootstrap("i686", "8288e13f0a6ddeb2ff9406d8f968a8930a58e9318d09fadb2b7c8970a034cfdc", version)
downloadBootstrap("x86_64", "c99b80a18d6bbb64c24c5a64d6ee6b8d4306729ebd172662b807bcb4a46dd39a", version)
def version = 26
downloadBootstrap("aarch64", "c7830de73aa437933aef1957bdea29640afa34ca292fd7e27a6bdd1c9271bfe3", version)
downloadBootstrap("arm", "d6c250d853ef235da6f64ee946018cfaca1ca5a416d2ce0bdd82d97c35972bc5", version)
downloadBootstrap("i686", "d1b272e022a6bbee9d6bff024f1e42d26c58d0d3dfe64ca68846b94b40db352d", version)
downloadBootstrap("x86_64", "866793074541aa1ead0927affc8f1b5279a2cf9d683688a8379e6090754e077e", version)
}
}

View File

@@ -139,6 +139,7 @@ public final class BackgroundJob {
List<String> environment = new ArrayList<>();
environment.add("TERM=xterm-256color");
environment.add("COLORTERM=truecolor");
environment.add("HOME=" + TermuxService.HOME_PATH);
environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
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
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
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_TZDATA_ROOT");
if (failSafe) {
// Keep the default path so that system binaries can be used in the failsafe session.
environment.add("PATH= " + System.getenv("PATH"));
} else {
if (shouldAddLdLibraryPath()) {
environment.add("LD_LIBRARY_PATH=" + TermuxService.PREFIX_PATH + "/lib");
}
environment.add("LANG=en_US.UTF-8");
environment.add("PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets");
environment.add("PWD=" + cwd);
@@ -166,20 +169,6 @@ public final class BackgroundJob {
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) {
try {
Field f = p.getClass().getDeclaredField("pid");

View File

@@ -15,18 +15,32 @@ import java.nio.charset.StandardCharsets;
import java.util.Properties;
/**
* When allow-external-apps property is set to "true", Termux is able to process execute intents
* sent by third-party applications.
* When allow-external-apps property is set to "true" in ~/.termux/termux.properties, Termux
* 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
* 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.setClassName("com.termux", "com.termux.app.RunCommandService");
* 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_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);
*
* 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 {
@@ -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_ARGUMENTS = "com.termux.RUN_COMMAND_ARGUMENTS";
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 {
public final RunCommandService service = RunCommandService.this;
@@ -52,8 +67,9 @@ public class RunCommandService extends Service {
Intent execIntent = new Intent(TermuxService.ACTION_EXECUTE, programUri);
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_EXECUTE_IN_BACKGROUND, intent.getBooleanExtra(RUN_COMMAND_BACKGROUND, false));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(execIntent);

View File

@@ -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_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. */
class LocalBinder extends Binder {

View File

@@ -1,40 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
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. -->
<path
android:fillColor="#00000000"
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" />
<group>
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<!-- 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
android:pathData="M5,4H2L8,12L2,20H5L11,12L5,4Z"
android:fillColor="#ffffff"/>
<path
android:fillColor="#FFFFFF"
android:pathData="M56,66
h18
v4
h-18
"
/>
<path
android:pathData="M13,18H22V20H13V18Z"
android:fillColor="#ffffff"/>
</group>
</vector>

View File

@@ -86,6 +86,7 @@ public final class TerminalRenderer {
long lastRunStyle = 0;
boolean lastRunInsideCursor = false;
boolean lastRunInsideSelection = false;
int lastRunStartColumn = -1;
int lastRunStartIndex = 0;
boolean lastRunFontWidthMismatch = false;
@@ -98,7 +99,8 @@ public final class TerminalRenderer {
final int charsForCodePoint = charIsHighsurrogate ? 2 : 1;
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
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);
// 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);
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) {
// Skip first column as there is nothing to draw, just record the current style.
} else {
@@ -118,11 +120,12 @@ public final class TerminalRenderer {
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun,
lastRunStartIndex, charsSinceLastRun, measuredWidthForRun,
cursorColor, cursorShape, lastRunStyle, reverseVideo);
cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
}
measuredWidthForRun = 0.f;
lastRunStyle = style;
lastRunInsideCursor = insideCursor;
lastRunInsideSelection = insideSelection;
lastRunStartColumn = column;
lastRunStartIndex = currentCharIndex;
lastRunFontWidthMismatch = fontWidthMismatch;
@@ -141,7 +144,7 @@ public final class TerminalRenderer {
final int charsSinceLastRun = currentCharIndex - lastRunStartIndex;
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun,
measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo);
measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
}
}