Compare commits

...

10 Commits
v0.27 ... v0.29

Author SHA1 Message Date
Fredrik Fornwall
ce7ad530cd TermuxFilePickerProvider: Small improvements
1. Return true from onCreate().
2. Implement getType().
2016-02-14 00:49:27 +01:00
Fredrik Fornwall
d0015cbe82 Bump version to 0.29 2016-02-14 00:45:53 +01:00
Fredrik Fornwall
9e19217f8f Force refresh when returning in onStart()
This makes sure that terminal session changes that has happened
while away are visible when returning.
2016-02-14 00:44:33 +01:00
Fredrik Fornwall
048af64093 Map everything starting with x86 to i686
This fixes CPU detection for ARC welder which reports x86.
2016-02-14 00:42:34 +01:00
Fredrik Fornwall
a8f7bf1b6e Clarify how to find the Help menu entry 2016-02-13 22:01:18 +01:00
Fredrik Fornwall
62e229e184 Fix LOG_KEY_EVENTS=true committed by mistake 2016-02-13 00:27:58 +01:00
Fredrik Fornwall
36e4d94093 Add *.so to .gitignore 2016-02-09 11:33:57 +01:00
Fredrik Fornwall
d2c9c5a0f0 Bump version to 0.28 2016-02-09 11:25:58 +01:00
Fredrik Fornwall
6405180cb8 Wait for terminal size before starting process
This fixes https://github.com/termux/termux-widget/issues/2, which
was caused by the terminal launching the terminal session process
before the terminal size was known.

Also remove the built JNI libraries from source control.
2016-02-09 11:24:05 +01:00
Fredrik Fornwall
1b6919bb23 Add test comment 2016-01-28 16:45:45 +01:00
14 changed files with 72 additions and 22 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@
# Built application files # Built application files
build/ build/
*.apk *.apk
*.so
# Crashlytics configuations # Crashlytics configuations
com_crashlytics_export_strings.xml com_crashlytics_export_strings.xml

View File

@@ -20,7 +20,7 @@ Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). Conta
Building JNI libraries Building JNI libraries
====================== ======================
For ease of use, the JNI libraries are checked into version control. Execute the `build-jnilibs.sh` script to rebuild them. Execute the `build-jnilibs.sh` script to build the required JNI libraries.
Terminal resources Terminal resources
================== ==================

View File

@@ -18,8 +18,8 @@ android {
applicationId "com.termux" applicationId "com.termux"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 23 targetSdkVersion 23
versionCode 27 versionCode 29
versionName "0.27" versionName "0.29"
} }
buildTypes { buildTypes {

View File

@@ -525,6 +525,10 @@ public final class TermuxActivity extends Activity implements ServiceConnection
} }
registerReceiver(mBroadcastReceiever, new IntentFilter(RELOAD_STYLE_ACTION)); registerReceiver(mBroadcastReceiever, new IntentFilter(RELOAD_STYLE_ACTION));
// The current terminal session may have changed while being away, force
// a refresh of the displayed terminal:
mTerminalView.onScreenUpdated();
} }
@Override @Override

View File

