prepare for selecting text with cursor movement keys when shift is enabled manually

not enabled, as it's not working reliably
This commit is contained in:
Helium314 2025-06-15 17:41:05 +02:00
parent e430d13c4a
commit ef3191a2eb
5 changed files with 44 additions and 20 deletions

View file

@ -10,8 +10,6 @@ import android.view.KeyCharacterMap
import android.view.KeyEvent import android.view.KeyEvent
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.Constants
import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.getCustomKeyCode
/** /**
* A hardware event decoder for a hardware qwerty-ish keyboard. * A hardware event decoder for a hardware qwerty-ish keyboard.

View file

@ -5,7 +5,7 @@ import android.util.SparseArray
import android.view.KeyEvent import android.view.KeyEvent
import android.view.inputmethod.InputMethodSubtype import android.view.inputmethod.InputMethodSubtype
import helium314.keyboard.event.Event import helium314.keyboard.event.Event
import helium314.keyboard.event.HangulEventDecoder.decodeHardwareKeyEvent import helium314.keyboard.event.HangulEventDecoder
import helium314.keyboard.event.HardwareEventDecoder import helium314.keyboard.event.HardwareEventDecoder
import helium314.keyboard.event.HardwareKeyboardEventDecoder import helium314.keyboard.event.HardwareKeyboardEventDecoder
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
@ -88,7 +88,7 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp
val event: Event val event: Event
if (settings.current.mLocale.language == "ko") { // todo: this does not appear to be the right place if (settings.current.mLocale.language == "ko") { // todo: this does not appear to be the right place
val subtype = keyboardSwitcher.keyboard?.mId?.mSubtype ?: RichInputMethodManager.getInstance().currentSubtype val subtype = keyboardSwitcher.keyboard?.mId?.mSubtype ?: RichInputMethodManager.getInstance().currentSubtype
event = decodeHardwareKeyEvent(subtype, keyEvent) { event = HangulEventDecoder.decodeHardwareKeyEvent(subtype, keyEvent) {
getHardwareKeyEventDecoder(keyEvent.deviceId).decodeHardwareKey(keyEvent) getHardwareKeyEventDecoder(keyEvent.deviceId).decodeHardwareKey(keyEvent)
} }
} else { } else {
@ -118,6 +118,12 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp
val event = if (primaryCode in combiningRange) { // todo: should this be done later, maybe in inputLogic? val event = if (primaryCode in combiningRange) { // todo: should this be done later, maybe in inputLogic?
Event.createSoftwareDeadEvent(primaryCode, 0, metaState, mkv.getKeyX(x), mkv.getKeyY(y), null) Event.createSoftwareDeadEvent(primaryCode, 0, metaState, mkv.getKeyX(x), mkv.getKeyY(y), null)
} else { } else {
// todo:
// setting meta shift should only be done for arrow and similar cursor movement keys
// should only be enabled once it works more reliably (currently depends on app for some reason)
// if (mkv.keyboard?.mId?.isAlphabetShiftedManually == true)
// Event.createSoftwareKeypressEvent(primaryCode, metaState or KeyEvent.META_SHIFT_ON, mkv.getKeyX(x), mkv.getKeyY(y), isKeyRepeat)
// else Event.createSoftwareKeypressEvent(primaryCode, metaState, mkv.getKeyX(x), mkv.getKeyY(y), isKeyRepeat)
Event.createSoftwareKeypressEvent(primaryCode, metaState, mkv.getKeyX(x), mkv.getKeyY(y), isKeyRepeat) Event.createSoftwareKeypressEvent(primaryCode, metaState, mkv.getKeyX(x), mkv.getKeyY(y), isKeyRepeat)
} }
latinIME.onEvent(event) latinIME.onEvent(event)

View file

@ -184,6 +184,11 @@ public final class KeyboardId {
|| mElementId == ELEMENT_ALPHABET_AUTOMATIC_SHIFTED || mElementId == ELEMENT_ALPHABET_MANUAL_SHIFTED; || mElementId == ELEMENT_ALPHABET_AUTOMATIC_SHIFTED || mElementId == ELEMENT_ALPHABET_MANUAL_SHIFTED;
} }
public boolean isAlphabetShiftedManually() {
return mElementId == ELEMENT_ALPHABET_SHIFT_LOCKED || mElementId == ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED
|| mElementId == ELEMENT_ALPHABET_MANUAL_SHIFTED;
}
public boolean isNumberLayout() { public boolean isNumberLayout() {
return mElementId == ELEMENT_NUMBER || mElementId == ELEMENT_NUMPAD return mElementId == ELEMENT_NUMBER || mElementId == ELEMENT_NUMPAD
|| mElementId == ELEMENT_PHONE || mElementId == ELEMENT_PHONE_SYMBOLS; || mElementId == ELEMENT_PHONE || mElementId == ELEMENT_PHONE_SYMBOLS;

View file

@ -1164,8 +1164,12 @@ public class LatinIME extends InputMethodService implements
if (isInputViewShown() if (isInputViewShown()
&& mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
composingSpanStart, composingSpanEnd, settingsValues)) { composingSpanStart, composingSpanEnd, settingsValues)) {
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), // we don't want to update a manually set shift state if selection changed towards one side
getCurrentRecapitalizeState()); // because this may end the manual shift, which is unwanted in case of shift + arrow keys for changing selection
// todo: this is not fully implemented yet, and maybe should be behind a setting
if (mKeyboardSwitcher.getKeyboard() != null && mKeyboardSwitcher.getKeyboard().mId.isAlphabetShiftedManually()
&& !((oldSelEnd == newSelEnd && oldSelStart != newSelStart) || (oldSelEnd != newSelEnd && oldSelStart == newSelStart)))
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
} }
} }

View file

@ -89,6 +89,7 @@ public final class InputLogic {
private int mDeleteCount; private int mDeleteCount;
private long mLastKeyTime; private long mLastKeyTime;
// todo: this is not used, so either remove it or do something with it
public final TreeSet<Long> mCurrentlyPressedHardwareKeys = new TreeSet<>(); public final TreeSet<Long> mCurrentlyPressedHardwareKeys = new TreeSet<>();
// Keeps track of most recently inserted text (multi-character key) for reverting // Keeps track of most recently inserted text (multi-character key) for reverting
@ -399,7 +400,11 @@ public final class InputLogic {
// Stop the last recapitalization, if started. // Stop the last recapitalization, if started.
mRecapitalizeStatus.stop(); mRecapitalizeStatus.stop();
mWordBeingCorrectedByCursor = null; mWordBeingCorrectedByCursor = null;
return true;
// we do not return true if
final boolean oneSidedSelectionMove = hasOrHadSelection
&& ((oldSelEnd == newSelEnd && oldSelStart != newSelStart) || (oldSelEnd != newSelEnd && oldSelStart == newSelStart));
return !oneSidedSelectionMove;
} }
public boolean moveCursorByAndReturnIfInsideComposingWord(int distance) { public boolean moveCursorByAndReturnIfInsideComposingWord(int distance) {
@ -725,30 +730,36 @@ public final class InputLogic {
} }
break; break;
case KeyCode.WORD_LEFT: case KeyCode.WORD_LEFT:
sendDownUpKeyEventWithMetaState(ScriptUtils.isScriptRtl(currentKeyboardScript)? sendDownUpKeyEventWithMetaState(
KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_CTRL_ON); ScriptUtils.isScriptRtl(currentKeyboardScript) ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.META_CTRL_ON | event.getMMetaState());
break; break;
case KeyCode.WORD_RIGHT: case KeyCode.WORD_RIGHT:
sendDownUpKeyEventWithMetaState(ScriptUtils.isScriptRtl(currentKeyboardScript)? sendDownUpKeyEventWithMetaState(
KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_CTRL_ON); ScriptUtils.isScriptRtl(currentKeyboardScript) ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.META_CTRL_ON | event.getMMetaState());
break; break;
case KeyCode.MOVE_START_OF_PAGE: case KeyCode.MOVE_START_OF_PAGE:
final int selectionEnd = mConnection.getExpectedSelectionEnd(); final int selectionEnd1 = mConnection.getExpectedSelectionEnd();
sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_ON); final int selectionStart1 = mConnection.getExpectedSelectionStart();
if (mConnection.getExpectedSelectionStart() > 0 && mConnection.getExpectedSelectionEnd() == selectionEnd) { sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_ON | event.getMMetaState());
// unchanged, and we're not at the top -> try a different method (necessary for compose fields) if (mConnection.getExpectedSelectionStart() == selectionStart1 && mConnection.getExpectedSelectionEnd() == selectionEnd1) {
mConnection.setSelection(0, 0); // unchanged -> try a different method (necessary for compose fields)
final int newEnd = (event.getMMetaState() & KeyEvent.META_SHIFT_MASK) != 0 ? selectionEnd1 : 0;
mConnection.setSelection(0, newEnd);
} }
break; break;
case KeyCode.MOVE_END_OF_PAGE: case KeyCode.MOVE_END_OF_PAGE:
final int selectionStart = mConnection.getExpectedSelectionEnd(); final int selectionStart2 = mConnection.getExpectedSelectionStart();
sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_ON); final int selectionEnd2 = mConnection.getExpectedSelectionEnd();
if (mConnection.getExpectedSelectionStart() == selectionStart) { sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_ON | event.getMMetaState());
if (mConnection.getExpectedSelectionStart() == selectionStart2 && mConnection.getExpectedSelectionEnd() == selectionEnd2) {
// unchanged, try fallback e.g. for compose fields that don't care about ctrl + end // unchanged, try fallback e.g. for compose fields that don't care about ctrl + end
// we just move to a very large index, and hope the field is prepared to deal with this // we just move to a very large index, and hope the field is prepared to deal with this
// getting the actual length of the text for setting the correct position can be tricky for some apps... // getting the actual length of the text for setting the correct position can be tricky for some apps...
try { try {
mConnection.setSelection(Integer.MAX_VALUE, Integer.MAX_VALUE); final int newStart = (event.getMMetaState() & KeyEvent.META_SHIFT_MASK) != 0 ? selectionStart2 : Integer.MAX_VALUE;
mConnection.setSelection(newStart, Integer.MAX_VALUE);
} catch (Exception e) { } catch (Exception e) {
// better catch potential errors and just do nothing in this case // better catch potential errors and just do nothing in this case
Log.i(TAG, "error when trying to move cursor to last position: " + e); Log.i(TAG, "error when trying to move cursor to last position: " + e);