Add long press functions to more toolbar keys, and more clipboard history toolbar keys (#691)

Co-authored-by: codokie <@>
This commit is contained in:
codokie 2024-05-01 23:44:51 +03:00 committed by GitHub
parent 6bb49ee1a0
commit 83fc10ff02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 99 additions and 47 deletions

View file

@ -16,6 +16,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
@ -49,6 +50,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private EmojiPalettesView mEmojiPalettesView;
private View mEmojiTabStripView;
private LinearLayout mClipboardStripView;
private HorizontalScrollView mClipboardStripScrollView;
private View mSuggestionStripView;
private ClipboardHistoryView mClipboardHistoryView;
private LatinIME mLatinIME;
@ -280,7 +282,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mEmojiPalettesView.setVisibility(View.GONE);
mEmojiPalettesView.stopEmojiPalettes();
mEmojiTabStripView.setVisibility(View.GONE);
mClipboardStripView.setVisibility(View.GONE);
mClipboardStripScrollView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.VISIBLE);
mClipboardHistoryView.setVisibility(View.GONE);
mClipboardHistoryView.stopClipboardHistory();
@ -299,7 +301,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
// @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
mKeyboardView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.GONE);
mClipboardStripView.setVisibility(View.GONE);
mClipboardStripScrollView.setVisibility(View.GONE);
mEmojiTabStripView.setVisibility(View.VISIBLE);
mClipboardHistoryView.setVisibility(View.GONE);
mEmojiPalettesView.startEmojiPalettes(
@ -322,7 +324,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mKeyboardView.setVisibility(View.GONE);
mEmojiTabStripView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.GONE);
mClipboardStripView.setVisibility(View.VISIBLE);
mClipboardStripScrollView.post(() -> mClipboardStripScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT));
mClipboardStripScrollView.setVisibility(View.VISIBLE);
mEmojiPalettesView.setVisibility(View.GONE);
mClipboardHistoryView.startClipboardHistory(
mLatinIME.getClipboardHistoryManager(),
@ -571,6 +574,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mClipboardHistoryView.setKeyboardActionListener(mLatinIME.mKeyboardActionListener);
mEmojiTabStripView = mCurrentInputView.findViewById(R.id.emoji_tab_strip);
mClipboardStripView = mCurrentInputView.findViewById(R.id.clipboard_strip);
mClipboardStripScrollView = mCurrentInputView.findViewById(R.id.clipboard_strip_scroll_view);
mSuggestionStripView = mCurrentInputView.findViewById(R.id.suggestion_strip_view);
return mCurrentInputView;

View file

@ -28,13 +28,14 @@ import helium314.keyboard.latin.utils.ResourceUtils
import helium314.keyboard.latin.utils.ToolbarKey
import helium314.keyboard.latin.utils.createToolbarKey
import helium314.keyboard.latin.utils.getCodeForToolbarKey
import helium314.keyboard.latin.utils.getCodeForToolbarKeyLongClick
class ClipboardHistoryView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet?,
defStyle: Int = R.attr.clipboardHistoryViewStyle
) : LinearLayout(context, attrs, defStyle), View.OnTouchListener, View.OnClickListener,
ClipboardHistoryManager.OnHistoryChangeListener, OnKeyEventListener {
ClipboardHistoryManager.OnHistoryChangeListener, OnKeyEventListener, View.OnLongClickListener {
private val clipboardLayoutParams = ClipboardLayoutParams(context.resources)
private val pinIconId: Int
@ -69,7 +70,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
// even when state is activated, the not activated color is set
// in suggestionStripView the same thing works correctly, wtf?
// need to properly fix it (and maybe undo the inverted isActivated) when adding a toggle key
listOf(ToolbarKey.LEFT, ToolbarKey.RIGHT, ToolbarKey.COPY, ToolbarKey.CUT, ToolbarKey.CLEAR_CLIPBOARD, ToolbarKey.SELECT_WORD, ToolbarKey.SELECT_ALL, ToolbarKey.CLOSE_HISTORY)
listOf(ToolbarKey.ONE_HANDED, ToolbarKey.UNDO, ToolbarKey.UP, ToolbarKey.DOWN, ToolbarKey.LEFT, ToolbarKey.RIGHT, ToolbarKey.CLEAR_CLIPBOARD, ToolbarKey.COPY, ToolbarKey.CUT, ToolbarKey.SELECT_WORD, ToolbarKey.CLOSE_HISTORY)
.forEach { toolbarKeys.add(createToolbarKey(context, keyboardAttr, it)) }
keyboardAttr.recycle()
}
@ -121,6 +122,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
clipboardStrip.addView(it)
it.setOnTouchListener(this@ClipboardHistoryView)
it.setOnClickListener(this@ClipboardHistoryView)
it.setOnLongClickListener(this@ClipboardHistoryView)
colors.setColor(it, ColorType.TOOL_BAR_KEY)
colors.setBackground(it, ColorType.STRIP_BACKGROUND)
}
@ -240,6 +242,23 @@ class ClipboardHistoryView @JvmOverloads constructor(
}
}
override fun onLongClick(view: View): Boolean {
val tag = view.tag
if (tag is ToolbarKey) {
val longClickCode = getCodeForToolbarKeyLongClick(tag)
if (longClickCode != KeyCode.UNSPECIFIED) {
keyboardActionListener?.onCodeInput(
longClickCode,
Constants.NOT_A_COORDINATE,
Constants.NOT_A_COORDINATE,
false
)
}
return true
}
return false
}
override fun onKeyDown(clipId: Long) {
keyboardActionListener?.onPressKey(KeyCode.NOT_SPECIFIED, 0, true)
}