@@ -182,7 +182,7 @@ final class TermuxInstaller {
if (arch.startsWith("arm") || arch.equals("aarch64")) { if (arch.startsWith("arm") || arch.equals("aarch64")) {
// Handle different arm variants such as armv7l: // Handle different arm variants such as armv7l:
arch = "arm"; arch = "arm";
} else if (arch.equals("x86_64")) { } else if (arch.startsWith("x86")) { // "x86" on arcwelder, "x86_64" on 64-bit android.
arch = "i686"; arch = "i686";
} }
return new URL("https://termux.net/bootstrap/bootstrap-" + arch + ".zip"); return new URL("https://termux.net/bootstrap/bootstrap-" + arch + ".zip");

View File

@@ -7,6 +7,7 @@ import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.webkit.MimeTypeMap;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@@ -15,7 +16,7 @@ import java.io.FileNotFoundException;
public class TermuxFilePickerProvider extends ContentProvider { public class TermuxFilePickerProvider extends ContentProvider {
@Override @Override
public boolean onCreate() { public boolean onCreate() {
return false; return true;
} }
@Override @Override
@@ -25,7 +26,20 @@ public class TermuxFilePickerProvider extends ContentProvider {
@Override @Override
public String getType(@NonNull Uri uri) { public String getType(@NonNull Uri uri) {
return null; String contentType = null;
String path = uri.getPath();
int lastDotIndex = path.lastIndexOf('.');
String possibleFileExtension = path.substring(lastDotIndex + 1, path.length());
if (possibleFileExtension.contains("/")) {
// The dot was in the path, so not a file extension.
} else {
MimeTypeMap mimeTypes = MimeTypeMap.getSingleton();
// Lower casing makes it work with e.g. "JPG":
contentType = mimeTypes.getMimeTypeFromExtension(possibleFileExtension.toLowerCase());
}
if (contentType == null) contentType = "application/octet-stream";
return contentType;
} }
@Override @Override

View File

@@ -28,7 +28,7 @@ final class JNI {
* @return the file descriptor resulting from opening /dev/ptmx master device. The sub process will have opened the * @return the file descriptor resulting from opening /dev/ptmx master device. The sub process will have opened the
* slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr. * slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr.
*/ */
public static native int createSubprocess(String cmd, String cwd, String[] args, String[] envVars, int[] processId); public static native int createSubprocess(String cmd, String cwd, String[] args, String[] envVars, int[] processId, int rows, int columns);
/** Set the window size for a given pty, which allows connected programs to learn how large their screen is. */ /** Set the window size for a given pty, which allows connected programs to learn how large their screen is. */
public static native void setPtyWindowSize(int fd, int rows, int cols); public static native void setPtyWindowSize(int fd, int rows, int cols);

View File

@@ -82,14 +82,17 @@ public final class TerminalSession extends TerminalOutput {
/** Callback which gets notified when a session finishes or changes title. */ /** Callback which gets notified when a session finishes or changes title. */
final SessionChangedCallback mChangeCallback; final SessionChangedCallback mChangeCallback;
/** The pid of the shell process or -1 if not running. */ /** The pid of the shell process. 0 if not started and -1 if finished running. */
int mShellPid; int mShellPid;
int mShellExitStatus = -1;
/** The exit status of the shell process. Only valid if ${@link #mShellPid} is -1. */
int mShellExitStatus;
/** /**
* The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling * The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling
* {@link JNI#createSubprocess(String, String, String[], String[], int[])}. * {@link JNI#createSubprocess(String, String, String[], String[], int[])}.
*/ */
final int mTerminalFileDescriptor; private int mTerminalFileDescriptor;
/** Set by the application for user identification of session, not by terminal. */ /** Set by the application for user identification of session, not by terminal. */
public String mSessionName; public String mSessionName;
@@ -128,20 +131,26 @@ public final class TerminalSession extends TerminalOutput {
} }
}; };
private final String mShellPath;
private final String mCwd;
private final String[] mArgs;
private final String[] mEnv;
public TerminalSession(String shellPath, String cwd, String[] args, String[] env, SessionChangedCallback changeCallback) { public TerminalSession(String shellPath, String cwd, String[] args, String[] env, SessionChangedCallback changeCallback) {
mChangeCallback = changeCallback; mChangeCallback = changeCallback;
int[] processId = new int[1]; this.mShellPath = shellPath;
mTerminalFileDescriptor = JNI.createSubprocess(shellPath, cwd, args, env, processId); this.mCwd = cwd;
mShellPid = processId[0]; this.mArgs = args;
this.mEnv = env;
} }
/** Inform the attached pty of the new size and reflow or initialize the emulator. */ /** Inform the attached pty of the new size and reflow or initialize the emulator. */
public void updateSize(int columns, int rows) { public void updateSize(int columns, int rows) {
JNI.setPtyWindowSize(mTerminalFileDescriptor, rows, columns);
if (mEmulator == null) { if (mEmulator == null) {
initializeEmulator(columns, rows); initializeEmulator(columns, rows);
} else { } else {
JNI.setPtyWindowSize(mTerminalFileDescriptor, rows, columns);
mEmulator.resize(columns, rows); mEmulator.resize(columns, rows);
} }
} }
@@ -161,6 +170,11 @@ public final class TerminalSession extends TerminalOutput {
*/ */
public void initializeEmulator(int columns, int rows) { public void initializeEmulator(int columns, int rows) {
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000); mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000);
int[] processId = new int[1];
mTerminalFileDescriptor = JNI.createSubprocess(mShellPath, mCwd, mArgs, mEnv, processId, rows, columns);
mShellPid = processId[0];
final FileDescriptor terminalFileDescriptorWrapped = wrapFileDescriptor(mTerminalFileDescriptor); final FileDescriptor terminalFileDescriptorWrapped = wrapFileDescriptor(mTerminalFileDescriptor);
new Thread("TermSessionInputReader[pid=" + mShellPid + "]") { new Thread("TermSessionInputReader[pid=" + mShellPid + "]") {
@@ -204,7 +218,7 @@ public final class TerminalSession extends TerminalOutput {
/** Write data to the shell process. */ /** Write data to the shell process. */
@Override @Override
public void write(byte[] data, int offset, int count) { public void write(byte[] data, int offset, int count) {
mTerminalToProcessIOQueue.write(data, offset, count); if (mShellPid > 0) mTerminalToProcessIOQueue.write(data, offset, count);
} }
/** Write the Unicode code point to the terminal encoded in UTF-8. */ /** Write the Unicode code point to the terminal encoded in UTF-8. */

View File

@@ -47,7 +47,7 @@ import java.util.Properties;
public final class TerminalView extends View { 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 = true; 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; TerminalSession mTermSession;

View File

@@ -22,7 +22,14 @@ static int throw_runtime_exception(JNIEnv* env, char const* message)
return -1; return -1;
} }
static int create_subprocess(JNIEnv* env, char const* cmd, char const* cwd, char* const argv[], char** envp, int* pProcessId) static int create_subprocess(JNIEnv* env,
char const* cmd,
char const* cwd,
char* const argv[],
char** envp,
int* pProcessId,
jint rows,
jint columns)
{ {
int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC); int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx"); if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx");
@@ -49,8 +56,8 @@ static int create_subprocess(JNIEnv* env, char const* cmd, char const* cwd, char
tios.c_iflag &= ~(IXON | IXOFF); tios.c_iflag &= ~(IXON | IXOFF);
tcsetattr(ptm, TCSANOW, &tios); tcsetattr(ptm, TCSANOW, &tios);
/** Set initial winsize (better too small than too large). */ /** Set initial winsize. */
struct winsize sz = { .ws_row = 20, .ws_col = 20 }; struct winsize sz = { .ws_row = rows, .ws_col = columns };
ioctl(ptm, TIOCSWINSZ, &sz); ioctl(ptm, TIOCSWINSZ, &sz);
pid_t pid = fork(); pid_t pid = fork();
@@ -105,7 +112,16 @@ static int create_subprocess(JNIEnv* env, char const* cmd, char const* cwd, char
} }
} }
JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(JNIEnv* env, jclass TERMUX_UNUSED(clazz), jstring cmd, jstring cwd, jobjectArray args, jobjectArray envVars, jintArray processIdArray) JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
JNIEnv* env,
jclass TERMUX_UNUSED(clazz),
jstring cmd,
jstring cwd,
jobjectArray args,
jobjectArray envVars,
jintArray processIdArray,
jint rows,
jint columns)
{ {
jsize size = args ? (*env)->GetArrayLength(env, args) : 0; jsize size = args ? (*env)->GetArrayLength(env, args) : 0;
char** argv = NULL; char** argv = NULL;
@@ -140,7 +156,7 @@ JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(JNIEnv* env
int procId = 0; int procId = 0;
char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL); char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL);
char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL); char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL);
int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId); int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns);
(*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8); (*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8);
(*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd); (*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd);

