mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Add sliding cursor/deletion
This commit is contained in:
parent
e2999ada34
commit
7f17d66072
@ -101,6 +101,11 @@ public interface KeyboardActionListener {
|
|||||||
*/
|
*/
|
||||||
public boolean onCustomRequest(int requestCode);
|
public boolean onCustomRequest(int requestCode);
|
||||||
|
|
||||||
|
public void onMovePointer(int steps);
|
||||||
|
public void onMoveDeletePointer(int steps);
|
||||||
|
public void onUpWithDeletePointerActive();
|
||||||
|
public void onUpWithPointerActive();
|
||||||
|
|
||||||
public static final KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
public static final KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
||||||
|
|
||||||
public static class Adapter implements KeyboardActionListener {
|
public static class Adapter implements KeyboardActionListener {
|
||||||
@ -125,8 +130,14 @@ public interface KeyboardActionListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onFinishSlidingInput() {}
|
public void onFinishSlidingInput() {}
|
||||||
@Override
|
@Override
|
||||||
public boolean onCustomRequest(int requestCode) {
|
public boolean onCustomRequest(int requestCode) { return false; }
|
||||||
return false;
|
@Override
|
||||||
}
|
public void onMovePointer(int steps) {}
|
||||||
|
@Override
|
||||||
|
public void onMoveDeletePointer(int steps) {}
|
||||||
|
@Override
|
||||||
|
public void onUpWithDeletePointerActive() {}
|
||||||
|
@Override
|
||||||
|
public void onUpWithPointerActive() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
|
|
||||||
// Parameters for pointer handling.
|
// Parameters for pointer handling.
|
||||||
private static PointerTrackerParams sParams;
|
private static PointerTrackerParams sParams;
|
||||||
|
private static final int sPointerStep = (int)(16.0 * Resources.getSystem().getDisplayMetrics().density);
|
||||||
|
|
||||||
private static GestureStrokeRecognitionParams sGestureStrokeRecognitionParams;
|
private static GestureStrokeRecognitionParams sGestureStrokeRecognitionParams;
|
||||||
private static GestureStrokeDrawingParams sGestureStrokeDrawingParams;
|
private static GestureStrokeDrawingParams sGestureStrokeDrawingParams;
|
||||||
private static boolean sNeedsPhantomSuddenMoveEventHack;
|
private static boolean sNeedsPhantomSuddenMoveEventHack;
|
||||||
@ -128,6 +130,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
private int mLastX;
|
private int mLastX;
|
||||||
private int mLastY;
|
private int mLastY;
|
||||||
|
|
||||||
|
private int mStartX;
|
||||||
|
private int mStartY;
|
||||||
|
private long mStartTime;
|
||||||
|
private boolean mCursorMoved = false;
|
||||||
|
|
||||||
// true if keyboard layout has been changed.
|
// true if keyboard layout has been changed.
|
||||||
private boolean mKeyboardLayoutHasBeenChanged;
|
private boolean mKeyboardLayoutHasBeenChanged;
|
||||||
|
|
||||||
@ -691,6 +698,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
startRepeatKey(key);
|
startRepeatKey(key);
|
||||||
startLongPressTimer(key);
|
startLongPressTimer(key);
|
||||||
setPressedKeyGraphics(key, eventTime);
|
setPressedKeyGraphics(key, eventTime);
|
||||||
|
|
||||||
|
mStartX = x;
|
||||||
|
mStartY = y;
|
||||||
|
mStartTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,6 +903,29 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
final int lastX = mLastX;
|
final int lastX = mLastX;
|
||||||
final int lastY = mLastY;
|
final int lastY = mLastY;
|
||||||
final Key oldKey = mCurrentKey;
|
final Key oldKey = mCurrentKey;
|
||||||
|
|
||||||
|
if (oldKey != null && oldKey.getCode() == Constants.CODE_SPACE) {
|
||||||
|
int steps = (x - mStartX) / sPointerStep;
|
||||||
|
final int swipeIgnoreTime = Settings.getInstance().getCurrent().mKeyLongpressTimeout / MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
|
||||||
|
if (steps != 0 && mStartTime + swipeIgnoreTime < System.currentTimeMillis()) {
|
||||||
|
mCursorMoved = true;
|
||||||
|
mStartX += steps * sPointerStep;
|
||||||
|
sListener.onMovePointer(steps);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldKey != null && oldKey.getCode() == Constants.CODE_DELETE) {
|
||||||
|
int steps = (x - mStartX) / sPointerStep;
|
||||||
|
if (steps != 0) {
|
||||||
|
sTimerProxy.cancelKeyTimersOf(this);
|
||||||
|
mCursorMoved = true;
|
||||||
|
mStartX += steps * sPointerStep;
|
||||||
|
sListener.onMoveDeletePointer(steps);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final Key newKey = onMoveKey(x, y);
|
final Key newKey = onMoveKey(x, y);
|
||||||
|
|
||||||
if (sGestureEnabler.shouldHandleGesture()) {
|
if (sGestureEnabler.shouldHandleGesture()) {
|
||||||
@ -966,6 +1000,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
// Release the last pressed key.
|
// Release the last pressed key.
|
||||||
setReleasedKeyGraphics(currentKey, true /* withAnimation */);
|
setReleasedKeyGraphics(currentKey, true /* withAnimation */);
|
||||||
|
|
||||||
|
if(mCursorMoved && currentKey.getCode() == Constants.CODE_DELETE) {
|
||||||
|
sListener.onUpWithDeletePointerActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mCursorMoved) {
|
||||||
|
sListener.onUpWithPointerActive();
|
||||||
|
}
|
||||||
|
|
||||||
if (isShowingMoreKeysPanel()) {
|
if (isShowingMoreKeysPanel()) {
|
||||||
if (!mIsTrackingForActionDisabled) {
|
if (!mIsTrackingForActionDisabled) {
|
||||||
final int translatedX = mMoreKeysPanel.translateX(x);
|
final int translatedX = mMoreKeysPanel.translateX(x);
|
||||||
@ -988,6 +1030,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCursorMoved) {
|
||||||
|
mCursorMoved = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mIsTrackingForActionDisabled) {
|
if (mIsTrackingForActionDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1018,6 +1064,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
|||||||
if (isShowingMoreKeysPanel()) {
|
if (isShowingMoreKeysPanel()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mCursorMoved) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final Key key = getKey();
|
final Key key = getKey();
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -41,6 +41,7 @@ import android.os.IBinder;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
import android.util.Printer;
|
import android.util.Printer;
|
||||||
@ -158,6 +159,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
|||||||
private static final String SCHEME_PACKAGE = "package";
|
private static final String SCHEME_PACKAGE = "package";
|
||||||
|
|
||||||
final Settings mSettings;
|
final Settings mSettings;
|
||||||
|
private Locale mLocale;
|
||||||
final DictionaryFacilitator mDictionaryFacilitator =
|
final DictionaryFacilitator mDictionaryFacilitator =
|
||||||
DictionaryFacilitatorProvider.getDictionaryFacilitator(
|
DictionaryFacilitatorProvider.getDictionaryFacilitator(
|
||||||
false /* isNeededForSpellChecking */);
|
false /* isNeededForSpellChecking */);
|
||||||
@ -671,18 +673,18 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
|||||||
// Has to be package-visible for unit tests
|
// Has to be package-visible for unit tests
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
void loadSettings() {
|
void loadSettings() {
|
||||||
final Locale locale = mRichImm.getCurrentSubtypeLocale();
|
mLocale = mRichImm.getCurrentSubtypeLocale();
|
||||||
final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
|
final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
|
||||||
final InputAttributes inputAttributes = new InputAttributes(
|
final InputAttributes inputAttributes = new InputAttributes(
|
||||||
editorInfo, mInputMethodService.isFullscreenMode(), mInputMethodService.getPackageName());
|
editorInfo, mInputMethodService.isFullscreenMode(), mInputMethodService.getPackageName());
|
||||||
mSettings.loadSettings(mInputMethodService, locale, inputAttributes);
|
mSettings.loadSettings(mInputMethodService, mLocale, inputAttributes);
|
||||||
final SettingsValues currentSettingsValues = mSettings.getCurrent();
|
final SettingsValues currentSettingsValues = mSettings.getCurrent();
|
||||||
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues);
|
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues);
|
||||||
// This method is called on startup and language switch, before the new layout has
|
// This method is called on startup and language switch, before the new layout has
|
||||||
// been displayed. Opening dictionaries never affects responsivity as dictionaries are
|
// been displayed. Opening dictionaries never affects responsivity as dictionaries are
|
||||||
// asynchronously loaded.
|
// asynchronously loaded.
|
||||||
if (!mHandler.hasPendingReopenDictionaries()) {
|
if (!mHandler.hasPendingReopenDictionaries()) {
|
||||||
resetDictionaryFacilitator(locale);
|
resetDictionaryFacilitator(mLocale);
|
||||||
}
|
}
|
||||||
refreshPersonalizationDictionarySession(currentSettingsValues);
|
refreshPersonalizationDictionarySession(currentSettingsValues);
|
||||||
resetDictionaryFacilitatorIfNecessary();
|
resetDictionaryFacilitatorIfNecessary();
|
||||||
@ -1365,6 +1367,54 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMovePointer(int steps) {
|
||||||
|
if (mInputLogic.mConnection.hasCursorPosition()) {
|
||||||
|
if (TextUtils.getLayoutDirectionFromLocale(mLocale) == View.LAYOUT_DIRECTION_RTL)
|
||||||
|
steps = -steps;
|
||||||
|
|
||||||
|
steps = mInputLogic.mConnection.getUnicodeSteps(steps, true);
|
||||||
|
final int end = mInputLogic.mConnection.getExpectedSelectionEnd() + steps;
|
||||||
|
final int start = mInputLogic.mConnection.hasSelection() ? mInputLogic.mConnection.getExpectedSelectionStart() : end;
|
||||||
|
|
||||||
|
mInputLogic.finishInput();
|
||||||
|
mInputLogic.mConnection.setSelection(start, end);
|
||||||
|
} else {
|
||||||
|
for (; steps < 0; steps++)
|
||||||
|
mInputLogic.sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT, 0);
|
||||||
|
for (; steps > 0; steps--)
|
||||||
|
mInputLogic.sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveDeletePointer(int steps) {
|
||||||
|
if (mInputLogic.mConnection.hasCursorPosition()) {
|
||||||
|
steps = mInputLogic.mConnection.getUnicodeSteps(steps, false);
|
||||||
|
final int end = mInputLogic.mConnection.getExpectedSelectionEnd();
|
||||||
|
final int start = mInputLogic.mConnection.getExpectedSelectionStart() + steps;
|
||||||
|
if (start > end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mInputLogic.finishInput();
|
||||||
|
mInputLogic.mConnection.setSelection(start, end);
|
||||||
|
} else {
|
||||||
|
for (; steps < 0; steps++)
|
||||||
|
mInputLogic.sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpWithDeletePointerActive() {
|
||||||
|
if (mInputLogic.mConnection.hasSelection())
|
||||||
|
mInputLogic.sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpWithPointerActive() {
|
||||||
|
mInputLogic.restartSuggestionsOnWordTouchedByCursor(mSettings.getCurrent(), false, mKeyboardSwitcher.getCurrentKeyboardScriptId());
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isShowingOptionDialog() {
|
private boolean isShowingOptionDialog() {
|
||||||
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
||||||
}
|
}
|
||||||
|
@ -1044,4 +1044,41 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
|||||||
return InputConnectionCompatUtils.requestCursorUpdates(
|
return InputConnectionCompatUtils.requestCursorUpdates(
|
||||||
mIC, enableMonitor, requestImmediateCallback);
|
mIC, enableMonitor, requestImmediateCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasCursorPosition() {
|
||||||
|
return mExpectedSelStart != INVALID_CURSOR_POSITION && mExpectedSelEnd != INVALID_CURSOR_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some chars, such as emoji consist of 2 chars (surrogate pairs). We should treat them as one character.
|
||||||
|
*/
|
||||||
|
public int getUnicodeSteps(int chars, boolean rightSidePointer) {
|
||||||
|
int steps = 0;
|
||||||
|
if (chars < 0) {
|
||||||
|
CharSequence charsBeforeCursor = rightSidePointer && hasSelection() ?
|
||||||
|
getSelectedText(0) :
|
||||||
|
getTextBeforeCursor(-chars * 2, 0);
|
||||||
|
if (charsBeforeCursor != null) {
|
||||||
|
for (int i = charsBeforeCursor.length() - 1; i >= 0 && chars < 0; i--, chars++, steps--) {
|
||||||
|
if (Character.isSurrogate(charsBeforeCursor.charAt(i))) {
|
||||||
|
steps--;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (chars > 0) {
|
||||||
|
CharSequence charsAfterCursor = !rightSidePointer && hasSelection() ?
|
||||||
|
getSelectedText(0) :
|
||||||
|
getTextAfterCursor(chars * 2, 0);
|
||||||
|
if (charsAfterCursor != null) {
|
||||||
|
for (int i = 0; i < charsAfterCursor.length() && chars > 0; i++, chars--, steps++) {
|
||||||
|
if (Character.isSurrogate(charsAfterCursor.charAt(i))) {
|
||||||
|
steps++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user