mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 02:35:19 +08:00
Allow users to enable terminal cursor blinking with termux.properties
This `terminal-cursor-blink-rate` key can be used to enable terminal cursor blinking. The user can set an int value between `100` and `2000` which will be used as blink rate in millisecond. The default value is `0`, which disables cursor blinking. So adding an entry like `terminal-cursor-blink-rate=600` to `~/termux.properties` file will make the cursor attempt to blink every 600ms. Running `termux-reload-settings` command will also update the cursor blinking rate instantaneously if changed. A background thread is used to control the blinking by toggling the cursor visibility and then invalidating the view every x milliseconds set. This will have a performance impact, so use wisely and at your own risk. If the cursor itself is disabled, which is controlled by whether DECSET_BIT_CURSOR_ENABLED (DECSET 25, DECTCEM), then blinking will be automatically disabled. You can enable the cursor with `tput cnorm` or `echo -e '\e[?25h'` and disable it with `tput civis` or `echo -e '\e[?25l'`. Note that you can also change the cursor color by adding `cursor` property to `~/colors.properties` file, like `cursor=#FFFFFF` for a white cursor. The `TermuxPropertyConstants` class has been updated to `v0.9.0`. Check its Changelog sections for info on changes. Closes #153
This commit is contained in:
@@ -61,7 +61,7 @@ public final class TerminalRenderer {
|
||||
final int columns = mEmulator.mColumns;
|
||||
final int cursorCol = mEmulator.getCursorCol();
|
||||
final int cursorRow = mEmulator.getCursorRow();
|
||||
final boolean cursorVisible = mEmulator.isShowingCursor();
|
||||
final boolean cursorVisible = mEmulator.shouldCursorBeVisible();
|
||||
final TerminalBuffer screen = mEmulator.getScreen();
|
||||
final int[] palette = mEmulator.mColors.mCurrentColors;
|
||||
final int cursorShape = mEmulator.getCursorStyle();
|
||||
|
@@ -8,6 +8,8 @@ import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
@@ -52,6 +54,14 @@ public final class TerminalView extends View {
|
||||
|
||||
private TextSelectionCursorController mTextSelectionCursorController;
|
||||
|
||||
private Handler mTerminalCursorBlinkerHandler;
|
||||
private TerminalCursorBlinkerThread mTerminalCursorBlinkerThread;
|
||||
private int mTerminalCursorBlinkerRate;
|
||||
public static final int TERMINAL_CURSOR_BLINK_RATE_MIN = 100;
|
||||
public static final int TERMINAL_CURSOR_BLINK_RATE_MAX = 2000;
|
||||
|
||||
private boolean mRendering;
|
||||
|
||||
/** The top row of text to display. Ranges from -activeTranscriptRows to 0. */
|
||||
int mTopRow;
|
||||
int[] mDefaultSelectors = new int[]{-1,-1,-1,-1};
|
||||
@@ -209,6 +219,8 @@ public final class TerminalView extends View {
|
||||
mAccessibilityEnabled = am.isEnabled();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param client The {@link TerminalViewClient} interface implementation to allow
|
||||
* for communication between {@link TerminalView} and its client.
|
||||
@@ -218,7 +230,7 @@ public final class TerminalView extends View {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets terminal view key logging is enabled or not.
|
||||
* Sets whether terminal view key logging is enabled or not.
|
||||
*
|
||||
* @param value The boolean value that defines the state.
|
||||
*/
|
||||
@@ -226,6 +238,8 @@ public final class TerminalView extends View {
|
||||
TERMINAL_VIEW_KEY_LOGGING_ENABLED = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Attach a {@link TerminalSession} to this view.
|
||||
*
|
||||
@@ -755,7 +769,10 @@ public final class TerminalView extends View {
|
||||
if (mTextSelectionCursorController != null) {
|
||||
mTextSelectionCursorController.getSelectors(sel);
|
||||
}
|
||||
|
||||
mRendering = true;
|
||||
mRenderer.render(mEmulator, canvas, mTopRow, sel[0], sel[1], sel[2], sel[3]);
|
||||
mRendering = false;
|
||||
|
||||
// render the text selection handles
|
||||
renderTextSelection();
|
||||
@@ -799,7 +816,6 @@ public final class TerminalView extends View {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Define functions required for AutoFill API
|
||||
*/
|
||||
@@ -825,6 +841,98 @@ public final class TerminalView extends View {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set terminal cursor blinker rate. It must be between {@link #TERMINAL_CURSOR_BLINK_RATE_MIN}
|
||||
* and {@link #TERMINAL_CURSOR_BLINK_RATE_MAX}.
|
||||
*
|
||||
* @param blinkRate The value to set.
|
||||
*/
|
||||
public void setTerminalCursorBlinkerRate(int blinkRate) {
|
||||
mTerminalCursorBlinkerRate = blinkRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether cursor blinking should be started or stopped. Cursor blinking will only be
|
||||
* started if {@link #mTerminalCursorBlinkerRate} does not equal 0 and is between
|
||||
* {@link #TERMINAL_CURSOR_BLINK_RATE_MIN} and {@link #TERMINAL_CURSOR_BLINK_RATE_MAX}.
|
||||
*
|
||||
* @param start If cursor blinking should be started or stopped.
|
||||
* @param startOnlyIfCursorEnabled If set to {@code true}, then it will also be checked if the
|
||||
* cursor is even enabled by {@link TerminalEmulator} before
|
||||
* starting the cursor blinking thread.
|
||||
*/
|
||||
public synchronized void setTerminalCursorBlinkerState(boolean start, boolean startOnlyIfCursorEnabled) {
|
||||
// Stop any existing cursor blinker threads
|
||||
stopTerminalCursorBlinkerThread();
|
||||
|
||||
if (mEmulator == null) return;
|
||||
|
||||
mEmulator.setCursorBlinkingEnabled(false);
|
||||
|
||||
if (start) {
|
||||
// If cursor blinking is not enabled
|
||||
if (mTerminalCursorBlinkerRate == 0) {
|
||||
mClient.logVerbose(LOG_TAG, "Cursor blinking is not enabled");
|
||||
return;
|
||||
}
|
||||
// If cursor blinking rate is not valid
|
||||
else if (mTerminalCursorBlinkerRate < TERMINAL_CURSOR_BLINK_RATE_MIN || mTerminalCursorBlinkerRate > TERMINAL_CURSOR_BLINK_RATE_MAX) {
|
||||
mClient.logError(LOG_TAG, "startCursorBlinkerThread: The cursor blink rate must be in between " + TERMINAL_CURSOR_BLINK_RATE_MIN + "-" + TERMINAL_CURSOR_BLINK_RATE_MAX + ": " + mTerminalCursorBlinkerRate);
|
||||
return;
|
||||
}
|
||||
// If cursor is not enabled
|
||||
else if (startOnlyIfCursorEnabled && ! mEmulator.isCursorEnabled()) {
|
||||
mClient.logVerbose(LOG_TAG, "Ignoring call to start cursor blinking since cursor is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// Start cursor blinker thread
|
||||
mClient.logVerbose(LOG_TAG, "Starting cursor blinker thread with the blink rate: " + mTerminalCursorBlinkerRate);
|
||||
if (mTerminalCursorBlinkerHandler == null) mTerminalCursorBlinkerHandler = new Handler(Looper.getMainLooper());
|
||||
mTerminalCursorBlinkerThread = new TerminalCursorBlinkerThread(mTerminalCursorBlinkerRate);
|
||||
mEmulator.setCursorBlinkingEnabled(true);
|
||||
mTerminalCursorBlinkerThread.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the terminal cursor blinker thread
|
||||
*/
|
||||
private void stopTerminalCursorBlinkerThread() {
|
||||
if (mTerminalCursorBlinkerHandler != null && mTerminalCursorBlinkerThread != null) {
|
||||
mClient.logVerbose(LOG_TAG, "Stopping cursor blinker thread");
|
||||
mTerminalCursorBlinkerHandler.removeCallbacks(mTerminalCursorBlinkerThread);
|
||||
}
|
||||
}
|
||||
|
||||
private class TerminalCursorBlinkerThread implements Runnable {
|
||||
int mBlinkRate;
|
||||
boolean mCursorVisible;
|
||||
|
||||
public TerminalCursorBlinkerThread(int blinkRate) {
|
||||
mBlinkRate = blinkRate;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
if (mEmulator != null) {
|
||||
mCursorVisible = !mCursorVisible;
|
||||
// Toggle the blink state and then invalidate() the view so
|
||||
// that onDraw() is called, which then calls TerminalRenderer.render()
|
||||
// which checks with TerminalEmulator.shouldCursorBeVisible() to decide whether
|
||||
// to draw the cursor or not
|
||||
mEmulator.setCursorBlinkState(mCursorVisible);
|
||||
if (!mRendering)
|
||||
invalidate();
|
||||
}
|
||||
} finally {
|
||||
// Recall the Runnable after mBlinkRate milliseconds to toggle the blink state
|
||||
mTerminalCursorBlinkerHandler.postDelayed(mTerminalCursorBlinkerThread, mBlinkRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Define functions required for text selection and its handles.
|
||||
@@ -920,7 +1028,6 @@ public final class TerminalView extends View {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Define functions required for long hold toolbar.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user