View File

@@ -12,7 +12,7 @@
<string name="help">Help</string> <string name="help">Help</string>
<string name="welcome_dialog_title">Welcome to Termux</string> <string name="welcome_dialog_title">Welcome to Termux</string>
<string name="welcome_dialog_body">Long press anywhere on the terminal for a context menu where Help is available.\n\nExecute \'apt update\' to update the packages list before installing packages.</string> <string name="welcome_dialog_body">Long press and select <i>More…</i> to show a menu where <i>Help</i> is available.\n\nExecute <b>apt update</b> to update the packages list before installing packages.</string>
<string name="welcome_dialog_dont_show_again_button">Do not show again</string> <string name="welcome_dialog_dont_show_again_button">Do not show again</string>
<string name="bootstrap_installer_body">Installing…</string> <string name="bootstrap_installer_body">Installing…</string>

View File

@@ -92,6 +92,7 @@ public class TerminalTest extends TerminalTestCase {
assertEnteringStringGivesResponse("\033[6n", "\033[2;1R"); assertEnteringStringGivesResponse("\033[6n", "\033[2;1R");
} }
/** Test the cursor shape changes using DECSCUSR. */
public void testSetCursorStyle() throws Exception { public void testSetCursorStyle() throws Exception {
withTerminalSized(5, 5); withTerminalSized(5, 5);
assertEquals(TerminalEmulator.CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle()); assertEquals(TerminalEmulator.CURSOR_STYLE_BLOCK, mTerminal.getCursorStyle());