Skip to content

Commit

Permalink
Allow users to disable soft keyboard automatically if hardware keyboa…
Browse files Browse the repository at this point in the history
…rd is connected

Users can enable this behaviour by enabling the `Termux Settings` -> `Keyboard I/O` -> `Soft Keyboard Only If No Hardware` toggle.

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 also may help for the Lineage OS bug where blank space is shown where soft keyboard should be if "Show soft keyboard" toggle in "Language and Input" is disabled. Check KeyboardUtils.shouldSoftKeyboardBeDisabled() and #1995 (comment) for details.

The `TermuxPreferenceConstants` class has been updated to `v0.10.0`. Check its Changelog sections for info on changes.
  • Loading branch information
agnostic-apollo committed May 12, 2021
1 parent e6dac93 commit 90c9a7b
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@
<string name="keyboard_header">Keyboard</string>

<!-- Soft Keyboard -->
<string name="soft_keyboard_title">Soft Keyboard</string>
<string name="soft_keyboard_title">Soft Keyboard Enabled</string>
<string name="soft_keyboard_off">Soft keyboard will be disabled.</string>
<string name="soft_keyboard_on">Soft keyboard will be enabled. (Default)</string>

<!-- Soft Keyboard Only If No Hardware-->
<string name="soft_keyboard_enabled_only_if_no_hardware_title">Soft Keyboard If No Hardware</string>
<string name="soft_keyboard_enabled_only_if_no_hardware_off">Soft keyboard will be enabled even if hardware keyboard is connected. (Default)</string>
<string name="soft_keyboard_enabled_only_if_no_hardware_on">Soft keyboard will be enabled only if no hardware keyboard is connected.</string>

</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/xml/terminal_io_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
app:summaryOn="@string/soft_keyboard_on"
app:title="@string/soft_keyboard_title" />

<SwitchPreferenceCompat
app:key="soft_keyboard_enabled_only_if_no_hardware"
app:summaryOff="@string/soft_keyboard_enabled_only_if_no_hardware_off"
app:summaryOn="@string/soft_keyboard_enabled_only_if_no_hardware_on"
app:title="@string/soft_keyboard_enabled_only_if_no_hardware_title" />

</PreferenceCategory>

</PreferenceScreen>
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.termux.shared.settings.preferences;

/*
* Version: v0.9.0
* Version: v0.10.0
*
* Changelog
*
Expand Down Expand Up @@ -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`.
*/

/**
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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}.
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
}
}

}

0 comments on commit 90c9a7b

Please sign in to comment.