View file

@ -131,6 +131,9 @@ object KeyCode {
const val ACTION_PREVIOUS = -10007
// Code value representing the code is not specified.
const val NOT_SPECIFIED = -10008 // todo: not sure if there is need to have the "old" unspecified keyCode different, just test it and maybe merge
const val CLIPBOARD_COPY_ALL = -10009
const val PAGE_UP = -10010
const val PAGE_DOWN = -10011
/** to make sure a FlorisBoard code works when reading a JSON layout */
fun Int.checkAndConvertCode(): Int = if (this > 0) this else when (this) {

View file

@ -1518,6 +1518,7 @@ public class LatinIME extends InputMethodService implements
mInputLogic.onTextInput(mSettings.getCurrent(), event,
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
updateStateAfterInputTransaction(completeInputTransaction);
mInputLogic.restartSuggestionsOnWordTouchedByCursor(mSettings.getCurrent(), mKeyboardSwitcher.getCurrentKeyboardScript());
mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
}

View file

@ -653,9 +653,12 @@ public final class RichInputConnection implements PrivateCommandPerformer {
mIC.setSelection(mExpectedSelStart - range.getNumberOfCharsInWordBeforeCursor(), mExpectedSelStart + range.getNumberOfCharsInWordAfterCursor());
}
public void copyText() {
// copy selected text, and if nothing is selected copy the whole text
CharSequence text = getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
public void copyText(final boolean getSelection) {
CharSequence text = "";
if (getSelection) {
// copy selected text, and if nothing is selected copy the whole text
text = getSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
}
if (text == null || text.length() == 0) {
// we have no selection, get the whole text
final ExtractedTextRequest etr = new ExtractedTextRequest();

View file

@ -636,6 +636,18 @@ public final class InputLogic {
}
}
/**
* Handles the action of pasting content from the clipboard.
* Retrieves content from the clipboard history manager and commits it to the input connection.
*
*/
private void handleClipboardPaste() {
final String clipboardContent = mLatinIME.getClipboardHistoryManager().retrieveClipboardContent().toString();
if (!clipboardContent.isEmpty()) {
mLatinIME.onTextInput(clipboardContent);
}
}
/**
* Handle a functional key event.
* <p>
@ -685,14 +697,12 @@ public final class InputLogic {
// is being handled in {@link KeyboardState#onEvent(Event,int)}.
// If disabled, current clipboard content is committed.
if (!inputTransaction.getMSettingsValues().mClipboardHistoryEnabled) {
final CharSequence content = mLatinIME.getClipboardHistoryManager()
.retrieveClipboardContent();
if (!TextUtils.isEmpty(content)) {
mConnection.commitText(content, 1);
inputTransaction.setDidAffectContents();
}
handleClipboardPaste();
}
break;
case KeyCode.CLIPBOARD_PASTE:
handleClipboardPaste();
break;
case KeyCode.SHIFT_ENTER:
final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
event.getMKeyCode(), event.getMX(), event.getMY(), event.isKeyRepeat());
@ -714,11 +724,14 @@ public final class InputLogic {
mConnection.selectWord(inputTransaction.getMSettingsValues().mSpacingAndPunctuations, currentKeyboardScript);
break;
case KeyCode.CLIPBOARD_COPY:
mConnection.copyText();
mConnection.copyText(true);
break;
case KeyCode.CLIPBOARD_COPY_ALL:
mConnection.copyText(false);
break;
case KeyCode.CLIPBOARD_CUT:
if (mConnection.hasSelection()) {
mConnection.copyText();
mConnection.copyText(true);
// fake delete keypress to remove the text
final Event backspaceEvent = LatinIME.createSoftwareKeypressEvent(KeyCode.DELETE,
event.getMX(), event.getMY(), event.isKeyRepeat());
@ -750,6 +763,12 @@ public final class InputLogic {
case KeyCode.MOVE_END_OF_LINE:
sendDownUpKeyEvent(KeyEvent.KEYCODE_MOVE_END);
break;
case KeyCode.PAGE_UP:
sendDownUpKeyEvent(KeyEvent.KEYCODE_PAGE_UP);
break;
case KeyCode.PAGE_DOWN:
sendDownUpKeyEvent(KeyEvent.KEYCODE_PAGE_DOWN);
break;
case KeyCode.VOICE_INPUT:
// switching to shortcut IME, shift state, keyboard,... is handled by LatinIME,
// {@link KeyboardSwitcher#onEvent(Event)}, or {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.

View file

@ -10,8 +10,6 @@ import static helium314.keyboard.latin.utils.ToolbarUtilsKt.*;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
@ -375,10 +373,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
}
private void onLongClickToolKey(final View view) {
if (ToolbarKey.CLIPBOARD == view.getTag() && view.getParent() == mPinnedKeys) {
onLongClickClipboardKey(); // long click pinned clipboard key
if (!(view.getTag() instanceof ToolbarKey tag)) return;
if (view.getParent() == mPinnedKeys) {
final int longClickCode = getCodeForToolbarKeyLongClick(tag);
if (longClickCode != KeyCode.UNSPECIFIED) {
mListener.onCodeInput(longClickCode, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
}
} else if (view.getParent() == mToolbar) {
final ToolbarKey tag = (ToolbarKey) view.getTag();
final View pinnedKeyView = mPinnedKeys.findViewWithTag(tag);
if (pinnedKeyView == null) {
addKeyToPinnedKeys(tag);
@ -392,22 +393,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
}
}
private void onLongClickClipboardKey() {
ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = clipboardManager.getPrimaryClip();
Log.d(TAG, "long click clipboard key");
if (clipData != null && clipData.getItemCount() > 0 && clipData.getItemAt(0) != null) {
String clipString = clipData.getItemAt(0).coerceToText(getContext()).toString();
if (clipString.length() == 1) {
mListener.onTextInput(clipString);
} else if (clipString.length() > 1) {
//awkward workaround
mListener.onTextInput(clipString.substring(0, clipString.length() - 1));
mListener.onTextInput(clipString.substring(clipString.length() - 1));
}
}
}
@SuppressLint("ClickableViewAccessibility") // no need for View#performClick, we return false mostly anyway
private boolean onLongClickSuggestion(final TextView wordView) {
boolean showIcon = true;

View file

@ -60,6 +60,19 @@ fun getCodeForToolbarKey(key: ToolbarKey) = when (key) {
CLOSE_HISTORY -> KeyCode.ALPHA
}
fun getCodeForToolbarKeyLongClick(key: ToolbarKey) = when (key) {
RIGHT -> KeyCode.MOVE_END_OF_LINE
LEFT -> KeyCode.MOVE_START_OF_LINE
UP -> KeyCode.PAGE_UP
DOWN -> KeyCode.PAGE_DOWN
UNDO -> KeyCode.REDO
REDO -> KeyCode.UNDO
COPY -> KeyCode.CLIPBOARD_COPY_ALL
SELECT_WORD -> KeyCode.CLIPBOARD_SELECT_ALL
CLIPBOARD -> KeyCode.CLIPBOARD_PASTE
else -> KeyCode.UNSPECIFIED
}
private fun getStyleableIconId(key: ToolbarKey) = when (key) {
VOICE -> R.styleable.Keyboard_iconShortcutKey
SETTINGS -> R.styleable.Keyboard_iconSettingsKey

View file

@ -24,16 +24,21 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?attr/suggestionStripViewStyle" />
<LinearLayout
android:id="@+id/clipboard_strip"
android:orientation="horizontal"
<HorizontalScrollView
android:id="@+id/clipboard_strip_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?attr/suggestionStripViewStyle" >
<!-- empty view to move buttons to the right -->
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
android:scrollbarThumbHorizontal="@color/toolbar_scrollbar" >
<LinearLayout
android:id="@+id/clipboard_strip"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="?attr/suggestionStripViewStyle" >
<!-- empty view to move buttons to the right -->
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</HorizontalScrollView>
</FrameLayout>