mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-14 22:12:46 +00:00
Add support for delete swipe and spacebar navigation.
This is taken from simplekeyboard; the spacebar logic is the old one, to avoid a bug in some applications when moving the cursor at the beginning of the text.
This commit is contained in:
parent
3263ae00cc
commit
ec4c6ea2b9
10 changed files with 130 additions and 13 deletions
|
@ -19,11 +19,9 @@
|
||||||
package="org.dslul.openboard.inputmethod.latin">
|
package="org.dslul.openboard.inputmethod.latin">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
|
||||||
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
|
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
|
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
|
||||||
|
|
||||||
<!-- A signature-protected permission to ask AOSP Keyboard to close the software keyboard.
|
<!-- A signature-protected permission to ask AOSP Keyboard to close the software keyboard.
|
||||||
|
|
|
@ -100,6 +100,9 @@ public interface KeyboardActionListener {
|
||||||
* @return true if the request has been consumed, false otherwise.
|
* @return true if the request has been consumed, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean onCustomRequest(int requestCode);
|
public boolean onCustomRequest(int requestCode);
|
||||||
|
public void onMovePointer(int steps);
|
||||||
|
public void onMoveDeletePointer(int steps);
|
||||||
|
public void onUpWithDeletePointerActive();
|
||||||
|
|
||||||
public static final KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
public static final KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
||||||
|
|
||||||
|
@ -128,5 +131,11 @@ public interface KeyboardActionListener {
|
||||||
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() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ 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 int sPointerStep = (int)(10.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;
|
||||||
|
@ -127,6 +128,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
// Last pointer position.
|
// Last pointer position.
|
||||||
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;
|
||||||
|
@ -696,6 +701,9 @@ 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,10 +902,35 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onMoveEventInternal(final int x, final int y, final long eventTime) {
|
private void onMoveEventInternal(final int x, final int y, final long eventTime) {
|
||||||
|
final Key oldKey = mCurrentKey;
|
||||||
|
|
||||||
|
if (oldKey != null && oldKey.getCode() == Constants.CODE_SPACE && Settings.getInstance().getCurrent().mSpaceTrackpadEnabled) {
|
||||||
|
//Pointer slider
|
||||||
|
int steps = (x - mStartX) / sPointerStep;
|
||||||
|
final int longpressTimeout = Settings.getInstance().getCurrent().mKeyLongpressTimeout / MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
|
||||||
|
if (steps != 0 && mStartTime + longpressTimeout < System.currentTimeMillis()) {
|
||||||
|
mCursorMoved = true;
|
||||||
|
mStartX += steps * sPointerStep;
|
||||||
|
sListener.onMovePointer(steps);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldKey != null && oldKey.getCode() == Constants.CODE_DELETE && Settings.getInstance().getCurrent().mDeleteSwipeEnabled) {
|
||||||
|
//Delete slider
|
||||||
|
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 int lastX = mLastX;
|
final int lastX = mLastX;
|
||||||
final int lastY = mLastY;
|
final int lastY = mLastY;
|
||||||
final Key oldKey = mCurrentKey;
|
|
||||||
final Key newKey = onMoveKey(x, y);
|
|
||||||
|
|
||||||
if (sGestureEnabler.shouldHandleGesture()) {
|
if (sGestureEnabler.shouldHandleGesture()) {
|
||||||
// Register move event on gesture tracker.
|
// Register move event on gesture tracker.
|
||||||
|
@ -971,6 +1004,10 @@ 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 (isShowingMoreKeysPanel()) {
|
if (isShowingMoreKeysPanel()) {
|
||||||
if (!mIsTrackingForActionDisabled) {
|
if (!mIsTrackingForActionDisabled) {
|
||||||
final int translatedX = mMoreKeysPanel.translateX(x);
|
final int translatedX = mMoreKeysPanel.translateX(x);
|
||||||
|
@ -981,6 +1018,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCursorMoved) {
|
||||||
|
mCursorMoved = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sInGesture) {
|
if (sInGesture) {
|
||||||
if (currentKey != null) {
|
if (currentKey != null) {
|
||||||
callListenerOnRelease(currentKey, currentKey.getCode(), true /* withSliding */);
|
callListenerOnRelease(currentKey, currentKey.getCode(), true /* withSliding */);
|
||||||
|
@ -1023,6 +1065,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;
|
||||||
|
@ -1148,6 +1193,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
// We use longer timeout for sliding finger input started from the modifier key.
|
// We use longer timeout for sliding finger input started from the modifier key.
|
||||||
return longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
|
return longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
|
||||||
}
|
}
|
||||||
|
if (code == Constants.CODE_SPACE) {
|
||||||
|
// Cursor can be moved in space
|
||||||
|
return longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT;
|
||||||
|
}
|
||||||
return longpressTimeout;
|
return longpressTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,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;
|
||||||
|
@ -1357,6 +1358,38 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMovePointer(int steps) {
|
||||||
|
if (steps < 0) {
|
||||||
|
int availableCharacters = getCurrentInputConnection().getTextBeforeCursor(64, 0).length();
|
||||||
|
steps = availableCharacters < -steps ? -availableCharacters : steps;
|
||||||
|
}
|
||||||
|
else if (steps > 0) {
|
||||||
|
int availableCharacters = getCurrentInputConnection().getTextAfterCursor(64, 0).length();
|
||||||
|
steps = availableCharacters < steps ? availableCharacters : steps;
|
||||||
|
} else return;
|
||||||
|
|
||||||
|
int newPosition = mInputLogic.mConnection.mExpectedSelStart + steps;
|
||||||
|
getCurrentInputConnection().setSelection(newPosition, newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveDeletePointer(int steps) {
|
||||||
|
int end = mInputLogic.mConnection.getExpectedSelectionEnd();
|
||||||
|
int start = mInputLogic.mConnection.getExpectedSelectionStart() + steps;
|
||||||
|
if (start > end)
|
||||||
|
return;
|
||||||
|
mInputLogic.mConnection.setSelection(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpWithDeletePointerActive() {
|
||||||
|
if (mInputLogic.mConnection.hasSelection()) {
|
||||||
|
mInputLogic.sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
||||||
|
mInputLogic.finishInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isShowingOptionDialog() {
|
private boolean isShowingOptionDialog() {
|
||||||
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,12 +103,12 @@ public final class RichInputConnection implements PrivateCommandPerformer {
|
||||||
* It's not really the selection start position: the selection start may not be there yet, and
|
* It's not really the selection start position: the selection start may not be there yet, and
|
||||||
* in some cases, it may never arrive there.
|
* in some cases, it may never arrive there.
|
||||||
*/
|
*/
|
||||||
private int mExpectedSelStart = INVALID_CURSOR_POSITION; // in chars, not code points
|
public int mExpectedSelStart = INVALID_CURSOR_POSITION; // in chars, not code points
|
||||||
/**
|
/**
|
||||||
* The expected selection end. Only differs from mExpectedSelStart if a non-empty selection is
|
* The expected selection end. Only differs from mExpectedSelStart if a non-empty selection is
|
||||||
* expected. The same caveats as mExpectedSelStart apply.
|
* expected. The same caveats as mExpectedSelStart apply.
|
||||||
*/
|
*/
|
||||||
private int mExpectedSelEnd = INVALID_CURSOR_POSITION; // in chars, not code points
|
public int mExpectedSelEnd = INVALID_CURSOR_POSITION; // in chars, not code points
|
||||||
/**
|
/**
|
||||||
* This contains the committed text immediately preceding the cursor and the composing
|
* This contains the committed text immediately preceding the cursor and the composing
|
||||||
* text, if any. It is refreshed when the cursor moves by calling upon the TextView.
|
* text, if any. It is refreshed when the cursor moves by calling upon the TextView.
|
||||||
|
|
|
@ -1969,7 +1969,7 @@ public final class InputLogic {
|
||||||
*
|
*
|
||||||
* @param keyCode the key code to send inside the key event.
|
* @param keyCode the key code to send inside the key event.
|
||||||
*/
|
*/
|
||||||
private void sendDownUpKeyEvent(final int keyCode) {
|
public void sendDownUpKeyEvent(final int keyCode) {
|
||||||
final long eventTime = SystemClock.uptimeMillis();
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
|
mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
|
||||||
KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
KeyEvent.ACTION_DOWN, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
||||||
|
|
|
@ -83,6 +83,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
|
public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
|
||||||
public static final String PREF_ENABLE_SPLIT_KEYBOARD = "pref_split_keyboard";
|
public static final String PREF_ENABLE_SPLIT_KEYBOARD = "pref_split_keyboard";
|
||||||
public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale";
|
public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale";
|
||||||
|
public static final String PREF_SPACE_TRACKPAD = "pref_space_trackpad";
|
||||||
|
public static final String PREF_DELETE_SWIPE = "pref_delete_swipe";
|
||||||
// TODO: consolidate key preview dismiss delay with the key preview animation parameters.
|
// TODO: consolidate key preview dismiss delay with the key preview animation parameters.
|
||||||
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
|
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
|
||||||
"pref_key_preview_popup_dismiss_delay";
|
"pref_key_preview_popup_dismiss_delay";
|
||||||
|
@ -354,6 +356,14 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
|
return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean readSpaceTrackpadEnabled(final SharedPreferences prefs) {
|
||||||
|
return prefs.getBoolean(PREF_SPACE_TRACKPAD, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean readDeleteSwipeEnabled(final SharedPreferences prefs) {
|
||||||
|
return prefs.getBoolean(PREF_DELETE_SWIPE, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean readUseFullscreenMode(final Resources res) {
|
public static boolean readUseFullscreenMode(final Resources res) {
|
||||||
return res.getBoolean(R.bool.config_use_fullscreen_mode);
|
return res.getBoolean(R.bool.config_use_fullscreen_mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ public class SettingsValues {
|
||||||
public final boolean mUsePersonalizedDicts;
|
public final boolean mUsePersonalizedDicts;
|
||||||
public final boolean mUseDoubleSpacePeriod;
|
public final boolean mUseDoubleSpacePeriod;
|
||||||
public final boolean mBlockPotentiallyOffensive;
|
public final boolean mBlockPotentiallyOffensive;
|
||||||
|
public final boolean mSpaceTrackpadEnabled;
|
||||||
|
public final boolean mDeleteSwipeEnabled;
|
||||||
// Use bigrams to predict the next word when there is no input for it yet
|
// Use bigrams to predict the next word when there is no input for it yet
|
||||||
public final boolean mBigramPredictionEnabled;
|
public final boolean mBigramPredictionEnabled;
|
||||||
public final boolean mGestureInputEnabled;
|
public final boolean mGestureInputEnabled;
|
||||||
|
@ -223,6 +225,8 @@ public class SettingsValues {
|
||||||
new TargetPackageInfoGetterTask(context, mAppWorkarounds)
|
new TargetPackageInfoGetterTask(context, mAppWorkarounds)
|
||||||
.execute(mInputAttributes.mTargetApplicationPackageName);
|
.execute(mInputAttributes.mTargetApplicationPackageName);
|
||||||
}
|
}
|
||||||
|
mSpaceTrackpadEnabled = Settings.readSpaceTrackpadEnabled(prefs);
|
||||||
|
mDeleteSwipeEnabled = Settings.readDeleteSwipeEnabled(prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMetricsLoggingEnabled() {
|
public boolean isMetricsLoggingEnabled() {
|
||||||
|
|
|
@ -597,4 +597,8 @@ Tip: You can download and remove dictionaries by going to <b>Languages &
|
||||||
This resource is copied from packages/apps/Settings/res/values/strings.xml -->
|
This resource is copied from packages/apps/Settings/res/values/strings.xml -->
|
||||||
<!-- This resource is corresponding to msgid="5433275485499039199" -->
|
<!-- This resource is corresponding to msgid="5433275485499039199" -->
|
||||||
<string name="user_dict_fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
<string name="user_dict_fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
||||||
|
<string name="delete_swipe">Delete swipe</string>
|
||||||
|
<string name="space_trackpad">Space bar trackpad</string>
|
||||||
|
<string name="delete_swipe_summary">Perform a swipe from the delete key to select and remove bigger portions of text at once</string>
|
||||||
|
<string name="space_trackpad_summary">Swipe on the spacebar to move the cursor</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -48,6 +48,16 @@
|
||||||
android:title="@string/show_setup_wizard_icon"
|
android:title="@string/show_setup_wizard_icon"
|
||||||
android:summary="@string/show_setup_wizard_icon_summary"
|
android:summary="@string/show_setup_wizard_icon_summary"
|
||||||
android:persistent="true" />
|
android:persistent="true" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="pref_space_trackpad"
|
||||||
|
android:title="@string/space_trackpad"
|
||||||
|
android:summary="@string/space_trackpad_summary"
|
||||||
|
android:defaultValue="true" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="pref_delete_swipe"
|
||||||
|
android:title="@string/delete_swipe"
|
||||||
|
android:summary="@string/delete_swipe_summary"
|
||||||
|
android:defaultValue="true" />
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:fragment="org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment"
|
android:fragment="org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment"
|
||||||
android:key="screen_debug"
|
android:key="screen_debug"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue