mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 02:35:19 +08:00
Implement GUI based Termux settings manager and a centralized logging framework
The settings activity can be accessed by long pressing on terminal view and selecting "Settings" from the popup shown. It uses the Android's Preference framework. Currently only debugging preferences to set log level and enabling terminal view key logging are provided. The Preference framework by default uses the keys set in `app:key` attribute in the respective preferences XML file to store the values in the default `SharedPreferences` file of the app. However, since we rely on `TermuxPreferenceConstants` and `TermuxPropertyConstants` classes to define key names so that they can be easily shared between termux and its plugin apps, we provide our own `PreferenceDataStore` for storing key/value pairs. The key name in the XML file can optionally be the same. Check `DebuggingPreferencesFragment` class for a sample. Each new preference category fragment should be added to `app/settings/` with its data store. This commit may allow support to be added for modifying `termux.properties` file directly from the UI but that requires more work, since writing to property files with comments require in-place modification. The `Logger` class provides various static functions for logging that should be used from now on instead of directly calling android `Log.*` functions. The log level is automatically loaded from shared preferences at application startup via `TermuxApplication` and set in the static `Logger.CURRENT_LOG_LEVEL` variable. Changing the log level through the settings activity also changes the log level immediately. The 4 supported log levels are: - LOG_LEVEL_OFF which will log nothing. - LOG_LEVEL_NORMAL which will start logging error, warn and info messages and stacktraces. - LOG_LEVEL_DEBUG which will start logging debug messages. - LOG_LEVEL_VERBOSE which will start logging verbose messages. The default log level is `LOG_LEVEL_NORMAL` which will not log debug or verbose messages. Contributors can add useful log entries at those levels where ever they feel is appropriate so that it allows users and devs to more easily help solve issues or find bugs, specially without having to recompile termux after having to manually add general log entries to the source. DO NOT log data that may have private info of users like command arguments at log levels below debug, like `BackgroundJob` was doing previously. Logging to file support may be added later, will require log file rotation support and storage permissions.
This commit is contained in:
@@ -12,7 +12,6 @@ import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.InputDevice;
|
||||
@@ -31,7 +30,6 @@ import android.widget.Scroller;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.termux.terminal.EmulatorDebug;
|
||||
import com.termux.terminal.KeyHandler;
|
||||
import com.termux.terminal.TerminalEmulator;
|
||||
import com.termux.terminal.TerminalSession;
|
||||
@@ -40,8 +38,8 @@ import com.termux.view.textselection.TextSelectionCursorController;
|
||||
/** View displaying and interacting with a {@link TerminalSession}. */
|
||||
public final class TerminalView extends View {
|
||||
|
||||
/** Log view key and IME events. */
|
||||
private static final boolean LOG_KEY_EVENTS = false;
|
||||
/** Log terminal view key and IME events. */
|
||||
private static boolean TERMINAL_VIEW_KEY_LOGGING_ENABLED = false;
|
||||
|
||||
/** The currently displayed terminal session, whose emulator is {@link #mEmulator}. */
|
||||
public TerminalSession mTermSession;
|
||||
@@ -76,6 +74,8 @@ public final class TerminalView extends View {
|
||||
|
||||
private final boolean mAccessibilityEnabled;
|
||||
|
||||
private static final String LOG_TAG = "TerminalView";
|
||||
|
||||
public TerminalView(Context context, AttributeSet attributes) { // NO_UCD (unused code)
|
||||
super(context, attributes);
|
||||
mGestureRecognizer = new GestureAndScaleRecognizer(context, new GestureAndScaleRecognizer.Listener() {
|
||||
@@ -210,11 +210,23 @@ 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
|
||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||
* @param terminalViewClient Interface for communicating with the terminal view client. It allows
|
||||
* for getting various configuration options from the client and
|
||||
* for sending back data to the client like logs, key events, both
|
||||
* hardware and IME (which makes it different from that available with
|
||||
* {@link View#setOnKeyListener(OnKeyListener)}, etc.
|
||||
*/
|
||||
public void setOnKeyListener(TerminalViewClient onKeyListener) {
|
||||
this.mClient = onKeyListener;
|
||||
public void setTerminalViewClient(TerminalViewClient terminalViewClient) {
|
||||
this.mClient = terminalViewClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets terminal view key logging is enabled or not.
|
||||
*
|
||||
* @param value The boolean value that defines the state.
|
||||
*/
|
||||
public void setIsTerminalViewKeyLoggingEnabled(boolean value) {
|
||||
TERMINAL_VIEW_KEY_LOGGING_ENABLED = value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +276,7 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean finishComposingText() {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "IME: finishComposingText()");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED) mClient.logInfo(LOG_TAG, "IME: finishComposingText()");
|
||||
super.finishComposingText();
|
||||
|
||||
sendTextToTerminal(getEditable());
|
||||
@@ -274,8 +286,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||
if (LOG_KEY_EVENTS) {
|
||||
Log.i(EmulatorDebug.LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED) {
|
||||
mClient.logInfo(LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
||||
}
|
||||
super.commitText(text, newCursorPosition);
|
||||
|
||||
@@ -289,8 +301,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean deleteSurroundingText(int leftLength, int rightLength) {
|
||||
if (LOG_KEY_EVENTS) {
|
||||
Log.i(EmulatorDebug.LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED) {
|
||||
mClient.logInfo(LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
||||
}
|
||||
// The stock Samsung keyboard with 'Auto check spelling' enabled sends leftLength > 1.
|
||||
KeyEvent deleteKey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
|
||||
@@ -521,8 +533,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyPreIme(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED)
|
||||
mClient.logInfo(LOG_TAG, "onKeyPreIme(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (isSelectingText()) {
|
||||
stopTextSelectionMode();
|
||||
@@ -547,8 +559,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED)
|
||||
mClient.logInfo(LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
||||
if (mEmulator == null) return true;
|
||||
if (isSelectingText()) {
|
||||
stopTextSelectionMode();
|
||||
@@ -575,7 +587,7 @@ public final class TerminalView extends View {
|
||||
if (event.isShiftPressed()) keyMod |= KeyHandler.KEYMOD_SHIFT;
|
||||
if (event.isNumLockOn()) keyMod |= KeyHandler.KEYMOD_NUM_LOCK;
|
||||
if (!event.isFunctionPressed() && handleKeyCode(keyCode, keyMod)) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "handleKeyCode() took key event");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED) mClient.logInfo(LOG_TAG, "handleKeyCode() took key event");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -590,8 +602,8 @@ public final class TerminalView extends View {
|
||||
int effectiveMetaState = event.getMetaState() & ~bitsToClear;
|
||||
|
||||
int result = event.getUnicodeChar(effectiveMetaState);
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "KeyEvent#getUnicodeChar(" + effectiveMetaState + ") returned: " + result);
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED)
|
||||
mClient.logInfo(LOG_TAG, "KeyEvent#getUnicodeChar(" + effectiveMetaState + ") returned: " + result);
|
||||
if (result == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -617,8 +629,8 @@ public final class TerminalView extends View {
|
||||
}
|
||||
|
||||
public void inputCodePoint(int codePoint, boolean controlDownFromEvent, boolean leftAltDownFromEvent) {
|
||||
if (LOG_KEY_EVENTS) {
|
||||
Log.i(EmulatorDebug.LOG_TAG, "inputCodePoint(codePoint=" + codePoint + ", controlDownFromEvent=" + controlDownFromEvent + ", leftAltDownFromEvent="
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED) {
|
||||
mClient.logInfo(LOG_TAG, "inputCodePoint(codePoint=" + codePoint + ", controlDownFromEvent=" + controlDownFromEvent + ", leftAltDownFromEvent="
|
||||
+ leftAltDownFromEvent + ")");
|
||||
}
|
||||
|
||||
@@ -692,8 +704,8 @@ public final class TerminalView extends View {
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (TERMINAL_VIEW_KEY_LOGGING_ENABLED)
|
||||
mClient.logInfo(LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (mEmulator == null) return true;
|
||||
|
||||
if (mClient.onKeyUp(keyCode, event)) {
|
||||
|
@@ -8,7 +8,7 @@ import com.termux.terminal.TerminalSession;
|
||||
|
||||
/**
|
||||
* Input and scale listener which may be set on a {@link TerminalView} through
|
||||
* {@link TerminalView#setOnKeyListener(TerminalViewClient)}.
|
||||
* {@link TerminalView#setTerminalViewClient(TerminalViewClient)}.
|
||||
* <p/>
|
||||
*/
|
||||
public interface TerminalViewClient {
|
||||
@@ -18,6 +18,8 @@ public interface TerminalViewClient {
|
||||
*/
|
||||
float onScale(float scale);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* On a single tap on the terminal if terminal mouse reporting not enabled.
|
||||
*/
|
||||
@@ -29,18 +31,41 @@ public interface TerminalViewClient {
|
||||
|
||||
boolean shouldUseCtrlSpaceWorkaround();
|
||||
|
||||
|
||||
|
||||
void copyModeChanged(boolean copyMode);
|
||||
|
||||
|
||||
|
||||
boolean onKeyDown(int keyCode, KeyEvent e, TerminalSession session);
|
||||
|
||||
boolean onKeyUp(int keyCode, KeyEvent e);
|
||||
|
||||
boolean onLongPress(MotionEvent event);
|
||||
|
||||
|
||||
|
||||
boolean readControlKey();
|
||||
|
||||
boolean readAltKey();
|
||||
|
||||
|
||||
boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession session);
|
||||
|
||||
boolean onLongPress(MotionEvent event);
|
||||
|
||||
|
||||
void logError(String tag, String message);
|
||||
|
||||
void logWarn(String tag, String message);
|
||||
|
||||
void logInfo(String tag, String message);
|
||||
|
||||
void logDebug(String tag, String message);
|
||||
|
||||
void logVerbose(String tag, String message);
|
||||
|
||||
void logStackTraceWithMessage(String tag, String message, Exception e);
|
||||
|
||||
void logStackTrace(String tag, Exception e);
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user