diff --git a/app/src/main/java/com/termux/x11/LorieView.java b/app/src/main/java/com/termux/x11/LorieView.java
index 8758fd5c4..6812b85f7 100644
--- a/app/src/main/java/com/termux/x11/LorieView.java
+++ b/app/src/main/java/com/termux/x11/LorieView.java
@@ -11,6 +11,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.Log;
@@ -18,8 +19,10 @@
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
@@ -45,6 +48,10 @@ interface PixelFormat {
private long lastClipboardTimestamp = System.currentTimeMillis();
private static boolean clipboardSyncEnabled = false;
private static boolean hardwareKbdScancodesWorkaround = false;
+ private InputMethodManager mIMM = (InputMethodManager)getContext().getSystemService( Context.INPUT_METHOD_SERVICE);
+ private String mImeLang;
+ private boolean mImeCJK;
+ public boolean enableGboardCJK;
private Callback mCallback;
private final Point p = new Point();
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
@@ -219,6 +226,8 @@ public void reloadPreferences(Prefs p) {
clipboardSyncEnabled = p.clipboardEnable.get();
setClipboardSyncEnabled(clipboardSyncEnabled, clipboardSyncEnabled);
TouchInputHandler.refreshInputDevices();
+ enableGboardCJK = p.enableGboardCJK.get();
+ mIMM.restartInput(this);
}
// It is used in native code
@@ -279,6 +288,14 @@ public void onWindowFocusChanged(boolean hasFocus) {
TouchInputHandler.refreshInputDevices();
}
+ public void checkRestartInput(boolean recheck) {
+ if (!enableGboardCJK) return;
+ if (mIMM.getCurrentInputMethodSubtype().getLanguageTag().length() >= 2 && !mIMM.getCurrentInputMethodSubtype().getLanguageTag().substring(0, 2).equals(mImeLang))
+ mIMM.restartInput(this);
+ else if (recheck) { // recheck needed because sometimes requestCursorUpdates() is called too fast, before InputMethodManager detect change in IM subtype
+ MainActivity.handler.postDelayed(() -> checkRestartInput(false), 40);
+ }
+ }
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
@@ -287,7 +304,40 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
// keyboard on Android TV (see https://github.com/termux/termux-app/issues/221).
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
- return super.onCreateInputConnection(outAttrs);
+ if (enableGboardCJK) {
+ mImeLang = mIMM.getCurrentInputMethodSubtype().getLanguageTag();
+ if (mImeLang.length() > 2)
+ mImeLang = mImeLang.substring(0, 2);
+ mImeCJK = mImeLang.equals("zh") || mImeLang.equals("ko") || mImeLang.equals("ja");
+ outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS |
+ (mImeCJK ? InputType.TYPE_TEXT_VARIATION_NORMAL : InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
+ return new BaseInputConnection(this, false) {
+ @Override
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
+ // workaround for Gboard
+ // Gboard calls requestCursorUpdates() whenever switching language
+ // check and then restart keyboard in different inputtype when needed
+ checkRestartInput(true);
+ return super.requestCursorUpdates(cursorUpdateMode);
+ }
+
+ @Override
+ public boolean commitText(CharSequence text, int newCursorPosition) {
+ boolean result = super.commitText(text, newCursorPosition);
+ if (mImeCJK)
+ // suppress Gboard CJK keyboard suggestion
+ // this workaround does not work well for non-CJK keyboards
+ // , when typing fast and two keypresses (commitText) are close in time
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ mIMM.invalidateInput(LorieView.this);
+ else
+ mIMM.restartInput(LorieView.this);
+ return result;
+ }
+ };
+ } else {
+ return super.onCreateInputConnection(outAttrs);
+ }
}
static native void connect(int fd);
diff --git a/app/src/main/java/com/termux/x11/MainActivity.java b/app/src/main/java/com/termux/x11/MainActivity.java
index 3c3d794d8..eec1dc939 100644
--- a/app/src/main/java/com/termux/x11/MainActivity.java
+++ b/app/src/main/java/com/termux/x11/MainActivity.java
@@ -66,6 +66,7 @@
import com.termux.x11.input.TouchInputHandler;
import com.termux.x11.utils.FullscreenWorkaround;
import com.termux.x11.utils.KeyInterceptor;
+import com.termux.x11.utils.SamsungDexUtils;
import com.termux.x11.utils.TermuxX11ExtraKeys;
import com.termux.x11.utils.X11ToolbarViewPager;
@@ -824,6 +825,11 @@ public static boolean isConnected() {
private void checkXEvents() {
getLorieView().handleXEvents();
+ // an imperfect workaround for Gboard CJK keyboard in DeX soft keyboard mode
+ // in that particular mode during language switching, InputConnection#requestCursorUpdates() is not called and no signal can be picked up.
+ // therefore, check to activate CJK keyboard is done upon a keypress.
+ if (getLorieView().enableGboardCJK && SamsungDexUtils.checkDeXEnabled(this))
+ getLorieView().checkRestartInput(false);
handler.postDelayed(this::checkXEvents, 300);
}
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index d2d342e5e..0177a67ff 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -192,6 +192,12 @@
android:summary="Allows you to use Dex shortcuts while intercepting. Requires Accessibility service to work."
android:defaultValue="false"
android:key="filterOutWinkey" />
+
+