fix: unable to exit input when an external keyboard is connected & cannot input continuously

This commit is contained in:
Tungstend 2024-02-25 20:57:56 +08:00
parent ea39dcb123
commit 16967ab508
4 changed files with 63 additions and 36 deletions

View File

@ -96,12 +96,20 @@ public class FCLInput implements View.OnCapturedPointerListener, View.OnGenericM
}
}
private View focusableView;
public View getFocusableView() {
return focusableView;
}
public void initExternalController(View view) {
view.setFocusable(true);
view.setOnCapturedPointerListener(this);
view.setOnGenericMotionListener(this);
view.requestFocus();
view.requestPointerCapture();
this.focusableView = view;
}
private boolean handleExternalMouseEvent(MotionEvent event) {
@ -153,13 +161,14 @@ public class FCLInput implements View.OnCapturedPointerListener, View.OnGenericM
@Override
public boolean onGenericMotion(View v, MotionEvent event) {
if (menu instanceof GameMenu && !((GameMenu) menu).getTouchCharInput().isEnabled()) {
((GameMenu) menu).getBaseLayout().requestFocus();
((GameMenu) menu).getBaseLayout().requestPointerCapture();
if (!((GameMenu) menu).getTouchCharInput().isEnabled()) {
focusableView.requestFocus();
focusableView.requestPointerCapture();
}
return true;
}
public boolean handleKeyEvent(KeyEvent event) {
int fclKeycode = AndroidKeycodeMap.convertKeycode(event.getKeyCode());
if (event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN)
@ -168,28 +177,30 @@ public class FCLInput implements View.OnCapturedPointerListener, View.OnGenericM
return false;
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP)
return false;
if (event.getRepeatCount() != 0)
return true;
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return true;
if (event.getAction() == KeyEvent.ACTION_UP && (event.getFlags() & KeyEvent.FLAG_CANCELED) != 0)
return true;
if (event.getDevice() != null && ((event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE || (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE)) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
sendKeyEvent(MOUSE_RIGHT, event.getAction() == KeyEvent.ACTION_DOWN);
return true;
}
}
if (event.getKeyCode() == KeyEvent.KEYCODE_ALT_RIGHT && menu.getCursorMode() == FCLBridge.CursorEnabled) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
((GameMenu) menu).getTouchCharInput().switchKeyboardState();
}
return true;
}
if ((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) == KeyEvent.FLAG_SOFT_KEYBOARD) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
return true;
((GameMenu) menu).getTouchCharInput().dispatchKeyEvent(event);
return true;
}
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (!((GameMenu) menu).getTouchCharInput().isLock() && event.getAction() == KeyEvent.ACTION_UP && !((GameMenu) menu).getTouchCharInput().isEnabled()) {
((GameMenu) menu).getTouchCharInput().switchKeyboardState();
} else if (((GameMenu) menu).getTouchCharInput().isLock()) {
((GameMenu) menu).getTouchCharInput().setLock(false);
}
return true;
}
if (fclKeycode == FCLKeycodes.KEY_UNKNOWN)
return (event.getFlags() & KeyEvent.FLAG_FALLBACK) == KeyEvent.FLAG_FALLBACK;
sendKeyEvent(fclKeycode, event.getAction() == KeyEvent.ACTION_DOWN);

View File

@ -448,7 +448,7 @@ public class GameMenu implements MenuCallback, View.OnClickListener {
touchPad.post(() -> gameItemBar.setup(this));
}
touchPad.init(this);
touchCharInput.setCharacterSender(new LwjglCharSender(this));
touchCharInput.setCharacterSender(this, new LwjglCharSender(this));
ViewGroup.LayoutParams layoutParams = cursorView.getLayoutParams();
layoutParams.width = ConvertUtils.dip2px(activity, menuSetting.mouseSizeProperty().get());
layoutParams.height = ConvertUtils.dip2px(activity, menuSetting.mouseSizeProperty().get());

View File

@ -74,7 +74,7 @@ public class JarExecutorMenu implements MenuCallback, View.OnClickListener, View
touchCharInput = findViewById(R.id.input_scanner);
touchPad.setOnTouchListener(this);
logWindow.setVisibilityValue(true);
touchCharInput.setCharacterSender(new AwtCharSender(awtInput));
touchCharInput.setCharacterSender(null, new AwtCharSender(awtInput));
forceExit = findViewById(R.id.force_exit);
showLog = findViewById(R.id.show_log);

View File

@ -4,16 +4,14 @@ import static android.content.Context.INPUT_METHOD_SERVICE;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Objects;
import com.tungsten.fcl.control.GameMenu;
/**
* From PojavLauncher
@ -21,6 +19,8 @@ import java.util.Objects;
*/
public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText {
public static final String TEXT_FILLER = " ";
public TouchCharInput(@NonNull Context context) {
this(context, null);
}
@ -34,9 +34,19 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
setup();
}
private GameMenu menu;
private boolean lock = false;
private boolean isDoingInternalChanges = false;
private CharacterSenderStrategy characterSender;
public void setLock(boolean lock) {
this.lock = lock;
}
public boolean isLock() {
return lock;
}
/**
* We take the new chars, and send them to the game.
* If less chars are present, remove some.
@ -58,8 +68,8 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
}
}
//Reset the keyboard state
if(text.length() < 1)
// Reset the keyboard state
if (text.length() < 1)
clear();
}
@ -87,26 +97,28 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
/**
* Toggle on and off the soft keyboard, depending of the state
*
* @return if the keyboard is set to be shown.
*/
public boolean switchKeyboardState() {
public void switchKeyboardState() {
InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
// If an hard keyboard is present, never trigger the soft one
if (hasFocus()
|| (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY
&& getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES)) {
if (hasFocus()) {
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
clear();
disable();
return false;
} else {
if (menu != null && menu.getInput().getFocusableView() != null) {
menu.getInput().getFocusableView().requestFocus();
menu.getInput().getFocusableView().requestPointerCapture();
}
} else{
if (menu != null && menu.getInput().getFocusableView() != null) {
menu.getInput().getFocusableView().releasePointerCapture();
menu.getInput().getFocusableView().clearFocus();
}
enable();
inputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
return true;
}
}
/**
* Clear the EditText from any leftover inputs
* It does not affect the in-game input
@ -114,10 +126,8 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
@SuppressLint("SetTextI18n")
public void clear() {
isDoingInternalChanges = true;
//Braille space, doesn't trigger keyboard auto-complete
//replacing directly the text without though setText avoids notifying changes
setText(" ");
setSelection(Objects.requireNonNull(getText()).length());
setText(TEXT_FILLER);
setSelection(TEXT_FILLER.length());
isDoingInternalChanges = false;
}
@ -135,8 +145,6 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
setVisibility(GONE);
clearFocus();
setEnabled(false);
InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
}
/** Send the enter key. */
@ -146,20 +154,28 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
}
/** Just sets the char sender that should be used. */
public void setCharacterSender(CharacterSenderStrategy characterSender) {
public void setCharacterSender(GameMenu gameMenu, CharacterSenderStrategy characterSender) {
this.menu = gameMenu;
this.characterSender = characterSender;
}
/** This function deals with anything that has to be executed when the constructor is called */
private void setup() {
setOnEditorActionListener((textView, i, keyEvent) -> {
setLock(true);
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
sendEnter();
clear();
disable();
if (menu != null && menu.getInput().getFocusableView() != null) {
menu.getInput().getFocusableView().requestFocus();
menu.getInput().getFocusableView().requestPointerCapture();
}
return false;
});
clear();
disable();
}
}
}