From 31298b88575e12ea73e484cfd760ea3f030dcbd5 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Sat, 15 May 2021 16:35:54 +0500 Subject: [PATCH] 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 --- .../java/com/termux/app/TermuxActivity.java | 9 ++ .../terminal/TermuxTerminalSessionClient.java | 13 ++ .../terminal/TermuxTerminalViewClient.java | 12 ++ .../com/termux/terminal/TerminalEmulator.java | 47 ++++++-- .../terminal/TerminalSessionClient.java | 2 + .../java/com/termux/terminal/DecSetTest.java | 24 ++-- .../com/termux/view/TerminalRenderer.java | 2 +- .../java/com/termux/view/TerminalView.java | 113 +++++++++++++++++- .../properties/TermuxPropertyConstants.java | 15 ++- .../properties/TermuxSharedProperties.java | 35 ++++++ .../TermuxTerminalSessionClientBase.java | 6 + 11 files changed, 254 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/termux/app/TermuxActivity.java b/app/src/main/java/com/termux/app/TermuxActivity.java index 582d141588..766f941f45 100644 --- a/app/src/main/java/com/termux/app/TermuxActivity.java +++ b/app/src/main/java/com/termux/app/TermuxActivity.java @@ -257,6 +257,9 @@ public void onResume() { if (mIsInvalidState) return; mTermuxTerminalViewClient.setSoftKeyboardState(true, false); + + // Start terminal cursor blinking if enabled + mTermuxTerminalViewClient.setTerminalCursorBlinkerState(true); } /** @@ -330,6 +333,9 @@ protected void onStop() { // {@link #onStart} if needed. mTermuxTerminalSessionClient.setCurrentStoredSession(); + // Stop terminal cursor blinking if enabled + mTermuxTerminalViewClient.setTerminalCursorBlinkerState(false); + unregisterTermuxActivityBroadcastReceiever(); getDrawer().closeDrawers(); } @@ -799,6 +805,9 @@ private void reloadTermuxActivityStyling() { mTermuxTerminalViewClient.setSoftKeyboardState(false, true); + mTermuxTerminalViewClient.setTerminalCursorBlinkerState(true); + + // To change the activity and drawer theme, activity needs to be recreated. // But this will destroy the activity, and will call the onCreate() again. // We need to investigate if enabling this is wise, since all stored variables and diff --git a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java index 98003d0d7d..7d11689048 100644 --- a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java +++ b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java @@ -137,6 +137,19 @@ public void onColorsChanged(TerminalSession changedSession) { updateBackgroundColor(); } + @Override + public void onTerminalCursorStateChange(boolean enabled) { + // Do not start cursor blinking thread if activity is not visible + if (enabled && !mActivity.isVisible()) { + Logger.logVerbose(LOG_TAG, "Ignoring call to start cursor blinking since activity is not visible"); + return; + } + + // If cursor is to enabled now, then start cursor blinking if blinking is enabled + // otherwise stop cursor blinking + mActivity.getTerminalView().setTerminalCursorBlinkerState(enabled, false); + } + /** Try switching to session. */ diff --git a/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java b/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java index 7700cc6252..6c4be3855f 100644 --- a/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java +++ b/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java @@ -427,6 +427,18 @@ public void onFocusChange(View view, boolean hasFocus) { + public void setTerminalCursorBlinkerState(boolean start) { + if (start) { + // Set/Update the cursor blinking rate + mActivity.getTerminalView().setTerminalCursorBlinkerRate(mActivity.getProperties().getTerminalCursorBlinkRate()); + } + + // Set the new state of cursor blinker + mActivity.getTerminalView().setTerminalCursorBlinkerState(start, true); + } + + + public void shareSessionTranscript() { TerminalSession session = mActivity.getCurrentSession(); if (session == null) return; diff --git a/terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java b/terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java index 8f449dab2d..f5fb10e855 100644 --- a/terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java +++ b/terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java @@ -108,8 +108,8 @@ public final class TerminalEmulator { * characters received when the cursor is at the right border of the page replace characters already on the page." */ private static final int DECSET_BIT_AUTOWRAP = 1 << 3; - /** DECSET 25 - if the cursor should be visible, {@link #isShowingCursor()}. */ - private static final int DECSET_BIT_SHOWING_CURSOR = 1 << 4; + /** DECSET 25 - if the cursor should be enabled, {@link #isCursorEnabled()}. */ + private static final int DECSET_BIT_CURSOR_ENABLED = 1 << 4; private static final int DECSET_BIT_APPLICATION_KEYPAD = 1 << 5; /** DECSET 1000 - if to report mouse press&release events. */ private static final int DECSET_BIT_MOUSE_TRACKING_PRESS_RELEASE = 1 << 6; @@ -205,6 +205,18 @@ public final class TerminalEmulator { */ private boolean mAboutToAutoWrap; + /** + * If the cursor blinking is enabled. It requires cursor itself to be enabled, which is controlled + * byt whether {@link #DECSET_BIT_CURSOR_ENABLED} bit is set or not. + */ + private boolean mCursorBlinkingEnabled; + + /** + * If currently cursor should be in a visible state or not if {@link #mCursorBlinkingEnabled} + * is {@code true}. + */ + private boolean mCursorBlinkState; + /** * Current foreground and background colors. Can either be a color index in [0,259] or a truecolor (24-bit) value. * For a 24-bit value the top byte (0xff000000) is set. @@ -261,7 +273,7 @@ static int mapDecSetBitToInternalBit(int decsetBit) { case 7: return DECSET_BIT_AUTOWRAP; case 25: - return DECSET_BIT_SHOWING_CURSOR; + return DECSET_BIT_CURSOR_ENABLED; case 66: return DECSET_BIT_APPLICATION_KEYPAD; case 69: @@ -381,10 +393,28 @@ public boolean isReverseVideo() { return isDecsetInternalBitSet(DECSET_BIT_REVERSE_VIDEO); } - public boolean isShowingCursor() { - return isDecsetInternalBitSet(DECSET_BIT_SHOWING_CURSOR); + + + public boolean isCursorEnabled() { + return isDecsetInternalBitSet(DECSET_BIT_CURSOR_ENABLED); + } + public boolean shouldCursorBeVisible() { + if (!isCursorEnabled()) + return false; + else + return mCursorBlinkingEnabled ? mCursorBlinkState : true; + } + + public void setCursorBlinkingEnabled(boolean cursorBlinkingEnabled) { + this.mCursorBlinkingEnabled = cursorBlinkingEnabled; + } + + public void setCursorBlinkState(boolean cursorBlinkState) { + this.mCursorBlinkState = cursorBlinkState; } + + public boolean isKeypadApplicationMode() { return isDecsetInternalBitSet(DECSET_BIT_APPLICATION_KEYPAD); } @@ -1054,7 +1084,10 @@ public void doDecSetOrReset(boolean setting, int externalBit) { case 8: // Auto-repeat Keys (DECARM). Do not implement. case 9: // X10 mouse reporting - outdated. Do not implement. case 12: // Control cursor blinking - ignore. - case 25: // Hide/show cursor - no action needed, renderer will check with isShowingCursor(). + case 25: // Hide/show cursor - no action needed, renderer will check with shouldCursorBeVisible(). + if (mClient != null) + mClient.onTerminalCursorStateChange(setting); + break; case 40: // Allow 80 => 132 Mode, ignore. case 45: // TODO: Reverse wrap-around. Implement??? case 66: // Application keypad (DECNKM). @@ -2318,7 +2351,7 @@ public void reset() { mCurrentDecSetFlags = 0; // Initial wrap-around is not accurate but makes terminal more useful, especially on a small screen: setDecsetinternalBit(DECSET_BIT_AUTOWRAP, true); - setDecsetinternalBit(DECSET_BIT_SHOWING_CURSOR, true); + setDecsetinternalBit(DECSET_BIT_CURSOR_ENABLED, true); mSavedDecSetFlags = mSavedStateMain.mSavedDecFlags = mSavedStateAlt.mSavedDecFlags = mCurrentDecSetFlags; // XXX: Should we set terminal driver back to IUTF8 with termios? diff --git a/terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java b/terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java index c275ca82d3..9c99803023 100644 --- a/terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java +++ b/terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java @@ -19,6 +19,8 @@ public interface TerminalSessionClient { void onColorsChanged(TerminalSession session); + void onTerminalCursorStateChange(boolean state); + void logError(String tag, String message); diff --git a/terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java b/terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java index 9d4b5e26bf..f31f1fb833 100644 --- a/terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java +++ b/terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java @@ -16,23 +16,23 @@ public class DecSetTest extends TerminalTestCase { /** DECSET 25, DECTCEM, controls visibility of the cursor. */ - public void testShowHideCursor() { + public void testEnableDisableCursor() { withTerminalSized(3, 3); - assertTrue("Initially the cursor should be visible", mTerminal.isShowingCursor()); - enterString("\033[?25l"); // Hide Cursor (DECTCEM). - assertFalse(mTerminal.isShowingCursor()); - enterString("\033[?25h"); // Show Cursor (DECTCEM). - assertTrue(mTerminal.isShowingCursor()); + assertTrue("Initially the cursor should be enabled", mTerminal.isCursorEnabled()); + enterString("\033[?25l"); // Disable Cursor (DECTCEM). + assertFalse(mTerminal.isCursorEnabled()); + enterString("\033[?25h"); // Enable Cursor (DECTCEM). + assertTrue(mTerminal.isCursorEnabled()); - enterString("\033[?25l"); // Hide Cursor (DECTCEM), again. - assertFalse(mTerminal.isShowingCursor()); + enterString("\033[?25l"); // Disable Cursor (DECTCEM), again. + assertFalse(mTerminal.isCursorEnabled()); mTerminal.reset(); - assertTrue("Resetting the terminal should show the cursor", mTerminal.isShowingCursor()); + assertTrue("Resetting the terminal should enable the cursor", mTerminal.isCursorEnabled()); enterString("\033[?25l"); - assertFalse(mTerminal.isShowingCursor()); - enterString("\033c"); // RIS resetting should reveal cursor. - assertTrue(mTerminal.isShowingCursor()); + assertFalse(mTerminal.isCursorEnabled()); + enterString("\033c"); // RIS resetting should enabled cursor. + assertTrue(mTerminal.isCursorEnabled()); } /** DECSET 2004, controls bracketed paste mode. */ diff --git a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java index 5c9caf1c6d..6189dd6712 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java @@ -61,7 +61,7 @@ public final void render(TerminalEmulator mEmulator, Canvas canvas, int topRow, 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(); diff --git a/terminal-view/src/main/java/com/termux/view/TerminalView.java b/terminal-view/src/main/java/com/termux/view/TerminalView.java index 3a0f005261..0e5ef38e24 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalView.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalView.java @@ -8,6 +8,8 @@ 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 void onLongPress(MotionEvent event) { 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 void setTerminalViewClient(TerminalViewClient client) { } /** - * 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 void setIsTerminalViewKeyLoggingEnabled(boolean value) { TERMINAL_VIEW_KEY_LOGGING_ENABLED = value; } + + /** * Attach a {@link TerminalSession} to this view. * @@ -755,7 +769,10 @@ protected void onDraw(Canvas canvas) { 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 void setTopRow(int mTopRow) { - /** * Define functions required for AutoFill API */ @@ -825,6 +841,98 @@ public AutofillValue getAutofillValue() { + /** + * 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 @@ protected void onDetachedFromWindow() { - /** * Define functions required for long hold toolbar. */ diff --git a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java index bedc27f3c9..c84a0f38c0 100644 --- a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxPropertyConstants.java @@ -10,7 +10,7 @@ import java.util.Set; /* - * Version: v0.8.0 + * Version: v0.9.0 * * Changelog * @@ -41,6 +41,10 @@ * - Change the `KEY_USE_BACK_KEY_AS_ESCAPE_KEY` and `KEY_VIRTUAL_VOLUME_KEYS_DISABLED` booleans * to `KEY_BACK_KEY_BEHAVIOUR` and `KEY_VOLUME_KEYS_BEHAVIOUR` String internal values. * - Renamed `SOFT_KEYBOARD_TOGGLE_BEHAVIOUR` to `KEY_SOFT_KEYBOARD_TOGGLE_BEHAVIOUR`. + * + * - 0.9.0 (2021-05-14) + * - Add `*KEY_TERMINAL_CURSOR_BLINK_RATE*`. + * */ /** @@ -115,6 +119,14 @@ public final class TermuxPropertyConstants { + /** Defines the key for the terminal cursor blink rate */ + public static final String KEY_TERMINAL_CURSOR_BLINK_RATE = "terminal-cursor-blink-rate"; // Default: "terminal-cursor-blink-rate" + public static final int IVALUE_TERMINAL_CURSOR_BLINK_RATE_MIN = 100; + public static final int IVALUE_TERMINAL_CURSOR_BLINK_RATE_MAX = 2000; + public static final int DEFAULT_IVALUE_TERMINAL_CURSOR_BLINK_RATE = 0; + + + /* float */ @@ -221,6 +233,7 @@ public final class TermuxPropertyConstants { /* int */ KEY_BELL_BEHAVIOUR, + KEY_TERMINAL_CURSOR_BLINK_RATE, /* float */ KEY_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR, diff --git a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxSharedProperties.java b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxSharedProperties.java index 4d294d108d..68acf87278 100644 --- a/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxSharedProperties.java +++ b/termux-shared/src/main/java/com/termux/shared/settings/properties/TermuxSharedProperties.java @@ -188,6 +188,8 @@ public static Object getInternalTermuxPropertyValueFromValue(Context context, St /* int */ case TermuxPropertyConstants.KEY_BELL_BEHAVIOUR: return (int) getBellBehaviourInternalPropertyValueFromValue(value); + case TermuxPropertyConstants.KEY_TERMINAL_CURSOR_BLINK_RATE: + return (int) getTerminalCursorBlinkRateInternalPropertyValueFromValue(value); /* float */ case TermuxPropertyConstants.KEY_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR: @@ -257,6 +259,35 @@ public static int getBellBehaviourInternalPropertyValueFromValue(String value) { return SharedProperties.getDefaultIfNull(TermuxPropertyConstants.MAP_BELL_BEHAVIOUR.get(SharedProperties.toLowerCase(value)), TermuxPropertyConstants.DEFAULT_IVALUE_BELL_BEHAVIOUR); } + /** + * Returns the int for the value if its not null and is between + * {@code TermuxPropertyConstants#IVALUE_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR_MIN} and + * {@code TermuxPropertyConstants#IVALUE_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR_MAX}, + * otherwise returns {@code TermuxPropertyConstants#DEFAULT_IVALUE_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR}. + * + * @param value The {@link String} value to convert. + * @return Returns the internal value for value. + */ + public static float getTerminalCursorBlinkRateInternalPropertyValueFromValue(String value) { + return rangeTerminalCursorBlinkRateValue(DataUtils.getIntFromString(value, TermuxPropertyConstants.DEFAULT_IVALUE_TERMINAL_CURSOR_BLINK_RATE)); + } + + /** + * Returns the value itself if it is between + * {@code TermuxPropertyConstants#IVALUE_TERMINAL_CURSOR_BLINK_RATE_MIN} and + * {@code TermuxPropertyConstants#IVALUE_TERMINAL_CURSOR_BLINK_RATE_MAX}, + * otherwise returns {@code TermuxPropertyConstants#DEFAULT_IVALUE_TERMINAL_CURSOR_BLINK_RATE}. + * + * @param value The value to clamp. + * @return Returns the clamped value. + */ + public static int rangeTerminalCursorBlinkRateValue(int value) { + return (int) DataUtils.rangedOrDefault(value, + TermuxPropertyConstants.DEFAULT_IVALUE_TERMINAL_CURSOR_BLINK_RATE, + TermuxPropertyConstants.IVALUE_TERMINAL_CURSOR_BLINK_RATE_MIN, + TermuxPropertyConstants.IVALUE_TERMINAL_CURSOR_BLINK_RATE_MAX); + } + /** * Returns the int for the value if its not null and is between * {@code TermuxPropertyConstants#IVALUE_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR_MIN} and @@ -418,6 +449,10 @@ public int getBellBehaviour() { return (int) getInternalPropertyValue(TermuxPropertyConstants.KEY_BELL_BEHAVIOUR, true); } + public int getTerminalCursorBlinkRate() { + return rangeTerminalCursorBlinkRateValue((int) getInternalPropertyValue(TermuxPropertyConstants.KEY_TERMINAL_CURSOR_BLINK_RATE, true)); + } + public float getTerminalToolbarHeightScaleFactor() { return rangeTerminalToolbarHeightScaleFactorValue((float) getInternalPropertyValue(TermuxPropertyConstants.KEY_TERMINAL_TOOLBAR_HEIGHT_SCALE_FACTOR, true)); } diff --git a/termux-shared/src/main/java/com/termux/shared/terminal/TermuxTerminalSessionClientBase.java b/termux-shared/src/main/java/com/termux/shared/terminal/TermuxTerminalSessionClientBase.java index 1f77eaa188..6261972b8a 100644 --- a/termux-shared/src/main/java/com/termux/shared/terminal/TermuxTerminalSessionClientBase.java +++ b/termux-shared/src/main/java/com/termux/shared/terminal/TermuxTerminalSessionClientBase.java @@ -33,6 +33,12 @@ public void onBell(TerminalSession session) { public void onColorsChanged(TerminalSession changedSession) { } + @Override + public void onTerminalCursorStateChange(boolean state) { + } + + + @Override public void logError(String tag, String message) { Logger.logError(tag, message);