diff --git a/app/src/main/java/com/termux/app/fragments/settings/TerminalIOPreferencesFragment.java b/app/src/main/java/com/termux/app/fragments/settings/TerminalIOPreferencesFragment.java
index ef0a56c2c8..d9500f841d 100644
--- a/app/src/main/java/com/termux/app/fragments/settings/TerminalIOPreferencesFragment.java
+++ b/app/src/main/java/com/termux/app/fragments/settings/TerminalIOPreferencesFragment.java
@@ -53,6 +53,9 @@ public void putBoolean(String key, boolean value) {
case "soft_keyboard_enabled":
mPreferences.setSoftKeyboardEnabled(value);
break;
+ case "soft_keyboard_enabled_only_if_no_hardware":
+ mPreferences.setSoftKeyboardEnabledOnlyIfNoHardware(value);
+ break;
default:
break;
}
@@ -63,6 +66,8 @@ public boolean getBoolean(String key, boolean defValue) {
switch (key) {
case "soft_keyboard_enabled":
return mPreferences.getSoftKeyboardEnabled();
+ case "soft_keyboard_enabled_only_if_no_hardware":
+ return mPreferences.getSoftKeyboardEnabledOnlyIfNoHardware();
default:
return false;
}
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 93e387d16f..18a0d39b03 100644
--- a/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java
+++ b/app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java
@@ -80,7 +80,7 @@ public void onSingleTapUp(MotionEvent e) {
if (!KeyboardUtils.areDisableSoftKeyboardFlagsSet(mActivity))
KeyboardUtils.showSoftKeyboard(mActivity, mActivity.getTerminalView());
else
- Logger.logVerbose(LOG_TAG, "Not showing keyboard onSingleTapUp since its disabled");
+ Logger.logVerbose(LOG_TAG, "Not showing soft keyboard onSingleTapUp since its disabled");
}
@Override
@@ -380,8 +380,10 @@ public void onToggleSoftKeyboardRequest() {
}
public void setSoftKeyboardState(boolean isStartup, boolean isReloadTermuxProperties) {
- // If soft keyboard is disabled by user for Termux
- if (!mActivity.getPreferences().getSoftKeyboardEnabled()) {
+ // If soft keyboard is disabled by user for Termux (check function docs for Termux behaviour info)
+ if (KeyboardUtils.shouldSoftKeyboardBeDisabled(mActivity,
+ mActivity.getPreferences().getSoftKeyboardEnabled(),
+ mActivity.getPreferences().getSoftKeyboardEnabledOnlyIfNoHardware())) {
Logger.logVerbose(LOG_TAG, "Maintaining disabled soft keyboard");
KeyboardUtils.disableSoftKeyboard(mActivity, mActivity.getTerminalView());
} else {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0cebd0b560..b12521886c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -151,8 +151,13 @@
Keyboard
- Soft Keyboard
+ Soft Keyboard Enabled
Soft keyboard will be disabled.
Soft keyboard will be enabled. (Default)
+
+ Soft Keyboard If No Hardware
+ Soft keyboard will be enabled even if hardware keyboard is connected. (Default)
+ Soft keyboard will be enabled only if no hardware keyboard is connected.
+
diff --git a/app/src/main/res/xml/terminal_io_preferences.xml b/app/src/main/res/xml/terminal_io_preferences.xml
index d20e7c58bf..6aecbf482c 100644
--- a/app/src/main/res/xml/terminal_io_preferences.xml
+++ b/app/src/main/res/xml/terminal_io_preferences.xml
@@ -10,6 +10,12 @@
app:summaryOn="@string/soft_keyboard_on"
app:title="@string/soft_keyboard_title" />
+
+
diff --git a/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxAppSharedPreferences.java b/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxAppSharedPreferences.java
index 086e50d75e..7c6656cdb3 100644
--- a/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxAppSharedPreferences.java
+++ b/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxAppSharedPreferences.java
@@ -62,6 +62,14 @@ public void setSoftKeyboardEnabled(boolean value) {
SharedPreferenceUtils.setBoolean(mSharedPreferences, TERMUX_APP.KEY_SOFT_KEYBOARD_ENABLED, value, false);
}
+ public boolean getSoftKeyboardEnabledOnlyIfNoHardware() {
+ return SharedPreferenceUtils.getBoolean(mSharedPreferences, TERMUX_APP.KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE, TERMUX_APP.DEFAULT_VALUE_KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE);
+ }
+
+ public void setSoftKeyboardEnabledOnlyIfNoHardware(boolean value) {
+ SharedPreferenceUtils.setBoolean(mSharedPreferences, TERMUX_APP.KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE, value, false);
+ }
+
public boolean getKeepScreenOn() {
diff --git a/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxPreferenceConstants.java b/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxPreferenceConstants.java
index 633b7c3441..efec9d9863 100644
--- a/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxPreferenceConstants.java
+++ b/termux-shared/src/main/java/com/termux/shared/settings/preferences/TermuxPreferenceConstants.java
@@ -1,7 +1,7 @@
package com.termux.shared.settings.preferences;
/*
- * Version: v0.9.0
+ * Version: v0.10.0
*
* Changelog
*
@@ -40,6 +40,10 @@
*
* - 0.9.0 (2021-04-07)
* - Updated javadocs.
+ *
+ * - 0.10.0 (2021-05-12)
+ * - Added following to `TERMUX_APP`:
+ * `KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE` and `DEFAULT_VALUE_KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE`.
*/
/**
@@ -70,6 +74,13 @@ public static final class TERMUX_APP {
public static final String KEY_SOFT_KEYBOARD_ENABLED = "soft_keyboard_enabled";
public static final boolean DEFAULT_VALUE_KEY_SOFT_KEYBOARD_ENABLED = true;
+ /**
+ * Defines the key for whether the soft keyboard will be enabled only if no hardware keyboard
+ * attached, for cases where users want to use a hardware keyboard instead.
+ */
+ public static final String KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE = "soft_keyboard_enabled_only_if_no_hardware";
+ public static final boolean DEFAULT_VALUE_KEY_SOFT_KEYBOARD_ENABLED_ONLY_IF_NO_HARDWARE = false;
+
/**
* Defines the key for whether to always keep screen on.
diff --git a/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java b/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java
index 3891086dec..a54b4fa9f9 100644
--- a/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java
+++ b/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java
@@ -2,6 +2,7 @@
import android.app.Activity;
import android.content.Context;
+import android.content.res.Configuration;
import android.inputmethodservice.InputMethodService;
import android.view.View;
import android.view.WindowInsets;
@@ -32,8 +33,8 @@ public static void setSoftKeyboardVisibility(@NonNull final Runnable showSoftKey
* Toggle the soft keyboard. The {@link InputMethodManager#SHOW_FORCED} is passed as
* {@code showFlags} so that keyboard is forcefully shown if it needs to be enabled.
*
- * This is also important for soft keyboard to be shown when a hardware keyboard is attached, and
- * user has disabled the {@code Show on-screen keyboard while hardware keyboard is attached} toggle
+ * This is also important for soft keyboard to be shown when a hardware keyboard is connected, and
+ * user has disabled the {@code Show on-screen keyboard while hardware keyboard is connected} toggle
* in Android "Language and Input" settings but the current soft keyboard app overrides the
* default implementation of {@link InputMethodService#onEvaluateInputViewShown()} and returns
* {@code true}.
@@ -50,8 +51,8 @@ public static void toggleSoftKeyboard(final Context context) {
* forcefully shown.
*
* This is also important for soft keyboard to be shown on app startup when a hardware keyboard
- * is attached, and user has disabled the {@code Show on-screen keyboard while hardware keyboard
- * is attached} toggle in Android "Language and Input" settings but the current soft keyboard app
+ * is connected, and user has disabled the {@code Show on-screen keyboard while hardware keyboard
+ * is connected} toggle in Android "Language and Input" settings but the current soft keyboard app
* overrides the default implementation of {@link InputMethodService#onEvaluateInputViewShown()}
* and returns {@code true}.
* https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:frameworks/base/core/java/android/inputmethodservice/InputMethodService.java;l=1751
@@ -110,21 +111,85 @@ public static void setResizeTerminalViewForSoftKeyboardFlags(final Activity acti
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
- /** Check if keyboard visible. Does not work on android 7 but does on android 11 avd. */
+ /**
+ * Check if soft keyboard is visible.
+ * Does not work on android 7 but does on android 11 avd.
+ *
+ * @param activity The Activity of the root view for which the visibility should be checked.
+ * @return Returns {@code true} if soft keyboard is visible, otherwise {@code false}.
+ */
public static boolean isSoftKeyboardVisible(final Activity activity) {
if (activity != null && activity.getWindow() != null) {
WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
if (insets != null) {
WindowInsetsCompat insetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets);
- if (insetsCompat != null && insetsCompat.isVisible(WindowInsetsCompat.Type.ime())) {
- Logger.logVerbose(LOG_TAG, "Keyboard visible");
+ if (insetsCompat.isVisible(WindowInsetsCompat.Type.ime())) {
+ Logger.logVerbose(LOG_TAG, "Soft keyboard visible");
return true;
}
}
}
- Logger.logVerbose(LOG_TAG, "Keyboard not visible");
+ Logger.logVerbose(LOG_TAG, "Soft keyboard not visible");
return false;
}
+ /**
+ * Check if hardware keyboard is connected.
+ * Based on default implementation of {@link InputMethodService#onEvaluateInputViewShown()}.
+ *
+ * https://developer.android.com/guide/topics/resources/providing-resources#ImeQualifier
+ *
+ * @param context The Context for operations.
+ * @return Returns {@code true} if device has hardware keys for text input or an external hardware
+ * keyboard is connected, otherwise {@code false}.
+ */
+ public static boolean isHardKeyboardConnected(final Context context) {
+ if (context == null) return false;
+
+ Configuration config = context.getResources().getConfiguration();
+ return config.keyboard != Configuration.KEYBOARD_NOKEYS
+ || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
+ }
+
+ /**
+ * Check if soft keyboard should be disabled based on user configuration.
+ *
+ * @param context The Context for operations.
+ * @return Returns {@code true} if device has soft keyboard should be disabled, otherwise {@code false}.
+ */
+ public static boolean shouldSoftKeyboardBeDisabled(final Context context, final boolean isSoftKeyboardEnabled, final boolean isSoftKeyboardEnabledOnlyIfNoHardware) {
+ // If soft keyboard is disabled by user regardless of hardware keyboard
+ if (!isSoftKeyboardEnabled) {
+ return true;
+ } else {
+ /*
+ * Currently, for this case, soft keyboard will be disabled on Termux app startup and
+ * when switching back from another app. Soft keyboard can be temporarily enabled in
+ * show/hide soft keyboard toggle behaviour with keyboard toggle buttons and will continue
+ * to work when tapping on terminal view for opening and back button for closing, until
+ * Termux app is switched to another app. After returning back, keyboard will be disabled
+ * until toggle is pressed again.
+ * This may also be helpful for the Lineage OS bug where if "Show soft keyboard" toggle
+ * in "Language and Input" is disabled and Termux is started without a hardware keyboard
+ * in landscape mode, and then the keyboard is connected and phone is rotated to portrait
+ * mode and then keyboard is toggled with Termux keyboard toggle buttons, then a blank
+ * space is shown in-place of the soft keyboard. Its likely related to
+ * WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE which pushes up the view when
+ * keyboard is opened instead of the keyboard opening on top of the view (hiding stuff).
+ * If the "Show soft keyboard" toggle was disabled, then this resizing shouldn't happen.
+ * But it seems resizing does happen, but keyboard is never opened since its not supposed to.
+ * https://github.com/termux/termux-app/issues/1995#issuecomment-837080079
+ */
+ // If soft keyboard is disabled by user only if hardware keyboard is connected
+ if(isSoftKeyboardEnabledOnlyIfNoHardware) {
+ boolean isHardKeyboardConnected = KeyboardUtils.isHardKeyboardConnected(context);
+ Logger.logVerbose(LOG_TAG, "Hardware keyboard connected=" + isHardKeyboardConnected);
+ return isHardKeyboardConnected;
+ } else {
+ return false;
+ }
+ }
+ }
+
}